Describes the graphics API independent functionality required by a hardware vertex buffer.
Inheritance: Axiom.Graphics.HardwareBuffer
Exemple #1
0
        /// <summary>
        ///		Internal method that forces the release of copies of a given buffer.
        /// </summary>
        /// <remarks>
        ///		This usually means that the buffer which the copies are based on has
        ///		been changed in some fundamental way, and the owner of the original
        ///		wishes to make that known so that new copies will reflect the changes.
        /// </remarks>
        /// <param name="sourceBuffer">Buffer to release temp copies of.</param>
        internal void ForceReleaseBufferCopies(HardwareVertexBuffer sourceBuffer)
        {
            // erase the copies which are licensed out
            for (int i = tempVertexBufferLicenses.Count - 1; i >= 0; i--)
            {
                VertexBufferLicense vbl =
                    (VertexBufferLicense)tempVertexBufferLicenses[i];

                if (vbl.originalBuffer == sourceBuffer)
                {
                    // Just tell the owner that this is being released
                    vbl.licensee.LicenseExpired(vbl.buffer);
                    tempVertexBufferLicenses.RemoveAt(i);
                }
            }

            // TODO: Verify this works
            foreach (DictionaryEntry entry in freeTempVertexBufferMap)
            {
                if (entry.Key == sourceBuffer)
                {
                    ArrayList list = (ArrayList)entry.Value;
                    list.Clear();
                }
            }
        }
        /// <summary>
        ///   Utility method to pull a bunch of floats out of a vertex buffer.
        /// </summary>
        /// <param name="data"></param>
        /// <param name="vBuffer"></param>
        /// <param name="elem"></param>
        public static void ReadBuffer( float[ , ] data, HardwareVertexBuffer vBuffer, VertexElement elem )
        {
            int count = data.GetLength( 1 );
            IntPtr bufData = vBuffer.Lock( BufferLocking.ReadOnly );

            Debug.Assert( vBuffer.VertexSize % sizeof( float ) == 0 );
            Debug.Assert( elem.Offset % sizeof( float ) == 0 );
            int vertexCount = vBuffer.VertexCount;
            int vertexSpan = vBuffer.VertexSize / sizeof( float );
            int offset = elem.Offset / sizeof( float );
            unsafe
            {
                float* pFloats = (float*) bufData.ToPointer();
                for( int i = 0; i < vertexCount; ++i )
                {
                    for( int j = 0; j < count; ++j )
                    {
                        Debug.Assert( ((offset + i * vertexSpan + j) * sizeof( float )) < (vertexCount * vBuffer.VertexSize),
                                     "Read off end of vertex buffer" );
                        data[ i, j ] = pFloats[ offset + i * vertexSpan + j ];
                    }
                }
            }

            // unlock the buffer
            vBuffer.Unlock();
        }
        /// <summary>
        ///		Updates the face normals for this edge list based on (changed)
        ///		position information, useful for animated objects.
        /// </summary>
        /// <param name="vertexSet">The vertex set we are updating.</param>
        /// <param name="positionBuffer">The updated position buffer, must contain ONLY xyz.</param>
        public void UpdateFaceNormals(int vertexSet, HardwareVertexBuffer positionBuffer)
        {
            unsafe {
                Debug.Assert(positionBuffer.VertexSize == sizeof(float) * 3, "Position buffer should contain only positions!");

                // Lock buffer for reading
                IntPtr posPtr = positionBuffer.Lock(BufferLocking.ReadOnly);
                float *pVert  = (float *)posPtr.ToPointer();

                // Iterate over the triangles
                for (int i = 0; i < triangles.Count; i++)
                {
                    Triangle t = (Triangle)triangles[i];

                    // Only update tris which are using this vertex set
                    if (t.vertexSet == vertexSet)
                    {
                        int     offset = t.vertIndex[0] * 3;
                        Vector3 v1     = new Vector3(pVert[offset], pVert[offset + 1], pVert[offset + 2]);

                        offset = t.vertIndex[1] * 3;
                        Vector3 v2 = new Vector3(pVert[offset], pVert[offset + 1], pVert[offset + 2]);

                        offset = t.vertIndex[2] * 3;
                        Vector3 v3 = new Vector3(pVert[offset], pVert[offset + 1], pVert[offset + 2]);

                        t.normal = MathUtil.CalculateFaceNormal(v1, v2, v3);
                    }
                }
            }

            // unlock the buffer
            positionBuffer.Unlock();
        }
 public virtual void RegisterVertexBufferSourceAndCopy(HardwareVertexBuffer sourceBuffer, HardwareVertexBuffer copy)
 {
     lock (TempBuffersMutex)
     {
         // Add copy to free temporary vertex buffers
         this.freeTempVertexBufferMap.Add(sourceBuffer, copy);
     }
 }
Exemple #5
0
        /// <summary>
        ///		Gets the buffer bound to the given source index.
        /// </summary>
        /// <param name="index">Index of the binding to retreive the buffer for.</param>
        /// <returns>Buffer at the specified index.</returns>
        public virtual HardwareVertexBuffer GetBuffer(ushort index)
        {
            Debug.Assert(bindingMap.ContainsKey(index), "No buffer is bound to index " + index);

            HardwareVertexBuffer buf = bindingMap[index];

            return(buf);
        }
        /// <summary>
        /// 
        /// </summary>
        public VertexBufferLicense(HardwareVertexBuffer originalBuffer, BufferLicenseRelease licenseType, 
								   int expiredDelay, HardwareVertexBuffer buffer, IHardwareBufferLicensee licensee)
        {
            this.originalBuffer = originalBuffer;
            this.licenseType = licenseType;
            this.expiredDelay = expiredDelay;
            this.buffer = buffer;
            this.licensee = licensee;
        }
 /// <summary>
 ///
 /// </summary>
 public VertexBufferLicense(HardwareVertexBuffer originalBuffer, BufferLicenseRelease licenseType,
                            int expiredDelay, HardwareVertexBuffer buffer, IHardwareBufferLicensee licensee)
 {
     this.originalBuffer = originalBuffer;
     this.licenseType    = licenseType;
     this.expiredDelay   = expiredDelay;
     this.buffer         = buffer;
     this.licensee       = licensee;
 }
 /// <summary>
 ///     Implementation of LicenseExpired.
 /// </summary>
 /// <param name="buffer"></param>
 public void LicenseExpired(HardwareBuffer buffer)
 {
     if (buffer == destPositionBuffer)
     {
         destPositionBuffer = null;
     }
     if (buffer == destNormalBuffer)
     {
         destNormalBuffer = null;
     }
 }
        /// <summary>
        ///     Utility method, checks out temporary copies of src into dest.
        /// </summary>
        public void CheckoutTempCopies(bool positions, bool normals, bool tangents, bool binormals)
        {
            bindPositions = positions;
            bindNormals   = normals;
            bindTangents  = tangents;
            bindBinormals = binormals;

            if (bindPositions && destPositionBuffer == null)
            {
                destPositionBuffer =
                    HardwareBufferManager.Instance.AllocateVertexBufferCopy(
                        srcPositionBuffer,
                        BufferLicenseRelease.Automatic,
                        this);
            }

            if (bindNormals && !posNormalShareBuffer &&
                srcNormalBuffer != null && destNormalBuffer == null)
            {
                destNormalBuffer =
                    HardwareBufferManager.Instance.AllocateVertexBufferCopy(
                        srcNormalBuffer,
                        BufferLicenseRelease.Automatic,
                        this);
            }

            if (bindTangents && srcTangentBuffer != null)
            {
                if (this.tanBindIndex != this.posBindIndex &&
                    this.tanBindIndex != this.normBindIndex)
                {
                    destTangentBuffer =
                        HardwareBufferManager.Instance.AllocateVertexBufferCopy(
                            srcTangentBuffer,
                            BufferLicenseRelease.Automatic,
                            this);
                }
            }

            if (bindNormals && srcBinormalBuffer != null)
            {
                if (this.binormBindIndex != this.posBindIndex &&
                    this.binormBindIndex != this.normBindIndex &&
                    this.binormBindIndex != this.tanBindIndex)
                {
                    destBinormalBuffer =
                        HardwareBufferManager.Instance.AllocateVertexBufferCopy(
                            srcBinormalBuffer,
                            BufferLicenseRelease.Automatic,
                            this);
                }
            }
        }
Exemple #10
0
 /// <summary>
 ///     Manually release a vertex buffer copy for others to subsequently use.
 /// </summary>
 /// <remarks>
 ///     Only required if the original call to <see cref="AllocateVertexBufferCopy"/>
 ///     included a licenseType of <see cref="BufferLicenseRelease.Manual"/>.
 /// </remarks>
 /// <param name="bufferCopy">
 ///     The buffer copy. The caller is expected to no longer use this reference,
 ///     since another user may well begin to modify the contents of the buffer.
 /// </param>
 public virtual void ReleaseVertexBufferCopy(HardwareVertexBuffer bufferCopy)
 {
     for (int i = 0; i < tempVertexBufferLicenses.Count; i++)
     {
         VertexBufferLicense vbl = (VertexBufferLicense)tempVertexBufferLicenses[i];
         if (vbl.buffer != bufferCopy)
         {
             continue;
         }
         vbl.licensee.LicenseExpired(bufferCopy);
         tempVertexBufferLicenses.RemoveAt(i);
         return;
     }
 }
Exemple #11
0
        /// <summary>
        ///     Tell engine that the vertex buffer copy intent to reuse.
        /// </summary>
        /// <remarks>
        ///     Ogre internal keep an expired delay counter of BLT_AUTOMATIC_RELEASE
        ///     buffers, when the counter count down to zero, it'll release for other
        ///     purposes later. But you can use this function to reset the counter to
        ///     the internal configured value, keep the buffer not get released for
        ///     some frames.
        /// </remarks>
        /// <param name="bufferCopy" The buffer copy. The caller is expected to keep this
        ///     buffer copy for use.</param>
        public void TouchVertexBufferCopy(HardwareVertexBuffer bufferCopy)
        {
            for (int i = 0; i < tempVertexBufferLicenses.Count; i++)
            {
                VertexBufferLicense vbl = (VertexBufferLicense)tempVertexBufferLicenses[i];
                if (vbl.buffer != bufferCopy)
                {
                    continue;
                }
                Debug.Assert(vbl.licenseType == BufferLicenseRelease.Automatic);

                vbl.expiredDelay = expiredDelayFrameThreshold;
            }
        }
        /// <summary>
        ///		Sets the corners of the rectangle, in relative coordinates.
        /// </summary>
        /// <param name="left">Left position in screen relative coordinates, -1 = left edge, 1.0 = right edge.</param>
        /// <param name="top">Top position in screen relative coordinates, 1 = top edge, -1 = bottom edge.</param>
        /// <param name="right">Position in screen relative coordinates.</param>
        /// <param name="bottom">Position in screen relative coordinates.</param>
        public void SetCorners(float left, float top, float right, float bottom)
        {
            float[] data = new float[] {
                left, top, -1,
                left, bottom, -1,
                right, top, -1,
                right, bottom, -1
            };

            HardwareVertexBuffer buffer =
                vertexData.vertexBufferBinding.GetBuffer(POSITION);

            buffer.WriteData(0, buffer.Size, data, true);

            box = new AxisAlignedBox();
            box.SetExtents(new Vector3(left, top, 0), new Vector3(right, bottom, 0));
        }
