Ejemplo n.º 1
0
        private void LoadTagDataFromFile(EndianBinaryReader reader, int tagCount, bool dumpTextures, bool dumpShaders)
        {
            for (int i = 0; i < tagCount; i++)
            {
                long tagStart = reader.BaseStream.Position;

                string tagName = reader.ReadString(4);
                int    tagSize = reader.ReadInt32();

                switch (tagName)
                {
                // INFO - Vertex Count, Scene Hierarchy
                case "INF1":
                    INF1Tag = new INF1();
                    INF1Tag.LoadINF1FromStream(reader, tagStart);
                    break;

                // VERTEX - Stores vertex arrays for pos/normal/color0/tex0 etc.
                // Contains VertexAttributes which describe how the data is stored/laid out.
                case "VTX1":
                    VTX1Tag = new VTX1();
                    VTX1Tag.LoadVTX1FromStream(reader, tagStart, tagSize);
                    break;

                // ENVELOPES - Defines vertex weights for skinning
                case "EVP1":
                    EVP1Tag = new EVP1();
                    EVP1Tag.LoadEVP1FromStream(reader, tagStart);
                    break;

                // DRAW (Skeletal Animation Data) - Stores which matrices (?) are weighted, and which are used directly
                case "DRW1":
                    DRW1Tag = new DRW1();
                    DRW1Tag.LoadDRW1FromStream(reader, tagStart);
                    break;

                // JOINTS - Stores the skeletal joints (position, rotation, scale, etc...)
                case "JNT1":
                    JNT1Tag = new JNT1();
                    JNT1Tag.LoadJNT1FromStream(reader, tagStart);
                    JNT1Tag.CalculateParentJointsForSkeleton(INF1Tag.HierarchyRoot);
                    break;

                // SHAPE - Face/Triangle information for model.
                case "SHP1":
                    SHP1Tag = new SHP1();
                    SHP1Tag.ReadSHP1FromStream(reader, tagStart);

                    CalculateModelBounds();
                    break;

                // MATERIAL - Stores materials (which describes how textures, etc. are drawn)
                case "MAT3":
                    MAT3Tag = new MAT3();
                    MAT3Tag.LoadMAT3FromStream(reader, tagStart);
                    break;

                // TEXTURES - Stores binary texture images.
                case "TEX1":
                    TEX1Tag = new TEX1();
                    TEX1Tag.LoadTEX1FromStream(reader, tagStart, dumpTextures);
                    break;

                // MODEL - Seems to be bypass commands for Materials and invokes GX registers directly.
                case "MDL3":
                    break;
                }

                // Skip the stream reader to the start of the next tag since it gets moved around during loading.
                reader.BaseStream.Position = tagStart + tagSize;
            }

            INF1Tag.LinkData(MAT3Tag, SHP1Tag);

            Tick(float.Epsilon);

            if (EVP1Tag.InverseBindPose.Count <= 0)
            {
                EVP1Tag.GenerateInverseBindMatrices(JNT1Tag);
            }

            DRW1Tag.UpdateMatrices(JNT1Tag.BindJoints, EVP1Tag);

            SHP1Tag.LinkData(VTX1Tag, DRW1Tag, EVP1Tag);
            SHP1Tag.UploadShapesToGPU();
        }
Ejemplo n.º 2
0
 public void LinkData(VTX1 vertex_data, DRW1 draw_matrix_data, EVP1 envelope_data)
 {
     LinkVertexData(vertex_data);
     LinkSkinningData(draw_matrix_data, envelope_data);
 }
Ejemplo n.º 3
0
        private void LinkSkinningData(DRW1 draw_matrix_data, EVP1 envelope_data)
        {
            foreach (Shape shape in Shapes)
            {
                int vertex_index = 0;

                shape.VertexDescription.EnableAttribute(ShaderAttributeIds.SkinIndices);
                shape.VertexDescription.EnableAttribute(ShaderAttributeIds.SkinWeights);

                foreach (MatrixGroup group in shape.MatrixGroups)
                {
                    foreach (MeshVertexIndex vertex in group.Indices)
                    {
                        int draw_mat_index  = vertex.PosMtxIndex >= 0 ? group.MatrixDataTable.MatrixTable[vertex.PosMtxIndex] : 0;
                        int transform_index = draw_matrix_data.TransformIndexTable[draw_mat_index];

                        // If this vertex is influenced by mulltiple bones, we build vec4s containing the indices and weights
                        // for each bone that influences it.
                        if (draw_matrix_data.IsPartiallyWeighted[draw_mat_index])
                        {
                            EVP1.Envelope envelope = envelope_data.Envelopes[transform_index];

                            // Because we're using vec4s for the skinning data, any vertex with more than 4 bones influencing it
                            // is invalid to us. We're going to assume this never happens, but in the event that it does, this assert
                            // will tell us.
                            Trace.Assert(envelope.NumBones <= 4);

                            Vector4 indices = new Vector4(0, 0, 0, 0);
                            Vector4 weights = new Vector4(0, 0, 0, 0);

                            for (int i = 0; i < envelope.NumBones; i++)
                            {
                                indices[i] = envelope.BoneIndexes[i];
                                weights[i] = envelope.BoneWeights[i];
                            }

                            shape.VertexData.SkinIndices.Add(indices);
                            shape.VertexData.SkinWeights.Add(weights);
                        }
                        // If the vertex only has a single bone influencing it, we need to do some extra work. The vertex is stored in
                        // bone space instead of bind space. We need to transform the vertex into bind space so we can work with it more easily.
                        else
                        {
                            Vector4 pos_as_vec4 = new Vector4(shape.VertexData.Position[vertex_index], 1.0f);
                            shape.VertexData.Position[vertex_index] = Vector4.Transform(pos_as_vec4, envelope_data.InverseBindPose[transform_index].Inverted()).Xyz;

                            Vector4 nrm_as_vec4 = new Vector4(shape.VertexData.Normal[vertex_index], 0.0f);
                            Matrix4 nrm_mat     = envelope_data.InverseBindPose[transform_index];
                            nrm_mat.Transpose();

                            shape.VertexData.Normal[vertex_index] = Vector4.Transform(nrm_as_vec4, nrm_mat).Xyz;

                            shape.VertexData.SkinIndices.Add(new Vector4(transform_index, 0, 0, 0));
                            shape.VertexData.SkinWeights.Add(new Vector4(1, 0, 0, 0));
                        }

                        vertex_index++;
                    }
                }
            }
        }
