This class declares the usage of a single vertex buffer as a component of a complete VertexDeclaration.
Inheritance: ICloneable
        /// <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();
        }
Esempio n. 2
0
        public override Axiom.Graphics.VertexElement AddElement(ushort source, int offset, VertexElementType type, VertexElementSemantic semantic, int index)
        {
            Axiom.Graphics.VertexElement element = base.AddElement(source, offset, type, semantic, index);

            needsRebuild = true;

            return(element);
        }
Esempio n. 3
0
        public override Axiom.Graphics.VertexElement InsertElement(int position, ushort source, int offset, VertexElementType type, VertexElementSemantic semantic, int index)
        {
            Axiom.Graphics.VertexElement element = base.InsertElement(position, source, offset, type, semantic, index);

            needsRebuild = true;

            return(element);
        }
Esempio n. 4
0
        /// <summary>
        ///     Gets the vertex size defined by this declaration for a given source.
        /// </summary>
        /// <param name="source">The buffer binding index for which to get the vertex size.</param>
        public virtual int GetVertexSize(ushort source)
        {
            int size = 0;

            for (int i = 0; i < elements.Count; i++)
            {
                VertexElement element = elements[i];

                // do they match?
                if (element.Source == source)
                {
                    size += element.Size;
                }
            }

            // return the size
            return(size);
        }
Esempio n. 5
0
        /// <summary>
        ///     Gets a list of elements which use a given source.
        /// </summary>
        public virtual List <VertexElement> FindElementBySource(ushort source)
        {
            List <VertexElement> rv = new List <VertexElement>();

            for (int i = 0; i < elements.Count; i++)
            {
                VertexElement element = elements[i];

                // do they match?
                if (element.Source == source)
                {
                    rv.Add(element);
                }
            }

            // return the list
            return(rv);
        }
Esempio n. 6
0
            // Sort routine for VertexElement

            #region IComparer Members

            public int Compare(VertexElement e1, VertexElement e2)
            {
                // Sort by source first

                if (e1 == null && e2 == null)
                {
                    return(0);
                }

                if (e1 == null)
                {
                    return(-1);
                }
                else if (e2 == null)
                {
                    return(1);
                }

                if (e1.Source < e2.Source)
                {
                    return(-1);
                }
                else if (e1.Source == e2.Source)
                {
                    // Use ordering of semantics to sort
                    if (e1.Semantic < e2.Semantic)
                    {
                        return(-1);
                    }
                    else if (e1.Semantic == e2.Semantic)
                    {
                        // Use index to sort
                        if (e1.Index < e2.Index)
                        {
                            return(-1);
                        }
                        else if (e1.Index == e2.Index)
                        {
                            return(0);
                        }
                    }
                }
                return(1);
            }
Esempio n. 7
0
        /// <summary>
        ///     Tests equality of 2 <see cref="VertexElement"/> objects.
        /// </summary>
        /// <param name="left">A <see cref="VertexElement"/></param>
        /// <param name="right">A <see cref="VertexElement"/></param>
        /// <returns>true if equal, false otherwise.</returns>
        public static bool operator ==(VertexDeclaration left, VertexDeclaration right)
        {
            // if element lists are different sizes, they can't be equal
            if (left.elements.Count != right.elements.Count)
            {
                return(false);
            }

            for (int i = 0; i < right.elements.Count; i++)
            {
                VertexElement a = left.elements[i];
                VertexElement b = right.elements[i];

                // if they are not equal, this declaration differs
                if (!(a == b))
                {
                    return(false);
                }
            }

            // if we got thise far, they are equal
            return(true);
        }
        /// <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);
        }
Esempio n. 9
0
 /// <summary>
 ///		Modifies the definition of a <see cref="VertexElement"/>.
 /// </summary>
 /// <param name="elemIndex">Index of the element to modify.</param>
 /// <param name="source">Source of the element.</param>
 /// <param name="offset">Offset of the element.</param>
 /// <param name="type">Type of the element.</param>
 /// <param name="semantic">Semantic of the element.</param>
 /// <param name="index">Usage index of the element.</param>
 public virtual void ModifyElement(int elemIndex, ushort source, int offset, VertexElementType type, VertexElementSemantic semantic, int index)
 {
     elements[elemIndex] = new VertexElement(source, offset, type, semantic, index);
 }
        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;
        }
        /// <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);
            }
        }