Exemple #13
0
        /// <summary>
        ///		Utility method for extruding vertices based on a light.
        /// </summary>
        /// <remarks>
        ///		Unfortunately, because D3D cannot handle homogenous (4D) position
        ///		coordinates in the fixed-function pipeline (GL can, but we have to
        ///		be cross-API), when we extrude in software we cannot extrude to
        ///		infinity the way we do in the vertex program (by setting w to
        ///		0.0f). Therefore we extrude by a fixed distance, which may cause
        ///		some problems with larger scenes. Luckily better hardware (ie
        ///		vertex programs) can fix this.
        /// </remarks>
        /// <param name="vertexBuffer">The vertex buffer containing ONLY xyz position
        /// values, which must be originalVertexCount * 2 * 3 floats long.</param>
        /// <param name="originalVertexCount">The count of the original number of
        /// vertices, ie the number in the mesh, not counting the doubling
        /// which has already been done (by <see cref="VertexData.PrepareForShadowVolume"/>)
        /// to provide the extruded area of the buffer.</param>
        /// <param name="lightPosition"> 4D light position in object space, when w=0.0f this
        /// represents a directional light</param>
        /// <param name="extrudeDistance">The distance to extrude.</param>
        public static void ExtrudeVertices(HardwareVertexBuffer vertexBuffer, int originalVertexCount, Vector4 lightPosition,
                                           float extrudeDistance)
        {
#if !AXIOM_SAFE_ONLY
            unsafe
#endif
            {
                Debug.Assert(vertexBuffer.VertexSize == sizeof(float) * 3, "Position buffer should contain only positions!");

                // Extrude the first area of the buffer into the second area
                // Lock the entire buffer for writing, even though we'll only be
                // updating the latter because you can't have 2 locks on the same
                // buffer
                var srcPtr  = vertexBuffer.Lock(BufferLocking.Normal);
                var destPtr = srcPtr + (originalVertexCount * 3 * 4);
                var pSrc    = srcPtr.ToFloatPointer();
                var pDest   = destPtr.ToFloatPointer();

                int destCount = 0, srcCount = 0;

                // Assume directional light, extrusion is along light direction
                var extrusionDir = new Vector3(-lightPosition.x, -lightPosition.y, -lightPosition.z);
                extrusionDir.Normalize();
                extrusionDir *= extrudeDistance;

                for (var vert = 0; vert < originalVertexCount; vert++)
                {
                    if (lightPosition.w != 0.0f)
                    {
                        // Point light, adjust extrusionDir
                        extrusionDir.x = pSrc[srcCount + 0] - lightPosition.x;
                        extrusionDir.y = pSrc[srcCount + 1] - lightPosition.y;
                        extrusionDir.z = pSrc[srcCount + 2] - lightPosition.z;
                        extrusionDir.Normalize();
                        extrusionDir *= extrudeDistance;
                    }

                    pDest[destCount++] = pSrc[srcCount++] + extrusionDir.x;
                    pDest[destCount++] = pSrc[srcCount++] + extrusionDir.y;
                    pDest[destCount++] = pSrc[srcCount++] + extrusionDir.z;
                }
            }

            vertexBuffer.Unlock();
        }
        private static void ReadBuffer(HardwareVertexBuffer vBuffer, int vertexCount, int vertexSize,
								ref Vector3[] data)
        {
            IntPtr bufData = vBuffer.Lock(BufferLocking.ReadOnly);

            unsafe {
                float* pFloats = (float*)bufData.ToPointer();
                for (int i = 0; i < vertexCount; ++i)
                    for (int j = 0; j < 3; ++j) {
                        Debug.Assert(sizeof(float) * (i * 3 + j) < vertexCount * vertexSize,
                            "Read off end of vertex buffer");
                        data[i][j] = pFloats[i * 3 + j];
                    }
            }

            // unlock the buffer
            vBuffer.Unlock();
        }
        /// <summary>
        ///		Utility method for extruding vertices based on a light.
        /// </summary>
        /// <remarks>
        ///		Unfortunately, because D3D cannot handle homogenous (4D) position
        ///		coordinates in the fixed-function pipeline (GL can, but we have to
        ///		be cross-API), when we extrude in software we cannot extrude to 
        ///		infinity the way we do in the vertex program (by setting w to
        ///		0.0f). Therefore we extrude by a fixed distance, which may cause 
        ///		some problems with larger scenes. Luckily better hardware (ie
        ///		vertex programs) can fix this.
        /// </remarks>
        /// <param name="vertexBuffer">The vertex buffer containing ONLY xyz position
        /// values, which must be originalVertexCount * 2 * 3 floats long.</param>
        /// <param name="originalVertexCount">The count of the original number of
        /// vertices, ie the number in the mesh, not counting the doubling
        /// which has already been done (by <see cref="VertexData.PrepareForShadowVolume"/>)
        /// to provide the extruded area of the buffer.</param>
        /// <param name="lightPosition"> 4D light position in object space, when w=0.0f this
        /// represents a directional light</param>
        /// <param name="extrudeDistance">The distance to extrude.</param>
        public static void ExtrudeVertices(HardwareVertexBuffer vertexBuffer, int originalVertexCount, Vector4 lightPosition, float extrudeDistance)
        {
            unsafe {
                Debug.Assert(vertexBuffer.VertexSize == sizeof(float) * 3, "Position buffer should contain only positions!");

                // Extrude the first area of the buffer into the second area
                // Lock the entire buffer for writing, even though we'll only be
                // updating the latter because you can't have 2 locks on the same
                // buffer
                IntPtr srcPtr = vertexBuffer.Lock(BufferLocking.Normal);
                IntPtr destPtr = new IntPtr(srcPtr.ToInt32() + (originalVertexCount * 3 * 4));
                float* pSrc = (float*)srcPtr.ToPointer();
                float* pDest = (float*)destPtr.ToPointer();

                int destCount = 0, srcCount = 0;

                // Assume directional light, extrusion is along light direction
                Vector3 extrusionDir = new Vector3(-lightPosition.x, -lightPosition.y, -lightPosition.z);
                extrusionDir.Normalize();
                extrusionDir *= extrudeDistance;

                for (int vert = 0; vert < originalVertexCount; vert++) {
                    if (lightPosition.w != 0.0f) {
                        // Point light, adjust extrusionDir
                        extrusionDir.x = pSrc[srcCount + 0] - lightPosition.x;
                        extrusionDir.y = pSrc[srcCount + 1] - lightPosition.y;
                        extrusionDir.z = pSrc[srcCount + 2] - lightPosition.z;
                        extrusionDir.Normalize();
                        extrusionDir *= extrudeDistance;
                    }

                    pDest[destCount++] = pSrc[srcCount++] + extrusionDir.x;
                    pDest[destCount++] = pSrc[srcCount++] + extrusionDir.y;
                    pDest[destCount++] = pSrc[srcCount++] + extrusionDir.z;
                }
            }

            vertexBuffer.Unlock();
        }
Exemple #16
0
        /// <summary>
        ///     Allocates a copy of a given vertex buffer.
        /// </summary>
        /// <remarks>
        ///     This method allocates a temporary copy of an existing vertex buffer.
        ///     This buffer is subsequently stored and can be made available for
        ///     other purposes later without incurring the cost of construction /
        ///     destruction.
        /// </remarks>
        /// <param name="sourceBuffer">The source buffer to use as a copy.</param>
        /// <param name="licenseType">
        ///     The type of license required on this buffer - automatic
        ///     release causes this class to release licenses every frame so that
        ///     they can be reallocated anew.
        /// </param>
        /// <param name="licensee">
        ///     Reference back to the class requesting the copy, which must
        ///     implement <see cref="IHardwareBufferLicense"/> in order to be notified when the license
        ///     expires.
        /// </param>
        /// <param name="copyData">If true, the current data is copied as well as the structure of the buffer.</param>
        /// <returns></returns>
        public virtual HardwareVertexBuffer AllocateVertexBufferCopy(HardwareVertexBuffer sourceBuffer,
                                                                     BufferLicenseRelease licenseType, IHardwareBufferLicensee licensee, bool copyData)
        {
            HardwareVertexBuffer vbuf = null;

            // Locate existing buffer copy in free list
            IList list = (IList)freeTempVertexBufferMap[sourceBuffer];

            if (list == null)
            {
                list = new ArrayList();
                freeTempVertexBufferMap[sourceBuffer] = list;
            }

            // Are there any free buffers?
            if (list.Count == 0)
            {
                // copy buffer, use shadow buffer and make dynamic
                vbuf = MakeBufferCopy(sourceBuffer, BufferUsage.DynamicWriteOnly, true);
            }
            else
            {
                // grab the available buffer and remove it from the free list
                int lastIndex = list.Count - 1;
                vbuf = (HardwareVertexBuffer)list[lastIndex];
                list.RemoveAt(lastIndex);
            }

            // Copy data?
            if (copyData)
            {
                vbuf.CopyData(sourceBuffer, 0, 0, sourceBuffer.Size, true);
            }
            // Insert copy into licensee list
            tempVertexBufferLicenses.Add(new VertexBufferLicense(sourceBuffer, licenseType,
                                                                 expiredDelayFrameThreshold, vbuf, licensee));

            return(vbuf);
        }
        public Rectangle2D(bool includeTextureCoordinates)
        {
            vertexData             = new VertexData();
            vertexData.vertexStart = 0;
            vertexData.vertexCount = 4;

            VertexDeclaration   decl    = vertexData.vertexDeclaration;
            VertexBufferBinding binding = vertexData.vertexBufferBinding;

            decl.AddElement(POSITION, 0, VertexElementType.Float3, VertexElementSemantic.Position);

            HardwareVertexBuffer buffer =
                HardwareBufferManager.Instance.CreateVertexBuffer(
                    decl.GetVertexSize(POSITION),
                    vertexData.vertexCount,
                    BufferUsage.StaticWriteOnly);

            binding.SetBinding(POSITION, buffer);

            if (includeTextureCoordinates)
            {
                decl.AddElement(TEXCOORD, 0, VertexElementType.Float2, VertexElementSemantic.TexCoords);

                buffer =
                    HardwareBufferManager.Instance.CreateVertexBuffer(
                        decl.GetVertexSize(TEXCOORD),
                        vertexData.vertexCount,
                        BufferUsage.StaticWriteOnly);

                binding.SetBinding(TEXCOORD, buffer);

                buffer.WriteData(0, buffer.Size, texCoords, true);
            }

            // TODO: Fix
            material          = MaterialManager.Instance.GetByName("BaseWhite");
            material.Lighting = false;
        }
