Summary class collecting together index data source information.
Inheritance: DisposableObject
Beispiel #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="disposeManagedResources"></param>
        protected override void dispose(bool disposeManagedResources)
        {
            if (!IsDisposed)
            {
                if (disposeManagedResources)
                {
                    if (this.vertexData != null)
                    {
                        if (!this.vertexData.IsDisposed)
                        {
                            this.vertexData.Dispose();
                        }

                        this.vertexData = null;
                    }

                    if (this.indexData != null)
                    {
                        if (!this.indexData.IsDisposed)
                        {
                            this.indexData.Dispose();
                        }

                        this.indexData = null;
                    }
                }
            }

            base.dispose(disposeManagedResources);
        }
Beispiel #2
0
        /// <summary>
        ///		Clones this vertex data, potentially including replicating any index buffers.
        /// </summary>
        /// <param name="copyData">
        ///		If true, makes a copy the index buffer in addition to the definition.
        ///		If false, the clone will refer to the same index buffer this object refers to.
        /// </param>
        /// <returns>A copy of this IndexData object.</returns>
        public IndexData Clone(bool copyData)
        {
            var clone = new IndexData();

            if (this.indexBuffer != null)
            {
                if (copyData)
                {
                    clone.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer(this.indexBuffer.Type,
                                                                                         this.indexBuffer.IndexCount,
                                                                                         this.indexBuffer.Usage,
                                                                                         this.indexBuffer.HasShadowBuffer);

                    // copy all the existing buffer data
                    clone.indexBuffer.CopyTo(this.indexBuffer, 0, 0, this.indexBuffer.Size, true);
                }
                else
                {
                    clone.indexBuffer = this.indexBuffer;
                }
            }

            clone.indexStart = this.indexStart;
            clone.indexCount = this.indexCount;

            return(clone);
        }
 public static void GetSubmeshIndexData(out int[,] indices, IndexData indexData)
 {
     HardwareIndexBuffer idxBuffer = indexData.indexBuffer;
     IndexType indexType = IndexType.Size16;
     if ((idxBuffer.Size / indexData.indexCount) != 2) {
         Debug.Assert(false, "Unexpected index buffer size");
         indexType = IndexType.Size32;
     }
     Debug.Assert(indexData.indexCount % 3 == 0);
     indices = new int[indexData.indexCount / 3, 3];
     ReadBuffer(idxBuffer, indexData.indexCount, indexType, ref indices);
 }
Beispiel #4
0
        /// <summary>
        /// Class level dispose method
        /// </summary>
        /// <remarks>
        /// When implementing this method in an inherited class the following template should be used;
        /// protected override void dispose( bool disposeManagedResources )
        /// {
        ///     if ( !isDisposed )
        ///     {
        ///         if ( disposeManagedResources )
        ///         {
        ///             // Dispose managed resources.
        ///         }
        ///
        ///         // There are no unmanaged resources to release, but
        ///         // if we add them, they need to be released here.
        ///     }
        ///
        ///     // If it is available, make the call to the
        ///     // base class's Dispose(Boolean) method
        ///     base.dispose( disposeManagedResources );
        /// }
        /// </remarks>
        /// <param name="disposeManagedResources">True if Unmanaged resources should be released.</param>
        protected override void dispose(bool disposeManagedResources)
        {
            if (!IsDisposed)
            {
                if (disposeManagedResources)
                {
                    // Dispose managed resources.
                    if (this.renderOperation != null)
                    {
                        if (!this.renderOperation.IsDisposed)
                        {
                            this.renderOperation.Dispose();
                        }

                        this.renderOperation = null;
                    }

                    if (this.indexData != null)
                    {
                        if (!this.indexData.IsDisposed)
                        {
                            this.indexData.Dispose();
                        }

                        this.indexData = null;
                    }

                    if (this.vertexData != null)
                    {
                        if (!this.vertexData.IsDisposed)
                        {
                            this.vertexData.Dispose();
                        }

                        this.vertexData = null;
                    }
                }

                // There are no unmanaged resources to release, but
                // if we add them, they need to be released here.
            }

            base.dispose(disposeManagedResources);
        }
        public GeometryBucket(MaterialBucket parent, string formatString, 
                              VertexData vData, IndexData iData)
        {
            // Clone the structure from the example
            this.parent = parent;
            this.formatString = formatString;
            vertexData = vData.Clone(false);
            indexData = iData.Clone(false);
            vertexData.vertexCount = 0;
            vertexData.vertexStart = 0;
            indexData.indexCount = 0;
            indexData.indexStart = 0;
            indexType = indexData.indexBuffer.Type;
            queuedGeometry = new List<QueuedGeometry>();
            // Derive the max vertices
            if (indexType == IndexType.Size32)
                maxVertexIndex = int.MaxValue;
            else
                maxVertexIndex = ushort.MaxValue;

            // Check to see if we have blend indices / blend weights
            // remove them if so, they can try to blend non-existent bones!
            VertexElement blendIndices =
                vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.BlendIndices);
            VertexElement blendWeights =
                vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.BlendWeights);
            if (blendIndices != null && blendWeights != null) {
                Debug.Assert(blendIndices.Source == blendWeights.Source,
                             "Blend indices and weights should be in the same buffer");
                // Get the source
                ushort source = blendIndices.Source;
                Debug.Assert(blendIndices.Size + blendWeights.Size ==
                    vertexData.vertexBufferBinding.GetBuffer(source).VertexSize,
                    "Blend indices and blend buffers should have buffer to themselves!");
                // Unset the buffer
                vertexData.vertexBufferBinding.UnsetBinding(source);
                // Remove the elements
                vertexData.vertexDeclaration.RemoveElement(VertexElementSemantic.BlendIndices);
                vertexData.vertexDeclaration.RemoveElement(VertexElementSemantic.BlendWeights);
            }
        }
Beispiel #6
0
        public List <TriangleVertices> Build()
        {
            List <TriangleVertices> triangles = new  List <TriangleVertices>();

            try {
                for (int ind = 0, indexSet = 0; ind < indexDataList.Count; ind++, indexSet++)
                {
                    int vertexSet = (int)indexDataVertexDataSetList[ind];

                    IndexData     indexData = (IndexData)indexDataList[indexSet];
                    OperationType opType    = operationTypes[indexSet];

                    int iterations = 0;

                    switch (opType)
                    {
                    case OperationType.TriangleList:
                        iterations = indexData.indexCount / 3;
                        break;

                    case OperationType.TriangleFan:
                    case OperationType.TriangleStrip:
                        iterations = indexData.indexCount - 2;
                        break;
                    }

                    // locate position element & the buffer to go with it
                    VertexData    vertexData = (VertexData)vertexDataList[vertexSet];
                    VertexElement posElem    =
                        vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.Position);

                    HardwareVertexBuffer posBuffer = vertexData.vertexBufferBinding.GetBuffer(posElem.Source);
                    try {
                        IntPtr posPtr = posBuffer.Lock(BufferLocking.ReadOnly);
                        IntPtr idxPtr = indexData.indexBuffer.Lock(BufferLocking.ReadOnly);

                        unsafe {
                            byte *pBaseVertex = (byte *)posPtr.ToPointer();

                            ushort *p16Idx = null;
                            uint *  p32Idx = null;

                            // counters used for pointer indexing
                            int count16 = 0;
                            int count32 = 0;

                            if (indexData.indexBuffer.Type == IndexType.Size16)
                            {
                                p16Idx = (ushort *)idxPtr.ToPointer();
                            }
                            else
                            {
                                p32Idx = (uint *)idxPtr.ToPointer();
                            }

                            float *pReal = null;

                            int triStart = triangles.Count;

                            // iterate over all the groups of 3 indices
                            triangles.Capacity = triStart + iterations;

                            uint[] index = new uint[3];

                            for (int t = 0; t < iterations; t++)
                            {
                                Vector3[]        v      = new Vector3[3];
                                TriangleVertices tri    = new TriangleVertices(v);
                                bool             broken = false;
                                for (int i = 0; i < 3; i++)
                                {
                                    // Standard 3-index read for tri list or first tri in strip / fan
                                    if (opType == OperationType.TriangleList || t == 0)
                                    {
                                        if (indexData.indexBuffer.Type == IndexType.Size32)
                                        {
                                            index[i] = p32Idx[count32++];
                                        }
                                        else
                                        {
                                            index[i] = p16Idx[count16++];
                                        }
                                    }
                                    else
                                    {
                                        // Strips and fans are formed from last 2 indexes plus the
                                        // current one for triangles after the first
                                        if (indexData.indexBuffer.Type == IndexType.Size32)
                                        {
                                            index[i] = p32Idx[i - 2];
                                        }
                                        else
                                        {
                                            index[i] = p16Idx[i - 2];
                                        }

                                        // Perform single-index increment at the last tri index
                                        if (i == 2)
                                        {
                                            if (indexData.indexBuffer.Type == IndexType.Size32)
                                            {
                                                count32++;
                                            }
                                            else
                                            {
                                                count16++;
                                            }
                                        }
                                    }

                                    // Retrieve the vertex position
                                    if (index[i] >= posBuffer.VertexCount)
                                    {
                                        log.InfoFormat("TriangleListBuilder.Build: Error: index[i] {0} is not less than posBuffer.VertexCount {1}, iteration t {2}",
                                                       index[i], posBuffer.VertexCount, t);
                                        broken = true;
                                        break;
                                    }
                                    Debug.Assert(index[i] < posBuffer.VertexCount);
                                    byte *pVertex = pBaseVertex + (index[i] * posBuffer.VertexSize);
                                    pReal  = (float *)(pVertex + posElem.Offset);
                                    v[i].x = *pReal++;
                                    v[i].y = *pReal++;
                                    v[i].z = *pReal++;
                                }
                                if (!broken)
                                {
                                    // Put the points in in counter-clockwise order
                                    if (((v[0].x - v[2].x) * (v[1].y - v[2].y) - (v[1].x - v[2].x) * (v[0].y - v[2].y)) < 0)
                                    {
                                        // Clockwise, so reverse points 1 and 2
                                        Vector3 tmp = v[1];
                                        v[1] = v[2];
                                        v[2] = tmp;
                                    }
                                    // Debug.Assert(((v[0].x - v[2].x) * (v[1].y - v[2].y) - (v[1].x - v[2].x) * (v[0].y - v[2].y)) >= 0);
                                    // Add to the list of triangles
                                    triangles.Add(new TriangleVertices(v));
                                }
                            } // for iterations
                        }     // unsafe
                    }
                    finally {
                        // unlock those buffers!
                        indexData.indexBuffer.Unlock();
                        posBuffer.Unlock();
                    }
                }
                return(triangles);
            }
            catch (Exception e) {
                log.ErrorFormat("TriangleListBuilder.Build: Exception raised during triangle building: {0}", e.Message);
                triangles.Clear();
                return(triangles);
            }
        }
