//read in the positions of the bones public void UpdateTransforms(Transform[] boneTransforms, ReadOnlyArrayCollection <Transform> boneWorldTransforms) { Transform transform; //update previous positions for (int i = 0; i < previousPositions.Length; i++) { this.previousPositions[i] = this.positions[i]; } Matrix matrix; for (int i = 0; i < boneTransforms.Length; i++) { //read each bone if (activeBones[i]) { transform = (boneWorldTransforms[i] * boneTransforms[i]); transform.GetMatrix(out matrix); //as a matrix. //work out the position each offset point from each bone should be, and output to the position value. for (int p = 0; p < BonePointCount; p++) { Vector3.Transform(ref BoneOffsets[p], ref matrix, out this.positions[i * BonePointCount + p]); } } } }
//the final method in the interface, //when this method is called, the bones have been transformed into their final hierarchy. //modifying a bone here will only modify the transform of that bone (and not it's children). public void ProcessBonesPostTransform(Transform[] boneSpaceTransforms, ModelData modelData, ReadOnlyArrayCollection <Transform> boneWorldSpaceIdentityTransforms, ReadOnlyArrayCollection <Transform> boneWorldSpaceIdentityInverseTransforms) { //however, here, simply copy out the positions for each of the bones, and store them in the hacky verlet integrator //note: when the verlet system is active, neither this method or the second interface method will be called, //as it returns false in the first method. verletSolver.UpdateTransforms(boneSpaceTransforms, boneWorldSpaceIdentityTransforms); }
//the actual integration step public void IntegrateBones(Transform[] boneTransforms, ReadOnlyArrayCollection <Transform> boneWorldSpaceIdentityTransforms, ReadOnlyArrayCollection <Transform> boneWorldSpaceIdentityInverseTransforms) { //perform the integration (constraints, verlet, etc) PerformIntegration(); //new bone transfomrs will be written to boneTransforms Matrix matrix = Matrix.Identity; Transform transform; for (int i = 0; i < boneTransforms.Length; i++) { if (activeBones[i]) { //for each bone.. //the centre point (first position) Vector3 basis = this.positions[i * BonePointCount]; //the three positions offset from the centre Vector3 x = this.positions[i * BonePointCount + 1]; Vector3 y = this.positions[i * BonePointCount + 2]; Vector3 z = this.positions[i * BonePointCount + 3]; //get the differences to the centre point... x -= basis; y -= basis; z -= basis; //these form the axis of the bone's rotation //x-axis of the matrix matrix.M11 = x.X; matrix.M12 = x.Y; matrix.M13 = x.Z; //y-axis of the matrix matrix.M21 = y.X; matrix.M22 = y.Y; matrix.M23 = y.Z; //z-axis of the matrix matrix.M31 = z.X; matrix.M32 = z.Y; matrix.M33 = z.Z; //position matrix.M41 = basis.X; matrix.M42 = basis.Y; matrix.M43 = basis.Z; //work out the transform from the matrix... transform = new Transform(ref matrix); //set the transform (multiplied by the inverse of the bone->world transform) //as the bones are in world space, needs to be in bone local space boneTransforms[i] = (boneWorldSpaceIdentityInverseTransforms[i] * transform); } } }
public bool ProcessBonesPreTransform(Transform[] boneSpaceTransforms, ModelData modelData, ReadOnlyArrayCollection<Transform> boneWorldSpaceTransforms, ReadOnlyArrayCollection<Transform> boneWorldSpaceInverseTransforms) { for (int i = 0; i < 5; i++) { Transform transform = Transform.Identity; Quaternion.CreateFromYawPitchRoll(_rotations[i], 0, 0, out transform.Rotation); transform.Translation.Z = _rotations[i] * 2; int parent1 = modelData.Skeleton.BoneData[_fingers[i, 0]].Parent; int parent2 = modelData.Skeleton.BoneData[_fingers[i, 1]].Parent; boneSpaceTransforms[_fingers[i, 0]] *= transform; boneSpaceTransforms[_fingers[i, 1]] *= transform; } return true; }
public static CodeMemberMethod BuildCpuLogic(string name, ReadOnlyArrayCollection <ParticleSystemLogicStep> steps, bool addMethod) { //generate the a runtime method... if (memberTranslate == null) { memberTranslate = new Dictionary <string, CodeExpression>(); BuildTranslate(memberTranslate); } CodeMemberMethod method = new CodeMemberMethod(); method.Attributes = MemberAttributes.Public | MemberAttributes.Static | MemberAttributes.Final; method.Name = name; //inputs method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(uint), "count")); if (addMethod) { method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(uint[]), "indices")); } method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(float), "time")); method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Random), "rand")); method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(float), "delta_time")); method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(float[]), "global")); //fill the logic tree BuildLogic(method.Statements, steps, addMethod); method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Vector2[]), "life")); //pass in all members even if unused method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Vector4[]), "ps")); method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Vector4[]), "vr")); method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Vector4[]), "col")); method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Vector4[]), "user")); return(method); }
static internal void SetParticleTypeDrawMask(ref uint mask, ParticleSystem system, string particleTypeName, bool draw) { if (system == null) { throw new InvalidOperationException("ParticleSystem == null"); } if (system.ParticleSystemData == null) { throw new InvalidOperationException("ParticleSystem.ParticleSystemData == null"); } ReadOnlyArrayCollection <Xen.Ex.Graphics.Content.ParticleSystemTypeData> array = system.ParticleSystemData.ParticleTypeData; for (int i = 0; i < array.Length; i++) { if (array[i].Name == particleTypeName) { SetParticleTypeDrawMask(ref mask, i, draw); return; } } throw new ArgumentException(string.Format("ParticleSystem.ParticleSystemData.ParticleTypeData does not contain a particle type '{0}'", particleTypeName)); }
//the second method in the animation process. //At this point, the normal model animations have been generated. //However, the bones have not been transformed into a hierarchy yet. public bool ProcessBonesPreTransform(Transform[] boneSpaceTransforms, ModelData modelData, ReadOnlyArrayCollection <Transform> boneWorldSpaceTransforms, ReadOnlyArrayCollection <Transform> boneWorldSpaceInverseTransforms) { //spin the spine..? if (enableModifySingleBone) { //make a transform to rotate the bone Transform transform = Transform.Identity; //create a rotation Quaternion.CreateFromYawPitchRoll(0, this.rotationValue, 0, out transform.Rotation); //see the big comment at the top of this file transform = boneWorldSpaceInverseTransforms[spinBoneIndex] * (transform * boneWorldSpaceTransforms[spinBoneIndex]); //modify the bone transform (or you could replace it entirely) boneSpaceTransforms[spinBoneIndex] *= transform; } //returning true continues the animation process, so the hierarchy is transformed and ProcessBonesPostTransform is called //return false if animation is complete (for example, the animation has been transformed manually) return(true); }
public static CodeMemberMethod BuildCpuLogic(string name, ReadOnlyArrayCollection<ParticleSystemLogicStep> steps, bool addMethod) { //generate the a runtime method... if (memberTranslate == null) { memberTranslate = new Dictionary<string, CodeExpression>(); BuildTranslate(memberTranslate); } CodeMemberMethod method = new CodeMemberMethod(); method.Attributes = MemberAttributes.Public | MemberAttributes.Static | MemberAttributes.Final; method.Name = name; //inputs method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(uint), "count")); if (addMethod) method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(uint[]), "indices")); method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(float), "time")); method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Random), "rand")); method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(float), "delta_time")); method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(float[]), "global")); //fill the logic tree BuildLogic(method.Statements, steps, addMethod); method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Vector2[]), "life")); //pass in all members even if unused method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Vector4[]), "ps")); method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Vector4[]), "vr")); method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Vector4[]), "col")); method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Vector4[]), "user")); return method; }
private static void BuildLogic(CodeStatementCollection statements, ReadOnlyArrayCollection <ParticleSystemLogicStep> steps, bool addMethod) { Dictionary <string, bool> argsUsed = new Dictionary <string, bool>(); foreach (string arg in memberTranslate.Keys) { argsUsed.Add(arg, false); } argsUsed.Add("rand", false); CodeStatementCollection code = new CodeStatementCollection(); BuildLogic(code, steps, argsUsed, 0); //rand requires a local variable if (argsUsed["rand"]) { statements.Add( new CodeVariableDeclarationStatement( typeof(float), "_tmp", new CodePrimitiveExpression(0.0f))); } for (int i = 0; i < 4; i++) { if (argsUsed["local" + i]) { code.Insert(0, new CodeVariableDeclarationStatement( typeof(float), "local" + i, new CodePrimitiveExpression(0.0f))); } } CodeVariableReferenceExpression ref_i = new CodeVariableReferenceExpression("i"); if (addMethod) // add methods have indices to update... { ref_i.VariableName = "_i"; } CodeIterationStatement loop = new CodeIterationStatement(); loop.InitStatement = new CodeVariableDeclarationStatement(typeof(uint), ref_i.VariableName, new CodePrimitiveExpression(0)); loop.IncrementStatement = new CodeAssignStatement(ref_i, new CodeBinaryOperatorExpression(ref_i, CodeBinaryOperatorType.Add, new CodePrimitiveExpression((uint)1))); loop.TestExpression = new CodeBinaryOperatorExpression(ref_i, CodeBinaryOperatorType.LessThan, new CodeArgumentReferenceExpression("count")); // uint i = indices[_i]; if (addMethod) { loop.Statements.Add(new CodeVariableDeclarationStatement(typeof(uint), "i", new CodeArrayIndexerExpression(new CodeArgumentReferenceExpression("indices"), ref_i))); } else { //put in velocity logic loop.Statements.Add( new CodeAssignStatement(Arg("position.x"), new CodeBinaryOperatorExpression(Arg("position.x"), CodeBinaryOperatorType.Add, new CodeBinaryOperatorExpression(Arg("velocity.x"), CodeBinaryOperatorType.Multiply, Arg("delta_time"))))); loop.Statements.Add( new CodeAssignStatement(Arg("position.y"), new CodeBinaryOperatorExpression(Arg("position.y"), CodeBinaryOperatorType.Add, new CodeBinaryOperatorExpression(Arg("velocity.y"), CodeBinaryOperatorType.Multiply, Arg("delta_time"))))); loop.Statements.Add( new CodeAssignStatement(Arg("position.z"), new CodeBinaryOperatorExpression(Arg("position.z"), CodeBinaryOperatorType.Add, new CodeBinaryOperatorExpression(Arg("velocity.z"), CodeBinaryOperatorType.Multiply, Arg("delta_time"))))); } loop.Statements.AddRange(code); statements.Add(loop); }
//methods of the interface //this first method is called before any normal animation calculation takes place //the nonAnimatedBones Transforms are usualy still storing the previous frame's animation, //however, this is not guarenteed. They should be considered write-only. //returning true from this method stops the animation process early public bool PreProcessAnimation(Transform[] nonAnimatedBones, ModelData modelData, ReadOnlyArrayCollection <Transform> boneWorldSpaceIdentityTransforms, ReadOnlyArrayCollection <Transform> boneWorldSpaceIdentityInverseTransforms) { //is the hacky verlet example enabled? if (enableVerlet) { //if so, let the verlet integrator generate the bone transforms itself verletSolver.IntegrateBones(nonAnimatedBones, boneWorldSpaceIdentityTransforms, boneWorldSpaceIdentityInverseTransforms); //the bones are now entirely generated, so return false. //return false because the animation is complete (in this example, the animation has been transformed manually) return(false); } //returning true continues the animation process, //so the animations are generated, interpolated and ProcessBonesPreTransform is called. return(true); }
private static void BuildLogic(CodeStatementCollection statements, ReadOnlyArrayCollection<ParticleSystemLogicStep> steps, Dictionary<string, bool> argUsed, int depth) { for (int i = 0; i < steps.Length; i++) { ParticleSystemLogicStep step = steps[i]; CodeExpression arg0 = Arg(step.arg0); CodeExpression arg1 = Arg(step.arg1); CodeExpression argT = Arg(step.target); CodeExpression target = Arg(step.target); if (arg0 != null && arg0 is CodePrimitiveExpression == false) argUsed[step.arg0] = true; if (arg1 != null && arg1 is CodePrimitiveExpression == false) argUsed[step.arg1] = true; if (target != null && target is CodePrimitiveExpression == false) argUsed[step.target] = true; if (step.Children.Length > 0) { CodeVariableReferenceExpression local = new CodeVariableReferenceExpression("i" + depth); if (step.type == "loop") { CodeIterationStatement iteration = new CodeIterationStatement(); iteration.InitStatement = new CodeVariableDeclarationStatement(typeof(uint), local.VariableName, new CodePrimitiveExpression((uint)0)); iteration.TestExpression = new CodeBinaryOperatorExpression(local, CodeBinaryOperatorType.LessThan, arg0); iteration.IncrementStatement = new CodeAssignStatement(local, new CodeBinaryOperatorExpression(local, CodeBinaryOperatorType.Add, new CodePrimitiveExpression((uint)1))); BuildLogic(iteration.Statements, step.Children, argUsed, depth + 1); statements.Add(iteration); } else { CodeBinaryOperatorType op = CodeBinaryOperatorType.IdentityEquality; //if switch (step.type) { case "if_notequal": op = CodeBinaryOperatorType.IdentityInequality; break; case "if_lessequal": op = CodeBinaryOperatorType.LessThanOrEqual; break; case "if_greaterequal": op = CodeBinaryOperatorType.GreaterThanOrEqual; break; case "if_less": op = CodeBinaryOperatorType.LessThan; break; case "if_greater": op = CodeBinaryOperatorType.GreaterThan; break; } CodeConditionStatement condition = new CodeConditionStatement(); condition.Condition = new CodeBinaryOperatorExpression( arg0, op, arg1); BuildLogic(condition.TrueStatements, step.Children, argUsed, depth + 1); statements.Add(condition); } } else { CodeExpression expression = null; switch (step.type) { case "set": expression = arg0; break; case "add": expression = Op(CodeBinaryOperatorType.Add, argT, arg0, arg1); break; case "sub": expression = Op(CodeBinaryOperatorType.Subtract, argT, arg0, arg1); break; case "mul": expression = Op(CodeBinaryOperatorType.Multiply, argT, arg0, arg1); break; case "div": expression = Op(CodeBinaryOperatorType.Divide, argT, arg0, arg1); break; case "abs": case "sign": case "cos": case "sin": case "acos": case "asin": case "tan": case "atan": case "sqrt": expression = MathOp1(step.type, arg0); break; case "atan2": case "min": case "max": expression = MathOp2(step.type, arg0, arg1); break; case "saturate": expression = MathOp2("max", new CodePrimitiveExpression(0.0f), MathOp2("min", new CodePrimitiveExpression(1.0f), arg0)); break; case "rsqrt": expression = new CodeBinaryOperatorExpression( new CodePrimitiveExpression(1.0f), CodeBinaryOperatorType.Divide, MathOp1("sqrt", arg0)); break; case "madd": expression = new CodeBinaryOperatorExpression(argT, CodeBinaryOperatorType.Add, new CodeBinaryOperatorExpression(arg0, CodeBinaryOperatorType.Multiply, arg1)); break; case "rand": argUsed["rand"] = true; expression = Rand(arg0, arg1, statements); break; case "rand_smooth": argUsed["rand"] = true; expression = RandSmooth(arg0, arg1, statements); break; } if (expression == null) throw new ArgumentNullException("Unknown statement " + step.type); statements.Add(new CodeAssignStatement(target, expression)); } } }
private static void BuildLogic(CodeStatementCollection statements, ReadOnlyArrayCollection<ParticleSystemLogicStep> steps, bool addMethod) { Dictionary<string, bool> argsUsed = new Dictionary<string, bool>(); foreach (string arg in memberTranslate.Keys) argsUsed.Add(arg, false); argsUsed.Add("rand", false); CodeStatementCollection code = new CodeStatementCollection(); BuildLogic(code, steps, argsUsed, 0); //rand requires a local variable if (argsUsed["rand"]) statements.Add( new CodeVariableDeclarationStatement( typeof(float), "_tmp", new CodePrimitiveExpression(0.0f))); for (int i = 0; i < 4; i++) { if (argsUsed["local" + i]) { code.Insert(0, new CodeVariableDeclarationStatement( typeof(float), "local"+i, new CodePrimitiveExpression(0.0f))); } } CodeVariableReferenceExpression ref_i = new CodeVariableReferenceExpression("i"); if (addMethod) // add methods have indices to update... ref_i.VariableName = "_i"; CodeIterationStatement loop = new CodeIterationStatement(); loop.InitStatement = new CodeVariableDeclarationStatement(typeof(uint), ref_i.VariableName, new CodePrimitiveExpression(0)); loop.IncrementStatement = new CodeAssignStatement(ref_i,new CodeBinaryOperatorExpression(ref_i, CodeBinaryOperatorType.Add, new CodePrimitiveExpression((uint)1))); loop.TestExpression = new CodeBinaryOperatorExpression(ref_i, CodeBinaryOperatorType.LessThan, new CodeArgumentReferenceExpression("count")); // uint i = indices[_i]; if (addMethod) loop.Statements.Add(new CodeVariableDeclarationStatement(typeof(uint), "i", new CodeArrayIndexerExpression(new CodeArgumentReferenceExpression("indices"), ref_i))); else { //put in velocity logic loop.Statements.Add( new CodeAssignStatement(Arg("position.x"), new CodeBinaryOperatorExpression(Arg("position.x"), CodeBinaryOperatorType.Add, new CodeBinaryOperatorExpression(Arg("velocity.x"), CodeBinaryOperatorType.Multiply, Arg("delta_time"))))); loop.Statements.Add( new CodeAssignStatement(Arg("position.y"), new CodeBinaryOperatorExpression(Arg("position.y"), CodeBinaryOperatorType.Add, new CodeBinaryOperatorExpression(Arg("velocity.y"), CodeBinaryOperatorType.Multiply, Arg("delta_time"))))); loop.Statements.Add( new CodeAssignStatement(Arg("position.z"), new CodeBinaryOperatorExpression(Arg("position.z"), CodeBinaryOperatorType.Add, new CodeBinaryOperatorExpression(Arg("velocity.z"), CodeBinaryOperatorType.Multiply, Arg("delta_time"))))); } loop.Statements.AddRange(code); statements.Add(loop); }
//the actual integration step public void IntegrateBones(Transform[] boneTransforms, ReadOnlyArrayCollection<Transform> boneWorldSpaceIdentityTransforms, ReadOnlyArrayCollection<Transform> boneWorldSpaceIdentityInverseTransforms) { //perform the integration (constraints, verlet, etc) PerformIntegration(); //new bone transfomrs will be written to boneTransforms Matrix matrix = Matrix.Identity; Transform transform = Transform.Identity; for (int i = 0; i < boneTransforms.Length; i++) { if (activeBones[i]) { //for each bone.. //the centre point (first position) Vector3 basis = this.positions[i * BonePointCount]; //the three positions offset from the centre Vector3 x = this.positions[i * BonePointCount + 1]; Vector3 y = this.positions[i * BonePointCount + 2]; Vector3 z = this.positions[i * BonePointCount + 3]; //get the differences to the centre point... x -= basis; y -= basis; z -= basis; //these form the axis of the bone's rotation //x-axis of the matrix matrix.M11 = x.X; matrix.M12 = x.Y; matrix.M13 = x.Z; //y-axis of the matrix matrix.M21 = y.X; matrix.M22 = y.Y; matrix.M23 = y.Z; //z-axis of the matrix matrix.M31 = z.X; matrix.M32 = z.Y; matrix.M33 = z.Z; //position matrix.M41 = basis.X; matrix.M42 = basis.Y; matrix.M43 = basis.Z; //work out the transform from the matrix... //do not perform a validity check in the transform constrctor, //as who cares if the matrix isn't orthoganal :-) //otherwise it can throw an exception if the matrix is skewed transform = new Transform(ref matrix, false); //set the transform (multiplied by the inverse of the bone->world transform) //as the bones are in world space, needs to be in bone local space boneTransforms[i] = (boneWorldSpaceIdentityInverseTransforms[i] * transform); } } }
//the second method in the animation process. //At this point, the normal model animations have been generated. //However, the bones have not been transformed into a hierarchy yet. public bool ProcessBonesPreTransform(Transform[] boneSpaceTransforms, ModelData modelData, ReadOnlyArrayCollection<Transform> boneWorldSpaceTransforms, ReadOnlyArrayCollection<Transform> boneWorldSpaceInverseTransforms) { //spin the spine..? if (enableModifySingleBone) { //make a transform to rotate the bone Transform transform = Transform.Identity; //create a rotation Quaternion.CreateFromYawPitchRoll(0, this.rotationValue, 0, out transform.Rotation); //modify the bone transform (or you could replace it entirely) boneSpaceTransforms[spinBoneIndex] *= transform; } //returning true continues the animation process, so the hierarchy is transformed and ProcessBonesPostTransform is called //return false if animation is complete (for example, the animation has been transformed manually) return true; }
//methods of the interface //this first method is called before any normal animation calculation takes place //the nonAnimatedBones Transforms are usualy still storing the previous frame's animation, //however, this is not guarenteed. They should be considered write-only. //returning true from this method stops the animation process early public bool PreProcessAnimation(Transform[] nonAnimatedBones, ModelData modelData, ReadOnlyArrayCollection<Transform> boneWorldSpaceIdentityTransforms, ReadOnlyArrayCollection<Transform> boneWorldSpaceIdentityInverseTransforms) { //is the hacky verlet example enabled? if (enableVerlet) { //if so, let the verlet integrator generate the bone transforms itself verletSolver.IntegrateBones(nonAnimatedBones, boneWorldSpaceIdentityTransforms, boneWorldSpaceIdentityInverseTransforms); //the bones are now entirely generated, so return false. //return false because the animation is complete (in this example, the animation has been transformed manually) return false; } //returning true continues the animation process, //so the animations are generated, interpolated and ProcessBonesPreTransform is called. return true; }
private static void BuildLogic(CodeStatementCollection statements, ReadOnlyArrayCollection <ParticleSystemLogicStep> steps, Dictionary <string, bool> argUsed, int depth) { for (int i = 0; i < steps.Length; i++) { ParticleSystemLogicStep step = steps[i]; CodeExpression arg0 = Arg(step.arg0); CodeExpression arg1 = Arg(step.arg1); CodeExpression argT = Arg(step.target); CodeExpression target = Arg(step.target); if (arg0 != null && arg0 is CodePrimitiveExpression == false) { argUsed[step.arg0] = true; } if (arg1 != null && arg1 is CodePrimitiveExpression == false) { argUsed[step.arg1] = true; } if (target != null && target is CodePrimitiveExpression == false) { argUsed[step.target] = true; } if (step.Children.Length > 0) { CodeVariableReferenceExpression local = new CodeVariableReferenceExpression("i" + depth); if (step.type == "loop") { CodeIterationStatement iteration = new CodeIterationStatement(); iteration.InitStatement = new CodeVariableDeclarationStatement(typeof(uint), local.VariableName, new CodePrimitiveExpression((uint)0)); iteration.TestExpression = new CodeBinaryOperatorExpression(local, CodeBinaryOperatorType.LessThan, arg0); iteration.IncrementStatement = new CodeAssignStatement(local, new CodeBinaryOperatorExpression(local, CodeBinaryOperatorType.Add, new CodePrimitiveExpression((uint)1))); BuildLogic(iteration.Statements, step.Children, argUsed, depth + 1); statements.Add(iteration); } else { CodeBinaryOperatorType op = CodeBinaryOperatorType.IdentityEquality; //if switch (step.type) { case "if_notequal": op = CodeBinaryOperatorType.IdentityInequality; break; case "if_lessequal": op = CodeBinaryOperatorType.LessThanOrEqual; break; case "if_greaterequal": op = CodeBinaryOperatorType.GreaterThanOrEqual; break; case "if_less": op = CodeBinaryOperatorType.LessThan; break; case "if_greater": op = CodeBinaryOperatorType.GreaterThan; break; } CodeConditionStatement condition = new CodeConditionStatement(); condition.Condition = new CodeBinaryOperatorExpression( arg0, op, arg1); BuildLogic(condition.TrueStatements, step.Children, argUsed, depth + 1); statements.Add(condition); } } else { CodeExpression expression = null; switch (step.type) { case "set": expression = arg0; break; case "add": expression = Op(CodeBinaryOperatorType.Add, argT, arg0, arg1); break; case "sub": expression = Op(CodeBinaryOperatorType.Subtract, argT, arg0, arg1); break; case "mul": expression = Op(CodeBinaryOperatorType.Multiply, argT, arg0, arg1); break; case "div": expression = Op(CodeBinaryOperatorType.Divide, argT, arg0, arg1); break; case "abs": case "sign": case "cos": case "sin": case "acos": case "asin": case "tan": case "atan": case "sqrt": expression = MathOp1(step.type, arg0); break; case "atan2": case "min": case "max": expression = MathOp2(step.type, arg0, arg1); break; case "saturate": expression = MathOp2("max", new CodePrimitiveExpression(0.0f), MathOp2("min", new CodePrimitiveExpression(1.0f), arg0)); break; case "rsqrt": expression = new CodeBinaryOperatorExpression( new CodePrimitiveExpression(1.0f), CodeBinaryOperatorType.Divide, MathOp1("sqrt", arg0)); break; case "madd": expression = new CodeBinaryOperatorExpression(argT, CodeBinaryOperatorType.Add, new CodeBinaryOperatorExpression(arg0, CodeBinaryOperatorType.Multiply, arg1)); break; case "rand": argUsed["rand"] = true; expression = Rand(arg0, arg1, statements); break; case "rand_smooth": argUsed["rand"] = true; expression = RandSmooth(arg0, arg1, statements); break; } if (expression == null) { throw new ArgumentNullException("Unknown statement " + step.type); } statements.Add(new CodeAssignStatement(target, expression)); } } }
//NEW CODE private void DrawBoundingBoxes(DrawState state) { //First, get the animated bone transforms of the model. //These transforms are in 'bone-space', not in world space. ReadOnlyArrayCollection <Transform> boneAnimationTransforms = model.GetAnimationController().GetTransformedBones(state); //Get a simple shader from Xen.Ex that fills a solid colour Xen.Ex.Shaders.FillSolidColour shader = state.GetShader <Xen.Ex.Shaders.FillSolidColour>(); shader.FillColour = Color.White.ToVector4(); shader.Bind(state); //push the render state... state.PushRenderState(); //disable back face culling state.RenderState.DepthColourCull.CullMode = CullMode.None; //set to wireframe state.RenderState.DepthColourCull.FillMode = FillMode.WireFrame; //loop through all the geometry data in the model.. //(note, the sample model has only 1 geometry instance) Xen.Ex.Graphics.Content.SkeletonData modelSkeleton = model.ModelData.Skeleton; Matrix matrix; int boxIndex = 0; foreach (Xen.Ex.Graphics.Content.MeshData meshData in model.ModelData.Meshes) { foreach (Xen.Ex.Graphics.Content.GeometryData geometry in meshData.Geometry) { //now loop through all bones used by this geometry for (int geometryBone = 0; geometryBone < geometry.BoneIndices.Length; geometryBone++) { //index of the bone (a piece of geometry may not use all the bones in the model) int boneIndex = geometry.BoneIndices[geometryBone]; //get the base transform of the bone (the transform when not animated) Transform boneTransform = modelSkeleton.BoneWorldTransforms[boneIndex]; //multiply the transform with the animation bone-local transform //it would be better to use Transform.Multiply() here to save data copying on the xbox boneTransform *= boneAnimationTransforms[boneIndex]; //Get the transform as a matrix boneTransform.GetMatrix(out matrix); //push the matrix state.PushWorldMatrix(ref matrix); //draw the box if (boundingBoxes[boxIndex].CullTest(state)) { boundingBoxes[boxIndex].Draw(state); } boxIndex++; //pop the world matrix state.PopWorldMatrix(); } } } //pop the render state state.PopRenderState(); }
public bool PreProcessAnimation(Transform[] nonAnimatedBones, ModelData modelData, ReadOnlyArrayCollection<Transform> boneWorldSpaceIdentityTransforms, ReadOnlyArrayCollection<Transform> boneWorldSpaceIdentityInverseTransforms) { return true; }