示例#1
0
        static void TestMath()
        {
            var rand = new Random();

            for (int i = 0; i < 1000; i++)
            {
                var u  = new Vector(rand.NextDouble() - 0.5, rand.NextDouble() - 0.5, rand.NextDouble() - 0.5).Normalized();
                var t1 = new Vector(rand.NextDouble() - 0.5, rand.NextDouble() - 0.5, rand.NextDouble() - 0.5) * 10;
                var t2 = new Vector(rand.NextDouble() - 0.5, rand.NextDouble() - 0.5, rand.NextDouble() - 0.5) * 10;
                var p1 = new Vector(rand.NextDouble() - 0.5, rand.NextDouble() - 0.5, rand.NextDouble() - 0.5) * 10;

                var q  = new Quaternion(rand.NextDouble() * Math.PI, u);
                var m  = q.ToMatrix();
                var mt = TMatrix.Translation(t1) * m * TMatrix.Translation(t2);
                var q2 = mt.GetRotation();
                var m2 = q2.ToMatrix();

                if (((m * p1) - (m2 * p1)) * (m * p1 - m2 * p1) > .0001)
                {
                    Console.WriteLine("math error.");
                }
            }

            var badq = new Quaternion(3.1414934204542249,
                                      new Vector(-0.920567453, -0.390583634, -0));

            badq = badq.ToMatrix().GetRotation();
            Console.WriteLine(badq.Angle);
            Console.WriteLine(badq.Axis);
        }
示例#2
0
        public TMatrix Translated(Vector v)
        {
            var x = new TMatrix((double[])this.m.Clone());

            x.m[12] += v.x;
            x.m[13] += v.y;
            x.m[14] += v.z;
            return(x);
        }
示例#3
0
        public static TMatrix operator *(TMatrix left, TMatrix right)
        {
            TMatrix res = new TMatrix();

            res.m[15] = 0;
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    for (int r = 0; r < 4; r++)
                    {
                        res.m[i * 4 + j] += left.m[r * 4 + j] * right.m[i * 4 + r];
                    }
                }
            }
            return(res);
        }
示例#4
0
        public TMatrix Inverse()
        {
            // Since this matrix has the form (T * R), the inverse is
            //   R^-1 * T^-1 = (R^T) * -T = T' * (R^T), where
            //   T' = [ I R^T * (-t) ]
            TMatrix res = new TMatrix();

            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    res.m[i * 4 + j] = m[i + j * 4];
                }
            }
            Vector t = res * new Vector(this.m[12], this.m[13], this.m[14]);

            for (int i = 0; i < 3; i++)
            {
                res.m[12 + i] = -t[i];
            }
            return(res);
        }
