/// <summary> /// Loads a mesh and creates the vertex/index buffers for the part /// </summary> /// <param name="part"></param> /// <param name="meshData"></param> void LoadMesh(ref Part part, IXDataObject dataObject) { // load vertex data int dataOffset = 0; Match vertexCount = findArrayCount.Match(dataObject.Body); if(!vertexCount.Success) throw new System.IO.InvalidDataException("problem reading vertex count"); List<Vector4F> vertexList = new List<Vector4F>(); int verticies = int.Parse(vertexCount.Groups[1].Value, CultureInfo.InvariantCulture); dataOffset = vertexCount.Index + vertexCount.Length; for(int vertexIndex = 0; vertexIndex < verticies; vertexIndex++) { Match vertex = findVector3F.Match(dataObject.Body, dataOffset); if(!vertex.Success) throw new System.IO.InvalidDataException("problem reading vertex"); else dataOffset = vertex.Index + vertex.Length; vertexList.Add( new Vector4F( float.Parse(vertex.Groups[1].Value, CultureInfo.InvariantCulture), float.Parse(vertex.Groups[2].Value, CultureInfo.InvariantCulture), float.Parse(vertex.Groups[3].Value, CultureInfo.InvariantCulture), 1.0f)); } // load triangle index data Match triangleIndexCount = findArrayCount.Match(dataObject.Body, dataOffset); dataOffset = triangleIndexCount.Index + triangleIndexCount.Length; if(!triangleIndexCount.Success) throw new System.IO.InvalidDataException("problem reading index count"); List<Int32> triangleIndiciesList = new List<Int32>(); int triangleIndexListCount = int.Parse(triangleIndexCount.Groups[1].Value, CultureInfo.InvariantCulture); dataOffset = triangleIndexCount.Index + triangleIndexCount.Length; for(int triangleIndicyIndex = 0; triangleIndicyIndex < triangleIndexListCount; triangleIndicyIndex++) { Match indexEntry = findVertexIndex.Match(dataObject.Body, dataOffset); if(!indexEntry.Success) throw new System.IO.InvalidDataException("problem reading vertex index entry"); else dataOffset = indexEntry.Index + indexEntry.Length; int indexEntryCount = int.Parse(indexEntry.Groups[1].Value, CultureInfo.InvariantCulture); string[] vertexIndexes = indexEntry.Groups[2].Value.Split(new char[] { ',' }); if(indexEntryCount != vertexIndexes.Length) throw new System.IO.InvalidDataException("vertex index count does not equal count of indicies found"); for(int entryIndex = 0; entryIndex <= indexEntryCount - 3; entryIndex++) { triangleIndiciesList.Add(int.Parse(vertexIndexes[0], CultureInfo.InvariantCulture)); triangleIndiciesList.Add(int.Parse(vertexIndexes[1 + entryIndex].ToString(), CultureInfo.InvariantCulture)); triangleIndiciesList.Add(int.Parse(vertexIndexes[2 + entryIndex].ToString(), CultureInfo.InvariantCulture)); } } // load mesh colors IXDataObject vertexColorData = GetSingleChild(dataObject, "MeshVertexColors"); Dictionary<int, Vector4F> colorDictionary = null; if (vertexColorData != null) colorDictionary = LoadMeshColors(vertexColorData); // load mesh normals IXDataObject meshNormalData = GetSingleChild(dataObject, "MeshNormals"); IndexedMeshNormals meshNormals = null; if(meshNormalData != null) { meshNormals = LoadMeshNormals(meshNormalData); } // load mesh texture coordinates IXDataObject meshTextureCoordsData = GetSingleChild(dataObject, "MeshTextureCoords"); List<Vector2F> meshTextureCoords = null; if(meshTextureCoordsData != null) { meshTextureCoords = LoadMeshTextureCoordinates(meshTextureCoordsData); } // load mesh material IXDataObject meshMaterialsData = GetSingleChild(dataObject, "MeshMaterialList"); List<MaterialSpecification> meshMaterials = null; if(meshMaterialsData != null) { meshMaterials = LoadMeshMaterialList(meshMaterialsData); } // copy vertex data to HGLOBAL int byteLength = Marshal.SizeOf(typeof(XMeshVertex)) * triangleIndiciesList.Count; IntPtr nativeVertex = Marshal.AllocHGlobal(byteLength); byte[] byteBuffer = new byte[byteLength]; XMeshVertex[] varray = new XMeshVertex[triangleIndiciesList.Count]; for(int n = 0; n < triangleIndiciesList.Count; n++) { XMeshVertex vertex = new XMeshVertex() { Vertex = vertexList[triangleIndiciesList[n]], Normal = (meshNormals == null) ? new Vector4F(0, 0, 0, 1.0f) : meshNormals.normalVectors[meshNormals.normalIndexMap[n]], Color = ((colorDictionary == null) ? new Vector4F(0, 0, 0, 0) : colorDictionary[triangleIndiciesList[n]]), Texture = ((meshTextureCoords == null) ? new Vector2F(0, 0) : meshTextureCoords[triangleIndiciesList[n]]) }; byte[] vertexData = RawSerialize(vertex); Buffer.BlockCopy(vertexData, 0, byteBuffer, vertexData.Length * n, vertexData.Length); } Marshal.Copy(byteBuffer, 0, nativeVertex, byteLength); // build vertex buffer BufferDescription bdv = new BufferDescription() { Usage = Usage.Default, ByteWidth = (uint)(Marshal.SizeOf(typeof(XMeshVertex)) * triangleIndiciesList.Count), BindingOptions = BindingOptions.VertexBuffer, CpuAccessOptions = CpuAccessOptions.None, MiscellaneousResourceOptions = MiscellaneousResourceOptions.None }; SubresourceData vertexInit = new SubresourceData() { SystemMemory = nativeVertex }; part.vertexBuffer = device.CreateBuffer(bdv, vertexInit); Debug.Assert(part.vertexBuffer != null); part.vertexCount = triangleIndiciesList.Count; if(meshMaterials != null) { // only a single material is currently supported MaterialSpecification m = meshMaterials[0]; part.material = new Material() { emissiveColor = m.emissiveColor, specularColor = m.specularColor, materialColor = m.materialColor, specularPower = m.specularPower }; string texturePath = ""; if(File.Exists(m.textureFileName)) texturePath = m.textureFileName; if(File.Exists(meshDirectory + "\\" + m.textureFileName)) texturePath = meshDirectory + "\\" + m.textureFileName; if(File.Exists(meshDirectory + "\\..\\" + m.textureFileName)) texturePath = meshDirectory + "\\..\\" + m.textureFileName; if(texturePath.Length == 0) { part.material.textureResource = null; } else { part.material.textureResource = D3D10XHelpers.CreateShaderResourceViewFromFile( device, texturePath); } } Marshal.FreeHGlobal(nativeVertex); }
/// <summary> /// Loads a mesh and creates the vertex/index buffers for the part /// </summary> /// <param name="part"></param> /// <param name="meshData"></param> void LoadMesh( ref Part part, string meshData ) { // load vertex data int dataOffset = 0; Match vertexCount = findArrayCount.Match( meshData ); if( !vertexCount.Success ) throw new System.IO.InvalidDataException( "problem reading vertex count" ); List<Vector4F> vertexList = new List<Vector4F>(); int verticies = int.Parse(vertexCount.Groups[1].Value, CultureInfo.InvariantCulture); dataOffset = vertexCount.Index + vertexCount.Length; for( int vertexIndex = 0; vertexIndex < verticies; vertexIndex++ ) { Match vertex = findVector3F.Match( meshData, dataOffset ); if( !vertex.Success ) throw new System.IO.InvalidDataException( "problem reading vertex" ); else dataOffset = vertex.Index + vertex.Length; vertexList.Add( new Vector4F( float.Parse(vertex.Groups[1].Value, CultureInfo.InvariantCulture), float.Parse(vertex.Groups[2].Value, CultureInfo.InvariantCulture), float.Parse(vertex.Groups[3].Value, CultureInfo.InvariantCulture), 1.0f) ); } // load triangle index data Match triangleIndexCount = findArrayCount.Match( meshData, dataOffset ); dataOffset = triangleIndexCount.Index + triangleIndexCount.Length; if( !triangleIndexCount.Success ) throw new System.IO.InvalidDataException( "problem reading index count" ); List<Int32> triangleIndiciesList = new List<Int32>( ); int triangleIndexListCount = int.Parse(triangleIndexCount.Groups[1].Value, CultureInfo.InvariantCulture); dataOffset = triangleIndexCount.Index + triangleIndexCount.Length; for( int triangleIndicyIndex = 0; triangleIndicyIndex < triangleIndexListCount; triangleIndicyIndex++ ) { Match indexEntry = findVertexIndex.Match( meshData, dataOffset ); if( !indexEntry.Success ) throw new System.IO.InvalidDataException( "problem reading vertex index entry" ); else dataOffset = indexEntry.Index + indexEntry.Length; int indexEntryCount = int.Parse(indexEntry.Groups[1].Value, CultureInfo.InvariantCulture); string[ ] vertexIndexes = indexEntry.Groups[ 2 ].Value.Split( new char[ ] { ',' } ); if( indexEntryCount != vertexIndexes.Length ) throw new System.IO.InvalidDataException( "vertex index count does not equal count of indicies found" ); for( int entryIndex = 0; entryIndex <= indexEntryCount - 3; entryIndex++ ) { triangleIndiciesList.Add(int.Parse(vertexIndexes[0], CultureInfo.InvariantCulture)); triangleIndiciesList.Add(int.Parse(vertexIndexes[1 + entryIndex].ToString(), CultureInfo.InvariantCulture)); triangleIndiciesList.Add(int.Parse(vertexIndexes[2 + entryIndex].ToString(), CultureInfo.InvariantCulture)); } } // load mesh colors string vertexColorData = GetTagContent( new Regex( @"MeshVertexColors[\s]+{" ), meshData ); Dictionary<int,Vector4F> colorDictionary = null; if( vertexColorData != "" ) colorDictionary = LoadMeshColors( vertexColorData ); // load mesh normals string meshNormalData = GetTagContent( new Regex( @"MeshNormals[\s]+{" ), meshData ); IndexedMeshNormals meshNormals = null; if( meshNormalData != "" ) { meshNormals = LoadMeshNormals( meshNormalData ); } // load mesh texture coordinates string meshTextureCoordsData = GetTagContent( new Regex( @"MeshTextureCoords[\s]+{" ), meshData ); List<Vector2F> meshTextureCoords = null; if( meshTextureCoordsData != "" ) { meshTextureCoords = LoadMeshTextureCoordinates( meshTextureCoordsData ); } // load mesh material string meshMaterialsData = GetTagContent( new Regex( @"MeshMaterialList[\s]+{" ), meshData ); List<MaterialSpecification> meshMaterials = null; if( meshMaterialsData != "" ) { meshMaterials = LoadMeshMaterialList( meshMaterialsData ); } // copy vertex data to HGLOBAL int byteLength = Marshal.SizeOf( typeof( XMeshVertex ) ) * triangleIndiciesList.Count; IntPtr nativeVertex = Marshal.AllocHGlobal( byteLength ); byte[ ] byteBuffer = new byte[ byteLength ]; XMeshVertex[ ] varray = new XMeshVertex[ triangleIndiciesList.Count ]; for( int n = 0; n < triangleIndiciesList.Count; n++ ) { XMeshVertex vertex = new XMeshVertex( ) { Vertex = vertexList[ triangleIndiciesList[ n ] ], Normal = (meshNormals == null) ? new Vector4F( 0, 0, 0, 1.0f ) : meshNormals.normalVectors[ meshNormals.normalIndexMap[ n ] ], Color = ((colorDictionary == null) ? new Vector4F( 0, 0, 0, 0 ) : colorDictionary[ triangleIndiciesList[ n ] ]), Texture = ((meshTextureCoords == null) ? new Vector2F( 0, 0 ) : meshTextureCoords[ triangleIndiciesList[ n ] ]) }; byte[ ] vertexData = RawSerialize( vertex ); Buffer.BlockCopy( vertexData, 0, byteBuffer, vertexData.Length * n, vertexData.Length ); } Marshal.Copy( byteBuffer, 0, nativeVertex, byteLength ); // build vertex buffer BufferDescription bdv = new BufferDescription( ) { Usage = Usage.Default, ByteWidth = (uint)(Marshal.SizeOf( typeof( XMeshVertex ) ) * triangleIndiciesList.Count), BindFlags = BindFlag.VertexBuffer, CpuAccessFlags = 0, MiscFlags = 0 }; SubresourceData vertexInit = new SubresourceData( ) { SysMem = nativeVertex }; part.vertexBuffer = device.CreateBuffer( bdv, vertexInit ); Debug.Assert( part.vertexBuffer != null ); part.vertexCount = triangleIndiciesList.Count; if( meshMaterials != null ) { // only a single material is currently supported MaterialSpecification m = meshMaterials[ 0 ]; part.material = new Material() { emissiveColor = m.emissiveColor, specularColor = m.specularColor, materialColor = m.materialColor, specularPower = m.specularPower }; string texturePath = ""; if( File.Exists( m.textureFileName ) ) texturePath = m.textureFileName; if( File.Exists( meshDirectory + "\\" + m.textureFileName ) ) texturePath = meshDirectory + "\\" + m.textureFileName; if( File.Exists( meshDirectory + "\\..\\" + m.textureFileName ) ) texturePath = meshDirectory + "\\..\\" + m.textureFileName; if( texturePath.Length == 0 ) { part.material.textureResource = null; } else { part.material.textureResource = D3D10XHelpers.CreateShaderResourceViewFromFile( device, texturePath ); } } Marshal.FreeHGlobal( nativeVertex ); }