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 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 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); }