Exemple #1
0
 public AnimMeshPose(AnimMeshPose copyFrom)
 {
     Position        = copyFrom.Position;
     Rotation        = copyFrom.Rotation;
     AngularVelocity = copyFrom.AngularVelocity;
     Velocity        = copyFrom.Velocity;
     BoneNum         = copyFrom.BoneNum;
     FrameNum        = copyFrom.FrameNum;
 }
Exemple #2
0
        public void BuildPerFrameFKPoses()
        {
            perFrameFKPoses = new AnimMeshPose[NumFrames, NumBones];
            Point3D[]    parentPoints    = new Point3D[64];
            Quaternion[] parentRotations = new Quaternion[64];
            parentPoints[0]    = new Point3D(0, 0, 0);
            parentRotations[0] = new Quaternion(0, 0, 0, 1);
            for (int frame = 0; frame < NumFrames; ++frame)
            {
                for (int jointNum = 0; jointNum < skeletonDef.GetLength(0); ++jointNum)
                {
                    int        parentIndex = skeletonDef[jointNum];
                    Point3D    parentPos   = parentPoints[parentIndex];
                    Quaternion parentRot   = parentRotations[parentIndex];

                    // The world position of the child joint is the local position of the child joint rotated by the
                    // world rotation of the parent and then offset by the world position of the parent.
                    AnimMeshPose pose = perFramePoses[frame, jointNum];

                    Matrix3D m = Matrix3D.Identity;
                    m.Rotate(parentRot);
                    var thisPos = m.Transform(pose.Position);
                    thisPos.Offset(parentPos.X, parentPos.Y, parentPos.Z);

                    // The world rotation of the child joint is the world rotation of the parent rotated by the local rotation of the child.
                    var poseRot = pose.Rotation;
                    poseRot.Normalize();
                    Quaternion thisRot = Quaternion.Multiply(parentRot, poseRot);
                    thisRot.Normalize();

                    AnimMeshPose fkPose = new AnimMeshPose();
                    fkPose.Position = thisPos;
                    fkPose.Rotation = thisRot;
                    perFrameFKPoses[frame, jointNum] = fkPose;

                    parentPoints[parentIndex + 1]    = fkPose.Position;
                    parentRotations[parentIndex + 1] = fkPose.Rotation;
                }
            }
        }
Exemple #3
0
        public void BuildPerFrameFKPoses()
        {
            perFrameFKPoses = new AnimMeshPose[NumFrames, NumBones];
            Point3D[] parentPoints = new Point3D[64];
            Quaternion[] parentRotations = new Quaternion[64];
            parentPoints[0] = new Point3D(0, 0, 0);
            parentRotations[0] = new Quaternion(0, 0, 0, 1);
            for (int frame = 0; frame < NumFrames; ++frame) {
                for (int jointNum = 0; jointNum < skeletonDef.GetLength(0); ++jointNum) {

                    int parentIndex = skeletonDef[jointNum];
                    Point3D parentPos = parentPoints[parentIndex];
                    Quaternion parentRot = parentRotations[parentIndex];

                    // The world position of the child joint is the local position of the child joint rotated by the
                    // world rotation of the parent and then offset by the world position of the parent.
                    AnimMeshPose pose = perFramePoses[frame, jointNum];

                    Matrix3D m = Matrix3D.Identity;
                    m.Rotate(parentRot);
                    var thisPos = m.Transform(pose.Position);
                    thisPos.Offset(parentPos.X, parentPos.Y, parentPos.Z);

                    // The world rotation of the child joint is the world rotation of the parent rotated by the local rotation of the child.
                    var poseRot = pose.Rotation;
                    poseRot.Normalize();
                    Quaternion thisRot = Quaternion.Multiply(parentRot, poseRot);
                    thisRot.Normalize();

                    AnimMeshPose fkPose = new AnimMeshPose();
                    fkPose.Position = thisPos;
                    fkPose.Rotation = thisRot;
                    perFrameFKPoses[frame, jointNum] = fkPose;

                    parentPoints[parentIndex + 1] = fkPose.Position;
                    parentRotations[parentIndex + 1] = fkPose.Rotation;
                }
            }
        }
Exemple #4
0
        public void BuildPerFramePoses()
        {
            perFramePoses = new AnimMeshPose[NumFrames, NumBones];
            foreach (AnimMeshPose pose in MeshPoses)
            {
                if (pose != null)
                {
                    perFramePoses[pose.FrameNum, pose.BoneNum] = pose;
                }
            }
            for (int bone = 0; bone < NumBones; ++bone)
            {
                AnimMeshPose prevPose = null;
                for (int frame = 0; frame < NumFrames; ++frame)
                {
                    if (perFramePoses[frame, bone] == null)
                    {
                        int        frameDiff = frame - prevPose.FrameNum;
                        double     avCoeff   = frameDiff / 131072.0;
                        Quaternion rotDelta  = new Quaternion(prevPose.AngularVelocity.X * avCoeff, prevPose.AngularVelocity.Y * avCoeff, prevPose.AngularVelocity.Z * avCoeff, prevPose.AngularVelocity.W * avCoeff);

                        double  velCoeff = frameDiff / 512.0;
                        Point3D posDelta = new Point3D(prevPose.Velocity.X * velCoeff, prevPose.Velocity.Y * velCoeff, prevPose.Velocity.Z * velCoeff);

                        AnimMeshPose pose = new AnimMeshPose();
                        pose.BoneNum               = bone;
                        pose.FrameNum              = frame;
                        pose.Position              = new Point3D(prevPose.Position.X + posDelta.X, prevPose.Position.Y + posDelta.Y, prevPose.Position.Z + posDelta.Z);
                        pose.Rotation              = new Quaternion(prevPose.Rotation.X + rotDelta.X, prevPose.Rotation.Y + rotDelta.Y, prevPose.Rotation.Z + rotDelta.Z, prevPose.Rotation.W + rotDelta.W);
                        pose.AngularVelocity       = prevPose.AngularVelocity;
                        pose.Velocity              = prevPose.Velocity;
                        perFramePoses[frame, bone] = pose;
                    }
                    prevPose = perFramePoses[frame, bone];
                }
            }
        }
