• Advertisement

B. /

Member
  • Content count

    26
  • Joined

  • Last visited

Community Reputation

0 Neutral

About B. /

  • Rank
    Member

Personal Information

  • Interests
    Art
    Design
    Programming
  1. So the next problem is i saw. That i need the world space joint matrices from the controller lib, because they are the world space matrices of the bind pose of the mesh. For a sample, i start a animation not from the bind pose, than first i need first to set the vertices in the right space and that i only can do, if i have the source space of the bind pose. And the visual lib has only the local matrices of the first animation space. So i calculate the animation m_ws from the visual lib m_ls and the bone m_ws from the controller lib (because the controller lib has only the inverse value, so i invert it)
  2. ps. I update my code to calculate the local matrices from the animations to world matrices with this: public static void TransformHierachy(Joint joint, Matrix parentMatrix) { Matrix result = joint.ObjectSpace.Matrix * parentMatrix; joint.ObjectSpace.Set(result); if(joint.HasAnimations) for (int i = 0; i < joint.Animations[0].AnimationMatrices.Length; i++) joint.Animations[0].AnimationMatrices[i] = joint.Animations[0].AnimationMatrices[i] * parentMatrix; foreach (Joint child in joint.Children) TransformHierachy(child, result); } It works like befor, the source and target space are now similar, the mesh will not deform, but the problem is still there. pps. I think my code is doing the same as yours right?
  3. I go only recursively up from the parents to the root But i tried now your code to calculate the bone local matrices to world matrices and your code, start from the root is very good and easy to understand and do this And the Preview Skeleton will draw correct too In my code i send the root bone (Joint1) and a Matrix Idetity to the function public static void TransformHierachy(Joint joint, Matrix parentMatrix) { Matrix result = joint.ObjectSpace.Matrix * parentMatrix; joint.ObjectSpace.Set(result); foreach (Joint child in joint.Children) TransformHierachy(child, result); } So but whats now if the animation local matrices, they need to calculate from local to world space too, right? It's so confuse to understand how the interpretation of Autodesk Exporter is. Because the Collada Exporter from Autodesk is differnt as the OpenCollada Exporter. In Autodesk i can choose between single matrix or scale, rotate and translate values, but this has only a effect to the visual lib, not the controller lib. OpenCollada Exporter do only export rotate and translate values and hasn't in the animation lib any of target space matrices x.x
  4. I also read the docu again. I need the world space matrices from the matrix array of the controller_lib, because they are preculculatet, but whats with the local matrices from the animation_lib. These i need to bring first in the world space with the local matrices of the visual lib right?
  5. Yes it is, i just change the name to CalculateWorldFromLocalSpaceMatrix That the Local Matrix i load from the file animatedSpaceMatrix = targetspacematrix. animation.AnimationMatrices[12] is the animation local matrix from file that have the 90 degress roation. animation.AnimationMatrices[12] * worldSpaceMatrix is local matrix * world matix to get the final world/target matrix in world. That i dont get it. My Joint class has Parent node and children nodes. Why i get more multiplications only if i go back, i check only the parent node of every child? If i start from the root, i would check the children nodes first and that the same only backward? But for my bug, I know excatly what i make wrong. In my Elbow cube i have 3 bones, just call they root, arm and hand. I only rotate the arm 90 degress of the X Axis. So i calculate for the bones, because they are all local, the world space matrix. But my mistake is, the arm had the target space of aniamtion local matrix, not his origin local matrix and so if i calculate for the hand bone the world space, i do this if the origin local of the arm bone and not with the animation local arm bone and so i get this error. Greets Benjamin
  6. What do you mean by this, should I everytime calculate the World Space Matrices new, befor i do his part? for each bone // can be in random order { Matrix worldSpaceRestBoneMatrix = bone.matRestWS; // this is in world space, so hierarchy does not matter anymore at this point, precalulated once when file is loaded Matrix inverseBindMatrix = Inverse(worldSpaceRestBoneMatrix); Matrix animatedSpaceMatrix = bone.matAnimWS; // also world space, calculated once per frame with hierarchy and animation data Matrix finalMatrix = inverseBindMatrix * animatedSpaceMatrix; // or vice versa } Because in the controller_lib, the Bone World Space matrices/matRestWS already exist, only the animation matrices in the animation_lib are Local Space Because your code looks like how i calculate the Local Space Matrix to World Space? TransformHierachy (int boneIndex, Matrix &parentMatrix, bool animatePerFrame) { if (animatePerFrame) { bones[boneIndex].matAnimWS = parentMatrix * animationMatrixFromFile[boneIndex]; for each child { TransformHierachy (childIndex, bones[boneIndex].matAnimWS); } } else // loading character bones[boneIndex].matRestWS = parentMatrix * skeletonMatrixFromFile[boneIndex]; for each child { TransformHierachy (childIndex, bones[boneIndex].matRestWS ); } } } Actually, dont i do the same with my code like you in your code? First Calculate the World space from the Local Space, next do the same witht the animationSapce and multiply these? It seems to me we do the same thing? public static Matrix CalculateWorldFromLocalSpaceMatrix(Joint joint, Matrix result) { if (joint.Parent != null) { result *= CalculateLocalSpaceMatrix(joint.Parent, joint.Parent.ObjectSpace.Matrix); return result; } else return joint.ObjectSpace.Matrix; } Matrix worldSpaceMatrix = MatrixHelper.CalculateWorldFromLocalSpaceMatrix((Joint)bone, Matrix.Identity); Matrix inverseBindMatrix = Matrix.Invert(bone.ObjectSpace.Matrix * worldSpaceMatrix); animatedSpaceMatrix = animation.AnimationMatrices[12] * worldSpaceMatrix; Matrix finalMatrix = inverseBindMatrix * animatedSpaceMatrix;
  7. Hi Joe, ok that sounds good, but whats with the case, i rotate my arm and after this my hand, and i dont have a hierarchy anymore. I still need for the right hand worldspace the animated world space from the roateted arm, or do i think wrong? For my problem i just need to calculate the local space right and check if a parent bone has animations and take the current animation matrix instead of the worldspace matrix of the parent bone for the total result?
  8. Yeah, because in the visual_lib stay the same object space matix as in the animation array, but the collada docu say, i could ignore the visual matrices, because all imported stays in the matrices array in the controller_lib I will check this carefully and answer than
  9. ps. I check up the file to see, if the bone world/Object space matrix is the same as the first animation matrix, and its a little bit different Bone: 1.000000 0.000000 0.000000 3.963553 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.011606 0.000000 0.000000 0.000000 1.000000 First Animation Matrix: 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 That could explain, why i dont get the origin model shape back, after tranform these In the file i read joint3-Interpolations-array (Animation Matrices Array) Could it be that i first need to calculate the right animation matrices realtive from the bone object space, befor i can transform my vertices? Here is the animation_lib of the file <library_animations> <animation id="joint3-anim" name="joint3"><animation><source id="joint3-Matrix-animation-input"><float_array id="joint3-Matrix-animation-input-array" count="24"> 0.041667 0.083333 0.125000 0.166667 0.208333 0.250000 0.291667 0.333333 0.375000 0.416667 0.458333 0.500000 0.541667 0.583333 0.625000 0.666667 0.708333 0.750000 0.791667 0.833333 0.875000 0.916667 0.958333 1.000000</float_array><technique_common><accessor source="#joint3-Matrix-animation-input-array" count="24"><param name="TIME" type="float"/></accessor></technique_common></source><source id="joint3-Matrix-animation-output-transform"><float_array id="joint3-Matrix-animation-output-transform-array" count="384"> 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -0.142293 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -0.532450 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -1.115392 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -1.836036 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -2.639301 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -3.470107 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -4.273373 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -4.994017 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -5.576958 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -5.967116 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -6.109408 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -5.989200 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -5.656859 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -5.154813 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -4.525488 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -3.811309 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -3.054704 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -2.298099 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -1.583921 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -0.954595 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -0.452549 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 -0.120208 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 3.447073 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000</float_array><technique_common><accessor source="#joint3-Matrix-animation-output-transform-array" count="24" stride="16"><param type="float4x4"/></accessor></technique_common></source><source id="joint3-Interpolations"><Name_array id="joint3-Interpolations-array" count="24"> LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR</Name_array><technique_common><accessor source="#joint3-Interpolations-array" count="24"><param type="name"/></accessor></technique_common></source><sampler id="joint3-Matrix-animation-transform"><input semantic="INPUT" source="#joint3-Matrix-animation-input"/><input semantic="OUTPUT" source="#joint3-Matrix-animation-output-transform"/><input semantic="INTERPOLATION" source="#joint3-Interpolations"/></sampler><channel source="#joint3-Matrix-animation-transform" target="joint3/matrix"/></animation><animation><source id="joint3-visibility-animation-input"><float_array id="joint3-visibility-animation-input-array" count="3"> 0.041667 0.500000 1.000000</float_array><technique_common><accessor source="#joint3-visibility-animation-input-array" count="3"><param name="TIME" type="float"/></accessor></technique_common></source><source id="joint3-visibility-animation-output"><float_array id="joint3-visibility-animation-output-array" count="3"> 1.000000 1.000000 1.000000</float_array><technique_common><accessor source="#joint3-visibility-animation-output-array" count="3"><param type="float"/></accessor></technique_common></source><source id="joint3-visibility-animation-intan"><float_array id="joint3-visibility-animation-intan-array" count="3"> 0.000000 0.000000 0.000000</float_array><technique_common><accessor source="#joint3-visibility-animation-intan-array" count="3"><param type="float"/></accessor></technique_common></source><source id="joint3-visibility-animation-outtan"><float_array id="joint3-visibility-animation-outtan-array" count="3"> 0.000000 0.000000 0.000000</float_array><technique_common><accessor source="#joint3-visibility-animation-outtan-array" count="3"><param type="float"/></accessor></technique_common></source><source id="joint3-visibility-animation-interpolation"><Name_array id="joint3-visibility-animation-interpolation-array" count="3"> STEP STEP STEP</Name_array><technique_common><accessor source="#joint3-visibility-animation-interpolation-array" count="3"><param type="name"/></accessor></technique_common></source><sampler id="joint3-visibility-animation"><input semantic="INPUT" source="#joint3-visibility-animation-input"/><input semantic="OUTPUT" source="#joint3-visibility-animation-output"/><input semantic="IN_TANGENT" source="#joint3-visibility-animation-intan"/><input semantic="OUT_TANGENT" source="#joint3-visibility-animation-outtan"/><input semantic="INTERPOLATION" source="#joint3-visibility-animation-interpolation"/></sampler><channel source="#joint3-visibility-animation" target="joint3/visibility"/></animation></animation> </library_animations>
  10. The inverseBindMatrix is the world/object space matrix of the bone i load from the file, remember, i wrote, that the docu say that each marix in the bone matrices array in the file is inverse. That why i had two transform classes in my bone class, one is original load from the file, the inverse Version and one that is the invert value of the inverse Version to draw my skeleton lines. The localSpaceMatrix, i thought to get in the end the final tranform of the bone relative to the bone hierarchy. I use this code if i group many meshes and transform only the group node/parent node. The animatedSpaceMatrix should be the targetsource. I animated the last bone of 24 frames, so i have 24 targetsources/matrices. So the result of TransformAnimations[0] or TransformAnimations[23] should be in the after multipy them with the other matrices give a matrix idetity. Collada exportert for the bone matrices only the inverse world/object space matrices. So I invert these and store them in my second Transform Class in the bone class. The animated matrices exported normal. That the TransformAnimations Array, i store them for the mesh. So in the end i try it with what i wrote inverseBindMatrix * animatedSpaceMatrix without success, so i thought i try it again with multiy it with the Local Space Matrix
  11. Hi Joe, models will always draw correct in my engine and no model has a joint as parent, i am just a noob in gpu skinning, but not to transform a mesh right with a complex parent node hierarchy So now i do CPU skinning, like you said, to test the code, to find faster bugs. So I test my elbow cube model and animate (translate) the last bone, right side, to move down and again to the starpoint. So i take only the first animation matrix that start form the startpoint and test the animated joint (the last joint) to see if my model keep his form, but unfortunately he tranlate the right side (the 4 edges) a little bit after left, so the mesh will get a little bit smaller I think there is still a bug how i calculate the Local Space, that makes this translate effect!? Here's what i have: public static Matrix CalculateLocalSpaceMatrix(Joint joint, Matrix result) { if (joint.Parent != null) { result *= CalculateLocalSpaceMatrix(joint.Parent, joint.Parent.Transform.ObjectSpaceMatrix); return result; } else return joint.Transform.ObjectSpaceMatrix; } private List<Vertex> originVertices = new List<Vertex>(); private void DoSomethingToolStripMenuItem_Click(object sender, EventArgs e) { if (this.geometry != null) { Geometry g = this.geometry; if (this.originVertices.Count == 0) foreach (Vertex vertex in g.Vertices) this.originVertices.Add(vertex); List<Matrix> boneMatrices = new List<Matrix>(); if (g.Bones.Count != 0) { boneMatrices.Add(Matrix.Identity); for (int iBoneIndex = 0; iBoneIndex < g.Bones.Count; iBoneIndex++) { Joint bone = g.Bones[iBoneIndex]; Matrix inverseBindMatrix = bone.InverseTransform.ObjectSpaceMatrix; Matrix localSpaceMatrix = MatrixHelper.CalculateLocalSpaceMatrix(bone, Matrix.Identity); Matrix animatedSpaceMatrix = this.AnimationList[0].TransformAnimations[0]; Matrix finalMatrix = localSpaceMatrix * inverseBindMatrix * animatedSpaceMatrix; if (iBoneIndex == 2) boneMatrices.Add(finalMatrix); else boneMatrices.Add(Matrix.Identity); } } List<Vertex> skinVertices = new List<Vertex>(); for (int i = 0; i < this.originVertices.Count; i++ ) { Vertex vertex = this.originVertices[i]; Matrix boneTransform = new Matrix(0); boneTransform += boneMatrices[vertex.BoneIndices[0]] * vertex.Weights[0]; boneTransform += boneMatrices[vertex.BoneIndices[1]] * vertex.Weights[1]; boneTransform += boneMatrices[vertex.BoneIndices[2]] * vertex.Weights[2]; boneTransform += boneMatrices[vertex.BoneIndices[3]] * vertex.Weights[3]; vertex.Position = Vector4F.ToVector3(Vector3.Transform(vertex.Position, boneTransform)); skinVertices.Add(vertex); } List<float> result = new List<float>(); foreach (Vertex item in skinVertices) result.AddRange(item.ToFloatArray()); this.scene.Graphics3D.VertexBuffer.Update(result.ToArray()); } } I also read the Collada Docu about skinning again: https://www.khronos.org/collada/wiki/Skinning And the docu say that the bone matrices array are the invert bone matrices So i add in my Joint Class a second tranform class that store the Object Space Matrix of the bone, the first store the inverse matrix (load from file) and the second store the invert matrix from the file (to draw the skeleton preview right). Any Ideas? Greets Benjamin
  12. Hi Joe, thank you very much again, to take the time to explian me it, but i see in your example, we assume that we animate the model, but whats with the case, i only load the model without animation matrices, so we dont have a target space, just to see the skinned model, do i need than to transform the vertices too, or only if i had animation matrices? Greets Benjamin
  13. If i import the Collada file back to Maya i get a warning message that the tranform of every single joint is not compatible with fbx, so its baked into trs? Is not the Problem, that the gpu skinning should be only, if bone matrices animations exist, because my 3 bones has transform matrices who say where they should be in the world, but that is not the position of the vertices, so for a example, a bone with the x postion 3 and tranform with the binding vertices translate these 3 steps right on the x Axis and that is wrong right, because without a animation, every single vertex should be only tranform with a matrix ideity until the get animated? So the transform matrix should be the difference of the old and new bone transform matrix around the postion of the bone? Greets Benjamin
  14. Hi Joe, you had totally right, after hours of checking my code, i found two fatal bugs i made. The first one was a logic mistake by load the boneindices of the file and the second was to set the wrong offsets for weights and boneindices to the shader. So i fix this and now the geometry will draw right and can be deform by the bone matrices, without disconnect the triangle shap But there is still a last little bug. If i send the bone matrices in order of the code i post, i get a little scaling effect of the X Axis, so the mesh will get a little bit larger Inverse order of multiplication the bone matrices has the same result. Transpose the value of multiplication of all matrices, the mesh will pressed like from a heavy hammer. Invert the result of multiplication, i get a scaling effect of the X Axis too, but it will be a little bit smaller. Has anyone an Idea to fix this last step? Greets Benjamin
  15. That only bring a new strange effect, see image Heres again my code Engine Code public static Matrix CalculateMatrixFromParents(Joint joint, Matrix world) { if (joint.Parent != null) { world = CalculateMatrixFromParents(joint.Parent, joint.Parent.Transform.Matrix) * world; return world; } else return joint.Transform.Matrix; } List<Matrix> boneMatrices = new List<Matrix>(); if (this.bones.Count != 0) { boneMatrices.Add(Matrix.Identity); foreach (Joint joint in this.bones) { Matrix m = MatrixHelper.CalculateMatrixFromParents(joint, Matrix.Identity); m.Transpose(); boneMatrices.Add(m * this.bindPoseMatrix); } } return boneMatrices; Shader Code float4 ApplyBoneTransform(Vertex input, float4 value) { if(HasBones) { float4x4 skinTransform = (float4x4)0; skinTransform += BoneMatrices[input.BoneIndices.x] * input.Weights.x; skinTransform += BoneMatrices[input.BoneIndices.y] * input.Weights.y; skinTransform += BoneMatrices[input.BoneIndices.z] * input.Weights.z; skinTransform += BoneMatrices[input.BoneIndices.w] * input.Weights.w; float4 position = mul(value, skinTransform); return position; } else return value; } Pixel vertexShader(Vertex input) { Pixel result = (Pixel) 0; float4 posWorld = mul(ApplyBoneTransform(input, float4(input.Position.xyz, 1.0f)), World); result.Position = mul(mul(posWorld, View), Projection); result.Normal = normalize(mul(ApplyBoneTransform(input, float4(input.Normal.xyz, 1.0f)), WorldIT)); result.UV = input.UV; result.View = ViewInverse[3] - mul(float4(input.Position.xyz, 1.0f), World); result.Tangent = normalize(mul(ApplyBoneTransform(input, float4(input.Tangent.xyz, 1.0f)), WorldIT).xyz); result.Binormal = normalize(cross(input.Normal, input.Tangent)); return result; } Greets Benjamin
  • Advertisement