コード例 #1
0
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;
    }

}
コード例 #2
0
ファイル: decomposeTerm.cpp プロジェクト: coin-or/Couenne
void CouenneProblem::decomposeTerm (expression *term,
				    CouNumber initCoe,
				    CouNumber &c0,
				    LinMap  &lmap,
				    QuadMap &qmap) {

  switch (term -> code ()) {

    // easy cases ////////////////////////////////////////////////////////////////////////

  case COU_EXPRCONST: /// a constant
    c0 += initCoe * term -> Value ();
    break;

  case COU_EXPRVAR:   /// a variable
    lmap.insert (term -> Index (), initCoe);
    break;

  case COU_EXPROPP:   /// the opposite of a term
    decomposeTerm (term -> Argument (), -initCoe, c0, lmap, qmap);
    break;

  case COU_EXPRSUB:   /// a subtraction
    decomposeTerm (term -> ArgList () [0],  initCoe, c0, lmap, qmap);
    decomposeTerm (term -> ArgList () [1], -initCoe, c0, lmap, qmap);
    break;

  case COU_EXPRQUAD: { /// a quadratic form

    exprQuad *t = dynamic_cast <exprQuad *> (term -> isaCopy () ? 
					     term -> Copy () : 
					     term);
    exprQuad::sparseQ &M = t -> getQ ();

    for (exprQuad::sparseQ::iterator row = M.begin (); 
	 row != M.end (); ++row) {

      int xind = row -> first -> Index ();

      for (exprQuad::sparseQcol::iterator col = row -> second.begin (); 
	   col != row -> second.end (); ++col) {
	qmap.insert (xind, col -> first -> Index (), initCoe * col -> second);
      }
    }
  } // NO break here, exprQuad generalizes exprGroup

  case COU_EXPRGROUP: { /// a linear term

    exprGroup *t = dynamic_cast <exprGroup *> (term -> isaCopy () ? 
					       term -> Copy () : 
					       term);
    exprGroup::lincoeff &lcoe = t -> lcoeff ();

    //  for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el)
    for (int n = lcoe.size (), i=0; n--; i++)
      lmap.insert (lcoe [i].first -> Index (), initCoe * lcoe [i].second);

    c0 += initCoe * t -> getc0 ();
  } // NO break here, exprGroup generalizes exprSum

  case COU_EXPRSUM: { /// a sum of (possibly) nonlinear elements

    expression **al = term -> ArgList ();
    for (int i = term -> nArgs (); i--;)
      decomposeTerm (*al++, initCoe, c0, lmap, qmap);

  } break;

  // not-so-easy cases /////////////////////////////////////////////////////////////////
  //
  // cannot add terms as it may fill up the triplet

  case COU_EXPRMUL: { /// a product of n factors /////////////////////////////////////////

    std::map <int, CouNumber> indices;
    CouNumber coe = initCoe;

    // return list of variables (some of which auxiliary)
    flattenMul (term, coe, indices);

    if (jnlst_ -> ProduceOutput (Ipopt::J_ALL, J_REFORMULATE)) {
      printf ("from flattenmul: [%g] ", coe);
      for (std::map <int, CouNumber>::iterator itt = indices.begin ();
	   itt != indices.end(); ++itt)
	printf (" %d,%g",
		itt -> first,
		itt -> second);
      printf ("\n");
    }

    // based on number of factors, decide what to return
    switch (indices.size ()) {

    case 0: // no variables in multiplication (hmmm...)
      c0 += coe;
      break;

    case 1: { // only one term (may be with exponent != 1)

      std::map <int, CouNumber>::iterator one = indices.begin ();
      int       index = one -> first;
      CouNumber expon = one -> second;

      if      (fabs (expon - 1) < COUENNE_EPS) lmap.insert (index, coe);
      else if (fabs (expon - 2) < COUENNE_EPS) qmap.insert (index, index, coe);
      else {
	exprAux *aux = addAuxiliary 
	  (new exprPow (new exprClone (Var (index)),
			new exprConst (expon)));

	//linsert (lmap, aux -> Index (), initCoe); // which of these three is correct?
	//linsert (lmap, aux -> Index (), initCoe * coe);
	lmap.insert (aux -> Index (), coe);
      }
    } break;

    case 2: { // two terms

      int ind0, ind1;

      std::map <int, CouNumber>::iterator one = indices.begin (), 
	two = one;
      ++two; // now "two" points to the other variable

      // first variable
      if (fabs (one -> second - 1) > COUENNE_EPS) {
	exprAux *aux = addAuxiliary (new exprPow (new exprClone (Var (one -> first)),
						  new exprConst (one -> second)));
	ind0 = aux -> Index ();
      } else ind0 = one -> first;

      // second variable
      if (fabs (two -> second - 1) > COUENNE_EPS) {
	exprAux *aux = addAuxiliary (new exprPow (new exprClone (Var (two -> first)),
						  new exprConst (two -> second)));
	ind1 = aux -> Index ();
      } else ind1 = two -> first;

      qmap.insert (ind0, ind1, coe);
    } break;

    default: { 

      // create new auxiliary variable containing product of 3+ factors

      expression **al = new expression * [indices.size ()];
      std::map <int, CouNumber>::iterator one = indices.begin ();

      for (int i=0; one != indices.end (); ++one, i++) 
	if (fabs (one -> second - 1) > COUENNE_EPS) {
	  exprAux *aux = addAuxiliary (new exprPow (new exprClone (Var (one -> first)),
						    new exprConst (one -> second)));
	  al [i] = new exprClone (aux);
	} else al [i] = new exprClone (Var (one -> first));

      // TODO: when we have a convexification for \prod_{i \in I}...
      //      exprAux *aux = addAuxiliary (new exprMul (al, indices.size ()));

      exprMul *mul = new exprMul (al, indices.size ());
      exprAux *aux = mul -> standardize (this);
      lmap.insert (aux -> Index (), coe);

    } break;
    }

  } break; // end of case COU_EXPRMUL

  case COU_EXPRPOW: { // expression = f(x)^g(x) ////////////////////////////////////////////////

    expression **al = term -> ArgList (); 

    if (al [1] -> Type () != CONST) { 

      // non-constant exponent, standardize the whole term and add
      // linear component (single aux)

      expression *aux = term -> standardize (this);
      if (!aux) aux = term;
      lmap.insert (aux -> Index (), initCoe);

    } else { // this is of the form f(x)^k.  If k=2, return square. If
	     // k=1, return var. Otherwise, generate new auxiliary.

      expression *aux = (*al) -> standardize (this);

      if (!aux)
	aux = *al; // it was a simple variable, and was not standardized.

      CouNumber expon = al [1] -> Value ();
      int ind = aux -> Index ();

      if      (fabs (expon - 1.) == 0.) lmap.insert (ind,      initCoe);
      else if (fabs (expon - 2.) == 0.) qmap.insert (ind, ind, initCoe);
      else {
	exprAux *aux2 = addAuxiliary 
	  (new exprPow (new exprClone (aux), new exprConst (expon))); // TODO: FIX!
	lmap.insert (aux2 -> Index (), initCoe);
      }
    }
  } break;

  default: { /// otherwise, simply standardize expression 

    expression *aux = term -> standardize (this);
    if (!aux) 
      aux = term;
    lmap.insert (aux -> Index (), initCoe);
  } break;
  }
}