Beispiel #7
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="disposeManagedResources"></param>
        protected override void dispose(bool disposeManagedResources)
        {
            if (!this.IsDisposed)
            {
                if (disposeManagedResources)
                {
                    if (this.vertexData != null)
                    {
                        if (!this.vertexData.IsDisposed)
                            this.vertexData.Dispose();

                        this.vertexData = null;
                    }

                    if (this.indexData != null)
                    {
                        if (!this.indexData.IsDisposed)
                            this.indexData.Dispose();

                        this.indexData = null;
                    }
                }
            }

            base.dispose(disposeManagedResources);
        }
 public static void CopyIndexData(IndexData dst, IndexData src, Dictionary<uint, uint> vertexIdMap)
 {
     dst.indexStart = src.indexStart;
     dst.indexCount = src.indexCount;
     IndexType iType = IndexType.Size16;
     if (vertexIdMap.Count > ushort.MaxValue)
         iType = IndexType.Size32;
     HardwareIndexBuffer srcBuf = src.indexBuffer;
     HardwareIndexBuffer dstBuf =
         HardwareBufferManager.Instance.CreateIndexBuffer(iType, dst.indexCount, srcBuf.Usage);
     // TODO: copy the data
     IntPtr srcData = srcBuf.Lock(BufferLocking.ReadOnly);
     IntPtr dstData = dstBuf.Lock(BufferLocking.Discard);
     unsafe {
         if (srcBuf.IndexSize == 2 && dstBuf.IndexSize == 2) {
             ushort* srcPtr = (ushort *)srcData.ToPointer();
             ushort* dstPtr = (ushort *)dstData.ToPointer();
             for (int i = 0; i < srcBuf.IndexCount; ++i)
                 dstPtr[i] = (ushort)vertexIdMap[srcPtr[i]];
         } else if (srcBuf.IndexSize == 4 && dstBuf.IndexSize == 2) {
             uint* srcPtr = (uint *)srcData.ToPointer();
             ushort* dstPtr = (ushort *)dstData.ToPointer();
             for (int i = 0; i < srcBuf.IndexCount; ++i)
                 dstPtr[i] = (ushort)vertexIdMap[srcPtr[i]];
         } else if (srcBuf.IndexSize == 4 && dstBuf.IndexSize == 4) {
             uint* srcPtr = (uint *)srcData.ToPointer();
             uint* dstPtr = (uint *)dstData.ToPointer();
             for (int i = 0; i < srcBuf.IndexCount; ++i)
                 dstPtr[i] = vertexIdMap[srcPtr[i]];
         } else {
             throw new NotImplementedException();
         }
     }
     dstBuf.Unlock();
     srcBuf.Unlock();
     dst.indexBuffer = dstBuf;
 }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dstData"></param>
        /// <param name="orgdata"></param>
        /// <param name="indexData"></param>
        /// <param name="normals"></param>
        private unsafe void UpdateVertexDataNoiseAndNormals(VertexData dstData, VertexData orgData, IndexData indexData, float* normals)
        {
            // destination vertex buffer
            VertexElement dstPosElement = dstData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.Position);
            HardwareVertexBuffer dstPosBuffer = dstData.vertexBufferBinding.GetBuffer(dstPosElement.Source);

            // source vertex buffer
            VertexElement orgPosElement = orgData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.Position);
            HardwareVertexBuffer orgPosBuffer = orgData.vertexBufferBinding.GetBuffer(orgPosElement.Source);

            // lock the buffers
            IntPtr dstPosData = dstPosBuffer.Lock(BufferLocking.Discard);
            IntPtr orgPosData = orgPosBuffer.Lock(BufferLocking.ReadOnly);

            // get some raw pointer action goin on
            float* dstPosPtr = (float*)dstPosData.ToPointer();
            float* orgPosPtr = (float*)orgPosData.ToPointer();

            // make noise
            int numVerts = orgPosBuffer.VertexCount;

            for(int i = 0; i < 3 * numVerts; i += 3) {
                float n = 1 + displacement *
                    Noise3(orgPosPtr[i] / density + tm,
                                orgPosPtr[i + 1] / density + tm,
                                orgPosPtr[i + 2] / density + tm);

                dstPosPtr[i] = orgPosPtr[i] * n;
                dstPosPtr[i + 1] = orgPosPtr[i + 1] * n;
                dstPosPtr[i + 2] = orgPosPtr[i + 2] * n;
            } // for

            // unlock the original position buffer
            orgPosBuffer.Unlock();

            // calculate normals
            HardwareIndexBuffer indexBuffer = indexData.indexBuffer;

            short* vertexIndices = (short*)indexBuffer.Lock(BufferLocking.ReadOnly);
            int numFaces = indexData.indexCount / 3;

            for(int i = 0, index = 0; i < numFaces; i++, index += 3) {
                int p0 = vertexIndices[index];
                int p1 = vertexIndices[index + 1];
                int p2 = vertexIndices[index + 2];

                Vector3 v0 = new Vector3(dstPosPtr[3 * p0], dstPosPtr[3 * p0 + 1], dstPosPtr[3 * p0 + 2]);
                Vector3 v1 = new Vector3(dstPosPtr[3 * p1], dstPosPtr[3 * p1 + 1], dstPosPtr[3 * p1 + 2]);
                Vector3 v2 = new Vector3(dstPosPtr[3 * p2], dstPosPtr[3 * p2 + 1], dstPosPtr[3 * p2 + 2]);

                Vector3 diff1 = v1 - v2;
                Vector3 diff2 = v1 - v0;
                Vector3 fn = diff1.Cross(diff2);

                // update the normal of each vertex in the current face
                normals[3 * p0] += fn.x;
                normals[3 * p0 + 1] += fn.y;
                normals[3 * p0 + 2] += fn.z;

                normals[3 * p1] += fn.x;
                normals[3 * p1 + 1] += fn.y;
                normals[3 * p1 + 2] += fn.z;

                normals[3 * p2] += fn.x;
                normals[3 * p2 + 1] += fn.y;
                normals[3 * p2 + 2] += fn.z;
            }

            // unlock index buffer
            indexBuffer.Unlock();

            // unlock destination vertex buffer
            dstPosBuffer.Unlock();
        }
Beispiel #10
0
		/// <summary>
		/// Class level dispose method
		/// </summary>
		/// <remarks>
		/// When implementing this method in an inherited class the following template should be used;
		/// protected override void dispose( bool disposeManagedResources )
		/// {
		/// 	if ( !isDisposed )
		/// 	{
		/// 		if ( disposeManagedResources )
		/// 		{
		/// 			// Dispose managed resources.
		/// 		}
		///
		/// 		// There are no unmanaged resources to release, but
		/// 		// if we add them, they need to be released here.
		/// 	}
		///
		/// 	// If it is available, make the call to the
		/// 	// base class's Dispose(Boolean) method
		/// 	base.dispose( disposeManagedResources );
		/// }
		/// </remarks>
		/// <param name="disposeManagedResources">True if Unmanaged resources should be released.</param>
		protected override void dispose( bool disposeManagedResources )
		{
			if ( !IsDisposed )
			{
				if ( disposeManagedResources )
				{
					// Dispose managed resources.
					if ( renderOperation != null )
					{
                        if (!this.renderOperation.IsDisposed)
                            this.renderOperation.Dispose();

						renderOperation = null;
					}

                    if (indexData != null)
                    {
                        if (!indexData.IsDisposed)
                            indexData.Dispose();

                        indexData = null;
                    }

                    if (vertexData != null)
                    {
                        if (!vertexData.IsDisposed)
                            vertexData.Dispose();

                        vertexData = null;
                    }
				}

				// There are no unmanaged resources to release, but
				// if we add them, they need to be released here.
			}

            base.dispose(disposeManagedResources);
		}
        public unsafe void DebugLog(Log log)
        {
            log.Write("EdgeListBuilder Log");
            log.Write("-------------------");
            log.Write("Number of vertex sets: {0}", vertexDataList.Count);
            log.Write("Number of index sets: {0}", indexDataList.Count);

            int i, j;

            // Log original vertex data
            for (i = 0; i < vertexDataList.Count; i++)
            {
                VertexData vData = (VertexData)vertexDataList[i];
                log.Write(".");
                log.Write("Original vertex set {0} - vertex count {1}", i, vData.vertexCount);

                VertexElement posElem =
                    vData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.Position);
                HardwareVertexBuffer vbuf =
                    vData.vertexBufferBinding.GetBuffer(posElem.Source);

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

                byte *pBaseVertex = (byte *)basePtr.ToPointer();

                float *pReal;

                for (j = 0; j < vData.vertexCount; j++)
                {
                    pReal = (float *)(pBaseVertex + posElem.Offset);

                    log.Write("Vertex {0}: ({1}, {2}, {3})", j, pReal[0], pReal[1], pReal[2]);

                    pBaseVertex += vbuf.VertexSize;
                }

                vbuf.Unlock();
            }

            // Log original index data
            for (i = 0; i < indexDataList.Count; i += 3)
            {
                IndexData iData = (IndexData)indexDataList[i];
                log.Write(".");
                log.Write("Original triangle set {0} - index count {1} - vertex set {2})",
                          i, iData.indexCount, indexDataVertexDataSetList[i]);

                // Get the indexes ready for reading
                short *p16Idx = null;
                int *  p32Idx = null;

                IntPtr idxPtr = iData.indexBuffer.Lock(BufferLocking.ReadOnly);

                if (iData.indexBuffer.Type == IndexType.Size32)
                {
                    p32Idx = (int *)idxPtr.ToPointer();
                }
                else
                {
                    p16Idx = (short *)idxPtr.ToPointer();
                }

                for (j = 0; j < iData.indexCount / 3; j++)
                {
                    if (iData.indexBuffer.Type == IndexType.Size32)
                    {
                        log.Write("Triangle {0}: ({1}, {2}, {3})", j, *p32Idx++, *p32Idx++, *p32Idx++);
                    }
                    else
                    {
                        log.Write("Triangle {0}: ({1}, {2}, {3})", j, *p16Idx++, *p16Idx++, *p16Idx++);
                    }
                }

                iData.indexBuffer.Unlock();

                // Log common vertex list
                log.Write(".");
                log.Write("Common vertex list - vertex count {0}", vertices.Count);

                for (i = 0; i < vertices.Count; i++)
                {
                    CommonVertex c = (CommonVertex)vertices[i];

                    log.Write("Common vertex {0}: (vertexSet={1}, originalIndex={2}, position={3}",
                              i, c.vertexSet, c.index, c.position);
                }
            }
        }