Exemple #18
0
        /// <summary>
        ///		Updates the face normals for this edge list based on (changed)
        ///		position information, useful for animated objects.
        /// </summary>
        /// <param name="vertexSet">The vertex set we are updating.</param>
        /// <param name="positionBuffer">The updated position buffer, must contain ONLY xyz.</param>
        public void UpdateFaceNormals(int vertexSet, HardwareVertexBuffer positionBuffer)
        {
#if !AXIOM_SAFE_ONLY
            unsafe
#endif
            {
                Debug.Assert(positionBuffer.VertexSize == sizeof(float) * 3, "Position buffer should contain only positions!");

                // Lock buffer for reading
                var posPtr = positionBuffer.Lock(BufferLocking.ReadOnly);
                var pVert  = posPtr.ToFloatPointer();

                // Iterate over the triangles
                for (var i = 0; i < this.triangles.Count; i++)
                {
                    var t = (Triangle)this.triangles[i];

                    // Only update tris which are using this vertex set
                    if (t.vertexSet == vertexSet)
                    {
                        var offset = t.vertIndex[0] * 3;
                        var v1     = new Vector3(pVert[offset], pVert[offset + 1], pVert[offset + 2]);

                        offset = t.vertIndex[1] * 3;
                        var v2 = new Vector3(pVert[offset], pVert[offset + 1], pVert[offset + 2]);

                        offset = t.vertIndex[2] * 3;
                        var v3 = new Vector3(pVert[offset], pVert[offset + 1], pVert[offset + 2]);

                        t.normal = CalculateFaceNormal(v1, v2, v3);
                    }
                }
            }

            // unlock the buffer
            positionBuffer.Unlock();
        }
        private static void GenerateCurvedIllusionPlaneVertexData(HardwareVertexBuffer vertexBuffer, int ySegments, int xSegments, float xSpace, float halfWidth, float ySpace, float halfHeight, Matrix4 xform, bool firstTime, bool normals, Quaternion orientation, float cameraPosition, float sphereRadius, float uTiles, float vTiles, int numberOfTexCoordSets, ref Vector3 min, ref Vector3 max, ref float maxSquaredLength)
        {
            Vector3 vec;
            Vector3 norm;
            float sphereDistance;
            unsafe {
                // lock the vertex buffer
                IntPtr data = vertexBuffer.Lock(BufferLocking.Discard);

                float* pData = (float*)data.ToPointer();

                for (int y = 0; y < ySegments + 1; ++y) {
                    for (int x = 0; x < xSegments + 1; ++x) {
                        // centered on origin
                        vec.x = (x * xSpace) - halfWidth;
                        vec.y = (y * ySpace) - halfHeight;
                        vec.z = 0.0f;

                        // transform by orientation and distance
                        vec = xform * vec;

                        // assign to geometry
                        *pData++ = vec.x;
                        *pData++ = vec.y;
                        *pData++ = vec.z;

                        // build bounds as we go
                        if (firstTime) {
                            min = vec;
                            max = vec;
                            maxSquaredLength = vec.LengthSquared;
                            firstTime = false;
                        } else {
                            min.Floor(vec);
                            max.Ceil(vec);
                            maxSquaredLength = MathUtil.Max(maxSquaredLength, vec.LengthSquared);
                        }

                        if (normals) {
                            norm = Vector3.UnitZ;
                            norm = orientation * norm;

                            *pData++ = vec.x;
                            *pData++ = vec.y;
                            *pData++ = vec.z;
                        }

                        // generate texture coordinates, normalize position, modify by orientation to return +y up
                        vec = orientation.Inverse() * vec;
                        vec.Normalize();

                        // find distance to sphere
                        sphereDistance = MathUtil.Sqrt(cameraPosition * cameraPosition * (vec.y * vec.y - 1.0f) + sphereRadius * sphereRadius) - cameraPosition * vec.y;

                        vec.x *= sphereDistance;
                        vec.z *= sphereDistance;

                        // use x and y on sphere as texture coordinates, tiled
                        float s = vec.x * (0.01f * uTiles);
                        float t = vec.z * (0.01f * vTiles);
                        for (int i = 0; i < numberOfTexCoordSets; i++) {
                            *pData++ = s;
                            *pData++ = (1 - t);
                        }
                    } // x
                } // y

                // unlock the buffer
                vertexBuffer.Unlock();
            } // unsafe
        }
        /// <summary>
        ///		Utility method, extract info from the given VertexData
        /// </summary>
        public void ExtractFrom(VertexData sourceData)
        {
            // Release old buffer copies first
            HardwareBufferManager mgr = HardwareBufferManager.Instance;

            if (destPositionBuffer != null)
            {
                mgr.ReleaseVertexBufferCopy(destPositionBuffer);
                Debug.Assert(destPositionBuffer == null);
            }
            if (destNormalBuffer != null)
            {
                mgr.ReleaseVertexBufferCopy(destNormalBuffer);
                Debug.Assert(destNormalBuffer == null);
            }

            VertexDeclaration   decl       = sourceData.vertexDeclaration;
            VertexBufferBinding bind       = sourceData.vertexBufferBinding;
            VertexElement       posElem    = decl.FindElementBySemantic(VertexElementSemantic.Position);
            VertexElement       normElem   = decl.FindElementBySemantic(VertexElementSemantic.Normal);
            VertexElement       tanElem    = decl.FindElementBySemantic(VertexElementSemantic.Tangent);
            VertexElement       binormElem = decl.FindElementBySemantic(VertexElementSemantic.Binormal);

            Debug.Assert(posElem != null, "Positions are required");

            posBindIndex      = posElem.Source;
            srcPositionBuffer = bind.GetBuffer(posBindIndex);

            if (normElem == null)
            {
                posNormalShareBuffer = false;
                srcNormalBuffer      = null;
            }
            else
            {
                normBindIndex = normElem.Source;
                if (normBindIndex == posBindIndex)
                {
                    posNormalShareBuffer = true;
                    srcNormalBuffer      = null;
                }
                else
                {
                    posNormalShareBuffer = false;
                    srcNormalBuffer      = bind.GetBuffer(normBindIndex);
                }
            }
            if (tanElem == null)
            {
                srcTangentBuffer = null;
            }
            else
            {
                tanBindIndex     = tanElem.Source;
                srcTangentBuffer = bind.GetBuffer(tanBindIndex);
            }

            if (binormElem == null)
            {
                srcBinormalBuffer = null;
            }
            else
            {
                binormBindIndex   = binormElem.Source;
                srcBinormalBuffer = bind.GetBuffer(binormBindIndex);
            }
        }
		public override void NotifyVertexBufferDestroyed( HardwareVertexBuffer buffer )
		{
			_baseInstance.NotifyVertexBufferDestroyed( buffer );
		}
		public override void ReleaseVertexBufferCopy( HardwareVertexBuffer bufferCopy )
		{
			_baseInstance.ReleaseVertexBufferCopy( bufferCopy );
		}
Exemple #23
0
		private void _generateCurvedIllusionPlaneVertexData( HardwareVertexBuffer vertexBuffer, int ySegments, int xSegments, float xSpace, float halfWidth, float ySpace, float halfHeight, Matrix4 xform, bool firstTime, bool normals, Quaternion orientation, float curvature, float uTiles, float vTiles, int numberOfTexCoordSets, ref Vector3 min, ref Vector3 max, ref float maxSquaredLength )
		{
			// Imagine a large sphere with the camera located near the top
			// The lower the curvature, the larger the sphere
			// Use the angle from viewer to the points on the plane
			// Credit to Aftershock for the general approach
			Real cameraPosition;      // Camera position relative to sphere center

			// Derive sphere radius
			//Vector3 vertPos;  // position relative to camera
			//Real sphDist;      // Distance from camera to sphere along box vertex vector
			// Vector3 camToSph; // camera position to sphere
			Real sphereRadius;// Sphere radius
			// Actual values irrelevant, it's the relation between sphere radius and camera position that's important
			Real sphRadius = 100.0f;
			Real camDistance = 5.0f;

			sphereRadius = sphRadius - curvature;
			cameraPosition = sphereRadius - camDistance;

			Vector3 vec;
			Vector3 norm;
			float sphereDistance;
			unsafe
			{
				// lock the vertex buffer
				IntPtr data = vertexBuffer.Lock( BufferLocking.Discard );

				float* pData = (float*)data.ToPointer();

				for ( int y = 0; y < ySegments + 1; ++y )
				{
					for ( int x = 0; x < xSegments + 1; ++x )
					{
						// centered on origin
						vec.x = ( x * xSpace ) - halfWidth;
						vec.y = ( y * ySpace ) - halfHeight;
						vec.z = 0.0f;

						// transform by orientation and distance
						vec = xform * vec;

						// assign to geometry
						*pData++ = vec.x;
						*pData++ = vec.y;
						*pData++ = vec.z;

						// build bounds as we go
						if ( firstTime )
						{
							min = vec;
							max = vec;
							maxSquaredLength = vec.LengthSquared;
							firstTime = false;
						}
						else
						{
							min.Floor( vec );
							max.Ceil( vec );
							maxSquaredLength = Utility.Max( maxSquaredLength, vec.LengthSquared );
						}

						if ( normals )
						{
							norm = Vector3.UnitZ;
							norm = orientation * norm;

							*pData++ = vec.x;
							*pData++ = vec.y;
							*pData++ = vec.z;
						}

						// generate texture coordinates, normalize position, modify by orientation to return +y up
						vec = orientation.Inverse() * vec;
						vec.Normalize();

						// find distance to sphere
						sphereDistance = Utility.Sqrt( cameraPosition * cameraPosition * ( vec.y * vec.y - 1.0f ) + sphereRadius * sphereRadius ) - cameraPosition * vec.y;

						vec.x *= sphereDistance;
						vec.z *= sphereDistance;

						// use x and y on sphere as texture coordinates, tiled
						float s = vec.x * ( 0.01f * uTiles );
						float t = vec.z * ( 0.01f * vTiles );
						for ( int i = 0; i < numberOfTexCoordSets; i++ )
						{
							*pData++ = s;
							*pData++ = ( 1 - t );
						}
					} // x
				} // y

				// unlock the buffer
				vertexBuffer.Unlock();
			} // unsafe
		}
