Example #1
0
 public SkeletonBone(SkeletonBone other)
 {
     Name = other.Name;
     Parent = other.Parent;
     Scale = other.Scale;
     Rotation = other.Rotation;
     Translation = other.Translation;
     BoundingSphereDiameter = other.BoundingSphereDiameter;
     BoundingBoxMin = other.BoundingBoxMin;
     BoundingBoxMax = other.BoundingBoxMax;
 }
Example #2
0
 public SkeletonBone()
 {
     Name = "Joint";
     Parent = null;
     Scale = Vector3.One;
     Rotation = Quaternion.Identity;
     Translation = Vector3.Zero;
     BoundingSphereDiameter = 0f;
     BoundingBoxMin = Vector3.Zero;
     BoundingBoxMax = Vector3.Zero;
 }
Example #3
0
 public SkeletonBone(SkeletonBone other)
 {
     Name                   = other.Name;
     Parent                 = other.Parent;
     Scale                  = other.Scale;
     Rotation               = other.Rotation;
     Translation            = other.Translation;
     BoundingSphereDiameter = other.BoundingSphereDiameter;
     BoundingBoxMin         = other.BoundingBoxMin;
     BoundingBoxMax         = other.BoundingBoxMax;
 }
Example #4
0
 public SkeletonBone()
 {
     Name                   = "Joint";
     Parent                 = null;
     Scale                  = Vector3.One;
     Rotation               = Quaternion.Identity;
     Translation            = Vector3.Zero;
     BoundingSphereDiameter = 0f;
     BoundingBoxMin         = Vector3.Zero;
     BoundingBoxMax         = Vector3.Zero;
 }
Example #5
0
        private void DrawMesh(Mesh mesh, Camera camera, Matrix4 additionalMatrix)
        {
            if (mesh == null)
            {
                return;
            }

            Matrix4 viewMatrix = camera.ViewMatrix;
            Matrix4 projMatrix = camera.ProjectionMatrix;

            foreach (var batch in mesh.SubMeshes)
            {
                // Bind the shader
                if (batch.Material != null)
                {
                    if (batch.Material.Shader != null)
                    {
                        batch.Material.Shader.Bind();
                    }
                }

                // ToDo: Get the model's position in the world from the entity it belongs to and create a model matrix from that.
                Matrix4 modelMatrix = additionalMatrix;

                // Before we draw it, we're going to do something incredibly stupid, and try to add bone support.
                Matrix4[] boneTransforms = new Matrix4[mesh.Skeleton.Count];
                for (int i = 0; i < mesh.Skeleton.Count; i++)
                {
                    SkeletonBone bone = mesh.Skeleton[i];
                    Matrix4      cumulativeTransform = Matrix4.Identity;

                    while (bone != null)
                    {
                        cumulativeTransform = cumulativeTransform * Matrix4.CreateScale(bone.Scale) * Matrix4.CreateFromQuaternion(bone.Rotation) * Matrix4.CreateTranslation(bone.Translation);
                        bone = bone.Parent;
                    }

                    boneTransforms[i] = cumulativeTransform;
                }

                // Each boneCopy is now in it's final position, so we can apply that to the vertexes based on their bone weighting.
                // However, vertex positions have already been uploaded once, so we're uh... going to hack it and re-upload them.
                Vector3[] origVerts = batch.Vertices;
                Vector3[] vertices  = new Vector3[origVerts.Length];
                Array.Copy(origVerts, vertices, origVerts.Length);

                for (int v = 0; v < vertices.Length; v++)
                {
                    BoneWeight weights     = batch.BoneWeights[v];
                    Matrix4    finalMatrix = Matrix4.Zero;

                    for (int w = 0; w < weights.BoneIndexes.Length; w++)
                    {
                        Matrix4 boneInfluence = boneTransforms[weights.BoneIndexes[w]];
                        float   weight        = weights.BoneWeights[w];

                        finalMatrix = (boneInfluence * weight) + finalMatrix;
                    }

                    vertices[v] = Vector3.TransformPosition(vertices[v], finalMatrix);
                }

                // Now re-assign our Vertices to the mesh so they get uploaded to the GPU...
                batch.Vertices = vertices;

                // Bind the VAOs currently associated with this Mesh
                batch.Bind();

                // Bind our Textures
                GL.ActiveTexture(TextureUnit.Texture0);
                if (batch.Material.Textures[0] != null)
                {
                    batch.Material.Textures[0].Bind();
                }

                // Upload uniforms to the GPU
                GL.UniformMatrix4(batch.Material.Shader.UniformModelMtx, false, ref modelMatrix);
                GL.UniformMatrix4(batch.Material.Shader.UniformViewMtx, false, ref viewMatrix);
                GL.UniformMatrix4(batch.Material.Shader.UniformProjMtx, false, ref projMatrix);

                // Set our Blend, Cull, Depth and Dither states. Alpha Compare is
                // done in the pixel shader due to Nintendo having advanced AC options.
                GX2OpenGL.SetBlendState(batch.Material.BlendMode);
                GX2OpenGL.SetCullState(batch.Material.CullMode);
                GX2OpenGL.SetDepthState(batch.Material.ZMode);
                GX2OpenGL.SetDitherState(batch.Material.Dither);

                // Draw our Mesh.
                GL.DrawElements(batch.PrimitveType, batch.Indexes.Length, DrawElementsType.UnsignedInt, 0);

                // Unbind the VAOs so that our VAO doesn't leak into the next drawcall.
                batch.Unbind();

                // And finally restore our 'source' vertex positions
                batch.Vertices = origVerts;
            }
        }