Beispiel #12
0
		/// <summary>
		/// Add a set of index geometry data to the edge builder.
		/// </summary>
		/// <remarks>
		/// You must add at least one set of index data to the builder before invoking the
        /// <see name="Build"/> method.
		/// </remarks>
		/// <param name="indexData">The index information which describes the triangles.</param>
		public void AddIndexData( IndexData indexData )
		{
			AddIndexData( indexData, 0, OperationType.TriangleList );
		}
Beispiel #13
0
 public void AddIndexData(IndexData indexData, int vertexSet)
 {
     AddIndexData(indexData, vertexSet, OperationType.TriangleList);
 }
Beispiel #14
0
 /// <summary>
 /// Add a set of index geometry data to the edge builder.
 /// </summary>
 /// <remarks>
 /// You must add at least one set of index data to the builder before invoking the
 /// <see name="Build"/> method.
 /// </remarks>
 /// <param name="indexData">The index information which describes the triangles.</param>
 public void AddIndexData(IndexData indexData)
 {
     AddIndexData(indexData, 0, OperationType.TriangleList);
 }
		public unsafe IndexData GenerateTriListIndexes( uint stitchFlags )
		{

			int numIndexes = 0;
			int step = 1 << mRenderLevel;

			IndexData indexData;

			int north = ( stitchFlags & STITCH_NORTH ) != 0 ? step : 0;
			int south = ( stitchFlags & STITCH_SOUTH ) != 0 ? step : 0;
			int east = ( stitchFlags & STITCH_EAST ) != 0 ? step : 0;
			int west = ( stitchFlags & STITCH_WEST ) != 0 ? step : 0;

			int new_length = ( mOptions.tileSize / step ) * ( mOptions.tileSize / step ) * 2 * 2 * 2;
			//this is the maximum for a level.  It wastes a little, but shouldn't be a problem.

			indexData = new IndexData();
			indexData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer(
				IndexType.Size16,
				new_length, BufferUsage.StaticWriteOnly );//, false);

			mTerrainZone.IndexCache.mCache.Add( indexData );

			ushort* pIdx = (ushort*)indexData.indexBuffer.Lock( 0,
				indexData.indexBuffer.Size,
				BufferLocking.Discard );

			// Do the core vertices, minus stitches
			for ( int j = north; j < mOptions.tileSize - 1 - south; j += step )
			{
				for ( int i = west; i < mOptions.tileSize - 1 - east; i += step )
				{
					//triangles
					*pIdx++ = Index( i, j + step );
					numIndexes++; // original order: 2
					*pIdx++ = Index( i + step, j );
					numIndexes++; // original order: 3
					*pIdx++ = Index( i, j );
					numIndexes++; // original order: 1

					*pIdx++ = Index( i + step, j + step );
					numIndexes++; // original order: 2
					*pIdx++ = Index( i + step, j );
					numIndexes++; // original order: 3
					*pIdx++ = Index( i, j + step );
					numIndexes++; // original order: 1
				}
			}

			// North stitching
			if ( north > 0 )
			{
				numIndexes += StitchEdge( Neighbor.NORTH, mRenderLevel, mNeighbors[ (int)Neighbor.NORTH ].mRenderLevel,
					west > 0, east > 0, &pIdx );
			}
			// East stitching
			if ( east > 0 )
			{
				numIndexes += StitchEdge( Neighbor.EAST, mRenderLevel, mNeighbors[ (int)Neighbor.EAST ].mRenderLevel,
					north > 0, south > 0, &pIdx );
			}
			// South stitching
			if ( south > 0 )
			{
				numIndexes += StitchEdge( Neighbor.SOUTH, mRenderLevel, mNeighbors[ (int)Neighbor.SOUTH ].mRenderLevel,
					east > 0, west > 0, &pIdx );
			}
			// West stitching
			if ( west > 0 )
			{
				numIndexes += StitchEdge( Neighbor.WEST, mRenderLevel, mNeighbors[ (int)Neighbor.WEST ].mRenderLevel,
					south > 0, north > 0, &pIdx );
			}


			indexData.indexBuffer.Unlock();
			indexData.indexCount = numIndexes;
			indexData.indexStart = 0;

			return indexData;
		}
Beispiel #16
0
		private void DestroyBuffers()
		{
			//             LogManager.Instance.Write(string.Format("BillBoardSet.DestroyBuffers entered; vertexData {0}, indexData {1}, mainBuffer {2}",
			//                     vertexData == null ? "null" : vertexData.ToString(),
			//                     indexData == null ? "null" : indexData.ToString(),
			//                     mainBuffer == null ? "null" : mainBuffer.ToString()));
			this.vertexData = null;
			this.indexData = null;
			this.mainBuffer = null;
			this.buffersCreated = false;
		}
        private void buildIndexData()
        {
            indexData = new IndexData();

            int bufLength = width * height * 6;

            IndexType idxType = IndexType.Size32;

            if ((width * height) <= ushort.MaxValue)
                idxType = IndexType.Size16;

            indexData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer(
                    idxType, bufLength, BufferUsage.StaticWriteOnly);

            IntPtr indexBufferPtr = indexData.indexBuffer.Lock(0, indexData.indexBuffer.Size, BufferLocking.Discard);
            int indexCount = 0;

            int pos = 0;
            int i = 0;
            unsafe
            {
                if (idxType == IndexType.Size16) {
                    ushort* indexBuffer = (ushort*)indexBufferPtr.ToPointer();
                    for (int z = 0; z < height - 1; z++) {
                        for (int x = 0; x < width - 1; x++) {
                            indexBuffer[pos++] = (ushort)i;
                            indexBuffer[pos++] = (ushort)(i + width);
                            indexBuffer[pos++] = (ushort)(i + 1);

                            indexBuffer[pos++] = (ushort)(i + width);
                            indexBuffer[pos++] = (ushort)(i + 1 + width);
                            indexBuffer[pos++] = (ushort)(i + 1);

                            i++;
                            indexCount += 6;
                        }

                        i++;
                    }
                } else {
                    uint* indexBuffer = (uint*)indexBufferPtr.ToPointer();
                    for (int z = 0; z < height - 1; z++) {
                        for (int x = 0; x < width - 1; x++) {
                            indexBuffer[pos++] = (uint)i;
                            indexBuffer[pos++] = (uint)(i + width);
                            indexBuffer[pos++] = (uint)(i + 1);

                            indexBuffer[pos++] = (uint)(i + width);
                            indexBuffer[pos++] = (uint)(i + 1 + width);
                            indexBuffer[pos++] = (uint)(i + 1);

                            i++;
                            indexCount += 6;
                        }

                        i++;
                    }
                }
            }

            indexData.indexBuffer.Unlock();
            indexData.indexCount = indexCount;
            indexData.indexStart = 0;

            return;
        }
Beispiel #18
0
 /// <summary>
 /// Add a set of index geometry data to the edge builder.
 /// </summary>
 /// <remarks>
 /// You must add at least one set of index data to the builder before invoking the
 /// <see name="Build"/> method.
 /// </remarks>
 /// <param name="indexData">The index information which describes the triangles.</param>
 /// <param name="vertexSet">
 /// The vertex data set this index data refers to; you only need to alter this
 /// if you have added multiple sets of vertices.
 /// </param>
 /// <param name="opType"></param>
 public void AddIndexData(IndexData indexData, int vertexSet, OperationType opType)
 {
     this.indexDataList.Add(indexData);
     this.indexDataVertexDataSetList.Add(vertexSet);
     this.operationTypes.Add(opType);
 }
Beispiel #19
0
	    /// <summary>
	    /// Add a set of index geometry data to the edge builder.
	    /// </summary>
	    /// <remarks>
	    /// You must add at least one set of index data to the builder before invoking the
	    /// <see name="Build"/> method.
	    /// </remarks>
	    /// <param name="indexData">The index information which describes the triangles.</param>
	    /// <param name="vertexSet">
	    /// The vertex data set this index data refers to; you only need to alter this
	    /// if you have added multiple sets of vertices.
	    /// </param>
	    /// <param name="opType"></param>
	    public void AddIndexData( IndexData indexData, int vertexSet, OperationType opType )
		{
			indexDataList.Add( indexData );
			indexDataVertexDataSetList.Add( vertexSet );
			operationTypes.Add( opType );
		}