Esempio n. 12
0
		protected void BindVertexElementToGpu( VertexElement elem, HardwareVertexBuffer vertexBuffer, int vertexStart,
		                                       IList<int> attribsBound, IList<int> instanceAttribsBound )
		{
			IntPtr pBufferData;
			var hwGlBuffer = (GLHardwareVertexBuffer)vertexBuffer;

			if ( currentCapabilities.HasCapability( Graphics.Capabilities.VertexBuffer ) )
			{
				Gl.glBindBufferARB( Gl.GL_ARRAY_BUFFER_ARB, hwGlBuffer.GLBufferID );
				pBufferData = BUFFER_OFFSET( elem.Offset );
			}
			else
			{
				// ReSharper disable PossibleInvalidCastException
				pBufferData = ( (GLDefaultHardwareVertexBuffer)( vertexBuffer ) ).DataPtr( elem.Offset );
				// ReSharper restore PossibleInvalidCastException
			}
			if ( vertexStart != 0 )
			{
				pBufferData = pBufferData.Offset( vertexStart*vertexBuffer.VertexSize );
			}

			var sem = elem.Semantic;
			var multitexturing = Capabilities.TextureUnitCount > 1;

			var isCustomAttrib = false;
			if ( this.currentVertexProgram != null )
			{
				isCustomAttrib = this.currentVertexProgram.IsAttributeValid( sem, (uint)elem.Index );

				if ( hwGlBuffer.IsInstanceData )
				{
					var attrib = this.currentVertexProgram.AttributeIndex( sem, (uint)elem.Index );
					glVertexAttribDivisor( (int)attrib, hwGlBuffer.InstanceDataStepRate );
					instanceAttribsBound.Add( (int)attrib );
				}
			}


			// Custom attribute support
			// tangents, binormals, blendweights etc always via this route
			// builtins may be done this way too
			if ( isCustomAttrib )
			{
				var attrib = this.currentVertexProgram.AttributeIndex( sem, (uint)elem.Index );
				var typeCount = VertexElement.GetTypeCount( elem.Type );
				var normalised = Gl.GL_FALSE;
				switch ( elem.Type )
				{
					case VertexElementType.Color:
					case VertexElementType.Color_ABGR:
					case VertexElementType.Color_ARGB:
						// Because GL takes these as a sequence of single unsigned bytes, count needs to be 4
						// VertexElement::getTypeCount treats them as 1 (RGBA)
						// Also need to normalise the fixed-point data
						typeCount = 4;
						normalised = Gl.GL_TRUE;
						break;
					default:
						break;
				}

				Gl.glVertexAttribPointerARB( attrib, typeCount, GLHardwareBufferManager.GetGLType( elem.Type ), normalised,
				                             vertexBuffer.VertexSize, pBufferData );
				Gl.glEnableVertexAttribArrayARB( attrib );

				attribsBound.Add( (int)attrib );
			}
			else
			{
				// fixed-function & builtin attribute support
				switch ( sem )
				{
					case VertexElementSemantic.Position:
						Gl.glVertexPointer( VertexElement.GetTypeCount( elem.Type ), GLHardwareBufferManager.GetGLType( elem.Type ),
						                    vertexBuffer.VertexSize, pBufferData );
						Gl.glEnableClientState( Gl.GL_VERTEX_ARRAY );
						break;
					case VertexElementSemantic.Normal:
						Gl.glNormalPointer( GLHardwareBufferManager.GetGLType( elem.Type ), vertexBuffer.VertexSize, pBufferData );
						Gl.glEnableClientState( Gl.GL_NORMAL_ARRAY );
						break;
					case VertexElementSemantic.Diffuse:
						Gl.glColorPointer( 4, GLHardwareBufferManager.GetGLType( elem.Type ), vertexBuffer.VertexSize, pBufferData );
						Gl.glEnableClientState( Gl.GL_COLOR_ARRAY );
						break;
					case VertexElementSemantic.Specular:
						if ( this.GLEW_EXT_secondary_color )
						{
							Gl.glSecondaryColorPointerEXT( 4, GLHardwareBufferManager.GetGLType( elem.Type ), vertexBuffer.VertexSize,
							                               pBufferData );
							Gl.glEnableClientState( Gl.GL_SECONDARY_COLOR_ARRAY );
						}
						break;
					case VertexElementSemantic.TexCoords:

						if ( this.currentVertexProgram != null )
						{
							// Programmable pipeline - direct UV assignment
							Gl.glClientActiveTextureARB( Gl.GL_TEXTURE0 + elem.Index );
							Gl.glTexCoordPointer( VertexElement.GetTypeCount( elem.Type ), GLHardwareBufferManager.GetGLType( elem.Type ),
							                      vertexBuffer.VertexSize, pBufferData );
							Gl.glEnableClientState( Gl.GL_TEXTURE_COORD_ARRAY );
						}
						else
						{
							// fixed function matching to units based on tex_coord_set
							for ( var i = 0; i < disabledTexUnitsFrom; i++ )
							{
								// Only set this texture unit's texcoord pointer if it
								// is supposed to be using this element's index
								if ( this.texCoordIndex[ i ] != elem.Index || i >= this._fixedFunctionTextureUnits )
								{
									continue;
								}

								if ( multitexturing )
								{
									Gl.glClientActiveTextureARB( Gl.GL_TEXTURE0 + i );
								}
								Gl.glTexCoordPointer( VertexElement.GetTypeCount( elem.Type ), GLHardwareBufferManager.GetGLType( elem.Type ),
								                      vertexBuffer.VertexSize, pBufferData );
								Gl.glEnableClientState( Gl.GL_TEXTURE_COORD_ARRAY );
							}
						}
						break;
					default:
						break;
				}
			} // isCustomAttrib
		}
 /// <summary>
 ///		Modifies the definition of a <see cref="VertexElement"/>.
 /// </summary>
 /// <param name="elemIndex">Index of the element to modify.</param>
 /// <param name="source">Source of the element.</param>
 /// <param name="offset">Offset of the element.</param>
 /// <param name="type">Type of the element.</param>
 /// <param name="semantic">Semantic of the element.</param>
 /// <param name="index">Usage index of the element.</param>
 public virtual void ModifyElement(int elemIndex, ushort source, int offset, VertexElementType type, VertexElementSemantic semantic, int index)
 {
     elements[elemIndex] = new VertexElement(source, offset, type, semantic, index);
 }
        /// <summary>
        ///		Inserts a new <see cref="VertexElement"/> at a given position in this declaration.
        /// </summary>
        /// <remarks>
        ///		This method adds a single element (positions, normals etc) at a given position in this
        ///		vertex declaration. <b>Please read the information in VertexDeclaration about
        ///		the importance of ordering and structure for compatibility with older D3D drivers</b>.
        /// </remarks>
        /// <param name="position">Position to insert into.</param>
        /// <param name="source">The binding index of HardwareVertexBuffer which will provide the source for this element.</param>
        /// <param name="offset">The offset in bytes where this element is located in the buffer.</param>
        /// <param name="type">The data format of the element (3 floats, a color, etc).</param>
        /// <param name="semantic">The meaning of the data (position, normal, diffuse color etc).</param>
        /// <param name="index">Optional index for multi-input elements like texture coordinates.</param>
        /// <returns>A reference to the newly created element.</returns>
        public virtual VertexElement InsertElement(int position, ushort source, int offset, VertexElementType type, VertexElementSemantic semantic, int index)
        {
            if(position >= elements.Count) {
                return AddElement(source, offset, type, semantic, index);
            }

            VertexElement element = new VertexElement(source, offset, type, semantic, index);

            elements.Insert(position, element);

            return element;
        }
 /// <summary>
 ///     Adds a new VertexElement to this declaration.
 /// </summary>
 /// <remarks>
 ///     This method adds a single element (positions, normals etc) to the
 ///     vertex declaration. <b>Please read the information in <see cref="VertexDeclaration"/> about
 ///     the importance of ordering and structure for compatibility with older D3D drivers</b>.
 /// </remarks>
 /// <param name="source">
 ///     The binding index of HardwareVertexBuffer which will provide the source for this element.
 /// </param>
 /// <param name="offset">The offset in bytes where this element is located in the buffer.</param>
 /// <param name="type">The data format of the element (3 floats, a color etc).</param>
 /// <param name="semantic">The meaning of the data (position, normal, diffuse color etc).</param>
 /// <param name="index">Optional index for multi-input elements like texture coordinates.</param>
 public virtual VertexElement AddElement(ushort source, int offset, VertexElementType type, VertexElementSemantic semantic, int index)
 {
     VertexElement element = new VertexElement(source, offset, type, semantic, index);
     elements.Add(element);
     return element;
 }
        /// <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>
        // TODO: Step through and test
        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.Caps.CheckCap(Capabilities.VertexPrograms))
            {
                useVertexPrograms = true;
            }

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

            if (posElem != null)
            {
                ushort 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;

                if (wasSharedBuffer)
                {
                    newRemainderBuffer = HardwareBufferManager.Instance.CreateVertexBuffer(
                        vbuf.VertexSize - posElem.Size, 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;

                newPosBuffer = HardwareBufferManager.Instance.CreateVertexBuffer(
                    VertexElement.GetTypeSize(VertexElementType.Float3),
                    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.ToInt32() + (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 {
                        // Now it's time to set up the w buffer
                        hardwareShadowVolWBuffer =
                            HardwareBufferManager.Instance.CreateVertexBuffer(
                                sizeof(float),
                                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

                ushort 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
        }
Esempio n. 17
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);
            }
        }
        /// <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();
        }
 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;
 }
        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);
                }
            }
        }
Esempio n. 21
0
		protected void WriteGeometryVertexElement( BinaryWriter writer, VertexElement vertexElement )
		{
			var start_offset = writer.Seek( 0, SeekOrigin.Current );
			WriteChunk( writer, MeshChunkID.GeometryVertexElement, 0 );

			WriteUShort( writer, (ushort)vertexElement.Source );
			WriteUShort( writer, (ushort)vertexElement.Type );
			WriteUShort( writer, (ushort)vertexElement.Semantic );
			WriteUShort( writer, (ushort)vertexElement.Offset );
			WriteUShort( writer, (ushort)vertexElement.Index );

			var end_offset = writer.Seek( 0, SeekOrigin.Current );
			writer.Seek( (int)start_offset, SeekOrigin.Begin );
			WriteChunk( writer, MeshChunkID.GeometryVertexElement, (int)( end_offset - start_offset ) );
			writer.Seek( (int)end_offset, SeekOrigin.Begin );
		}
        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);
        }