public Mesh(Stream stream, Resource[] resources, Section section, CompressionBounds boundingBox) { int StartOffset = (int)stream.Position; BinaryReader br = new BinaryReader(stream); stream.Position = 4; Size = br.ReadInt32(); foreach (Resource r in resources) { stream.Position = StartOffset + 120 + r.RawDataOffset; int Count=0; switch (r.MainRawDataType) { case ResourceType.BoneMap: BoneMap = br.ReadBytes(r.RawDataSize); break; case ResourceType.MeshInformation: Groups = new Group[r.RawDataSize / 72]; for (int i = 0; i < Groups.Length; i++) { stream.Position = StartOffset + 120 + r.RawDataOffset + (i * 72); Groups[i] = new Group(br.ReadBytes(Group.Size)); } break; case ResourceType.Vertex: switch (r.SubRawDataType) { #region Vertices case ResourceSubType.VertexData: byte[] Bytes = br.ReadBytes(r.RawDataSize); int Index = 0; int Stride; switch (section.VertexType) { case VertexType.Rigid: Stride = 0;//xyz break; case VertexType.RigidBoned: Stride = 2;//xyz break; case VertexType.Skinned: Stride = 6;//xyz break; default: throw new Exception(); } if ((section.CompressionFlags & Compression.Position) != Compression.Position) { int VertexSize = 12 + Stride; int VertexCount = Bytes.Length / VertexSize; Index = 0; _Vertices = new Vector3[VertexCount]; for (int i = 0; i < VertexCount; i++) { float x = BitConverter.ToSingle(Bytes, Index + 0); float y = BitConverter.ToSingle(Bytes, Index + 4); float z = BitConverter.ToSingle(Bytes, Index + 8); _Vertices[i] = new Vector3(x, y, z); Index += VertexSize; } } else { int VertexSize = 6 + Stride; int VertexCount = Bytes.Length / VertexSize; Index = 0; _Vertices = new Vector3[VertexCount]; for (int i = 0; i < VertexCount; i++) { _Vertices[i] = new Vector3(CompressionBounds.Decompress(BitConverter.ToInt16(Bytes, Index + 0), boundingBox.X), CompressionBounds.Decompress(BitConverter.ToInt16(Bytes, Index + 2), boundingBox.Y), CompressionBounds.Decompress(BitConverter.ToInt16(Bytes, Index + 4), boundingBox.Z)); Index += VertexSize; } } break; #endregion #region Texcoords case ResourceSubType.UVData: Index = 0; Bytes = br.ReadBytes(r.RawDataSize); if ((section.CompressionFlags & Compression.Texcoord) == Compression.Texcoord) { int TexcoordSize = 4; Count = Bytes.Length / TexcoordSize; Texcoords = new Vector2[Count]; for (int i = 0; i < Count; i++) { Texcoords[i] = new Vector2(CompressionBounds.Decompress(BitConverter.ToInt16(Bytes, Index + 0), boundingBox.U), CompressionBounds.Decompress(BitConverter.ToInt16(Bytes, Index + 2), boundingBox.V)); Index += TexcoordSize; } } else { int TexcoordSize = 8; Count = Bytes.Length / TexcoordSize; Texcoords = new Vector2[Count]; for (int i = 0; i < Count; i++) { float u = BitConverter.ToSingle(Bytes, Index); float v = BitConverter.ToSingle(Bytes, Index + 4); Texcoords[i] = new Vector2(u, v); Index += TexcoordSize; } } break; #endregion #region Normals, Tangents, and Bitangents case ResourceSubType.VectorData: int[] Ints = new int[r.RawDataSize / 4]; for (int i = 0; i < Ints.Length; i++) Ints[i] = br.ReadInt32(); Normals = new Vector3[Ints.Length / 3]; Tangents = new Vector3[Ints.Length / 3]; Bitangents = new Vector3[Ints.Length / 3]; int[] normInts = new int[Ints.Length / 3]; for (int i = 0; i < normInts.Length; i++) { normInts[i] = Ints[i * 3]; } int normalsCount = 0; int tangentsCount = 0; int bitangentsCount = 0; for (int i = 0; i < Ints.Length; i++) { int CompressedData = Ints[i]; int x10 = (CompressedData & 0x000007FF); if ((x10 & 0x00000400) == 0x00000400) { x10 = -((~x10) & 0x000007FF); if (x10 == 0) x10 = -1; } int y11 = (CompressedData >> 11) & 0x000007FF; if ((y11 & 0x00000400) == 0x00000400) { y11 = -((~y11) & 0x000007FF); if (y11 == 0) y11 = -1; } int z11 = (CompressedData >> 22) & 0x000003FF; if ((z11 & 0x00000200) == 0x00000200) { z11 = -((~z11) & 0x000003FF); if (z11 == 0) z11 = -1; } float x, y, z; x = (x10 / (float)0x000003ff); y = (y11 / (float)0x000003FF); z = (z11 / (float)0x000001FF); int o = 0; switch (i % 3) { case 0: Normals[normalsCount] = new Vector3(x, y, z); normalsCount++; break; case 1: Tangents[tangentsCount] = new Vector3(x, y, z); tangentsCount++; break; case 2: Bitangents[bitangentsCount] = new Vector3(x, y, z); bitangentsCount++; break; } } //Normals = GenerateNormals(Vertices, Indices); break; #endregion } break; #region Triangle Strip Indices case ResourceType.TriangleStrip: Count = r.RawDataSize / 2; Indices = new short[Count]; for (int x = 0; x < Count; x++) { Indices[x] = br.ReadInt16(); } break; #endregion } } Vertices = new Vertex[_Vertices.Length]; for (int i = 0; i < Vertices.Length; i++) { Vertices[i] = new Vertex(){ Position = _Vertices[i].ToXnaVector3(), Color = Microsoft.Xna.Framework.Graphics.Color.Gray, Normal = Normals[i].ToXnaVector3(), Tangent = Tangents[i].ToXnaVector3(), Bitangent = Bitangents[i].ToXnaVector3(), /*Texcoord = Texcoords[i] */ }; } }
public void ImportWavefrontObject(WavefrontObject Wavefront, CompressionBounds boundingBox) { List<D3DVertex> temp = new List<D3DVertex>(Wavefront.FaceCount * 3); for (int Material = 0; Material < Wavefront.MaterialCount; Material++) { int[] FaceIndices = Wavefront.GetFaceIndicesUsingMaterialID(Material); for (int Face = 0; Face < FaceIndices.Length; Face++) { for (int Component = 0; Component < 3; Component++) { D3DVertex d3DVertex = new D3DVertex(); d3DVertex.Position = Wavefront.Vertices[Wavefront.Faces[FaceIndices[Face]].VertexIndices[Component]]; d3DVertex.Texture = Wavefront.Texcoords[Wavefront.Faces[FaceIndices[Face]].TexcoordIndices[Component]]; d3DVertex.Normal = Wavefront.Normals[Wavefront.Faces[FaceIndices[Face]].NormalIndices[Component]]; temp.Add(d3DVertex); } } } //Hashtable D3DVertexHashtable = new Hashtable(Wavefront.FaceCount * 3); List<short> tempIndices = new List<short>(Wavefront.FaceCount * 3); List<D3DVertex> D3DVertexList = new List<D3DVertex>(Wavefront.FaceCount * 3); short IndiceIndex = 0; for (int Index = 0; Index < temp.Count; Index++) { D3DVertex d3DVertex = temp[Index]; if (!D3DVertexList.Contains(d3DVertex)) { //D3DVertexHashtable.Add(d3DVertex, d3DVertex); D3DVertexList.Add(d3DVertex); tempIndices.Add(IndiceIndex); IndiceIndex++; } else { tempIndices.Add((short)D3DVertexList.IndexOf(d3DVertex)); } } this.Indices = tempIndices.ToArray(); D3DVertex[] D3DVertices = D3DVertexList.ToArray(); RenderDevice Device = new RenderDevice(); Device.InitializeDevice(); Microsoft.DirectX.Direct3D.Mesh mesh = new Microsoft.DirectX.Direct3D.Mesh(Wavefront.FaceCount, D3DVertices.Length, MeshFlags.SystemMemory, D3DVertex.Format, Device.Device); List<int> newAttributes = new List<int>(Wavefront.FaceCount); foreach (Face f in Wavefront.Faces) { newAttributes.Add(f.MaterialID); } mesh.LockAttributeBuffer(LockFlags.None); mesh.UnlockAttributeBuffer(newAttributes.ToArray()); mesh.SetIndexBufferData(Indices.ToArray(), LockFlags.None); mesh.SetVertexBufferData(D3DVertices.ToArray(), LockFlags.None); int[] adj = new int[Wavefront.FaceCount * 3]; mesh.GenerateAdjacency(0.005F, adj); mesh.OptimizeInPlace(MeshFlags.OptimizeAttributeSort, adj); IndexBuffer iBuffer = mesh.IndexBuffer; short[] D3DIndices; int IndiceCount; short[][] MaterialFaceIndices = new short[Wavefront.MaterialCount][]; for (int Material = 0; Material < Wavefront.MaterialCount; Material++) { iBuffer = Microsoft.DirectX.Direct3D.Mesh.ConvertMeshSubsetToSingleStrip(mesh, Material, MeshFlags.SystemMemory, out IndiceCount); GraphicsStream graphics = iBuffer.Lock(0, 0, LockFlags.None); unsafe { short* IndiceArray = (short*)graphics.InternalData.ToPointer(); D3DIndices = new short[IndiceCount]; for (int Index = 0; Index < IndiceCount; Index++) { D3DIndices[Index] = IndiceArray[Index]; } } MaterialFaceIndices[Material] = D3DIndices; } List<short> newIndices = new List<short>(); Groups = new Group[MaterialFaceIndices.Length]; for (int i = 0; i < MaterialFaceIndices.Length; i++) { Groups[i] = new Group(); Groups[i].IndiceStart = (short)newIndices.Count; Groups[i].IndiceCount = (short)MaterialFaceIndices[i].Length; Groups[i].ShaderIndex = (short)i; newIndices.AddRange(MaterialFaceIndices[i]); } this.Indices = newIndices.ToArray(); this._Vertices = new Vector3[D3DVertices.Length]; this.Texcoords = new Vector2[D3DVertices.Length]; this.Normals = new Vector3[D3DVertices.Length]; for (int i = 0; i < D3DVertices.Length; i++) { _Vertices[i] = D3DVertices[i].Position; Texcoords[i] = D3DVertices[i].Texture; Normals[i] = D3DVertices[i].Normal; } CalculateTangentArray(_Vertices.Length, _Vertices, Normals, Texcoords, mesh.NumberFaces, Wavefront.Faces.ToArray(), out Bitangents, out Tangents); mesh.Dispose(); }