Beispiel #20
0
        /// <summary>
        /// Populate with data as obtained from an IRenderable.
        /// </summary>
        /// <remarks>
        /// Will share the buffers.
        /// In case there are no index data associated with the <see cref="IRenderable"/>, i.e. <see cref="RenderOperation.useIndices"/> is false,
        /// custom software index buffer is created to provide default index data to the builder.
        /// This makes it possible for derived classes to handle the data in a convenient way.
        /// </remarks>
        public void AddObject(IRenderable obj)
        {
            if (obj == null)
            {
                throw new ArgumentNullException();
            }

            var renderOp = obj.RenderOperation;

            IndexData indexData;

            if (renderOp.useIndices)
            {
                indexData = renderOp.indexData;
            }
            else
            {
                //Create custom index buffer
                var vertexCount = renderOp.vertexData.vertexCount;
                var itype       = vertexCount > UInt16.MaxValue ? IndexType.Size32 : IndexType.Size16;

                var ibuf = new DefaultHardwareIndexBuffer(itype, vertexCount, BufferUsage.Static);
                this.customIndexBufferList.Add(ibuf); //to be disposed later

                indexData             = new IndexData();
                indexData.indexBuffer = ibuf;
                indexData.indexCount  = vertexCount;
                indexData.indexStart  = 0;

                //Fill buffer with indices
                var ibuffer = indexData.indexBuffer.Lock(BufferLocking.Normal);
                try
                {
#if !AXIOM_SAFE_ONLY
                    unsafe
#endif
                    {
                        var ibuf16 = ibuffer.ToShortPointer();
                        var ibuf32 = ibuffer.ToIntPointer();
                        for (var i = 0; i < indexData.indexCount; i++)
                        {
                            if (itype == IndexType.Size16)
                            {
                                ibuf16[i] = (Int16)i;
                            }
                            else
                            {
                                ibuf32[i] = i;
                            }
                        }
                    } //unsafe
                }
                finally
                {
                    indexData.indexBuffer.Unlock();
                }
            }

            AddVertexData(renderOp.vertexData);
            AddIndexData(indexData, this.vertexDataList.Count - 1, renderOp.operationType);
        }
        /// <summary>
        ///    Builds the progressive mesh with the specified number of levels.
        /// </summary>
        public void Build(ushort numLevels, List<IndexData> lodFaceList, VertexReductionQuota quota, float reductionValue)
        {
            ComputeAllCosts();
            // Init
            currNumIndexes = (uint)indexData.indexCount;
            // Use COMMON vert count, not original vert count
            // Since collapsing 1 common vert position is equivalent to collapsing them all
            uint numVerts = numCommonVertices;

            uint numCollapses = 0;
            bool abandon = false;

            while (numLevels-- != 0) {
                // NB if 'abandon' is set, we stop reducing
                // However, we still bake the number of LODs requested, even if it
                // means they are the same
                if (!abandon) {
                    if (quota == VertexReductionQuota.Proportional)
                        numCollapses = (uint)(numVerts * reductionValue);
                    else
                        numCollapses = (uint)reductionValue;
                    // Minimum 3 verts!
                    if ((numVerts - numCollapses) < 3)
                        numCollapses = numVerts - 3;
                    // Store new number of verts
                    numVerts = numVerts - numCollapses;

                    Debug.Assert(numVerts >= 3);
                    while (numCollapses-- !=  0 && !abandon) {
                        int nextIndex = GetNextCollapser();
                        // Collapse on every buffer
                        foreach (PMWorkingData data in workingDataList) {
                            PMVertex collapser = data.vertList[nextIndex];
                            // This will reduce currNumIndexes and recalc costs as required
                            if (collapser.collapseTo == null) {
                                // Must have run out of valid collapsables
                                abandon = true;
                                break;
                            }
                            Debug.Assert(collapser.collapseTo.removed == false);

                            Collapse(collapser);
                        }
                    }
                }

                // Bake a new LOD and add it to the list
                IndexData newLod = new IndexData();
                BakeNewLOD(newLod);
                lodFaceList.Add(newLod);
            }
        }
        /// <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();
        }
Beispiel #23
0
		public BillboardChain( string name, int maxElements, int numberOfChains, bool useTextureCoords, bool useColors, bool dynamic )
			: base( name )
		{
			this.maxElementsPerChain = maxElements;
			this.chainCount = numberOfChains;
			this.useTexCoords = useTextureCoords;
			this.useVertexColor = useColors;
			this.dynamic = dynamic;

			this.vertexDeclDirty = true;
			this.buffersNeedRecreating = true;
			this.boundsDirty = true;
			this.indexContentDirty = true;
			this.radius = 0.0f;
			this.texCoordDirection = TexCoordDirection.U;

			this.vertexData = new VertexData();
			this.indexData = new IndexData();

			this.otherTexCoordRange[ 0 ] = 0.0f;
			this.otherTexCoordRange[ 1 ] = 1.0f;

			this.SetupChainContainers();

			this.vertexData.vertexStart = 0;
			// index data setup later
			// set basic white material
			this.MaterialName = "BaseWhiteNoLighting";
		}
        /// <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();
        }
Beispiel #25
0
		/// <summary>
		/// Populate with data as obtained from an IRenderable.
		/// </summary>
		/// <remarks>
		/// Will share the buffers.
		/// In case there are no index data associated with the <see cref="IRenderable"/>, i.e. <see cref="RenderOperation.useIndices"/> is false,
		/// custom software index buffer is created to provide default index data to the builder.
		/// This makes it possible for derived classes to handle the data in a convenient way.
		/// </remarks>
		public void AddObject( IRenderable obj )
		{
			if ( obj == null )
			{
				throw new ArgumentNullException();
			}

			var renderOp = obj.RenderOperation;

			IndexData indexData;
			if ( renderOp.useIndices )
			{
				indexData = renderOp.indexData;
			}
			else
			{
				//Create custom index buffer
				var vertexCount = renderOp.vertexData.vertexCount;
				var itype = vertexCount > UInt16.MaxValue ? IndexType.Size32 : IndexType.Size16;

				var ibuf = new DefaultHardwareIndexBuffer( itype, vertexCount, BufferUsage.Static );
				this.customIndexBufferList.Add( ibuf ); //to be disposed later

				indexData = new IndexData();
				indexData.indexBuffer = ibuf;
				indexData.indexCount = vertexCount;
				indexData.indexStart = 0;

				//Fill buffer with indices
				var ibuffer = indexData.indexBuffer.Lock( BufferLocking.Normal );
				try
				{
#if !AXIOM_SAFE_ONLY
					unsafe
#endif
					{
						var ibuf16 = ibuffer.ToShortPointer();
						var ibuf32 = ibuffer.ToIntPointer();
						for ( var i = 0; i < indexData.indexCount; i++ )
						{
							if ( itype == IndexType.Size16 )
							{
								ibuf16[ i ] = (Int16)i;
							}
							else
							{
								ibuf32[ i ] = i;
							}
						}
					} //unsafe
				}
				finally
				{
					indexData.indexBuffer.Unlock();
				}
			}

			AddVertexData( renderOp.vertexData );
			AddIndexData( indexData, this.vertexDataList.Count - 1, renderOp.operationType );
		}
 /// <summary>
 ///    Constructor, takes the geometry data and index buffer. 
 /// </summary>
 /// <remarks>
 ///    DO NOT pass write-only, unshadowed buffers to this method! They will not
 ///    work. Pass only shadowed buffers, or better yet perform mesh reduction as
 ///    an offline process using DefaultHardwareBufferManager to manage vertex
 ///    buffers in system memory.
 /// </remarks>
 /// <param name="vertexData"></param>
 /// <param name="indexData"></param>
 public ProgressiveMesh(VertexData vertexData, IndexData indexData)
 {
     AddWorkingData(vertexData, indexData);
     this.vertexData = vertexData;
     this.indexData = indexData;
 }
 protected void AddSubmeshIndexData(IndexData indexData)
 {
     HardwareIndexBuffer indexBuffer = indexData.indexBuffer;
     IntPtr indices = indexBuffer.Lock(BufferLocking.ReadOnly);
     unsafe {
         if (indexBuffer.IndexSize == sizeof(ushort)) {
             ushort *pIdx = (ushort*)indices.ToPointer();
             for (int i = 0; i < indexData.indexCount; ++i) {
                 uint index = pIdx[indexData.indexStart + i];
                 if (!vertexIdMap.ContainsKey(index)) {
                     uint nextId = (uint)vertexIdMap.Count;
                     vertexIdMap[index] = nextId;
                 }
             }
         } else if (indexBuffer.IndexSize == sizeof(uint)) {
             uint *pIdx = (uint*)indices.ToPointer();
             for (int i = 0; i < indexData.indexCount; ++i) {
                 uint index = pIdx[indexData.indexStart + i];
                 if (!vertexIdMap.ContainsKey(index)) {
                     uint nextId = (uint)vertexIdMap.Count;
                     vertexIdMap[index] = nextId;
                 }
             }
         } else {
             Debug.Assert(false, "Invalid index buffer index size");
         }
     }
     indexBuffer.Unlock();
 }
        /// <summary>
        ///		Internal constructor, only allows creation of StitchRenderables within the scene manager.
        /// </summary>
        internal StitchRenderable(TerrainPatch terrainPatch, VertexData vertexData, IndexData indexData, 
			int numSamples, int southMetersPerSample, int eastMetersPerSample)
        {
            renderDetail = SceneDetailLevel.Solid;
            parent = terrainPatch;

            renderOp = new RenderOperation();
            renderOp.operationType = OperationType.TriangleList;
            renderOp.useIndices = true;
            renderOp.vertexData = vertexData;
            renderOp.indexData = indexData;

            isVisible = true;
            this.numSamples = numSamples;
            this.southMetersPerSample = southMetersPerSample;
            this.eastMetersPerSample = eastMetersPerSample;
        }
        /// Internal method for generating triangle list terrain indexes
        public IndexData GenerateTriListIndexes( long stitchFlags, long RenderLevel, Renderable[] neighbors)
        {
            long step = (1L << (int)RenderLevel);
            long north = ((stitchFlags & (long)Stitch_Direction.North) != 0 ? step : 0);
            long south = ((stitchFlags & (long)Stitch_Direction.South) != 0 ? step : 0);
            long east =  ((stitchFlags & (long)Stitch_Direction.East)  != 0 ? step : 0);
            long west =  ((stitchFlags & (long)Stitch_Direction.West)  != 0 ? step : 0);

            long new_length = ( tileSize * tileSize * 6 ) / step;

            IndexData indexData = new IndexData();
            indexData.indexBuffer =
            HardwareBufferManager.Instance.CreateIndexBuffer(IndexType.Size16, (int)new_length, BufferUsage.StaticWriteOnly);

            cache.Add( indexData );

            /** Returns the index into the height array for the given coordinates. */
            IntPtr ipIdx = indexData.indexBuffer.Lock(0,indexData.indexBuffer.Size,BufferLocking.Discard);
            numIndexes = 0;

            long pos = 0;
            long step_offset = step * tileSize;
            long height_count = north * tileSize;
            unsafe
            {
                ushort* pIdx = (ushort *)ipIdx.ToPointer();
                for (long j = north; j < tileSize - 1 - south; j += step )
                {
                    for (long i = west; i <  tileSize - 1 - east; i += step )
                    {
                        //triangles

                        pIdx[pos++] = (ushort) (i        + height_count);                 numIndexes++;
                        pIdx[pos++] = (ushort) (i        + height_count + step_offset);   numIndexes++;
                        pIdx[pos++] = (ushort) (i + step + height_count);                 numIndexes++;

                        pIdx[pos++] = (ushort) (i        + height_count + step_offset);   numIndexes++;
                        pIdx[pos++] = (ushort) (i + step + height_count + step_offset);   numIndexes++;
                        pIdx[pos++] = (ushort) (i + step + height_count);                 numIndexes++;

                    }
                    height_count += step_offset;
                }

            }

            // North stitching
            if ( north != 0 )
            {
                numIndexes += StitchEdge(Neighbor.North, RenderLevel, neighbors[(int)Neighbor.North].RenderLevel,
                    west > 0 , east > 0 , ipIdx,ref pos);
            }
            // East stitching
            if ( east != 0 )
            {
                numIndexes += StitchEdge(Neighbor.East, RenderLevel, neighbors[(int)Neighbor.East].RenderLevel,
                    north > 0, south > 0, ipIdx,ref pos);
            }
            // South stitching
            if ( south != 0 )
            {
                numIndexes += StitchEdge(Neighbor.South, RenderLevel, neighbors[(int)Neighbor.South].RenderLevel,
                    east > 0 , west > 0, ipIdx,ref pos);
            }
            // West stitching
            if ( west != 0 )
            {
                numIndexes += StitchEdge(Neighbor.West, RenderLevel, neighbors[(int)Neighbor.West].RenderLevel,
                    south > 0 , north > 0, ipIdx,ref pos);
            }

            indexData.indexBuffer.Unlock();
            indexData.indexCount = (int)numIndexes;
            indexData.indexStart = 0;

            return indexData;
        }
		public IndexData GenerateTriStripIndexes( uint stitchFlags )
		{
			// The step used for the current level
			var step = 1 << this.mRenderLevel;
			// The step used for the lower level
			var lowstep = 1 << ( this.mRenderLevel + 1 );

			var numIndexes = 0;

			// Calculate the number of indexes required
			// This is the number of 'cells' at this detail level x 2
			// plus 3 degenerates to turn corners
			var numTrisAcross = ( ( ( this.mOptions.tileSize - 1 )/step )*2 ) + 3;
			// Num indexes is number of tris + 2
			var new_length = numTrisAcross*( ( this.mOptions.tileSize - 1 )/step ) + 2;
			//this is the maximum for a level.  It wastes a little, but shouldn't be a problem.

			var indexData = new IndexData();
			indexData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size16, new_length,
			                                                                          BufferUsage.StaticWriteOnly ); //, false);

			this.mTerrainZone.IndexCache.mCache.Add( indexData );