Exemple #24
0
		private void _generatePlaneVertexData( HardwareVertexBuffer vbuf, int ySegments, int xSegments, float xSpace, float halfWidth, float ySpace, float halfHeight, Matrix4 transform, bool firstTime, bool normals, Matrix4 rotation, int numTexCoordSets, float xTexCoord, float yTexCoord, SubMesh subMesh, ref Vector3 min, ref Vector3 max, ref float maxSquaredLength )
		{
			Vector3 vec;
			unsafe
			{
				// lock the vertex buffer
				IntPtr data = vbuf.Lock( BufferLocking.Discard );

				float* pData = (float*)data.ToPointer();

				for ( int y = 0; y <= ySegments; y++ )
				{
					for ( int x = 0; x <= xSegments; x++ )
					{
						// centered on origin
						vec.x = ( x * xSpace ) - halfWidth;
						vec.y = ( y * ySpace ) - halfHeight;
						vec.z = 0.0f;

						vec = transform.TransformAffine( vec );

						*pData++ = vec.x;
						*pData++ = vec.y;
						*pData++ = vec.z;

						// Build bounds as we go
						if ( firstTime )
						{
							min = vec;
							max = vec;
							maxSquaredLength = vec.LengthSquared;
							firstTime = false;
						}
						else
						{
							min.Floor( vec );
							max.Ceil( vec );
							maxSquaredLength = Utility.Max( maxSquaredLength, vec.LengthSquared );
						}

						if ( normals )
						{
							vec = Vector3.UnitZ;
							vec = rotation.TransformAffine( vec );

							*pData++ = vec.x;
							*pData++ = vec.y;
							*pData++ = vec.z;
						}

						for ( int i = 0; i < numTexCoordSets; i++ )
						{
							*pData++ = x * xTexCoord;
							*pData++ = 1 - ( y * yTexCoord );
						} // for texCoords
					} // for x
				} // for y

				// unlock the buffer
				vbuf.Unlock();

				subMesh.useSharedVertices = true;

			} // unsafe
		}
		public override void RegisterVertexBufferSourceAndCopy( HardwareVertexBuffer sourceBuffer, HardwareVertexBuffer copy )
		{
			this._baseInstance.RegisterVertexBufferSourceAndCopy( sourceBuffer, copy );
		}
Exemple #26
0
 /// <summary>
 ///		Creates  a new buffer as a copy of the source, does not copy data.
 /// </summary>
 /// <param name="source">Source vertex buffer.</param>
 /// <param name="usage">New usage type.</param>
 /// <param name="useShadowBuffer">New shadow buffer choice.</param>
 /// <returns>A copy of the vertex buffer, but data is not copied.</returns>
 protected HardwareVertexBuffer MakeBufferCopy(HardwareVertexBuffer source, BufferUsage usage, bool useShadowBuffer)
 {
     return(CreateVertexBuffer(source.VertexSize, source.VertexCount, usage, useShadowBuffer));
 }
Exemple #27
0
        /// <summary>
        ///		Modifies the vertex data to be suitable for use for rendering shadow geometry.
        /// </summary>
        /// <remarks>
        ///		<para>
        ///			Preparing vertex data to generate a shadow volume involves firstly ensuring that the
        ///			vertex buffer containing the positions is a standalone vertex buffer,
        ///			with no other components in it. This method will therefore break apart any existing
        ///			vertex buffers if position is sharing a vertex buffer.
        ///			Secondly, it will double the size of this vertex buffer so that there are 2 copies of
        ///			the position data for the mesh. The first half is used for the original, and the second
        ///			half is used for the 'extruded' version. The vertex count used to render will remain
        ///			the same though, so as not to add any overhead to regular rendering of the object.
        ///			Both copies of the position are required in one buffer because shadow volumes stretch
        ///			from the original mesh to the extruded version.
        ///		</para>
        ///		<para>
        ///			It's important to appreciate that this method can fundamentally change the structure of your
        ///			vertex buffers, although in reality they will be new buffers. As it happens, if other
        ///			objects are using the original buffers then they will be unaffected because the reference
        ///			counting will keep them intact. However, if you have made any assumptions about the
        ///			structure of the vertex data in the buffers of this object, you may have to rethink them.
        ///		</para>
        /// </remarks>
        public void PrepareForShadowVolume()
        {
            /* NOTE
             *          Sinbad would dearly, dearly love to just use a 4D position buffer in order to
             *          store the extra 'w' value I need to differentiate between extruded and
             *          non-extruded sections of the buffer, so that vertex programs could use that.
             *          Hey, it works fine for GL. However, D3D9 in it's infinite stupidity, does not
             *          support 4d position vertices in the fixed-function pipeline. If you use them,
             *          you just see nothing. Since we can't know whether the application is going to use
             *          fixed function or vertex programs, we have to stick to 3d position vertices and
             *          store the 'w' in a separate 1D texture coordinate buffer, which is only used
             *          when rendering the shadow.
             */

            // Upfront, lets check whether we have vertex program capability
            var renderSystem      = Root.Instance.RenderSystem;
            var useVertexPrograms = false;

            if (renderSystem != null && renderSystem.Capabilities.HasCapability(Capabilities.VertexPrograms))
            {
                useVertexPrograms = true;
            }

            // Look for a position element
            var posElem = this.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.Position);

            if (posElem != null)
            {
                var posOldSource = posElem.Source;

                var vbuf = this.vertexBufferBinding.GetBuffer(posOldSource);

                var wasSharedBuffer = false;

                // Are there other elements in the buffer except for the position?
                if (vbuf.VertexSize > posElem.Size)
                {
                    // We need to create another buffer to contain the remaining elements
                    // Most drivers don't like gaps in the declaration, and in any case it's waste
                    wasSharedBuffer = true;
                }

                HardwareVertexBuffer newPosBuffer = null, newRemainderBuffer = null;
                var newRemainderDeclaration = (VertexDeclaration)this.vertexDeclaration.Clone();

                if (wasSharedBuffer)
                {
                    var found = false;
                    var index = 0;
                    do
                    {
                        if (newRemainderDeclaration.GetElement(index).Semantic == VertexElementSemantic.Position)
                        {
                            newRemainderDeclaration.RemoveElement(index);
                            found = true;
                        }
                        index++;
                    }while (!found);

                    newRemainderBuffer = HardwareBufferManager.Instance.CreateVertexBuffer(newRemainderDeclaration, vbuf.VertexCount,
                                                                                           vbuf.Usage, vbuf.HasShadowBuffer);
                }

                // Allocate new position buffer, will be FLOAT3 and 2x the size
                var oldVertexCount = vbuf.VertexCount;
                var newVertexCount = oldVertexCount * 2;

                var newPosDecl = HardwareBufferManager.Instance.CreateVertexDeclaration();
                newPosDecl.AddElement(0, 0, VertexElementType.Float3, VertexElementSemantic.Position);
                newPosBuffer = HardwareBufferManager.Instance.CreateVertexBuffer(newPosDecl, newVertexCount, vbuf.Usage,
                                                                                 vbuf.HasShadowBuffer);

                // Iterate over the old buffer, copying the appropriate elements and initializing the rest
                var baseSrcPtr = vbuf.Lock(BufferLocking.ReadOnly);

                // Point first destination pointer at the start of the new position buffer,
                // the other one half way along
                var destPtr = newPosBuffer.Lock(BufferLocking.Discard);
                // oldVertexCount * 3 * 4, since we are dealing with byte offsets here
                var dest2Ptr = destPtr + (oldVertexCount * 12);

                var prePosVertexSize    = 0;
                var postPosVertexSize   = 0;
                var postPosVertexOffset = 0;

                if (wasSharedBuffer)
                {
                    // Precalculate any dimensions of vertex areas outside the position
                    prePosVertexSize    = posElem.Offset;
                    postPosVertexOffset = prePosVertexSize + posElem.Size;
                    postPosVertexSize   = vbuf.VertexSize - postPosVertexOffset;

                    // the 2 separate bits together should be the same size as the remainder buffer vertex
                    Debug.Assert(newRemainderBuffer.VertexSize == (prePosVertexSize + postPosVertexSize));

                    var baseDestRemPtr = newRemainderBuffer.Lock(BufferLocking.Discard);

                    var baseSrcOffset     = 0;
                    var baseDestRemOffset = 0;

#if !AXIOM_SAFE_ONLY
                    unsafe
#endif
                    {
                        var pDest  = destPtr.ToFloatPointer();
                        var pDest2 = dest2Ptr.ToFloatPointer();

                        int destCount = 0, dest2Count = 0;

                        // Iterate over the vertices
                        for (var v = 0; v < oldVertexCount; v++)
                        {
                            var pSrc = (baseSrcPtr + (posElem.Offset + baseSrcOffset)).ToFloatPointer();

                            // Copy position, into both buffers
                            pDest[destCount++] = pDest2[dest2Count++] = pSrc[0];
                            pDest[destCount++] = pDest2[dest2Count++] = pSrc[1];
                            pDest[destCount++] = pDest2[dest2Count++] = pSrc[2];

                            // now deal with any other elements
                            // Basically we just memcpy the vertex excluding the position
                            if (prePosVertexSize > 0)
                            {
                                Memory.Copy(baseSrcPtr, baseDestRemPtr, baseSrcOffset, baseDestRemOffset, prePosVertexSize);
                            }

                            if (postPosVertexSize > 0)
                            {
                                Memory.Copy(baseSrcPtr, baseDestRemPtr, baseSrcOffset + postPosVertexOffset,
                                            baseDestRemOffset + prePosVertexSize, postPosVertexSize);
                            }

                            // increment the pointer offsets
                            baseDestRemOffset += newRemainderBuffer.VertexSize;
                            baseSrcOffset     += vbuf.VertexSize;
                        } // next vertex
                    }     // unsafe
                }
                else
                {
                    // copy the data directly
                    Memory.Copy(baseSrcPtr, destPtr, vbuf.Size);
                    Memory.Copy(baseSrcPtr, dest2Ptr, vbuf.Size);
                }

                vbuf.Unlock();
                newPosBuffer.Unlock();

                if (wasSharedBuffer)
                {
                    newRemainderBuffer.Unlock();
                }

                // At this stage, he original vertex buffer is going to be destroyed
                // So we should force the deallocation of any temporary copies
                HardwareBufferManager.Instance.ForceReleaseBufferCopies(vbuf);

                if (useVertexPrograms)
                {
#if !AXIOM_SAFE_ONLY
                    unsafe
#endif
                    {
                        var decl = HardwareBufferManager.Instance.CreateVertexDeclaration();
                        decl.AddElement(0, 0, VertexElementType.Float1, VertexElementSemantic.Position);

                        // Now it's time to set up the w buffer
                        this.hardwareShadowVolWBuffer = HardwareBufferManager.Instance.CreateVertexBuffer(decl, newVertexCount,
                                                                                                          BufferUsage.StaticWriteOnly,
                                                                                                          false);

                        // Fill the first half with 1.0, second half with 0.0
                        var wPtr      = this.hardwareShadowVolWBuffer.Lock(BufferLocking.Discard);
                        var pDest     = wPtr.ToFloatPointer();
                        var destCount = 0;

                        for (var v = 0; v < oldVertexCount; v++)
                        {
                            pDest[destCount++] = 1.0f;
                        }
                        for (var v = 0; v < oldVertexCount; v++)
                        {
                            pDest[destCount++] = 0.0f;
                        }
                    } // unsafe

                    this.hardwareShadowVolWBuffer.Unlock();
                } // if vertexPrograms

                short newPosBufferSource = 0;

                if (wasSharedBuffer)
                {
                    // Get the a new buffer binding index
                    newPosBufferSource = this.vertexBufferBinding.NextIndex;

                    // Re-bind the old index to the remainder buffer
                    this.vertexBufferBinding.SetBinding(posOldSource, newRemainderBuffer);
                }
                else
                {
                    // We can just re-use the same source idex for the new position buffer
                    newPosBufferSource = posOldSource;
                }

                // Bind the new position buffer
                this.vertexBufferBinding.SetBinding(newPosBufferSource, newPosBuffer);

                // Now, alter the vertex declaration to change the position source
                // and the offsets of elements using the same buffer
                for (var i = 0; i < this.vertexDeclaration.ElementCount; i++)
                {
                    var element = this.vertexDeclaration.GetElement(i);

                    if (element.Semantic == VertexElementSemantic.Position)
                    {
                        // Modify position to point at new position buffer
                        this.vertexDeclaration.ModifyElement(i, newPosBufferSource /* new source buffer */, 0 /* no offset now */,
                                                             VertexElementType.Float3, VertexElementSemantic.Position);
                    }
                    else if (wasSharedBuffer && element.Source == posOldSource && element.Offset > prePosVertexSize)
                    {
                        // This element came after position, remove the position's size
                        this.vertexDeclaration.ModifyElement(i, posOldSource /* same old source */, element.Offset - posElem.Size
                                                             /* less offset now */, element.Type, element.Semantic, element.Index);
                    }
                }
            } // if posElem != null
        }