Exemple #5
0
        public static AnimData DecodeCRTA(EngineVersion engineVersion, byte[] data, int startOffset, int length)
        {
            int      endIndex = startOffset + length;
            AnimData animData = new AnimData();

            animData.NumBones    = DataUtil.getLEInt(data, startOffset);
            animData.Offset4Val  = DataUtil.getLEInt(data, startOffset + 4);
            animData.Offset14Val = DataUtil.getLEInt(data, startOffset + 0x14);
            animData.Offset18Val = DataUtil.getLEInt(data, startOffset + 0x18);
            int offset8Val = startOffset + DataUtil.getLEInt(data, startOffset + 8);

            int bindingPoseOffset = startOffset + DataUtil.getLEInt(data, startOffset + 0x0C);

            animData.bindingPose = new Point3D[animData.NumBones];
            for (int i = 0; i < animData.NumBones; ++i)
            {
                animData.bindingPose[i] = new Point3D(
                    -DataUtil.getLEShort(data, bindingPoseOffset + i * 8 + 0) / 64.0,
                    -DataUtil.getLEShort(data, bindingPoseOffset + i * 8 + 2) / 64.0,
                    -DataUtil.getLEShort(data, bindingPoseOffset + i * 8 + 4) / 64.0
                    );
            }

            // Skeleton structure
            int offset10Val = startOffset + DataUtil.getLEInt(data, startOffset + 0x10);

            animData.skeletonDef = new int[animData.NumBones];
            for (int i = 0; i < animData.NumBones; ++i)
            {
                animData.skeletonDef[i] = data[offset10Val + i];
            }

            AnimMeshPose[] curPose = new AnimMeshPose[animData.NumBones];

            AnimMeshPose pose      = null;
            var          bitReader = new BitstreamReader(data, offset8Val, length - (offset8Val - startOffset));

            for (int boneNum = 0; boneNum < animData.NumBones; ++boneNum)
            {
                pose          = new AnimMeshPose();
                pose.BoneNum  = boneNum;
                pose.FrameNum = 0;

                int posLen = bitReader.Read(4) + 1;
                pose.Position = new Point3D(
                    bitReader.Read(posLen) / 64.0,
                    bitReader.Read(posLen) / 64.0,
                    bitReader.Read(posLen) / 64.0);

                int    rotLen = bitReader.Read(4) + 1;
                double a      = bitReader.Read(rotLen) / 4096.0;
                double b      = bitReader.Read(rotLen) / 4096.0;
                double c      = bitReader.Read(rotLen) / 4096.0;
                double d      = bitReader.Read(rotLen) / 4096.0;

                pose.Rotation = new Quaternion(b, c, d, a);

                pose.Velocity        = new Point3D(0, 0, 0);
                pose.AngularVelocity = new Quaternion(0, 0, 0, 0);

                // This may give us duplicate frame zero poses, but that's ok.
                animData.MeshPoses.Add(pose);
                curPose[boneNum] = new AnimMeshPose(pose);
            }
            int[] curAngVelFrame = new int[animData.NumBones];
            int[] curVelFrame    = new int[animData.NumBones];

            animData.NumFrames = 1;

            int totalFrame = 0;

            pose = null;
            while (bitReader.HasData(16))
            {
                int count   = bitReader.Read(8);
                int flag    = bitReader.Read(1);
                int boneNum = bitReader.Read(6);

                totalFrame += count;

                if (pose == null || pose.FrameNum != totalFrame || pose.BoneNum != boneNum)
                {
                    if (pose != null)
                    {
                        animData.MeshPoses.Add(pose);
                    }
                    pose                 = new AnimMeshPose();
                    pose.FrameNum        = totalFrame;
                    pose.BoneNum         = boneNum;
                    pose.Position        = curPose[boneNum].Position;
                    pose.Rotation        = curPose[boneNum].Rotation;
                    pose.AngularVelocity = curPose[boneNum].AngularVelocity;
                    pose.Velocity        = curPose[boneNum].Velocity;
                }
                if (flag == 1)
                {
                    // xyz
                    int posLen = bitReader.Read(4) + 1;

                    int x = bitReader.Read(posLen);
                    int y = bitReader.Read(posLen);
                    int z = bitReader.Read(posLen);

                    Point3D vel      = new Point3D(x, y, z);
                    Point3D prevVel  = pose.Velocity;
                    double  coeff    = (totalFrame - curVelFrame[boneNum]) / 256.0;
                    Point3D posDelta = new Point3D(prevVel.X * coeff, prevVel.Y * coeff, prevVel.Z * coeff);
                    pose.Position = new Point3D(pose.Position.X + posDelta.X, pose.Position.Y + posDelta.Y, pose.Position.Z + posDelta.Z);
                    pose.FrameNum = totalFrame;
                    pose.Velocity = vel;

                    curPose[boneNum].Position = pose.Position;
                    curPose[boneNum].Velocity = pose.Velocity;
                    curVelFrame[boneNum]      = totalFrame;
                }
                else
                {
                    // rot
                    int rotLen = bitReader.Read(4) + 1;
                    int a      = bitReader.Read(rotLen);
                    int b      = bitReader.Read(rotLen);
                    int c      = bitReader.Read(rotLen);
                    int d      = bitReader.Read(rotLen);

                    Quaternion angVel = new Quaternion(b, c, d, a);

                    Quaternion prevAngVel = pose.AngularVelocity;
                    double     coeff      = (totalFrame - curAngVelFrame[boneNum]) / 131072.0;
                    Quaternion angDelta   = new Quaternion(prevAngVel.X * coeff, prevAngVel.Y * coeff, prevAngVel.Z * coeff, prevAngVel.W * coeff);
                    pose.Rotation = new Quaternion(pose.Rotation.X + angDelta.X, pose.Rotation.Y + angDelta.Y, pose.Rotation.Z + angDelta.Z, pose.Rotation.W + angDelta.W);

                    pose.FrameNum        = totalFrame;
                    pose.AngularVelocity = angVel;

                    curPose[boneNum].Rotation        = pose.Rotation;
                    curPose[boneNum].AngularVelocity = pose.AngularVelocity;
                    curAngVelFrame[boneNum]          = totalFrame;
                }
            }
            animData.MeshPoses.Add(pose);
            animData.NumFrames = totalFrame + 1;
            animData.BuildPerFramePoses();
            animData.BuildPerFrameFKPoses();
            return(animData);
        }
