void DrawElementTypeSimplifier::simplify(osg::Geometry & geometry) const { osg::Geometry::PrimitiveSetList & psl = geometry.getPrimitiveSetList(); osg::Geometry::PrimitiveSetList::iterator it, end = psl.end(); unsigned int max = 0; for (it = psl.begin(); it!=end; ++it) { switch ((*it)->getType()) { case osg::PrimitiveSet::DrawElementsUShortPrimitiveType: { osg::DrawElementsUShort & de = *static_cast<osg::DrawElementsUShort*>(it->get()); max = getMax<osg::DrawElementsUShort>(de); if (max < 255) *it = copy<osg::DrawElementsUShort, osg::DrawElementsUByte>(de); break; } case osg::PrimitiveSet::DrawElementsUIntPrimitiveType: { osg::DrawElementsUInt & de = *static_cast<osg::DrawElementsUInt*>(it->get()); max = getMax<osg::DrawElementsUInt>(de); if (max < 256) *it = copy<osg::DrawElementsUInt, osg::DrawElementsUByte>(de); else if (max < 65536) *it = copy<osg::DrawElementsUInt, osg::DrawElementsUShort>(de); break; } default: break; } } }
void RigGeometry::copyFrom(osg::Geometry& from) { bool copyToSelf = (this==&from); osg::Geometry& target = *this; if (!copyToSelf) target.setStateSet(from.getStateSet()); // copy over primitive sets. if (!copyToSelf) target.getPrimitiveSetList() = from.getPrimitiveSetList(); if (from.getVertexArray()) { if (!copyToSelf) target.setVertexArray(from.getVertexArray()); } if (from.getNormalArray()) { if (!copyToSelf) target.setNormalArray(from.getNormalArray()); } if (from.getColorArray()) { if (!copyToSelf) target.setColorArray(from.getColorArray()); } if (from.getSecondaryColorArray()) { if (!copyToSelf) target.setSecondaryColorArray(from.getSecondaryColorArray()); } if (from.getFogCoordArray()) { if (!copyToSelf) target.setFogCoordArray(from.getFogCoordArray()); } for(unsigned int ti=0;ti<from.getNumTexCoordArrays();++ti) { if (from.getTexCoordArray(ti)) { if (!copyToSelf) target.setTexCoordArray(ti,from.getTexCoordArray(ti)); } } osg::Geometry::ArrayList& arrayList = from.getVertexAttribArrayList(); for(unsigned int vi=0;vi< arrayList.size();++vi) { osg::Array* array = arrayList[vi].get(); if (array) { if (!copyToSelf) target.setVertexAttribArray(vi,array); } } }
void osgToy::FacetingVisitor::facet( osg::Geometry& geom ) { // count #surfaces, exit if none osg::Geometry::PrimitiveSetList& primitives = geom.getPrimitiveSetList(); osg::Geometry::PrimitiveSetList::iterator itr; unsigned int numSurfacePrimitives=0; for(itr=primitives.begin(); itr!=primitives.end(); ++itr) { switch((*itr)->getMode()) { case osg::PrimitiveSet::TRIANGLES: case osg::PrimitiveSet::TRIANGLE_STRIP: case osg::PrimitiveSet::TRIANGLE_FAN: case osg::PrimitiveSet::QUADS: case osg::PrimitiveSet::QUAD_STRIP: case osg::PrimitiveSet::POLYGON: ++numSurfacePrimitives; break; default: break; } } if (!numSurfacePrimitives) return; // exit if no vertices osg::Vec3Array *coords = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray()); if (!coords || !coords->size()) return; // generate the normals osg::Vec3Array *normals = new osg::Vec3Array(coords->size()); osg::TriangleIndexFunctor<FacetingOperator> ftif; ftif.set( coords, normals ); geom.accept(ftif); geom.setNormalArray( normals ); geom.setNormalIndices( geom.getVertexIndices() ); geom.setNormalBinding(osg::Geometry::BIND_PER_VERTEX); geom.dirtyDisplayList(); }
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; }
void GeometryValidator::apply(osg::Geometry& geom) { if ( geom.getVertexArray() == 0L ) { OE_NOTICE << LC << "NULL vertex array!!\n"; return; } unsigned numVerts = geom.getVertexArray()->getNumElements(); if ( numVerts == 0 ) { OE_NOTICE << LC << "No verts!! name=" << geom.getName() << "\n"; return; } std::set<osg::BufferObject*> _vbos; osg::Geometry::ArrayList arrays; geom.getArrayList(arrays); for(unsigned i=0; i<arrays.size(); ++i) { osg::Array* a = arrays[i].get(); if ( a ) { if ( a->getBinding() == a->BIND_OVERALL && a->getNumElements() != 1 ) { OE_NOTICE << LC << "Found an array with BIND_OVERALL and size <> 1\n"; } else if ( a->getBinding() == a->BIND_PER_VERTEX && a->getNumElements() != numVerts ) { OE_NOTICE << LC << "Found BIND_PER_VERTEX with wrong number of elements (expecting " << numVerts << "; found " << a->getNumElements() << ")\n"; } _vbos.insert( a->getVertexBufferObject() ); } else { OE_NOTICE << LC << "Found a NULL array\n"; } } if ( _vbos.size() != 1 ) { OE_NOTICE << LC << "Found a Geometry that uses more than one VBO (non-optimal sharing)\n"; } const osg::Geometry::PrimitiveSetList& plist = geom.getPrimitiveSetList(); std::set<osg::BufferObject*> _ebos; for( osg::Geometry::PrimitiveSetList::const_iterator p = plist.begin(); p != plist.end(); ++p ) { osg::PrimitiveSet* pset = p->get(); osg::DrawArrays* da = dynamic_cast<osg::DrawArrays*>(pset); if ( da ) { if ( da->getFirst() >= numVerts ) { OE_NOTICE << LC << "DrawArrays: first > numVerts\n"; } if ( da->getFirst()+da->getCount() > numVerts ) { OE_NOTICE << LC << "DrawArrays: first/count out of bounds\n"; } if ( da->getCount() < 1 ) { OE_NOTICE << LC << "DrawArrays: count is zero\n"; } } bool isDe = pset->getDrawElements() != 0L; osg::DrawElementsUByte* de_byte = dynamic_cast<osg::DrawElementsUByte*>(pset); if ( de_byte ) { validateDE(de_byte, 0xFF, numVerts ); _ebos.insert( de_byte->getElementBufferObject() ); } osg::DrawElementsUShort* de_short = dynamic_cast<osg::DrawElementsUShort*>(pset); if ( de_short ) { validateDE(de_short, 0xFFFF, numVerts ); _ebos.insert( de_short->getElementBufferObject() ); } osg::DrawElementsUInt* de_int = dynamic_cast<osg::DrawElementsUInt*>(pset); if ( de_int ) { validateDE(de_int, 0xFFFFFFFF, numVerts ); _ebos.insert( de_int->getElementBufferObject() ); } if ( pset->getNumIndices() == 0 ) { OE_NOTICE << LC << "Primset: num elements = 0; class=" << pset->className() << ", name=" << pset->getName() << "\n"; } else if ( pset->getType() >= GL_TRIANGLES && pset->getNumIndices() < 3 ) { OE_NOTICE << LC << "Primset: not enough indicies for surface prim type\n"; } else if ( pset->getType() >= GL_LINE_STRIP && pset->getNumIndices() < 2 ) { OE_NOTICE << LC << "Primset: not enough indicies for linear prim type\n"; } else if ( isDe && pset->getType() == GL_LINES && pset->getNumIndices() % 2 != 0 ) { OE_NOTICE << LC << "Primset: non-even index count for GL_LINES\n"; } } if ( _ebos.size() != 1 ) { OE_NOTICE << LC << "Found a Geometry that uses more than one EBO (non-optimal sharing)\n"; } }
void UnIndexMeshVisitor::apply(osg::Geometry& geom) { // no point optimizing if we don't have enough vertices. if (!geom.getVertexArray()) return; // check for the existence of surface primitives unsigned int numIndexedPrimitives = 0; osg::Geometry::PrimitiveSetList& primitives = geom.getPrimitiveSetList(); osg::Geometry::PrimitiveSetList::iterator itr; for(itr=primitives.begin(); itr!=primitives.end(); ++itr) { osg::PrimitiveSet::Type type = (*itr)->getType(); if ((type == osg::PrimitiveSet::DrawElementsUBytePrimitiveType || type == osg::PrimitiveSet::DrawElementsUShortPrimitiveType || type == osg::PrimitiveSet::DrawElementsUIntPrimitiveType)) numIndexedPrimitives++; } // no polygons or no indexed primitive, nothing to do if (!numIndexedPrimitives) { return; } // we dont manage lines GeometryArrayList arraySrc(geom); GeometryArrayList arrayList = arraySrc.cloneType(); osg::Geometry::PrimitiveSetList newPrimitives; for(itr=primitives.begin(); itr!=primitives.end(); ++itr) { osg::PrimitiveSet::Mode mode = (osg::PrimitiveSet::Mode)(*itr)->getMode(); switch(mode) { // manage triangles case(osg::PrimitiveSet::TRIANGLES): case(osg::PrimitiveSet::TRIANGLE_STRIP): case(osg::PrimitiveSet::TRIANGLE_FAN): case(osg::PrimitiveSet::QUADS): case(osg::PrimitiveSet::QUAD_STRIP): case(osg::PrimitiveSet::POLYGON): { // for each geometry list indexes of vertexes // to makes triangles TriangleIndexor triangleIndexList; (*itr)->accept(triangleIndexList); unsigned int index = arrayList.size(); // now copy each vertex to new array, like a draw array arraySrc.append(triangleIndexList._indices, arrayList); newPrimitives.push_back(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, index, triangleIndexList._indices.size())); } break; // manage lines case(osg::PrimitiveSet::LINES): case(osg::PrimitiveSet::LINE_STRIP): case(osg::PrimitiveSet::LINE_LOOP): { EdgeIndexor edgesIndexList; (*itr)->accept(edgesIndexList); unsigned int index = arrayList.size(); // now copy each vertex to new array, like a draw array arraySrc.append(edgesIndexList._indices, arrayList); newPrimitives.push_back(new osg::DrawArrays(osg::PrimitiveSet::LINES, index, edgesIndexList._indices.size())); } break; case(osg::PrimitiveSet::POINTS): { PointIndexor pointsIndexList; (*itr)->accept(pointsIndexList); unsigned int index = arrayList.size(); // now copy each vertex to new array, like a draw array arraySrc.append(pointsIndexList._indices, arrayList); newPrimitives.push_back(new osg::DrawArrays(osg::PrimitiveSet::POINTS, index, pointsIndexList._indices.size())); } break; default: break; } } arrayList.setToGeometry(geom); geom.setPrimitiveSetList(newPrimitives); }
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 }
void MeshConsolidator::convertToTriangles( osg::Geometry& geom, bool force ) { if ( !force && !canOptimize(geom) ) return; osg::Geometry::PrimitiveSetList& primSets = geom.getPrimitiveSetList(); osg::Geometry::PrimitiveSetList triSets, nonTriSets; for( osg::Geometry::PrimitiveSetList::iterator i = primSets.begin(); i != primSets.end(); ++i ) { osg::PrimitiveSet* pset = i->get(); switch( pset->getMode() ) { case osg::PrimitiveSet::TRIANGLES: case osg::PrimitiveSet::TRIANGLE_STRIP: case osg::PrimitiveSet::TRIANGLE_FAN: case osg::PrimitiveSet::QUADS: case osg::PrimitiveSet::QUAD_STRIP: case osg::PrimitiveSet::POLYGON: triSets.push_back( pset ); break; default: nonTriSets.push_back( pset ); } } if ( triSets.size() > 0 ) { // we are assuming at this point that all the primitive sets in a single geometry // share a single user data structure. osg::Referenced* sharedUserData = triSets[0]->getUserData(); osg::Array* vertexArray = geom.getVertexArray(); unsigned numVerts = vertexArray->getNumElements(); osg::Geometry::PrimitiveSetList newPrimSets; if ( numVerts < 0x100 ) { osg::TriangleIndexFunctor< Collector<osg::DrawElementsUByte> > collector; collector._newPrimSets = &newPrimSets; collector._maxSize = 0xFF; geom.accept( collector ); } else if ( numVerts < 0x10000 ) { osg::TriangleIndexFunctor< Collector<osg::DrawElementsUShort> > collector; collector._newPrimSets = &newPrimSets; collector._maxSize = 0xFFFF; geom.accept( collector ); } else { #ifdef OSG_GLES2_AVAILABLE // GLES only supports UShort, not UInt osg::TriangleIndexFunctor< Collector<osg::DrawElementsUShort> > collector; collector._newPrimSets = &newPrimSets; collector._maxSize = 0xFFFF; geom.accept( collector ); #else osg::TriangleIndexFunctor< Collector<osg::DrawElementsUInt> > collector; collector._newPrimSets = &newPrimSets; collector._maxSize = 0xFFFFFFFF; geom.accept( collector ); #endif } for( osg::Geometry::PrimitiveSetList::iterator i = newPrimSets.begin(); i != newPrimSets.end(); ++i ) { i->get()->setUserData( sharedUserData ); nonTriSets.push_back( i->get() ); } } geom.setPrimitiveSetList( nonTriSets ); }
void GeometryValidator::apply(osg::Geometry& geom) { unsigned numVerts = geom.getVertexArray()->getNumElements(); if ( geom.getColorArray() ) { if ( geom.getColorBinding() == osg::Geometry::BIND_OVERALL && geom.getColorArray()->getNumElements() != 1 ) { OE_WARN << "Color: BIND_OVERALL with wrong number of elements" << std::endl; } else if ( geom.getColorBinding() == osg::Geometry::BIND_PER_VERTEX && geom.getColorArray()->getNumElements() != numVerts ) { OE_WARN << "Color: BIND_PER_VERTEX with color.size != verts.size" << std::endl; } } if ( geom.getNormalArray() ) { if ( geom.getNormalBinding() == osg::Geometry::BIND_OVERALL && geom.getNormalArray()->getNumElements() != 1 ) { OE_WARN << "Normal: BIND_OVERALL with wrong number of elements" << std::endl; } else if ( geom.getNormalBinding() == osg::Geometry::BIND_PER_VERTEX && geom.getNormalArray()->getNumElements() != numVerts ) { OE_WARN << "Normal: BIND_PER_VERTEX with color.size != verts.size" << std::endl; } } const osg::Geometry::PrimitiveSetList& plist = geom.getPrimitiveSetList(); for( osg::Geometry::PrimitiveSetList::const_iterator p = plist.begin(); p != plist.end(); ++p ) { osg::PrimitiveSet* pset = p->get(); osg::DrawElementsUByte* de_byte = dynamic_cast<osg::DrawElementsUByte*>(pset); if ( de_byte ) { if ( numVerts > 0xFF ) { OE_WARN << "DrawElementsUByte used when numVerts > 255 (" << numVerts << ")" << std::endl; } validateDE(de_byte, 0xFF, numVerts ); } osg::DrawElementsUShort* de_short = dynamic_cast<osg::DrawElementsUShort*>(pset); if ( de_short ) { if ( numVerts > 0xFFFF ) { OE_WARN << "DrawElementsUShort used when numVerts > 65535 (" << numVerts << ")" << std::endl; } validateDE(de_short, 0xFFFF, numVerts ); } osg::DrawElementsUInt* de_int = dynamic_cast<osg::DrawElementsUInt*>(pset); if ( de_int ) { validateDE(de_int, 0xFFFFFFFF, numVerts ); } } }
void IndexMeshVisitor::apply(osg::Geometry& geom) { // TODO: this is deprecated if (geom.getNormalBinding() == osg::Geometry::BIND_PER_PRIMITIVE_SET) return; if (geom.getColorBinding() == osg::Geometry::BIND_PER_PRIMITIVE_SET) return; if (geom.getSecondaryColorBinding() == osg::Geometry::BIND_PER_PRIMITIVE_SET) return; if (geom.getFogCoordBinding() == osg::Geometry::BIND_PER_PRIMITIVE_SET) return; // no point optimizing if we don't have enough vertices. if (!geom.getVertexArray() || geom.getVertexArray()->getNumElements() < 3) return; osgUtil::SharedArrayOptimizer deduplicator; deduplicator.findDuplicatedUVs(geom); // duplicate shared arrays as it isn't safe to rearrange vertices when arrays are shared. if (geom.containsSharedArrays()) { geom.duplicateSharedArrays(); } osg::Geometry::PrimitiveSetList& primitives = geom.getPrimitiveSetList(); osg::Geometry::PrimitiveSetList::iterator itr; osg::Geometry::PrimitiveSetList new_primitives; new_primitives.reserve(primitives.size()); // compute duplicate vertices typedef std::vector<unsigned int> IndexList; unsigned int numVertices = geom.getVertexArray()->getNumElements(); IndexList indices(numVertices); unsigned int i, j; for(i = 0 ; i < numVertices ; ++ i) { indices[i] = i; } VertexAttribComparitor arrayComparitor(geom); std::sort(indices.begin(), indices.end(), arrayComparitor); unsigned int lastUnique = 0; unsigned int numUnique = 1; for(i = 1 ; i < numVertices ; ++ i) { if (arrayComparitor.compare(indices[lastUnique], indices[i]) != 0) { lastUnique = i; ++ numUnique; } } IndexList remapDuplicatesToOrignals(numVertices); lastUnique = 0; for(i = 1 ; i < numVertices ; ++ i) { if (arrayComparitor.compare(indices[lastUnique],indices[i]) != 0) { // found a new vertex entry, so previous run of duplicates needs // to be put together. unsigned int min_index = indices[lastUnique]; for(j = lastUnique + 1 ; j < i ; ++ j) { min_index = osg::minimum(min_index, indices[j]); } for(j = lastUnique ; j < i ; ++ j) { remapDuplicatesToOrignals[indices[j]] = min_index; } lastUnique = i; } } unsigned int min_index = indices[lastUnique]; for(j = lastUnique + 1 ; j < i ; ++ j) { min_index = osg::minimum(min_index, indices[j]); } for(j = lastUnique ; j < i ; ++ j) { remapDuplicatesToOrignals[indices[j]] = min_index; } // copy the arrays. IndexList finalMapping(numVertices); IndexList copyMapping; copyMapping.reserve(numUnique); unsigned int currentIndex = 0; for(i = 0 ; i < numVertices ; ++ i) { if (remapDuplicatesToOrignals[i] == i) { finalMapping[i] = currentIndex; copyMapping.push_back(i); currentIndex++; } else { finalMapping[i] = finalMapping[remapDuplicatesToOrignals[i]]; } } // remap any shared vertex attributes RemapArray ra(copyMapping); arrayComparitor.accept(ra); // triangulate faces { TriangleIndexor ti; ti._maxIndex = numVertices; ti._remapping = finalMapping; for(itr = primitives.begin() ; itr != primitives.end() ; ++ itr) { (*itr)->accept(ti); } addDrawElements(ti._indices, osg::PrimitiveSet::TRIANGLES, new_primitives); } // line-ify line-type primitives { LineIndexor li, wi; // lines and wireframes li._maxIndex = numVertices; wi._maxIndex = numVertices; li._remapping = finalMapping; wi._remapping = finalMapping; for(itr = primitives.begin() ; itr != primitives.end() ; ++ itr) { bool isWireframe = false; if((*itr)->getUserValue("wireframe", isWireframe) && isWireframe) { (*itr)->accept(wi); } else { (*itr)->accept(li); } } addDrawElements(li._indices, osg::PrimitiveSet::LINES, new_primitives); addDrawElements(wi._indices, osg::PrimitiveSet::LINES, new_primitives, "wireframe"); } // adds points primitives { IndexList points; for(itr = primitives.begin() ; itr != primitives.end() ; ++ itr) { if((*itr) && (*itr)->getMode() == osg::PrimitiveSet::POINTS) { for(unsigned int k = 0 ; k < (*itr)->getNumIndices() ; ++ k) { points.push_back(finalMapping[(*itr)->index(k)]); } } } addDrawElements(points, osg::PrimitiveSet::POINTS, new_primitives); } geom.setPrimitiveSetList(new_primitives); deduplicator.deduplicateUVs(geom); setProcessed(&geom); }