コード例 #1
0
        public static Model3D GetSkeletonModel(AnimData animData, int frameNo)
        {
            if (null == animData) {
                return null;
            }

            GeometryModel3D model = new GeometryModel3D();
            MeshGeometry3D mesh = new MeshGeometry3D();

            Point3D[] parentPoints = new Point3D[64];
            parentPoints[0] = new Point3D(0, 0, 0);

            for (int jointNum = 0; jointNum < animData.skeletonDef.GetLength(0); ++jointNum)
            {
                int parentIndex = animData.skeletonDef[jointNum];
                // Binding position
                Point3D pos = animData.bindingPose[jointNum];

                if (frameNo >= 0)
                {
                    AnimMeshPose pose = animData.perFrameFKPoses[frameNo, jointNum];
                    pos = pose.Position;
                }
                parentPoints[parentIndex + 1] = pos;
                AddBone(mesh, parentPoints[parentIndex], pos);
            }

            model.Geometry = mesh;

            DiffuseMaterial dm = new DiffuseMaterial();
            dm.Brush = new SolidColorBrush(Colors.DarkGreen);
            model.Material = dm;

            return model;
        }
コード例 #2
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);
        }
コード例 #3
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);
        }
コード例 #4
0
ファイル: AnmDecoder.cs プロジェクト: Stranho/bgda-explorer
        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;
        }
コード例 #5
0
ファイル: AnmDecoder.cs プロジェクト: Stranho/bgda-explorer
        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;
        }
コード例 #6
0
ファイル: VifDecoder.cs プロジェクト: Stranho/bgda-explorer
        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;
        }
コード例 #7
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);
        }
コード例 #8
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);
        }