void IndexPseudoPyramidTree::insertToStructure(const Point& point, bool searchKeyExists) { // Add raw point adn the sum of all its elements to the vectors points.push_back(point); pointSums.push_back(point.sum()); int searchKey = computePseudoPyramidValue(numDimensions, point, minPoint, maxPoint, scaleFactors, cumulativeSFProducts); int currentIndex = points.size() - 1; if (searchKeyExists) { // If there is no inserted data, but there is a search key, // be sure to insert the current index (latest inserted point // index) into that point's bucket (this one) IndexList& indices = hashMap.find(searchKey)->second; // storing REFERFENCE so changes are made indices.push_back(currentIndex); } else { // If there is no inserted data and there is no search key IndexList indices; indices.reserve(10); indices.push_back(currentIndex); hashMap[searchKey] = indices; } }
void TriStripVisitor::stripify(Geometry& geom) { if (geom.containsDeprecatedData()) geom.fixDeprecatedData(); if (osg::getBinding(geom.getNormalArray())==osg::Array::BIND_PER_PRIMITIVE_SET) return; if (osg::getBinding(geom.getColorArray())==osg::Array::BIND_PER_PRIMITIVE_SET) return; if (osg::getBinding(geom.getSecondaryColorArray())==osg::Array::BIND_PER_PRIMITIVE_SET) return; if (osg::getBinding(geom.getFogCoordArray())==osg::Array::BIND_PER_PRIMITIVE_SET) return; // no point tri stripping if we don't have enough vertices. if (!geom.getVertexArray() || geom.getVertexArray()->getNumElements()<3) return; // check for the existence of surface primitives unsigned int numSurfacePrimitives = 0; unsigned int numNonSurfacePrimitives = 0; Geometry::PrimitiveSetList& primitives = geom.getPrimitiveSetList(); Geometry::PrimitiveSetList::iterator itr; for(itr=primitives.begin(); itr!=primitives.end(); ++itr) { switch((*itr)->getMode()) { case(PrimitiveSet::TRIANGLES): case(PrimitiveSet::TRIANGLE_STRIP): case(PrimitiveSet::TRIANGLE_FAN): case(PrimitiveSet::QUADS): case(PrimitiveSet::QUAD_STRIP): case(PrimitiveSet::POLYGON): ++numSurfacePrimitives; break; default: ++numNonSurfacePrimitives; break; } } // nothitng to tri strip leave. if (!numSurfacePrimitives) return; // 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; unsigned int numDuplicate = 0; for(i=1;i<numVertices;++i) { if (arrayComparitor.compare(indices[lastUnique],indices[i])==0) { //std::cout<<" found duplicate "<<indices[lastUnique]<<" and "<<indices[i]<<std::endl; ++numDuplicate; } else { //std::cout<<" unique "<<indices[i]<<std::endl; lastUnique = i; ++numUnique; } } // std::cout<<" Number of duplicates "<<numDuplicate<<std::endl; // std::cout<<" Number of unique "<<numUnique<<std::endl; // std::cout<<" Total number of vertices required "<<numUnique<<" vs original "<<numVertices<<std::endl; // std::cout<<" % size "<<(float)numUnique/(float)numVertices*100.0f<<std::endl; 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++; } } for(i=0;i<numVertices;++i) { if (remapDuplicatesToOrignals[i]!=i) { finalMapping[i] = finalMapping[remapDuplicatesToOrignals[i]]; } } MyTriangleIndexFunctor taf; taf._remapIndices.swap(finalMapping); Geometry::PrimitiveSetList new_primitives; new_primitives.reserve(primitives.size()); for(itr=primitives.begin(); itr!=primitives.end(); ++itr) { switch((*itr)->getMode()) { case(PrimitiveSet::TRIANGLES): case(PrimitiveSet::TRIANGLE_STRIP): case(PrimitiveSet::TRIANGLE_FAN): case(PrimitiveSet::QUADS): case(PrimitiveSet::QUAD_STRIP): case(PrimitiveSet::POLYGON): (*itr)->accept(taf); break; default: new_primitives.push_back(*itr); break; } } float minimum_ratio_of_indices_to_unique_vertices = 1; float ratio_of_indices_to_unique_vertices = ((float)taf._in_indices.size()/(float)numUnique); OSG_INFO<<"TriStripVisitor::stripify(Geometry&): Number of indices"<<taf._in_indices.size()<<" numUnique"<< numUnique << std::endl; OSG_INFO<<"TriStripVisitor::stripify(Geometry&): ratio indices/numUnique"<< ratio_of_indices_to_unique_vertices << std::endl; // only tri strip if there is point in doing so. if (!taf._in_indices.empty() && ratio_of_indices_to_unique_vertices>=minimum_ratio_of_indices_to_unique_vertices) { OSG_INFO<<"TriStripVisitor::stripify(Geometry&): doing tri strip"<< std::endl; unsigned int in_numVertices = 0; for(triangle_stripper::indices::iterator itr=taf._in_indices.begin(); itr!=taf._in_indices.end(); ++itr) { if (*itr>in_numVertices) in_numVertices=*itr; } // the largest indice is in_numVertices, but indices start at 0 // so increment to give to the corrent number of verticies. ++in_numVertices; // remap any shared vertex attributes RemapArray ra(copyMapping); arrayComparitor.accept(ra); triangle_stripper::tri_stripper stripifier(taf._in_indices); stripifier.SetCacheSize(_cacheSize); stripifier.SetMinStripSize(_minStripSize); triangle_stripper::primitive_vector outPrimitives; stripifier.Strip(&outPrimitives); if (outPrimitives.empty()) { OSG_WARN<<"Error: TriStripVisitor::stripify(Geometry& geom) failed."<<std::endl; return; } triangle_stripper::primitive_vector::iterator pitr; if (_generateFourPointPrimitivesQuads) { OSG_INFO<<"Collecting all quads"<<std::endl; typedef triangle_stripper::primitive_vector::iterator prim_iterator; typedef std::multimap<unsigned int,prim_iterator> QuadMap; QuadMap quadMap; // pick out quads and place them in the quadMap, and also look for the max for(pitr=outPrimitives.begin(); pitr!=outPrimitives.end(); ++pitr) { if (pitr->Indices.size()==4) { std::swap(pitr->Indices[2],pitr->Indices[3]); unsigned int minValue = *(std::max_element(pitr->Indices.begin(),pitr->Indices.end())); quadMap.insert(QuadMap::value_type(minValue,pitr)); } } // handle the quads if (!quadMap.empty()) { IndexList indices; indices.reserve(4*quadMap.size()); // adds all the quads into the quad primitive, in ascending order // and the QuadMap stores the quad's in ascending order. for(QuadMap::iterator qitr=quadMap.begin(); qitr!=quadMap.end(); ++qitr) { pitr = qitr->second; unsigned int min_pos = 0; for(i=1;i<4;++i) { if (pitr->Indices[min_pos]>pitr->Indices[i]) min_pos = i; } indices.push_back(pitr->Indices[min_pos]); indices.push_back(pitr->Indices[(min_pos+1)%4]); indices.push_back(pitr->Indices[(min_pos+2)%4]); indices.push_back(pitr->Indices[(min_pos+3)%4]); } bool inOrder = true; unsigned int previousValue = indices.front(); for(IndexList::iterator qi_itr=indices.begin()+1; qi_itr!=indices.end() && inOrder; ++qi_itr) { inOrder = (previousValue+1)==*qi_itr; previousValue = *qi_itr; } if (inOrder) { new_primitives.push_back(new osg::DrawArrays(GL_QUADS,indices.front(),indices.size())); } else { unsigned int maxValue = *(std::max_element(indices.begin(),indices.end())); if (maxValue>=65536) { osg::DrawElementsUInt* elements = new osg::DrawElementsUInt(GL_QUADS); std::copy(indices.begin(),indices.end(),std::back_inserter(*elements)); new_primitives.push_back(elements); } else { osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(GL_QUADS); std::copy(indices.begin(),indices.end(),std::back_inserter(*elements)); new_primitives.push_back(elements); } } } } // handle non quad primitives for(pitr=outPrimitives.begin(); pitr!=outPrimitives.end(); ++pitr) { if (!_generateFourPointPrimitivesQuads || pitr->Indices.size()!=4) { bool inOrder = true; unsigned int previousValue = pitr->Indices.front(); for(triangle_stripper::indices::iterator qi_itr=pitr->Indices.begin()+1; qi_itr!=pitr->Indices.end() && inOrder; ++qi_itr) { inOrder = (previousValue+1)==*qi_itr; previousValue = *qi_itr; } if (inOrder) { new_primitives.push_back(new osg::DrawArrays(pitr->Type,pitr->Indices.front(),pitr->Indices.size())); } else { unsigned int maxValue = *(std::max_element(pitr->Indices.begin(),pitr->Indices.end())); if (maxValue>=65536) { osg::DrawElementsUInt* elements = new osg::DrawElementsUInt(pitr->Type); elements->reserve(pitr->Indices.size()); std::copy(pitr->Indices.begin(),pitr->Indices.end(),std::back_inserter(*elements)); new_primitives.push_back(elements); } else { osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(pitr->Type); elements->reserve(pitr->Indices.size()); std::copy(pitr->Indices.begin(),pitr->Indices.end(),std::back_inserter(*elements)); new_primitives.push_back(elements); } } } } geom.setPrimitiveSetList(new_primitives); #if 0 // debugging code for indentifying the tri-strips. osg::Vec4Array* colors = new osg::Vec4Array(new_primitives.size()); for(i=0;i<colors->size();++i) { (*colors)[i].set(((float)rand()/(float)RAND_MAX), ((float)rand()/(float)RAND_MAX), ((float)rand()/(float)RAND_MAX), 1.0f); } geom.setColorArray(colors); geom.setColorBinding(osg::Array::BIND_PER_PRIMITIVE_SET); #endif } else { OSG_INFO<<"TriStripVisitor::stripify(Geometry&): not doing tri strip *****************"<< std::endl; } }
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); }