Exemple #6
0
        public static AnimData DecodeBGDA(EngineVersion engineVersion, byte[] data, int startOffset, int length)
        {
            int      endIndex = startOffset + length;
            AnimData animData = new AnimData();

            animData.NumBones    = DataUtil.getLEInt(data, startOffset);
            animData.Offset4Val  = DataUtil.getLEInt(data, startOffset + 4);
            animData.Offset14Val = DataUtil.getLEInt(data, startOffset + 0x14);
            animData.Offset18Val = DataUtil.getLEInt(data, startOffset + 0x18);
            int offset8Val = startOffset + DataUtil.getLEInt(data, startOffset + 8);

            int bindingPoseOffset = startOffset + DataUtil.getLEInt(data, startOffset + 0x0C);

            animData.bindingPose = new Point3D[animData.NumBones];
            for (int i = 0; i < animData.NumBones; ++i)
            {
                animData.bindingPose[i] = new Point3D(
                    -DataUtil.getLEShort(data, bindingPoseOffset + i * 8 + 0) / 64.0,
                    -DataUtil.getLEShort(data, bindingPoseOffset + i * 8 + 2) / 64.0,
                    -DataUtil.getLEShort(data, bindingPoseOffset + i * 8 + 4) / 64.0
                    );
            }

            // Skeleton structure
            int offset10Val = startOffset + DataUtil.getLEInt(data, startOffset + 0x10);

            animData.skeletonDef = new int[animData.NumBones];
            for (int i = 0; i < animData.NumBones; ++i)
            {
                animData.skeletonDef[i] = data[offset10Val + i];
            }

            AnimMeshPose[] curPose = new AnimMeshPose[animData.NumBones];

            AnimMeshPose pose = null;

            for (int boneNum = 0; boneNum < animData.NumBones; ++boneNum)
            {
                pose          = new AnimMeshPose();
                pose.BoneNum  = boneNum;
                pose.FrameNum = 0;
                int frameOff = offset8Val + boneNum * 0x0e;

                pose.Position = new Point3D(
                    DataUtil.getLEShort(data, frameOff) / 64.0,
                    DataUtil.getLEShort(data, frameOff + 2) / 64.0,
                    DataUtil.getLEShort(data, frameOff + 4) / 64.0);

                double a = DataUtil.getLEShort(data, frameOff + 6) / 4096.0;
                double b = DataUtil.getLEShort(data, frameOff + 8) / 4096.0;
                double c = DataUtil.getLEShort(data, frameOff + 0x0A) / 4096.0;
                double d = DataUtil.getLEShort(data, frameOff + 0x0C) / 4096.0;

                pose.Rotation = new Quaternion(b, c, d, a);

                pose.Velocity        = new Point3D(0, 0, 0);
                pose.AngularVelocity = new Quaternion(0, 0, 0, 0);

                // This may give us duplicate frame zero poses, but that's ok.
                animData.MeshPoses.Add(pose);
                curPose[boneNum] = new AnimMeshPose(pose);
            }
            int[] curAngVelFrame = new int[animData.NumBones];
            int[] curVelFrame    = new int[animData.NumBones];

            animData.NumFrames = 1;

            int totalFrame = 0;
            int otherOff   = offset8Val + animData.NumBones * 0x0e;

            pose = null;
            while (otherOff < endIndex)
            {
                int  count   = data[otherOff++];
                byte byte2   = data[otherOff++];
                int  boneNum = byte2 & 0x3f;
                if (boneNum == 0x3f)
                {
                    break;
                }

                totalFrame += count;

                if (pose == null || pose.FrameNum != totalFrame || pose.BoneNum != boneNum)
                {
                    if (pose != null)
                    {
                        animData.MeshPoses.Add(pose);
                    }
                    pose                 = new AnimMeshPose();
                    pose.FrameNum        = totalFrame;
                    pose.BoneNum         = boneNum;
                    pose.Position        = curPose[boneNum].Position;
                    pose.Rotation        = curPose[boneNum].Rotation;
                    pose.AngularVelocity = curPose[boneNum].AngularVelocity;
                    pose.Velocity        = curPose[boneNum].Velocity;
                }

                // bit 7 specifies whether to read 4 (set) or 3 elements following
                // bit 6 specifies whether they are shorts or bytes (set).
                if ((byte2 & 0x80) == 0x80)
                {
                    int a, b, c, d;
                    if ((byte2 & 0x40) == 0x40)
                    {
                        a = (sbyte)data[otherOff++];
                        b = (sbyte)data[otherOff++];
                        c = (sbyte)data[otherOff++];
                        d = (sbyte)data[otherOff++];
                    }
                    else
                    {
                        a         = DataUtil.getLEShort(data, otherOff);
                        b         = DataUtil.getLEShort(data, otherOff + 2);
                        c         = DataUtil.getLEShort(data, otherOff + 4);
                        d         = DataUtil.getLEShort(data, otherOff + 6);
                        otherOff += 8;
                    }
                    Quaternion angVel = new Quaternion(b, c, d, a);

                    Quaternion prevAngVel = pose.AngularVelocity;
                    double     coeff      = (totalFrame - curAngVelFrame[boneNum]) / 131072.0;
                    Quaternion angDelta   = new Quaternion(prevAngVel.X * coeff, prevAngVel.Y * coeff, prevAngVel.Z * coeff, prevAngVel.W * coeff);
                    pose.Rotation = new Quaternion(pose.Rotation.X + angDelta.X, pose.Rotation.Y + angDelta.Y, pose.Rotation.Z + angDelta.Z, pose.Rotation.W + angDelta.W);

                    pose.FrameNum        = totalFrame;
                    pose.AngularVelocity = angVel;

                    curPose[boneNum].Rotation        = pose.Rotation;
                    curPose[boneNum].AngularVelocity = pose.AngularVelocity;
                    curAngVelFrame[boneNum]          = totalFrame;
                }
                else
                {
                    int x, y, z;
                    if ((byte2 & 0x40) == 0x40)
                    {
                        x = (sbyte)data[otherOff++];
                        y = (sbyte)data[otherOff++];
                        z = (sbyte)data[otherOff++];
                    }
                    else
                    {
                        x         = DataUtil.getLEShort(data, otherOff);
                        y         = DataUtil.getLEShort(data, otherOff + 2);
                        z         = DataUtil.getLEShort(data, otherOff + 4);
                        otherOff += 6;
                    }
                    Point3D vel      = new Point3D(x, y, z);
                    Point3D prevVel  = pose.Velocity;
                    double  coeff    = (totalFrame - curVelFrame[boneNum]) / 512.0;
                    Point3D posDelta = new Point3D(prevVel.X * coeff, prevVel.Y * coeff, prevVel.Z * coeff);
                    pose.Position = new Point3D(pose.Position.X + posDelta.X, pose.Position.Y + posDelta.Y, pose.Position.Z + posDelta.Z);
                    pose.FrameNum = totalFrame;
                    pose.Velocity = vel;

                    curPose[boneNum].Position = pose.Position;
                    curPose[boneNum].Velocity = pose.Velocity;
                    curVelFrame[boneNum]      = totalFrame;
                }
            }
            animData.MeshPoses.Add(pose);
            animData.NumFrames = totalFrame + 1;
            animData.BuildPerFramePoses();
            animData.BuildPerFrameFKPoses();
            return(animData);
        }
