HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GR_PrimTetra.C
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * Produced by:
7  * Side Effects Software Inc
8  * 123 Front Street West, Suite 1401
9  * Toronto, Ontario
10  * Canada M5J 2M2
11  * 416-504-9876
12  *
13  * NAME: GR_PrimTetra.C (GR Library, C++)
14  *
15  * COMMENTS:
16  */
17 #include "GR_PrimTetra.h"
18 #include "GEO_PrimTetra.h"
19 
20 #include <DM/DM_RenderTable.h>
21 #include <GR/GR_Utils.h>
22 #include <RE/RE_ElementArray.h>
23 #include <RE/RE_Geometry.h>
24 #include <RE/RE_LightList.h>
25 #include <RE/RE_ShaderHandle.h>
26 #include <RE/RE_VertexArray.h>
27 
28 #include <GT/GT_GEOPrimitive.h>
29 
30 using namespace HDK_Sample;
31 
32 // See GEO_PrimTetra::registerMyself() for installation of the hook.
33 
35  : GUI_PrimitiveHook("Tetrahedron")
36 {
37 }
38 
40 {
41 }
42 
45  const GEO_Primitive *geo_prim,
46  const GR_RenderInfo *info,
47  const char *cache_name,
48  GR_PrimAcceptResult &processed)
49 {
50  return new GR_PrimTetra(info, cache_name, geo_prim);
51 }
52 
54  const char *cache_name,
55  const GEO_Primitive *prim)
56  : GR_Primitive(info, cache_name, GA_PrimCompat::TypeMask(0))
57 {
58 
59  myID = prim->getTypeId().get();
60  myGeo = NULL;
61 }
62 
64 {
65  delete myGeo;
66 }
67 
68 
71  int geo_type,
72  const GT_PrimitiveHandle &ph,
73  const GEO_Primitive *prim)
74 {
75  if(geo_type == myID)
76  return GR_PROCESSED;
77 
78  return GR_NOT_PROCESSED;
79 }
80 
81 
82 void
84  const GT_PrimitiveHandle &primh,
85  const GR_UpdateParms &p)
86 {
87  // Fetch the GEO primitive from the GT primitive handle
88  const GEO_PrimTetra *tet = NULL;
89 
90  // GL3 and above requires named vertex attributes, while GL2 and GL1 use
91  // the older builtin names.
92 
93  const char *posname = "P";
94  const char *nmlname = "N";
95  RE_VertexArray *pos = NULL;
96  RE_VertexArray *nml = NULL;
98 
99  // Initialize the geometry with the proper name for the GL cache
100  if(!myGeo)
101  myGeo = new RE_Geometry;
102  myGeo->cacheBuffers(getCacheName());
103 
104  getGEOPrimFromGT<GEO_PrimTetra>(primh, tet);
105 
106  const int num_tets = tet ? 1 : 0;
107  if(num_tets == 0)
108  {
109  delete myGeo;
110  myGeo = NULL;
111  return;
112  }
113 
114  // Extract tetra point positions.
115  {
117  const GU_Detail *dtl = georl.getGdp();
118 
119  for(int v=0; v<4; v++)
120  pt.append(dtl->getPos3(dtl->vertexPoint(tet->getVertexOffset(v))));
121  }
122 
123  // Initialize the number of points in the geometry.
124  myGeo->setNumPoints( 12 * num_tets);
125 
126  GR_UpdateParms dp(p);
127  const GR_Decoration pdecs[] = { GR_POINT_MARKER,
130  GR_POINT_UV,
138  GR_VERTEX_UV,
141  dp, pdecs, GR_POINT_ATTRIB);
142 
143 
144  // Fetch P (point position). If its cache version matches, no upload is
145  // required.
146  pos = myGeo->findCachedAttrib(r, posname, RE_GPU_FLOAT32, 3,
147  RE_ARRAY_POINT, true);
148  if(pos->getCacheVersion() != dp.geo_version)
149  {
150  // map() returns a pointer to the GL buffer
151  UT_Vector3F *pdata = static_cast<UT_Vector3F *>(pos->map(r));
152  if(pdata)
153  {
154  for(int t=0; t<num_tets; t++)
155  {
156  pdata[0] = pt(t*4);
157  pdata[1] = pt(t*4+1);
158  pdata[2] = pt(t*4+2);
159 
160  pdata[3] = pt(t*4);
161  pdata[4] = pt(t*4+2);
162  pdata[5] = pt(t*4+3);
163 
164  pdata[6] = pt(t*4+1);
165  pdata[7] = pt(t*4+2);
166  pdata[8] = pt(t*4+3);
167 
168  pdata[9] = pt(t*4);
169  pdata[10] = pt(t*4+3);
170  pdata[11] = pt(t*4+1);
171 
172  pdata += 12;
173  }
174 
175  // unmap the buffer so it can be used by GL
176  pos->unmap(r);
177 
178  // Always set the cache version after assigning data.
179  pos->setCacheVersion(dp.geo_version);
180  }
181  }
182 
183 
184  // NOTE: you can add more attributes from a detail, such as Cd, uv, Alpha
185  // by repeating the process above.
186 
187  // Fetch N (point normal). This just generates normals for the tetras.
188  nml = myGeo->findCachedAttrib(r, nmlname, RE_GPU_FLOAT32, 3,
189  RE_ARRAY_POINT, true);
190  if(nml->getCacheVersion() != dp.geo_version)
191  {
192  UT_Vector3F *ndata = static_cast<UT_Vector3F *>(nml->map(r));
193  if(ndata)
194  {
195  UT_Vector3F n0, n1, n2, n3;
196 
197  // This just creates primitive normals for the tet. It's currently
198  // not 100% correct (FIXME).
199  for(int t=0; t<num_tets; t++)
200  {
201  n0 = -cross(pt(t*4+2)-pt(t*4), pt(t*4+1)-pt(t*4)).normalize();
202  n1 = cross(pt(t*4+3)-pt(t*4), pt(t*4+2)-pt(t*4)).normalize();
203  n2 = -cross(pt(t*4+3)-pt(t*4+1),pt(t*4+2)-pt(t*4+1)).normalize();
204  n3 = -cross(pt(t*4+1)-pt(t*4), pt(t*4+3)-pt(t*4)).normalize();
205 
206  ndata[0] = ndata[1] = ndata[2] = n0;
207  ndata[3] = ndata[4] = ndata[5] = n1;
208  ndata[6] = ndata[7] = ndata[8] = n2;
209  ndata[9] = ndata[10] = ndata[11] = n3;
210 
211  ndata += 12;
212  }
213 
214  nml->unmap(r);
215 
216  // Always set the cache version after assigning data.
217  nml->setCacheVersion(dp.geo_version);
218  }
219  }
220 
221 
222  // Extra constant inputs for the GL3 default shaders we are using.
223  // This isn't required unless
224  fpreal32 col[3] = { 1.0, 1.0, 1.0 };
225  fpreal32 uv[2] = { 0.0, 0.0 };
226  fpreal32 alpha = 1.0;
227  fpreal32 pnt = 0.0;
228 
229  myGeo->createConstAttribute(r, "Cd", RE_GPU_FLOAT32, 3, col);
230  myGeo->createConstAttribute(r, "uv", RE_GPU_FLOAT32, 2, uv);
231  myGeo->createConstAttribute(r, "Alpha", RE_GPU_FLOAT32, 1, &alpha);
232  myGeo->createConstAttribute(r, "pointSelection", RE_GPU_FLOAT32, 1,&pnt);
233 
234  myInstancedFlag =
235  GR_Utils::buildInstanceObjectMatrix(r, primh, p, myGeo,
236  p.instance_version, 0);
237  UT_IntArray dummy;
238  GR_Utils::buildInstanceIndex(r, myGeo, false, dummy, 0);
239 
240  // Connectivity, for both shaded and wireframe
241  myGeo->connectAllPrims(r, RE_GEO_WIRE_IDX, RE_PRIM_LINES, NULL, true);
242  myGeo->connectAllPrims(r, RE_GEO_SHADED_IDX, RE_PRIM_TRIANGLES, NULL, true);
243 }
244 
245 
246 // GL3 shaders. These use some of the builtin Houdini shaders, which are
247 // described by the .prog file format - a simple container format for various
248 // shader stages and other information.
249 
250 static RE_ShaderHandle theNQShader("material/GL32/beauty_lit.prog");
251 static RE_ShaderHandle theNQFlatShader("material/GL32/beauty_flat_lit.prog");
252 static RE_ShaderHandle theNQUnlitShader("material/GL32/beauty_unlit.prog");
253 static RE_ShaderHandle theHQShader("material/GL32/beauty_material.prog");
254 static RE_ShaderHandle theLineShader("basic/GL32/wire_color.prog");
255 static RE_ShaderHandle theConstShader("material/GL32/constant.prog");
256 static RE_ShaderHandle theZCubeShader("basic/GL32/depth_cube.prog");
257 static RE_ShaderHandle theZLinearShader("basic/GL32/depth_linear.prog");
258 static RE_ShaderHandle theMatteShader("basic/GL32/matte.prog");
259 
260 
261 void
263  GR_RenderMode render_mode,
265  GR_DrawParms dp)
266 {
267  if(!myGeo)
268  return;
269 
270  bool need_wire = (render_mode == GR_RENDER_WIREFRAME ||
271  render_mode == GR_RENDER_HIDDEN_LINE ||
272  render_mode == GR_RENDER_GHOST_LINE ||
273  render_mode == GR_RENDER_MATERIAL_WIREFRAME ||
274  (flags & GR_RENDER_FLAG_WIRE_OVER));
275 
276  // Shaded mode rendering
277  if(render_mode == GR_RENDER_BEAUTY ||
278  render_mode == GR_RENDER_MATERIAL ||
279  render_mode == GR_RENDER_CONSTANT ||
280  render_mode == GR_RENDER_HIDDEN_LINE ||
281  render_mode == GR_RENDER_GHOST_LINE ||
282  render_mode == GR_RENDER_DEPTH ||
283  render_mode == GR_RENDER_DEPTH_LINEAR ||
284  render_mode == GR_RENDER_DEPTH_CUBE ||
285  render_mode == GR_RENDER_MATTE)
286  {
287  // enable polygon offset if doing a wireframe on top of shaded
288  bool polyoff = r->isPolygonOffset();
289  if(need_wire)
290  r->polygonOffset(true);
291 
292  r->pushShader();
293 
294  // GL3 requires the use of shaders. The fixed function pipeline
295  // GL builtins (which are deprecated, like gl_ModelViewMatrix)
296  // are not initialized in the GL3 renderer.
297 
298  if(render_mode == GR_RENDER_BEAUTY)
299  {
300  if(flags & GR_RENDER_FLAG_UNLIT)
301  r->bindShader(theNQUnlitShader);
302  else if(flags & GR_RENDER_FLAG_FLAT_SHADED)
303  r->bindShader(theNQFlatShader);
304  else
305  r->bindShader(theNQShader);
306  }
307  else if(render_mode == GR_RENDER_MATERIAL)
308  {
309  r->bindShader(theHQShader);
310  }
311  else if(render_mode == GR_RENDER_CONSTANT ||
312  render_mode == GR_RENDER_DEPTH ||
313  render_mode == GR_RENDER_HIDDEN_LINE ||
314  render_mode == GR_RENDER_GHOST_LINE)
315  {
316  // Reuse constant for depth-only since it's so lightweight.
317  r->bindShader(theConstShader);
318  }
319  else if(render_mode == GR_RENDER_DEPTH_LINEAR)
320  {
321  // Depth written to world-space Z instead of non-linear depth
322  // buffer Z ([0..1] near-far depth range)
323  r->bindShader(theZLinearShader);
324  }
325  else if(render_mode == GR_RENDER_DEPTH_CUBE)
326  {
327  // Linear depth written to
328  r->bindShader(theZCubeShader);
329  }
330  else if(render_mode == GR_RENDER_MATTE)
331  {
332  r->bindShader(theMatteShader);
333  }
334 
335 
336  // setup materials and lighting
337  if(dp.materials && (dp.materials->getDefaultMaterial() ||
339  {
340  RE_Shader *shader = r->getShader();
342  if(!mat)
343  mat = dp.materials->getFactoryMaterial();
344 
345  // Set up lighting for any GL3 lighting blocks
346  if(shader && dp.opts->getLightList())
347  dp.opts->getLightList()->bindForShader(r, shader);
348 
349  // set up the main material block for GL3
350  mat->updateShaderForMaterial(r, 0, true, true,
351  RE_SHADER_TARGET_TRIANGLE, shader);
352  }
353 
354  // Draw call for the geometry
355  if(dp.draw_instanced)
357  else
358  myGeo->draw(r, RE_GEO_SHADED_IDX);
359 
360  if(r->getShader())
362  r->popShader();
363 
364  if(need_wire && !polyoff)
365  r->polygonOffset(polyoff);
366  }
367 
368 
369  // Wireframe rendering
370  if(need_wire)
371  {
372  // GL3 requires a shader even for simple wireframe rendering.
373  r->pushShader(theLineShader);
374 
375  if(dp.draw_instanced)
377  else
378  myGeo->draw(r, RE_GEO_WIRE_IDX);
379 
380  r->popShader();
381  }
382 }
383 
384 void
386  GR_Decoration decor,
387  const GR_DecorationParms &p)
388 {
389  drawDecorationForGeo(r, myGeo, decor, p.opts, p.render_flags,
392 
393 }
394 
395 int
397  const GR_DisplayOption *opt,
398  unsigned int pick_type,
399  GR_PickStyle pick_style,
400  bool has_pick_map)
401 {
402  // This example is not pickable.
403  return 0;
404 }
RE_VertexArray * findCachedAttrib(RE_Render *r, const char *attrib_name, RE_GPUType data_format, int vectorsize, RE_ArrayType array_type, bool create_if_missing=false, int random_array_size=-1, const RE_CacheVersion *cv=NULL, RE_BufferUsageHint h=RE_BUFFER_WRITE_FREQUENT, const char *cache_prefix=NULL, int capacity=-1)
Find an attribute or array in the GL cache, possibly creating it Returns the cached array...
Definition: RE_Geometry.h:857
virtual void renderDecoration(RE_Render *r, GR_Decoration decor, const GR_DecorationParms &parms)
Definition: GR_PrimTetra.C:385
void unmap(RE_Render *r, int array_index=0)
virtual GR_PrimAcceptResult acceptPrimitive(GT_PrimitiveType t, int geo_type, const GT_PrimitiveHandle &ph, const GEO_Primitive *prim)
Definition: GR_PrimTetra.C:70
void drawInstanceGroup(RE_Render *r, int connect_idx, int instance_group, RE_PrimType prim_type=RE_PRIM_AS_IS, RE_OverrideList *attrib_over=NULL)
Draw an instance group using a given connectivity.
GR_DecorationRender * myDecorRender
Definition: GR_Primitive.h:524
const RE_LightList * getLightList() const
GA_API const UT_StringHolder uv
GU_ConstDetailHandle geometry
const GR_DisplayOption * opts
const GLdouble * v
Definition: glcorearb.h:836
void drawDecorationForGeo(RE_Render *r, RE_Geometry *geo, GR_Decoration dec, const GR_DisplayOption *opts, GR_DecorRenderFlags flags, bool overlay, bool override_vis, int instance_group, GR_SelectMode smode, GR_DecorationRender::PrimitiveType t=GR_DecorationRender::PRIM_TRIANGLE, RE_OverrideList *override_list=NULL)
RE_CacheVersion geo_version
A collection of vertex arrays defining a geometry object. This class acts as a wrapper around multipl...
Definition: RE_Geometry.h:53
int instance_group
Definition: GR_DrawParms.h:24
GT_API const UT_StringHolder cache_name
const RE_MaterialPtr & getDefaultMaterial() const
Definition: RE_Material.h:856
GLbitfield flags
Definition: glcorearb.h:1595
SYS_FORCE_INLINE const GA_PrimitiveTypeId & getTypeId() const
Definition: GA_Primitive.h:169
bool isPolygonOffset()
SYS_FORCE_INLINE UT_Vector3 getPos3(GA_Offset ptoff) const
The ptoff passed is the point offset.
Definition: GA_Detail.h:174
RE_CacheVersion instance_version
GR_Decoration
Definition: GR_Defines.h:139
virtual int renderPick(RE_Render *r, const GR_DisplayOption *opt, unsigned int pick_type, GR_PickStyle pick_style, bool has_pick_map)
Definition: GR_PrimTetra.C:396
const char * getCacheName() const
The base GL cache name assigned to this primitive.
Definition: GR_Primitive.h:335
SIM_DerVector3 normalize() const
set of parameters sent to GR_Primitive::update()
GR_RenderMode
Definition: GR_Defines.h:44
const GR_DisplayOption & dopts
GR_DecorRenderFlags render_flags
const GR_DisplayOption * opts
Definition: GR_DrawParms.h:20
int pushShader()
void draw(RE_Render *r, int connect_idx, RE_PrimType prim_type=RE_PRIM_AS_IS, RE_OverrideList *attrib_overrides=NULL)
Definition: RE_Geometry.h:613
void bindForShader(RE_Render *r, RE_Shader *sh) const
RE_Shader * getShader()
GR_API bool buildInstanceObjectMatrix(RE_Render *r, const GT_PrimitiveHandle &h, const GR_UpdateParms &p, RE_Geometry *geo, RE_CacheVersion version, int instance_group=0, UT_Matrix4D *transform=NULL)
GLfloat GLfloat GLfloat alpha
Definition: glcorearb.h:111
SYS_FORCE_INLINE int get() const
SYS_FORCE_INLINE GA_Offset vertexPoint(GA_Offset vertex) const
Given a vertex, return the point it references.
Definition: GA_Detail.h:473
virtual GR_Primitive * createPrimitive(const GT_PrimitiveHandle &gt_prim, const GEO_Primitive *geo_prim, const GR_RenderInfo *info, const char *cache_name, GR_PrimAcceptResult &processed)
Definition: GR_PrimTetra.C:44
RE_CacheVersion getCacheVersion() const
GR_PrimAcceptResult
Definition: GR_Defines.h:328
void polygonOffset(bool onoff)
GR_RenderFlags
Definition: GR_Defines.h:79
#define RE_GEO_SHADED_IDX
Definition: RE_Geometry.h:44
GT_PrimitiveType
const RE_MaterialAtlas * materials
Definition: GR_DrawParms.h:21
GR_API void buildInstanceIndex(RE_Render *r, RE_Geometry *geo, bool has_partial_visibility, const UT_IntArray &inst_indices, int instance_group=0, int max_capacity=-1)
void setCacheVersion(RE_CacheVersion v)
GLuint shader
Definition: glcorearb.h:784
RE_VertexArray * createConstAttribute(RE_Render *r, const char *attrib_name, RE_GPUType data_format, int vectorsize, const void *data)
Create a constant attribute value Only RE_GPU_FLOAT32 and _FLOAT64 are supported for constant data...
const RE_MaterialPtr & getFactoryMaterial() const
Definition: RE_Material.h:860
int connectAllPrims(RE_Render *r, int connect_index, RE_PrimType prim, const RE_MaterialPtr &mat=NULL, bool replace=false, int vertices_per_patch=0)
Primitive Connectivity .
#define RE_GEO_WIRE_IDX
Definition: RE_Geometry.h:43
virtual void removeOverrideBlocks()
Remove all override blocks from the shader.
Definition: RE_Shader.h:689
virtual void update(RE_Render *r, const GT_PrimitiveHandle &primh, const GR_UpdateParms &p)
Definition: GR_PrimTetra.C:83
GR_DecorationOverride required_dec
virtual void render(RE_Render *r, GR_RenderMode render_mode, GR_RenderFlags flags, GR_DrawParms dp)
Definition: GR_PrimTetra.C:262
SYS_FORCE_INLINE GA_Offset getVertexOffset(GA_Size primvertexnum) const
Definition: GA_Primitive.h:232
exint append(void)
Definition: UT_Array.h:95
void * map(RE_Render *r, RE_BufferAccess access=RE_BUFFER_WRITE_ONLY, int array_index=0)
GR_PrimTetra(const GR_RenderInfo *info, const char *cache_name, const GEO_Primitive *prim)
Definition: GR_PrimTetra.C:53
bool cacheBuffers(const char *name)
Caching .
void setupFromDisplayOptions(const GR_DisplayOption &opts, GR_DecorationOverride select_dec, GR_UpdateParms &parms, const GR_Decoration *supported, GR_AttribMask mask)
GLboolean r
Definition: glcorearb.h:1221
bool setNumPoints(int num)
Number of points in the geometry. Number of points for the arrays declared as RE_ARRAY_POINT. This will clear the data in all point arrays and reset the connectivty.
float fpreal32
Definition: SYS_Types.h:191
SIM_DerVector3 cross(const SIM_DerVector3 &lhs, const SIM_DerVector3 &rhs)
const GU_Detail * getGdp() const
void popShader(int *nest=nullptr)
void bindShader(RE_Shader *s)
bool draw_instanced
Definition: GR_DrawParms.h:23
Simple interface to building a shader from a .prog file.
GR_PickStyle
Definition: GR_Defines.h:228