Exemple #1
0
void MeshBVH::InitSingleMesh(const BaseMesh &M, UINT triangleCountCutoff)
{
	FreeMemory();

    const MeshVertex *vertices = M.Vertices();
    const UINT vertexCount = M.VertexCount();

    const DWORD *indices = M.Indices();
    const UINT triCount = M.FaceCount();

    if(MeshBVHDebugging) Console::WriteLine("Making BVH, triCount=" + String(triCount));

    _triInfo.Allocate(triCount);
    Vector<MeshBVHTriangleInfo*> dataPointers(triCount);
    for(UINT triIndex = 0; triIndex < triCount; triIndex++)
    {
        MeshBVHTriangleInfo &curTriInfo = _triInfo[triIndex];
        dataPointers[triIndex] = &curTriInfo;

        curTriInfo.v[0] = vertices[ indices[ triIndex * 3 + 0 ] ].Pos;
        curTriInfo.v[1] = vertices[ indices[ triIndex * 3 + 1 ] ].Pos;
        curTriInfo.v[2] = vertices[ indices[ triIndex * 3 + 2 ] ].Pos;
    }

    _storage.Allocate(triCount);

    MeshBVHNodeConstructorInfo info;
    info.storage = _storage.CArray();
    info.storageIndex = 0;
    info.triangleCountCutoff = triangleCountCutoff;

    _root = new MeshBVHNode(dataPointers.CArray(), dataPointers.Length(), info, 0);
}
Exemple #2
0
void BaseMesh::CopyMesh(BaseMesh &Copy) const
{
    Copy._GD = _GD;
    Copy.Allocate(VertexCount(), FaceCount());
    memcpy(Copy.Vertices(), Vertices(), sizeof(MeshVertex) * VertexCount());
    memcpy(Copy.Indices(), Indices(), sizeof(DWORD) * IndexCount());
}
Exemple #3
0
BaseMesh* BoolOp::Diff (BaseMesh* mesh1,  BaseMesh* mesh2)
{
	BaseMesh* result = NULL;
	if (mesh1 != NULL)
	{
		if (mesh2 == NULL || !(mesh1->AABB().Intersects(mesh2->AABB())))	
			result = mesh1->Clone();
		else{
            result = ComputeBoolean(mesh1, mesh2,eDiff);
			if (result && result->PrimitiveCount() ==0 )
			{
				delete result;
				result = NULL;
			}
		}
	}
	if (result != NULL)
	{
		result->GenID();
	//	result->GenSurface();
	//	result->GenAABB(true);
	}
	return result ; 

}
Exemple #4
0
void D3D9Mesh::CopyMesh(BaseMesh &Copy) const
{
    Copy.SetGD(GetGD());

    int VC = VertexCount();
    int IC = IndexCount();

    if(VC > 0 && IC > 0)
    {
        if(_Vertices == NULL)
        {
            _Mesh->LockVertexBuffer(0,(void**) &_Vertices);
        }
        if(_Indices == NULL)
        {
            _Mesh->LockIndexBuffer(0,(void**) &_Indices);
        }

        Copy.Allocate(VC, IC / 3);                                //allocate space in Copy
        memcpy(Copy.Vertices(), _Vertices, VC * sizeof(MeshVertex));    //insert our vertices into Copy
        memcpy(Copy.Indices(), _Indices, IC * sizeof(DWORD));            //insert our indices into Copy

        Unlock();
    }
}
Exemple #5
0
void Subdivide(BaseMesh &M1, BaseMesh &M2)
{
    M2.SetGD(M1.GetGD());
    ComplexMesh EM;
    EM.Load(M1);
    EM.Subdivision(M2);
}
Exemple #6
0
void ComplexMesh::Subdivision(BaseMesh &Mesh)
{
    UINT VertexCount = _Vertices.Length();
    UINT EdgeCount = _FullEdges.Length();
    UINT TriangleCount = _Triangles.Length();
    //IntPair P;

    Mesh.Allocate(VertexCount + EdgeCount, TriangleCount * 4);

    MeshVertex *V = Mesh.Vertices();
    DWORD *I = Mesh.Indices();

    Vector<Vec3f> NewVertexPositions(_Vertices.Length());
    for(UINT VertexIndex = 0; VertexIndex < VertexCount; VertexIndex++)
    {
        V[VertexIndex].Pos = _Vertices[VertexIndex].ComputeLoopSubdivisionPos();
    }

    for(UINT EdgeIndex = 0; EdgeIndex < EdgeCount; EdgeIndex++)
    {
        V[VertexCount + EdgeIndex].Pos = _FullEdges[EdgeIndex]->ComputeLoopSubdivisionPos();
    }

    for(UINT i = 0; i < TriangleCount; i++)
    {
        UINT SourceI[6];
        Triangle &CurTriangle = _Triangles[i];

        for(UINT i2 = 0; i2 < 3; i2++)
        {
            SourceI[i2 + 0] = CurTriangle.GetVertex(i2).Index();
            SourceI[i2 + 3] = VertexCount + CurTriangle.GetOtherEdge(_Triangles[i].GetVertex(i2)).Index();
        }

        I[i * 12 + 0] = SourceI[0];
        I[i * 12 + 1] = SourceI[5];
        I[i * 12 + 2] = SourceI[4];

        I[i * 12 + 3] = SourceI[5];
        I[i * 12 + 4] = SourceI[1];
        I[i * 12 + 5] = SourceI[3];

        I[i * 12 + 6] = SourceI[4];
        I[i * 12 + 7] = SourceI[3];
        I[i * 12 + 8] = SourceI[2];

        I[i * 12 + 9] = SourceI[4];
        I[i * 12 + 10] = SourceI[5];
        I[i * 12 + 11] = SourceI[3];
    }
}
Exemple #7
0
BaseMesh* BSPBoolOp::ComputeBoolean(PlaneMesh* mesh1, PlaneMesh* mesh2, BOOL_OP op)
{
    BSPTree::SET_OP BSPOp;
    switch (op)
    {
        case eUnion:
            BSPOp = BSPTree::OP_UNION;
            break;
        case eIntersect:
            BSPOp = BSPTree::OP_INTERSECT;
            break;
        case eDiff:
            BSPOp = BSPTree::OP_DIFFERENCE;
            break;
        default :
            break;
    }
	Box3 bbox(mesh1->AABB());
	bbox.IncludeBox(mesh2->AABB());

    BSPTree* pTree1 =  mesh1->ToBSPTree();
    pTree1->FormSubHyperPlane(bbox);
	pTree1->OutputDebugInfo("D:\\x1.txt");

    BSPTree* pTree2 = mesh2->ToBSPTree();
    if (BSPOp == BSPTree::OP_DIFFERENCE)
    {
        pTree2->Negate();
        BSPOp = BSPTree::OP_INTERSECT;
    }
    pTree2->FormSubHyperPlane(bbox);
	pTree2->OutputDebugInfo("D:\\y1.txt");

    BSPTree* pResultTree = pTree1->Merge(pTree2, BSPOp);
	pResultTree->OutputDebugInfo("D:\\z1.txt");
    delete pTree2;
    delete pTree1;

   PlaneMesh* pPlaneMesh1 = new PlaneMesh(pResultTree);
   //PlaneMesh* pPlaneMesh1 = new PlaneMesh(pTree1);
    //delete pTree1;
    BaseMesh* pMesh = pPlaneMesh1->ToBaseMesh();
    if (pMesh && pMesh->PrimitiveCount() ==0 )
	{
        delete pMesh;
        pMesh = NULL;
    }
    delete pPlaneMesh1;

    return pMesh;
}
Exemple #8
0
D3D9Mesh::D3D9Mesh(const BaseMesh &O)
{
    _Mesh = NULL;
    _Vertices = NULL;
    _Indices = NULL;
    O.CopyMesh(*this);
}
Exemple #9
0
Mesh::Mesh(BaseMesh &O)
{
    _Vertices = 0;
    _Indices = 0;
    _VertexCount = 0;
    _IndexCount = 0;
    O.CopyMesh(*this);
}
Exemple #10
0
BaseMesh* BoolOp::Union ( BaseMesh* mesh1,  BaseMesh* mesh2)
{
    tbb::tick_count t0 = tbb::tick_count::now();
  
	if (mesh1 == NULL && mesh2 == NULL)
		return NULL;
	if ( mesh1 == NULL)
		return mesh2->Clone();
	if (mesh2 == NULL)
		return mesh1->Clone();
	BaseMesh* result = NULL;
	if (mesh1->AABB().Intersects(mesh2->AABB()))
	{
        result = ComputeBoolean(mesh1, mesh2, eUnion);
		if (result && result->PrimitiveCount() ==0 )
		{
			delete result;
			result = NULL;
		}
	}
	else {
		result = mesh1->Clone();
		for (int i = 0; i < mesh2->PrimitiveCount(); i++) 
		{
			const TriInfo&  info= mesh2->TriangleInfo(i);
			result->Add(mesh2->Vertex(info.VertexId[0]) , mesh2->Vertex(info.VertexId[1]), mesh2->Vertex(info.VertexId[2]));
			        
		}
	}

    if (result != NULL)
    {
        result->GenID();
    //    result->GenSurface();
     //   result->GenAABB(true);
    }
   /*  tbb::tick_count t1 = tbb::tick_count::now();
     WCHAR buffer [100];
    ::swprintf_s(buffer, 100, L"Time %f mec", (t1-t0).seconds());
    ::MessageBox(NULL, buffer, L"Warning", MB_OK); */
	return result ; 
	 
}
void RayIntersectorKDTree::Init(const BaseMesh &M)
{
    Console::WriteString("Building RayIntersectorKDTree...");
    FreeMemory();

    _VertexCount = M.VertexCount();
    _TriangleCount = M.FaceCount();

    Console::WriteString(String(_TriangleCount) + String(" base triangles, "));
    

    _Vertices = new Vec3f[_VertexCount];
    _Indices = new UINT[_TriangleCount * 3];
    
    const MeshVertex *MeshVertices = M.Vertices();
    const DWORD *MeshIndices = M.Indices();
    
    for(UINT VertexIndex = 0; VertexIndex < _VertexCount; VertexIndex++)
    {
        _Vertices[VertexIndex] = MeshVertices[VertexIndex].Pos;
    }

    for(UINT IndexIndex = 0; IndexIndex < _TriangleCount * 3; IndexIndex++)
    {
        _Indices[IndexIndex] = MeshIndices[IndexIndex];
    }

    Vector<UINT> TriangleIndices(_TriangleCount);
    for(UINT TriangleIndex = 0; TriangleIndex < _TriangleCount; TriangleIndex++)
    {
        TriangleIndices[TriangleIndex] = TriangleIndex;
    }
    
    Vector<UINT> LeafTrianglesVector;
    _Root = new RayIntersectorKDTreeNode(TriangleIndices, *this, 0, LeafTrianglesVector);
    _LeafTriangleCount = LeafTrianglesVector.Length();
    _LeafTriangles = new UINT[_LeafTriangleCount];
    memcpy(_LeafTriangles, LeafTrianglesVector.CArray(), sizeof(UINT) * _LeafTriangleCount);
    Console::WriteLine(String(_LeafTriangleCount) + String(" leaf triangles."));
}
Exemple #12
0
void BaseMesh::AppendVertices(const BaseMesh &O)
{
    int vc = VertexCount(), ic = IndexCount();
    MeshVertex *V = Vertices(), *OldV = new MeshVertex[vc];
    DWORD *I = Indices(), *OldI = new DWORD[ic];

    memcpy(OldV, V, vc * sizeof(MeshVertex));
    memcpy(OldI, I, ic * sizeof(DWORD));            //store all the old vertices/indices

    Allocate(vc + O.VertexCount(), ic/3 + O.FaceCount());    //allocate space for the current vertices/indices and o's vertices/indices

    V = Vertices();
    I = Indices();

    memcpy(V, OldV, vc * sizeof(MeshVertex));
    memcpy(I, OldI, ic * sizeof(DWORD));        //copy the old vertices/indices back into the mesh,

    memcpy(&(V[vc]), O.Vertices(), O.VertexCount() * sizeof(MeshVertex));    //copy the new vertices after the current ones,

    UINT oic = O.IndexCount();
    const DWORD *oI = O.Indices();
    for(UINT i = 0; i < oic; i++)
    {
        I[ic+i] = oI[i] + vc;    //copy o's indices as well, except increasing the index by vc (since o's vertices start at vc, not 0)
    }

    delete[] OldV;
    delete[] OldI;
}
Exemple #13
0
 BaseMesh* FixedPlaneMesh::ToBaseMesh() 
 {
     std::vector<Point3D> pts; 
     ListOfvertices results;
     BaseMesh* pMesh = new BaseMesh;
     pMesh->SetTransformedAABB(AABB());
	//auto center = AABB().Center();
	//auto scale = AABB().Diagonal();

     for (int i = 0 ; i < mPolygons.size(); i++)
     {
        for (int j = 0 ; j < mPolygons[i].bplanes.size(); j++)
        {
            int prevPtIdx = j == 0? mPolygons[i].bplanes.size() -1 : j -1;
			Point3D pt = InexactComputePoint(mPolygons[i].splane, mPolygons[i].bplanes[prevPtIdx], mPolygons[i].bplanes[j] );
			//pt = denormalize(pt, center, scale);
			if (!pts.size() || 
				!IsSimilar(pt, pts.back())) 
				pts.push_back(pt);
        }
        auto normal = normalize(mPolygons[i].splane.Normal());
		TrianglatePolygon(normal, pts, results);
		//catch (...){
		//	wchar_t ch[64];
		//	swprintf(ch, 64, L"Error, %u", i);
		//	OutputDebugString(ch);
		//	results.clear();
		//}

        for (int k = 0 ; k < results.size(); k+=3)
        {   
            pMesh->Add(results[k], results[k+1], results[k+2], normal);
        }
        pts.clear();
		results.clear();
     }
     pMesh->GenID();
     return pMesh;
 }
