public WhBone(WhModel model, int index, BinaryReader r)
        {
            Model       = model;
            Index       = index;
            KeyId       = r.ReadInt32();
            Flags       = r.ReadUInt32();
            Parent      = r.ReadInt16();
            Mesh        = r.ReadUInt16();
            Id          = r.ReadUInt32();
            Pivot       = new Vec3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
            Translation = WhAnimatedVec3.ReadSet(r);
            Rotation    = WhAnimatedQuat.ReadSet(r);
            Scale       = WhAnimatedVec3.ReadSet(r);
            Hidden      = false;
            Updated     = false;

            // Не стал делать
            //self.transformedPivot = vec3.create();
            //self.matrix = mat4.create();
            //self.tmpVec = vec3.create();
            //self.tmpQuat = quat.create();
            //self.tmpMat = mat4.create();

            // Я сделал. -1 значит что эта переменная будет игнорироваться при Update модели
            IndexInParentModel = -1;
        }
        public static WhAnimatedVec3[] ReadSet(BinaryReader r)
        {
            var count = r.ReadInt32();
            var data  = new WhAnimatedVec3[count];

            for (var i = 0; i < count; i++)
            {
                data[i] = new WhAnimatedVec3(r);
            }

            return(data);
        }
        public void Update(int time)
        {
            if (Hidden)
            {
                Hide();
                return;
            }

            if (Updated || SkipUpdate)
            {
                return;
            }

            Updated = true;

            if (Model == null || Model.Animations == null || Model.AnimPaused)
            {
                return;
            }

            //mat4.identity(self.matrix);

            var anim = Model.CurrentAnimation;

            if (anim == null)
            {
                return;
            }

            var billboard = (Flags & 8) != 0;
            var transUsed = WhAnimatedVec3.IsUsed(Translation, anim.Index);
            var rotUsed   = WhAnimatedQuat.IsUsed(Rotation, anim.Index);
            var scaleUsed = WhAnimatedVec3.IsUsed(Scale, anim.Index);

            if (transUsed || rotUsed || scaleUsed || billboard)
            {
                //mat4.translate(self.matrix, self.matrix, self.pivot);

                if (transUsed)
                {
                    // Запоминаю текущий translation вместо модификации матрицы (как в оригинале)

                    LastUpdatedTranslation = WhAnimatedVec3.GetValue(Translation, anim.Index, time);

                    //Wow.AnimatedVec3.getValue(self.translation, anim.index, time, self.tmpVec);
                    //mat4.translate(self.matrix, self.matrix, self.tmpVec)
                }

                if (rotUsed)
                {
                    // Запоминаю текущий rotation вместо модификации матрицы (как в оригинале)

                    // mat4.fromQuat + mat4.transpose (создать матрицу из квартерниона и инвертировать ее) это то же самое что инверт квартерниона, а затем создание матрицы из полученного квартерниона
                    // но так как я матрицы не использую, я просто инвертирую квартернион и сохраняю его
                    LastUpdatedRotation = Quat.Invert(WhAnimatedQuat.GetValue(Rotation, anim.Index, time));

                    //Wow.AnimatedQuat.getValue(self.rotation, anim.index, time, self.tmpQuat);
                    //mat4.fromQuat(self.tmpMat, self.tmpQuat);
                    //mat4.transpose(self.tmpMat, self.tmpMat);
                    //mat4.multiply(self.matrix, self.matrix, self.tmpMat)
                }

                if (scaleUsed)
                {
                    // Запоминаю текущий scale вместо модификации матрицы (как в оригинале)

                    LastUpdatedScale = WhAnimatedVec3.GetValue(Scale, anim.Index, time);

                    //Wow.AnimatedVec3.getValue(self.scale, anim.index, time, self.tmpVec);
                    //mat4.scale(self.matrix, self.matrix, self.tmpVec)
                }

                if (billboard)
                {
                    //var yRot = -self.model.renderer.zenith + Math.PI / 2;
                    //var zRot;
                    //if (self.model.model.type == Wow.Types.ITEM)
                    //{
                    //    zRot = self.model.renderer.azimuth - Math.PI
                    //    }
                    //else
                    //{
                    //    zRot = self.model.renderer.azimuth - Math.PI * 1.5
                    //  }
                    //mat4.identity(self.matrix);
                    //mat4.translate(self.matrix, self.matrix, self.pivot);
                    //mat4.rotateZ(self.matrix, self.matrix, zRot);
                    //mat4.rotateY(self.matrix, self.matrix, yRot)
                }

                //mat4.translate(self.matrix, self.matrix, vec3.negate(self.tmpVec, self.pivot))
            }

            if (Parent > -1)
            {
                Model.Bones[Parent].Update(time);

                // По сути это значит что translation/rotation/scale которые в этой кости вычеслены будут являться локальными и чтобы получить глобальные,
                // нужно учесть еще из parent кости тоже
                //mat4.multiply(self.matrix, self.model.bones[self.parent].matrix, self.matrix)
            }

            //vec3.transformMat4(self.transformedPivot, self.pivot, self.matrix)
        }