#if !AXIOM_SAFE_ONLY
			unsafe
#endif
			{
				var pIdx = indexData.indexBuffer.Lock( 0, indexData.indexBuffer.Size, BufferLocking.Discard ).ToUShortPointer();
				var idx = 0;

				// Stripified mesh
				for ( var j = 0; j < this.mOptions.tileSize - 1; j += step )
				{
					int i;
					// Forward strip
					// We just do the |/ here, final | done after
					for ( i = 0; i < this.mOptions.tileSize - 1; i += step )
					{
						var x = new int[4];
						var y = new int[4];
						x[ 0 ] = x[ 1 ] = i;
						x[ 2 ] = x[ 3 ] = i + step;
						y[ 0 ] = y[ 2 ] = j;
						y[ 1 ] = y[ 3 ] = j + step;

						if ( j == 0 && ( stitchFlags & STITCH_NORTH ) != 0 )
						{
							// North reduction means rounding x[0] and x[2]
							if ( x[ 0 ]%lowstep != 0 )
							{
								// Since we know we only drop down one level of LOD,
								// removing 1 step of higher LOD should return to lower
								x[ 0 ] -= step;
							}
							if ( x[ 2 ]%lowstep != 0 )
							{
								x[ 2 ] -= step;
							}
						}

						// Never get a south tiling on a forward strip (always finish on
						// a backward strip)

						if ( i == 0 && ( stitchFlags & STITCH_WEST ) != 0 )
						{
							// West reduction means rounding y[0] / y[1]
							if ( y[ 0 ]%lowstep != 0 )
							{
								y[ 0 ] -= step;
							}
							if ( y[ 1 ]%lowstep != 0 )
							{
								y[ 1 ] -= step;
							}
						}
						if ( i == ( this.mOptions.tileSize - 1 - step ) && ( stitchFlags & STITCH_EAST ) != 0 )
						{
							// East tiling means rounding y[2] & y[3]
							if ( y[ 2 ]%lowstep != 0 )
							{
								y[ 2 ] -= step;
							}
							if ( y[ 3 ]%lowstep != 0 )
							{
								y[ 3 ] -= step;
							}
						}

						//triangles
						if ( i == 0 )
						{
							// Starter
							pIdx[ idx++ ] = (ushort)Index( x[ 0 ], y[ 0 ] );
							numIndexes++;
						}
						pIdx[ idx++ ] = (ushort)Index( x[ 1 ], y[ 1 ] );
						numIndexes++;
						pIdx[ idx++ ] = (ushort)Index( x[ 2 ], y[ 2 ] );
						numIndexes++;

						if ( i == this.mOptions.tileSize - 1 - step )
						{
							// Emit extra index to finish row
							pIdx[ idx++ ] = (ushort)Index( x[ 3 ], y[ 3 ] );
							numIndexes++;
							if ( j < this.mOptions.tileSize - 1 - step )
							{
								// Emit this index twice more (this is to turn around without
								// artefacts)
								// ** Hmm, looks like we can drop this and it's unnoticeable
								// *pIdx++ = ( ushort ) Index( x[ 3 ], y[ 3 ] ); numIndexes++;
								// *pIdx++ = ( ushort ) Index( x[ 3 ], y[ 3 ] ); numIndexes++;
							}
						}
					}
					// Increment row
					j += step;
					// Backward strip
					for ( i = this.mOptions.tileSize - 1; i > 0; i -= step )
					{
						var x = new int[4];
						var y = new int[4];
						x[ 0 ] = x[ 1 ] = i;
						x[ 2 ] = x[ 3 ] = i - step;
						y[ 0 ] = y[ 2 ] = j;
						y[ 1 ] = y[ 3 ] = j + step;

						// Never get a north tiling on a backward strip (always
						// start on a forward strip)
						if ( j == ( this.mOptions.tileSize - 1 - step ) && ( stitchFlags & STITCH_SOUTH ) != 0 )
						{
							// South reduction means rounding x[1] / x[3]
							if ( x[ 1 ]%lowstep != 0 )
							{
								x[ 1 ] -= step;
							}
							if ( x[ 3 ]%lowstep != 0 )
							{
								x[ 3 ] -= step;
							}
						}

						if ( i == step && ( stitchFlags & STITCH_WEST ) != 0 )
						{
							// West tiling on backward strip is rounding of y[2] / y[3]
							if ( y[ 2 ]%lowstep != 0 )
							{
								y[ 2 ] -= step;
							}
							if ( y[ 3 ]%lowstep != 0 )
							{
								y[ 3 ] -= step;
							}
						}
						if ( i == this.mOptions.tileSize - 1 && ( stitchFlags & STITCH_EAST ) != 0 )
						{
							// East tiling means rounding y[0] and y[1] on backward strip
							if ( y[ 0 ]%lowstep != 0 )
							{
								y[ 0 ] -= step;
							}
							if ( y[ 1 ]%lowstep != 0 )
							{
								y[ 1 ] -= step;
							}
						}

						//triangles
						if ( i == this.mOptions.tileSize )
						{
							// Starter
							pIdx[ idx++ ] = (ushort)Index( x[ 0 ], y[ 0 ] );
							numIndexes++;
						}
						pIdx[ idx++ ] = (ushort)Index( x[ 1 ], y[ 1 ] );
						numIndexes++;
						pIdx[ idx++ ] = (ushort)Index( x[ 2 ], y[ 2 ] );
						numIndexes++;

						if ( i == step )
						{
							// Emit extra index to finish row
							pIdx[ idx++ ] = (ushort)Index( x[ 3 ], y[ 3 ] );
							numIndexes++;
							if ( j < this.mOptions.tileSize - 1 - step )
							{
								// Emit this index once more (this is to turn around)
								pIdx[ idx++ ] = (ushort)Index( x[ 3 ], y[ 3 ] );
								numIndexes++;
							}
						}
					}
				}
			}


			indexData.indexBuffer.Unlock();
			indexData.indexCount = numIndexes;
			indexData.indexStart = 0;

			return indexData;
		}