Example #6
0
        private static List<SkeletonBone> LoadJNT1SectionFromStream(EndianBinaryReader reader, long chunkStart)
        {
            List<SkeletonBone> skeletonBones = new List<SkeletonBone>();

            ushort numJoints = reader.ReadUInt16();
            ushort padding = reader.ReadUInt16();
            uint jointDataOffset = reader.ReadUInt32(); // Relative to JNT1 Header Start
            uint jointRemapOffset = reader.ReadUInt32();
            uint stringTableOffset = reader.ReadUInt32();

            // Grab the joint names from file
            reader.BaseStream.Position = chunkStart + stringTableOffset;
            StringTable jointNames = StringTable.FromStream(reader);

            // This is always 0 to (numJoints-1) - unsure if it's a joint
            // remap (likely) or a string-table remap (less likely). It's unknown
            // if any models don't follow this 0 to (n-1) pattern.
            ushort[] jointRemaps = new ushort[numJoints];
            reader.BaseStream.Position = chunkStart + jointRemapOffset;
            for (int j = 0; j < numJoints; j++)
                jointRemaps[j] = reader.ReadUInt16();

            // Grab the actual joints
            reader.BaseStream.Position = chunkStart + jointDataOffset;
            for (int j = 0; j < numJoints; j++)
            {
                SkeletonBone bone = new SkeletonBone();

                bone.Name = jointNames[j];
                ushort unknown1 = reader.ReadUInt16();  // Values of 0, 2 or 1. yaz0r calls it Matrix Type (referring to 'MatrixTable' which is an index into DRW1 - Draw type?
                                                        // If value is 1 or 2 then Bounding Box / Radius is Vector3.Zero / 0f
                                                        // And seems to be 0 if a joint has direct non-joint children (Maybe 0 is a 'bone with children' and the BBMin/Max contain
                                                        // the bounds of children?
                ushort unknown2 = reader.ReadUInt16();  // No one seems to know what it is, often 0xFF or 0 or 1. May be two individual bytes with a pad afterwards.

                for (int f = 0; f < 3; f++)
                    bone.Scale[f] = reader.ReadSingle();

                Vector3 eulerAngles = new Vector3();
                for (int f = 0; f < 3; f++)
                    eulerAngles[f] = (reader.ReadInt16() * (180 / 32786f));

                Quaternion xAxis = Quaternion.FromAxisAngle(new Vector3(1, 0, 0), eulerAngles.X * MathE.Deg2Rad);
                Quaternion yAxis = Quaternion.FromAxisAngle(new Vector3(0, 1, 0), eulerAngles.Y * MathE.Deg2Rad);
                Quaternion zAxis = Quaternion.FromAxisAngle(new Vector3(0, 0, 1), eulerAngles.Z * MathE.Deg2Rad);

                // Swizzling to the ZYX order seems to be the right one.
                Quaternion finalRot = zAxis * yAxis * xAxis;

                bone.Rotation = finalRot;
                Trace.Assert(reader.ReadUInt16() == 0xFFFF); // Padding
                for (int f = 0; f < 3; f++)
                    bone.Translation[f] = reader.ReadSingle();
                bone.BoundingSphereDiameter = reader.ReadSingle();
                for (int f = 0; f < 3; f++)
                    bone.BoundingBoxMin[f] = reader.ReadSingle();
                for (int f = 0; f < 3; f++)
                    bone.BoundingBoxMax[f] = reader.ReadSingle();

                skeletonBones.Add(bone);
            }
            return skeletonBones;
        }