예제 #1
0
        /// <summary>
        ///    Internal method evaluates all collapse costs from this vertex and picks the lowest for a single buffer
        /// </summary>
        private float ComputeEdgeCostAtVertexForBuffer(PMWorkingData workingData, uint vertIndex)
        {
            // compute the edge collapse cost for all edges that start
            // from vertex v.  Since we are only interested in reducing
            // the object by selecting the min cost edge at each step, we
            // only cache the cost of the least cost edge at this vertex
            // (in member variable collapse) as well as the value of the
            // cost (in member variable objdist).

            var v = workingData.vertList[(int)vertIndex];

            if (v.neighbors.Count == 0)
            {
                // v doesn't have neighbors so nothing to collapse
                v.NotifyRemoved();
                return(v.collapseCost);
            }

            // Init metrics
            v.collapseCost = float.MaxValue;
            v.collapseTo   = null;

            // search all neighboring edges for "least cost" edge
            foreach (var neighbor in v.neighbors)
            {
                var cost = ComputeEdgeCollapseCost(v, neighbor);
                if ((v.collapseTo == null) || cost < v.collapseCost)
                {
                    v.collapseTo   = neighbor;                 // candidate for edge collapse
                    v.collapseCost = cost;                     // cost of the collapse
                }
            }

            return(v.collapseCost);
        }
        /// <summary>
        ///    Internal method builds an new LOD based on the current state
        /// </summary>
        /// <param name="indexData">Index data which will have an index buffer created and initialized</param>
        void BakeNewLOD(IndexData indexData)
        {
            Debug.Assert(currNumIndexes > 0, "No triangles to bake!");
            // Zip through the tri list of any working data copy and bake
            indexData.indexCount = (int)currNumIndexes;
            indexData.indexStart = 0;
            // Base size of indexes on original
            bool use32bitindexes =
                (this.indexData.indexBuffer.Type == IndexType.Size32);

            // Create index buffer, we don't need to read it back or modify it a lot
            indexData.indexBuffer =
                HardwareBufferManager.Instance.CreateIndexBuffer(this.indexData.indexBuffer.Type,
                                                                 indexData.indexCount,
                                                                 BufferUsage.StaticWriteOnly,
                                                                 false);

            IntPtr bufPtr = indexData.indexBuffer.Lock(BufferLocking.Discard);

            unsafe {
                ushort *pShort = null;
                uint *  pInt   = null;
                if (use32bitindexes)
                {
                    pInt = (uint *)bufPtr.ToPointer();
                }
                else
                {
                    pShort = (ushort *)bufPtr.ToPointer();
                }
                // Use the first working data buffer, they are all the same index-wise
                PMWorkingData work = this.workingDataList[0];
                foreach (PMTriangle tri in work.triList)
                {
                    if (!tri.removed)
                    {
                        if (use32bitindexes)
                        {
                            *pInt++ = tri.vertex[0].realIndex;
                            *pInt++ = tri.vertex[1].realIndex;
                            *pInt++ = tri.vertex[2].realIndex;
                        }
                        else
                        {
                            *pShort++ = (ushort)tri.vertex[0].realIndex;
                            *pShort++ = (ushort)tri.vertex[1].realIndex;
                            *pShort++ = (ushort)tri.vertex[2].realIndex;
                        }
                    }
                }
            }

            indexData.indexBuffer.Unlock();
        }
예제 #3
0
        /// <summary>
        ///    Internal method for building PMWorkingData from geometry data
        /// </summary>
        private void AddWorkingData(VertexData vertexData, IndexData indexData)
        {
            // Insert blank working data, then fill
            var 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
            var posElem = vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.Position);
            var vbuf    = vertexData.vertexBufferBinding.GetBuffer(posElem.Source);

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

            uint numCommon = 0;

#if !AXIOM_SAFE_ONLY
            unsafe