Exemple #7
0
        public void BuildPerFramePoses()
        {
            perFramePoses = new AnimMeshPose[NumFrames, NumBones];
            foreach (AnimMeshPose pose in MeshPoses)
            {
                if (pose != null)
                {
                    perFramePoses[pose.FrameNum, pose.BoneNum] = pose;
                }
            }
            for (int bone = 0; bone < NumBones; ++bone)
            {
                AnimMeshPose prevPose = null;
                for (int frame = 0; frame < NumFrames; ++frame)
                {
                    if (perFramePoses[frame, bone] == null)
                    {
                        int frameDiff = frame - prevPose.FrameNum;
                        double avCoeff = frameDiff / 131072.0;
                        Quaternion rotDelta = new Quaternion(prevPose.AngularVelocity.X * avCoeff, prevPose.AngularVelocity.Y * avCoeff, prevPose.AngularVelocity.Z * avCoeff, prevPose.AngularVelocity.W * avCoeff);

                        double velCoeff = frameDiff / 512.0;
                        Point3D posDelta = new Point3D(prevPose.Velocity.X * velCoeff, prevPose.Velocity.Y * velCoeff, prevPose.Velocity.Z * velCoeff);

                        AnimMeshPose pose = new AnimMeshPose();
                        pose.BoneNum = bone;
                        pose.FrameNum = frame;
                        pose.Position = new Point3D(prevPose.Position.X + posDelta.X, prevPose.Position.Y + posDelta.Y, prevPose.Position.Z + posDelta.Z);
                        pose.Rotation = new Quaternion(prevPose.Rotation.X + rotDelta.X, prevPose.Rotation.Y + rotDelta.Y, prevPose.Rotation.Z + rotDelta.Z, prevPose.Rotation.W + rotDelta.W);
                        pose.AngularVelocity = prevPose.AngularVelocity;
                        pose.Velocity = prevPose.Velocity;
                        perFramePoses[frame, bone] = pose;
                    }
                    prevPose = perFramePoses[frame, bone];
                }
            }
        }