Beispiel #31
0
		/// <summary>
		///     Allocate / reallocate vertex data
		///     Note that we allocate enough space for ALL the billboards in the pool, but only issue
		///     rendering operations for the sections relating to the active billboards
		/// </summary>
		private void CreateBuffers()
		{
			/* Alloc positions   ( 1 or 4 verts per billboard, 3 components )
					 colours     ( 1 x RGBA per vertex )
					 indices     ( 6 per billboard ( 2 tris ) if not point rendering )
					 tex. coords ( 2D coords, 1 or 4 per billboard )
			*/

			//             LogManager.Instance.Write(string.Format("BillBoardSet.CreateBuffers entered; vertexData {0}, indexData {1}, mainBuffer {2}",
			//                     vertexData == null ? "null" : vertexData.ToString(),
			//                     indexData == null ? "null" : indexData.ToString(),
			//                     mainBuffer == null ? "null" : mainBuffer.ToString()));

			// Warn if user requested an invalid setup
			// Do it here so it only appears once
			if ( this.pointRendering && this.billboardType != BillboardType.Point )
			{
				LogManager.Instance.Write(
						"Warning: BillboardSet {0} has point rendering enabled but is using a type " +
						"other than BillboardType.Point, this may not give you the results you " +
						"expect.",
						this.name );
			}

			this.vertexData = new VertexData();
			if ( this.pointRendering )
			{
				this.vertexData.vertexCount = this.poolSize;
			}
			else
			{
				this.vertexData.vertexCount = this.poolSize * 4;
			}

			this.vertexData.vertexStart = 0;

			// Vertex declaration
			VertexDeclaration decl = this.vertexData.vertexDeclaration;
			VertexBufferBinding binding = this.vertexData.vertexBufferBinding;

			int offset = 0;
			decl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Position );
			offset += VertexElement.GetTypeSize( VertexElementType.Float3 );
			decl.AddElement( 0, offset, VertexElementType.Color, VertexElementSemantic.Diffuse );
			offset += VertexElement.GetTypeSize( VertexElementType.Color );
			// Texture coords irrelevant when enabled point rendering (generated
			// in point sprite mode, and unused in standard point mode)
			if ( !this.pointRendering )
			{
				decl.AddElement( 0, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 0 );
			}

			this.mainBuffer =
					HardwareBufferManager.Instance.CreateVertexBuffer( decl.Clone( 0 ), this.vertexData.vertexCount, BufferUsage.DynamicWriteOnlyDiscardable );

			// bind position and diffuses
			binding.SetBinding( 0, this.mainBuffer );

			if ( !this.pointRendering )
			{
				this.indexData = new IndexData();

				// calc index buffer size
				this.indexData.indexStart = 0;
				this.indexData.indexCount = this.poolSize * 6;

				// create the index buffer
				this.indexData.indexBuffer =
						HardwareBufferManager.Instance.CreateIndexBuffer(
								IndexType.Size16,
								this.indexData.indexCount,
								BufferUsage.StaticWriteOnly );

				/* Create indexes (will be the same every frame)
				   Using indexes because it means 1/3 less vertex transforms (4 instead of 6)

				   Billboard layout relative to camera:

					0-----1
					|    /|
					|  /  |
					|/    |
					2-----3
				*/

				// lock the index buffer
				IntPtr idxPtr = this.indexData.indexBuffer.Lock( BufferLocking.Discard );

				unsafe
				{
					ushort* pIdx = (ushort*)idxPtr.ToPointer();

					for ( int idx, idxOffset, bboard = 0; bboard < this.poolSize; ++bboard )
					{
						// Do indexes
						idx = bboard * 6;
						idxOffset = bboard * 4;

						pIdx[ idx ] = (ushort)idxOffset; // + 0;, for clarity
						pIdx[ idx + 1 ] = (ushort)( idxOffset + 2 );
						pIdx[ idx + 2 ] = (ushort)( idxOffset + 1 );
						pIdx[ idx + 3 ] = (ushort)( idxOffset + 1 );
						pIdx[ idx + 4 ] = (ushort)( idxOffset + 2 );
						pIdx[ idx + 5 ] = (ushort)( idxOffset + 3 );
					} // for
				} // unsafe

				// unlock the buffers
				this.indexData.indexBuffer.Unlock();
			}
			this.buffersCreated = true;
		}
		public IndexData GenerateTriListIndexes( uint stitchFlags )
#endif
		{
			var numIndexes = 0;
			var step = 1 << this.mRenderLevel;

			IndexData indexData;

			var north = ( stitchFlags & STITCH_NORTH ) != 0 ? step : 0;
			var south = ( stitchFlags & STITCH_SOUTH ) != 0 ? step : 0;
			var east = ( stitchFlags & STITCH_EAST ) != 0 ? step : 0;
			var west = ( stitchFlags & STITCH_WEST ) != 0 ? step : 0;

			var new_length = ( this.mOptions.tileSize/step )*( this.mOptions.tileSize/step )*2*2*2;
			//this is the maximum for a level.  It wastes a little, but shouldn't be a problem.

			indexData = new IndexData();
			indexData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size16, new_length,
			                                                                          BufferUsage.StaticWriteOnly ); //, false);

			this.mTerrainZone.IndexCache.mCache.Add( indexData );

			var ppIdx = indexData.indexBuffer.Lock( 0, indexData.indexBuffer.Size, BufferLocking.Discard );
			var pIdx = ppIdx.ToUShortPointer();
			var idx = 0;

			// Do the core vertices, minus stitches
			for ( var j = north; j < this.mOptions.tileSize - 1 - south; j += step )
			{
				for ( var i = west; i < this.mOptions.tileSize - 1 - east; i += step )
				{
					//triangles
					pIdx[ idx++ ] = Index( i, j + step );
					numIndexes++; // original order: 2
					pIdx[ idx++ ] = Index( i + step, j );
					numIndexes++; // original order: 3
					pIdx[ idx++ ] = Index( i, j );
					numIndexes++; // original order: 1

					pIdx[ idx++ ] = Index( i + step, j + step );
					numIndexes++; // original order: 2
					pIdx[ idx++ ] = Index( i + step, j );
					numIndexes++; // original order: 3
					pIdx[ idx++ ] = Index( i, j + step );
					numIndexes++; // original order: 1
				}
			}

			ppIdx.Ptr += idx*sizeof ( ushort );

			// North stitching
			if ( north > 0 )
			{
				numIndexes += StitchEdge( Neighbor.NORTH, this.mRenderLevel, this.mNeighbors[ (int)Neighbor.NORTH ].mRenderLevel,
				                          west > 0,
				                          east > 0, ppIdx );
			}
			// East stitching
			if ( east > 0 )
			{
				numIndexes += StitchEdge( Neighbor.EAST, this.mRenderLevel, this.mNeighbors[ (int)Neighbor.EAST ].mRenderLevel,
				                          north > 0,
				                          south > 0, ppIdx );
			}
			// South stitching
			if ( south > 0 )
			{
				numIndexes += StitchEdge( Neighbor.SOUTH, this.mRenderLevel, this.mNeighbors[ (int)Neighbor.SOUTH ].mRenderLevel,
				                          east > 0,
				                          west > 0, ppIdx );
			}
			// West stitching
			if ( west > 0 )
			{
				numIndexes += StitchEdge( Neighbor.WEST, this.mRenderLevel, this.mNeighbors[ (int)Neighbor.WEST ].mRenderLevel,
				                          south > 0,
				                          north > 0, ppIdx );
			}


			indexData.indexBuffer.Unlock();
			indexData.indexCount = numIndexes;
			indexData.indexStart = 0;

			return indexData;
		}
		protected virtual void ReadMeshLodUsageGenerated( BinaryReader reader, int lodNum, ref MeshLodUsage usage )
		{
			usage.ManualName = "";
			usage.ManualMesh = null;

			// get one set of detail per submesh
			MeshChunkID chunkId;

			for ( var i = 0; i < this.mesh.SubMeshCount; i++ )
			{
				chunkId = ReadChunk( reader );

				if ( chunkId != MeshChunkID.MeshLODGenerated )
				{
					throw new AxiomException( "Missing MeshLodGenerated chunk in '{0}'", this.mesh.Name );
				}

				// get the current submesh
				var sm = this.mesh.GetSubMesh( i );

				// drop another index data object into the list
				var indexData = new IndexData();
				sm.lodFaceList[ lodNum - 1 ] = indexData;

				// number of indices
				indexData.indexCount = ReadInt( reader );

				var is32bit = ReadBool( reader );

				// create an appropriate index buffer and stuff in the data
				if ( is32bit )
				{
					indexData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size32, indexData.indexCount,
					                                                                          this.mesh.IndexBufferUsage,
					                                                                          this.mesh.UseIndexShadowBuffer );

					// lock the buffer
					var data = indexData.indexBuffer.Lock( BufferLocking.Discard );

					// stuff the data into the index buffer
					ReadInts( reader, indexData.indexCount, data );

					// unlock the index buffer
					indexData.indexBuffer.Unlock();
				}
				else
				{
					indexData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size16, indexData.indexCount,
					                                                                          this.mesh.IndexBufferUsage,
					                                                                          this.mesh.UseIndexShadowBuffer );

					// lock the buffer
					var data = indexData.indexBuffer.Lock( BufferLocking.Discard );

					// stuff the data into the index buffer
					ReadShorts( reader, indexData.indexCount, data );

					// unlock the index buffer
					indexData.indexBuffer.Unlock();
				}
			}
		}
