コード例 #1
0
void Mesh::Load(
	lpxmlnode						pNode)
{
	lpxmlnode pCurrNode = pNode->first_node();

	while(pCurrNode != NULL) {
		std::string Name = pCurrNode->name();
		if(Name == "source") {
			Source src;
			src.Load(pCurrNode);
			m_source.push_back(src);
		} else if(Name == "polylist") {
			Polylist pl;
			pl.Load(pCurrNode);
			m_polylist.push_back(pl);
		} else if(Name == "triangles") {
			Triangles triangles;
			triangles.Load(pCurrNode);
			m_triangles.push_back(triangles);
		} else if(Name == "vertices") {
			Vertices vertices;
			m_vertices.Load(pCurrNode);
		}
		pCurrNode = pCurrNode->next_sibling();
	};
}
コード例 #2
0
// callback function that reports all truly intersecting triangles
void report_inters( const Box* a, const Box* b) {
    std::cout << "Box " << (a->handle() - triangles.begin()) << " and "
              << (b->handle() - triangles.begin()) << " intersect";
    if ( ! a->handle()->is_degenerate() && ! b->handle()->is_degenerate()
         && CGAL::do_intersect( *(a->handle()), *(b->handle()))) {
        std::cout << ", and the triangles intersect also";
    }
    std::cout << '.' << std::endl;
}
コード例 #3
0
ファイル: NBHeightMapper.cpp プロジェクト: fieryzig/sumo
double
NBHeightMapper::getZ(const Position& geo) const {
    if (!ready()) {
        WRITE_WARNING("Cannot supply height since no height data was loaded");
        return 0;
    }
    if (myRaster != 0) {
        double result = -1e6;
        if (myBoundary.around(geo)) {
            const int xSize = int((myBoundary.xmax() - myBoundary.xmin()) / mySizeOfPixel.x() + .5);
            const double normX = (geo.x() - myBoundary.xmin()) / mySizeOfPixel.x();
            const double normY = (geo.y() - myBoundary.ymax()) / mySizeOfPixel.y();
            PositionVector corners;
            corners.push_back(Position(floor(normX) + 0.5, floor(normY) + 0.5, myRaster[(int)normY * xSize + (int)normX]));
            if (normX - floor(normX) > 0.5) {
                corners.push_back(Position(floor(normX) + 1.5, floor(normY) + 0.5, myRaster[(int)normY * xSize + (int)normX + 1]));
            } else {
                corners.push_back(Position(floor(normX) - 0.5, floor(normY) + 0.5, myRaster[(int)normY * xSize + (int)normX - 1]));
            }
            if (normY - floor(normY) > 0.5) {
                corners.push_back(Position(floor(normX) + 0.5, floor(normY) + 1.5, myRaster[((int)normY + 1) * xSize + (int)normX]));
            } else {
                corners.push_back(Position(floor(normX) + 0.5, floor(normY) - 0.5, myRaster[((int)normY - 1) * xSize + (int)normX]));
            }
            result = Triangle(corners).getZ(Position(normX, normY));
        }
        if (result > -1e5 && result < 1e5) {
            return result;
        }
    }
    // coordinates in degrees hence a small search window
    float minB[2];
    float maxB[2];
    minB[0] = (float)geo.x() - 0.00001f;
    minB[1] = (float)geo.y() - 0.00001f;
    maxB[0] = (float)geo.x() + 0.00001f;
    maxB[1] = (float)geo.y() + 0.00001f;
    QueryResult queryResult;
    int hits = myRTree.Search(minB, maxB, queryResult);
    Triangles result = queryResult.triangles;
    assert(hits == (int)result.size());
    UNUSED_PARAMETER(hits); // only used for assertion

    for (Triangles::iterator it = result.begin(); it != result.end(); it++) {
        const Triangle* triangle = *it;
        if (triangle->contains(geo)) {
            return triangle->getZ(geo);
        }
    }
    WRITE_WARNING("Could not get height data for coordinate " + toString(geo));
    return 0;
}
コード例 #4
0
bool detect(vector<Triangle_3> &a, vector<Triangle_3> &b)
{
    std::vector<Box> boxes;
    triangles.clear();
    for ( Iterator i = a.begin(); i != a.end(); ++i)
        triangles.push_back(*i);
    for ( Iterator i = b.begin(); i != b.end(); ++i)
        triangles.push_back(*i);

    for(Iterator i = triangles.begin(); i!= triangles.end(); ++i)
        boxes.push_back( Box( i->bbox(), i));

    // Run the self intersection algorithm with all defaults
    CGAL::box_self_intersection_d( boxes.begin(), boxes.end(), report_inters);
   return true;
}
コード例 #5
0
int main(int argc, char*argv[])
{
  std::ifstream in((argc>1)?argv[1]:"data/triangles.xyz");
  Triangles triangles;
  Triangle_3 t;
  while(in >> t){
    triangles.push_back(t);
  }
  // Create the corresponding vector of bounding boxes
  std::vector<Box> boxes;
  for ( Iterator i = triangles.begin(); i != triangles.end(); ++i)
    boxes.push_back( Box( i->bbox(), i));
  
  // Create the corresponding vector of pointers to bounding boxes
  std::vector<Box *> ptr;
  for ( std::vector<Box>::iterator i = boxes.begin(); i != boxes.end(); ++i)
    ptr.push_back( &*i);
  
  // Run the self intersection algorithm with all defaults on the
  // indirect pointers to bounding boxes. Avoids copying the boxes.
  CGAL::box_self_intersection_d( ptr.begin(), ptr.end(), Report(triangles));
  return 0;
}
コード例 #6
0
ファイル: mesh.cpp プロジェクト: blackerpaper/face
Mesh Mesh::fromOBJ(const std::string &filename, bool centralizeLoadedMesh)
{
    std::ifstream in(filename);
    if (!in.is_open())
        throw FACELIB_EXCEPTION("Can't open file " + filename);

    VectorOfPoints points;
    Triangles triangles;
    std::string line;
    while (std::getline(in, line))
    {
        if (line.empty()) continue;

        if (line[0] == 'v')
        {
            Poco::StringTokenizer tokens(line, " ");
            double x = Poco::NumberParser::parseFloat(tokens[1]);
            double y = Poco::NumberParser::parseFloat(tokens[2]);
            double z = Poco::NumberParser::parseFloat(tokens[3]);

            points.push_back(cv::Point3d(x,y,z));
        }
        else if (line[0] == 'f')
        {
            Poco::StringTokenizer tokens(line, " ");
            int t1 = Poco::NumberParser::parse(tokens[1]) - 1;
            int t2 = Poco::NumberParser::parse(tokens[2]) - 1;
            int t3 = Poco::NumberParser::parse(tokens[3]) - 1;

            triangles.push_back(cv::Vec3i(t1, t2, t3));
        }
    }

    Mesh result = Mesh::fromPointcloud(points, centralizeLoadedMesh, false);
    result.triangles = triangles;
    return result;
}
コード例 #7
0
int main() {
    // Create 10 random triangles
    typedef CGAL::Random_points_in_cube_3<Point_3>           Pts;
    typedef CGAL::Creator_uniform_3< Point_3, Triangle_3>    Creator;
    typedef CGAL::Join_input_iterator_3<Pts,Pts,Pts,Creator> Triangle_gen;
    Pts    points( 1); // in centered cube [-1,1)^3
    Triangle_gen triangle_gen( points, points, points);
    CGAL::cpp11::copy_n( triangle_gen, 10, std::back_inserter(triangles));

    // Create the corresponding vector of bounding boxes
    std::vector<Box> boxes;
    for ( Iterator i = triangles.begin(); i != triangles.end(); ++i)
        boxes.push_back( Box( i->bbox(), i));

    // Create the corresponding vector of pointers to bounding boxes
    std::vector<Box *> ptr;
    for ( std::vector<Box>::iterator i = boxes.begin(); i != boxes.end(); ++i)
        ptr.push_back( &*i);

    // Run the self intersection algorithm with all defaults on the
    // indirect pointers to bounding boxes. Avoids copying the boxes.
    CGAL::box_self_intersection_d( ptr.begin(), ptr.end(), report_inters);
    return 0;
}
コード例 #8
0
      static IGL_INLINE bool intersect_other_helper(
        const Eigen::PlainObjectBase<DerivedVA> & VA,
        const Eigen::PlainObjectBase<DerivedFA> & FA,
        const Eigen::PlainObjectBase<DerivedVB> & VB,
        const Eigen::PlainObjectBase<DerivedFB> & FB,
        const RemeshSelfIntersectionsParam & params,
        Eigen::PlainObjectBase<DerivedIF> & IF,
        Eigen::PlainObjectBase<DerivedVVAB> & VVAB,
        Eigen::PlainObjectBase<DerivedFFAB> & FFAB,
        Eigen::PlainObjectBase<DerivedJAB>  & JAB,
        Eigen::PlainObjectBase<DerivedIMAB> & IMAB)
      {

        using namespace std;
        using namespace Eigen;

        typedef typename DerivedFA::Index Index;
        // 3D Primitives
        typedef CGAL::Point_3<Kernel>    Point_3;
        typedef CGAL::Segment_3<Kernel>  Segment_3; 
        typedef CGAL::Triangle_3<Kernel> Triangle_3; 
        typedef CGAL::Plane_3<Kernel>    Plane_3;
        typedef CGAL::Tetrahedron_3<Kernel> Tetrahedron_3; 
        // 2D Primitives
        typedef CGAL::Point_2<Kernel>    Point_2;
        typedef CGAL::Segment_2<Kernel>  Segment_2; 
        typedef CGAL::Triangle_2<Kernel> Triangle_2; 
        // 2D Constrained Delaunay Triangulation types
        typedef CGAL::Triangulation_vertex_base_2<Kernel>  TVB_2;
        typedef CGAL::Constrained_triangulation_face_base_2<Kernel> CTAB_2;
        typedef CGAL::Triangulation_data_structure_2<TVB_2,CTAB_2> TDS_2;
        typedef CGAL::Exact_intersections_tag Itag;
        // Axis-align boxes for all-pairs self-intersection detection
        typedef std::vector<Triangle_3> Triangles;
        typedef typename Triangles::iterator TrianglesIterator;
        typedef typename Triangles::const_iterator TrianglesConstIterator;
        typedef 
          CGAL::Box_intersection_d::Box_with_handle_d<double,3,TrianglesIterator> 
          Box;
        typedef 
          std::map<Index,std::vector<std::pair<Index,CGAL::Object> > > 
          OffendingMap;
        typedef std::map<std::pair<Index,Index>,std::vector<Index> >  EdgeMap;
        typedef std::pair<Index,Index> EMK;

        Triangles TA,TB;
        // Compute and process self intersections
        mesh_to_cgal_triangle_list(VA,FA,TA);
        mesh_to_cgal_triangle_list(VB,FB,TB);
        // http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Box_intersection_d/Chapter_main.html#Section_63.5 
        // Create the corresponding vector of bounding boxes
        std::vector<Box> A_boxes,B_boxes;
        const auto box_up = [](Triangles & T, std::vector<Box> & boxes) -> void
        {
          boxes.reserve(T.size());
          for ( 
            TrianglesIterator tit = T.begin(); 
            tit != T.end(); 
            ++tit)
          {
            boxes.push_back(Box(tit->bbox(), tit));
          }
        };
        box_up(TA,A_boxes);
        box_up(TB,B_boxes);
        OffendingMap offendingA,offendingB;
        //EdgeMap edge2facesA,edge2facesB;

        std::list<int> lIF;
        const auto cb = [&](const Box &a, const Box &b) -> void
        {
          using namespace std;
          // index in F and T
          int fa = a.handle()-TA.begin();
          int fb = b.handle()-TB.begin();
          const Triangle_3 & A = *a.handle();
          const Triangle_3 & B = *b.handle();
          if(CGAL::do_intersect(A,B))
          {
            // There was an intersection
            lIF.push_back(fa);
            lIF.push_back(fb);
            if(params.first_only)
            {
              throw IGL_FIRST_HIT_EXCEPTION;
            }
            if(!params.detect_only)
            {
              CGAL::Object result = CGAL::intersection(A,B);

              push_result(FA,fa,fb,result,offendingA);
              push_result(FB,fb,fa,result,offendingB);
            }
          }
        };
        try{
          CGAL::box_intersection_d(
            A_boxes.begin(), A_boxes.end(),
            B_boxes.begin(), B_boxes.end(),
            cb);
        }catch(int e)
        {
          // Rethrow if not FIRST_HIT_EXCEPTION
          if(e != IGL_FIRST_HIT_EXCEPTION)
          {
            throw e;
          }
          // Otherwise just fall through
        }

        // Convert lIF to Eigen matrix
        assert(lIF.size()%2 == 0);
        IF.resize(lIF.size()/2,2);
        {
          int i=0;
          for(
            list<int>::const_iterator ifit = lIF.begin();
            ifit!=lIF.end();
            )
          {
            IF(i,0) = (*ifit);
            ifit++; 
            IF(i,1) = (*ifit);
            ifit++;
            i++;
          }
        }
        if(!params.detect_only)
        {
          // Obsolete, now remesh_intersections expects a single mesh
          // remesh_intersections(VA,FA,TA,offendingA,VVA,FFA,JA,IMA);
          // remesh_intersections(VB,FB,TB,offendingB,VVB,FFB,JB,IMB);
          // Combine mesh and offending maps
          DerivedVA VAB(VA.rows()+VB.rows(),3);
          VAB<<VA,VB;
          DerivedFA FAB(FA.rows()+FB.rows(),3);
          FAB<<FA,(FB.array()+VA.rows());
          Triangles TAB;
          TAB.reserve(TA.size()+TB.size());
          TAB.insert(TAB.end(),TA.begin(),TA.end());
          TAB.insert(TAB.end(),TB.begin(),TB.end());
          OffendingMap offending;
          //offending.reserve(offendingA.size() + offendingB.size());
          for (const auto itr : offendingA)
          {
            // Remap offenders in FB to FAB
            auto offenders = itr.second;
            for(auto & offender : offenders)
            {
              offender.first += FA.rows();
            }
            offending[itr.first] = offenders;
          }
          for (const auto itr : offendingB)
          {
            // Store offenders for FB according to place in FAB
            offending[FA.rows() + itr.first] = itr.second;
          }

          remesh_intersections(
            VAB,FAB,TAB,offending,params.stitch_all,VVAB,FFAB,JAB,IMAB);
        }

        return IF.rows() > 0;
      }