Exemple #8
0
        public static AnimData DecodeCRTA(EngineVersion engineVersion, byte[] data, int startOffset, int length)
        {
            int endIndex = startOffset + length;
            AnimData animData = new AnimData();
            animData.NumBones = DataUtil.getLEInt(data, startOffset);
            animData.Offset4Val = DataUtil.getLEInt(data, startOffset + 4);
            animData.Offset14Val = DataUtil.getLEInt(data, startOffset + 0x14);
            animData.Offset18Val = DataUtil.getLEInt(data, startOffset + 0x18);
            int offset8Val = startOffset + DataUtil.getLEInt(data, startOffset + 8);

            int bindingPoseOffset = startOffset + DataUtil.getLEInt(data, startOffset + 0x0C);
            animData.bindingPose = new Point3D[animData.NumBones];
            for (int i = 0; i < animData.NumBones; ++i) {
                animData.bindingPose[i] = new Point3D(
                    -DataUtil.getLEShort(data, bindingPoseOffset + i * 8 + 0) / 64.0,
                    -DataUtil.getLEShort(data, bindingPoseOffset + i * 8 + 2) / 64.0,
                    -DataUtil.getLEShort(data, bindingPoseOffset + i * 8 + 4) / 64.0
                );
            }

            // Skeleton structure
            int offset10Val = startOffset + DataUtil.getLEInt(data, startOffset + 0x10);
            animData.skeletonDef = new int[animData.NumBones];
            for (int i = 0; i < animData.NumBones; ++i) {
                animData.skeletonDef[i] = data[offset10Val + i];
            }

            AnimMeshPose[] curPose = new AnimMeshPose[animData.NumBones];

            AnimMeshPose pose = null;
            var bitReader = new BitstreamReader(data, offset8Val, length - (offset8Val - startOffset));
            for (int boneNum = 0; boneNum < animData.NumBones; ++boneNum) {
                pose = new AnimMeshPose();
                pose.BoneNum = boneNum;
                pose.FrameNum = 0;

                int posLen = bitReader.Read(4) + 1;
                pose.Position = new Point3D(
                    bitReader.Read(posLen) / 64.0,
                    bitReader.Read(posLen) / 64.0,
                    bitReader.Read(posLen) / 64.0);

                int rotLen = bitReader.Read(4) + 1;
                double a = bitReader.Read(rotLen) / 4096.0;
                double b = bitReader.Read(rotLen) / 4096.0;
                double c = bitReader.Read(rotLen) / 4096.0;
                double d = bitReader.Read(rotLen) / 4096.0;

                pose.Rotation = new Quaternion(b, c, d, a);

                pose.Velocity = new Point3D(0, 0, 0);
                pose.AngularVelocity = new Quaternion(0, 0, 0, 0);

                // This may give us duplicate frame zero poses, but that's ok.
                animData.MeshPoses.Add(pose);
                curPose[boneNum] = new AnimMeshPose(pose);
            }
            int[] curAngVelFrame = new int[animData.NumBones];
            int[] curVelFrame = new int[animData.NumBones];

            animData.NumFrames = 1;

            int totalFrame = 0;

            pose = null;
            while (bitReader.HasData(16)) {
                int count = bitReader.Read(8);
                int flag = bitReader.Read(1);
                int boneNum = bitReader.Read(6);

                totalFrame += count;

                if (pose == null || pose.FrameNum != totalFrame || pose.BoneNum != boneNum) {
                    if (pose != null) {
                        animData.MeshPoses.Add(pose);
                    }
                    pose = new AnimMeshPose();
                    pose.FrameNum = totalFrame;
                    pose.BoneNum = boneNum;
                    pose.Position = curPose[boneNum].Position;
                    pose.Rotation = curPose[boneNum].Rotation;
                    pose.AngularVelocity = curPose[boneNum].AngularVelocity;
                    pose.Velocity = curPose[boneNum].Velocity;
                }
                if (flag == 1) {
                    // xyz
                    int posLen = bitReader.Read(4) + 1;

                    int x = bitReader.Read(posLen);
                    int y = bitReader.Read(posLen);
                    int z = bitReader.Read(posLen);

                    Point3D vel = new Point3D(x, y, z);
                    Point3D prevVel = pose.Velocity;
                    double coeff = (totalFrame - curVelFrame[boneNum]) / 256.0;
                    Point3D posDelta = new Point3D(prevVel.X * coeff, prevVel.Y * coeff, prevVel.Z * coeff);
                    pose.Position = new Point3D(pose.Position.X + posDelta.X, pose.Position.Y + posDelta.Y, pose.Position.Z + posDelta.Z);
                    pose.FrameNum = totalFrame;
                    pose.Velocity = vel;

                    curPose[boneNum].Position = pose.Position;
                    curPose[boneNum].Velocity = pose.Velocity;
                    curVelFrame[boneNum] = totalFrame;
                } else {
                    // rot
                    int rotLen = bitReader.Read(4) + 1;
                    int a = bitReader.Read(rotLen);
                    int b = bitReader.Read(rotLen);
                    int c = bitReader.Read(rotLen);
                    int d = bitReader.Read(rotLen);

                    Quaternion angVel = new Quaternion(b, c, d, a);

                    Quaternion prevAngVel = pose.AngularVelocity;
                    double coeff = (totalFrame - curAngVelFrame[boneNum]) / 131072.0;
                    Quaternion angDelta = new Quaternion(prevAngVel.X * coeff, prevAngVel.Y * coeff, prevAngVel.Z * coeff, prevAngVel.W * coeff);
                    pose.Rotation = new Quaternion(pose.Rotation.X + angDelta.X, pose.Rotation.Y + angDelta.Y, pose.Rotation.Z + angDelta.Z, pose.Rotation.W + angDelta.W);

                    pose.FrameNum = totalFrame;
                    pose.AngularVelocity = angVel;

                    curPose[boneNum].Rotation = pose.Rotation;
                    curPose[boneNum].AngularVelocity = pose.AngularVelocity;
                    curAngVelFrame[boneNum] = totalFrame;
                }

            }
            animData.MeshPoses.Add(pose);
            animData.NumFrames = totalFrame + 1;
            animData.BuildPerFramePoses();
            animData.BuildPerFrameFKPoses();
            return animData;
        }
