public override OverrideTransformJob Create(Animator animator, ref T data, Component component)
        {
            var job          = new OverrideTransformJob();
            var cacheBuilder = new AnimationJobCacheBuilder();

            job.driven = ReadWriteTransformHandle.Bind(animator, data.constrainedObject);

            if (data.sourceObject != null)
            {
                // Cache source to possible space rotation offsets (world, local and pivot)
                // at bind time so we can switch dynamically between them at runtime.

                job.source = ReadOnlyTransformHandle.Bind(animator, data.sourceObject);
                var sourceLocalTx = new AffineTransform(data.sourceObject.localPosition, data.sourceObject.localRotation);
                job.sourceInvLocalBindTx = sourceLocalTx.Inverse();

                var sourceWorldTx = new AffineTransform(data.sourceObject.position, data.sourceObject.rotation);
                var drivenWorldTx = new AffineTransform(data.constrainedObject.position, data.constrainedObject.rotation);
                job.sourceToWorldRot = sourceWorldTx.Inverse().rotation;
                job.sourceToPivotRot = sourceWorldTx.InverseMul(drivenWorldTx).rotation;

                var drivenParent = data.constrainedObject.parent;
                if (drivenParent != null)
                {
                    var drivenParentWorldTx = new AffineTransform(drivenParent.position, drivenParent.rotation);
                    job.sourceToLocalRot = sourceWorldTx.InverseMul(drivenParentWorldTx).rotation;
                }
                else
                {
                    job.sourceToLocalRot = job.sourceToPivotRot;
                }
            }

            job.spaceIdx = cacheBuilder.Add(data.space);
            if (data.space == (int)OverrideTransformJob.Space.Pivot)
            {
                job.sourceToCurrSpaceRotIdx = cacheBuilder.Add(job.sourceToPivotRot);
            }
            else if (data.space == (int)OverrideTransformJob.Space.Local)
            {
                job.sourceToCurrSpaceRotIdx = cacheBuilder.Add(job.sourceToLocalRot);
            }
            else
            {
                job.sourceToCurrSpaceRotIdx = cacheBuilder.Add(job.sourceToWorldRot);
            }

            job.position       = Vector3Property.Bind(animator, component, data.positionVector3Property);
            job.rotation       = Vector3Property.Bind(animator, component, data.rotationVector3Property);
            job.positionWeight = FloatProperty.Bind(animator, component, data.positionWeightFloatProperty);
            job.rotationWeight = FloatProperty.Bind(animator, component, data.rotationWeightFloatProperty);

            job.cache = cacheBuilder.Build();

            return(job);
        }
        public void InverseAffineTransformationTest ()
        {
            //Local coordinate system MNAU (Kraftwerk Mäuserich) (based on Gau?Krüger using affine transformation)
            // affine transform
            // 1) Offset: X=-3454886,640m Y=-5479481,278m;
            // 2)Rotation: 332,0657, Rotation point  X=3456926,640m Y=5481071,278m;
            // 3) Scale: 1.0

            //TODO MathTransformFactory fac = new MathTransformFactory ();
            double[,] matrix = new double[,] {{0.883485346527455, -0.468458794848877, 3455869.17937689}, 
                                              {0.468458794848877, 0.883485346527455, 5478710.88035753},
                                              {0.0 , 0.0, 1},};
            IMathTransform mt = new AffineTransform (matrix);

            Assert.IsNotNull (mt);

            Assert.AreEqual (2, mt.DimSource);
            Assert.AreEqual (2, mt.DimTarget);

            //Transformation example (MNAU -> GK)
            // Start point (MNAU) X=2040,000m Y=1590,000m]
            // Target point (GK): X=3456926,640m Y=5481071,278m;

            //check source transform
            double[] outPt = mt.Transform (new double[] { 2040.0, 1590.0 });

            Assert.AreEqual (2, outPt.Length);
            Assert.AreEqual (3456926.640, outPt[0], 0.00000001);
            Assert.AreEqual (5481071.278, outPt[1], 0.00000001);

            IMathTransform invMt = mt.Inverse ();

            double[] inPt = invMt.Transform (new double[] { 3456926.640, 5481071.278 });

            Assert.AreEqual (2, inPt.Length);
            Assert.AreEqual (2040.0, inPt[0], 0.00000001);
            Assert.AreEqual (1590.0, inPt[1], 0.00000001);

            //check source transform - once more
            double[] outPt2 = mt.Transform (new double[] { 2040.0, 1590.0 });

            Assert.AreEqual (2, outPt2.Length);
            Assert.AreEqual (3456926.640, outPt2[0], 0.00000001);
            Assert.AreEqual (5481071.278, outPt2[1], 0.00000001);
        }