#endif
            {
                var pVertex = bufPtr;

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

                    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
                        var 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
                        var 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();

            this.numCommonVertices = numCommon;

            // Build tri list
            var numTris         = (uint)indexData.indexCount / 3;
            var ibuf            = indexData.indexBuffer;
            var use32bitindexes = (ibuf.Type == IndexType.Size32);
            var indexBufferPtr  = ibuf.Lock(BufferLocking.ReadOnly);
#if !AXIOM_SAFE_ONLY
            unsafe
#endif
            {
                var pInt   = indexBufferPtr.ToUIntPointer();
                var pShort = indexBufferPtr.ToUShortPointer();
                var idx    = 0;
                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
                    var vindex = use32bitindexes ? pInt[idx++] : pShort[idx++];
                    var v0     = work.faceVertList[(int)vindex];
                    vindex = use32bitindexes ? pInt[idx++] : pShort[idx++];
                    var v1 = work.faceVertList[(int)vindex];
                    vindex = use32bitindexes ? pInt[idx++] : pShort[idx++];
                    var 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();
        }
        /// <summary>
        ///    Internal method evaluates all collapse costs from this vertex and picks the lowest for a single buffer
        /// </summary>
        float ComputeEdgeCostAtVertexForBuffer(PMWorkingData workingData, uint vertIndex)
        {
            // compute the edge collapse cost for all edges that start
            // from vertex v.  Since we are only interested in reducing
            // the object by selecting the min cost edge at each step, we
            // only cache the cost of the least cost edge at this vertex
            // (in member variable collapse) as well as the value of the
            // cost (in member variable objdist).

            PMVertex v = workingData.vertList[(int)vertIndex];

            if (v.neighbors.Count == 0) {
                // v doesn't have neighbors so nothing to collapse
                v.NotifyRemoved();
                return v.collapseCost;
            }

            // Init metrics
            v.collapseCost = float.MaxValue;
            v.collapseTo = null;

            // search all neighboring edges for "least cost" edge
            foreach (PMVertex neighbor in v.neighbors)
            {
                float cost = ComputeEdgeCollapseCost(v, neighbor);
                if ((v.collapseTo == null) || cost < v.collapseCost)
                {
                    v.collapseTo = neighbor;  // candidate for edge collapse
                    v.collapseCost = cost;    // cost of the collapse
                }
            }

            return v.collapseCost;
        }
        /// <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();
        }
예제 #6
0
		/// <summary>
		///    Internal method for building PMWorkingData from geometry data
		/// </summary>
		private void AddWorkingData( VertexData vertexData, IndexData indexData )
		{
			// Insert blank working data, then fill
			var 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
			var posElem = vertexData.vertexDeclaration.FindElementBySemantic( VertexElementSemantic.Position );
			var vbuf = vertexData.vertexBufferBinding.GetBuffer( posElem.Source );

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

			uint numCommon = 0;
#if !AXIOM_SAFE_ONLY
			unsafe
#endif
			{
				var pVertex = bufPtr;

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

					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
						var 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
						var 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();

			this.numCommonVertices = numCommon;

			// Build tri list
			var numTris = (uint)indexData.indexCount/3;
			var ibuf = indexData.indexBuffer;
			var use32bitindexes = ( ibuf.Type == IndexType.Size32 );
			var indexBufferPtr = ibuf.Lock( BufferLocking.ReadOnly );
#if !AXIOM_SAFE_ONLY
			unsafe
#endif
			{
				var pInt = indexBufferPtr.ToUIntPointer();
				var pShort = indexBufferPtr.ToUShortPointer();
				var idx = 0;
				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
					var vindex = use32bitindexes ? pInt[ idx++ ] : pShort[ idx++ ];
					var v0 = work.faceVertList[ (int)vindex ];
					vindex = use32bitindexes ? pInt[ idx++ ] : pShort[ idx++ ];
					var v1 = work.faceVertList[ (int)vindex ];
					vindex = use32bitindexes ? pInt[ idx++ ] : pShort[ idx++ ];
					var 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();
		}
        /// <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();
        }