Exemple #9
0
        public static AnimData DecodeBGDA(EngineVersion engineVersion, byte[] data, int startOffset, int length)
        {
            int endIndex = startOffset + length;
            AnimData animData = new AnimData();
            animData.NumBones = DataUtil.getLEInt(data, startOffset);
            animData.Offset4Val = DataUtil.getLEInt(data, startOffset + 4);
            animData.Offset14Val = DataUtil.getLEInt(data, startOffset + 0x14);
            animData.Offset18Val = DataUtil.getLEInt(data, startOffset + 0x18);
            int offset8Val = startOffset + DataUtil.getLEInt(data, startOffset + 8);

            int bindingPoseOffset = startOffset + DataUtil.getLEInt(data, startOffset + 0x0C);
            animData.bindingPose = new Point3D[animData.NumBones];
            for (int i = 0; i < animData.NumBones; ++i)
            {
                animData.bindingPose[i] = new Point3D(
                    -DataUtil.getLEShort(data, bindingPoseOffset + i * 8 + 0) / 64.0,
                    -DataUtil.getLEShort(data, bindingPoseOffset + i * 8 + 2) / 64.0,
                    -DataUtil.getLEShort(data, bindingPoseOffset + i * 8 + 4) / 64.0
                );
            }

            // Skeleton structure
            int offset10Val = startOffset + DataUtil.getLEInt(data, startOffset + 0x10);
            animData.skeletonDef = new int[animData.NumBones];
            for (int i = 0; i < animData.NumBones; ++i)
            {
                animData.skeletonDef[i] = data[offset10Val + i];
            }

            AnimMeshPose[] curPose = new AnimMeshPose[animData.NumBones];

            AnimMeshPose pose = null;
            for (int boneNum = 0; boneNum < animData.NumBones; ++boneNum)
            {
                pose = new AnimMeshPose();
                pose.BoneNum = boneNum;
                pose.FrameNum = 0;
                int frameOff = offset8Val + boneNum * 0x0e;

                pose.Position = new Point3D(
                    DataUtil.getLEShort(data, frameOff) / 64.0,
                    DataUtil.getLEShort(data, frameOff + 2) / 64.0,
                    DataUtil.getLEShort(data, frameOff + 4) / 64.0);

                double a = DataUtil.getLEShort(data, frameOff + 6) / 4096.0;
                double b = DataUtil.getLEShort(data, frameOff + 8) / 4096.0;
                double c = DataUtil.getLEShort(data, frameOff + 0x0A) / 4096.0;
                double d = DataUtil.getLEShort(data, frameOff + 0x0C) / 4096.0;

                pose.Rotation = new Quaternion(b, c, d, a);

                pose.Velocity = new Point3D(0, 0, 0);
                pose.AngularVelocity = new Quaternion(0, 0, 0, 0);

                // This may give us duplicate frame zero poses, but that's ok.
                animData.MeshPoses.Add(pose);
                curPose[boneNum] = new AnimMeshPose(pose);
            }
            int[] curAngVelFrame = new int[animData.NumBones];
            int[] curVelFrame = new int[animData.NumBones];

            animData.NumFrames = 1;

            int totalFrame = 0;
            int otherOff = offset8Val + animData.NumBones * 0x0e;

            pose = null;
            while (otherOff < endIndex) {
                int count = data[otherOff++];
                byte byte2 = data[otherOff++];
                int boneNum = byte2 & 0x3f;
                if (boneNum == 0x3f) break;

                totalFrame += count;

                if (pose == null || pose.FrameNum != totalFrame || pose.BoneNum != boneNum)
                {
                    if (pose != null)
                    {
                        animData.MeshPoses.Add(pose);
                    }
                    pose = new AnimMeshPose();
                    pose.FrameNum = totalFrame;
                    pose.BoneNum = boneNum;
                    pose.Position = curPose[boneNum].Position;
                    pose.Rotation = curPose[boneNum].Rotation;
                    pose.AngularVelocity = curPose[boneNum].AngularVelocity;
                    pose.Velocity = curPose[boneNum].Velocity;
                }

                // bit 7 specifies whether to read 4 (set) or 3 elements following
                // bit 6 specifies whether they are shorts or bytes (set).
                if ((byte2 & 0x80) == 0x80) {
                    int a, b, c, d;
                    if ((byte2 & 0x40) == 0x40) {
                        a = (sbyte)data[otherOff++];
                        b = (sbyte)data[otherOff++];
                        c = (sbyte)data[otherOff++];
                        d = (sbyte)data[otherOff++];
                    } else {
                        a = DataUtil.getLEShort(data, otherOff);
                        b = DataUtil.getLEShort(data, otherOff+2);
                        c = DataUtil.getLEShort(data, otherOff+4);
                        d = DataUtil.getLEShort(data, otherOff+6);
                        otherOff += 8;
                    }
                    Quaternion angVel = new Quaternion(b, c, d, a);

                    Quaternion prevAngVel = pose.AngularVelocity;
                    double coeff = (totalFrame - curAngVelFrame[boneNum]) / 131072.0;
                    Quaternion angDelta = new Quaternion(prevAngVel.X * coeff, prevAngVel.Y * coeff, prevAngVel.Z * coeff, prevAngVel.W * coeff);
                    pose.Rotation = new Quaternion(pose.Rotation.X + angDelta.X, pose.Rotation.Y + angDelta.Y, pose.Rotation.Z + angDelta.Z, pose.Rotation.W + angDelta.W);

                    pose.FrameNum = totalFrame;
                    pose.AngularVelocity = angVel;

                    curPose[boneNum].Rotation = pose.Rotation;
                    curPose[boneNum].AngularVelocity = pose.AngularVelocity;
                    curAngVelFrame[boneNum] = totalFrame;
                }
                else
                {
                    int x, y, z;
                    if ((byte2 & 0x40) == 0x40) {
                        x = (sbyte)data[otherOff++];
                        y = (sbyte)data[otherOff++];
                        z = (sbyte)data[otherOff++];
                    } else {
                        x = DataUtil.getLEShort(data, otherOff);
                        y = DataUtil.getLEShort(data, otherOff + 2);
                        z = DataUtil.getLEShort(data, otherOff + 4);
                        otherOff += 6;
                    }
                    Point3D vel = new Point3D(x, y, z);
                    Point3D prevVel = pose.Velocity;
                    double coeff = (totalFrame - curVelFrame[boneNum]) / 512.0;
                    Point3D posDelta = new Point3D(prevVel.X * coeff, prevVel.Y * coeff, prevVel.Z * coeff);
                    pose.Position = new Point3D(pose.Position.X + posDelta.X, pose.Position.Y + posDelta.Y, pose.Position.Z + posDelta.Z);
                    pose.FrameNum = totalFrame;
                    pose.Velocity = vel;

                    curPose[boneNum].Position = pose.Position;
                    curPose[boneNum].Velocity = pose.Velocity;
                    curVelFrame[boneNum] = totalFrame;
                }
            }
            animData.MeshPoses.Add(pose);
            animData.NumFrames = totalFrame+1;
            animData.BuildPerFramePoses();
            animData.BuildPerFrameFKPoses();
            return animData;
        }
Exemple #10
0
 public AnimMeshPose(AnimMeshPose copyFrom)
 {
     Position = copyFrom.Position;
     Rotation = copyFrom.Rotation;
     AngularVelocity = copyFrom.AngularVelocity;
     Velocity = copyFrom.Velocity;
     BoneNum = copyFrom.BoneNum;
     FrameNum = copyFrom.FrameNum;
 }
