Exemple #1
0
 internal void SetDetails(uint index, PMFaceVertex v0, PMFaceVertex v1, PMFaceVertex v2)
 {
     Debug.Assert(v0 != v1 && v1 != v2 && v2 != v0);
     this.index     = index;
     this.vertex[0] = v0;
     this.vertex[1] = v1;
     this.vertex[2] = v2;
     ComputeNormal();
     // Add tri to vertices
     // Also tell vertices they are neighbours
     for (var i = 0; i < 3; i++)
     {
         this.vertex[i].commonVertex.faces.Add(this);
         for (var j = 0; j < 3; j++)
         {
             if (i != j)
             {
                 this.vertex[i].commonVertex.AddIfNonNeighbor(this.vertex[j].commonVertex);
             }
         }
     }
 }
Exemple #2
0
 internal void ReplaceVertex(PMFaceVertex vold, PMFaceVertex vnew)
 {
     Debug.Assert(vold == this.vertex[0] || vold == this.vertex[1] || vold == this.vertex[2]);
     Debug.Assert(vnew != this.vertex[0] && vnew != this.vertex[1] && vnew != this.vertex[2]);
     if (vold == this.vertex[0])
     {
         this.vertex[0] = vnew;
     }
     else if (vold == this.vertex[1])
     {
         this.vertex[1] = vnew;
     }
     else
     {
         this.vertex[2] = vnew;
     }
     vold.commonVertex.faces.Remove(this);
     vnew.commonVertex.faces.Add(this);
     for (var i = 0; i < 3; i++)
     {
         vold.commonVertex.RemoveIfNonNeighbor(this.vertex[i].commonVertex);
         this.vertex[i].commonVertex.RemoveIfNonNeighbor(vold.commonVertex);
     }
     for (var i = 0; i < 3; i++)
     {
         Debug.Assert(this.vertex[i].commonVertex.faces.Contains(this));
         for (var j = 0; j < 3; j++)
         {
             if (i != j)
             {
                 this.vertex[i].commonVertex.AddIfNonNeighbor(this.vertex[j].commonVertex);
             }
         }
     }
     ComputeNormal();
 }
Exemple #3
0
        /// <summary>
        ///    Internal method, collapses vertex onto it's saved collapse target.
        /// </summary>
        /// <remarks>
        ///    This updates the working triangle list to drop a triangle and recalculates
        ///    the edge collapse costs around the collapse target.
        ///    This also updates all the working vertex lists for the relevant buffer.
        /// </remarks>
        /// <pram name="src">the collapser</pram>
        private void Collapse(PMVertex src)
        {
            var dest         = src.collapseTo;
            var recomputeSet = new List <PMVertex>();

            // Abort if we're never supposed to collapse
            if (src.collapseCost == float.MaxValue)
            {
                return;
            }

            // Remove this vertex from the running for the next check
            src.collapseTo   = null;
            src.collapseCost = float.MaxValue;
            this.worstCosts[(int)src.index] = float.MaxValue;

            // Collapse the edge uv by moving vertex u onto v
            // Actually remove tris on uv, then update tris that
            // have u to have v, and then remove u.
            if (dest == null)
            {
                // src is a vertex all by itself
                return;
            }

            // Add dest and all the neighbours of source and dest to recompute list
            recomputeSet.Add(dest);

            foreach (var neighbor in src.neighbors)
            {
                if (!recomputeSet.Contains(neighbor))
                {
                    recomputeSet.Add(neighbor);
                }
            }
            foreach (var neighbor in dest.neighbors)
            {
                if (!recomputeSet.Contains(neighbor))
                {
                    recomputeSet.Add(neighbor);
                }
            }

            // delete triangles on edge src-dest
            // Notify others to replace src with dest
            // Queue of faces for removal / replacement
            // prevents us screwing up the iterators while we parse
            var faceRemovalList     = new List <PMTriangle>();
            var faceReplacementList = new List <PMTriangle>();

            foreach (var face in src.faces)
            {
                if (face.HasCommonVertex(dest))
                {
                    // Tri is on src-dest therefore is gone
                    faceRemovalList.Add(face);
                    // Reduce index count by 3 (useful for quick allocation later)
                    this.currNumIndexes -= 3;
                }
                else
                {
                    // Only src involved, replace with dest
                    faceReplacementList.Add(face);
                }
            }

            src.toBeRemoved = true;
            // Replace all the faces queued for replacement
            foreach (var face in faceReplacementList)
            {
                /* Locate the face vertex which corresponds with the common 'dest' vertex
                 * To to this, find a removed face which has the FACE vertex corresponding with
                 * src, and use it's FACE vertex version of dest.
                 */
                var          srcFaceVert  = face.GetFaceVertexFromCommon(src);
                PMFaceVertex destFaceVert = null;
                foreach (var removed in faceRemovalList)
                {
                    //if (removed.HasFaceVertex(srcFaceVert))
                    //{
                    destFaceVert = removed.GetFaceVertexFromCommon(dest);
                    //}
                }

                Debug.Assert(destFaceVert != null);

                face.ReplaceVertex(srcFaceVert, destFaceVert);
            }
            // Remove all the faces queued for removal
            foreach (var face in faceRemovalList)
            {
                face.NotifyRemoved();
            }

            // Notify the vertex that it is gone
            src.NotifyRemoved();

            // recompute costs
            foreach (var recomp in recomputeSet)
            {
                ComputeEdgeCostAtVertex(recomp.index);
            }
        }
