private SkelletalMesh GetMesh(GMeshContainer meshContainer, Bone root, VertexDescriptor vd) { SlimDX.Direct3D9.Mesh d3dMesh = meshContainer.Mesh; var adjacency = meshContainer.GetAdjacency(); var meshMaterials = meshContainer.GetMaterials(); List <MeshMaterial> materials = new List <MeshMaterial>(); for (int i = 0; i < meshMaterials.Length; i++) { var matd3d = meshMaterials[i].MaterialD3D; string textureFilename = meshMaterials[i].TextureFileName; if (textureFilename != null && !Path.IsPathRooted(textureFilename)) { textureFilename = Path.Combine(Path.GetDirectoryName(xFile), textureFilename); } materials.Add(new MeshMaterial() { Name = root.Name + "_material" + i, Alpha = matd3d.Diffuse.Alpha, Diffuse = matd3d.Diffuse.ToVector3(), Specular = matd3d.Specular.ToVector3(), SpecularPower = Math.Max(1, matd3d.Power), Reflectivity = 0, Refractitity = 0, EmissiveColor = matd3d.Emissive.ToVector3(), DiffuseMap = textureFilename }); } SkelletalMesh mesh = new SkelletalMesh(vd); mesh.Adjacency = adjacency; SkinVertex[] vertexes = new SkinVertex[d3dMesh.VertexCount]; Array indices; if (d3dMesh.IndexBuffer.Description.Format == Format.Index16) { indices = new ushort[d3dMesh.FaceCount * 3]; } else { indices = new uint[d3dMesh.FaceCount * 3]; } VertexDescriptor meshVD = new VertexDescriptor(d3dMesh.GetDeclaration()); int positionOffset = meshVD.GetOffset(DeclarationUsage.Position, 0); int normalOffset = meshVD.GetOffset(DeclarationUsage.Normal, 0); int texCoordOffset = meshVD.GetOffset(DeclarationUsage.TextureCoordinate, 0); int blendIndicesOffset = meshVD.GetOffset(DeclarationUsage.BlendIndices, 0); int blendIndicesSize = meshVD.SizeOfElement(DeclarationUsage.BlendIndices, 0); int blendWeightsOffset = meshVD.GetOffset(DeclarationUsage.BlendWeight, 0); int blendWeightSize = meshVD.SizeOfElement(DeclarationUsage.BlendWeight, 0); byte[] buffer; unsafe { DataStream vertexStream = d3dMesh.LockVertexBuffer(0); buffer = new byte[vertexStream.Length]; vertexStream.Read(buffer, 0, (int)vertexStream.Length); fixed(byte *_pter = buffer) { fixed(SkinVertex *pVertexes = vertexes) { byte *pter = _pter; int j = 0; for (int i = 0; i < d3dMesh.VertexCount; i++) { pVertexes[i].Position = *((Vector3 *)(pter + positionOffset)); if (normalOffset >= 0) { pVertexes[i].Normal = *((Vector3 *)(pter + normalOffset)); } if (texCoordOffset >= 0) { pVertexes[i].TexCoord = *((Vector2 *)(pter + texCoordOffset)); } if (blendIndicesOffset >= 0) { byte *indicesPter = (pter + blendIndicesOffset); uint *pDest = (uint *)&(pVertexes[i].BlendIndices); for (j = 0; j < blendIndicesSize; j++) { *(((byte *)pDest) + j) = *(indicesPter + j); } } if (blendWeightsOffset >= 0) { byte * weightsPter = (pter + blendWeightsOffset); Vector4 *pDest = &(pVertexes[i].BlendWeights); for (j = 0; j < blendWeightSize; j++) { *(((byte *)pDest) + j) = *(weightsPter + j); } } pter += d3dMesh.BytesPerVertex; } } } d3dMesh.UnlockVertexBuffer(); DataStream indexStream = d3dMesh.LockIndexBuffer(0); GCHandle handler = GCHandle.Alloc(indices, GCHandleType.Pinned); IntPtr indexPter = Marshal.UnsafeAddrOfPinnedArrayElement(indices, 0); buffer = new byte[indexStream.Length]; indexStream.Read(buffer, 0, (int)indexStream.Length); Marshal.Copy(buffer, 0, indexPter, buffer.Length); handler.Free(); d3dMesh.UnlockIndexBuffer(); } mesh.CreateVertexBuffer(vertexes); if (d3dMesh.IndexBuffer.Description.Format == Format.Index16) { mesh.CreateIndexBuffer((ushort[])indices); } else { mesh.CreateIndexBuffer((uint[])indices); } List <MeshLayer> layers = new List <MeshLayer>(); if (meshContainer.BoneCombinations == null || meshContainer.BoneCombinations.Length == 0) { MeshLayer component = new MeshLayer(); materials.Add(MeshMaterial.CreateDefaultMaterial(meshContainer.Name + "_default")); component.materialIndex = 0; component.primitiveCount = mesh.FaceCount; component.startIndex = 0; component.startVertex = 0; component.vertexCount = mesh.VertexCount; layers.Add(component); } else { for (int i = 0; i < meshContainer.BoneCombinations.Length; i++) { BoneCombination comb = meshContainer.BoneCombinations[i]; MeshLayer component = new MeshLayer(); component.materialIndex = comb.AttributeId; component.primitiveCount = comb.FaceCount; component.startIndex = comb.FaceStart * 3; component.startVertex = comb.VertexStart; component.vertexCount = comb.VertexCount; layers.Add(component); } } var layerArray = layers.ToArray(); mesh.Materials = materials.ToArray(); mesh.SetLayers(layerArray); var skinInfo = meshContainer.SkinInfo; mesh.MaxVertexInfluences = skinInfo.MaximumVertexInfluences; var bones = new Bone[skinInfo.BoneCount]; var boneOffsetMatrices = new Matrix[bones.Length]; for (int i = 0; i < bones.Length; i++) { bones[i] = root.FindChild(skinInfo.GetBoneName(i)); boneOffsetMatrices[i] = skinInfo.GetBoneOffsetMatrix(i); } mesh.Bones = bones; mesh.BoneBindingMatrices = boneOffsetMatrices; if (meshContainer.BoneCombinations != null && meshContainer.BoneCombinations.Length > 0) { for (int layerIndex = 0; layerIndex < layerArray.Length; layerIndex++) { mesh.SetLayerBones(layerIndex, meshContainer.BoneCombinations[layerIndex].BoneIds); } } mesh.LockVertexBuffer(); int[] vertices; float[] weights; for (int i = 0; i < mesh.bones.Length; i++) { skinInfo.GetBoneInfluence(i, out vertices, out weights); VertexStreamView <Vector3> positions = mesh.GetVertexViewStream <Vector3>(DeclarationUsage.Position, 0, vertices); } mesh.UnlockVertexBuffer(); meshVD.Dispose(); if (normalOffset < 0) { mesh.ComputeNormals(); } if (texCoordOffset < 0) { mesh.ComputeTextureCoords(CoordMappingType.Spherical); } mesh.ComputeTangents(); return(mesh); }
public SceneImportResult LoadStaticMesh(string filename) { var file = new FileInfo(filename); VertexDescriptor vd = VertexDescriptor.Get <ModelVertex>(); List <MeshLayer> layers = new List <MeshLayer>(); int[] adjacency; ExtendedMaterial[] meshMaterials; Mesh mesh = new Mesh(vd); List <MeshMaterial> material = new List <MeshMaterial>(); using (SlimDX.Direct3D9.Mesh d3dMesh = SlimDX.Direct3D9.Mesh.FromFile(Engine.Graphics, filename, MeshFlags.Managed)) { adjacency = d3dMesh.GetAdjacency(); meshMaterials = d3dMesh.GetMaterials(); for (int i = 0; i < meshMaterials.Length; i++) { var matd3d = meshMaterials[i].MaterialD3D; string textureFilename = meshMaterials[i].TextureFileName; if (textureFilename != null && !Path.IsPathRooted(textureFilename)) { textureFilename = Path.Combine(Path.GetDirectoryName(filename), textureFilename); } material.Add(new MeshMaterial() { Name = file.Name + "_material" + i, Alpha = matd3d.Diffuse.Alpha, Diffuse = matd3d.Diffuse.ToVector3(), Specular = matd3d.Specular.ToVector3(), SpecularPower = Math.Max(1, matd3d.Power), Reflectivity = 0, Refractitity = 0, EmissiveColor = matd3d.Emissive.ToVector3(), DiffuseMap = textureFilename != null && File.Exists(textureFilename) ? textureFilename : null }); } ModelVertex[] vertexes = new ModelVertex[d3dMesh.VertexCount]; Array indices; if (d3dMesh.IndexBuffer.Description.Format == Format.Index16) { indices = new ushort[d3dMesh.FaceCount * 3]; } else { indices = new uint[d3dMesh.FaceCount * 3]; } DataStream vertexStream = d3dMesh.LockVertexBuffer(0); VertexDescriptor meshVD = new VertexDescriptor(d3dMesh.GetDeclaration()); int positionOffset = meshVD.GetOffset(DeclarationUsage.Position, 0); int normalOffset = meshVD.GetOffset(DeclarationUsage.Normal, 0); int texCoordOffset = meshVD.GetOffset(DeclarationUsage.TextureCoordinate, 0); byte[] buffer; unsafe { buffer = new byte[vertexStream.Length]; vertexStream.Read(buffer, 0, (int)vertexStream.Length); fixed(byte *_pter = buffer) { byte *pter = _pter; for (int i = 0; i < d3dMesh.VertexCount; i++) { vertexes[i].Position = *((Vector3 *)(pter + positionOffset)); if (normalOffset > 0) { vertexes[i].Normal = *((Vector3 *)(pter + normalOffset)); } if (texCoordOffset > 0) { vertexes[i].TexCoord = *((Vector2 *)(pter + texCoordOffset)); } pter += d3dMesh.BytesPerVertex; } } d3dMesh.UnlockVertexBuffer(); DataStream indexStream = d3dMesh.LockIndexBuffer(0); GCHandle handler = GCHandle.Alloc(indices, GCHandleType.Pinned); byte * indexPter = (byte *)Marshal.UnsafeAddrOfPinnedArrayElement(indices, 0); buffer = new byte[indexStream.Length]; indexStream.Read(buffer, 0, (int)indexStream.Length); for (int i = 0; i < indexStream.Length; i++) { indexPter[i] = buffer[i]; } handler.Free(); d3dMesh.UnlockIndexBuffer(); } mesh.CreateVertexBuffer(vertexes); if (d3dMesh.IndexBuffer.Description.Format == Format.Index16) { mesh.CreateIndexBuffer((ushort[])indices); } else { mesh.CreateIndexBuffer((uint[])indices); } var d3dComponents = d3dMesh.GetAttributeTable(); if (d3dComponents == null) { MeshLayer component = new MeshLayer(); layers.Add(component); material.Add(MeshMaterial.CreateDefaultMaterial(file.Name + "_default")); component.materialIndex = 0; component.primitiveCount = mesh.FaceCount; component.startIndex = 0; component.startVertex = 0; component.vertexCount = mesh.VertexCount; } else { for (int i = 0; i < d3dComponents.Length; i++) { AttributeRange ar = d3dComponents[i]; MeshLayer component = new MeshLayer(); layers.Add(component); component.materialIndex = ar.AttribId; component.primitiveCount = ar.FaceCount; component.startIndex = ar.FaceStart * 3; component.startVertex = ar.VertexStart; component.vertexCount = ar.VertexCount; } } mesh.Materials = material.ToArray(); mesh.SetLayers(layers.ToArray()); if (normalOffset < 0) { mesh.ComputeNormals(); } if (texCoordOffset < 0) { mesh.ComputeTextureCoords(CoordMappingType.Spherical); } mesh.ComputeTangents(); meshVD.Dispose(); } StaticMeshSceneNode meshNode = new StaticMeshSceneNode(file.Name, mesh); return(new SceneImportResult { VisualSceneRoot = meshNode, VisualMaterials = material }); }