Exemple #11
0
        public static AnimData DecodeCRTA(EngineVersion engineVersion, byte[] data, int startOffset, int length)
        {
            var endIndex = startOffset + length;
            var animData = new AnimData
            {
                NumBones    = DataUtil.getLEInt(data, startOffset),
                Offset4Val  = DataUtil.getLEInt(data, startOffset + 4),    // max frame
                Offset14Val = DataUtil.getLEInt(data, startOffset + 0x14),
                Offset18Val = DataUtil.getLEInt(data, startOffset + 0x18)
            };
            var offset8Val = DataUtil.getLEInt(data, startOffset + 8);

            var bindingPoseOffset = startOffset + DataUtil.getLEInt(data, startOffset + 0x0C);

            animData.bindingPose = new Point3D[animData.NumBones];
            for (var i = 0; i < animData.NumBones; ++i)
            {
                animData.bindingPose[i] = new Point3D(
                    -DataUtil.getLEShort(data, bindingPoseOffset + i * 8 + 0) / 64.0,
                    -DataUtil.getLEShort(data, bindingPoseOffset + i * 8 + 2) / 64.0,
                    -DataUtil.getLEShort(data, bindingPoseOffset + i * 8 + 4) / 64.0
                    );
            }

            // Skeleton structure
            var offset10Val = startOffset + DataUtil.getLEInt(data, startOffset + 0x10);

            animData.skeletonDef = new int[animData.NumBones];
            for (var i = 0; i < animData.NumBones; ++i)
            {
                animData.skeletonDef[i] = data[offset10Val + i];
            }

            var curPose = new AnimMeshPose[animData.NumBones];

            AnimMeshPose pose      = null;
            var          bitReader = new BitstreamReader(data, startOffset + offset8Val, length - offset8Val);

            for (var boneNum = 0; boneNum < animData.NumBones; ++boneNum)
            {
                pose = new AnimMeshPose
                {
                    BoneNum  = boneNum,
                    FrameNum = 0
                };

                var posLen = bitReader.Read(4) + 1;
                pose.Position = new Point3D(
                    bitReader.ReadSigned(posLen) / 64.0,
                    bitReader.ReadSigned(posLen) / 64.0,
                    bitReader.ReadSigned(posLen) / 64.0);

                var rotLen = bitReader.Read(4) + 1;
                var a      = bitReader.ReadSigned(rotLen) / 4096.0;
                var b      = bitReader.ReadSigned(rotLen) / 4096.0;
                var c      = bitReader.ReadSigned(rotLen) / 4096.0;
                var d      = bitReader.ReadSigned(rotLen) / 4096.0;

                pose.Rotation = new Quaternion(b, c, d, a);

                pose.Velocity        = new Point3D(0, 0, 0);
                pose.AngularVelocity = new Quaternion(0, 0, 0, 0);

                // This may give us duplicate frame zero poses, but that's ok.
                animData.MeshPoses.Add(pose);
                curPose[boneNum] = new AnimMeshPose(pose);
            }
            var curAngVelFrame = new int[animData.NumBones];
            var curVelFrame    = new int[animData.NumBones];

            animData.NumFrames = 1;

            var totalFrame = 0;

            pose = null;
            while (bitReader.HasData(22) && totalFrame < animData.Offset4Val)
            {
                int count = bitReader.Read(8);
                if (count == 0xFF)
                {
                    break;
                }
                int flag    = bitReader.Read(1);
                int boneNum = bitReader.Read(6);

                if (boneNum >= animData.NumBones)
                {
                    break;
                }

                totalFrame += count;

                if (pose == null || pose.FrameNum != totalFrame || pose.BoneNum != boneNum)
                {
                    if (pose != null)
                    {
                        animData.MeshPoses.Add(pose);
                    }
                    pose = new AnimMeshPose
                    {
                        FrameNum        = totalFrame,
                        BoneNum         = boneNum,
                        Position        = curPose[boneNum].Position,
                        Rotation        = curPose[boneNum].Rotation,
                        AngularVelocity = curPose[boneNum].AngularVelocity,
                        Velocity        = curPose[boneNum].Velocity
                    };
                }
                if (flag == 1)
                {
                    // xyz
                    var posLen = bitReader.Read(4) + 1;

                    var x = bitReader.ReadSigned(posLen);
                    var y = bitReader.ReadSigned(posLen);
                    var z = bitReader.ReadSigned(posLen);

                    var vel      = new Point3D(x, y, z);
                    var prevVel  = pose.Velocity;
                    var coeff    = (totalFrame - curVelFrame[boneNum]) / 256.0;
                    var posDelta = new Point3D(prevVel.X * coeff, prevVel.Y * coeff, prevVel.Z * coeff);
                    pose.Position = new Point3D(pose.Position.X + posDelta.X, pose.Position.Y + posDelta.Y, pose.Position.Z + posDelta.Z);
                    pose.FrameNum = totalFrame;
                    pose.Velocity = vel;

                    curPose[boneNum].Position = pose.Position;
                    curPose[boneNum].Velocity = pose.Velocity;
                    curVelFrame[boneNum]      = totalFrame;
                }
                else
                {
                    // rot
                    var rotLen = bitReader.Read(4) + 1;
                    var a      = bitReader.ReadSigned(rotLen);
                    var b      = bitReader.ReadSigned(rotLen);
                    var c      = bitReader.ReadSigned(rotLen);
                    var d      = bitReader.ReadSigned(rotLen);

                    var angVel = new Quaternion(b, c, d, a);

                    var prevAngVel = pose.AngularVelocity;
                    var coeff      = (totalFrame - curAngVelFrame[boneNum]) / 131072.0;
                    var angDelta   = new Quaternion(prevAngVel.X * coeff, prevAngVel.Y * coeff, prevAngVel.Z * coeff, prevAngVel.W * coeff);
                    pose.Rotation = new Quaternion(pose.Rotation.X + angDelta.X, pose.Rotation.Y + angDelta.Y, pose.Rotation.Z + angDelta.Z, pose.Rotation.W + angDelta.W);

                    pose.FrameNum        = totalFrame;
                    pose.AngularVelocity = angVel;

                    curPose[boneNum].Rotation        = pose.Rotation;
                    curPose[boneNum].AngularVelocity = pose.AngularVelocity;
                    curAngVelFrame[boneNum]          = totalFrame;
                }
            }
            animData.MeshPoses.Add(pose);
            animData.NumFrames = animData.Offset4Val + 1; // totalFrame + 1;
            animData.BuildPerFramePoses();
            animData.BuildPerFrameFKPoses();
            return(animData);
        }
