Exemplo n.º 1
0
        private List<J3DRenderer.VertexFormatLayout> BuildVertexArraysFromFile()
        {
            List<J3DRenderer.VertexFormatLayout> finalData = new List<J3DRenderer.VertexFormatLayout>();


            //Now, let's try to get our data.
            for (uint i = 0; i < _file.Shapes.GetBatchCount(); i++)
            {
                J3DFormat.Batch batch = _file.Shapes.GetBatch(i);

                RenderBatch renderBatch = new RenderBatch();
                _renderList.Add(renderBatch);

                //Console.WriteLine("[{0}] Unk0: {5}, Attb: {6} Mtx Type: {1} #Packets {2}[{3}] Matrix Index: {4}", i, batch.MatrixType, batch.PacketCount, batch.PacketIndex, batch.FirstMatrixIndex, batch.Unknown0, batch.AttribOffset);

                uint attributeCount = 0;
                for (uint attribIndex = 0; attribIndex < 13; attribIndex++)
                {
                    J3DFormat.BatchAttribute attrib = _file.Shapes.GetAttribute(attribIndex, batch.AttribOffset);
                    if (attrib.AttribType == J3DFormat.ArrayTypes.NullAttr)
                        break;

                    attributeCount++;
                }

                for (ushort p = 0; p < batch.PacketCount; p++)
                {
                    RenderPacket renderPacket = new RenderPacket();
                    renderBatch.Packets.Add(renderPacket);

                    //Matrix Data
                    J3DFormat.PacketMatrixData pmd = _file.Shapes.GetPacketMatrixData((ushort)(batch.FirstMatrixIndex + p));
                    renderPacket.DrawIndexes = new ushort[pmd.Count];
                    for (ushort mtx = 0; mtx < pmd.Count; mtx++)
                    {
                        //Console.WriteLine("{4} {0} Packet: {1} Index: {2} PMD Unknown: {3}", i, p, _file.Shapes.GetMatrixTableIndex((ushort) (pmd.FirstIndex + mtx)), pmd.Unknown, mtx);
                        renderPacket.DrawIndexes[mtx] = _file.Shapes.GetMatrixTableIndex((ushort)(pmd.FirstIndex + mtx));
                    }

                    J3DFormat.BatchPacketLocation packetLoc = _file.Shapes.GetBatchPacketLocation((ushort)(batch.PacketIndex + p));
                    uint numPrimitiveBytesRead = packetLoc.Offset;
                    while (numPrimitiveBytesRead < packetLoc.Offset + packetLoc.PacketSize)
                    {
                        J3DFormat.BatchPrimitive primitive = _file.Shapes.GetPrimitive(numPrimitiveBytesRead);
                        numPrimitiveBytesRead += J3DFormat.BatchPrimitive.Size;

                        //Game pads the chunks out with zeros, so this is signal for early break.
                        if (primitive.Type == 0)
                        {
                            break;
                        }

                        var primList = new PrimitiveList();
                        primList.VertexCount = primitive.VertexCount;
                        primList.VertexStart = finalData.Count;
                        primList.DrawType = primitive.Type == J3DFormat.PrimitiveTypes.TriangleStrip ? PrimitiveType.TriangleStrip : PrimitiveType.TriangleFan; //Todo: More support
                        renderPacket.PrimList.Add(primList);

                        for (int vert = 0; vert < primitive.VertexCount; vert++)
                        {
                            J3DRenderer.VertexFormatLayout newVertex = new J3DRenderer.VertexFormatLayout();
                            for (uint vertIndex = 0; vertIndex < attributeCount; vertIndex++)
                            {
                                var batchAttrib = _file.Shapes.GetAttribute(vertIndex, batch.AttribOffset);
                                ushort curIndex = _file.Shapes.GetPrimitiveIndex(numPrimitiveBytesRead, batchAttrib);

                                switch (batchAttrib.AttribType)
                                {
                                    case J3DFormat.ArrayTypes.Position:
                                        newVertex.Position = _file.Vertexes.GetPosition(curIndex);
                                        break;
                                    case J3DFormat.ArrayTypes.Normal:
                                        newVertex.Color = new Vector4(_file.Vertexes.GetNormal(curIndex, 14), 1); //temp
                                        break;
                                    case J3DFormat.ArrayTypes.Color0:
                                        newVertex.Color = _file.Vertexes.GetColor0(curIndex);
                                        break;
                                    case J3DFormat.ArrayTypes.Tex0:
                                        newVertex.TexCoord = _file.Vertexes.GetTex0(curIndex, 8);
                                        break;

                                    case J3DFormat.ArrayTypes.PositionMatrixIndex:
                                        //Console.WriteLine("B: {0} P: {1} Prim: {2} Vert{3} Index: {4}", i, p, renderPacket.PrimList.Count, vert, curIndex);
                                        primList.PosMatrixIndex.Add(curIndex);
                                        break;
                                    default:
                                        Console.WriteLine("Unknown AttribType {0}, Index: {1}", batchAttrib.AttribType, curIndex);
                                        break;
                                }

                                numPrimitiveBytesRead += GetAttribElementSize(batchAttrib.DataType);
                            }

                            //Add our vertex to our list of Vertexes
                            finalData.Add(newVertex);
                        }

                        //Console.WriteLine("Batch {0} Prim {1} #Vertices with PosMtxIndex: {2}", i, p, primList.PosMatrixIndex.Count);
                    }
                }

                //Console.WriteLine("Finished batch {0}, triangleStrip count: {1}", i, _renderList.Count);
            }

            return finalData;
        }