Beispiel #34
0
		/// <summary>
		/// 
		/// </summary>
		protected void Initialize()
		{
			// Create geometry
			int nvertices = this.slices*4; // n+1 planes
			int elemsize = 3*3;
			int dsize = elemsize*nvertices;
			int x;

			var indexData = new IndexData();
			var vertexData = new VertexData();
			var vertices = new float[dsize];

			var coords = new float[4,2]
			             {
			             	{
			             		0.0f, 0.0f
			             	}, {
			             	   	0.0f, 1.0f
			             	   }, {
			             	      	1.0f, 0.0f
			             	      }, {
			             	         	1.0f, 1.0f
			             	         }
			             };

			for ( x = 0; x < this.slices; x++ )
			{
				for ( int y = 0; y < 4; y++ )
				{
					float xcoord = coords[ y, 0 ] - 0.5f;
					float ycoord = coords[ y, 1 ] - 0.5f;
					float zcoord = -( (float)x/(float)( this.slices - 1 ) - 0.5f );
					// 1.0f .. a/(a+1)
					// coordinate
					vertices[ x*4*elemsize + y*elemsize + 0 ] = xcoord*( this.size/2.0f );
					vertices[ x*4*elemsize + y*elemsize + 1 ] = ycoord*( this.size/2.0f );
					vertices[ x*4*elemsize + y*elemsize + 2 ] = zcoord*( this.size/2.0f );
					// normal
					vertices[ x*4*elemsize + y*elemsize + 3 ] = 0.0f;
					vertices[ x*4*elemsize + y*elemsize + 4 ] = 0.0f;
					vertices[ x*4*elemsize + y*elemsize + 5 ] = 1.0f;
					// tex
					vertices[ x*4*elemsize + y*elemsize + 6 ] = xcoord*Utility.Sqrt( 3.0f );
					vertices[ x*4*elemsize + y*elemsize + 7 ] = ycoord*Utility.Sqrt( 3.0f );
					vertices[ x*4*elemsize + y*elemsize + 8 ] = zcoord*Utility.Sqrt( 3.0f );
				}
			}

			var faces = new short[this.slices*6];
			for ( x = 0; x < this.slices; x++ )
			{
				faces[ x*6 + 0 ] = (short)( x*4 + 0 );
				faces[ x*6 + 1 ] = (short)( x*4 + 1 );
				faces[ x*6 + 2 ] = (short)( x*4 + 2 );
				faces[ x*6 + 3 ] = (short)( x*4 + 1 );
				faces[ x*6 + 4 ] = (short)( x*4 + 2 );
				faces[ x*6 + 5 ] = (short)( x*4 + 3 );
			}

			//setup buffers
			vertexData.vertexStart = 0;
			vertexData.vertexCount = nvertices;

			VertexDeclaration decl = vertexData.vertexDeclaration;
			VertexBufferBinding bind = vertexData.vertexBufferBinding;
			int offset = 0;
			offset += decl.AddElement( 0, 0, VertexElementType.Float3, VertexElementSemantic.Position ).Size;
			offset += decl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Normal ).Size;
			offset += decl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.TexCoords ).Size;

			HardwareVertexBuffer vertexBuffer = HardwareBufferManager.Instance.CreateVertexBuffer( decl, nvertices,
			                                                                                       BufferUsage.StaticWriteOnly );

			bind.SetBinding( 0, vertexBuffer );

			HardwareIndexBuffer indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size16, this.slices*6,
			                                                                                    BufferUsage.StaticWriteOnly );

			indexData.indexBuffer = indexBuffer;
			indexData.indexCount = this.slices*6;
			indexData.indexStart = 0;

			indexBuffer.WriteData( 0, indexBuffer.Size, faces, true );
			vertexBuffer.WriteData( 0, vertexBuffer.Size, vertices );
			vertices = null;
			faces = null;

			// Now make the render operation
			renderOperation.operationType = OperationType.TriangleList;
			renderOperation.indexData = indexData;
			renderOperation.vertexData = vertexData;
			renderOperation.useIndices = true;

			// Create a brand new private material
			if ( !ResourceGroupManager.Instance.GetResourceGroups().Contains( "VolumeRendable" ) )
			{
				ResourceGroupManager.Instance.CreateResourceGroup( "VolumeRendable" );
			}

			var material = (Material)MaterialManager.Instance.Create( this.texture, "VolumeRendable" );
			// Remove pre-created technique from defaults
			material.RemoveAllTechniques();

			// Create a techinique and a pass and a texture unit
			Technique technique = material.CreateTechnique();
			Pass pass = technique.CreatePass();
			TextureUnitState textureUnit = pass.CreateTextureUnitState();

			// Set pass parameters
			pass.SetSceneBlending( SceneBlendType.TransparentAlpha );
			pass.DepthWrite = false;
			pass.CullingMode = CullingMode.None;
			pass.LightingEnabled = false;
			textureUnit.SetTextureAddressingMode( TextureAddressing.Clamp );
			textureUnit.SetTextureName( this.texture, TextureType.ThreeD );
			textureUnit.SetTextureFiltering( TextureFiltering.Trilinear );

			this.unit = textureUnit;
			base.material = material;
		}
Beispiel #35
0
		/// <summary>
		///		Clones this vertex data, potentially including replicating any index buffers.
		/// </summary>
		/// <param name="copyData">
		///		If true, makes a copy the index buffer in addition to the definition.
		///		If false, the clone will refer to the same index buffer this object refers to.
		/// </param>
		/// <returns>A copy of this IndexData object.</returns>
		public IndexData Clone( bool copyData )
		{
			IndexData clone = new IndexData();

			if ( indexBuffer != null )
			{
				if ( copyData )
				{
					clone.indexBuffer =
						HardwareBufferManager.Instance.CreateIndexBuffer(
							indexBuffer.Type,
							indexBuffer.IndexCount,
							indexBuffer.Usage,
							indexBuffer.HasShadowBuffer );

					// copy all the existing buffer data
					clone.indexBuffer.CopyData( indexBuffer, 0, 0, indexBuffer.Size, true );
				}
				else
				{
					clone.indexBuffer = indexBuffer;
				}
			}

			clone.indexStart = indexStart;
			clone.indexCount = indexCount;

			return clone;
		}
        protected void buildVertexData()
        {
            // accumulate the number of verts and triangles from the patches
            int numVerts = 0;
            int numTriangles = 0;
            for (int z = 0; z < numTiles; z++)
            {
                for (int x = 0; x < numTiles; x++)
                {
                    numVerts += terrainPatches[x, z].NumVerts;
                    numTriangles += terrainPatches[x, z].NumTriangles;
                }
            }

            //
            // Create the vertex buffer
            //
            VertexData localVertexData = new VertexData();

            localVertexData.vertexCount = numVerts;
            localVertexData.vertexStart = 0;

            // free the original vertex declaration to avoid a leak
            HardwareBufferManager.Instance.DestroyVertexDeclaration(localVertexData.vertexDeclaration);

            localVertexData.vertexDeclaration = terrainVertexDeclaration;

            // create the hardware vertex buffer and set up the buffer binding
            HardwareVertexBuffer hvBuffer = HardwareBufferManager.Instance.CreateVertexBuffer(
                localVertexData.vertexDeclaration.GetVertexSize(0), localVertexData.vertexCount,
                BufferUsage.StaticWriteOnly, false);

            localVertexData.vertexBufferBinding.SetBinding(0, hvBuffer);
            renderOp.vertexData = localVertexData;

            //
            // Create the index buffer
            //
            IndexData localIndexData = new IndexData();

            localIndexData.indexCount = numTriangles * 3;
            localIndexData.indexStart = 0;

            localIndexData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer(
                IndexType.Size16, localIndexData.indexCount, BufferUsage.StaticWriteOnly);

            renderOp.indexData = localIndexData;

            // lock the vertex and index buffers
            IntPtr vertexBufferPtr = hvBuffer.Lock(BufferLocking.Discard);
            IntPtr indexBufferPtr = localIndexData.indexBuffer.Lock(BufferLocking.Discard);

            int vertOff = 0;
            int indexOff = 0;

            for (int z = 0; z < numTiles; z++)
            {
                for (int x = 0; x < numTiles; x++)
                {
                    TerrainPatch patch = terrainPatches[x, z];
                    int nv = patch.NumVerts;
                    int nt = patch.NumTriangles;
                    patch.BuildVertexIndexData(vertexBufferPtr, vertOff, indexBufferPtr, indexOff);

                    // update buffer offsets
                    vertOff += nv * VertexSize;
                    indexOff += (3 * nt);
                }
            }

            // unlock the buffers
            localIndexData.indexBuffer.Unlock();
            hvBuffer.Unlock();
        }