示例#5
0
        static void ReadAnim(RW4Model model, string outname, string ogreSkeletonFile)
        {
            var anims     = (from anim in model.GetObjects(Anim.type_code) select(Anim) anim).ToArray();
            var skeletons = (from s in model.GetObjects(RW4Skeleton.type_code) select(RW4Skeleton) s).ToArray();

            if (anims.Length == 0 && skeletons.Length == 0)
            {
                return;
            }

            var only = new int[] { 1 };

            var x_skels =
                new XElement("skeletons",
                             from skel in skeletons
                             select new XElement("skeleton",
                                                 new XAttribute("name", SporeMaster.NameRegistry.Files.toName(skel.jointInfo.id)),
                                                 new XAttribute("unk1", "0x" + skel.unk1.ToString("X")),
                                                 new XElement("joints",
                                                              from joint in skel.jointInfo.items
                                                              let mat4 = skel.mat4.items[joint.index]
                                                                         let inv_bind                       = TMatrix.FromMat4(mat4)
                                                                                                   let bind = inv_bind.Inverse()
                                                                                                              let rotation = bind.Inverse().GetRotation() //< TODO: Why inverse?
                                                                                                                             select new XElement("joint",
                                                                                                                                                 new XAttribute("name", SporeMaster.NameRegistry.Files.toName(joint.name_fnv)),
                                                                                                                                                 new XAttribute("flags", "0x" + joint.flags.ToString("X")),
                                                                                                                                                 from _ in only where joint.parent != null
                                                                                                                                                 select new XAttribute("parent", SporeMaster.NameRegistry.Files.toName(joint.parent.name_fnv)),
                                                                                                                                                 new XElement("Transform",
                                                                                                                                                              new XElement("position", bind.GetColumn(3).toXML()),
                                                                                                                                                              new XElement("rotation", new XAttribute("angle", rotation.Angle), rotation.Axis.toXML())
                                                                                                                                                              ),
                                                                                                                                                 new XElement("RawInverseBindMatrix",
                                                                                                                                                              new XElement("rx", writeVector(mat4.m[0], mat4.m[1], mat4.m[2])),
                                                                                                                                                              new XElement("ry", writeVector(mat4.m[4], mat4.m[5], mat4.m[6])),
                                                                                                                                                              new XElement("rz", writeVector(mat4.m[8], mat4.m[9], mat4.m[10])),
                                                                                                                                                              new XElement("t", writeVector(mat4.m[12], mat4.m[13], mat4.m[15]))
                                                                                                                                                              )
                                                                                                                                                 )
                                                              )
                                                 )
                             );

            var x_anims =
                new XElement("anims",
                             from anim in anims
                             select new XElement("anim",
                                                 new XAttribute("name", SporeMaster.NameRegistry.Files.toName(anim.hash_name)),
                                                 new XAttribute("flags", "0x" + anim.flags.ToString("X")),
                                                 new XAttribute("length", anim.length),
                                                 new XAttribute("skeleton", SporeMaster.NameRegistry.Files.toName(anim.skeleton_id)),
                                                 //new XAttribute("padding", anim.padding),
                                                 new XAttribute("components", "0x" + anim.pose_components.ToString("X")),
                                                 new XElement("channels",
                                                              from i in Enumerable.Range(0, anim.channel_names.Length)
                                                              let name = anim.channel_names[i]
                                                                         select new XElement("channel",
                                                                                             new XAttribute("name", SporeMaster.NameRegistry.Files.toName(name)),
                                                                                             new XAttribute("padding", anim.padding[i]),
                                                                                             new XElement("frames",
                                                                                                          from pose in anim.channel_frame_pose[i]
                                                                                                          select new XElement("frame",
                                                                                                                              new XAttribute("time", pose.time),
                                                                                                                              new XElement("Translation",
                                                                                                                                           new XAttribute("x", pose.tx),
                                                                                                                                           new XAttribute("y", pose.ty),
                                                                                                                                           new XAttribute("z", pose.tz)),
                                                                                                                              new XElement("Rotation",
                                                                                                                                           new XAttribute("x", pose.qx),
                                                                                                                                           new XAttribute("y", pose.qy),
                                                                                                                                           new XAttribute("z", pose.qz),
                                                                                                                                           new XAttribute("s", pose.qs)),
                                                                                                                              new XElement("Scale",
                                                                                                                                           new XAttribute("x", pose.sx),
                                                                                                                                           new XAttribute("y", pose.sy),
                                                                                                                                           new XAttribute("z", pose.sz))
                                                                                                                              )
                                                                                                          )
                                                                                             )
                                                              )
                                                 )
                             );
            var output = new XElement("raw_animation_info",
                                      x_anims,
                                      x_skels);

            output.Save(outname);

            WriteOgreSkeleton(model).Save(ogreSkeletonFile);

            foreach (var s in skeletons)
            {
                foreach (var mat4 in s.mat4.items)
                {
                    if (mat4.m[3] != 0 || mat4.m[7] != 0 || mat4.m[15] != 0)
                    {
                        throw new Exception("Extra matrix cells nonzero.");
                    }
                }
            }
        }
