root/OpenSceneGraph/trunk/src/osgPlugins/bsp/VBSPGeometry.cpp @ 13041

Revision 13041, 23.7 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
Line 
1
2#include <stdlib.h>
3#include <osg/Geode>
4#include <osgUtil/TriStripVisitor>
5
6#include "VBSPGeometry.h"
7
8
9using namespace osg;
10using namespace bsp;
11
12
13VBSPGeometry::VBSPGeometry(VBSPData * bspData)
14{
15    // Keep track of the bsp data, as it has all of the data lists that we
16    // need
17    bsp_data = bspData;
18
19    // Create arrays for the vertex attributes
20    vertex_array = new Vec3Array();
21    normal_array = new Vec3Array();
22    texcoord_array = new Vec2Array();
23
24    // Create a primitive set for drawing variable length primitives (VBSP
25    // primitives are only guaranteed to be convex polygons)
26    primitive_set = new DrawArrayLengths(PrimitiveSet::POLYGON);
27
28    // Create a second set of arrays for displacement surfaces
29    disp_vertex_array = new Vec3Array();
30    disp_normal_array = new Vec3Array();
31    disp_texcoord_array = new Vec2Array();
32    disp_vertex_attr_array = new Vec4Array();
33
34    // Create a second primitive set for drawing indexed triangles, which is
35    // the quickest method for drawing the displacement surfaces
36    disp_primitive_set = new DrawElementsUInt(PrimitiveSet::TRIANGLES);
37}
38
39
40VBSPGeometry::~VBSPGeometry()
41{
42}
43
44
45bool VBSPGeometry::doesEdgeExist(int row, int col, int direction,
46                                 int vertsPerEdge)
47{
48    // See if there is an edge on the displacement surface from the given
49    // vertex in the given direction (we only need to know the vertices
50    // indices, because all displacement surfaces are tessellated in the
51    // same way)
52    switch (direction)
53    {
54        case 0:
55            // False if we're on the left edge, otherwise true
56            if ((row - 1) < 0)
57                return false;
58            else
59                return true;
60
61        case 1:
62            // False if we're on the top edge, otherwise true
63            if ((col + 1) >= vertsPerEdge)
64                return false;
65            else
66                return true;
67
68        case 2:
69            // False if we're on the right edge, otherwise true
70            if ((row + 1) >= vertsPerEdge)
71                return false;
72            else
73                return true;
74
75        case 3:
76            // False if we're on the bottom edge, otherwise true
77            if ((col - 1) < 0)
78                return false;
79            else
80                return true;
81
82        default:
83            return false;
84    }
85}
86
87
88osg::Vec3 VBSPGeometry::getNormalFromEdges(int row, int col,
89                                           unsigned char edgeBits,
90                                           int firstVertex, int vertsPerEdge)
91{
92    osg::Vec3 *   vertexData;
93    osg::Vec3 *   surfaceVerts;
94    osg::Vec3     finalNormal;
95    osg::Vec3     v1, v2, v3;
96    osg::Vec3     e1, e2;
97    osg::Vec3     tempNormal;
98    int           normalCount;
99
100    // Constants for direction.  If the bit is set in the edgeBits, then
101    // there is an edge connected to the current vertex in that direction
102    const unsigned char   NEG_X = 1 << 0;
103    const unsigned char   POS_Y = 1 << 1;
104    const unsigned char   POS_X = 1 << 2;
105    const unsigned char   NEG_Y = 1 << 3;
106
107    // Constants for quadrants.  If both bits are set, then there are
108    // exactly two triangles in that quadrant
109    const unsigned char   QUAD_1 = POS_X | POS_Y;
110    const unsigned char   QUAD_2 = NEG_X | POS_Y;
111    const unsigned char   QUAD_3 = NEG_X | NEG_Y;
112    const unsigned char   QUAD_4 = POS_X | NEG_Y;
113
114
115    // Grab the vertex data from the displaced vertex array (if there's a
116    // better way to randomly access the data in this array, I'm all ears)
117    vertexData = (osg::Vec3 *)disp_vertex_array->getDataPointer();
118
119    // Move to the surface we're interested in, and start counting vertices
120    // from there
121    surfaceVerts = &vertexData[firstVertex];
122
123    // Start with no normals computed
124    finalNormal.set(0.0, 0.0, 0.0);
125    normalCount = 0;
126
127    // The process is fairly simple.  For all four quadrants surrounding
128    // the vertex, check each quadrant to see if there are triangles there.
129    // If so, calculate the normals of the two triangles in that quadrant, and
130    // add them to the final normal.  When fininshed, scale the final normal
131    // based on the number of contributing triangle normals
132
133    // Check quadrant 1 (+X,+Y)
134    if ((edgeBits & QUAD_1) == QUAD_1)
135    {
136        // First triangle
137        v1 = surfaceVerts[(col+1) * vertsPerEdge + row];
138        v2 = surfaceVerts[col * vertsPerEdge + row];
139        v3 = surfaceVerts[col * vertsPerEdge + (row+1)];
140        e1 = v1 - v2;
141        e2 = v3 - v2;
142        tempNormal = e2 ^ e1;
143        tempNormal.normalize();
144        finalNormal += tempNormal;
145        normalCount++;
146
147        // Second triangle
148        v1 = surfaceVerts[(col+1) * vertsPerEdge + row];
149        v2 = surfaceVerts[col * vertsPerEdge + (row+1)];
150        v3 = surfaceVerts[(col+1) * vertsPerEdge + (row+1)];
151        e1 = v1 - v2;
152        e2 = v3 - v2;
153        tempNormal = e2 ^ e1;
154        tempNormal.normalize();
155        finalNormal += tempNormal;
156        normalCount++;
157    }
158
159    // Check quadrant 2 (-X,+Y)
160    if ((edgeBits & QUAD_2) == QUAD_2)
161    {
162        // First triangle
163        v1 = surfaceVerts[(col+1) * vertsPerEdge + (row-1)];
164        v2 = surfaceVerts[col * vertsPerEdge + (row-1)];
165        v3 = surfaceVerts[col * vertsPerEdge + row];
166        e1 = v1 - v2;
167        e2 = v3 - v2;
168        tempNormal = e2 ^ e1;
169        tempNormal.normalize();
170        finalNormal += tempNormal;
171        normalCount++;
172
173        // Second triangle
174        v1 = surfaceVerts[(col+1) * vertsPerEdge + (row-1)];
175        v2 = surfaceVerts[col * vertsPerEdge + row];
176        v3 = surfaceVerts[(col+1) * vertsPerEdge + row];
177        e1 = v1 - v2;
178        e2 = v3 - v2;
179        tempNormal = e2 ^ e1;
180        tempNormal.normalize();
181        finalNormal += tempNormal;
182        normalCount++;
183    }
184
185    // Check quadrant 3 (-X,-Y)
186    if ((edgeBits & QUAD_3) == QUAD_3)
187    {
188        // First triangle
189        v1 = surfaceVerts[col * vertsPerEdge + (row-1)];
190        v2 = surfaceVerts[(col-1) * vertsPerEdge + (row-1)];
191        v3 = surfaceVerts[(col-1) * vertsPerEdge + row];
192        e1 = v1 - v2;
193        e2 = v3 - v2;
194        tempNormal = e2 ^ e1;
195        tempNormal.normalize();
196        finalNormal += tempNormal;
197        normalCount++;
198
199        // Second triangle
200        v1 = surfaceVerts[col * vertsPerEdge + (row-1)];
201        v2 = surfaceVerts[(col-1) * vertsPerEdge + row];
202        v3 = surfaceVerts[col * vertsPerEdge + row];
203        e1 = v1 - v2;
204        e2 = v3 - v2;
205        tempNormal = e2 ^ e1;
206        tempNormal.normalize();
207        finalNormal += tempNormal;
208        normalCount++;
209    }
210
211    // Check quadrant 4 (+X,-Y)
212    if ((edgeBits & QUAD_4) == QUAD_4)
213    {
214        // First triangle
215        v1 = surfaceVerts[col * vertsPerEdge + row];
216        v2 = surfaceVerts[(col-1) * vertsPerEdge + row];
217        v3 = surfaceVerts[(col-1) * vertsPerEdge + (row+1)];
218        e1 = v1 - v2;
219        e2 = v3 - v2;
220        tempNormal = e2 ^ e1;
221        tempNormal.normalize();
222        finalNormal += tempNormal;
223        normalCount++;
224
225        // Second triangle
226        v1 = surfaceVerts[col * vertsPerEdge + row];
227        v2 = surfaceVerts[(col-1) * vertsPerEdge + (row+1)];
228        v3 = surfaceVerts[col * vertsPerEdge + (row+1)];
229        e1 = v1 - v2;
230        e2 = v3 - v2;
231        tempNormal = e2 ^ e1;
232        tempNormal.normalize();
233        finalNormal += tempNormal;
234        normalCount++;
235    }
236
237    // Scale the final normal according to how many triangle normals are
238    // contributing
239    finalNormal *= (1.0f / (float)normalCount);
240
241    return finalNormal;
242}
243
244
245void VBSPGeometry::createDispSurface(Face & face, DisplaceInfo & dispInfo)
246{
247    TexInfo           currentTexInfo;
248    TexData           currentTexData;
249    Vec3              texU;
250    float             texUOffset;
251    float             texUScale;
252    Vec3              texV;
253    float             texVOffset;
254    float             texVScale;
255    int               i, j;
256    unsigned int      k;
257    double            dist, minDist;
258    int               minIndex = 0;
259    osg::Vec3         temp;
260    int               edgeIndex;
261    int               currentSurfEdge;
262    Edge              currentEdge;
263    osg::Vec3         currentVertex;
264    osg::Vec3         vertices[4];
265    unsigned int      firstVertex;
266    int               numEdgeVertices;
267    double            subdivideScale;
268    osg::Vec3         leftEdge, rightEdge;
269    osg::Vec3         leftEdgeStep, rightEdgeStep;
270    osg::Vec3         leftEnd, rightEnd;
271    osg::Vec3         leftRightSeg, leftRightStep;
272    unsigned int      dispVertIndex;
273    DisplacedVertex   dispVertInfo;
274    osg::Vec3         flatVertex, dispVertex;
275    unsigned int      index;
276    osg::Vec3         normal;
277    float             u, v;
278    osg::Vec2         texCoord;
279    float             alphaBlend;
280    unsigned char     edgeBits;
281
282
283    // Get the texture info for this face
284    currentTexInfo = bsp_data->getTexInfo(face.texinfo_index);
285    currentTexData = bsp_data->getTexData(currentTexInfo.texdata_index);
286
287    // Get the texture vectors and offsets.  These are used to calculate
288    // texture coordinates
289    texU.set(currentTexInfo.texture_vecs[0][0],
290             currentTexInfo.texture_vecs[0][1],
291             currentTexInfo.texture_vecs[0][2]);
292    texUOffset = currentTexInfo.texture_vecs[0][3];
293    texV.set(currentTexInfo.texture_vecs[1][0],
294             currentTexInfo.texture_vecs[1][1],
295             currentTexInfo.texture_vecs[1][2]);
296    texVOffset = currentTexInfo.texture_vecs[1][3];
297
298    // Scale the texture vectors from inches to meters
299    texU *= 39.37f;
300    texV *= 39.37f;
301
302    // Get the size of the texture involved, as the planar texture projection
303    // assumes non-normalized texture coordinates
304    texUScale = 1.0f / (float)currentTexData.texture_width;
305    texVScale = 1.0f / (float)currentTexData.texture_height;
306
307    // Get the first edge index
308    edgeIndex = face.first_edge;
309
310    // Get the base vertices for this face
311    for (i = 0; i < face.num_edges; i++)
312    {
313        // Look up the edge specified by the surface edge index, the
314        // index might be negative (see below), so take the absolute
315        // value
316        currentSurfEdge = bsp_data->getSurfaceEdge(edgeIndex);
317        currentEdge = bsp_data->getEdge(abs(currentSurfEdge));
318
319        // The sign of the surface edge index specifies which vertex is
320        // "first" for this face.  A negative index means the edge should
321        // be flipped, and the second vertex treated as the first
322        if (currentSurfEdge < 0)
323            currentVertex = bsp_data->getVertex(currentEdge.vertex[1]);
324        else
325            currentVertex = bsp_data->getVertex(currentEdge.vertex[0]);
326
327        // Add the vertex to the array
328        vertices[i] = currentVertex;
329
330        // Move on to the next vertex
331        edgeIndex++;
332    }
333
334    // Rotate the base coordinates for the surface until the first vertex
335    // matches the start position
336    minDist = 1.0e9;
337    for (i = 0; i < 4; i++)
338    {
339       // Calculate the distance of the start position from this vertex
340       dist = (vertices[i] - dispInfo.start_position * 0.0254f).length();
341
342       // If this is the smallest distance we've seen, remember it
343       if (dist < minDist)
344       {
345          minDist = dist;
346          minIndex = i;
347       }
348    }
349
350    // Rotate the displacement surface quad until we get the starting vertex
351    // in the 0th position
352    for (i = 0; i < minIndex; i++)
353    {
354        temp = vertices[0];
355        vertices[0] = vertices[1];
356        vertices[1] = vertices[2];
357        vertices[2] = vertices[3];
358        vertices[3] = temp;
359    }
360
361    // Calculate the vectors for the left and right edges of the surface
362    // (remembering that the surface is wound clockwise)
363    leftEdge = vertices[1] - vertices[0];
364    rightEdge = vertices[2] - vertices[3];
365
366    // Calculate the number of vertices along each edge of the surface
367    numEdgeVertices = (1 << dispInfo.power) + 1;
368
369    // Calculate the subdivide scale, which will tell us how far apart to
370    // put each vertex (relative to the length of the surface's edges)
371    subdivideScale = 1.0 / (double)(numEdgeVertices - 1);
372
373    // Calculate the step size between vertices on the left and right edges
374    leftEdgeStep = leftEdge * subdivideScale;
375    rightEdgeStep = rightEdge * subdivideScale;
376
377    // Remember the first vertex index in the vertex array
378    firstVertex = disp_vertex_array->size();
379
380    // Generate the displaced vertices (this technique comes from the
381    // Source SDK)
382    for (i = 0; i < numEdgeVertices; i++)
383    {
384        // Calculate the two endpoints for this section of the surface
385        leftEnd = leftEdgeStep * (double) i;
386        leftEnd += vertices[0];
387        rightEnd = rightEdgeStep * (double) i;
388        rightEnd += vertices[3];
389
390        // Now, get the vector from left to right, and subdivide it as well
391        leftRightSeg = rightEnd - leftEnd;
392        leftRightStep = leftRightSeg * subdivideScale;
393
394        // Generate the vertices for this section
395        for (j = 0; j < numEdgeVertices; j++)
396        {
397            // Get the displacement info for this vertex
398            dispVertIndex = dispInfo.disp_vert_start;
399            dispVertIndex += i * numEdgeVertices + j;
400            dispVertInfo = bsp_data->getDispVertex(dispVertIndex);
401
402            // Calculate the flat vertex
403            flatVertex = leftEnd + (leftRightStep * (double) j);
404
405            // Calculate the displaced vertex
406            dispVertex =
407                dispVertInfo.displace_vec *
408                (dispVertInfo.displace_dist * 0.0254);
409            dispVertex += flatVertex;
410
411            // Add the vertex to the displaced vertex array
412            disp_vertex_array->push_back(dispVertex);
413
414            // Calculate the texture coordinates for this vertex.  Texture
415            // coordinates are calculated using a planar projection, so we need
416            // to use the non-displaced vertex position here
417            u = texU * flatVertex + texUOffset;
418            u *= texUScale;
419            v = texV * flatVertex + texVOffset;
420            v *= texVScale;
421            texCoord.set(u, v);
422
423            // Add the texture coordinate to the array
424            disp_texcoord_array->push_back(texCoord);
425
426            // Get the texture blend parameter for this vertex as well, and
427            // assign it as the alpha channel for the primary vertex color.
428            // We'll use a combiner operation to do the texture blending
429            alphaBlend = dispVertInfo.alpha_blend / 255.0;
430            disp_vertex_attr_array->push_back(
431                osg::Vec4f(1.0, 1.0, 1.0, 1.0 - alphaBlend));
432        }
433    }
434
435    // Calculate normals at each vertex (this is adapted from the Source SDK,
436    // including the two helper functions)
437    for (i = 0; i < numEdgeVertices; i++)
438    {
439        for (j = 0; j < numEdgeVertices; j++)
440        {
441            // See which of the 4 possible edges (left, up, right, or down) are
442            // incident on this vertex
443            edgeBits = 0;
444            for (k = 0; k < 4; k++)
445            {
446                if (doesEdgeExist(j, i, k, numEdgeVertices))
447                    edgeBits |= 1 << k;
448            }
449
450            // Calculate the normal based on the adjacent edges
451            normal = getNormalFromEdges(j, i, edgeBits, firstVertex,
452                                        numEdgeVertices);
453
454            // Add the normal to the normal array
455            disp_normal_array->push_back(normal);
456        }
457    }
458
459    // Now, triangulate the surface (this technique comes from the Source SDK)
460    for (i = 0; i < numEdgeVertices-1; i++)
461    {
462        for (j = 0; j < numEdgeVertices-1; j++)
463        {
464            // Get the current vertex index (local to this surface)
465            index = i * numEdgeVertices + j;
466
467            // See if this index is odd
468            if ((index % 2) == 1)
469            {
470                // Add the vertex offset (so we reference this surface's
471                // vertices in the array)
472                index += firstVertex;
473
474                // Create two triangles on this vertex from top-left to
475                // bottom-right
476                disp_primitive_set->push_back(index);
477                disp_primitive_set->push_back(index + 1);
478                disp_primitive_set->push_back(index + numEdgeVertices);
479                disp_primitive_set->push_back(index + 1);
480                disp_primitive_set->push_back(index + numEdgeVertices + 1);
481                disp_primitive_set->push_back(index + numEdgeVertices);
482            }
483            else
484            {
485                // Add the vertex offset (so we reference this surface's
486                // vertices in the array)
487                index += firstVertex;
488
489                // Create two triangles on this vertex from bottom-left to
490                // top-right
491                disp_primitive_set->push_back(index);
492                disp_primitive_set->push_back(index + numEdgeVertices + 1);
493                disp_primitive_set->push_back(index + numEdgeVertices);
494                disp_primitive_set->push_back(index);
495                disp_primitive_set->push_back(index + 1);
496                disp_primitive_set->push_back(index + numEdgeVertices + 1);
497            }
498        }
499    }
500}
501
502
503void VBSPGeometry::addFace(int faceIndex)
504{
505    Face                  currentFace;
506    Edge                  currentEdge;
507    DisplaceInfo          currentDispInfo;
508    TexInfo               currentTexInfo;
509    TexData               currentTexData;
510    Vec3                  normal;
511    int                   edgeIndex;
512    int                   i;
513    int                   currentSurfEdge;
514    Vec3                  currentVertex;
515    Vec3                  texU;
516    float                 texUOffset;
517    float                 texUScale;
518    Vec3                  texV;
519    float                 texVOffset;
520    float                 texVScale;
521    float                 u, v;
522    Vec2f                 texCoord;
523
524    // Make sure this face is not "on node" (an internal node of the BSP tree).
525    // These faces are not used for visible geometry
526    currentFace = bsp_data->getFace(faceIndex);
527
528    // See if this is a displacement surface
529    if (currentFace.dispinfo_index != -1)
530    {
531        // Get the displacement info
532        currentDispInfo =
533            bsp_data->getDispInfo(currentFace.dispinfo_index);
534
535        // Generate the displacement surface
536        createDispSurface(currentFace, currentDispInfo);
537    }
538    else
539    {
540        // Get the face normal, using the plane information
541        normal = bsp_data->getPlane(currentFace.plane_index).plane_normal;
542        if (currentFace.plane_side != 0)
543            normal = -normal;
544
545        // Get the texture info and data structures
546        currentTexInfo = bsp_data->getTexInfo(currentFace.texinfo_index);
547        currentTexData = bsp_data->getTexData(currentTexInfo.texdata_index);
548
549        // Get the texture vectors and offsets.  These are used to calculate
550        // texture coordinates
551        texU.set(currentTexInfo.texture_vecs[0][0],
552                 currentTexInfo.texture_vecs[0][1],
553                 currentTexInfo.texture_vecs[0][2]);
554        texUOffset = currentTexInfo.texture_vecs[0][3];
555        texV.set(currentTexInfo.texture_vecs[1][0],
556                 currentTexInfo.texture_vecs[1][1],
557                 currentTexInfo.texture_vecs[1][2]);
558        texVOffset = currentTexInfo.texture_vecs[1][3];
559
560        // Scale the texture vectors from inches to meters
561        texU *= 39.37f;
562        texV *= 39.37f;
563
564        // Get the texture size, as the planar texture projection results in
565        // non-normalized texture coordinates
566        texUScale = 1.0f / (float)currentTexData.texture_width;
567        texVScale = 1.0f / (float)currentTexData.texture_height;
568
569        // Start with the last edge index, because we need to switch from
570        // clockwise winding (DirectX) to counter-clockwise winding (OpenGL)
571        edgeIndex = currentFace.first_edge + currentFace.num_edges - 1;
572
573        // Set the length of this primitive on the primitive set
574        primitive_set->push_back(currentFace.num_edges);
575
576        // Iterate over the edges in this face, and extract the vertex data
577        for (i = 0; i < currentFace.num_edges; i++)
578        {
579            // Look up the edge specified by the surface edge index, the
580            // index might be negative (see below), so take the absolute
581            // value
582            currentSurfEdge = bsp_data->getSurfaceEdge(edgeIndex);
583            currentEdge = bsp_data->getEdge(abs(currentSurfEdge));
584
585            // The sign of the surface edge index specifies which vertex is
586            // "first" for this face.  A negative index means the edge should
587            // be flipped, and the second vertex treated as the first
588            if (currentSurfEdge < 0)
589                currentVertex = bsp_data->getVertex(currentEdge.vertex[1]);
590            else
591                currentVertex = bsp_data->getVertex(currentEdge.vertex[0]);
592
593            // Add the vertex to the array
594            vertex_array->push_back(currentVertex);
595
596            // Set the normal
597            normal_array->push_back(normal);
598
599            // Calculate the texture coordinates for this vertex
600            u = texU * currentVertex + texUOffset;
601            u *= texUScale;
602            v = texV * currentVertex + texVOffset;
603            v *= texVScale;
604            texCoord.set(u, v);
605
606            // Add the texture coordinate to the array
607            texcoord_array->push_back(texCoord);
608
609            // Move on to the next (previous?) vertex
610            edgeIndex--;
611        }
612    }
613}
614
615
616ref_ptr<Group> VBSPGeometry::createGeometry()
617{
618    ref_ptr<Group>       rootGroup;
619    ref_ptr<Geode>       geode;
620    ref_ptr<Geometry>    geometry;
621    Vec4f                color;
622    ref_ptr<Vec4Array>   colorArray;
623
624    // Create the root group (we'll attach everything to this group and
625    // return it)
626    rootGroup = new Group();
627
628    // Create a geode for the geometries
629    geode = new Geode();
630    rootGroup->addChild(geode.get());
631
632    // See if there are any regular (non-displaced) faces to render
633    if (primitive_set->size() > 0)
634    {
635        // Create a geometry object for the regular surfaces
636        geometry = new Geometry();
637
638        // Add the vertex attributes
639        geometry->setVertexArray(vertex_array.get());
640        geometry->setNormalArray(normal_array.get());
641        geometry->setNormalBinding(Geometry::BIND_PER_VERTEX);
642        geometry->setTexCoordArray(0, texcoord_array.get());
643
644        // Add an overall color
645        color.set(1.0, 1.0, 1.0, 1.0);
646        colorArray = new Vec4Array(1, &color);
647        geometry->setColorArray(colorArray.get());
648        geometry->setColorBinding(Geometry::BIND_OVERALL);
649
650        // Add our primitive set to the geometry
651        geometry->addPrimitiveSet(primitive_set.get());
652
653        // Add the geometry to the geode
654        geode->addDrawable(geometry.get());
655
656        // Now, stripify the geode to convert the POLYGON primitives to
657        // triangle strips
658        osgUtil::TriStripVisitor tsv;
659        geode->accept(tsv);
660        tsv.stripify();
661    }
662
663    // Now do the same for the displacement surfaces (if any)
664    if (disp_primitive_set->size() > 0)
665    {
666        // Create a geometry object for the regular surfaces
667        geometry = new Geometry();
668
669        // Add the vertex attributes
670        geometry->setVertexArray(disp_vertex_array.get());
671        geometry->setNormalArray(disp_normal_array.get());
672        geometry->setNormalBinding(Geometry::BIND_PER_VERTEX);
673        geometry->setTexCoordArray(0, disp_texcoord_array.get());
674        geometry->setTexCoordArray(1, disp_texcoord_array.get());
675        geometry->setColorArray(disp_vertex_attr_array.get());
676        geometry->setColorBinding(Geometry::BIND_PER_VERTEX);
677
678        // Add our primitive set to the geometry
679        geometry->addPrimitiveSet(disp_primitive_set.get());
680
681        // Add the geometry to the geode
682        geode->addDrawable(geometry.get());
683    }
684
685    // Return the root group
686    return rootGroup;
687}
Note: See TracBrowser for help on using the browser.