Ejemplo n.º 4
0
        private void LoadTagDataFromFile(EndianBinaryReader reader, int tagCount, bool dumpTextures, bool dumpShaders)
        {
            for (int i = 0; i < tagCount; i++)
            {
                long tagStart = reader.BaseStream.Position;

                string tagName = reader.ReadString(4);
                int    tagSize = reader.ReadInt32();

                switch (tagName)
                {
                // INFO - Vertex Count, Scene Hierarchy
                case "INF1":
                    INF1Tag = new INF1();
                    INF1Tag.LoadINF1FromStream(reader, tagStart);
                    break;

                // VERTEX - Stores vertex arrays for pos/normal/color0/tex0 etc.
                // Contains VertexAttributes which describe how the data is stored/laid out.
                case "VTX1":
                    VTX1Tag = new VTX1();
                    VTX1Tag.LoadVTX1FromStream(reader, tagStart, tagSize);
                    break;

                // ENVELOPES - Defines vertex weights for skinning
                case "EVP1":
                    EVP1Tag = new EVP1();
                    EVP1Tag.LoadEVP1FromStream(reader, tagStart);
                    break;

                // DRAW (Skeletal Animation Data) - Stores which matrices (?) are weighted, and which are used directly
                case "DRW1":
                    DRW1Tag = new DRW1();
                    DRW1Tag.LoadDRW1FromStream(reader, tagStart);
                    break;

                // JOINTS - Stores the skeletal joints (position, rotation, scale, etc...)
                case "JNT1":
                    JNT1Tag = new JNT1();
                    JNT1Tag.LoadJNT1FromStream(reader, tagStart);
                    JNT1Tag.CalculateParentJointsForSkeleton(INF1Tag.HierarchyRoot);
                    break;

                // SHAPE - Face/Triangle information for model.
                case "SHP1":
                    SHP1Tag = new SHP1();
                    SHP1Tag.ReadSHP1FromStream(reader, tagStart, VTX1Tag.VertexData);
                    break;

                // MATERIAL - Stores materials (which describes how textures, etc. are drawn)
                case "MAT3":
                    MAT3Tag = new MAT3();
                    MAT3Tag.LoadMAT3FromStream(reader, tagStart);
                    break;

                // TEXTURES - Stores binary texture images.
                case "TEX1":
                    TEX1Tag = new TEX1();
                    TEX1Tag.LoadTEX1FromStream(reader, tagStart, dumpTextures);
                    break;

                // MODEL - Seems to be bypass commands for Materials and invokes GX registers directly.
                case "MDL3":
                    break;
                }

                // Skip the stream reader to the start of the next tag since it gets moved around during loading.
                reader.BaseStream.Position = tagStart + tagSize;
            }

            // To generate shaders we need to know which vertex attributes need to be enabled for the shader. However,
            // the shader has no knowledge in our book as to what attributes are enabled. Theoretically we could enable
            // them on the fly as something requested it, but that'd involve more code that I don't want to do right now.
            // To resolve, we iterate once through the hierarchy to see which mesh is called after a material and bind the
            // vertex descriptions.
            Material dummyMat = null;

            AssignVertexAttributesToMaterialsRecursive(INF1Tag.HierarchyRoot, ref dummyMat, MAT3Tag);

            // Now that the vertex attributes are assigned to the materials, generate a shader from the data.
            GenerateShadersForMaterials(MAT3Tag, dumpShaders);

            // Iterate through the shapes and calculate a bounding box which encompasses all of them.
            Vector3 min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
            Vector3 max = new Vector3(float.MinValue, float.MinValue, float.MinValue);

            foreach (var shape in SHP1Tag.Shapes)
            {
                Vector3 sMin = shape.BoundingBox.Min;
                Vector3 sMax = shape.BoundingBox.Max;

                if (sMin.X < min.X)
                {
                    min.X = sMin.X;
                }
                if (sMax.X > max.X)
                {
                    max.X = sMax.X;
                }

                if (sMin.Y < min.Y)
                {
                    min.Y = sMin.Y;
                }
                if (sMax.Y > max.Y)
                {
                    max.Y = sMax.Y;
                }

                if (sMin.Z < min.Z)
                {
                    min.Z = sMin.Z;
                }
                if (sMax.Z > max.Z)
                {
                    max.Z = sMax.Z;
                }
            }

            BoundingBox    = new FAABox(min, max);
            BoundingSphere = new FSphere(BoundingBox.Center, BoundingBox.Max.Length);
        }