示例#6
0
        static XElement WriteOgreSkeleton(RW4Model model)
        {
            var anims  = (from anim in model.GetObjects(Anim.type_code) select(Anim) anim).ToArray();
            var rskels = model.GetObjects(RW4Skeleton.type_code);

            if (rskels.Count != 1)
            {
                throw new NotSupportedException("Exactly one skeleton required.");
            }
            var skel = (RW4Skeleton)rskels[0];

            Dictionary <uint, int> bone_name_lookup = new Dictionary <uint, int>();

            foreach (var j in skel.jointInfo.items)
            {
                bone_name_lookup[j.name_fnv] = j.index;
            }

            var inv_binds = (from m in skel.mat4.items select TMatrix.FromMat4(m)).ToArray();

            var rel_bind = (
                from joint in skel.jointInfo.items
                let inv_bind = TMatrix.FromMat4(skel.mat4.items[joint.index])
                               let bind = inv_bind.Inverse()
                                          let parent_inv_bind = joint.parent == null ? null : TMatrix.FromMat4(skel.mat4.items[joint.parent.index])
                                                                select parent_inv_bind == null ? bind : parent_inv_bind * bind
                ).ToArray();

            return(new XElement("skeleton",
                                new XElement("bones",
                                             from joint in skel.jointInfo.items
                                             let rel = rel_bind[joint.index]
                                                       let rotation = -rel.GetRotation() // < TODO: Why inverse?
                                                                      select new XElement("bone",
                                                                                          new XAttribute("id", joint.index),
                                                                                          new XAttribute("name", SporeMaster.NameRegistry.Files.toName(joint.name_fnv)),
                                                                                          new XElement("position", rel.GetColumn(3).toXML()),
                                                                                          new XElement("rotation",
                                                                                                       new XAttribute("angle", rotation.Angle),
                                                                                                       new XElement("axis", rotation.Axis.toXML()))
                                                                                          )
                                             ),
                                new XElement("bonehierarchy",
                                             from joint in skel.jointInfo.items
                                             where joint.parent != null
                                             select new XElement("boneparent",
                                                                 new XAttribute("bone", SporeMaster.NameRegistry.Files.toName(joint.name_fnv)),
                                                                 new XAttribute("parent", SporeMaster.NameRegistry.Files.toName(joint.parent.name_fnv)))),
                                new XElement("animations",
                                             from anim in anims
                                             select new XElement("animation",
                                                                 new XAttribute("name", SporeMaster.NameRegistry.Files.toName(anim.hash_name)),
                                                                 new XAttribute("length", anim.length),
                                                                 new XElement("tracks",
                                                                              from i in Enumerable.Range(0, anim.channel_names.Length)
                                                                              let name = anim.channel_names[i]
                                                                                         let poses = anim.channel_frame_pose[i]
                                                                                                     let rel = rel_bind[bone_name_lookup[name]]
                                                                                                               let bind_rot = rel.Inverse()
                                                                                                                              let bind_pos = rel.GetColumn(3)
                                                                                                                                             select new XElement("track",
                                                                                                                                                                 new XAttribute("bone", SporeMaster.NameRegistry.Files.toName(name)),
                                                                                                                                                                 new XElement("keyframes",
                                                                                                                                                                              from f in poses
                                                                                                                                                                              let scale = new Vector(f.sx, f.sy, f.sz)
                                                                                                                                                                                          let pose = TMatrix.Translation(new Vector(f.tx, f.ty, f.tz)) *
                                                                                                                                                                                                     (-new Quaternion {
                x = f.qx, y = f.qy, z = f.qz, w = f.qs
            }).ToMatrix()
                                                                                                                                                                                                     let pose_world = bind_rot * pose
                                                                                                                                                                                                                      let rot = -pose_world.GetRotation()
                                                                                                                                                                                                                                let pos = pose.GetColumn(3) - bind_pos
                                                                                                                                                                                                                                          select new XElement("keyframe",
                                                                                                                                                                                                                                                              new XAttribute("time", f.time),
                                                                                                                                                                                                                                                              new XElement("translate", pos.toXML()),
                                                                                                                                                                                                                                                              new XElement("rotate",
                                                                                                                                                                                                                                                                           new XAttribute("angle", rot.Angle),
                                                                                                                                                                                                                                                                           new XElement("axis", rot.Axis.toXML())),
                                                                                                                                                                                                                                                              new XElement("scale", scale.toXML())))))))));
        }
示例#7
0
 public TMatrix Translated(Vector v)
 {
     var x = new TMatrix( (double[])this.m.Clone() );
     x.m[12] += v.x;
     x.m[13] += v.y;
     x.m[14] += v.z;
     return x;
 }
示例#8
0
 public TMatrix Inverse()
 {
     // Since this matrix has the form (T * R), the inverse is
     //   R^-1 * T^-1 = (R^T) * -T = T' * (R^T), where
     //   T' = [ I R^T * (-t) ]
     TMatrix res = new TMatrix();
     for (int i = 0; i < 3; i++)
         for (int j = 0; j < 3; j++)
             res.m[i * 4 + j] = m[i + j * 4];
     Vector t = res * new Vector(this.m[12], this.m[13], this.m[14]);
     for (int i = 0; i < 3; i++)
         res.m[12 + i] = -t[i];
     return res;
 }
示例#9
0
 public static TMatrix operator *(TMatrix left, TMatrix right)
 {
     TMatrix res = new TMatrix();
     res.m[15] = 0;
     for (int i = 0; i < 4; i++)
         for (int j = 0; j < 4; j++)
             for (int r = 0; r < 4; r++)
                 res.m[i * 4 + j] += left.m[r * 4 + j] * right.m[i * 4 + r];
     return res;
 }