BaseMesh* MainWindow::CreateTriangleMesh(BaseMesh* mesh) {
    if (mesh == NULL) return NULL;
    BaseMesh* triMesh = NULL;
    try {
        triMesh = new BaseMesh();
    } catch (...) {
        QMessageBox::information(this, tr("Error"), "Not enough memory!");
    }

    QVector <Vertex* > vertices = mesh->GetVertices();
    QMap <Vertex*, Vertex*> maps;
    // Add vertices
    for (int i=0; i<vertices.size(); ++i) {
        Vertex* newVertex = triMesh->AddVertex(vertices[i]);
        maps[vertices[i]] = newVertex;
    }

    // Add triangles

    QVector <Face* > faces = mesh->GetFaces();
    for (int i=0; i<faces.size(); ++i) {
        QVector <Vertex* > currentVertices = faces[i]->GetVertices();
        int faceSize = currentVertices.size();
        if (faceSize < 3) {
            QMessageBox::information(this, tr("Error"), "Face with less than 3 vertices!");
            return NULL;
        }

        for (int j=2; j<faceSize; ++j) {
            QVector <Vertex* > triangle;
            triangle.push_back(maps[currentVertices[0]]);
            triangle.push_back(maps[currentVertices[j-1]]);
            triangle.push_back(maps[currentVertices[j]]);
            triMesh->AddFace(triangle);
        }
    }
    return triMesh;
}
Exemple #15
0
BaseMesh* BoolOp::Intersect (BaseMesh* mesh1,  BaseMesh* mesh2)
{
	BaseMesh* result = NULL;
	if (mesh1 != NULL && mesh2 != NULL && (mesh1->AABB().Intersects(mesh2->AABB())))
	{
        result = ComputeBoolean(mesh1, mesh2, eIntersect);
		if (result && result->PrimitiveCount() ==0 )
		{
			delete result;
			result = NULL;
		}
	}
	if (result != NULL)
	{
		result->GenID();
	//	result->GenSurface();
	//	result->GenAABB(true);
	}
	return result ; 
 


}
Exemple #16
0
void Indicator::CreateMesh(const Vector<IndicatorShape> &Shapes, BaseMesh &MOut) const
{
    Vector<BaseMesh*> AllMeshes(Shapes.Length());
    for(UINT ShapeIndex = 0; ShapeIndex < Shapes.Length(); ShapeIndex++)
    {
        const IndicatorShape &CurShape = Shapes[ShapeIndex];
        Mesh *NewMesh = NULL;
        switch(CurShape.Type)
        {
        case IndicatorShapeSphere:
            {
                NewMesh = new Mesh(_Sphere);
            }
            break;
        case IndicatorShapeCylinder:
            {
                NewMesh = new Mesh(_Cylinder);
            }
            break;
        default:
            SignalError("Invalid shape type");
            return;
        }
        NewMesh->ApplyMatrix(CurShape.TransformMatrix());
        NewMesh->SetColor(CurShape.Color);
        AllMeshes[ShapeIndex] = NewMesh;
    }

    MOut.SetGD(_Sphere.GetGD());
    MOut.LoadMeshList(AllMeshes);

    for(UINT ShapeIndex = 0; ShapeIndex < Shapes.Length(); ShapeIndex++)
    {
        delete AllMeshes[ShapeIndex];
    }
}
Exemple #17
0
void ComplexMesh::Dump(BaseMesh &Mesh) const
{
    Mesh.Allocate(_Vertices.Length(),_Triangles.Length());
    for(UINT i=0;i<_Vertices.Length();i++)
    {
        Mesh.Vertices()[i].Pos = _Vertices[i].Pos();
        Mesh.Vertices()[i].TexCoord.x = _Vertices[i].TexCoords().x;
        Mesh.Vertices()[i].TexCoord.y = _Vertices[i].TexCoords().y;
    }
    for(UINT i=0;i<_Triangles.Length();i++)
    {
        Mesh.Indices()[i * 3 + 0] = _Triangles[i].GetVertex(0).Index();
        Mesh.Indices()[i * 3 + 1] = _Triangles[i].GetVertex(1).Index();
        Mesh.Indices()[i * 3 + 2] = _Triangles[i].GetVertex(2).Index();
    }
    Mesh.GenerateNormals();
}
Exemple #18
0
void BaseMesh::Split(float (*PositionFunction) (Vec3f &), BaseMesh &M1, BaseMesh &M2)
{
    int i,vc=VertexCount(),ic=IndexCount();
    MeshVertex *V = Vertices();
    DWORD *I = Indices();

    Vector<MeshVertex> NV1,NV2;
    Vector<TriMeshFace> NT1,NT2;

    SplitVMapper *VMap = new SplitVMapper[vc];
    float Value;

    for(i=0;i<vc;i++)
    {
        Value = PositionFunction(V[i].Pos);
        if(Value < 0.0f)
        {
            VMap[i].Side = 0;
            VMap[i].NVMap1 = NV1.Length();
            VMap[i].NVMap2 = -1;
            NV1.PushEnd(V[i]);
        } else {
            VMap[i].Side = 1;
            VMap[i].NVMap1 = -1;
            VMap[i].NVMap2 = NV2.Length();
            NV2.PushEnd(V[i]);
        }
    }

    int TSide[3];
    TriMeshFace Tri;
    int Oddball,State;

    for(i=0;i<ic;i+=3)
    {
        TSide[0] = VMap[I[i]].Side;
        TSide[1] = VMap[I[i+1]].Side;
        TSide[2] = VMap[I[i+2]].Side;

        if(TSide[0] && TSide[1] && TSide[2]) //all O2
        {            
            Tri.I[0] = VMap[I[i]].NVMap2;
            Tri.I[1] = VMap[I[i+1]].NVMap2;
            Tri.I[2] = VMap[I[i+2]].NVMap2;
            NT2.PushEnd(Tri);
        } else if(!(TSide[0] || TSide[1] || TSide[2])) //all O1
        {
            Tri.I[0] = VMap[I[i]].NVMap1;
            Tri.I[1] = VMap[I[i+1]].NVMap1;
            Tri.I[2] = VMap[I[i+2]].NVMap1;
            NT1.PushEnd(Tri);
        } else {
            if(TSide[0] && TSide[1]) {Oddball = 2; State = 1;}
            if(TSide[0] && TSide[2]) {Oddball = 1; State = 1;}
            if(TSide[1] && TSide[2]) {Oddball = 0; State = 1;}
            if(!(TSide[0] || TSide[1])) {Oddball = 2; State = 2;}
            if(!(TSide[0] || TSide[2])) {Oddball = 1; State = 2;}
            if(!(TSide[1] || TSide[2])) {Oddball = 0; State = 2;}

            if(State == 1)    //Add to Obj2
            {
                if(VMap[I[i+Oddball]].NVMap2 == -1)
                {
                    VMap[I[i+Oddball]].NVMap2 = NV2.Length();
                    NV2.PushEnd(V[I[i+Oddball]]);
                }
                Tri.I[0] = VMap[I[i]].NVMap2;
                Tri.I[1] = VMap[I[i+1]].NVMap2;
                Tri.I[2] = VMap[I[i+2]].NVMap2;
                NT2.PushEnd(Tri);
            } else {        //Add to Obj1
                if(VMap[I[i+Oddball]].NVMap1 == -1)
                {
                    VMap[I[i+Oddball]].NVMap1 = NV1.Length();
                    NV1.PushEnd(V[I[i+Oddball]]);
                }
                Tri.I[0] = VMap[I[i]].NVMap1;
                Tri.I[1] = VMap[I[i+1]].NVMap1;
                Tri.I[2] = VMap[I[i+2]].NVMap1;
                NT1.PushEnd(Tri);
            }
        }
    }

    delete[] VMap;

    M1.Allocate(NV1.Length(),NT1.Length());
    M2.Allocate(NV2.Length(),NT2.Length());
    
    memcpy(M1.Vertices(), NV1.CArray(), M1.VertexCount() * sizeof(MeshVertex));
    memcpy(M2.Vertices(), NV2.CArray(), M2.VertexCount() * sizeof(MeshVertex));
    memcpy(M1.Indices(), NT1.CArray(), M1.IndexCount() * sizeof(DWORD));
    memcpy(M2.Indices(), NT2.CArray(), M2.IndexCount() * sizeof(DWORD));
}
Exemple #19
0
BaseMesh* BSPBoolOp::ComputeBoolean(FixedPlaneMesh* mesh1, FixedPlaneMesh* mesh2, BOOL_OP op)
{
	GSOutputTimeLog(L"start: ");
    FixedBSPTree::SET_OP BSPOp;
    switch (op)
    {
        case eUnion:
            BSPOp = FixedBSPTree::OP_UNION;
            break;
        case eIntersect:
            BSPOp = FixedBSPTree::OP_INTERSECT;
            break;
        case eDiff:
            BSPOp = FixedBSPTree::OP_DIFFERENCE;
            break;
        default :
            break;
    }

	Box3 bbox(-1.5, -1.5, -1.5, 1.5, 1.5, 1.5);
    FixedBSPTree* pTree1 =  mesh1->ToBSPTree();
	GSOutputTimeLog(L"tree1, build: ");

    pTree1->FormSubHyperPlane(bbox);
	//pTree1->OutputDebugInfo("D:\\x.txt");
     
	GSOutputTimeLog(L"tree1, sp: ");

    FixedBSPTree* pTree2 = mesh2->ToBSPTree();
	GSOutputTimeLog(L"tree2, build: ");
    if (BSPOp == FixedBSPTree::OP_DIFFERENCE)
    {
        pTree2->Negate();
        BSPOp = FixedBSPTree::OP_INTERSECT;
    }
    pTree2->FormSubHyperPlane(bbox);
	GSOutputTimeLog(L"tree2, sp: ");
	//pTree2->OutputDebugInfo("D:\\y.txt");

    FixedBSPTree* pResultTree = pTree1->Merge(pTree2, BSPOp);
	GSOutputTimeLog(L"merged: ");
	//pResultTree->OutputDebugInfo("D:\\z.txt");
    delete pTree2;
    delete pTree1;
    //FixedPlaneMesh* pPlaneMesh1 = new FixedPlaneMesh(pTree1, mesh1->Color());//debug2

    // delete pTree1;//debug2
    FixedPlaneMesh* pPlaneMesh1 = new FixedPlaneMesh(pResultTree, mesh1->Color());
    delete pResultTree;
	GSOutputTimeLog(L"toPlaneMesh: ");

	pPlaneMesh1->SetAABB(mesh1->AABB());
    BaseMesh* pMesh = pPlaneMesh1->ToBaseMesh();
	GSOutputTimeLog(L"toBaseMesh: ");

    pMesh->DenormalizeCoord();
    pMesh->GenAABB(true);
    //BaseMesh* pMesh = mesh1->ToBaseMesh();//debug1
    if (pMesh && pMesh->PrimitiveCount() ==0 )
	{
        delete pMesh;
        pMesh = NULL;
    }
    delete pPlaneMesh1;
    return pMesh;
    return nullptr;
}
Exemple #20
0
void BaseMesh::ClosedPlaneSplit(const Plane &P, BaseMesh &M1, BaseMesh &M2)
{
    UINT VC = VertexCount(), IC = IndexCount();
    MeshVertex *V = Vertices();
    DWORD *I = Indices();

    Vector<Vec3f> NewVertices[2];
    Vector<TriMeshFace> NewFaces[2];
    Vector<Vec2f> BoundaryVertices;
    Vector<UINT> BoundaryIndices[2];

    Vec3f OrthogonalBasis1, OrthogonalBasis2;
    Vec3f::CompleteOrthonormalBasis(P.Normal(), OrthogonalBasis1, OrthogonalBasis2);

    PerfectSplitVMapper *VMap = new PerfectSplitVMapper[VC];
    
    for(UINT VertexIndex = 0; VertexIndex < VC; VertexIndex++)
    {
        Vec3f Pos = V[VertexIndex].Pos;
        float Value = Plane::DotCoord(P, Pos);
        if(Value < 0.0f)
        {
            VMap[VertexIndex].Side = 0;
            VMap[VertexIndex].NVMap = NewVertices[0].Length();
            NewVertices[0].PushEnd(Pos);
        }
        else
        {
            VMap[VertexIndex].Side = 1;
            VMap[VertexIndex].NVMap = NewVertices[1].Length();
            NewVertices[1].PushEnd(Pos);
        }
    }

    for(UINT IndexIndex = 0; IndexIndex < IC; IndexIndex += 3)
    {
        int TSide[3];
        TSide[0] = VMap[I[IndexIndex + 0]].Side;
        TSide[1] = VMap[I[IndexIndex + 1]].Side;
        TSide[2] = VMap[I[IndexIndex + 2]].Side;

        DWORD LocalTriangleM1[6], LocalTriangleM2[6];
        LocalTriangleM2[0] = LocalTriangleM1[0] = VMap[I[IndexIndex + 0]].NVMap;
        LocalTriangleM2[1] = LocalTriangleM1[1] = VMap[I[IndexIndex + 1]].NVMap;
        LocalTriangleM2[2] = LocalTriangleM1[2] = VMap[I[IndexIndex + 2]].NVMap;

        UINT TriangleType = TSide[0] * 4 + TSide[1] * 2 + TSide[2] * 1;

        for(UINT EdgeIndex = 0; EdgeIndex < 3; EdgeIndex++)
        {
            if(PerfectEdges[TriangleType][EdgeIndex])
            {
                Vec3f Vtx1 = V[I[IndexIndex + PerfectEdgeList[EdgeIndex][0]]].Pos;
                Vec3f Vtx2 = V[I[IndexIndex + PerfectEdgeList[EdgeIndex][1]]].Pos;
                Vec3f VtxIntersect = P.IntersectLine(Vtx1, Vtx2);
                
                if(!Vec3f::WithinRect(VtxIntersect, Rectangle3f::ConstructFromTwoPoints(Vtx1, Vtx2)))
                {
                    VtxIntersect = (Vtx1 + Vtx2) * 0.5f;
                }
                
                BoundaryVertices.PushEnd(Vec2f(Vec3f::Dot(VtxIntersect, OrthogonalBasis1), Vec3f::Dot(VtxIntersect, OrthogonalBasis2)));

                LocalTriangleM1[3 + EdgeIndex] = NewVertices[0].Length();
                BoundaryIndices[0].PushEnd(NewVertices[0].Length());
                NewVertices[0].PushEnd(VtxIntersect);

                LocalTriangleM2[3 + EdgeIndex] = NewVertices[1].Length();
                BoundaryIndices[1].PushEnd(NewVertices[1].Length());
                NewVertices[1].PushEnd(VtxIntersect);
            }
        }

        for(UINT LocalTriangleIndex = 0; LocalTriangleIndex < 6; LocalTriangleIndex += 3)
        {
            if(M1Indices[TriangleType][LocalTriangleIndex] != -1)
            {
                TriMeshFace Tri;
                Tri.I[0] = LocalTriangleM1[M1Indices[TriangleType][LocalTriangleIndex + 0]];
                Tri.I[1] = LocalTriangleM1[M1Indices[TriangleType][LocalTriangleIndex + 1]];
                Tri.I[2] = LocalTriangleM1[M1Indices[TriangleType][LocalTriangleIndex + 2]];
                NewFaces[0].PushEnd(Tri);
            }
            if(M2Indices[TriangleType][LocalTriangleIndex] != -1)
            {
                TriMeshFace Tri;
                Tri.I[0] = LocalTriangleM2[M2Indices[TriangleType][LocalTriangleIndex + 0]];
                Tri.I[1] = LocalTriangleM2[M2Indices[TriangleType][LocalTriangleIndex + 1]];
                Tri.I[2] = LocalTriangleM2[M2Indices[TriangleType][LocalTriangleIndex + 2]];
                NewFaces[1].PushEnd(Tri);
            }
        }
    }

#ifdef DELAUNAY_TRIANGULATOR
    if(BoundaryVertices.Length() > 0)
    {
        Vector<DWORD> BoundaryTriangulation;
        DelaunayTriangulator::Triangulate(BoundaryVertices, BoundaryTriangulation);
        for(UINT TriangleIndex = 0; TriangleIndex < BoundaryTriangulation.Length() / 3; TriangleIndex++)
        {
            for(UINT MeshIndex = 0; MeshIndex < 2; MeshIndex++)
            {
                TriMeshFace Tri;
                Vec3f V[3];
                for(UINT LocalVertexIndex = 0; LocalVertexIndex < 3; LocalVertexIndex++)
                {
                    Tri.I[LocalVertexIndex] = BoundaryIndices[MeshIndex][UINT(BoundaryTriangulation[TriangleIndex * 3 + LocalVertexIndex])];
                    V[LocalVertexIndex] = NewVertices[MeshIndex][UINT(Tri.I[LocalVertexIndex])];
                }
                //Utility::Swap(Tri.I[0], Tri.I[1]);
                //if(Math::TriangleArea(V[0], V[1], V[2]) > 1e-5f)
                {
                    NewFaces[MeshIndex].PushEnd(Tri);
                }
            }
        }
    }
#endif

    delete[] VMap;

    M1.SetGD(GetGD());
    M2.SetGD(GetGD());
    M1.Allocate(NewVertices[0].Length(), NewFaces[0].Length());
    M2.Allocate(NewVertices[1].Length(), NewFaces[1].Length());
    
    for(UINT VertexIndex = 0; VertexIndex < NewVertices[0].Length(); VertexIndex++)
    {
        M1.Vertices()[VertexIndex].Pos = NewVertices[0][VertexIndex];
    }
    for(UINT VertexIndex = 0; VertexIndex < NewVertices[1].Length(); VertexIndex++)
    {
        M2.Vertices()[VertexIndex].Pos = NewVertices[1][VertexIndex];
    }
    
    if(NewFaces[0].Length() > 0)
    {
        memcpy(M1.Indices(), NewFaces[0].CArray(), M1.IndexCount() * sizeof(DWORD));
    }
    if(NewFaces[1].Length() > 0)
    {
        memcpy(M2.Indices(), NewFaces[1].CArray(), M2.IndexCount() * sizeof(DWORD));
    }
}
Exemple #21
0
void ComplexMesh::Load(const BaseMesh &Mesh)
{
    FreeMemory();
    
    _Vertices.Allocate(Mesh.VertexCount());
    _Triangles.Allocate(Mesh.FaceCount());
    _HalfEdges.Allocate(Mesh.FaceCount() * 3);
    _FullEdges.FreeMemory();

    for(UINT i = 0; i < _Vertices.Length(); i++)
    {
        _Vertices[i].Pos() = Mesh.Vertices()[i].Pos;
        _Vertices[i].TexCoords() = Mesh.Vertices()[i].TexCoord;
        _Vertices[i].Boundary() = false;
        _Vertices[i]._Index = i;
    }

    InitHashTable(_Vertices.Length());

    for(UINT TriangleIndex = 0; TriangleIndex < _Triangles.Length(); TriangleIndex++)
    {
        Triangle &CurTriangle = _Triangles[TriangleIndex];
        UINT LocalIndices[3];
        LocalIndices[0] = Mesh.Indices()[TriangleIndex * 3 + 0];
        LocalIndices[1] = Mesh.Indices()[TriangleIndex * 3 + 1];
        LocalIndices[2] = Mesh.Indices()[TriangleIndex * 3 + 2];
        CurTriangle._Index = TriangleIndex;
        for(UINT LocalEdgeIndex = 0; LocalEdgeIndex < 3; LocalEdgeIndex++)
        {
            Vertex *SearchV[2];

            CurTriangle._HalfEdges[LocalEdgeIndex] = &_HalfEdges[TriangleIndex * 3 + LocalEdgeIndex];
            CurTriangle._Vertices[LocalEdgeIndex] = &_Vertices[LocalIndices[LocalEdgeIndex]];
            _HalfEdges[TriangleIndex * 3 + LocalEdgeIndex]._NextEdge = &_HalfEdges[TriangleIndex * 3 + (LocalEdgeIndex + 1) % 3];

            SearchV[0] = &_Vertices[LocalIndices[(LocalEdgeIndex + 1) % 3]];
            SearchV[1] = &_Vertices[LocalIndices[(LocalEdgeIndex + 2) % 3]];
            if(SearchV[0]->Index() > SearchV[1]->Index())
            {
                Utility::Swap(SearchV[0], SearchV[1]);
            }
            FullEdge &Target = FindFullEdge(SearchV);
            if(Target != FullEdge::NotFound)
            {
                PersistentAssert(Target.GetTriangle(1) == Triangle::Boundary, "Duplicate edge; 2-manifold criterion violated.");
                //PersistentAssert(Target.GetTriangle(1) == Triangle::Boundary,
                //                 String("Duplicate edge; 2-manifold criterion violated: ") + String(SearchV[0]->Index()) + String(", ") + String(SearchV[1]->Index()));

                _HalfEdges[TriangleIndex * 3 + LocalEdgeIndex]._AcrossEdge = &Target;
                Target._Triangles[1] = &CurTriangle;
            }
            else
            {
                FullEdge *NewEdge = new FullEdge;
                Assert(NewEdge != NULL, "Out of memory");
                NewEdge->_Index = _FullEdges.Length();
                NewEdge->_Triangles[0] = &CurTriangle;
                NewEdge->_Triangles[1] = &Triangle::Boundary;
                NewEdge->_Vertices[0] = SearchV[0];
                NewEdge->_Vertices[1] = SearchV[1];
                _HalfEdges[TriangleIndex * 3 + LocalEdgeIndex]._AcrossEdge = NewEdge;

                _FullEdges.PushEnd(NewEdge);
                HashEdge(*NewEdge);
            }
        }
    }

    for(UINT TriangleIndex = 0; TriangleIndex < _Triangles.Length(); TriangleIndex++)
    {
        Triangle &CurTriangle = _Triangles[TriangleIndex];
        for(UINT AdjacentTriangleIndex = 0; AdjacentTriangleIndex < 3; AdjacentTriangleIndex++)
        {
            Triangle &AdjTriangle = CurTriangle.GetNeighboringTriangle(AdjacentTriangleIndex);
        }
    }

    ClearHashTable();
    
    for(UINT i = 0; i < _FullEdges.Length(); i++)
    {
        if(_FullEdges[i]->Boundary())
        {
            _FullEdges[i]->GetVertex(0).Boundary() = true;
            _FullEdges[i]->GetVertex(1).Boundary() = true;
            _FullEdges[i]->OrientMatchingBoundary();
        }
    }

    PrepareTopology();

    /*if(!Oriented())
    {
        Orient();
    }
    PersistentAssert(Oriented(), "Mesh not oriented");*/

}