Exemple #28
0
 /// <summary>
 ///     Allocates a copy of a given vertex buffer.
 /// </summary>
 /// <remarks>
 ///     This method allocates a temporary copy of an existing vertex buffer.
 ///     This buffer is subsequently stored and can be made available for
 ///     other purposes later without incurring the cost of construction /
 ///     destruction.
 /// </remarks>
 /// <param name="sourceBuffer">The source buffer to use as a copy.</param>
 /// <param name="licenseType">
 ///     The type of license required on this buffer - automatic
 ///     release causes this class to release licenses every frame so that
 ///     they can be reallocated anew.
 /// </param>
 /// <param name="licensee">
 ///     Reference back to the class requesting the copy, which must
 ///     implement <see cref="IHardwareBufferLicense"/> in order to be notified when the license
 ///     expires.
 /// </param>
 /// <returns></returns>
 public virtual HardwareVertexBuffer AllocateVertexBufferCopy(HardwareVertexBuffer sourceBuffer,
                                                              BufferLicenseRelease licenseType, IHardwareBufferLicensee licensee)
 {
     return(AllocateVertexBufferCopy(sourceBuffer, licenseType, licensee, false));
 }
Exemple #29
0
 public override void RegisterVertexBufferSourceAndCopy(HardwareVertexBuffer sourceBuffer, HardwareVertexBuffer copy)
 {
     this._baseInstance.RegisterVertexBufferSourceAndCopy(sourceBuffer, copy);
 }
        /// <summary>
        ///     Tells the system to build the mesh relating to the surface into externally created buffers.
        /// </summary>
        /// <remarks>
        ///     The VertexDeclaration of the vertex buffer must be identical to the one passed into
        ///     <see cref="DefineSurface"/>.  In addition, there must be enough space in the buffer to 
        ///     accommodate the patch at full detail level; you should check <see cref="RequiredVertexCount"/>
        ///     and <see cref="RequiredIndexCount"/> to determine this. This method does not create an internal
        ///     mesh for this patch and so GetMesh will return null if you call it after building the
        ///     patch this way.
        /// </remarks>
        /// <param name="destVertexBuffer">The destination vertex buffer in which to build the patch.</param>
        /// <param name="vertexStart">The offset at which to start writing vertices for this patch.</param>
        /// <param name="destIndexBuffer">The destination index buffer in which to build the patch.</param>
        /// <param name="indexStart">The offset at which to start writing indexes for this patch.</param>
        public void Build(HardwareVertexBuffer destVertexBuffer, int vertexStart, HardwareIndexBuffer destIndexBuffer, int indexStart)
        {
            if(controlPoints.Count == 0) {
                return;
            }

            vertexBuffer = destVertexBuffer;
            vertexOffset = vertexStart;
            indexBuffer = destIndexBuffer;
            indexOffset = indexStart;

            // lock just the region we are interested in
            IntPtr lockedBuffer = vertexBuffer.Lock(
                vertexOffset * declaration.GetVertexSize(0),
                requiredVertexCount * declaration.GetVertexSize(0),
                BufferLocking.NoOverwrite);

            DistributeControlPoints(lockedBuffer);

            // subdivide the curves to the max
            // Do u direction first, so need to step over v levels not done yet
            int vStep = 1 << maxVLevel;
            int uStep = 1 << maxULevel;

            // subdivide this row in u
            for(int v = 0; v < meshHeight; v += vStep) {
                SubdivideCurve(lockedBuffer, v * meshWidth, uStep, meshWidth / uStep, uLevel);
            }

            // Now subdivide in v direction, this time all the u direction points are there so no step
            for(int u = 0; u < meshWidth; u++) {
                SubdivideCurve(lockedBuffer, u, vStep * meshWidth, meshHeight / vStep, vLevel);
            }

            // don't forget to unlock!
            vertexBuffer.Unlock();

            // Make triangles from mesh at this current level of detail
            MakeTriangles();
        }
Exemple #31
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;
		}
Exemple #32
0
		/// <summary>
		///     Performs a software vertex morph, of the kind used for
		///     morph animation although it can be used for other purposes.
		/// </summary>
		/// <remarks>
		///   	This function will linearly interpolate positions between two
		/// 	source buffers, into a third buffer.
		/// </remarks>
		/// <param name="t">Parametric distance between the start and end buffer positions</param>
		/// <param name="b1">Vertex buffer containing VertexElementType.Float3 entries for the start positions</param>
		/// <param name="b2">Vertex buffer containing VertexElementType.Float3 entries for the end positions</param>
		/// <param name="targetVertexData"> VertexData destination; assumed to have a separate position
		///	     buffer already bound, and the number of vertices must agree with the
		///   number in start and end
		/// </param>
		public static void SoftwareVertexMorph( float t, HardwareVertexBuffer b1, HardwareVertexBuffer b2,
		                                        VertexData targetVertexData )
		{
#if !AXIOM_SAFE_ONLY
			unsafe
#endif
			{
				var bpb1 = b1.Lock( BufferLocking.ReadOnly ).ToFloatPointer();
				var pb1 = 0;
				var bpb2 = b2.Lock( BufferLocking.ReadOnly ).ToFloatPointer();
				var pb2 = 0;
				var posElem = targetVertexData.vertexDeclaration.FindElementBySemantic( VertexElementSemantic.Position );
				Debug.Assert( posElem != null );
				var destBuf = targetVertexData.vertexBufferBinding.GetBuffer( posElem.Source );
				Debug.Assert( posElem.Size == destBuf.VertexSize, "Positions must be in a buffer on their own for morphing" );
				var bpdst = destBuf.Lock( BufferLocking.Discard ).ToFloatPointer();
				var pdst = 0;
				for ( var i = 0; i < targetVertexData.vertexCount; ++i )
				{
					// x
					bpdst[ pdst++ ] = bpb1[ pb1 ] + t*( bpb2[ pb2 ] - bpb1[ pb1 ] );
					++pb1;
					++pb2;
					// y
					bpdst[ pdst++ ] = bpb1[ pb1 ] + t*( bpb2[ pb2 ] - bpb1[ pb1 ] );
					++pb1;
					++pb2;
					// z
					bpdst[ pdst++ ] = bpb1[ pb1 ] + t*( bpb2[ pb2 ] - bpb1[ pb1 ] );
					++pb1;
					++pb2;
				}
				destBuf.Unlock();
				b1.Unlock();
				b2.Unlock();
			}
		}
        /// <summary>
        ///		Clones this vertex data, potentially including replicating any vertex buffers.
        /// </summary>
        /// <param name="copyData">
        ///		If true, makes a copy the vertex buffer in addition to the definition.
        ///		If false, the clone will refer to the same vertex buffer this object refers to.
        /// </param>
        /// <returns>A cloned vertex data object.</returns>
        public VertexData Clone(bool copyData)
        {
            VertexData dest = new VertexData();

            // Copy vertex buffers in turn
            Dictionary <ushort, HardwareVertexBuffer> bindings = vertexBufferBinding.Bindings;

            foreach (ushort source in bindings.Keys)
            {
                HardwareVertexBuffer srcbuf = bindings[source];
                HardwareVertexBuffer dstBuf;

                if (copyData)
                {
                    // create new buffer with the same settings
                    dstBuf =
                        HardwareBufferManager.Instance.CreateVertexBuffer(
                            srcbuf.VertexSize, srcbuf.VertexCount, srcbuf.Usage,
                            srcbuf.HasShadowBuffer);

                    // copy data
                    dstBuf.CopyData(srcbuf, 0, 0, srcbuf.Size, true);
                }
                else
                {
                    // don't copy, point at existing buffer
                    dstBuf = srcbuf;
                }

                // Copy binding
                dest.vertexBufferBinding.SetBinding(source, dstBuf);
            }

            // Basic vertex info
            dest.vertexStart = this.vertexStart;
            dest.vertexCount = this.vertexCount;

            // Copy elements
            for (int i = 0; i < vertexDeclaration.ElementCount; i++)
            {
                VertexElement element = vertexDeclaration.GetElement(i);

                dest.vertexDeclaration.AddElement(
                    element.Source,
                    element.Offset,
                    element.Type,
                    element.Semantic,
                    element.Index);
            }

            // Copy hardware shadow buffer if set up
            if (hardwareShadowVolWBuffer != null)
            {
                dest.hardwareShadowVolWBuffer =
                    HardwareBufferManager.Instance.CreateVertexBuffer(
                        hardwareShadowVolWBuffer.VertexSize,
                        hardwareShadowVolWBuffer.VertexCount,
                        hardwareShadowVolWBuffer.Usage,
                        hardwareShadowVolWBuffer.HasShadowBuffer);

                // copy data
                dest.hardwareShadowVolWBuffer.CopyData(
                    hardwareShadowVolWBuffer, 0, 0,
                    hardwareShadowVolWBuffer.Size,
                    true);
            }

            // copy anim data
            dest.HWAnimationDataList = HWAnimationDataList;
            dest.HWAnimDataItemsUsed = HWAnimDataItemsUsed;

            return(dest);
        }
		public override HardwareVertexBuffer AllocateVertexBufferCopy( HardwareVertexBuffer sourceBuffer,
																	   BufferLicenseRelease licenseType,
#if NET_40
			IHardwareBufferLicensee licensee, bool copyData = false )
        private LineRenderable CreateNormalLines()
        {
            List<Vector3> points = new List<Vector3>();
            List<ColorEx> colors = new List<ColorEx>();

            foreach (SubEntity subEntity in loadedModel.SubEntities) {
                if (subEntity.IsVisible) {
                    VertexData vData = subEntity.SubMesh.VertexData;
                    VertexElement[] elems = new VertexElement[4];
                    elems[0] = vData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.Position);
                    elems[1] = vData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.Normal);
                    elems[2] = vData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.Tangent);
                    elems[3] = vData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.Binormal);
                    HardwareVertexBuffer[] vBuffers = new HardwareVertexBuffer[4];
                    for (int i = 0; i < 4; ++i) {
                        if (elems[i] == null)
                            vBuffers[i] = null;
                        else
                            vBuffers[i] = vData.vertexBufferBinding.Bindings[elems[i].Source];
                    }
                    Vector3[] positionVectors = ReadBuffer(vBuffers[0], elems[0], vData.vertexCount);
                    Vector3[] normalVectors   = ReadBuffer(vBuffers[1], elems[1], vData.vertexCount);
                    Vector3[] tangentVectors  = ReadBuffer(vBuffers[2], elems[2], vData.vertexCount);
                    Vector3[] binormalVectors = ReadBuffer(vBuffers[3], elems[3], vData.vertexCount);
                    for (int i = 0; i < vData.vertexCount; ++i)
                        BuildAxisLines(points, colors, positionVectors[i],
                                       normalsAxisLength * normalVectors[i],
                                       normalsAxisLength * tangentVectors[i],
                                       normalsAxisLength * binormalVectors[i]);
                }
            }

            if (points.Count == 0)
                return null;
            LineRenderable lines = new LineRenderable();
            lines.SetPoints(points, colors);
            lines.MaterialName = "MVLines";

            return lines;
        }