Exemple #4
0
 private bool HasFaceVertex(PMFaceVertex v)
 {
     return(v == this.vertex[0] || v == this.vertex[1] || v == this.vertex[2]);
 }
 bool HasFaceVertex(PMFaceVertex v)
 {
     return (v == vertex[0] ||
             v == vertex[1] ||
             v == vertex[2]);
 }
 internal void SetDetails(uint index, PMFaceVertex v0, PMFaceVertex v1, PMFaceVertex v2)
 {
     Debug.Assert(v0 != v1 && v1 != v2 && v2 != v0);
     this.index = index;
     vertex[0] = v0;
     vertex[1] = v1;
     vertex[2] = v2;
     ComputeNormal();
     // Add tri to vertices
     // Also tell vertices they are neighbours
     for (int i = 0; i < 3; i++) {
         vertex[i].commonVertex.faces.Add(this);
         for (int j = 0; j < 3; j++)
             if (i != j)
                 vertex[i].commonVertex.AddIfNonNeighbor(vertex[j].commonVertex);
     }
 }
 internal void ReplaceVertex(PMFaceVertex vold, PMFaceVertex vnew)
 {
     Debug.Assert(vold == vertex[0] || vold == vertex[1] || vold == vertex[2]);
     Debug.Assert(vnew != vertex[0] && vnew != vertex[1] && vnew != vertex[2]);
     if (vold == vertex[0]) {
         vertex[0] = vnew;
     } else if (vold == vertex[1]) {
         vertex[1] = vnew;
     } else {
         vertex[2] = vnew;
     }
     vold.commonVertex.faces.Remove(this);
     vnew.commonVertex.faces.Add(this);
     for (int i = 0; i < 3; i++) {
         vold.commonVertex.RemoveIfNonNeighbor(vertex[i].commonVertex);
         vertex[i].commonVertex.RemoveIfNonNeighbor(vold.commonVertex);
     }
     for (int i = 0; i < 3; i++) {
         Debug.Assert(vertex[i].commonVertex.faces.Contains(this));
         for (int j = 0; j < 3; j++)
             if (i != j)
                 vertex[i].commonVertex.AddIfNonNeighbor(vertex[j].commonVertex);
     }
     ComputeNormal();
 }
			private bool HasFaceVertex( PMFaceVertex v )
			{
				return ( v == this.vertex[ 0 ] || v == this.vertex[ 1 ] || v == this.vertex[ 2 ] );
			}
        /// <summary>
        ///    Internal method for building PMWorkingData from geometry data
        /// </summary>
        void AddWorkingData(VertexData vertexData, IndexData indexData)
        {
            // Insert blank working data, then fill
            PMWorkingData work = new PMWorkingData();

            this.workingDataList.Add(work);

            // Build vertex list
            // Resize face list (this will always be this big)
            work.faceVertList = new PMFaceVertex[vertexData.vertexCount];
            // Also resize common vert list to max, to avoid reallocations
            work.vertList = new PMVertex[vertexData.vertexCount];

            // locate position element & the buffer to go with it
            VertexElement posElem =
                vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.Position);
            HardwareVertexBuffer vbuf =
                vertexData.vertexBufferBinding.GetBuffer(posElem.Source);

            // lock the buffer for reading
            IntPtr bufPtr = vbuf.Lock(BufferLocking.ReadOnly);

            uint numCommon = 0;

            unsafe {
                byte *pVertex = (byte *)bufPtr.ToPointer();

                float * pFloat;
                Vector3 pos;
                // Map for identifying duplicate position vertices
                Dictionary <Vector3, uint> commonVertexMap = new Dictionary <Vector3, uint>();
                for (uint i = 0; i < vertexData.vertexCount; ++i, pVertex += vbuf.VertexSize)
                {
                    pFloat = (float *)(pVertex + posElem.Offset);
                    pos.x  = *pFloat++;
                    pos.y  = *pFloat++;
                    pos.z  = *pFloat++;

                    work.faceVertList[(int)i] = new PMFaceVertex();

                    // Try to find this position in the existing map
                    if (!commonVertexMap.ContainsKey(pos))
                    {
                        // Doesn't exist, so create it
                        PMVertex commonVert = new PMVertex();
                        commonVert.SetDetails(pos, numCommon);
                        commonVert.removed     = false;
                        commonVert.toBeRemoved = false;
                        commonVert.seam        = false;
                        // Add it to our working set
                        work.vertList[(int)numCommon] = commonVert;

                        // Enter it in the map
                        commonVertexMap.Add(pos, numCommon);
                        // Increment common index
                        ++numCommon;

                        work.faceVertList[(int)i].commonVertex = commonVert;
                        work.faceVertList[(int)i].realIndex    = i;
                    }
                    else
                    {
                        // Exists already, reference it
                        PMVertex existingVert = work.vertList[(int)commonVertexMap[pos]];

                        work.faceVertList[(int)i].commonVertex = existingVert;
                        work.faceVertList[(int)i].realIndex    = i;

                        // Also tag original as a seam since duplicates at this location
                        work.faceVertList[(int)i].commonVertex.seam = true;
                    }
                }
            }
            vbuf.Unlock();

            numCommonVertices = numCommon;

            // Build tri list
            uint numTris             = (uint)indexData.indexCount / 3;
            HardwareIndexBuffer ibuf = indexData.indexBuffer;
            bool   use32bitindexes   = (ibuf.Type == IndexType.Size32);
            IntPtr indexBufferPtr    = ibuf.Lock(BufferLocking.ReadOnly);

            unsafe {
                ushort *pShort = null;
                uint *  pInt   = null;

                if (use32bitindexes)
                {
                    pInt = (uint *)indexBufferPtr.ToPointer();
                }
                else
                {
                    pShort = (ushort *)indexBufferPtr.ToPointer();
                }
                work.triList = new PMTriangle[(int)numTris]; // assumed tri list
                for (uint i = 0; i < numTris; ++i)
                {
                    // use 32-bit index always since we're not storing
                    uint         vindex = use32bitindexes ? *pInt++ : *pShort++;
                    PMFaceVertex v0     = work.faceVertList[(int)vindex];
                    vindex = use32bitindexes ? *pInt++ : *pShort++;
                    PMFaceVertex v1 = work.faceVertList[(int)vindex];
                    vindex = use32bitindexes ? *pInt++ : *pShort++;
                    PMFaceVertex v2 = work.faceVertList[(int)vindex];

                    work.triList[(int)i] = new PMTriangle();
                    work.triList[(int)i].SetDetails(i, v0, v1, v2);
                    work.triList[(int)i].removed = false;
                }
            }
            ibuf.Unlock();
        }
 bool HasFaceVertex(PMFaceVertex v)
 {
     return(v == vertex[0] ||
            v == vertex[1] ||
            v == vertex[2]);
 }