public void Serialize(Stream stream, CompressionBounds boundingbox) { BinaryWriter bw = new BinaryWriter(stream); bw.Write((short)2); bw.Write((short)3); bw.Write(ShaderIndex); bw.Write(IndiceStart); bw.Write(IndiceCount); stream.Seek(4, SeekOrigin.Current); bw.Write((short)1); stream.Seek(16, SeekOrigin.Current); bw.Write(1.0F); bw.Write(0.0F); bw.Write(0.0F); bw.Write(1.0F); bw.Write(boundingbox.X.Min); bw.Write(boundingbox.X.Max); bw.Write(boundingbox.Y.Min); bw.Write(boundingbox.Y.Max); bw.Write(boundingbox.Z.Min); bw.Write(boundingbox.Z.Max); }
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 byte[] Serialize(Section section, CompressionBounds boundingBox, out Resource[] resources) { MemoryStream stream = new MemoryStream(); BinaryWriter bw = new BinaryWriter(stream); List<Resource> resourceList = new List<Resource>(); byte[] fourCC = Encoding.UTF8.GetBytes("crsr"); bw.Write(Encoding.UTF8.GetBytes("hklb"), 0, 4); stream.Seek(4, SeekOrigin.Current); bw.Write(Groups.Length); //stream.Seek(4, SeekOrigin.Current); //bw.Write(1); stream.Seek(8, SeekOrigin.Current); stream.Seek(20, SeekOrigin.Current); bw.Write(Indices.Length); stream.Seek(20, SeekOrigin.Current); bw.Write(3); stream.Seek(40, SeekOrigin.Current); bw.Write(1); stream.Seek(8, SeekOrigin.Current); bw.Write(fourCC, 0, 4); resourceList.Add(new Resource(ResourceType.MeshInformation, ResourceSubType.MeshInformationData, (int)(stream.Position - 120), 72)); for (int i = 0; i < Groups.Length; i++) { Groups[i].Serialize(stream, boundingBox); } //bw.Write(fourCC, 0, 4); //resourceList.Add(new Resource(ResourceType.UnknownStruct8, ResourceSubType.UnknownStruct8, (int)(stream.Position - 120), 8)); //bw.Write(0x00000000); bw.Write((ushort)0xFFFF); bw.Write((short)0x0000); bw.Write(fourCC, 0, 4); resourceList.Add(new Resource(ResourceType.TriangleStrip, ResourceSubType.IndiceStripData, (int)(stream.Position - 120), Indices.Length * 2)); foreach (short i in Indices) bw.Write(i); stream.Pad(4); bw.Write(fourCC, 0, 4); resourceList.Add(new Resource(ResourceType.Unknown, ResourceSubType.UnknownData, (int)(stream.Position - 120), 96)); bw.Write((byte)0x02); bw.Write((byte)0x06); bw.Write((byte)0x00); bw.Write((byte)0x00); bw.Write(new byte[28]); bw.Write((byte)0x19); bw.Write((byte)0x04); bw.Write((byte)0x00); bw.Write((byte)0x00); bw.Write(new byte[28]); bw.Write((byte)0x1B); bw.Write((byte)0x0C); bw.Write((byte)0x00); bw.Write((byte)0x00); bw.Write(new byte[28]); bw.Write(fourCC, 0, 4); resourceList.Add(new Resource(ResourceType.Vertex, ResourceSubType.VertexData, (int)(stream.Position - 120), _Vertices.Length * 6)); foreach (Vector3 v in _Vertices) { bw.Write(CompressionBounds.Compress(v.X, boundingBox.X)); bw.Write(CompressionBounds.Compress(v.Y, boundingBox.Y)); bw.Write(CompressionBounds.Compress(v.Z, boundingBox.Z)); } bw.Write(Padding.GetBytes(stream.Position, 4)); bw.Write(fourCC, 0, 4); resourceList.Add(new Resource(ResourceType.Vertex, ResourceSubType.UVData, (int)(stream.Position - 120), _Vertices.Length * 4)); foreach (Vector2 t in Texcoords) { bw.Write(CompressionBounds.Compress(t.X, boundingBox.X)); bw.Write(CompressionBounds.Compress(t.Y, boundingBox.Y)); } bw.Write(Padding.GetBytes(stream.Position, 4)); bw.Write(fourCC, 0, 4); resourceList.Add(new Resource(ResourceType.Vertex, ResourceSubType.VectorData, (int)(stream.Position - 120), Normals.Length * 4 * 3)); for (int i = 0; i < Normals.Length; i++) { bw.Write(CompressVector(Normals[i])); bw.Write(CompressVector(Tangents[i])); bw.Write(CompressVector(Bitangents[i])); } bw.Write(Padding.GetBytes(stream.Position, 4)); bw.Write(fourCC, 0, 4); resourceList.Add(new Resource(ResourceType.BoneMap, ResourceSubType.BoneData, (int)(stream.Position - 120), BoneMap.Length)); if (BoneMap.Length == 0) { foreach (byte b in BoneMap) bw.Write(b); bw.Write(Padding.GetBytes(stream.Position, 4)); } else { bw.Write(0); } bw.Write(Encoding.UTF8.GetBytes("fklb"), 0, 4); int rawLength = (int)stream.Position; stream.Seek(4, SeekOrigin.Begin); bw.Write(rawLength - 116); resources = resourceList.ToArray(); return stream.ToArray(); }
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(); }
public CompressionBounds GenerateBoundingBox() { CompressionBounds bounds = new CompressionBounds(); foreach (Vector3 v in Vertices) { bounds.X.Expand(v.X); bounds.Y.Expand(v.Y); bounds.Z.Expand(v.Z); } foreach (Vector2 vt in Texcoords) { bounds.U.Expand(vt.X); bounds.V.Expand(vt.Y); } return bounds; }