Exemple #36
0
		private void _generateCurvedPlaneVertexData( HardwareVertexBuffer vbuf, int ySegments, int xSegments, float xSpace, float halfWidth, float ySpace, float halfHeight, Matrix4 transform, bool firstTime, bool normals, Matrix4 rotation, float curvature, int numTexCoordSets, float xTexCoord, float yTexCoord, SubMesh subMesh, ref Vector3 min, ref Vector3 max, ref float maxSquaredLength )
		{
			Vector3 vec;
			unsafe
			{
				// lock the vertex buffer
				IntPtr data = vbuf.Lock( BufferLocking.Discard );

				float* pData = (float*)data.ToPointer();

				for ( int y = 0; y <= ySegments; y++ )
				{
					for ( int x = 0; x <= xSegments; x++ )
					{
						// centered on origin
						vec.x = ( x * xSpace ) - halfWidth;
						vec.y = ( y * ySpace ) - halfHeight;

						// Here's where curved plane is different from standard plane.  Amazing, I know.
						Real diff_x = ( x - ( (Real)xSegments / 2 ) ) / (Real)xSegments;
						Real diff_y = ( y - ( (Real)ySegments / 2 ) ) / (Real)ySegments;
						Real dist = Utility.Sqrt( diff_x * diff_x + diff_y * diff_y );
						vec.z = ( -Utility.Sin( ( 1 - dist ) * ( Utility.PI / 2 ) ) * curvature ) + curvature;

						// Transform by orientation and distance
						Vector3 pos = transform.TransformAffine( vec );

						*pData++ = pos.x;
						*pData++ = pos.y;
						*pData++ = pos.z;

						// Build bounds as we go
						if ( firstTime )
						{
							min = vec;
							max = vec;
							maxSquaredLength = vec.LengthSquared;
							firstTime = false;
						}
						else
						{
							min.Floor( vec );
							max.Ceil( vec );
							maxSquaredLength = Utility.Max( maxSquaredLength, vec.LengthSquared );
						}

						if ( normals )
						{
							// This part is kinda 'wrong' for curved planes... but curved planes are
							//   very valuable outside sky planes, which don't typically need normals
							//   so I'm not going to mess with it for now.

							// Default normal is along unit Z
							//vec = Vector3::UNIT_Z;
							// Rotate
							vec = rotation.TransformAffine( vec );

							*pData++ = vec.x;
							*pData++ = vec.y;
							*pData++ = vec.z;
						}

						for ( int i = 0; i < numTexCoordSets; i++ )
						{
							*pData++ = x * xTexCoord;
							*pData++ = 1 - ( y * yTexCoord );
						} // for texCoords
					} // for x
				} // for y

				// unlock the buffer
				vbuf.Unlock();

				subMesh.useSharedVertices = true;

			} // unsafe
		}
        /// <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();
        }
		//public override RegisterVertexBufferSourceAndCopy( HardwareVertexBuffer sourceBuffer, HardwareVertexBuffer copy )
		//{
		//}

		public override HardwareVertexBuffer AllocateVertexBufferCopy( HardwareVertexBuffer sourceBuffer, BufferLicenseRelease licenseType, IHardwareBufferLicensee licensee, bool copyData )
		{
			return _baseInstance.AllocateVertexBufferCopy( sourceBuffer, licenseType, licensee, copyData );
		}
        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);
                }
            }
        }
		public override void ForceReleaseBufferCopies( HardwareVertexBuffer sourceBuffer )
		{
			_baseInstance.ForceReleaseBufferCopies( sourceBuffer );
		}
 /// <summary>
 ///     Implementation of LicenseExpired.
 /// </summary>
 /// <param name="buffer"></param>
 public void LicenseExpired(HardwareBuffer buffer)
 {
     if(buffer == destPositionBuffer) {
         destPositionBuffer = null;
     }
     if(buffer == destNormalBuffer) {
         destNormalBuffer = null;
     }
 }
Exemple #42
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);
            }
        }
Exemple #43
0
		/// <summary>
		///		Updates the face normals for this edge list based on (changed)
		///		position information, useful for animated objects. 
		/// </summary>
		/// <param name="vertexSet">The vertex set we are updating.</param>
		/// <param name="positionBuffer">The updated position buffer, must contain ONLY xyz.</param>
		public void UpdateFaceNormals( int vertexSet, HardwareVertexBuffer positionBuffer )
		{
#if !AXIOM_SAFE_ONLY
			unsafe
#endif
			{
				Debug.Assert( positionBuffer.VertexSize == sizeof ( float )*3, "Position buffer should contain only positions!" );

				// Lock buffer for reading
				var posPtr = positionBuffer.Lock( BufferLocking.ReadOnly );
				var pVert = posPtr.ToFloatPointer();

				// Iterate over the triangles
				for ( var i = 0; i < this.triangles.Count; i++ )
				{
					var t = (Triangle)this.triangles[ i ];

					// Only update tris which are using this vertex set
					if ( t.vertexSet == vertexSet )
					{
						var offset = t.vertIndex[ 0 ]*3;
						var v1 = new Vector3( pVert[ offset ], pVert[ offset + 1 ], pVert[ offset + 2 ] );

						offset = t.vertIndex[ 1 ]*3;
						var v2 = new Vector3( pVert[ offset ], pVert[ offset + 1 ], pVert[ offset + 2 ] );

						offset = t.vertIndex[ 2 ]*3;
						var v3 = new Vector3( pVert[ offset ], pVert[ offset + 1 ], pVert[ offset + 2 ] );

						t.normal = Utility.CalculateFaceNormal( v1, v2, v3 );
					}
				}
			}

			// unlock the buffer
			positionBuffer.Unlock();
		}
Exemple #44
0
 /// <summary>
 ///		Set a binding, associating a vertex buffer with a given index.
 /// </summary>
 /// <remarks>
 ///		If the index is already associated with a vertex buffer,
 ///		the association will be replaced. This may cause the old buffer
 ///		to be destroyed if nothing else is referring to it.
 ///		You should assign bindings from 0 and not leave gaps, although you can
 ///		bind them in any order.
 /// </remarks>
 /// <param name="index">Index at which to bind the buffer.</param>
 /// <param name="buffer">Vertex buffer to bind.</param>
 public virtual void SetBinding(short index, HardwareVertexBuffer buffer)
 {
     this.bindingMap[index] = buffer;
     this.highIndex         = (short)Utility.Max(this.highIndex, index + 1);
 }
        public virtual HardwareVertexBuffer AllocateVertexBufferCopy(HardwareVertexBuffer sourceBuffer,
                                                                     BufferLicenseRelease licenseType,
#if NET_40
                                                                     IHardwareBufferLicensee licensee, bool copyData = false)
 private static Vector3[] ReadBuffer(HardwareVertexBuffer vBuffer, VertexElement elem, int vertexCount)
 {
     Vector3[] rv = new Vector3[vertexCount];
     if (vBuffer == null) {
         for (int i = 0; i < vertexCount; ++i)
             rv[i] = Vector3.Zero;
         return rv;
     }
     float[,] data = new float[vertexCount, 3];
     HardwareBufferHelper.ReadBuffer( data, vBuffer, elem );
     for (int i = 0; i < vertexCount; ++i)
         for (int j = 0; j < 3; ++j)
             rv[i][j] = data[i, j];
     return rv;
 }
Exemple #47
0
			/// <summary>
			///		Rebind the source positions for temp buffer users.
			/// </summary>
			public void RebindPositionBuffer( VertexData vertexData, bool force )
			{
				if ( force || this.currentVertexData != vertexData )
				{
					this.currentVertexData = vertexData;
					this.positionBuffer = this.currentVertexData.vertexBufferBinding.GetBuffer( this.originalPosBufferBinding );
					renderOperation.vertexData.vertexBufferBinding.SetBinding( 0, this.positionBuffer );
					if ( lightCap != null )
					{
						( (EntityShadowRenderable)lightCap ).RebindPositionBuffer( vertexData, force );
					}
				}
			}
Exemple #48
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;
		}
