I have already loaded vertices, materials, normals, weights, joint IDs, joints themselves and the parent children info (hierarchy), I have also managed to render it all, and when I rotate or translate one of the joints, the children rotate with the parent. My problem is, the parent rotates on a wrong point or offset (hopefully you understand what I mean), this means, that I've gotten the initial offsets wrong, right? To get the start t-pose, I'm guessing I don't need rotation or translation, only the offset of the position of the joint, but I have no clue of how to get it, been stuck for ages. In the Collada file, there is a transform for each joint, I've loaded that one also, but I don't know how to implement it correctly, my 3d model gets deformed and looks wrong. If you answer this question please make it as if you where explaining it to a monkey (me), and step by step if possible, I'm unfamiliar with these bind and inverse bind terms, and very confused. I think that if i manage to get this, I'll eventually figure out the rest of skeletal animation myself, so it's just this little thing.
How do I calculate the start matrix for each bone(t-pose) (using collada and opengl)
1.7k views Asked by Franc Pujolar At
1
There are 1 answers
Related Questions in C++
- How to immediately apply DISPLAYCONFIG_SCALING display scaling mode with SetDisplayConfig and DISPLAYCONFIG_PATH_TARGET_INFO
- Why can't I use templates members in its specialization?
- How to fix "Access violation executing location" when using GLFW and GLAD
- Dynamic array of structures in C++/ cannot fill a dynamic array of doubles in structure from dynamic array of structures
- How do I apply the interface concept with the base-class in design?
- File refuses to compile std::erase() even if using -std=g++23
- How can I do a successful map when the number of elements to be mapped is not consistent in Thrust C++
- Can std::bit_cast be applied to an empty object?
- Unexpected inter-thread happens-before relationships from relaxed memory ordering
- How i can move element of dynamic vector in argument of function push_back for dynamic vector
- Brick Breaker Ball Bounce
- Thread-safe lock-free min where both operands can change c++
- Watchdog Timer Reset on ESP32 using Webservers
- How to solve compiler error: no matching function for call to 'dmhFS::dmhFS()' in my case?
- Conda CMAKE CXX Compiler error while compiling Pytorch
Related Questions in OPENGL
- How to fix "Access violation executing location" when using GLFW and GLAD
- getting Access violation writing location when calling glDrawElements caused by shader
- Experimenting with GLFW library: window boundary problem and normalized coordinates
- OpenGL Framebuffer/FBO RTT subpixel movement discrepancy
- Why isn't my glfw window showing anything?
- How can glPushMatrix affect the rotation of an object around a rotating object?
- g++ / vscode apparently cannot see my src folder? "cc1plus.exe: fatal error: src/glad.c No such file or directory"
- Does addition-assignment cause dependency chain in GLSL?
- Compiling C++ program with Opengl and Glut in windows
- Using Silk.NET in WinForms
- What happens when rendering an OpenGL buffer that has been padded with NULL (or another value)?
- How can I make a sphere follow an eight-like path in Python using OpenGL?
- OpenGL only rendering second triangle, first triangle not visible
- OpenGL shows black texture on quad
- My Visual Studio 2022 consistently gives me errors saying that the GLchar variable type is undefined
Related Questions in MATRIX
- Setting diagonal of a matrix to zero
- CUDA matrix inversion
- Function to create matrix of zeros and ones, with a certain density of ones
- DirectX 9 With No SDK Installed - How To Translate a D3DMATRIX?
- Using the sympy module to compute the matrix multiplication involving symbols
- Rendering a visualisation of matrix using pygame
- I do not receive iOS push notifications from Element Matrix Notify
- Matrix reconstruction by SVD in tensorflow
- Why does the following code detect this matrix as a non-singular matrix?
- Bound for product of matrices
- iterating through raster bands to perform calculation
- How to make a heatmap and the matrix for it?
- MATLAB: Turn every element of complex matrix into another matrix
- Matrix calculated based on the previous value
- Matlab array of structure
Related Questions in COLLADA
- caollada modell from aframe do not appear when uploaded to server
- Collada dae Model is not displayed Angular 16
- Collada (.dae) only 1st texture is applied on object
- Migrating 3D Project from QT 5.4.0 to QT 6 with QT3D: File Format Recommendations
- ThreeJS ColladaLoader convertUpAxis removed? - Model is flipped/wrongly oriented
- Can you check if there are any errors in the collada (.dae) models that I extracted?
- How to get Bindpose from COLLADA Schema Version 1.4.1?
- How to render an animation stored in a collada file format using Vulkan
- writing Collada object in python
- How to cache three.js Object3D in cache?
- Collada model loaded in Black
- how to receive argument in COLLADA (.dae) file?
- No texture display for 3D models in Google-Earth Pro when using KMZ with networklink to other KMZ (including the model)
- How to extract Data from a COLLADA .dae file with Python?
- ColladaLoader access remote files
Related Questions in SKELETAL-ANIMATION
- Unreal Engine Import Warning "The following bones are missing from the bind pose"
- DirectX12 Problems with skeletal animation and Assimp library
- joints in gltf model bunched together on origin during animation
- Processing raw Mocap data into a Skeletal Joints (BVH)
- Optimizing Animation Saving Speed in Matplotlib
- Scenekit start/stop Skeletal animation of imported USDZ
- How can I create a 2D skeleton using forward kinematics in Fabric.js/JavaScript?
- Unexpected transformationMatrix and offset Matrix with Skeletal Animation
- How to setup bone hierarchy for SCNSkinner from glb data?
- Draw bone for skinned mesh
- OpenGl C++ How to implement lighting for 3D models with skeletal animation
- opengl assimp skeletal node transformation
- Writing to Framebuffer using multiple shaders
- How do I correctly blend between skeletal animations in OpenGL from a walk animation to a run animation?
- Bones rotate around parent - OpenGL Animation/Skinning
Popular Questions
- How do I undo the most recent local commits in Git?
- How can I remove a specific item from an array in JavaScript?
- How do I delete a Git branch locally and remotely?
- Find all files containing a specific text (string) on Linux?
- How do I revert a Git repository to a previous commit?
- How do I create an HTML button that acts like a link?
- How do I check out a remote Git branch?
- How do I force "git pull" to overwrite local files?
- How do I list all files of a directory?
- How to check whether a string contains a substring in JavaScript?
- How do I redirect to another webpage?
- How can I iterate over rows in a Pandas DataFrame?
- How do I convert a String to an int in Java?
- Does Python have a string 'contains' substring method?
- How do I check if a string contains a specific word?
Trending Questions
- UIImageView Frame Doesn't Reflect Constraints
- Is it possible to use adb commands to click on a view by finding its ID?
- How to create a new web character symbol recognizable by html/javascript?
- Why isn't my CSS3 animation smooth in Google Chrome (but very smooth on other browsers)?
- Heap Gives Page Fault
- Connect ffmpeg to Visual Studio 2008
- Both Object- and ValueAnimator jumps when Duration is set above API LvL 24
- How to avoid default initialization of objects in std::vector?
- second argument of the command line arguments in a format other than char** argv or char* argv[]
- How to improve efficiency of algorithm which generates next lexicographic permutation?
- Navigating to the another actvity app getting crash in android
- How to read the particular message format in android and store in sqlite database?
- Resetting inventory status after order is cancelled
- Efficiently compute powers of X in SSE/AVX
- Insert into an external database using ajax and php : POST 500 (Internal Server Error)
I've recently gotten bones, joints and nodes working, so I'll try to explain exactly how I achieved it. Do note, I am using Assimp to import my DAE files, but as far as I know, Assimp doesn't do any processing on the data, so this explanation should directly relate to the data in the Collada file.
I'm just learning all this myself, so I may get things wrong. If I do, anyone, please tell me and I will update this answer accordingly.
Semantics
A mesh is a set of vertices, normals, texture coordinates and faces. The points stored in a mesh are in a bind pose, or a rest pose. This is often, but not always, a T-pose.
A skin is a controller. It refers to a single mesh, and contains the list of bones that will modify that mesh (this is where the bones are stored). You can think of the skin element as the actual model (or part of the model) that will be rendered.
A bone is a flat list of names and associated matrices. There is no hierarchical data here, it is simply a flat list. The hierarchy is provided by the nodes that refer to the bones.
A node, or joint, is a hierarchical data element. They are stored in a hierarchy, with a parent node having zero or more child nodes. A node may be linked to zero or more bones, and may be linked to zero or more skins. There should only be one root node. A joint is the same as a node, so I will refer to joins as nodes.
Do note that nodes and bones are separate. You do not modify a bone to animate your model. Instead, you modify a node, which gets applied to the bone when the model is rendered.
Skin
A skin is the thing you will render. A skin always refers to one single mesh. You can have multiple skins in a DAE file, as part of the same model (or, scene). Sometimes, a model will reuse meshes by transforming them. For instance, you may have a mesh for a single arm, and reuse that arm, mirrored, for the other side of the body. I believe that is what the
bind_shape_matrixvalue of a skin is used for. So far, I haven't used this, and my matrices are always identity, so I cannot speak as to it's usage.Bone
A bone is what applies transformations to your model. You do not modify bones. Instead, you modify the nodes that control the bones. More on this later.
A bone consists of the following:
Name_array)bind_posesarray)vertex_weightselement)weightsarray)Node
A node is a hierarchical data element, describing how the model gets transformed when rendered. You will always start with one root node, and travel up the node tree, applying transforms in sequence. I use a depth-first algorithm for this.
The node tells how the model, skins, and bones should be transformed when rendering or animating.
A node may refer to a skin. This means that skin will be used as part of the render for this model. If you see a node refer to a skin, it gets included when rendering.
A node consists of the following:
sidattribute)transformelement)nodeelements)GlobalInverseTransform Matrix
The
GlobalInverseTransformmatrix is calculated by taking theTransformmatrix of the first node, and inverting it. Simple as that.The Algorithm
Now we can get to the good bits - the actual skinning and rendering.
Calculating a node's LocalTransform
Each node should have a matrix, called the
LocalTransformmatrix. This matrix isn't in the DAE file, but is calculated by your software. It is basically the accumulation of theTransformmatrices of the node, and all its parents.First step is to traverse the node hierarchy.
Start at the first node, and calculate the
LocalTransformfor the node, using theTransformmatrix of the node, and theLocalTransformof the parent. If the node has no parent, use an identity matrix as the parent'sLocalTransformmatrix.Repeat this process recursively for every child node in this node.
Calculating a bone's FinalTransform matrix
Just like a node, a bone should have a
FinalTransformmatrix. Again, this is not stored in the DAE file, it is calculated by your software as part of the render process.For each mesh used, for each bone in that mesh, apply the following algorithm:
We now have the
FinalTransformmatrix for each bone in the model.Calculating a vertex's position
Once we have all the bones calculated, we can then transform the mesh's points into their final render locations. This is the algorithm I use. This is not the "correct" way to do this, as it should be calculated by a vertex shader on-the-fly, but it works to demonstrate what's happening.
This should get you a correctly rendered output.
Note that with this system, it is possible to re-use a mesh more than once.
Animating
Just a quick note on animating. I haven't done much with this, and Assimp hides much of the gory details of Collada (and introduces its own form of gore), but to use predefined animations from your file, you do some interpolation of translations, rotations and scales to come up with a matrix that represents a node's animated state at as single point in time.
Remember, matrix construction follows the TRS (translate, rotate, scale) convention, where translations happen first, then rotations, then scale.
The generated matrix completely replaces the node's Transform matrix - it is not combined with the matrix.
I am still trying to work out how to perform on-the-fly animation (think Inverse Kinematics) correctly. For some models I try, it works great. I can apply a quaternion to the node’s Transform matrix and it will work. However, some other models will do strange things, like rotate the node around the origin, so I think I’m still missing something there. If I finally solve this, I will update this section to reflect what I discover.
Hope this helps. If I've missed anything, or gotten anything wrong, anyone please feel free to correct me. I am only learning this stuff myself. If I notice any mistakes, I will edit the answer.
Also, be aware that I use Direct3D, so my matrix multiplication order is probably reversed from yours. You will likely need to flip the multiplication order of some of the operations in my answer.