protected void GenerateFrame(int indexNumber, AnimationFrame[] resKeyFrames, ShapeElement[] elements, Dictionary <int, AnimationJoint> jointsById, float[] modelMatrix, List <ElementPose> transforms, bool recursive = true) { int frameNumber = resKeyFrames[indexNumber].FrameNumber; for (int i = 0; i < elements.Length; i++) { ShapeElement element = elements[i]; ElementPose animTransform = new ElementPose(); animTransform.ForElement = element; GenerateFrameForElement(frameNumber, element, ref animTransform); transforms.Add(animTransform); float[] animModelMatrix = Mat4f.CloneIt(modelMatrix); Mat4f.Mul(animModelMatrix, animModelMatrix, element.GetLocalTransformMatrix(null, animTransform)); if (element.JointId > 0 && !jointsDone.Contains(element.JointId)) { resKeyFrames[indexNumber].SetTransform(element.JointId, animModelMatrix); jointsDone.Add(element.JointId); } if (recursive && element.Children != null) { GenerateFrame(indexNumber, resKeyFrames, element.Children, jointsById, animModelMatrix, animTransform.ChildElementPoses); } } }
public void Add(ElementPose tf, ElementPose tfNext, float l, float weight) { if (tf.RotShortestDistance) { float distX = MathTools.GameMath.AngleDegDistance(tf.degX, tfNext.degX); float distY = MathTools.GameMath.AngleDegDistance(tf.degY, tfNext.degY); float distZ = MathTools.GameMath.AngleDegDistance(tf.degZ, tfNext.degZ); degX += (tf.degX + distX * l) * weight; degY += (tf.degY + distY * l) * weight; degZ += (tf.degZ + distZ * l) * weight; } else { degX += (tf.degX * (1 - l) + tfNext.degX * l) * weight; degY += (tf.degY * (1 - l) + tfNext.degY * l) * weight; degZ += (tf.degZ * (1 - l) + tfNext.degZ * l) * weight; } scaleX += ((tf.scaleX - 1) * (1 - l) + (tfNext.scaleX - 1) * l) * weight; scaleY += ((tf.scaleY - 1) * (1 - l) + (tfNext.scaleY - 1) * l) * weight; scaleZ += ((tf.scaleZ - 1) * (1 - l) + (tfNext.scaleZ - 1) * l) * weight; translateX += (tf.translateX * (1 - l) + tfNext.translateX * l) * weight; translateY += (tf.translateY * (1 - l) + tfNext.translateY * l) * weight; translateZ += (tf.translateZ * (1 - l) + tfNext.translateZ * l) * weight; }
protected override void LoadPosesAndAttachmentPoints(ShapeElement[] elements, List <ElementPose> intoPoses) { // Only load root pose and only the ones that have attachment points if (loadFully) { base.LoadPosesAndAttachmentPoints(elements, intoPoses); return; } ElementPose pose; for (int i = 0; i < elements.Length; i++) { ShapeElement elem = elements[i]; if (elem.AttachmentPoints == null) { continue; } intoPoses.Add(pose = new ElementPose()); pose.AnimModelMatrix = Mat4f.Create(); pose.ForElement = elem; for (int j = 0; j < elem.AttachmentPoints.Length; j++) { AttachmentPoint apoint = elem.AttachmentPoints[j]; AttachmentPointByCode[apoint.Code] = new AttachmentPointAndPose() { AttachPoint = apoint, CachedPose = pose }; } } }
protected virtual void LoadPosesAndAttachmentPoints(ShapeElement[] elements, List <ElementPose> intoPoses) { ElementPose pose; for (int i = 0; i < elements.Length; i++) { ShapeElement elem = elements[i]; intoPoses.Add(pose = new ElementPose()); pose.AnimModelMatrix = Mat4f.Create(); pose.ForElement = elem; if (elem.AttachmentPoints != null) { for (int j = 0; j < elem.AttachmentPoints.Length; j++) { AttachmentPoint apoint = elem.AttachmentPoints[j]; AttachmentPointByCode[apoint.Code] = new AttachmentPointAndPose() { AttachPoint = apoint, CachedPose = pose }; } } if (elem.Children != null) { pose.ChildElementPoses = new List <ElementPose>(elem.Children.Length); LoadPosesAndAttachmentPoints(elem.Children, pose.ChildElementPoses); } } }
protected virtual void LoadAttachmentPoints(List <ElementPose> cachedPoses) { for (int i = 0; i < cachedPoses.Count; i++) { ElementPose elem = cachedPoses[i]; if (elem.ForElement.AttachmentPoints != null) { for (int j = 0; j < elem.ForElement.AttachmentPoints.Length; j++) { AttachmentPoint apoint = elem.ForElement.AttachmentPoints[j]; AttachmentPointByCode[apoint.Code] = new AttachmentPointAndPose() { AttachPoint = apoint, CachedPose = elem }; } } if (elem.ChildElementPoses != null) { LoadAttachmentPoints(elem.ChildElementPoses); } } }
public void Add(ElementPose tf, ElementPose tfNext, float l, float weight) { degX += (tf.degX * (1 - l) + tfNext.degX * l) * weight; degY += (tf.degY * (1 - l) + tfNext.degY * l) * weight; degZ += (tf.degZ * (1 - l) + tfNext.degZ * l) * weight; scaleX += ((tf.scaleX - 1) * (1 - l) + (tfNext.scaleX - 1) * l) * weight; scaleY += ((tf.scaleY - 1) * (1 - l) + (tfNext.scaleY - 1) * l) * weight; scaleZ += ((tf.scaleZ - 1) * (1 - l) + (tfNext.scaleZ - 1) * l) * weight; translateX += (tf.translateX * (1 - l) + tfNext.translateX * l) * weight; translateY += (tf.translateY * (1 - l) + tfNext.translateY * l) * weight; translateZ += (tf.translateZ * (1 - l) + tfNext.translateZ * l) * weight; }
public float[] GetLocalTransformMatrix(float[] output = null, ElementPose tf = null) { if (tf == null) { tf = noTransform; } ShapeElement elem = this; if (output == null) { output = Mat4f.Create(); } float[] origin = new float[] { 0f, 0f, 0f }; if (elem.RotationOrigin != null) { origin[0] = (float)elem.RotationOrigin[0] / 16; origin[1] = (float)elem.RotationOrigin[1] / 16; origin[2] = (float)elem.RotationOrigin[2] / 16; } Mat4f.Translate(output, output, origin); if (elem.RotationX + tf.degX != 0) { Mat4f.RotateX(output, output, (float)(elem.RotationX + tf.degX) * GameMath.DEG2RAD); } if (elem.RotationY + tf.degY != 0) { Mat4f.RotateY(output, output, (float)(elem.RotationY + tf.degY) * GameMath.DEG2RAD); } if (elem.RotationZ + tf.degZ != 0) { Mat4f.RotateZ(output, output, (float)(elem.RotationZ + tf.degZ) * GameMath.DEG2RAD); } Mat4f.Scale(output, output, new float[] { (float)elem.ScaleX * tf.scaleX, (float)elem.ScaleY * tf.scaleY, (float)elem.ScaleZ * tf.scaleZ }); Mat4f.Translate(output, output, new float[] { -origin[0], -origin[1], -origin[2] }); Mat4f.Translate(output, output, new float[] { (float)elem.From[0] / 16 + tf.translateX, (float)elem.From[1] / 16 + tf.translateY, (float)elem.From[2] / 16 + tf.translateZ }); return(output); }
protected void lerpKeyFrameElement(AnimationKeyFrameElement prev, AnimationKeyFrameElement next, int forFlag, float t, ref ElementPose transform) { if (prev == null && next == null) { return; } t = GameMath.SmoothStep(t); // Applies the transforms in model space if (forFlag == 0) { transform.translateX = GameMath.Lerp((float)prev.OffsetX / 16f, (float)next.OffsetX / 16f, t); transform.translateY = GameMath.Lerp((float)prev.OffsetY / 16f, (float)next.OffsetY / 16f, t); transform.translateZ = GameMath.Lerp((float)prev.OffsetZ / 16f, (float)next.OffsetZ / 16f, t); } else if (forFlag == 1) { transform.degX = GameMath.Lerp((float)prev.RotationX, (float)next.RotationX, t); transform.degY = GameMath.Lerp((float)prev.RotationY, (float)next.RotationY, t); transform.degZ = GameMath.Lerp((float)prev.RotationZ, (float)next.RotationZ, t); } else { transform.scaleX = GameMath.Lerp((float)prev.StretchX, (float)next.StretchX, t); transform.scaleY = GameMath.Lerp((float)prev.StretchY, (float)next.StretchY, t); transform.scaleZ = GameMath.Lerp((float)prev.StretchZ, (float)next.StretchZ, t); } }
protected void GenerateFrameForElement(int frameNumber, ShapeElement element, ref ElementPose transform) { for (int flag = 0; flag < 3; flag++) { AnimationKeyFrameElement curKelem, nextKelem; getTwoKeyFramesElementForFlag(frameNumber, element, flag, out curKelem, out nextKelem); if (curKelem == null) { continue; } float t; if (nextKelem == null || curKelem == nextKelem) { nextKelem = curKelem; t = 0; } else { if (nextKelem.Frame < curKelem.Frame) { int quantity = nextKelem.Frame + (QuantityFrames - curKelem.Frame); int framePos = GameMath.Mod(frameNumber - curKelem.Frame, QuantityFrames); t = (float)framePos / quantity; } else { t = (float)(frameNumber - curKelem.Frame) / (nextKelem.Frame - curKelem.Frame); } } lerpKeyFrameElement(curKelem, nextKelem, flag, t, ref transform); } }
// Careful when changing around stuff in here, this is a recursively called method private void calculateMatrices( float dt, List <ElementPose> currentPoses, ShapeElementWeights[][] weightsByAnimationAndElement, float[] modelMatrix, List <ElementPose>[] transformsByAnimation, List <ElementPose>[] nextFrameTransformsByAnimation, int depth ) { depth++; List <ElementPose>[] childTransformsByAnimation = this.transformsByAnimation[depth]; List <ElementPose>[] nextFrameChildTransformsByAnimation = this.nextFrameTransformsByAnimation[depth]; ShapeElementWeights[][] childWeightsByAnimationAndElement = this.weightsByAnimationAndElement[depth]; for (int i = 0; i < currentPoses.Count; i++) { ElementPose currentPose = currentPoses[i]; ShapeElement elem = currentPose.ForElement; currentPose.SetMat(modelMatrix); Mat4f.Identity(localTransformMatrix); currentPose.Clear(); float weightSum = 0f; for (int j = 0; j < curAnimCount; j++) { RunningAnimation anim = CurAnims[j]; ShapeElementWeights sew = weightsByAnimationAndElement[j][i]; if (sew.BlendMode != EnumAnimationBlendMode.Add) { weightSum += sew.Weight * anim.EasingFactor; } } for (int j = 0; j < curAnimCount; j++) { RunningAnimation anim = CurAnims[j]; ShapeElementWeights sew = weightsByAnimationAndElement[j][i]; //anim.CalcBlendedWeight(sew.Weight weightSum, sew.BlendMode); - that makes no sense for element weights != 1 anim.CalcBlendedWeight(weightSum / sew.Weight, sew.BlendMode); ElementPose prevFramePose = transformsByAnimation[j][i]; ElementPose nextFramePose = nextFrameTransformsByAnimation[j][i]; int prevFrame = this.prevFrame[j]; int nextFrame = this.nextFrame[j]; // May loop around, so nextFrame can be smaller than prevFrame float keyFrameDist = nextFrame > prevFrame ? (nextFrame - prevFrame) : (anim.Animation.QuantityFrames - prevFrame + nextFrame); float curFrameDist = anim.CurrentFrame >= prevFrame ? (anim.CurrentFrame - prevFrame) : (anim.Animation.QuantityFrames - prevFrame + anim.CurrentFrame); float lerp = curFrameDist / keyFrameDist; currentPose.Add(prevFramePose, nextFramePose, lerp, anim.BlendedWeight); childTransformsByAnimation[j] = prevFramePose.ChildElementPoses; childWeightsByAnimationAndElement[j] = sew.ChildElements; nextFrameChildTransformsByAnimation[j] = nextFramePose.ChildElementPoses; } elem.GetLocalTransformMatrix(localTransformMatrix, currentPose); Mat4f.Mul(currentPose.AnimModelMatrix, currentPose.AnimModelMatrix, localTransformMatrix); if (elem.JointId > 0 && !jointsDone.Contains(elem.JointId)) { Mat4f.Mul(tmpMatrix, currentPose.AnimModelMatrix, elem.inverseModelTransform); for (int l = 0; l < 16; l++) { TransformationMatrices[16 * elem.JointId + l] = tmpMatrix[l]; } jointsDone.Add(elem.JointId); } if (currentPose.ChildElementPoses != null) { calculateMatrices( dt, currentPose.ChildElementPoses, childWeightsByAnimationAndElement, currentPose.AnimModelMatrix, childTransformsByAnimation, nextFrameChildTransformsByAnimation, depth ); } } }