Ejemplo n.º 1
0
        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] */
                };
            }
        }
Ejemplo n.º 2
0
        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();
        }