Exemple #49
0
		/// <summary>
		///		Modifies the vertex data to be suitable for use for rendering shadow geometry.
		/// </summary>
		/// <remarks>
		///		<para>
		///			Preparing vertex data to generate a shadow volume involves firstly ensuring that the
		///			vertex buffer containing the positions is a standalone vertex buffer,
		///			with no other components in it. This method will therefore break apart any existing
		///			vertex buffers if position is sharing a vertex buffer.
		///			Secondly, it will double the size of this vertex buffer so that there are 2 copies of
		///			the position data for the mesh. The first half is used for the original, and the second
		///			half is used for the 'extruded' version. The vertex count used to render will remain
		///			the same though, so as not to add any overhead to regular rendering of the object.
		///			Both copies of the position are required in one buffer because shadow volumes stretch
		///			from the original mesh to the extruded version.
		///		</para>
		///		<para>
		///			It's important to appreciate that this method can fundamentally change the structure of your
		///			vertex buffers, although in reality they will be new buffers. As it happens, if other
		///			objects are using the original buffers then they will be unaffected because the reference
		///			counting will keep them intact. However, if you have made any assumptions about the
		///			structure of the vertex data in the buffers of this object, you may have to rethink them.
		///		</para>
		/// </remarks>
		public void PrepareForShadowVolume()
		{
			/* NOTE
			Sinbad would dearly, dearly love to just use a 4D position buffer in order to
			store the extra 'w' value I need to differentiate between extruded and
			non-extruded sections of the buffer, so that vertex programs could use that.
			Hey, it works fine for GL. However, D3D9 in it's infinite stupidity, does not
			support 4d position vertices in the fixed-function pipeline. If you use them,
			you just see nothing. Since we can't know whether the application is going to use
			fixed function or vertex programs, we have to stick to 3d position vertices and
			store the 'w' in a separate 1D texture coordinate buffer, which is only used
			when rendering the shadow.
			*/

			// Upfront, lets check whether we have vertex program capability
			RenderSystem renderSystem = Root.Instance.RenderSystem;
			bool useVertexPrograms = false;

			if ( renderSystem != null && renderSystem.Capabilities.HasCapability( Capabilities.VertexPrograms ) )
			{
				useVertexPrograms = true;
			}

			// Look for a position element
			VertexElement posElem =	vertexDeclaration.FindElementBySemantic( VertexElementSemantic.Position );

			if ( posElem != null )
			{
				short posOldSource = posElem.Source;

				HardwareVertexBuffer vbuf = vertexBufferBinding.GetBuffer( posOldSource );

				bool wasSharedBuffer = false;

				// Are there other elements in the buffer except for the position?
				if ( vbuf.VertexSize > posElem.Size )
				{
					// We need to create another buffer to contain the remaining elements
					// Most drivers don't like gaps in the declaration, and in any case it's waste
					wasSharedBuffer = true;
				}

				HardwareVertexBuffer newPosBuffer = null, newRemainderBuffer = null;
                VertexDeclaration newRemainderDeclaration = (VertexDeclaration)vertexDeclaration.Clone();

				if ( wasSharedBuffer )
				{
                    bool found = false;
                    int index = 0;
                    do 
                    {
                        if (newRemainderDeclaration.GetElement(index).Semantic == VertexElementSemantic.Position)
                        {
                            newRemainderDeclaration.RemoveElement(index);
                            found = true;
                        }
                        index++;
                    } while ( !found );

					newRemainderBuffer = HardwareBufferManager.Instance.CreateVertexBuffer( newRemainderDeclaration, vbuf.VertexCount, vbuf.Usage, vbuf.HasShadowBuffer );
				}

				// Allocate new position buffer, will be FLOAT3 and 2x the size
				int oldVertexCount = vbuf.VertexCount;
				int newVertexCount = oldVertexCount * 2;

                VertexDeclaration newPosDecl = HardwareBufferManager.Instance.CreateVertexDeclaration();
                newPosDecl.AddElement( 0, 0, VertexElementType.Float3, VertexElementSemantic.Position );
                newPosBuffer = HardwareBufferManager.Instance.CreateVertexBuffer( newPosDecl, newVertexCount, vbuf.Usage, vbuf.HasShadowBuffer );

				// Iterate over the old buffer, copying the appropriate elements and initializing the rest
				IntPtr baseSrcPtr = vbuf.Lock( BufferLocking.ReadOnly );

				// Point first destination pointer at the start of the new position buffer,
				// the other one half way along
				IntPtr destPtr = newPosBuffer.Lock( BufferLocking.Discard );
				// oldVertexCount * 3 * 4, since we are dealing with byte offsets here
				IntPtr dest2Ptr = new IntPtr( destPtr.ToInt64() + ( oldVertexCount * 12 ) );

				int prePosVertexSize = 0;
				int postPosVertexSize = 0;
				int postPosVertexOffset = 0;

				if ( wasSharedBuffer )
				{
					// Precalculate any dimensions of vertex areas outside the position
					prePosVertexSize = posElem.Offset;
					postPosVertexOffset = prePosVertexSize + posElem.Size;
					postPosVertexSize = vbuf.VertexSize - postPosVertexOffset;

					// the 2 separate bits together should be the same size as the remainder buffer vertex
					Debug.Assert( newRemainderBuffer.VertexSize == ( prePosVertexSize + postPosVertexSize ) );

					IntPtr baseDestRemPtr = newRemainderBuffer.Lock( BufferLocking.Discard );

					int baseSrcOffset = 0;
					int baseDestRemOffset = 0;

					unsafe
					{
						float* pDest = (float*)destPtr.ToPointer();
						float* pDest2 = (float*)dest2Ptr.ToPointer();

						int destCount = 0, dest2Count = 0;

						// Iterate over the vertices
						for ( int v = 0; v < oldVertexCount; v++ )
						{
							float* pSrc = (float*)( (byte*)baseSrcPtr.ToPointer() + posElem.Offset + baseSrcOffset );

							// Copy position, into both buffers
							pDest[ destCount++ ] = pDest2[ dest2Count++ ] = pSrc[ 0 ];
							pDest[ destCount++ ] = pDest2[ dest2Count++ ] = pSrc[ 1 ];
							pDest[ destCount++ ] = pDest2[ dest2Count++ ] = pSrc[ 2 ];

							// now deal with any other elements
							// Basically we just memcpy the vertex excluding the position
							if ( prePosVertexSize > 0 )
							{
								Memory.Copy( baseSrcPtr, baseDestRemPtr, baseSrcOffset, baseDestRemOffset, prePosVertexSize );
							}

							if ( postPosVertexSize > 0 )
							{
								Memory.Copy( baseSrcPtr, baseDestRemPtr, baseSrcOffset + postPosVertexOffset, baseDestRemOffset + prePosVertexSize, postPosVertexSize );
							}

							// increment the pointer offsets
							baseDestRemOffset += newRemainderBuffer.VertexSize;
							baseSrcOffset += vbuf.VertexSize;
						} // next vertex
					} // unsafe
				}
				else
				{
					// copy the data directly
					Memory.Copy( baseSrcPtr, destPtr, vbuf.Size );
					Memory.Copy( baseSrcPtr, dest2Ptr, vbuf.Size );
				}

				vbuf.Unlock();
				newPosBuffer.Unlock();

				if ( wasSharedBuffer )
				{
					newRemainderBuffer.Unlock();
				}

				// At this stage, he original vertex buffer is going to be destroyed
				// So we should force the deallocation of any temporary copies
				HardwareBufferManager.Instance.ForceReleaseBufferCopies( vbuf );

				if ( useVertexPrograms )
				{
					unsafe
					{
                        VertexDeclaration decl = HardwareBufferManager.Instance.CreateVertexDeclaration();
                        decl.AddElement(0, 0, VertexElementType.Float1, VertexElementSemantic.Position);

						// Now it's time to set up the w buffer
						hardwareShadowVolWBuffer = HardwareBufferManager.Instance.CreateVertexBuffer( decl,	newVertexCount,	BufferUsage.StaticWriteOnly, false );

						// Fill the first half with 1.0, second half with 0.0
						IntPtr wPtr = hardwareShadowVolWBuffer.Lock( BufferLocking.Discard );
						float* pDest = (float*)wPtr.ToPointer();
						int destCount = 0;

						for ( int v = 0; v < oldVertexCount; v++ )
						{
							pDest[ destCount++ ] = 1.0f;
						}
						for ( int v = 0; v < oldVertexCount; v++ )
						{
							pDest[ destCount++ ] = 0.0f;
						}
					} // unsafe

					hardwareShadowVolWBuffer.Unlock();
				} // if vertexPrograms

				short newPosBufferSource = 0;

				if ( wasSharedBuffer )
				{
					// Get the a new buffer binding index
					newPosBufferSource = vertexBufferBinding.NextIndex;

					// Re-bind the old index to the remainder buffer
					vertexBufferBinding.SetBinding( posOldSource, newRemainderBuffer );
				}
				else
				{
					// We can just re-use the same source idex for the new position buffer
					newPosBufferSource = posOldSource;
				}

				// Bind the new position buffer
				vertexBufferBinding.SetBinding( newPosBufferSource, newPosBuffer );

				// Now, alter the vertex declaration to change the position source
				// and the offsets of elements using the same buffer
				for ( int i = 0; i < vertexDeclaration.ElementCount; i++ )
				{
					VertexElement element = vertexDeclaration.GetElement( i );

					if ( element.Semantic == VertexElementSemantic.Position )
					{
						// Modify position to point at new position buffer
						vertexDeclaration.ModifyElement( i, newPosBufferSource /* new source buffer */,  0 /* no offset now */, VertexElementType.Float3, VertexElementSemantic.Position );
					}
					else if ( wasSharedBuffer &&
						element.Source == posOldSource &&
						element.Offset > prePosVertexSize )
					{
						// This element came after position, remove the position's size
						vertexDeclaration.ModifyElement( i, posOldSource /* same old source */, 	element.Offset - posElem.Size /* less offset now */, element.Type, element.Semantic, element.Index );
					}
				}
			} // if posElem != null
		}
		protected void WriteGeometryVertexBuffer( BinaryWriter writer, short bindIndex, HardwareVertexBuffer vertexBuffer )
		{
			var start_offset = writer.Seek( 0, SeekOrigin.Current );
			WriteChunk( writer, MeshChunkID.GeometryVertexBuffer, 0 );

			WriteShort( writer, bindIndex );
			WriteShort( writer, (short)vertexBuffer.VertexSize );
			var buf = vertexBuffer.Lock( BufferLocking.Discard );
			try
			{
				WriteGeometryVertexBufferData( writer, vertexBuffer.Size, buf );
			}
			finally
			{
				vertexBuffer.Unlock();
			}

			var end_offset = writer.Seek( 0, SeekOrigin.Current );
			writer.Seek( (int)start_offset, SeekOrigin.Begin );
			WriteChunk( writer, MeshChunkID.GeometryVertexBuffer, (int)( end_offset - start_offset ) );
			writer.Seek( (int)end_offset, SeekOrigin.Begin );
		}
Exemple #51
0
 /// <summary>
 ///		Set a binding, associating a vertex buffer with a given index.
 /// </summary>
 /// <remarks>
 ///		If the index is already associated with a vertex buffer,
 ///		the association will be replaced. This may cause the old buffer
 ///		to be destroyed if nothing else is referring to it.
 ///		You should assign bindings from 0 and not leave gaps, although you can
 ///		bind them in any order.
 /// </remarks>
 /// <param name="index">Index at which to bind the buffer.</param>
 /// <param name="buffer">Vertex buffer to bind.</param>
 public virtual void SetBinding(ushort index, HardwareVertexBuffer buffer)
 {
     bindingMap[index] = buffer;
     highIndex         = (ushort)MathUtil.Max(highIndex, index + 1);
 }
