/// <summary> /// This method adds a face normal vector to a list. /// The vector is calculated for the face which handle the method expects. /// </summary> /// <param name="faceHandle">Handle to a face to calculate the normal for.</param> public void CalcFaceNormal(HandleFace faceHandle) { List <HandleVertex> tmpList = EnFaceAdjacentVertices(faceHandle).ToList(); if (tmpList.Count < 3) { return; } var v0 = _LvertexVal[tmpList[0]]; var v1 = _LvertexVal[tmpList[1]]; var v2 = _LvertexVal[tmpList[2]]; float3 c1 = float3.Subtract(v0, v1); float3 c2 = float3.Subtract(v0, v2); float3 n = float3.Cross(c1, c2); _LfaceNormals.Add(float3.Normalize(n)); FacePtrCont fc = _LfacePtrCont[faceHandle]; _LfacePtrCont[faceHandle] = new FacePtrCont() { _fn = new HandleFaceNormal(_LfaceNormals.Count - 1), _h = fc._h }; }
/// <summary> /// Adds a face from the importer to the geometry container /// </summary> /// <param name="gf">GeoFace object from the importer</param> private void AddFace(GeoFace gf) { // Add a face container. _LfacePtrCont.Add( new FacePtrCont() { _h = new HandleHalfEdge() { _DataIndex = -1 } } ); // Add a face handle. _LfaceHndl.Add( new HandleFace() { _DataIndex = _LfacePtrCont.Count - 1 } ); // Insert all the vertices for the face. List <HandleVertex> LHandleVertsForFace = new List <HandleVertex>(); foreach (float3 vVal in gf._LFVertices) { LHandleVertsForFace.Add( AddVertex(vVal) ); } // Insert all the uv coordinates for the face. List <HandleVertexUV> LHandleUVsForFace = new List <HandleVertexUV>(); foreach (float2 uvVal in gf._UV) { _LuvCoordinates.Add(uvVal); LHandleUVsForFace.Add(new HandleVertexUV() { _DataIndex = _LuvCoordinates.Count - 1 }); } // Build up the half-edge connections for the face List <HandleHalfEdge> LHandleHEForFace = new List <HandleHalfEdge>(); for (int i = 0; i < LHandleVertsForFace.Count; i++) { HandleVertex fromVert = LHandleVertsForFace[i]; HandleVertex toVert = i + 1 < LHandleVertsForFace.Count ? LHandleVertsForFace[i + 1] : LHandleVertsForFace[0]; LHandleHEForFace.Add( CreateConnection(fromVert, toVert) ); } // Loop over all the half-edges for the face and concat them and set the correct uv coordinates. for (int i = 0; i < LHandleHEForFace.Count; i++) { HandleHalfEdge currentHedge = LHandleHEForFace[i]; HEdgePtrCont hedge = _LhedgePtrCont[currentHedge]; HandleHalfEdge nextHedge = i + 1 < LHandleHEForFace.Count ? LHandleHEForFace[i + 1] : LHandleHEForFace[0]; hedge._nhe = nextHedge; if (LHandleUVsForFace.Count > 0) { HandleVertexUV currentUV = i + 1 < LHandleUVsForFace.Count ? LHandleUVsForFace[i + 1] : LHandleUVsForFace[0]; hedge._vuv = currentUV; } //_LhedgePtrCont.RemoveAt(currentHedge); //_LhedgePtrCont.Insert(currentHedge, hedge); _LhedgePtrCont[currentHedge] = new HEdgePtrCont() { _f = hedge._f, _he = hedge._he, _nhe = hedge._nhe, _v = hedge._v, _vn = hedge._vn, _vuv = hedge._vuv }; } // Set the half-edge the face points to. FacePtrCont face = _LfacePtrCont[_LfacePtrCont.Count - 1]; face._h = new HandleHalfEdge(LHandleHEForFace.First()); _LfacePtrCont.RemoveAt(_LfacePtrCont.Count - 1); _LfacePtrCont.Add(face); }
/// <summary> /// This method converts a quad based 'Geometry' object to a triangle based one. /// </summary> private void TriangulateGeometry() { List <HandleFace> LtmpFaces = new List <HandleFace>(); foreach (HandleFace currentFace in _LfaceHndl) { // Pruefe zuerst ob man das face triangulaten sollte oder nicht. if (EnFaceAdjacentHalfEdges(currentFace).Count() == 3) { continue; } // Hole aktuelles face und merke den index. FacePtrCont currentFaceCont = _LfacePtrCont[currentFace]; // Merke erste hedge h0. HandleHalfEdge h0H = currentFaceCont._h; HEdgePtrCont h0Cont = _LhedgePtrCont[h0H]; // Merke ersten vert v0. HandleVertex v0H = _LhedgePtrCont[h0Cont._he]._v; // Merke die letzte hedge im face hl. //HandleHalfEdge hlH = RetLastHalfEdgeInFaceCw(currentFace); var temp = EnFaceAdjacentHalfEdges(currentFace); HandleHalfEdge hlH = temp.ElementAt(temp.Count() - 1); HEdgePtrCont hlCont = _LhedgePtrCont[hlH]; // Lege zwei neue hedges an und fülle sie korrekt. int hedgeCount = _LhedgePtrCont.Count; HandleHalfEdge hedge0H = new HandleHalfEdge() { _DataIndex = hedgeCount }; HandleHalfEdge hedge1H = new HandleHalfEdge() { _DataIndex = hedgeCount + 1 }; HandleEdge edgeHNew = new HandleEdge() { _DataIndex = _LedgeHndl.Count }; EdgePtrCont edgeContNew = new EdgePtrCont() { _he1 = hedge0H, _he2 = hedge1H }; HEdgePtrCont newhedge0 = new HEdgePtrCont() { _nhe = h0H, _v = v0H, _he = hedge1H, _f = currentFace, _vn = hlCont._vn, _vuv = hlCont._vuv }; // Hole h1 und h2 zum Merken. HandleHalfEdge h1H = h0Cont._nhe; HEdgePtrCont h1Cont = _LhedgePtrCont[h1H]; HandleHalfEdge h2H = h1Cont._nhe; HEdgePtrCont h2Cont = _LhedgePtrCont[h2H]; HEdgePtrCont newhedge1 = new HEdgePtrCont() { _nhe = h1Cont._nhe, _v = h1Cont._v, _he = hedge0H, _f = new HandleFace(-1), _vn = h1Cont._vn, _vuv = h1Cont._vuv, }; // Update die jeweiligen next pointer der angrenzenden hedges. h1Cont._nhe = hedge0H; hlCont._nhe = hedge1H; // Lege ein neues face an für das triangle 2. HandleFace f1H = new HandleFace() { _DataIndex = (_LfaceHndl.Count - 1) + LtmpFaces.Count + 1 }; FacePtrCont f1Cont = new FacePtrCont() { _fn = currentFaceCont._fn, _h = hlH }; // Update das neue triangle bezüglich des neuen faces. Dazu erstmal h2 holen noch. newhedge1._f = f1H; h2Cont._f = f1H; hlCont._f = f1H; // Sichere die Änderungen in den listen. _LedgeHndl.Add(edgeHNew); _LedgePtrCont.Add(edgeContNew); _LhedgePtrCont.Add(newhedge0); _LhedgePtrCont.Add(newhedge1); // Speichere das face handle erstmal in tmp faces wegen der iteration. LtmpFaces.Add(f1H); _LfacePtrCont.Add(f1Cont); _LhedgePtrCont[h1H] = new HEdgePtrCont() { _f = h1Cont._f, _he = h1Cont._he, _nhe = h1Cont._nhe, _v = h1Cont._v, _vn = h1Cont._vn, _vuv = h1Cont._vuv }; _LhedgePtrCont[h2H] = new HEdgePtrCont() { _f = h2Cont._f, _he = h2Cont._he, _nhe = h2Cont._nhe, _v = h2Cont._v, _vn = h2Cont._vn, _vuv = h2Cont._vuv }; _LhedgePtrCont[hlH] = new HEdgePtrCont() { _f = hlCont._f, _he = hlCont._he, _nhe = hlCont._nhe, _v = hlCont._v, _vn = hlCont._vn, _vuv = hlCont._vuv }; } foreach (HandleFace handleFace in LtmpFaces) { _LfaceHndl.Add(handleFace); } LtmpFaces.Clear(); }