コード例 #9
0
ファイル: PX2Picker.cpp プロジェクト: manyxu/Phoenix3D_2.0
//----------------------------------------------------------------------------
void Picker::ExecuteRecursive (Movable* object, bool &hasMeshPicked)
{
	if (object)
	{
		if (object->Culling == Movable::CULL_ALWAYS)
			return;
	}

	Triangles* mesh = DynamicCast<Triangles>(object);
	if (mesh)
	{
		if (mesh->WorldBound.TestIntersection(mOrigin, mDirection, mTMin, mTMax))
		{
			// 将射线从世界坐标系转换到模型坐标系。
			APoint ptmp = mesh->WorldTransform.Inverse()*mOrigin;
			Vector3f modelOrigin(ptmp[0], ptmp[1], ptmp[2]);

			AVector vtmp = mesh->WorldTransform.Inverse()*mDirection;
			Vector3f modelDirection(vtmp[0], vtmp[1], vtmp[2]);

			Line3f line(modelOrigin, modelDirection);

			// 访问方位数据
			VertexBufferAccessor vba(mesh);

			int numTriangles = mesh->GetNumTriangles();
			for (int i = 0; i < numTriangles; ++i)
			{
				int v0, v1, v2;
				if (!mesh->GetTriangle(i, v0, v1, v2))
				{
					continue;
				}

				Vector3f vertex0 = vba.Position<Vector3f>(v0);
				Vector3f vertex1 = vba.Position<Vector3f>(v1);
				Vector3f vertex2 = vba.Position<Vector3f>(v2);
				Triangle3f triangle(vertex0, vertex1, vertex2);

				IntrLine3Triangle3f calc(line, triangle);
				if (calc.Find() && mTMin <= calc.GetLineParameter()
					&&  calc.GetLineParameter() <= mTMax)
				{
					PickRecord record;
					record.Intersected = mesh;
					record.T = calc.GetLineParameter();
					record.Triangle = i;
					record.Bary[0] = calc.GetTriBary0();
					record.Bary[1] = calc.GetTriBary1();
					record.Bary[2] = calc.GetTriBary2();
					Records.push_back(record);

					if (mIsDoMovPickCall)
					{
						hasMeshPicked = true;
						mesh->OnPicked(mPickInfo);
					}
				}
			}
		}
		else
		{
			if (mIsDoMovPickCall)
				mesh->OnNotPicked(mPickInfo);
		}
		return;
	}

	SwitchNode* switchNode = DynamicCast<SwitchNode>(object);
	if (switchNode)
	{
		int activeChild = switchNode->GetActiveChild();
		if (activeChild != SwitchNode::SN_INVALID_CHILD)
		{
			if (switchNode->WorldBound.TestIntersection(mOrigin, mDirection, mTMin, mTMax))
			{
				Movable* child = switchNode->GetChild(activeChild);
				if (child)
				{
					ExecuteRecursive(child, hasMeshPicked);
				}

				if (mIsDoMovPickCall)
				{
					if (hasMeshPicked)
					{
						switchNode->OnPicked(mPickInfo);
					}
					else
					{
						switchNode->OnNotPicked(mPickInfo);
					}
				}
			}
			else
			{
				if (mIsDoMovPickCall)
					switchNode->OnNotPicked(mPickInfo);
			}
		}
		return;
	}

	Node* node = DynamicCast<Node>(object);
	if (node)
	{
		if (node->WorldBound.TestIntersection(mOrigin, mDirection, mTMin, mTMax))
		{
			for (int i = 0; i < node->GetNumChildren(); ++i)
			{
				Movable* child = node->GetChild(i);
				if (child)
				{
					ExecuteRecursive(child, hasMeshPicked);
				}
			}

			if (mIsDoMovPickCall)
			{
				if (hasMeshPicked)
				{
					node->OnPicked(mPickInfo);
				}
				else
				{
					node->OnNotPicked(mPickInfo);
				}
			}
		}
		else
		{
			if (mIsDoMovPickCall)
				node->OnNotPicked(mPickInfo);
		}
	}
}
コード例 #10
0
ファイル: KeyEdge.cpp プロジェクト: EgoIncarnate/vpaint
void KeyEdge::triangulate_(double width, Time time, Triangles & out) const
{
    out.clear();
    if (exists(time))
        geometry()->triangulate(width, out);
}
コード例 #11
0
ファイル: Wm5Picker.cpp プロジェクト: Kiichi77/WildMagic
//----------------------------------------------------------------------------
void Picker::ExecuteRecursive (Spatial* object)
{
    Triangles* mesh = DynamicCast<Triangles>(object);
    if (mesh)
    {
        if (mesh->WorldBound.TestIntersection(mOrigin, mDirection, mTMin,
            mTMax))
        {
            // Convert the linear component to model-space coordinates.
            APoint ptmp = mesh->WorldTransform.Inverse()*mOrigin;
            Vector3f modelOrigin(ptmp[0], ptmp[1], ptmp[2]);

            AVector vtmp = mesh->WorldTransform.Inverse()*mDirection;
            Vector3f modelDirection(vtmp[0], vtmp[1], vtmp[2]);

            Line3f line(modelOrigin, modelDirection);

            // Get the position data.
            VertexBufferAccessor vba(mesh);

            // Compute intersections with the model-space triangles.
            int numTriangles = mesh->GetNumTriangles();
            for (int i = 0; i < numTriangles; ++i)
            {
                int v0, v1, v2;
                if (!mesh->GetTriangle(i, v0, v1, v2))
                {
                    continue;
                }

                Vector3f vertex0 = vba.Position<Vector3f>(v0);
                Vector3f vertex1 = vba.Position<Vector3f>(v1);
                Vector3f vertex2 = vba.Position<Vector3f>(v2);
                Triangle3f triangle(vertex0, vertex1, vertex2);

                IntrLine3Triangle3f calc(line, triangle);
                if (calc.Find() && mTMin <= calc.GetLineParameter()
                &&  calc.GetLineParameter() <= mTMax)
                {
                    PickRecord record;
                    record.Intersected = mesh;
                    record.T = calc.GetLineParameter();
                    record.Triangle = i;
                    record.Bary[0] = calc.GetTriBary0();
                    record.Bary[1] = calc.GetTriBary1();
                    record.Bary[2] = calc.GetTriBary2();
                    Records.push_back(record);
                }
            }
        }
        return;
    }

    SwitchNode* switchNode = DynamicCast<SwitchNode>(object);
    if (switchNode)
    {
        int activeChild = switchNode->GetActiveChild();
        if (activeChild != SwitchNode::SN_INVALID_CHILD)
        {
            if (switchNode->WorldBound.TestIntersection(mOrigin,
                mDirection, mTMin, mTMax))
            {
                Spatial* child = switchNode->GetChild(activeChild);
                if (child)
                {
                    ExecuteRecursive(child);
                }
            }
        }
        return;
    }

    Node* node = DynamicCast<Node>(object);
    if (node)
    {
        if (node->WorldBound.TestIntersection(mOrigin, mDirection, mTMin,
            mTMax))
        {
            for (int i = 0; i < node->GetNumChildren(); ++i)
            {
                Spatial* child = node->GetChild(i);
                if (child)
                {
                    ExecuteRecursive(child);
                }
            }
        }
    }
}
コード例 #12
0
NiSkinPartition::NiSkinPartition(Ref<NiTriBasedGeom> shape) {
   NiSkinInstanceRef skinInst = shape->GetSkinInstance();
   if ( skinInst == NULL ) {
      throw runtime_error( "You must bind a skin before setting generating skin partitions.  No NiSkinInstance found." );
   }
   NiSkinDataRef skinData = skinInst->GetSkinData();
   if ( skinData == NULL ) {
      throw runtime_error( "You must bind a skin before setting generating skin partitions.  No NiSkinData found." );
   }
   NiTriBasedGeomDataRef geomData = DynamicCast<NiTriBasedGeomData>( shape->GetData() );
   if ( geomData == NULL ) {
      throw runtime_error( "Attempted to generate a skin partition on a mesh with no geometry data." );
   }

   int nWeightsPerVertex = 4;
   vector<WeightList> vertexWeights;
   BoneList boneMap;
   vector<unsigned short> vertexMap;
   Strips strips;
   vector<BoneList> boneIndexList;
   Triangles triangles;

   int totalBones = skinInst->GetBoneCount();
   boneMap.resize(totalBones);

   int nv = geomData->GetVertexCount();
   vertexMap.resize(nv);
   vertexWeights.resize(nv);
   boneIndexList.resize(nv);

   for (int i=0; i<totalBones; ++i) {
      boneMap[i] = i;

      vector<SkinWeight> skinWeights = skinData->GetBoneWeights(i);
      for (vector<SkinWeight>::const_iterator skinWeight = skinWeights.begin(); skinWeight != skinWeights.end(); ++skinWeight) {
         WeightList& vertexWeight = vertexWeights[skinWeight->index];
         BoneList& boneIndex = boneIndexList[skinWeight->index];

         vertexWeight.push_back(skinWeight->weight);
         boneIndex.push_back(i);

         // Adjust upper limit on number of weights per vertex if necessary.
         int nWeights = vertexWeight.size();
         if (nWeights > nWeightsPerVertex)
            nWeightsPerVertex = nWeights;
      }
   }
   if (nWeightsPerVertex == 0) {
      throw runtime_error( "Attempted to generate a skin partition on a mesh with no weights specified." );
   }
   for (int i=0; i<nv; ++i) {
      vertexMap[i] = i;

      WeightList& vertexWeight = vertexWeights[i];
      BoneList& boneIndex = boneIndexList[i];
      vertexWeight.reserve(nWeightsPerVertex);
      boneIndex.reserve(nWeightsPerVertex);
      for (int j = nWeightsPerVertex - vertexWeight.size(); j>0; --j) {
         vertexWeight.push_back(0.0f);
         boneIndex.push_back(0);
      }
   }

   SetNumPartitions(1);
   SetWeightsPerVertex(0, nWeightsPerVertex);
   SetBoneMap(0, boneMap);
   SetNumVertices(0, (unsigned short)(vertexMap.size()) );
   SetVertexMap(0, vertexMap);
   EnableVertexWeights(0, true);
   EnableVertexBoneIndices(0, true);
   for (int i=0; i<nv; ++i) {
      SetVertexWeights(0, i, vertexWeights[i]);
      SetVertexBoneIndices(0, i, boneIndexList[i]);
   }

   // Special case for pre-stripped data
   if (NiTriStripsDataRef stripData = DynamicCast<NiTriStripsData>(geomData)) {
      unsigned short nstrips = stripData->GetStripCount();
      SetStripCount(0, nstrips);
      for (int i=0; i<int(nstrips); ++i) {
         SetStrip(0, i, stripData->GetStrip(i));
      }
   } else {

      Triangles triangles = geomData->GetTriangles();
      SetTriangles(0, triangles);

      unsigned short *data = new unsigned short[triangles.size() * 3 * 2];
      for (size_t i=0; i< triangles.size(); i++) {
         data[i * 3 + 0] = triangles[i][0];
         data[i * 3 + 1] = triangles[i][1];
         data[i * 3 + 2] = triangles[i][2];
      }
      PrimitiveGroup * groups = 0;
      unsigned short numGroups = 0;

      // GF 3+
      SetCacheSize(CACHESIZE_GEFORCE3);
      // don't generate hundreds of strips
      SetStitchStrips(true);
      GenerateStrips(data, triangles.size()*3, &groups, &numGroups);

      delete [] data;

      if (groups) {
         SetStripCount(0, numGroups);
         for (int g=0; g<numGroups; g++) {
            if (groups[g].type == PT_STRIP) {
               vector<unsigned short> strip(groups[g].numIndices);
               for ( unsigned int s = 0; s<groups[g].numIndices; s++ )
                  strip[s] = groups[g].indices[s];
               SetStrip(0, g, strip);
            }
         }
         delete [] groups;
      }
   }
  
}
コード例 #13
0
ファイル: EdgeCell.cpp プロジェクト: gitter-badger/vpaint
void EdgeCell::triangulate(double /*width*/, Time /*time*/, Triangles & out)
{
    out.clear();
}
コード例 #14
0
int main()
{
   Triangles application; // create Triangles object 
   application.drawTriangles(); // call its drawTriangles function
} // end main
コード例 #15
0
NiSkinPartition::NiSkinPartition(Ref<NiTriBasedGeom> shape, int maxBonesPerPartition, int maxBonesPerVertex ) {
   NiSkinInstanceRef skinInst = shape->GetSkinInstance();
   if ( skinInst == NULL ) {
      throw runtime_error( "You must bind a skin before setting generating skin partitions.  No NiSkinInstance found." );
   }
   NiSkinDataRef skinData = skinInst->GetSkinData();
   if ( skinData == NULL ) {
      throw runtime_error( "You must bind a skin before setting generating skin partitions.  No NiSkinData found." );
   }
   NiTriBasedGeomDataRef geomData = DynamicCast<NiTriBasedGeomData>(shape->GetData() );
   if ( geomData == NULL ) {
      throw runtime_error( "Attempted to generate a skin partition on a mesh with no geometry data." );
   }

      // read in the weights from NiSkinData
   vector<Vector3> verts = geomData->GetVertices();
   vector< BoneWeightList > weights;
   if (verts.empty()){
      throw runtime_error( "Attempted to generate a skin partition on a mesh with no vertices." );
   }

   Triangles triangles = geomData->GetTriangles();
   if (triangles.empty()) {
      throw runtime_error( "Attempted to generate a skin partition on a mesh with no triangles." );
   }

   weights.resize( verts.size() );
   int numBones = skinData->GetBoneCount();
   for ( int bone = 0; bone < numBones; bone++ )
   {
      vector<SkinWeight> vertexWeights = skinData->GetBoneWeights(bone);
      for (int r = 0; r < int(vertexWeights.size()); ++r ){
         int vertex = vertexWeights[r].index;
         float weight = vertexWeights[r].weight;
         if ( vertex >= int(weights.size()) )
            throw runtime_error( "bad NiSkinData - vertex count does not match" );
         weights[vertex].insert( weights[vertex].end(), BoneWeight(bone, weight) );
      }
   }

   // count min and max bones per vertex
   int minBones, maxBones;
   minBones = maxBones = weights[0].size();
   for(vector< BoneWeightList >::iterator itr = weights.begin(); itr != weights.end(); ++itr ){
      int n = (*itr).size();
      minBones = min(n, minBones);
      maxBones = max(n, maxBones);
   }

   if ( minBones <= 0 )
      throw runtime_error( "bad NiSkinData - some vertices have no weights at all" );

   // reduce vertex influences if necessary
   if ( maxBones > maxBonesPerVertex )
   {
      int c = 0;
      for ( vector< BoneWeightList >::iterator it = weights.begin(); it != weights.end(); ++it )
      {
         BoneWeightList & lst = *it;
         if ( int(lst.size()) > maxBonesPerVertex )
            c++;

         while ( int(lst.size()) > maxBonesPerVertex ) {
            int j = 0;
            float weight = lst.front().second;
            for ( int i = 0; i < int(lst.size()); i++ )
            {
               if ( lst[i].second < weight )
                  j = i;
            }
            BoneWeightList::iterator jit = lst.begin() + j;
            lst.erase( jit );
         }

         float totalWeight = 0;
         for (BoneWeightList::iterator bw = lst.begin(); bw != lst.end(); ++bw) {
            totalWeight += (*bw).second;
         }
         for (BoneWeightList::iterator bw = lst.begin(); bw != lst.end(); ++bw) {
            (*bw).second /= totalWeight;
         }
      }
      //qWarning() << "reduced" << c << "vertices to" << maxBonesPerVertex << "bone influences (maximum number of bones per vertex was" << maxBones << ")";
   }

   maxBones = maxBonesPerVertex;

   // reduces bone weights so that the triangles fit into the partitions

   typedef multimap<int,int> matchmap;
   typedef pair<matchmap::iterator, matchmap::iterator> matchrange;
   matchmap match;
   bool doMatch = true;

   BoneList tribones;
   int cnt = 0;
   for (Triangles::iterator itr = triangles.begin(); itr != triangles.end(); ++itr) {
      Triangle& tri = (*itr);
      do
      {
         tribones.clear();
         for ( int c = 0; c < 3; c++ ) {
            BoneWeightList& bwl = weights[tri[c]];
            for (BoneWeightList::iterator bw = bwl.begin(); bw != bwl.end(); ++bw) {
               if ( tribones.end() == find(tribones.begin(), tribones.end(), (*bw).first ) )
                  tribones.insert(tribones.end(), (*bw).first );
            }
         }

         if ( int(tribones.size()) > maxBonesPerPartition )
         {
            // sum up the weights for each bone
            // bones with weight == 1 can't be removed

            map<int, float> sum;
            vector<int> nono;

            for ( int t = 0; t < 3; t++ ) {
               BoneWeightList& bwl = weights[tri[t]];
               if ( bwl.size() == 1 )
                  nono.insert(nono.end(), bwl.front().first );

               for (BoneWeightList::iterator bw = bwl.begin(); bw != bwl.end(); ++bw) {
                  sum[ (*bw).first ] += (*bw).second;
               }                 
            }

            // select the bone to remove

            float minWeight = 5.0;
            int minBone = -1;

            for (map<int, float>::iterator sitr = sum.begin(); sitr != sum.end(); ++sitr) {
               int b = (*sitr).first;
               if ( (find(nono.begin(), nono.end(), b) == nono.end()) && sum[b] < minWeight) {
                  minWeight = sum[b];
                  minBone = b;
               }
            }

            if ( minBone < 0 )	// this shouldn't never happen
               throw runtime_error( "internal error 0x01" );

            // do a vertex match detect
            if ( doMatch ) {
               for ( size_t a = 0; a < verts.size(); a++ ) {
                  match.insert(matchmap::value_type(a, a));
                  for ( size_t b = a + 1; b < verts.size(); b++ ) {
                     if ( verts[a] == verts[b] && weights[a] == weights[b] ) {
                        match.insert(matchmap::value_type(a, b));
                        match.insert(matchmap::value_type(b, a));
                     }
                  }
               }
            }

            // now remove that bone from all vertices of this triangle and from all matching vertices too
            for ( int t = 0; t < 3; t++ ) {
               bool rem = false;

               matchrange range = match.equal_range(tri[t]);
               for (matchmap::iterator itr = range.first; itr != range.second; ++itr) {
                  int v = (*itr).second;

                  BoneWeightList & bws = weights[ v ];
                  BoneWeightList::iterator it = bws.begin();
                  while ( it != bws.end() ) {
                     BoneWeight & bw = *it;
                     if ( bw.first == minBone ) {
                        it = bws.erase(it);
                        rem = true;
                     } else {
                        ++it;
                     }
                  }

                  float totalWeight = 0;

                  for (BoneWeightList::iterator bw = bws.begin(); bw != bws.end(); ++bw) {
                     totalWeight += (*bw).second;
                  }

                  if ( totalWeight == 0 )
                     throw runtime_error( "internal error 0x02" );

                  // normalize
                  for (BoneWeightList::iterator bw = bws.begin(); bw != bws.end(); ++bw) {
                     (*bw).second /= totalWeight;
                  }
               }
               if ( rem )
                  cnt++;
            }
         }
      } while ( int(tribones.size()) > maxBonesPerPartition );
   }
   //if ( cnt > 0 )
   //   qWarning() << "removed" << cnt << "bone influences";

   PartitionList& parts = skinPartitionBlocks;
   // split the triangles into partitions
   while ( ! triangles.empty() ) {

      SkinPartition part;
      Triangles::iterator it = triangles.begin();
      while ( it != triangles.end() ) {
         Triangle & tri = *it;

         BoneList tribones;
         for ( int c = 0; c < 3; c++ ) {
            BoneWeightList& bws = weights[tri[c]];
            for (BoneWeightList::iterator bw = bws.begin(); bw != bws.end(); ++bw) {
               if ( tribones.end() == find(tribones.begin(), tribones.end(), (*bw).first ) )
                  tribones.push_back( (*bw).first );
            }
         }

         if ( part.bones.empty() || containsBones( part.bones, tribones ) ) {
            mergeBones( part.bones, tribones );
            part.triangles.push_back( tri );
            it = triangles.erase(it);
         } else {
            ++it;
         }
      }

      parts.push_back( part );
   }

   //qWarning() << parts.size() << "small partitions";

   // merge partitions

   bool merged;
   do
   {
      merged = false;
      // Working backwards through this list minimizes numbers of swaps
      //for ( int p2 = int(parts.size()-1); p2 >= 0  && ! merged; --p2 )
      //{
      //   Partition& part2 = parts[p2];
      //   for ( int p1 = int(p2-1); p1 >= 0 && ! merged; --p1 )
      //   {
      //      Partition& part1 = parts[p1];
      for ( int p1 = 0; p1 < int(parts.size()) && ! merged; p1++ )
      {
         Partition& part1 = parts[p1];
         for ( int p2 = p1+1; p2 < int(parts.size()) && ! merged; p2++ )
         {
            Partition& part2 = parts[p2];
            BoneList mergedBones = part1.bones;
            mergeBones( mergedBones, part2.bones );
            if ( int(mergedBones.size()) <= maxBonesPerPartition )
            {
               PartitionList::iterator p2i = parts.begin() + p2;
               part1.bones = mergedBones;
               part1.triangles.insert(part1.triangles.end(), (*p2i).triangles.begin(), (*p2i).triangles.end());
               parts.erase(p2i);
               merged = true;
            }
         }
      }
   }
   while ( merged );

   //qWarning() << parts.size() << "partitions";

   // start writing NiSkinPartition

   for ( int p = 0; p < int(parts.size()); p++ )
   {
      Partition& part = parts[p];
      BoneList& bones = part.bones;
      sort( bones.begin(), bones.end() );

      Triangles& triangles = part.triangles;

      vector<unsigned short>& vertices = part.vertexMap;
      for( Triangles::iterator tri = triangles.begin(); tri !=  triangles.end(); ++tri) {
         for ( int t = 0; t < 3; t++ ) {
            if ( vertices.end() == find(vertices.begin(), vertices.end(), (*tri)[t] ) )
               vertices.push_back( (*tri)[t] );
         }
      }
      sort( vertices.begin(), vertices.end() );
      part.numVertices = vertices.size();
      part.hasVertexMap = true;

      // map the vertices

      for ( int tri = 0; tri < int(triangles.size()); tri++ ) {
         for ( int t = 0; t < 3; t++ ) {
            triangles[tri][t] = indexOf(vertices.begin(), vertices.end(), triangles[tri][t]);
         }
      }

      SetWeightsPerVertex(p, maxBones);
      EnableVertexWeights(p, true);
      EnableVertexBoneIndices(p, true);

      // strippify the triangles
      NiTriStripsDataRef data = new NiTriStripsData(triangles, true);
      int nstrips = data->GetStripCount();
      SetStripCount( p, nstrips );
      for ( int i=0; i<nstrips; ++i ) {
         SetStrip(p, i, data->GetStrip(i));
      }

      //// Special case for pre-stripped data
      //unsigned short *data = new unsigned short[triangles.size() * 3 * 2];
      //for (size_t i=0; i< triangles.size(); i++) {
      //   data[i * 3 + 0] = triangles[i][0];
      //   data[i * 3 + 1] = triangles[i][1];
      //   data[i * 3 + 2] = triangles[i][2];
      //}
      //PrimitiveGroup * groups = 0;
      //unsigned short numGroups = 0;

      //// GF 3+
      //SetCacheSize(CACHESIZE_GEFORCE3);
      //// don't generate hundreds of strips
      //SetStitchStrips(true);
      //GenerateStrips(data, triangles.size()*3, &groups, &numGroups);
      //delete [] data;
      //if (groups) {
      //   SetStripCount(p, numGroups);
      //   for (int g=0; g<numGroups; g++) {
      //      if (groups[g].type == PT_STRIP) {
      //         vector<Niflib::unsigned short> strip(groups[g].numIndices);
      //         for (size_t s=0; s<groups[g].numIndices; s++)
      //            strip[s] = groups[g].indices[s];
      //         SetStrip(p, g, strip);
      //      }
      //   }
      //   delete [] groups;
      //}

      // fill in vertex weights and bones
      for (size_t v = 0; v < vertices.size(); ++v) {
         BoneWeightList& bwl = weights[vertices[v]];
         for ( int b = 0; b < maxBones; b++ ) {
            part.boneIndices[v][b] = (int(bwl.size()) > b) ? indexOf(bones.begin(), bones.end(), bwl[b].first) : 0 ;
            part.vertexWeights[v][b] = (int(bwl.size()) > b ? bwl[b].second : 0.0f);
         }
      }
   }
}
コード例 #16
0
ファイル: PX2Picker.cpp プロジェクト: PhoenixSteam/Phoenix3D
//----------------------------------------------------------------------------
void Picker::ExecuteRecursive (Movable* object, bool &hasMeshPicked)
{
	if (object)
	{
		if (!object->IsDoPick())
			return;

		if (!object->IsShow() && !object->IsPickIngoreCullingMode())
			return;
	}

	Triangles* mesh = DynamicCast<Triangles>(object);
	if (mesh)
	{
		if (!mesh->GetVertexBuffer())
			return;

		if (mesh->WorldBound.TestIntersection(mOrigin, mDirection, mTMin, mTMax))
		{
			if (mesh->IsUseBoundPick())
			{
				AVector dir = mesh->GetWorldTransform().GetTranslate() - mOrigin;
				float length = dir.Length();

				PickRecord record;
				record.Intersected = mesh;
				record.T = length;
				Records.push_back(record);
			}
			else
			{
				// 将射线从世界坐标系转换到模型坐标系。
				APoint ptmp;
				if (!mesh->IsSkinCtrlSetWroldTrans)
					ptmp = mesh->WorldTransform.Inverse()*mOrigin;
				else
					ptmp = mesh->BoundWorldTransform.Inverse()*mOrigin;
				Vector3f modelOrigin(ptmp[0], ptmp[1], ptmp[2]);

				AVector vtmp;
				if (!mesh->IsSkinCtrlSetWroldTrans)
					vtmp = mesh->WorldTransform.Inverse()*mDirection;
				else
					vtmp = mesh->BoundWorldTransform.Inverse()*mDirection;
				Vector3f modelDirection(vtmp[0], vtmp[1], vtmp[2]);

				Line3f line(modelOrigin, modelDirection);

				// 访问方位数据
				VertexBufferAccessor vba(mesh);

				int numTriangles = mesh->GetNumTriangles();
				for (int i = 0; i < numTriangles; ++i)
				{
					int v0, v1, v2;
					if (!mesh->GetTriangle(i, v0, v1, v2))
					{
						continue;
					}

					Vector3f vertex0 = vba.Position<Vector3f>(v0);
					Vector3f vertex1 = vba.Position<Vector3f>(v1);
					Vector3f vertex2 = vba.Position<Vector3f>(v2);
					Triangle3f triangle(vertex0, vertex1, vertex2);

					IntrLine3Triangle3f calc(line, triangle);
					if (calc.Find())
					{
						float lineParameter = calc.GetLineParameter();
						if (mTMin<=lineParameter && lineParameter<=mTMax)
						{
							PickRecord record;
							record.Intersected = mesh;
							record.T = calc.GetLineParameter();
							record.Triangle = i;
							record.Bary[0] = calc.GetTriBary0();
							record.Bary[1] = calc.GetTriBary1();
							record.Bary[2] = calc.GetTriBary2();

							Vector3f edg1 = vertex1 - vertex0;
							Vector3f edg2 = vertex2 - vertex0;
							Vector3f normal = edg1.UnitCross(edg2);
							float dotVal = line.Direction.Dot(normal);
							if (dotVal > Mathf::ZERO_TOLERANCE)
							{
								normal *= -1.0f;
							}
							record.LocalNormal = normal;
							record.WorldPos = mOrigin + mDirection * record.T;

							Records.push_back(record);

							if (mIsDoMovPickCall)
							{
								hasMeshPicked = true;
								mesh->OnPicked(mPickInfo);
							}
						}
					}
				}
			}
		}
		else
		{
			if (mIsDoMovPickCall)
				mesh->OnNotPicked(mPickInfo);
		}
		return;
	}

	SwitchNode* switchNode = DynamicCast<SwitchNode>(object);
	if (switchNode)
	{
		bool newHasChildPicked = false;

		int activeChild = switchNode->GetActiveChild();
		if (activeChild != SwitchNode::SN_INVALID_CHILD)
		{
			if (switchNode->WorldBound.TestIntersection(mOrigin, mDirection, mTMin, mTMax))
			{
				Movable* child = switchNode->GetChild(activeChild);
				if (child)
				{
					ExecuteRecursive(child, newHasChildPicked);
				}

				if (newHasChildPicked)
				{
					hasMeshPicked = true;
				}

				if (mIsDoMovPickCall)
				{
					if (hasMeshPicked)
					{
						switchNode->OnPicked(mPickInfo);
					}
					else
					{
						switchNode->OnNotPicked(mPickInfo);
					}
				}
			}
			else
			{
				if (mIsDoMovPickCall)
					switchNode->OnNotPicked(mPickInfo);
			}
		}
		return;
	}

	Node* node = DynamicCast<Node>(object);
	if (node)
	{
		bool newHasChildPicked = false;
		if (node->WorldBound.TestIntersection(mOrigin, mDirection, mTMin, mTMax))
		{
			Movable *movPriority = 0;
			if (node->IsDoPickPriority())
			{
				for (int i=0; i<node->GetNumChildren(); i++)
				{
					Movable *mov = node->GetChild(i);
					if (mov && mov->IsNotPickedParentChildrenNotPicked())
						movPriority = mov;
				}
			}

			// 做优先检测
			bool doLastPick = false;
			if (movPriority)
			{
				ExecuteRecursive (movPriority, doLastPick);		
			}
			else
			{
				doLastPick = true;
			}

			if (doLastPick)
			{
				for (int i = 0; i < node->GetNumChildren(); ++i)
				{
					Movable* child = node->GetChild(i);
					if (child && child!=movPriority)
					{
						ExecuteRecursive(child, newHasChildPicked);
					}
				}

				if (newHasChildPicked)
				{
					hasMeshPicked = true;
				}

				if (mIsDoMovPickCall)
				{
					if (newHasChildPicked)
					{
						node->OnPicked(mPickInfo);
					}
					else
					{
						node->OnNotPicked(mPickInfo);
					}
				}
			}
		}
		else
		{
			if (mIsDoMovPickCall)
				node->OnNotPicked(mPickInfo);
		}
	}
}
コード例 #17
0
ファイル: EdgeCell.cpp プロジェクト: gitter-badger/vpaint
void EdgeCell::triangulate(Time /*time*/, Triangles & out)
{
    out.clear();
}