Exemplo n.º 2
0
        private void DrawModelRecursive(ref Matrix4[] jointMatrix, SceneGraph curNode, BaseRenderer renderer, bool bSelectedPass)
        {
            switch (curNode.NodeType)
            {
                case J3DFormat.HierarchyDataTypes.Material:
                    if (!bSelectedPass)
                        GL.BindTexture(TextureTarget.Texture2D, GetGLTexIdFromCache(curNode.DataIndex));
                    break;

                case J3DFormat.HierarchyDataTypes.Batch:
                    /* For each batch, we're going to enable the
                         * appropriate Vertex Attributes for that batch
                         * and set default values for vertex attribs that
                         * the batch doesn't use, then draw all primitives
                         * within it.*/

                    if (bSelectedPass)
                    {
                        #region Selected
                        float[] front_face_wireframe_color = { 1.0f, 1.0f, 1.0f, 1.0f };
                        float[] back_face_wireframe_color = { 0.7f, 0.7f, 0.7f, 0.7f };

                        GL.LineWidth(1);
                        GL.Enable(EnableCap.CullFace);
                        //GL.Disable(EnableCap.DepthTest);
                        GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
                        GL.EnableVertexAttribArray((int)BaseRenderer.ShaderAttributeIds.Position);

                        // 1. Draw the back-faces with a darker color:
                        GL.CullFace(CullFaceMode.Back);
                        GL.VertexAttrib4((int)BaseRenderer.ShaderAttributeIds.Color, back_face_wireframe_color);
                        foreach (var packet in _renderList[curNode.DataIndex].Packets)
                        {
                            int vertexIndex = 0;
                            foreach (var primitive in packet.PrimList)
                            {
                                //Uhh... 
                                ushort drawIndex = packet.DrawIndexes[primitive.PosMatrixIndex[vertexIndex] / 3];
                                bool isWeighted = _file.Draw.IsWeighted(drawIndex);

                                if (isWeighted)
                                {

                                }
                                else
                                {
                                    var jnt = _file.Joints.GetJoint(curNode.DataIndex);
                                    Vector3 jntRot = jnt.GetRotation().ToDegrees();
                                    Vector3 trans = jnt.GetTranslation();
                                    Matrix4 trnMatrix = Matrix4.CreateTranslation(trans);
                                    Matrix4 rtMatrix = Matrix4.CreateRotationX(jntRot.X) * Matrix4.CreateRotationY(jntRot.Y) *
                                                        Matrix4.CreateRotationZ(jntRot.Z);
                                    Matrix4 sclMatrix = Matrix4.CreateScale(jnt.GetScale());

                                    Matrix4 final = trnMatrix * rtMatrix * sclMatrix;

                                    //renderer.SetModelMatrix(Matrix4.Identity);
                                    renderer.SetModelMatrix(final);
                                }

                                GL.DrawArrays(primitive.DrawType, primitive.VertexStart, primitive.VertexCount);

                                vertexIndex++;
                            }

                        }


                        // 2. Draw the front-faces with a lighter color:
                        GL.CullFace(CullFaceMode.Front);
                        GL.VertexAttrib4((int)BaseRenderer.ShaderAttributeIds.Color, front_face_wireframe_color);
                        /*foreach (var primitive in _renderList[curNode.DataIndex])
                        {
                            GL.DrawArrays(primitive.DrawType, primitive.VertexStart, primitive.VertexCount);
                        }*/

                        GL.DisableVertexAttribArray((int)BaseRenderer.ShaderAttributeIds.Position);
                        GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
                        //GL.Enable(EnableCap.DepthTest);
                        GL.LineWidth(1);
                        #endregion
                    }
                    else
                    {
                        SetVertexAttribArraysForBatch(true, curNode.DataIndex);
                        //GL.CullFace(CullFaceMode.Front);
                        for (int packetIndex = 0; packetIndex < _renderList[curNode.DataIndex].Packets.Count; packetIndex++)
                        {
                            RenderPacket packet = _renderList[curNode.DataIndex].Packets[packetIndex];
                            foreach (var primitive in packet.PrimList)
                            {
                                renderer.SetModelMatrix(Matrix4.Identity);

                                if (primitive.PosMatrixIndex.Count > 0)
                                {
                                    var transformedData = new J3DRenderer.VertexFormatLayout[primitive.VertexCount];

                                    //For each vertex within this primitive, we're going to get its id.
                                    for (int vertexIndex = 0; vertexIndex < primitive.VertexCount; vertexIndex++)
                                    {
                                        ushort vertIndex = primitive.PosMatrixIndex[vertexIndex];
                                        ushort drawIndex = packet.DrawIndexes[vertIndex / 3];

                                        //ehh
                                        int seriously = 0;
                                        while (drawIndex == 0xFFFF)
                                        {
                                            RenderPacket prevPacket =
                                                _renderList[curNode.DataIndex].Packets[packetIndex - seriously];
                                            drawIndex = prevPacket.DrawIndexes[vertIndex / 3];
                                            seriously++;
                                        }

                                        bool isWeighted = _file.Draw.IsWeighted(drawIndex);
                                        if (isWeighted)
                                        {
                                            ushort numBonesAffecting =
                                                _file.Envelopes.GetCount(_file.Draw.GetIndex(drawIndex));

                                            //Much WTFs
                                            ushort offset = 0;
                                            for (ushort i = 0; i < _file.Draw.GetIndex(drawIndex); i++)
                                                offset += _file.Envelopes.GetCount(i);

                                            offset *= 2;
                                            Matrix4 finalTransform = Matrix4.Identity;
                                            for (ushort i = 0; i < numBonesAffecting; i++)
                                            {
                                                ushort boneIndex =
                                                    _file.Envelopes.GetIndexOffset((ushort)(offset + (i * 0x2)));
                                                float boneWeight = _file.Envelopes.GetWeight((ushort)((offset / 2) + i));

                                                Matrix3x4 envMatrix = _file.Envelopes.GetMatrix(boneIndex);
                                                Matrix4 newEnvelopeMtx = new Matrix4(envMatrix.Row0, envMatrix.Row1,
                                                    envMatrix.Row2, new Vector4(0, 0, 0, 1));

                                                SkeletonJoint joint = _skeleCopy[boneIndex];
                                                //Matrix4 transMatrix = Matrix4.CreateTranslation(joint.Position);
                                                //We need to use the bone's matrix from EVP1 to get the joint matrix
                                                Matrix4 jointMtx = joint.Rotation * newEnvelopeMtx;

                                                //finalTransform = Matrix4.Mult(jointMtx * newEnvelopeMtx, boneWeight) * finalTransform;
                                                //ToDo: This is the wrong scale.
                                                //AddScaleMatrix(ref finalTransform, Matrix4.Mult(jointMtx, newEnvelopeMtx), 1f);
                                            }

                                            transformedData[vertexIndex] = _vertDataBind[primitive.VertexStart + vertexIndex];

                                            Vector3 vertPosition = transformedData[vertexIndex].Position;
                                            transformedData[vertexIndex].Position = Vector3.TransformPosition(vertPosition, finalTransform);
                                        }
                                        else
                                        {
                                            //If the vertex is not weighted, we're just going to use the position
                                            //from the bone matrix. Something like this.
                                            Vector3 vertPosition =
                                                _vertDataBind[primitive.VertexStart + vertexIndex].Position;

                                            transformedData[vertexIndex] = _vertDataBind[primitive.VertexStart + vertexIndex];

                                            SkeletonJoint joint = _skeleCopy[_file.Draw.GetIndex(drawIndex)];
                                            Matrix4 transMatrix = Matrix4.CreateTranslation(joint.Position);
                                            Matrix4 final = joint.Rotation * transMatrix;
                                            transformedData[vertexIndex].Position = Vector3.TransformPosition(vertPosition, final);
                                        }
                                    }

                                    //Re-upload the subsection to the buffer.
                                    GL.BindBuffer(BufferTarget.ArrayBuffer, _glVbo);
                                    GL.BufferSubData(BufferTarget.ArrayBuffer, (IntPtr)(primitive.VertexStart * (9 * 4)),
                                        (IntPtr)(primitive.VertexCount * (9 * 4)), transformedData);

                                    float[] front_face_wireframe_color = { 1.0f, 1.0f, 1.0f, 1.0f };
                                    GL.VertexAttrib4((int)BaseRenderer.ShaderAttributeIds.Color, front_face_wireframe_color);
                                }


                                GL.DrawArrays(primitive.DrawType, primitive.VertexStart, primitive.VertexCount);
                            }

                        }

                        SetVertexAttribArraysForBatch(false, curNode.DataIndex);
                    }

                    break;
            }

            foreach (SceneGraph subNode in curNode.Children)
            {
                DrawModelRecursive(ref jointMatrix, subNode, renderer, bSelectedPass);
            }
        }