Esempio n. 1
0
        public static IReadOnlyList <AnimationFrame> CreateInstances(BinaryReader br, byte cFrames, Skeleton skeleton)
        {
            var bitReader       = new ExtapathyExtended.BitReader(br.BaseStream);
            var animationFrames = new AnimationFrame[cFrames];

            foreach (var n in Enumerable.Range(0, cFrames)) //frames
            {
                animationFrames[n] = n == 0
                    ? new AnimationFrame(bitReader, skeleton)
                    : new AnimationFrame(bitReader, skeleton, animationFrames[n - 1]);
            }

            return(animationFrames);
        }
Esempio n. 2
0
        private AnimationFrame(ExtapathyExtended.BitReader bitReader, Skeleton skeleton, AnimationFrame?previous = null)
        {
            /// <summary>
            /// Some enemies use additional information that is saved for bone AFTER rotation types. We
            /// are still not sure what it does as enemy works without it
            /// </summary>
            // ReSharper disable once UnusedLocalFunctionReturnValue
            (short unk1V, short unk2V, short unk3V) GetAdditionalRotationInformation()
            {
                short calc()
                {
                    var       unk1    = bitReader.ReadBits(1);
                    const int special = 1024;

                    if ((byte)unk1 <= 0)
                    {
                        return(special);                 // if checked here it'll crash
                    }
                    var unk1V = bitReader.ReadBits(16);

                    return(checked ((short)(unk1V + special)));
                }

                return(calc(), calc(), calc());
            }

            //Step 1. It starts with bone0.position. Let's read that into AnimationFrames[animId]- it's only one position per currentFrame

            var x = bitReader.ReadPositionType() * .01f;
            var y = bitReader.ReadPositionType() * .01f;
            var z = bitReader.ReadPositionType() * .01f;

            Position = !previous.HasValue
                ? new Vector3(x, y, z)
                : new Vector3(
                previous.Value.Position.X + x,
                previous.Value.Position.Y + y,
                previous.Value.Position.Z + z);

            var modeTest = (byte)bitReader.ReadBits(1); //used to determine if additional info is required

            var boneMatrix           = new Matrix[skeleton.CBones];
            var bonesVectorRotations = new Vector3[skeleton.CBones];

            //Step 2. We read the position and we need to store the bones rotations or save base rotation if currentFrame==0

            foreach (var k in Enumerable.Range(0, skeleton.CBones)) //bones iterator
            {
                if (previous.HasValue)                              //just like position the data for next frames are added to previous
                {
                    bonesVectorRotations[k] = new Vector3
                    {
                        X = bitReader.ReadRotationType(),
                        Y = bitReader.ReadRotationType(),
                        Z = bitReader.ReadRotationType()
                    };
                    if (modeTest > 0)
                    {
                        GetAdditionalRotationInformation();
                    }
                    var previousFrame = previous.Value.BonesVectorRotations[k];
                    var currentFrame  = bonesVectorRotations[k];
                    bonesVectorRotations[k] =
                        previousFrame + currentFrame;
                }
                else //if this is zero currentFrame, then we need to set the base rotations for bones
                {
                    bonesVectorRotations[k] = new Vector3
                    {
                        X = bitReader.ReadRotationType(),
                        Y = bitReader.ReadRotationType(),
                        Z = bitReader.ReadRotationType()
                    };
                    if (modeTest > 0)
                    {
                        GetAdditionalRotationInformation();
                    }
                }

                //Step 3. We now have all bone rotations stored into short. We need to convert that into Matrix and 360/4096

                var boneRotation = bonesVectorRotations[k];
                boneRotation =
                    Extended.S16VectorToFloat(
                        boneRotation);   //we had vector3 containing direct copy of short to float, now we need them in real floating point values
                boneRotation *= Degrees; //bone rotations are in 360 scope
                                         //maki way
                var xRot = Extended.GetRotationMatrixX(-boneRotation.X);
                var yRot = Extended.GetRotationMatrixY(-boneRotation.Y);
                var zRot = Extended.GetRotationMatrixZ(-boneRotation.Z);

                //this is the monogame way and gives same results as above.
                //Matrix xRot = Matrix.CreateRotationX(MathHelper.ToRadians(boneRotation.X));
                //Matrix yRot = Matrix.CreateRotationY(MathHelper.ToRadians(boneRotation.Y));
                //Matrix zRot = Matrix.CreateRotationZ(MathHelper.ToRadians(boneRotation.Z));

                var matrixZ = Extended.MatrixMultiply_transpose(yRot, xRot);
                matrixZ = Extended.MatrixMultiply_transpose(zRot, matrixZ);

                // ReSharper disable once CommentTypo
                if (skeleton.Bones[k].ParentId == 0xFFFF
                    ) //if parentId is 0xFFFF then the current bone is core aka bone0
                {
                    matrixZ.M41 = -Position.X;
                    matrixZ.M42 = -Position.Y; //up/down
                    matrixZ.M43 = Position.Z;
                    matrixZ.M44 = 1;
                }
                else
                {
                    var parentBone = boneMatrix[skeleton.Bones[k].ParentId]; //gets the parent bone
                    matrixZ.M43 = skeleton.Bones[skeleton.Bones[k].ParentId].Size;
                    var rMatrix = Matrix.Multiply(parentBone, matrixZ);
                    rMatrix.M41 = parentBone.M11 * matrixZ.M41 + parentBone.M12 * matrixZ.M42 +
                                  parentBone.M13 * matrixZ.M43 + parentBone.M41;
                    rMatrix.M42 = parentBone.M21 * matrixZ.M41 + parentBone.M22 * matrixZ.M42 +
                                  parentBone.M23 * matrixZ.M43 + parentBone.M42;
                    rMatrix.M43 = parentBone.M31 * matrixZ.M41 + parentBone.M32 * matrixZ.M42 +
                                  parentBone.M33 * matrixZ.M43 + parentBone.M43;
                    rMatrix.M44 = 1;
                    matrixZ     = rMatrix;
                }

                boneMatrix[k] = matrixZ;
            }

            BonesVectorRotations = bonesVectorRotations;
            BoneMatrix           = boneMatrix;
        }