Exemple #52
0
			public EntityShadowRenderable( Entity parent, HardwareIndexBuffer indexBuffer, VertexData vertexData,
			                               bool createSeparateLightCap, SubEntity subEntity, bool isLightCap )
			{
				this.parent = parent;

				// Save link to vertex data
				this.currentVertexData = vertexData;

				// Initialize render op
				renderOperation.indexData = new IndexData();
				renderOperation.indexData.indexBuffer = indexBuffer;
				renderOperation.indexData.indexStart = 0;
				// index start and count are sorted out later

				// Create vertex data which just references position component (and 2 component)
				renderOperation.vertexData = new VertexData();
				renderOperation.vertexData.vertexDeclaration = HardwareBufferManager.Instance.CreateVertexDeclaration();
				renderOperation.vertexData.vertexBufferBinding = HardwareBufferManager.Instance.CreateVertexBufferBinding();

				// Map in position data
				renderOperation.vertexData.vertexDeclaration.AddElement( 0, 0, VertexElementType.Float3,
				                                                         VertexElementSemantic.Position );
				this.originalPosBufferBinding =
					vertexData.vertexDeclaration.FindElementBySemantic( VertexElementSemantic.Position ).Source;

				this.positionBuffer = vertexData.vertexBufferBinding.GetBuffer( this.originalPosBufferBinding );
				renderOperation.vertexData.vertexBufferBinding.SetBinding( 0, this.positionBuffer );

				// Map in w-coord buffer (if present)
				if ( vertexData.hardwareShadowVolWBuffer != null )
				{
					renderOperation.vertexData.vertexDeclaration.AddElement( 1, 0, VertexElementType.Float1,
					                                                         VertexElementSemantic.TexCoords, 0 );
					this.wBuffer = vertexData.hardwareShadowVolWBuffer;
					renderOperation.vertexData.vertexBufferBinding.SetBinding( 1, this.wBuffer );
				}

				// Use same vertex start as input
				renderOperation.vertexData.vertexStart = vertexData.vertexStart;

				if ( isLightCap )
				{
					// Use original vertex count, no extrusion
					renderOperation.vertexData.vertexCount = vertexData.vertexCount;
				}
				else
				{
					// Vertex count must take into account the doubling of the buffer,
					// because second half of the buffer is the extruded copy
					renderOperation.vertexData.vertexCount = vertexData.vertexCount*2;

					if ( createSeparateLightCap )
					{
						// Create child light cap
						lightCap = new EntityShadowRenderable( parent, indexBuffer, vertexData, false, subEntity, true );
					}
				}
			}
        /// <summary>
        ///     Utility method, checks out temporary copies of src into dest.
        /// </summary>
        public void CheckoutTempCopies(bool positions, bool normals, bool tangents, bool binormals)
        {
            bindPositions = positions;
            bindNormals = normals;
            bindTangents = tangents;
            bindBinormals = binormals;

            if(bindPositions && destPositionBuffer == null) {
                destPositionBuffer =
                    HardwareBufferManager.Instance.AllocateVertexBufferCopy(
                    srcPositionBuffer,
                    BufferLicenseRelease.Automatic,
                    this);
            }

            if (bindNormals && !posNormalShareBuffer &&
                srcNormalBuffer != null && destNormalBuffer == null) {
                destNormalBuffer =
                    HardwareBufferManager.Instance.AllocateVertexBufferCopy(
                    srcNormalBuffer,
                    BufferLicenseRelease.Automatic,
                    this);
            }

            if (bindTangents && srcTangentBuffer != null) {
                if (this.tanBindIndex != this.posBindIndex &&
                    this.tanBindIndex != this.normBindIndex) {
                    destTangentBuffer =
                           HardwareBufferManager.Instance.AllocateVertexBufferCopy(
                           srcTangentBuffer,
                           BufferLicenseRelease.Automatic,
                           this);
                }
            }

            if (bindNormals && srcBinormalBuffer != null) {
                if (this.binormBindIndex != this.posBindIndex &&
                    this.binormBindIndex != this.normBindIndex &&
                    this.binormBindIndex != this.tanBindIndex) {
                    destBinormalBuffer =
                        HardwareBufferManager.Instance.AllocateVertexBufferCopy(
                        srcBinormalBuffer,
                        BufferLicenseRelease.Automatic,
                        this);
                }
            }
        }
Exemple #54
0
			/// <summary>
			/// 
			/// </summary>
			/// <param name="disposeManagedResources"></param>
			protected override void dispose( bool disposeManagedResources )
			{
				if ( !IsDisposed )
				{
					if ( disposeManagedResources )
					{
						// Dispose managed resources.
						if ( lightCap != null )
						{
							if ( !lightCap.IsDisposed )
							{
								lightCap.Dispose();
							}

							lightCap = null;
						}

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

							this.wBuffer = null;
						}

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

							this.positionBuffer = null;
						}

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

							this.subEntity = null;
						}

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

							this.currentVertexData = null;
						}
					}

					// 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 );
			}
        /// <summary>
        ///		Utility method, extract info from the given VertexData
        /// </summary>
        public void ExtractFrom(VertexData sourceData)
        {
            // Release old buffer copies first
            HardwareBufferManager mgr = HardwareBufferManager.Instance;
            if (destPositionBuffer != null) {
                mgr.ReleaseVertexBufferCopy(destPositionBuffer);
                Debug.Assert(destPositionBuffer == null);
            }
            if (destNormalBuffer != null) {
                mgr.ReleaseVertexBufferCopy(destNormalBuffer);
                Debug.Assert(destNormalBuffer == null);
            }

            VertexDeclaration decl = sourceData.vertexDeclaration;
            VertexBufferBinding bind = sourceData.vertexBufferBinding;
            VertexElement posElem = decl.FindElementBySemantic(VertexElementSemantic.Position);
            VertexElement normElem = decl.FindElementBySemantic(VertexElementSemantic.Normal);
            VertexElement tanElem = decl.FindElementBySemantic(VertexElementSemantic.Tangent);
            VertexElement binormElem = decl.FindElementBySemantic(VertexElementSemantic.Binormal);

            Debug.Assert(posElem != null, "Positions are required");

            posBindIndex = posElem.Source;
            srcPositionBuffer = bind.GetBuffer(posBindIndex);

            if (normElem == null) {
                posNormalShareBuffer = false;
                srcNormalBuffer = null;
            }
            else {
                normBindIndex = normElem.Source;
                if (normBindIndex == posBindIndex) {
                    posNormalShareBuffer = true;
                    srcNormalBuffer = null;
                }
                else {
                    posNormalShareBuffer = false;
                    srcNormalBuffer = bind.GetBuffer(normBindIndex);
                }
            }
            if (tanElem == null)
                srcTangentBuffer = null;
            else {
                tanBindIndex = tanElem.Source;
                srcTangentBuffer = bind.GetBuffer(tanBindIndex);
            }

            if (binormElem == null)
                srcBinormalBuffer = null;
            else {
                binormBindIndex = binormElem.Source;
                srcBinormalBuffer = bind.GetBuffer(binormBindIndex);
            }
        }
 /// <summary>
 ///		Set a binding, associating a vertex buffer with a given index.
 /// </summary>
 /// <remarks>
 ///		If the index is already associated with a vertex buffer, 
 ///		the association will be replaced. This may cause the old buffer
 ///		to be destroyed if nothing else is referring to it.
 ///		You should assign bindings from 0 and not leave gaps, although you can
 ///		bind them in any order.
 /// </remarks>
 /// <param name="index">Index at which to bind the buffer.</param>
 /// <param name="buffer">Vertex buffer to bind.</param>
 public virtual void SetBinding(ushort index, HardwareVertexBuffer buffer)
 {
     bindingMap[index] = buffer;
     highIndex = (ushort)MathUtil.Max(highIndex, index + 1);
 }
        protected void SetPointsImpl(List <Vector3> points, List <ColorEx> colors, List <List <VertexBoneAssignment> > boneAssignments)
        {
            if (colors != null && points.Count != colors.Count)
            {
                throw new Exception("Invalid parameters to SetPoints.  Point list length does not match colors list length");
            }
            Vector3 min = Vector3.Zero;
            Vector3 max = Vector3.Zero;

            // set up vertex data
            vertexData = new VertexData();

            // set up vertex declaration
            VertexDeclaration vertexDeclaration = vertexData.vertexDeclaration;
            int currentOffset = 0;

            // always need positions
            vertexDeclaration.AddElement(0, currentOffset, VertexElementType.Float3, VertexElementSemantic.Position);
            currentOffset += VertexElement.GetTypeSize(VertexElementType.Float3);
            int colorOffset = currentOffset / sizeof(float);

            if (colors != null)
            {
                vertexDeclaration.AddElement(0, currentOffset, VertexElementType.Color, VertexElementSemantic.Diffuse);
                currentOffset += VertexElement.GetTypeSize(VertexElementType.Color);
            }
            int boneIndexOffset = currentOffset / sizeof(float);

            if (boneAssignments != null)
            {
                vertexDeclaration.AddElement(0, currentOffset, VertexElementType.UByte4, VertexElementSemantic.BlendIndices);
                currentOffset += VertexElement.GetTypeSize(VertexElementType.UByte4);
            }
            int boneWeightOffset = currentOffset / sizeof(float);

            if (boneAssignments != null)
            {
                vertexDeclaration.AddElement(0, currentOffset, VertexElementType.Float4, VertexElementSemantic.BlendWeights);
                currentOffset += VertexElement.GetTypeSize(VertexElementType.Float4);
            }
            int stride = currentOffset / sizeof(float);

            vertexData.vertexCount = points.Count;

            // allocate vertex buffer
            HardwareVertexBuffer vertexBuffer = HardwareBufferManager.Instance.CreateVertexBuffer(vertexDeclaration.GetVertexSize(0), vertexData.vertexCount, BufferUsage.StaticWriteOnly);

            // set up the binding, one source only
            VertexBufferBinding binding = vertexData.vertexBufferBinding;

            binding.SetBinding(0, vertexBuffer);

            // Generate vertex data
            unsafe {
                // lock the vertex buffer
                IntPtr data = vertexBuffer.Lock(BufferLocking.Discard);

                byte * pData  = (byte *)data.ToPointer();
                float *pFloat = (float *)pData;
                uint * pInt   = (uint *)pData;
                for (int i = 0; i < points.Count; ++i)
                {
                    Vector3 vec = points[i];
                    // assign to geometry
                    pFloat[stride * i]     = vec.x;
                    pFloat[stride * i + 1] = vec.y;
                    pFloat[stride * i + 2] = vec.z;
                    if (colors != null)
                    {
                        // assign to diffuse
                        pInt[stride * i + colorOffset] = Root.Instance.RenderSystem.ConvertColor(colors[i]);
                    }
                    if (boneAssignments != null)
                    {
                        for (int j = 0; j < 4; ++j)
                        {
                            pData[4 * (stride * i + boneIndexOffset) + j] = (byte)(boneAssignments[i][j].boneIndex);
                            pFloat[stride * i + boneWeightOffset + j]     = boneAssignments[i][j].weight;
                        }
                    }
                }
                // unlock the buffer
                vertexBuffer.Unlock();
            } // unsafe

            for (int i = 0; i < points.Count; ++i)
            {
                Vector3 vec = points[i];
                // Also update the bounding sphere radius
                float len = vec.Length;
                if (len > boundingSphereRadius)
                {
                    boundingSphereRadius = len;
                }
                // Also update the bounding box
                if (vec.x < min.x)
                {
                    min.x = vec.x;
                }
                if (vec.y < min.y)
                {
                    min.y = vec.y;
                }
                if (vec.z < min.z)
                {
                    min.z = vec.z;
                }
                if (vec.x > max.x)
                {
                    max.x = vec.x;
                }
                if (vec.y > max.y)
                {
                    max.y = vec.y;
                }
                if (vec.z > max.z)
                {
                    max.z = vec.z;
                }
            }

            // Set the SimpleRenderable bounding box
            box = new AxisAlignedBox(min, max);
        }