Exemple #12
0
        public static Model3D CreateModel3D(List <Mesh> meshGroups, BitmapSource texture, AnimData pose, int frame)
        {
            GeometryModel3D model  = new GeometryModel3D();
            var             mesh3D = new MeshGeometry3D();

            int numVertices = 0;

            foreach (var meshGroup in meshGroups)
            {
                numVertices += meshGroup.Positions.Count;
            }
            var triangleIndices = new Int32Collection();
            var positions       = new Point3DCollection(numVertices);
            var normals         = new Vector3DCollection(numVertices);
            var uvCoords        = new PointCollection(numVertices);
            int vstart          = 0;

            foreach (var meshGroup in meshGroups)
            {
                Boolean      hasVertexWeights = meshGroup.vertexWeights.Count > 0;
                int          vwNum            = 0;
                VertexWeight vw = new VertexWeight();
                if (meshGroup.vertexWeights.Count > 0)
                {
                    vw = meshGroup.vertexWeights[vwNum];
                }
                int vnum = 0;
                foreach (var vertex in meshGroup.Positions)
                {
                    var point = vertex;
                    if (frame >= 0 && pose != null)
                    {
                        if (vw.endVertex < vnum)
                        {
                            ++vwNum;
                            vw = meshGroup.vertexWeights[vwNum];
                            if (vnum < vw.startVertex || vnum > vw.endVertex)
                            {
                                Debug.Fail("Vertex " + vnum + " out of range of bone weights " + vw.startVertex + " -> " + vw.endVertex);
                            }
                        }
                        int          bone1No     = vw.bone1;
                        Point3D      bindingPos1 = pose.bindingPose[bone1No];
                        AnimMeshPose bone1Pose   = pose.perFrameFKPoses[frame, bone1No];
                        var          joint1Pos   = bone1Pose.Position;
                        if (vw.bone2 == 0xFF)
                        {
                            if (bone1No == 1)
                            {
                                bone1No = 1;
                            }
                            Matrix3D m = Matrix3D.Identity;
                            m.Translate(new Vector3D(-bindingPos1.X, -bindingPos1.Y, -bindingPos1.Z));   // Inverse binding matrix
                            m.Rotate(bone1Pose.Rotation);
                            m.Translate(new Vector3D(bone1Pose.Position.X, bone1Pose.Position.Y, bone1Pose.Position.Z));
                            point = m.Transform(point);
                        }
                        else
                        {
                            // multi-bone
                            int          bone2No     = vw.bone2;
                            Point3D      bindingPos2 = pose.bindingPose[bone2No];
                            AnimMeshPose bone2Pose   = pose.perFrameFKPoses[frame, bone2No];
                            double       boneSum     = vw.boneWeight1 + vw.boneWeight2;
                            double       bone1Coeff  = vw.boneWeight1 / boneSum;
                            double       bone2Coeff  = vw.boneWeight2 / boneSum;

                            Matrix3D m = Matrix3D.Identity;
                            m.Translate(new Vector3D(-bindingPos1.X, -bindingPos1.Y, -bindingPos1.Z));   // Inverse binding matrix
                            m.Rotate(bone1Pose.Rotation);
                            m.Translate(new Vector3D(bone1Pose.Position.X, bone1Pose.Position.Y, bone1Pose.Position.Z));
                            var point1 = m.Transform(point);

                            // Now rotate
                            Matrix3D m2 = Matrix3D.Identity;
                            m2.Translate(new Vector3D(-bindingPos2.X, -bindingPos2.Y, -bindingPos2.Z));   // Inverse binding matrix
                            m2.Rotate(bone2Pose.Rotation);
                            m2.Translate(new Vector3D(bone2Pose.Position.X, bone2Pose.Position.Y, bone2Pose.Position.Z));
                            var point2 = m2.Transform(point);

                            point = new Point3D(point1.X * bone1Coeff + point2.X * bone2Coeff, point1.Y * bone1Coeff + point2.Y * bone2Coeff, point1.Z * bone1Coeff + point2.Z * bone2Coeff);
                        }
                    }
                    positions.Add(point);
                    ++vnum;
                }
                foreach (var normal in meshGroup.Normals)
                {
                    normals.Add(normal);
                }
                foreach (var ti in meshGroup.TriangleIndices)
                {
                    triangleIndices.Add(ti + vstart);
                }
                foreach (var uv in meshGroup.TextureCoordinates)
                {
                    uvCoords.Add(uv);
                }
                vstart += meshGroup.Positions.Count;
            }
            mesh3D.TriangleIndices    = triangleIndices;
            mesh3D.Positions          = positions;
            mesh3D.TextureCoordinates = uvCoords;
            mesh3D.Normals            = normals;
            model.Geometry            = mesh3D;
            var dm = new DiffuseMaterial();

            if (texture != null && texture.Width > 0 && texture.Height > 0)
            {
                var ib = new ImageBrush(texture);
                ib.ViewportUnits = BrushMappingMode.Absolute;
                // May be needed at a later point
                //ib.TileMode = TileMode.Tile;
                dm.Brush = ib;
            }
            else
            {
                var dg = new DrawingGroup();
                // Background
                dg.Children.Add(new GeometryDrawing()
                {
                    Brush    = new SolidColorBrush(Colors.Black),
                    Geometry = new RectangleGeometry(new Rect(0, 0, 2, 2))
                });

                // Tiles
                dg.Children.Add(new GeometryDrawing()
                {
                    Brush    = new SolidColorBrush(Colors.Violet),
                    Geometry = new RectangleGeometry(new Rect(0, 0, 1, 1))
                });
                dg.Children.Add(new GeometryDrawing()
                {
                    Brush    = new SolidColorBrush(Colors.Violet),
                    Geometry = new RectangleGeometry(new Rect(1, 1, 1, 1))
                });

                dm.Brush = new DrawingBrush(dg)
                {
                    TileMode = TileMode.Tile, Transform = new ScaleTransform(0.1, 0.1)
                };
            }
            model.Material = dm;
            return(model);
        }