void createDAIGeometry( osg::Geometry& geom, int nInstances=1 ) { const float halfDimX( .5 ); const float halfDimZ( .5 ); osg::Vec3Array* v = new osg::Vec3Array; v->resize( 4 ); geom.setVertexArray( v ); // Geometry for a single quad. (*v)[ 0 ] = osg::Vec3( -halfDimX, 0., -halfDimZ ); (*v)[ 1 ] = osg::Vec3( halfDimX, 0., -halfDimZ ); (*v)[ 2 ] = osg::Vec3( halfDimX, 0., halfDimZ ); (*v)[ 3 ] = osg::Vec3( -halfDimX, 0., halfDimZ ); // Use the DrawArraysInstanced PrimitiveSet and tell it to draw 1024 instances. geom.addPrimitiveSet( new osg::DrawArrays( GL_QUADS, 0, 4, nInstances ) ); }
void createFaces(osg::Geometry& geometry, Polyhedron const& polyhedron, unsigned int faceMask = PolyhedronGeometry::All) { osgUtil::Tessellator tessellator; tessellator.setTessellationType(osgUtil::Tessellator::TESS_TYPE_POLYGONS); tessellator.setWindingType(osgUtil::Tessellator::TESS_WINDING_NONZERO); auto _vertices = getOrCreateVertexArray(geometry); auto _normals = getOrCreateNormalArray(geometry); auto _colors = getOrCreateColorArray(geometry); osg::ref_ptr<osg::Vec3Array> vertices = createVertexArray(polyhedron); VertexIndexArrays polygons = createVertexIndexArrays(polyhedron); for (auto const& polygon: polygons) { assert(polygon && polygon->size() >= 3); if (!(faceMask & PolyhedronGeometry::FaceMaskFromSides(polygon->size()))) continue; auto first = _vertices->size(); auto count = polygon->size(); auto normal = detail::calculateNormal(vertices, polygon); auto color = detail::calculateColor(vertices, polygon); for (auto i = 0u; i < polygon->size(); ++i) { auto vertex = vertices->at(polygon->at(i)); _vertices->push_back(vertex); _normals->push_back(normal); _colors->push_back(color); } geometry.addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON, first, count)); } tessellator.retessellatePolygons(geometry); }
void createDAIGeometry( osg::Geometry& geom, int nInstances=1 ) { const float halfDimX( .5 ); const float halfDimZ( .5 ); osg::Vec3Array* v = new osg::Vec3Array; v->resize( 4 ); geom.setVertexArray( v ); // Geometry for a single quad. (*v)[ 0 ] = osg::Vec3( -halfDimX, 0., 0. ); (*v)[ 1 ] = osg::Vec3( halfDimX, 0., 0. ); (*v)[ 2 ] = osg::Vec3( halfDimX, 0., halfDimZ*2.0f ); (*v)[ 3 ] = osg::Vec3( -halfDimX, 0., halfDimZ*2.0f ); // create color array data (each corner of our triangle will have one color component) osg::Vec4Array* pColors = new osg::Vec4Array; pColors->push_back( osg::Vec4( 1.0f, 0.0f, 0.0f, 1.0f ) ); pColors->push_back( osg::Vec4( 0.0f, 1.0f, 0.0f, 1.0f ) ); pColors->push_back( osg::Vec4( 0.0f, 0.0f, 1.0f, 1.0f ) ); pColors->push_back( osg::Vec4( 0.0f, 0.0f, 1.0f, 1.0f ) ); geom.setColorArray( pColors ); // make sure that our geometry is using one color per vertex geom.setColorBinding( osg::Geometry::BIND_PER_VERTEX ); osg::Vec2Array* pTexCoords = new osg::Vec2Array( 4 ); (*pTexCoords)[0].set( 0.0f, 0.0f ); (*pTexCoords)[1].set( 1.0f, 0.0f ); (*pTexCoords)[2].set( 1.0f, 1.0f ); (*pTexCoords)[3].set( 0.0f, 1.0f ); geom.setTexCoordArray( 0, pTexCoords ); // Use the DrawArraysInstanced PrimitiveSet and tell it to draw 1024 instances. geom.addPrimitiveSet( new osg::DrawArrays( GL_QUADS, 0, 4, nInstances ) ); }
bool Tessellator::tessellateGeometry(osg::Geometry &geom) { osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray()); if (!vertices || vertices->empty() || geom.getPrimitiveSetList().empty()) return false; // copy the original primitive set list osg::Geometry::PrimitiveSetList originalPrimitives = geom.getPrimitiveSetList(); // clear the primitive sets unsigned int nprimsetoriginal= geom.getNumPrimitiveSets(); if (nprimsetoriginal) geom.removePrimitiveSet(0, nprimsetoriginal); bool success = true; for (unsigned int i=0; i < originalPrimitives.size(); i++) { osg::ref_ptr<osg::PrimitiveSet> primitive = originalPrimitives[i].get(); if (primitive->getMode()==osg::PrimitiveSet::POLYGON || primitive->getMode()==osg::PrimitiveSet::LINE_LOOP) { if (primitive->getType()==osg::PrimitiveSet::DrawArrayLengthsPrimitiveType) { osg::DrawArrayLengths* drawArrayLengths = static_cast<osg::DrawArrayLengths*>(primitive.get()); unsigned int first = drawArrayLengths->getFirst(); for(osg::DrawArrayLengths::iterator itr=drawArrayLengths->begin(); itr!=drawArrayLengths->end(); ++itr) { unsigned int last = first + *itr; osg::PrimitiveSet* newPrimitive = tessellatePrimitive(first, last, vertices); if (newPrimitive) { geom.addPrimitiveSet(newPrimitive); } else { // tessellation failed, add old primitive set back geom.addPrimitiveSet(primitive); success = false; } first = last; } } else { if (primitive->getNumIndices()>=3) { osg::PrimitiveSet* newPrimitive = tessellatePrimitive(primitive.get(), vertices); if (newPrimitive) { geom.addPrimitiveSet(newPrimitive); } else { // tessellation failed, add old primitive set back geom.addPrimitiveSet(primitive); success = false; } } } } else { // // TODO: handle more primitive modes // } } return success; }
bool Primitive_readLocalData(Input& fr,osg::Geometry& geom) { bool iteratorAdvanced = false; bool firstMatched = false; if ((firstMatched = fr.matchSequence("DrawArrays %w %i %i %i")) || fr.matchSequence("DrawArrays %w %i %i") ) { GLenum mode; Geometry_matchPrimitiveModeStr(fr[1].getStr(),mode); int first; fr[2].getInt(first); int count; fr[3].getInt(count); int numInstances = 0; if (firstMatched) { fr[4].getInt(numInstances); fr += 5; } else { fr += 4; } geom.addPrimitiveSet(new DrawArrays(mode, first, count, numInstances)); iteratorAdvanced = true; } else if ((firstMatched = fr.matchSequence("DrawArrayLengths %w %i %i %i {")) || fr.matchSequence("DrawArrayLengths %w %i %i {") ) { int entry = fr[1].getNoNestedBrackets(); GLenum mode; Geometry_matchPrimitiveModeStr(fr[1].getStr(),mode); int first; fr[2].getInt(first); int capacity; fr[3].getInt(capacity); int numInstances = 0; if (firstMatched) { fr[4].getInt(numInstances); fr += 6; } else { fr += 5; } DrawArrayLengths* prim = new DrawArrayLengths; prim->setMode(mode); prim->setNumInstances(numInstances); prim->setFirst(first); prim->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { unsigned int i; if (fr[0].getUInt(i)) { prim->push_back(i); ++fr; } } ++fr; geom.addPrimitiveSet(prim); iteratorAdvanced = true; } else if ((firstMatched = fr.matchSequence("DrawElementsUByte %w %i %i {")) || fr.matchSequence("DrawElementsUByte %w %i {")) { int entry = fr[1].getNoNestedBrackets(); GLenum mode; Geometry_matchPrimitiveModeStr(fr[1].getStr(),mode); int capacity; fr[2].getInt(capacity); int numInstances = 0; if (firstMatched) { fr[3].getInt(numInstances); fr += 5; } else { fr += 4; } DrawElementsUByte* prim = new DrawElementsUByte; prim->setMode(mode); prim->setNumInstances(numInstances); prim->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { unsigned int i; if (fr[0].getUInt(i)) { prim->push_back(i); ++fr; } } ++fr; geom.addPrimitiveSet(prim); iteratorAdvanced = true; } else if ((firstMatched = fr.matchSequence("DrawElementsUShort %w %i %i {")) || fr.matchSequence("DrawElementsUShort %w %i {")) { int entry = fr[1].getNoNestedBrackets(); GLenum mode; Geometry_matchPrimitiveModeStr(fr[1].getStr(),mode); int capacity; fr[2].getInt(capacity); int numInstances = 0; if (firstMatched) { fr[3].getInt(numInstances); fr += 5; } else { fr += 4; } DrawElementsUShort* prim = new DrawElementsUShort; prim->setMode(mode); prim->setNumInstances(numInstances); prim->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { unsigned int i; if (fr[0].getUInt(i)) { prim->push_back(i); ++fr; } } ++fr; geom.addPrimitiveSet(prim); iteratorAdvanced = true; } else if ((firstMatched = fr.matchSequence("DrawElementsUInt %w %i %i {")) || fr.matchSequence("DrawElementsUInt %w %i {")) { int entry = fr[1].getNoNestedBrackets(); GLenum mode; Geometry_matchPrimitiveModeStr(fr[1].getStr(),mode); int capacity; fr[2].getInt(capacity); int numInstances = 0; if (firstMatched) { fr[3].getInt(numInstances); fr += 5; } else { fr += 4; } DrawElementsUInt* prim = new DrawElementsUInt; prim->setMode(mode); prim->setNumInstances(numInstances); prim->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { unsigned int i; if (fr[0].getUInt(i)) { prim->push_back(i); ++fr; } } ++fr; geom.addPrimitiveSet(prim); iteratorAdvanced = true; } return iteratorAdvanced; }
void Tessellator::collectTessellation(osg::Geometry &geom, unsigned int originalIndex) { osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray()); VertexPtrToIndexMap vertexPtrToIndexMap; // populate the VertexPtrToIndexMap. for(unsigned int vi=0;vi<vertices->size();++vi) { vertexPtrToIndexMap[&((*vertices)[vi])] = vi; } handleNewVertices(geom, vertexPtrToIndexMap); // we don't properly handle per primitive and per primitive_set bindings yet // will need to address this soon. Robert Oct 2002. { osg::Vec3Array* normals = NULL; // GWM Sep 2002 - add normals for extra facets int iprim=0; if (geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE || geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET) { normals = dynamic_cast<osg::Vec3Array*>(geom.getNormalArray()); // GWM Sep 2002 } // GWM Dec 2003 - needed to add colours for extra facets osg::Vec4Array* cols4 = NULL; // GWM Dec 2003 colours are vec4 osg::Vec3Array* cols3 = NULL; // GWM Dec 2003 colours are vec3 if (geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE || geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET) { Array* colours = geom.getColorArray(); // GWM Dec 2003 - need to duplicate face colours switch (colours->getType()) { case osg::Array::Vec4ArrayType: cols4=dynamic_cast<osg::Vec4Array *> (colours); break; case osg::Array::Vec3ArrayType: cols3=dynamic_cast<osg::Vec3Array *> (colours); break; default: break; } } // GWM Dec 2003 - these holders need to go outside the loop to // retain the flat shaded colour &/or normal for each tessellated polygon osg::Vec3 norm(0.0f,0.0f,0.0f); osg::Vec4 primCol4(0.0f,0.0f,0.0f,1.0f); osg::Vec3 primCol3(0.0f,0.0f,0.0f); for(PrimList::iterator primItr=_primList.begin(); primItr!=_primList.end(); ++primItr, ++_index) { Prim* prim=primItr->get(); int ntris=0; if(vertexPtrToIndexMap.size() <= 255) { osg::DrawElementsUByte* elements = new osg::DrawElementsUByte(prim->_mode); for(Prim::VecList::iterator vitr=prim->_vertices.begin(); vitr!=prim->_vertices.end(); ++vitr) { elements->push_back(vertexPtrToIndexMap[*vitr]); } // add to the drawn primitive list. geom.addPrimitiveSet(elements); ntris=elements->getNumIndices()/3; } else if(vertexPtrToIndexMap.size() > 255 && vertexPtrToIndexMap.size() <= 65535) { osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(prim->_mode); for(Prim::VecList::iterator vitr=prim->_vertices.begin(); vitr!=prim->_vertices.end(); ++vitr) { elements->push_back(vertexPtrToIndexMap[*vitr]); } // add to the drawn primitive list. geom.addPrimitiveSet(elements); ntris=elements->getNumIndices()/3; } else { osg::DrawElementsUInt* elements = new osg::DrawElementsUInt(prim->_mode); for(Prim::VecList::iterator vitr=prim->_vertices.begin(); vitr!=prim->_vertices.end(); ++vitr) { elements->push_back(vertexPtrToIndexMap[*vitr]); } // add to the drawn primitive list. geom.addPrimitiveSet(elements); ntris=elements->getNumIndices()/3; } if (primItr==_primList.begin()) { // first primitive so collect primitive normal & colour. if (normals) { if (geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE) norm=(*normals)[originalIndex + _extraPrimitives]; else norm=(*normals)[iprim]; // GWM Sep 2002 the flat shaded normal } if (cols4) { primCol4=(*cols4)[iprim]; // GWM Dec 2003 the flat shaded rgba colour if (_index>=cols4->size()) { cols4->push_back(primCol4); // GWM Dec 2003 add flat shaded colour for new facet } } if (cols3) { primCol3=(*cols3)[iprim]; // GWM Dec 2003 flat shaded rgb colour if (_index>=cols3->size()) { cols3->push_back(primCol3); // GWM Dec 2003 add flat shaded colour for new facet } } } else { // later primitives use same colour if (normals) { if (geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE) { _extraPrimitives++; normals->insert(normals->begin() + originalIndex + _extraPrimitives, norm); } else normals->push_back(norm); // GWM Sep 2002 add flat shaded normal for new facet } if (cols4 && _index>=cols4->size()) { cols4->push_back(primCol4); // GWM Dec 2003 add flat shaded colour for new facet } if (cols3 && _index>=cols3->size()) { if (cols3) cols3->push_back(primCol3); // GWM Dec 2003 add flat shaded colour for new facet } if (prim->_mode==GL_TRIANGLES) { if (geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET || geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE) { // need one per triangle? Not one per set. for (int ii=1; ii<ntris; ii++) { if (normals) normals->push_back(norm); // GWM Sep 2002 add flat shaded normal for new facet } } if (geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET || geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE) { // need one per triangle? Not one per set. for (int ii=1; ii<ntris; ii++) { if (cols3 && _index>=cols3->size()) { if (cols3) cols3->push_back(primCol3); } if (cols4 && _index>=cols4->size()) { if (cols4) cols4->push_back(primCol4); } _index++; } } } // osg::notify(osg::WARN)<<"Add: "<< iprim << std::endl; } iprim++; // GWM Sep 2002 count which normal we should use } } }
void Tessellator::retessellatePolygons(osg::Geometry &geom) { #ifdef OSG_GLU_AVAILABLE // turn the contour list into primitives, a little like Tessellator does but more generally osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray()); if (!vertices || vertices->empty() || geom.getPrimitiveSetList().empty()) return; // we currently don't handle geometry which use indices... if (geom.getVertexIndices() || geom.getNormalIndices() || geom.getColorIndices() || geom.getSecondaryColorIndices() || geom.getFogCoordIndices()) return; // not even text coord indices don't handle geometry which use indices... for(unsigned int unit=0;unit<geom.getNumTexCoordArrays();++unit) { if (geom.getTexCoordIndices(unit)) return; } if (_ttype==TESS_TYPE_POLYGONS || _ttype==TESS_TYPE_DRAWABLE) _numberVerts=0; // 09.04.04 GWM reset Tessellator // the reset is needed by the flt loader which reuses a Tessellator for triangulating polygons. // as such it might be reset by other loaders/developers in future. _index=0; // reset the counter for indexed vertices _extraPrimitives = 0; if (!_numberVerts) { _numberVerts=geom.getVertexArray()->getNumElements(); // save the contours for complex (winding rule) tessellations _Contours=geom.getPrimitiveSetList(); } // now cut out vertex attributes added on any previous tessellation reduceArray(geom.getVertexArray(), _numberVerts); reduceArray(geom.getColorArray(), _numberVerts); reduceArray(geom.getNormalArray(), _numberVerts); reduceArray(geom.getFogCoordArray(), _numberVerts); for(unsigned int unit1=0;unit1<geom.getNumTexCoordArrays();++unit1) { reduceArray(geom.getTexCoordArray(unit1), _numberVerts); } // remove the existing primitives. unsigned int nprimsetoriginal= geom.getNumPrimitiveSets(); if (nprimsetoriginal) geom.removePrimitiveSet(0, nprimsetoriginal); // the main difference from osgUtil::Tessellator for Geometry sets of multiple contours is that the begin/end tessellation // occurs around the whole set of contours. if (_ttype==TESS_TYPE_GEOMETRY) { beginTessellation(); gluTessProperty(_tobj, GLU_TESS_WINDING_RULE, _wtype); gluTessProperty(_tobj, GLU_TESS_BOUNDARY_ONLY , _boundaryOnly); } // process all the contours into the Tessellator int noContours = _Contours.size(); int currentPrimitive = 0; for(int primNo=0;primNo<noContours;++primNo) { osg::ref_ptr<osg::PrimitiveSet> primitive = _Contours[primNo].get(); if (_ttype==TESS_TYPE_POLYGONS || _ttype==TESS_TYPE_DRAWABLE) { // this recovers the 'old' tessellation which just retessellates single polygons. if (primitive->getMode()==osg::PrimitiveSet::POLYGON || _ttype==TESS_TYPE_DRAWABLE) { if (primitive->getType()==osg::PrimitiveSet::DrawArrayLengthsPrimitiveType) { osg::DrawArrayLengths* drawArrayLengths = static_cast<osg::DrawArrayLengths*>(primitive.get()); unsigned int first = drawArrayLengths->getFirst(); for(osg::DrawArrayLengths::iterator itr=drawArrayLengths->begin(); itr!=drawArrayLengths->end(); ++itr) { beginTessellation(); unsigned int last = first + *itr; addContour(primitive->getMode(),first,last,vertices); first = last; endTessellation(); collectTessellation(geom, currentPrimitive); currentPrimitive++; } } else { if (primitive->getNumIndices()>3) { // April 2005 gwm only retessellate "complex" polygons beginTessellation(); addContour(primitive.get(), vertices); endTessellation(); collectTessellation(geom, currentPrimitive); currentPrimitive++; } else { // April 2005 gwm triangles don't need to be retessellated geom.addPrimitiveSet(primitive.get()); } } } else { // copy the contour primitive as it is not being tessellated geom.addPrimitiveSet(primitive.get()); } } else { if (primitive->getMode()==osg::PrimitiveSet::POLYGON || primitive->getMode()==osg::PrimitiveSet::QUADS || primitive->getMode()==osg::PrimitiveSet::TRIANGLES || primitive->getMode()==osg::PrimitiveSet::LINE_LOOP || primitive->getMode()==osg::PrimitiveSet::QUAD_STRIP || primitive->getMode()==osg::PrimitiveSet::TRIANGLE_FAN || primitive->getMode()==osg::PrimitiveSet::TRIANGLE_STRIP) { addContour(primitive.get(), vertices); } else { // copy the contour primitive as it is not being tessellated // in this case points, lines or line_strip geom.addPrimitiveSet(primitive.get()); } } } if (_ttype==TESS_TYPE_GEOMETRY) { endTessellation(); collectTessellation(geom, 0); } #endif }
nave(int x,int y, int z, int tamaño) { pyramidGeode = new osg::Geode(); pyramidGeometry = new osg::Geometry(); pyramidGeode->addDrawable(pyramidGeometry); osg::Vec3Array* pyramidVertices = new osg::Vec3Array; //0-4 pyramidVertices->push_back( osg::Vec3( x, y, z) ); // front left //1-5 pyramidVertices->push_back( osg::Vec3(tamaño+x, y, z) ); // front right //2-6 pyramidVertices->push_back( osg::Vec3(tamaño+x,tamaño+y, z) ); // back right //3-7 pyramidVertices->push_back( osg::Vec3( x,tamaño+y, z) ); // back left //4-0 pyramidVertices->push_back( osg::Vec3( x, y,tamaño+z) ); // peak //5-1 pyramidVertices->push_back( osg::Vec3(tamaño+x, y,tamaño+z) ); // front right //6-2 pyramidVertices->push_back( osg::Vec3(tamaño+x,tamaño+y,tamaño+z) ); // back right //7-3 pyramidVertices->push_back( osg::Vec3( x,tamaño+y,tamaño+z) ); // back left pyramidGeometry->setVertexArray( pyramidVertices ); osg::DrawElementsUInt* pyramidBase = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0); pyramidBase->push_back(3); pyramidBase->push_back(2); pyramidBase->push_back(1); pyramidBase->push_back(0); pyramidGeometry->addPrimitiveSet(pyramidBase); osg::DrawElementsUInt* pyramidTop = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0); pyramidTop->push_back(4); pyramidTop->push_back(5); pyramidTop->push_back(6); pyramidTop->push_back(7); pyramidGeometry->addPrimitiveSet(pyramidTop); //Repeat the same for each of the four sides. Again, vertices are //specified in counter-clockwise order. osg::DrawElementsUInt* pyramidFaceOne = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0); pyramidFaceOne->push_back(0); pyramidFaceOne->push_back(1); pyramidFaceOne->push_back(5); pyramidFaceOne->push_back(4); pyramidGeometry->addPrimitiveSet(pyramidFaceOne); osg::DrawElementsUInt* pyramidFaceTwo = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0); pyramidFaceTwo->push_back(1); pyramidFaceTwo->push_back(2); pyramidFaceTwo->push_back(6); pyramidFaceTwo->push_back(5); pyramidGeometry->addPrimitiveSet(pyramidFaceTwo); osg::DrawElementsUInt* pyramidFaceThree = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0); pyramidFaceThree->push_back(2); pyramidFaceThree->push_back(3); pyramidFaceThree->push_back(7); pyramidFaceThree->push_back(6); pyramidGeometry->addPrimitiveSet(pyramidFaceThree); osg::DrawElementsUInt* pyramidFaceFour = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0); pyramidFaceFour->push_back(3); pyramidFaceFour->push_back(0); pyramidFaceThree->push_back(4); pyramidFaceFour->push_back(7); pyramidGeometry->addPrimitiveSet(pyramidFaceFour); //Declare and load an array of Vec4 elements to store colors. osg::Vec4Array* colors = new osg::Vec4Array; colors->push_back(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f) ); //index 0 red colors->push_back(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f) ); //index 1 green colors->push_back(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f) ); //index 2 blue colors->push_back(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f) ); //index 3 white colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //index 4 red colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //index 4 red colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //index 4 red colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //index 4 red //The next step is to associate the array of colors with the geometry, //assign the color indices created above to the geometry and set the //binding mode to _PER_VERTEX. pyramidGeometry->setColorArray(colors); pyramidGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX); };