示例#1
0
        // split VBE by stream
        private VertexElementDescriptor[][] SplitVBE(VertexElementDescriptor[] input)
        {
            VertexElementDescriptor[][] elements = new VertexElementDescriptor[2][];

            // pass 1
            byte[] sizes = { 0, 0 };
            for (int i = 0; i < input.Length; ++i)
            {
                sizes[input[i].Stream] += 1;
            }

            // pass 2
            elements[0] = new VertexElementDescriptor[sizes[0]];
            elements[1] = new VertexElementDescriptor[sizes[1]];
            sizes       = new byte[] { 0, 0 };
            for (int i = 0; i < input.Length; ++i)
            {
                byte stream = input[i].Stream;
                elements[stream][sizes[stream]] = input[i];
                sizes[stream] += 1;
            }
            return(elements);
        }
示例#2
0
        /// <summary>Generate <see cref="Submesh"/> objects</summary>
        private void GenerateMeshes(BinaryReader reader)
        {
            Submeshes = new Submesh[SubmeshDescriptors.Length];

            for (int i = 0; i < SubmeshDescriptors.Length; ++i)
            {
                SubmeshDescriptor submeshDescriptor = SubmeshDescriptors[i];
                //VertexBufferDescriptor vbo = VertexBuffers[submeshDescriptor.VertexBuffer];
                IndexBufferDescriptor ibo = IndexBuffers[submeshDescriptor.IndexBuffer];
                byte uvCount = GetMaxIndex(VertexElements[submeshDescriptor.VertexBuffer], teShaderInstance.ShaderInputUse.TexCoord);

                Submesh submesh = new Submesh(submeshDescriptor, uvCount);

                reader.BaseStream.Position = ibo.DataStreamPointer + submeshDescriptor.IndexStart * 2;
                Dictionary <int, ushort> indexRemap       = new Dictionary <int, ushort>();
                Dictionary <int, int>    indexRemapInvert = new Dictionary <int, int>();

                // todo: make this cleaner
                for (int j = 0; j < submeshDescriptor.IndicesToDraw; j++)
                {
                    ushort index = reader.ReadUInt16();
                    ushort newIndex;
                    if (indexRemap.ContainsKey(index))
                    {
                        newIndex = indexRemap[index];  // "index of", value = fake index
                    }
                    else
                    {
                        newIndex                   = (ushort)indexRemap.Count;
                        indexRemap[index]          = newIndex;
                        indexRemapInvert[newIndex] = index;
                    }

                    submesh.Indices[j] = newIndex;
                }

                VertexElementDescriptor[][] elements = SplitVBE(VertexElements[submeshDescriptor.VertexBuffer]);
                for (int j = 0; j < Stride[submeshDescriptor.VertexBuffer].Length; ++j)
                {
                    for (int k = 0; k < submeshDescriptor.VerticesToDraw; ++k)
                    {
                        long offset = submeshDescriptor.VertexStart + indexRemapInvert[k];
                        for (int l = 0; l < elements[j].Length; ++l)
                        {
                            VertexElementDescriptor element = elements[j][l];
                            if (element.Format == SemanticFormat.NONE)
                            {
                                break;
                            }
                            object value = Stride[submeshDescriptor.VertexBuffer][j][offset][l];
                            switch (element.Type)
                            {
                            case teShaderInstance.ShaderInputUse.Position:
                                if (element.Index == 0)
                                {
                                    float[] position = (float[])value;
                                    submesh.Vertices[k] = new teVec3(position);
                                }
                                else
                                {
                                    Debugger.Log(2, "teModelChunk_RenderMesh",
                                                 $"Unhandled vertex layer {element.Index:X} for type {element.Type}!\n");
                                }
                                break;

                            case teShaderInstance.ShaderInputUse.Normal:
                                if (element.Index == 0)
                                {
                                    float[] normal = (float[])value;
                                    submesh.Normals[k] = new teVec3(normal.Take(3).ToArray());
                                }
                                else
                                {
                                    Debugger.Log(2, "teModelChunk_RenderMesh",
                                                 $"Unhandled vertex layer {element.Index:X} for type {element.Type}!\n");
                                }
                                break;

                            case teShaderInstance.ShaderInputUse.TexCoord: {
                                ushort[] uv = (ushort[])value;
                                submesh.UV[k][element.Index] = teVec2.FromHalf(uv);
                            }
                            break;

                            case teShaderInstance.ShaderInputUse.BlendIndices:
                                if (element.Index == 0)
                                {
                                    byte[] boneIndex = (byte[])value;
                                    submesh.BoneIndices[k] = new ushort[boneIndex.Length];
                                    for (int m = 0; m < boneIndex.Length; ++m)
                                    {
                                        submesh.BoneIndices[k][m] = (ushort)(boneIndex[m] + submeshDescriptor.BoneIdOffset);
                                    }
                                }
                                else
                                {
                                    Debugger.Log(2, "teModelChunk_RenderMesh",
                                                 $"Unhandled vertex layer {element.Index:X} for type {element.Type}!\n");
                                }
                                break;

                            case teShaderInstance.ShaderInputUse.BlendWeights:
                                if (element.Index == 0)
                                {
                                    submesh.BoneWeights[k] = (float[])value;
                                }
                                else
                                {
                                    Debugger.Log(2, "teModelChunk_RenderMesh",
                                                 $"Unhandled vertex layer {element.Index:X} for type {element.Type}!\n");
                                }
                                break;

                            case teShaderInstance.ShaderInputUse.Tangent:
                                float[] tangent = (float[])value;
                                submesh.Tangents[k] = new teVec4(tangent);
                                break;

                            case teShaderInstance.ShaderInputUse.VertexIndex:  // todo: lolno
                                uint id = (uint)value;
                                submesh.IDs[k] = id;
                                break;

                            case teShaderInstance.ShaderInputUse.Color:
                                float[] col = (float[])value;
                                if (element.Index == 0)
                                {
                                    submesh.Color1[k] = new teColorRGBA(col);
                                }
                                else if (element.Index == 1)
                                {
                                    submesh.Color2[k] = new teColorRGBA(col);
                                }
                                else
                                {
                                    Debugger.Log(2, "teModelChunk_RenderMesh",
                                                 $"Unhandled vertex color index: {element.Index:X}\n");
                                }

                                break;

                            default:
                                if (UnhandledSemanticTypes.Add(element.Type) && Debugger.IsAttached)
                                {
                                    Debugger.Log(2, "teModelChunk_RenderMesh",
                                                 $"Unhandled vertex type {element.Type}!\n");
                                }
                                break;
                            }
                        }
                    }
                }

                Submeshes[i] = submesh;
            }
        }