private void ApplyQuaternion_(Quaternion q)
        {
            var qx = q.X;
            var qy = q.Y;
            var qz = q.Z;
            var qw = q.W;

            var m = this.tempMatrix_;

            m[0, 0] = 1.0 - 2.0 * qy * qy - 2.0 * qz * qz;
            m[0, 1] = 2.0 * qx * qy - 2.0 * qz * qw;
            m[0, 2] = 2.0 * qx * qz + 2.0 * qy * qw;
            m[0, 3] = 0.0;

            m[1, 0] = 2.0 * qx * qy + 2.0 * qz * qw;
            m[1, 1] = 1.0 - 2.0 * qx * qx - 2.0 * qz * qz;
            m[1, 2] = 2.0 * qy * qz - 2.0 * qx * qw;
            m[1, 3] = 0.0;

            m[2, 0] = 2.0 * qx * qz - 2.0 * qy * qw;
            m[2, 1] = 2.0 * qy * qz + 2.0 * qx * qw;
            m[2, 2] = 1.0 - 2.0 * qx * qx - 2.0 * qy * qy;
            m[2, 3] = 0.0;

            m[3, 0] = 0;
            m[3, 1] = 0;
            m[3, 2] = 0;
            m[3, 3] = 1;

            ModelViewMatrixTransformer.MultMatrix(m);
        }
        private void UpdateLimbMatricesRecursively_(
            IList <IOldLimb> limbs,
            int limbIndex,
            IAnimation?animation,
            float frame)
        {
            var limb = limbs[limbIndex];

            ModelViewMatrixTransformer.Push();
            {
                ModelViewMatrixTransformer.Translate(limb.x, limb.y, limb.z);

                if (animation != null)
                {
                    this.PushRotation_(limbIndex, animation, frame);
                }

                ModelViewMatrixTransformer.Get(this.tempMatrix_);
                this.tempMatrix_.CopyTo(this.impl_[limbIndex]);

                var firstChild = limb.firstChild;
                if (firstChild > -1)
                {
                    this.UpdateLimbMatricesRecursively_(limbs,
                                                        firstChild,
                                                        animation,
                                                        frame);
                }
            }
            ModelViewMatrixTransformer.Pop();

            var nextSibling = limb.nextSibling;

            if (nextSibling > -1)
            {
                this.UpdateLimbMatricesRecursively_(limbs,
                                                    nextSibling,
                                                    animation,
                                                    frame);
            }
        }
        public static void Render(
            IList <IOldLimb> limbs,
            LimbMatrices limbMatrices,
            IAnimation?animation,
            IAnimationPlaybackManager animationPlaybackManager)
        {
            if (limbs.Count == 0)
            {
                return;
            }

            ModelViewMatrixTransformer.Push();

            if (animation != null)
            {
                var frame       = animationPlaybackManager.Frame;
                var totalFrames = animationPlaybackManager.TotalFrames;

                var frameIndex = (int)Math.Floor(frame);
                var frameDelta = frame % 1;

                var startPos = animation.GetPosition(frameIndex);
                var endPos   = animation.GetPosition((frameIndex + 1) % totalFrames);

                var f = frameDelta;

                var x = startPos.X * (1 - f) + endPos.X * f;
                var y = startPos.Y * (1 - f) + endPos.Y * f;
                var z = startPos.Z * (1 - f) + endPos.Z * f;

                ModelViewMatrixTransformer.Translate(x, y, z);

                /*If indirectTextureHack IsNot Nothing Then
                 *  Dim face As FacialState = CurrAnimation.GetFacialState(frameIndex)
                 * indirectTextureHack.EyeState = face.EyeState
                 * indirectTextureHack.MouthState = face.MouthState
                 * End If*/

                limbMatrices.UpdateLimbMatrices(limbs,
                                                animation,
                                                (float)animationPlaybackManager.Frame);
            }

            SkeletonRenderer.ForEachLimbRecursively_(
                limbs,
                0,
                (limb, limbIndex) => {
                var xI = 0.0;
                var yI = 0.0;
                var zI = 0.0;
                ModelViewMatrixTransformer.ProjectVertex(ref xI, ref yI, ref zI);

                double xF = limb.x;
                double yF = limb.y;
                double zF = limb.z;
                ModelViewMatrixTransformer.ProjectVertex(ref xF, ref yF, ref zF);

                Gl.glDepthRange(0, 0);
                Gl.glLineWidth(9);
                Gl.glBegin(Gl.GL_LINES);
                Gl.glColor3f(1, 1, 1);
                Gl.glVertex3d(xI, yI, zI);
                Gl.glVertex3d(xF, yF, zF);
                Gl.glEnd();
                Gl.glDepthRange(0, -0.5);
                Gl.glPointSize(11);
                Gl.glBegin(Gl.GL_POINTS);
                Gl.glColor3f(0, 0, 0);
                Gl.glVertex3d(xF, yF, zF);
                Gl.glEnd();

                /*Gl.glPointSize(8);
                 * Gl.glBegin(Gl.GL_POINTS);
                 * Gl.glColor3ub(BoneColorFactor.r,
                 *            BoneColorFactor.g,
                 *            BoneColorFactor.b);
                 * Gl.glVertex3f(xF, yF, zF);
                 * Gl.glEnd();*/
                Gl.glPointSize(1);
                Gl.glLineWidth(1);
                Gl.glDepthRange(0, 1);

                ModelViewMatrixTransformer.Push();

                var matrix = limbMatrices.GetMatrixForLimb((uint)limbIndex);
                ModelViewMatrixTransformer.Set(matrix);
            },
                (limb, _) => {
                ModelViewMatrixTransformer.Pop();
            });
            ModelViewMatrixTransformer.Pop();
        }