private void LoadWeights(ShapeElement[] elements, ShapeElementWeights[] intoList, Dictionary <string, float> elementWeight, Dictionary <string, EnumAnimationBlendMode> elementBlendMode) { for (int i = 0; i < elements.Length; i++) { ShapeElement elem = elements[i]; intoList[i] = new ShapeElementWeights(); float w; if (elementWeight.TryGetValue(elem.Name, out w)) { intoList[i].Weight = w; } else { intoList[i].Weight = meta.Weight; } EnumAnimationBlendMode blendMode; if (elementBlendMode.TryGetValue(elem.Name, out blendMode)) { intoList[i].BlendMode = blendMode; } else { intoList[i].BlendMode = meta.BlendMode; } if (elem.Children != null) { intoList[i].ChildElements = new ShapeElementWeights[elem.Children.Length]; LoadWeights(elem.Children, intoList[i].ChildElements, elementWeight, elementBlendMode); } } }
protected virtual void initFields() { maxDepth = 2 + (RootPoses == null ? 0 : getMaxDepth(RootPoses, 1)); transformsByAnimation = new List <ElementPose> [maxDepth][]; nextFrameTransformsByAnimation = new List <ElementPose> [maxDepth][]; weightsByAnimationAndElement = new ShapeElementWeights[maxDepth][][]; for (int i = 0; i < maxDepth; i++) { transformsByAnimation[i] = new List <ElementPose> [MaxConcurrentAnimations]; nextFrameTransformsByAnimation[i] = new List <ElementPose> [MaxConcurrentAnimations]; weightsByAnimationAndElement[i] = new ShapeElementWeights[MaxConcurrentAnimations][]; } }
// 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 ); } } }