void process_for_equations(Modelica::MMO_Class &mmo_class) { EquationList &equations = mmo_class.equations_ref().equations_ref(); EquationList new_equations; foreach_ (Equation &e, equations) { if (is<ForEq>(e)) { ForEq feq = boost::get<ForEq>(e); IndexList il = feq.range().indexes(); ERROR_UNLESS(il.size() == 1, "process_for_equations:\n" "forIndexList with more than 1 forIndex are not supported yet\n"); Index in = il.front(); Name variable = in.name(); OptExp ind = in.exp(); ERROR_UNLESS(ind, "for-equation's index with implicit range not supported yet\n"); Expression exp = ind.get(); ForIndexIterator *forIndexIter = NULL; if (is<Range>(exp)) { forIndexIter = new RangeIterator(get<Range>(exp),mmo_class.syms_ref()); } else if (is<Brace>(exp)) { forIndexIter = new BraceIterator(get<Brace>(exp),mmo_class.syms_ref()); } else { ERROR("For Iterator not supported"); } while (forIndexIter->hasNext()) { Real index_val = forIndexIter->next(); foreach_ (Equation eq, feq.elements()) new_equations.push_back(instantiate_equation(eq, variable, index_val, mmo_class.syms_ref())); } delete forIndexIter; } else { // Not a for eq new_equations.push_back(e); } } mmo_class.equations_ref().equations_ref()=new_equations; }
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; } }