Beispiel #37
0
		public void AddIndexData( IndexData indexData, int vertexSet )
		{
			AddIndexData( indexData, vertexSet, OperationType.TriangleList );
		}
        private void BuildBuffers()
        {
            //
            // Build the vertex buffer
            //

            List<Vector2> points = boundary.Points;
            List<int[]> indices = boundary.Triangles;

            VertexData vertexData = new VertexData();

            vertexData.vertexCount = boundary.Points.Count;
            vertexData.vertexStart = 0;

            // set up the vertex declaration
            int vDecOffset = 0;
            vertexData.vertexDeclaration.AddElement(0, vDecOffset, VertexElementType.Float3, VertexElementSemantic.Position);
            vDecOffset += VertexElement.GetTypeSize(VertexElementType.Float3);

            vertexData.vertexDeclaration.AddElement(0, vDecOffset, VertexElementType.Float3, VertexElementSemantic.Normal);
            vDecOffset += VertexElement.GetTypeSize(VertexElementType.Float3);

            vertexData.vertexDeclaration.AddElement(0, vDecOffset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 0);
            vDecOffset += VertexElement.GetTypeSize(VertexElementType.Float2);

            // create the hardware vertex buffer and set up the buffer binding
            HardwareVertexBuffer hvBuffer = HardwareBufferManager.Instance.CreateVertexBuffer(
                vertexData.vertexDeclaration.GetVertexSize(0), vertexData.vertexCount,
                BufferUsage.StaticWriteOnly, false);

            vertexData.vertexBufferBinding.SetBinding(0, hvBuffer);

            // lock the vertex buffer
            IntPtr ipBuf = hvBuffer.Lock(BufferLocking.Discard);

            int bufferOff = 0;

            float minx = boundary.Bounds.Minimum.x;
            float minz = boundary.Bounds.Minimum.z;

            unsafe
            {
                float* buffer = (float*)ipBuf.ToPointer();

                for (int v = 0; v < vertexData.vertexCount; v++)
                {

                    // Position
                    buffer[bufferOff++] = points[v].x;
                    buffer[bufferOff++] = height;
                    buffer[bufferOff++] = points[v].y;

                    // normals
                    buffer[bufferOff++] = 0;
                    buffer[bufferOff++] = 1;
                    buffer[bufferOff++] = 0;

                    // Texture
                    float tmpu = ( points[v].x - minx ) / (128 * TerrainManager.oneMeter);
                    float tmpv = ( points[v].y - minz )/ (128 * TerrainManager.oneMeter);

                    buffer[bufferOff++] = tmpu;
                    buffer[bufferOff++] = tmpv;
                }
            }
            hvBuffer.Unlock();

            //
            // build the index buffer
            //
            IndexData indexData = new IndexData();

            int numIndices = indices.Count * 3;

            indexData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer(
                IndexType.Size16, numIndices, BufferUsage.StaticWriteOnly);

            IntPtr indexBufferPtr = indexData.indexBuffer.Lock(0, indexData.indexBuffer.Size, BufferLocking.Discard);

            unsafe
            {
                ushort* indexBuffer = (ushort*)indexBufferPtr.ToPointer();
                for (int i = 0; i < indices.Count; i++)
                {
                    indexBuffer[i * 3] = (ushort)indices[i][0];
                    indexBuffer[i * 3 + 1] = (ushort)indices[i][1];
                    indexBuffer[i * 3 + 2] = (ushort)indices[i][2];
                }
            }

            indexData.indexBuffer.Unlock();

            indexData.indexCount = numIndices;
            indexData.indexStart = 0;

            renderOp = new RenderOperation();

            renderOp.vertexData = vertexData;
            renderOp.indexData = indexData;
            renderOp.operationType = OperationType.TriangleList;
            renderOp.useIndices = true;
        }
Beispiel #39
0
		/// <summary>
		/// Populate with data as obtained from an IRenderable.
        /// </summary>
		/// <remarks>
		/// Will share the buffers.
		/// In case there are no index data associated with the <see cref="IRenderable"/>, i.e. <see cref="RenderOperation.useIndices"/> is false,
		/// custom software index buffer is created to provide default index data to the builder.
		/// This makes it possible for derived classes to handle the data in a convenient way.
		/// </remarks>
		public void AddObject( IRenderable obj )
		{
			if ( obj == null )
				throw new ArgumentNullException();

			RenderOperation renderOp = obj.RenderOperation;

			IndexData indexData;
			if ( renderOp.useIndices )
			{
				indexData = renderOp.indexData;
			}
			else
			{
				//Create custom index buffer
				int vertexCount = renderOp.vertexData.vertexCount;
				IndexType itype = vertexCount > UInt16.MaxValue ?
				IndexType.Size32 : IndexType.Size16;

				DefaultHardwareIndexBuffer ibuf = new DefaultHardwareIndexBuffer( itype, vertexCount, BufferUsage.Static );
				customIndexBufferList.Add( ibuf ); //to be disposed later

				indexData = new IndexData();
				indexData.indexBuffer = ibuf;
				indexData.indexCount = vertexCount;
				indexData.indexStart = 0;

				//Fill buffer with indices
				IntPtr ibuffer =
				indexData.indexBuffer.Lock( BufferLocking.Normal );
				try
				{
					unsafe
					{
						Int16* ibuf16 = (Int16*)ibuffer;
						Int32* ibuf32 = (Int32*)ibuffer;
						for ( int i = 0; i < indexData.indexCount; i++ )
						{
							if ( itype == IndexType.Size16 )
							{
								ibuf16[ i ] = (Int16)i;
							}
							else
							{
								ibuf32[ i ] = i;
							}
						}
					} //unsafe
				}
				finally
				{
					indexData.indexBuffer.Unlock();
				}
			}

			AddVertexData( renderOp.vertexData );
			AddIndexData( indexData, vertexDataList.Count - 1,
			renderOp.operationType );
		}
        /// <summary>
        ///
        /// </summary>
        /// <param name="indexSet"></param>
        /// <param name="vertexSet"></param>
        protected void BuildTrianglesEdges(int indexSet, int vertexSet)
        {
            IndexData     indexData = (IndexData)indexDataList[indexSet];
            OperationType opType    = operationTypes[indexSet];

            int iterations = 0;

            switch (opType)
            {
            case OperationType.TriangleList:
                iterations = indexData.indexCount / 3;
                break;

            case OperationType.TriangleFan:
            case OperationType.TriangleStrip:
                iterations = indexData.indexCount - 2;
                break;
            }

            // locate postion element & the buffer to go with it
            VertexData    vertexData = (VertexData)vertexDataList[vertexSet];
            VertexElement posElem    =
                vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.Position);

            HardwareVertexBuffer posBuffer = vertexData.vertexBufferBinding.GetBuffer(posElem.Source);
            IntPtr posPtr = posBuffer.Lock(BufferLocking.ReadOnly);
            IntPtr idxPtr = indexData.indexBuffer.Lock(BufferLocking.ReadOnly);

            unsafe {
                byte *pBaseVertex = (byte *)posPtr.ToPointer();

                short *p16Idx = null;
                int *  p32Idx = null;

                // counters used for pointer indexing
                int count16 = 0;
                int count32 = 0;

                if (indexData.indexBuffer.Type == IndexType.Size16)
                {
                    p16Idx = (short *)idxPtr.ToPointer();
                }
                else
                {
                    p32Idx = (int *)idxPtr.ToPointer();
                }

                float *pReal = null;

                int triStart = edgeData.triangles.Count;

                // iterate over all the groups of 3 indices
                edgeData.triangles.Capacity = triStart + iterations;

                for (int t = 0; t < iterations; t++)
                {
                    EdgeData.Triangle tri = new EdgeData.Triangle();
                    tri.indexSet  = indexSet;
                    tri.vertexSet = vertexSet;

                    int[]     index = new int[3];
                    Vector3[] v     = new Vector3[3];

                    for (int i = 0; i < 3; i++)
                    {
                        // Standard 3-index read for tri list or first tri in strip / fan
                        if (opType == OperationType.TriangleList || t == 0)
                        {
                            if (indexData.indexBuffer.Type == IndexType.Size32)
                            {
                                index[i] = p32Idx[count32++];
                            }
                            else
                            {
                                index[i] = p16Idx[count16++];
                            }
                        }
                        else
                        {
                            // Strips and fans are formed from last 2 indexes plus the
                            // current one for triangles after the first
                            if (indexData.indexBuffer.Type == IndexType.Size32)
                            {
                                index[i] = p32Idx[i - 2];
                            }
                            else
                            {
                                index[i] = p16Idx[i - 2];
                            }

                            // Perform single-index increment at the last tri index
                            if (i == 2)
                            {
                                if (indexData.indexBuffer.Type == IndexType.Size32)
                                {
                                    count32++;
                                }
                                else
                                {
                                    count16++;
                                }
                            }
                        }

                        // populate tri original vertex index
                        tri.vertIndex[i] = index[i];

                        // Retrieve the vertex position
                        byte *pVertex = pBaseVertex + (index[i] * posBuffer.VertexSize);
                        pReal  = (float *)(pVertex + posElem.Offset);
                        v[i].x = *pReal++;
                        v[i].y = *pReal++;
                        v[i].z = *pReal++;
                        // find this vertex in the existing vertex map, or create it
                        tri.sharedVertIndex[i] = FindOrCreateCommonVertex(v[i], vertexSet, indexSet, index[i]);
                    }

                    // Calculate triangle normal (NB will require recalculation for
                    // skeletally animated meshes)
                    tri.normal = MathUtil.CalculateFaceNormal(v[0], v[1], v[2]);

                    // Add triangle to list
                    edgeData.triangles.Add(tri);

                    try {
                        // create edges from common list
                        if (tri.sharedVertIndex[0] < tri.sharedVertIndex[1])
                        {
                            CreateEdge(vertexSet, triStart + t,
                                       tri.vertIndex[0], tri.vertIndex[1],
                                       tri.sharedVertIndex[0], tri.sharedVertIndex[1]);
                        }
                        if (tri.sharedVertIndex[1] < tri.sharedVertIndex[2])
                        {
                            CreateEdge(vertexSet, triStart + t,
                                       tri.vertIndex[1], tri.vertIndex[2],
                                       tri.sharedVertIndex[1], tri.sharedVertIndex[2]);
                        }
                        if (tri.sharedVertIndex[2] < tri.sharedVertIndex[0])
                        {
                            CreateEdge(vertexSet, triStart + t,
                                       tri.vertIndex[2], tri.vertIndex[0],
                                       tri.sharedVertIndex[2], tri.sharedVertIndex[0]);
                        }
                    }
                    catch (Exception ex) {
                        //Debug.WriteLine(ex.ToString());
                        //Debug.WriteLine(ex.StackTrace);
                        // unlock those buffers!
                        indexData.indexBuffer.Unlock();
                        posBuffer.Unlock();

                        throw ex;
                    }
                } // for iterations
            }     // unsafe

            // unlock those buffers!
            indexData.indexBuffer.Unlock();
            posBuffer.Unlock();
        }