HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros 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 #ifdef TETRA_GR_PRIM_COLLECTION
59  myPrimIndices.append( prim->getMapIndex() );
60 #endif
61 
62  myID = prim->getTypeId().get();
63  myGeo = NULL;
64 }
65 
67 {
68  delete myGeo;
69 }
70 
71 
72 void
74 {
75 #ifdef TETRA_GR_PRIM_COLLECTION
76  myPrimIndices.entries(GA_Index(0));
77 #else
78  // nothing for single primitives - will not be called.
79 #endif
80 }
81 
84  int geo_type,
85  const GT_PrimitiveHandle &ph,
86  const GEO_Primitive *prim)
87 {
88  if(geo_type == myID)
89  {
90 #ifdef TETRA_GR_PRIM_COLLECTION
91  myPrimIndices.append( prim->getMapIndex() );
92 #endif
93 
94  return GR_PROCESSED;
95  }
96 
97  return GR_NOT_PROCESSED;
98 }
99 
100 
101 void
103  const GT_PrimitiveHandle &primh,
104  const GR_UpdateParms &p)
105 {
106  // Fetch the GEO primitive from the GT primitive handle
107  const GEO_PrimTetra *tet = NULL;
108 
109  // GL3 and above requires named vertex attributes, while GL2 and GL1 use
110  // the older builtin names.
111 
112  const char *posname = "P";
113  const char *nmlname = "N";
114  RE_VertexArray *pos = NULL;
115  RE_VertexArray *nml = NULL;
116  UT_Vector3FArray pt;
117 
118  // Initialize the geometry with the proper name for the GL cache
119  if(!myGeo)
120  myGeo = new RE_Geometry;
121  myGeo->cacheBuffers(getCacheName());
122 
123 
124  // Enable this codepath in tetra.C to collect multiple GEO_PrimTetras into
125  // one GR_PrimTetra.
126 #ifdef TETRA_GR_PRIM_COLLECTION
127 
128  // Multiple GEO_PrimTetra's collected for this GR_Primitive
129  const int num_tets = myPrimIndices.entries();
130  if(num_tets == 0)
131  {
132  delete myGeo;
133  myGeo = NULL;
134  return;
135  }
136 
137  {
139  const GU_Detail *dtl = georl.getGdp();
140 
141  for(int i=0; i<myPrimIndices.entries(); i++)
142  {
143  GA_Offset off = dtl->primitiveIndex(myPrimIndices(i));
144 
145  tet = dynamic_cast<const GEO_PrimTetra *>
146  ( dtl->getGEOPrimitive(off) );
147  if(tet)
148  {
149  for(int v=0; v<4; v++)
150  pt.append(dtl->getPos3(dtl->vertexPoint(
151  tet->getVertexOffset(v))));
152  }
153  }
154  }
155 
156 #else
157  // Single GEO_PrimTetra for this GR_Primitive
158 
159  getGEOPrimFromGT<GEO_PrimTetra>(primh, tet);
160 
161  const int num_tets = tet ? 1 : 0;
162  if(num_tets == 0)
163  {
164  delete myGeo;
165  myGeo = NULL;
166  return;
167  }
168 
169  // Extract tetra point positions.
170  {
172  const GU_Detail *dtl = georl.getGdp();
173 
174  for(int v=0; v<4; v++)
175  pt.append(dtl->getPos3(dtl->vertexPoint(tet->getVertexOffset(v))));
176  }
177 #endif
178 
179  // Initialize the number of points in the geometry.
180  myGeo->setNumPoints( 12 * num_tets);
181 
182  GR_UpdateParms dp(p);
183  const GR_Decoration pdecs[] = { GR_POINT_MARKER,
186  GR_POINT_UV,
194  GR_VERTEX_UV,
197  dp, pdecs, GR_POINT_ATTRIB);
198 
199 
200  // Fetch P (point position). If its cache version matches, no upload is
201  // required.
202  pos = myGeo->findCachedAttrib(r, posname, RE_GPU_FLOAT32, 3,
203  RE_ARRAY_POINT, true);
204  if(pos->getCacheVersion() != dp.geo_version)
205  {
206  // map() returns a pointer to the GL buffer
207  UT_Vector3F *pdata = static_cast<UT_Vector3F *>(pos->map(r));
208  if(pdata)
209  {
210  for(int t=0; t<num_tets; t++)
211  {
212  pdata[0] = pt(t*4);
213  pdata[1] = pt(t*4+1);
214  pdata[2] = pt(t*4+2);
215 
216  pdata[3] = pt(t*4);
217  pdata[4] = pt(t*4+2);
218  pdata[5] = pt(t*4+3);
219 
220  pdata[6] = pt(t*4+1);
221  pdata[7] = pt(t*4+2);
222  pdata[8] = pt(t*4+3);
223 
224  pdata[9] = pt(t*4);
225  pdata[10] = pt(t*4+3);
226  pdata[11] = pt(t*4+1);
227 
228  pdata += 12;
229  }
230 
231  // unmap the buffer so it can be used by GL
232  pos->unmap(r);
233 
234  // Always set the cache version after assigning data.
235  pos->setCacheVersion(dp.geo_version);
236  }
237  }
238 
239 
240  // NOTE: you can add more attributes from a detail, such as Cd, uv, Alpha
241  // by repeating the process above.
242 
243  // Fetch N (point normal). This just generates normals for the tetras.
244  nml = myGeo->findCachedAttrib(r, nmlname, RE_GPU_FLOAT32, 3,
245  RE_ARRAY_POINT, true);
246  if(nml->getCacheVersion() != dp.geo_version)
247  {
248  UT_Vector3F *ndata = static_cast<UT_Vector3F *>(nml->map(r));
249  if(ndata)
250  {
251  UT_Vector3F n0, n1, n2, n3;
252 
253  // This just creates primitive normals for the tet. It's currently
254  // not 100% correct (FIXME).
255  for(int t=0; t<num_tets; t++)
256  {
257  n0 = -cross(pt(t*4+2)-pt(t*4), pt(t*4+1)-pt(t*4)).normalize();
258  n1 = cross(pt(t*4+3)-pt(t*4), pt(t*4+2)-pt(t*4)).normalize();
259  n2 = -cross(pt(t*4+3)-pt(t*4+1),pt(t*4+2)-pt(t*4+1)).normalize();
260  n3 = -cross(pt(t*4+1)-pt(t*4), pt(t*4+3)-pt(t*4)).normalize();
261 
262  ndata[0] = ndata[1] = ndata[2] = n0;
263  ndata[3] = ndata[4] = ndata[5] = n1;
264  ndata[6] = ndata[7] = ndata[8] = n2;
265  ndata[9] = ndata[10] = ndata[11] = n3;
266 
267  ndata += 12;
268  }
269 
270  nml->unmap(r);
271 
272  // Always set the cache version after assigning data.
273  nml->setCacheVersion(dp.geo_version);
274  }
275  }
276 
277 
278  // Extra constant inputs for the GL3 default shaders we are using.
279  // This isn't required unless
280  fpreal32 col[3] = { 1.0, 1.0, 1.0 };
281  fpreal32 uv[2] = { 0.0, 0.0 };
282  fpreal32 alpha = 1.0;
283  fpreal32 pnt = 0.0;
284 
285  myGeo->createConstAttribute(r, "Cd", RE_GPU_FLOAT32, 3, col);
286  myGeo->createConstAttribute(r, "uv", RE_GPU_FLOAT32, 2, uv);
287  myGeo->createConstAttribute(r, "Alpha", RE_GPU_FLOAT32, 1, &alpha);
288  myGeo->createConstAttribute(r, "pointSelection", RE_GPU_FLOAT32, 1,&pnt);
289 
290  myInstancedFlag =
291  GR_Utils::buildInstanceObjectMatrix(r, primh, p, myGeo,
292  p.instance_version, 0);
293  UT_IntArray dummy;
294  GR_Utils::buildInstanceIndex(r, myGeo, false, dummy, 0);
295 
296  // Connectivity, for both shaded and wireframe
297  myGeo->connectAllPrims(r, RE_GEO_WIRE_IDX, RE_PRIM_LINES, NULL, true);
298  myGeo->connectAllPrims(r, RE_GEO_SHADED_IDX, RE_PRIM_TRIANGLES, NULL, true);
299 }
300 
301 
302 // GL3 shaders. These use some of the builtin Houdini shaders, which are
303 // described by the .prog file format - a simple container format for various
304 // shader stages and other information.
305 
306 static RE_ShaderHandle theNQShader("material/GL32/beauty_lit.prog");
307 static RE_ShaderHandle theNQFlatShader("material/GL32/beauty_flat_lit.prog");
308 static RE_ShaderHandle theNQUnlitShader("material/GL32/beauty_unlit.prog");
309 static RE_ShaderHandle theHQShader("material/GL32/beauty_material.prog");
310 static RE_ShaderHandle theLineShader("basic/GL32/wire_color.prog");
311 static RE_ShaderHandle theConstShader("material/GL32/constant.prog");
312 static RE_ShaderHandle theZCubeShader("basic/GL32/depth_cube.prog");
313 static RE_ShaderHandle theZLinearShader("basic/GL32/depth_linear.prog");
314 static RE_ShaderHandle theMatteShader("basic/GL32/matte.prog");
315 
316 
317 void
319  GR_RenderMode render_mode,
321  GR_DrawParms dp)
322 {
323  if(!myGeo)
324  return;
325 
326  bool need_wire = (render_mode == GR_RENDER_WIREFRAME ||
327  render_mode == GR_RENDER_HIDDEN_LINE ||
328  render_mode == GR_RENDER_GHOST_LINE ||
329  render_mode == GR_RENDER_MATERIAL_WIREFRAME ||
330  (flags & GR_RENDER_FLAG_WIRE_OVER));
331 
332  // Shaded mode rendering
333  if(render_mode == GR_RENDER_BEAUTY ||
334  render_mode == GR_RENDER_MATERIAL ||
335  render_mode == GR_RENDER_CONSTANT ||
336  render_mode == GR_RENDER_HIDDEN_LINE ||
337  render_mode == GR_RENDER_GHOST_LINE ||
338  render_mode == GR_RENDER_DEPTH ||
339  render_mode == GR_RENDER_DEPTH_LINEAR ||
340  render_mode == GR_RENDER_DEPTH_CUBE ||
341  render_mode == GR_RENDER_MATTE)
342  {
343  // enable polygon offset if doing a wireframe on top of shaded
344  bool polyoff = r->isPolygonOffset();
345  if(need_wire)
346  r->polygonOffset(true);
347 
348  r->pushShader();
349 
350  // GL3 requires the use of shaders. The fixed function pipeline
351  // GL builtins (which are deprecated, like gl_ModelViewMatrix)
352  // are not initialized in the GL3 renderer.
353 
354  if(render_mode == GR_RENDER_BEAUTY)
355  {
356  if(flags & GR_RENDER_FLAG_UNLIT)
357  r->bindShader(theNQUnlitShader);
358  else if(flags & GR_RENDER_FLAG_FLAT_SHADED)
359  r->bindShader(theNQFlatShader);
360  else
361  r->bindShader(theNQShader);
362  }
363  else if(render_mode == GR_RENDER_MATERIAL)
364  {
365  r->bindShader(theHQShader);
366  }
367  else if(render_mode == GR_RENDER_CONSTANT ||
368  render_mode == GR_RENDER_DEPTH ||
369  render_mode == GR_RENDER_HIDDEN_LINE ||
370  render_mode == GR_RENDER_GHOST_LINE)
371  {
372  // Reuse constant for depth-only since it's so lightweight.
373  r->bindShader(theConstShader);
374  }
375  else if(render_mode == GR_RENDER_DEPTH_LINEAR)
376  {
377  // Depth written to world-space Z instead of non-linear depth
378  // buffer Z ([0..1] near-far depth range)
379  r->bindShader(theZLinearShader);
380  }
381  else if(render_mode == GR_RENDER_DEPTH_CUBE)
382  {
383  // Linear depth written to
384  r->bindShader(theZCubeShader);
385  }
386  else if(render_mode == GR_RENDER_MATTE)
387  {
388  r->bindShader(theMatteShader);
389  }
390 
391 
392  // setup materials and lighting
393  if(dp.materials && (dp.materials->getDefaultMaterial() ||
395  {
396  RE_Shader *shader = r->getShader();
398  if(!mat)
399  mat = dp.materials->getFactoryMaterial();
400 
401  // Set up lighting for any GL3 lighting blocks
402  if(shader && dp.opts->getLightList())
403  dp.opts->getLightList()->bindForShader(r, shader);
404 
405  // set up the main material block for GL3
406  mat->updateShaderForMaterial(r, 0, true, true,
407  RE_SHADER_TARGET_TRIANGLE, shader);
408  }
409 
410  // Draw call for the geometry
411  if(dp.draw_instanced)
413  else
414  myGeo->draw(r, RE_GEO_SHADED_IDX);
415 
416  if(r->getShader())
418  r->popShader();
419 
420  if(need_wire && !polyoff)
421  r->polygonOffset(polyoff);
422  }
423 
424 
425  // Wireframe rendering
426  if(need_wire)
427  {
428  // GL3 requires a shader even for simple wireframe rendering.
429  r->pushShader(theLineShader);
430 
431  if(dp.draw_instanced)
433  else
434  myGeo->draw(r, RE_GEO_WIRE_IDX);
435 
436  r->popShader();
437  }
438 }
439 
440 void
442  GR_Decoration decor,
443  const GR_DecorationParms &p)
444 {
445  drawDecorationForGeo(r, myGeo, decor, p.opts, p.render_flags,
448 
449 }
450 
451 int
453  const GR_DisplayOption *opt,
454  unsigned int pick_type,
455  GR_PickStyle pick_style,
456  bool has_pick_map)
457 {
458  // This example is not pickable.
459  return 0;
460 }
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)
Find an attribute or array in the GL cache, possibly creating it Returns the cached array...
Definition: RE_Geometry.h:840
virtual void renderDecoration(RE_Render *r, GR_Decoration decor, const GR_DecorationParms &parms)
Definition: GR_PrimTetra.C:441
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:83
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:521
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)
void popShader(int *nest=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
const RE_MaterialPtr & getDefaultMaterial() const
Definition: RE_Material.h:837
GLbitfield flags
Definition: glcorearb.h:1595
SYS_FORCE_INLINE const GA_PrimitiveTypeId & getTypeId() const
Definition: GA_Primitive.h:172
bool isPolygonOffset()
SYS_FORCE_INLINE UT_Vector3 getPos3(GA_Offset ptoff) const
The ptoff passed is the point offset.
Definition: GA_Detail.h:170
RE_CacheVersion instance_version
GR_Decoration
Definition: GR_Defines.h:137
png_uint_32 i
Definition: png.h:2877
GR_API bool buildInstanceIndex(RE_Render *r, RE_Geometry *geo, bool has_partial_visibility, const UT_IntArray &inst_indices, int instance_group=0)
virtual void resetPrimitives()
Definition: GR_PrimTetra.C:73
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:452
const char * getCacheName() const
The base GL cache name assigned to this primitive.
Definition: GR_Primitive.h:332
SIM_DerVector3 normalize() const
SYS_FORCE_INLINE GEO_Primitive * getGEOPrimitive(GA_Offset primoff)
Definition: GEO_Detail.h:1089
set of parameters sent to GR_Primitive::update()
GA_Size GA_Offset
Definition: GA_Types.h:617
SYS_FORCE_INLINE GA_Index primitiveIndex(GA_Offset offset) const
Given a primitive's data offset, return its index.
Definition: GA_Detail.h:363
GR_RenderMode
Definition: GR_Defines.h:42
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:602
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:469
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:320
void polygonOffset(bool onoff)
GR_RenderFlags
Definition: GR_Defines.h:77
GA_Size GA_Index
Define the strictness of GA_Offset/GA_Index.
Definition: GA_Types.h:611
#define RE_GEO_SHADED_IDX
Definition: RE_Geometry.h:44
GT_PrimitiveType
const RE_MaterialAtlas * materials
Definition: GR_DrawParms.h:21
void setCacheVersion(RE_CacheVersion v)
GLuint shader
Definition: glcorearb.h:784
SYS_FORCE_INLINE GA_Index getMapIndex() const
Gets the index of this primitive in the detail containing it.
Definition: GA_Primitive.h:142
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:841
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:678
virtual void update(RE_Render *r, const GT_PrimitiveHandle &primh, const GR_UpdateParms &p)
Definition: GR_PrimTetra.C:102
GR_DecorationOverride required_dec
virtual void render(RE_Render *r, GR_RenderMode render_mode, GR_RenderFlags flags, GR_DrawParms dp)
Definition: GR_PrimTetra.C:318
SYS_FORCE_INLINE GA_Offset getVertexOffset(GA_Size primvertexnum) const
Definition: GA_Primitive.h:235
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:184
SIM_DerVector3 cross(const SIM_DerVector3 &lhs, const SIM_DerVector3 &rhs)
const GU_Detail * getGdp() const
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:226