Hi,
I'm using the latest version of Assimp and Assimp.Net 3.0 release.
After Importing I'm getting the model rotated by 90 degrees.
Any suggestions on what I'm missing?
Have you used the transformation matrix of the root node?
Hi Kim, thanks for your prompt answer. I'll post the processing function. The first call is for model.RootNode, where the model is the imported model.
public GameObject processNodes(Assimp.Node rootNode) {
GameObject unityRoot = new GameObject( rootNode.Name );
if ( rootNode.HasChildren ) {
foreach ( Assimp.Node childNode in rootNode.Children ) {
GameObject unityChild = processNodes( childNode );
unityChild.transform.parent = unityRoot .transform;
}
}
Assimp.Vector3D position, scaling;
Assimp.Quaternion rotation;
rootNode.Transform.Decompose( out scaling, out rotation, out position );
unityRoot.transform.localPosition = new Vector3( position.X, position.Y, position.Z );
unityRoot.transform.localRotation = new UnityEngine.Quaternion( rotation.X, rotation.Y, rotation.Z, rotation.W );
unityRoot.transform.localScale = new Vector3( scaling.X, scaling.Y, scaling.Z );
}
Hm, which loader are you using. Maybe there is something wrong. Your code looks fine for me.
I'm trying to load an fbx model with Assimp in Unity. And I'm sorry, there was a little mistake in my first question, I have edited it. Actually I'm using Assimp.Net version 3.0, because with the latest release of it or the code from the master branch an exception is thrown at the file importing step.
AssimpImporter importer = new AssimpImporter();
MeshVertexLimitConfig m = new MeshVertexLimitConfig (meshVertexLimit);
importer.SetConfig (m);
Scene model = importer.ImportFile(path + '/' + modelName,
PostProcessSteps.SplitLargeMeshes |
PostProcessSteps.OptimizeGraph |
PostProcessSteps.OptimizeMeshes |
PostProcessSteps.Triangulate |
PostProcessSteps.SortByPrimitiveType |
PostProcessPreset.TargetRealTimeMaximumQuality
);
Hi @kimkulling ,
I have found some points about the issue. My exported model has Z-up axis, instead of Y-up axis (unlike assimp), that's why the model is rotated. Is there a way I can get that info from the model (how the axises are set up in the model)?
Thanks.
Up-axis usually taken from file format specification. Or from description of a camera if scene is contain it.
Also you must pay attention to your graphics library. For example - OpenGL by default has Y-up axis.
Hey I have a similar issue but annoyingly everything LOOKS fine when imported, but the Armature itself when I peek at the code is rotated by 90 degrees, this means when I try to get the world space coordinates of the bones, all non-root bones have the Y and Z columns flipped and with the wrong sign.
I think Assimp may be applying the wrong transform to mRootNode. Isn't a scene-level, root node transform supposed to be identity? Here's my debug output for scene->mRootNode->mTransform for a Z_UP COLLADA file containing two sibling boxes at the scene level:
(1.000000, 0.000000, 0.000000, 0.000000)
(0.000000, 0.000000, -1.000000, 0.000000)
(0.000000, 1.000000, 0.000000, 0.000000)
(0.000000, 0.000000, 0.000000, 1.000000)
Inside the COLLADA file, the only transform matricies specified are on the boxes themselves, not on the scene node, so I expected this to be an identity mat4. If I manually do scene->mRootNode->mTransformation = aiMatrix4x4(); before processing the tree, everything works as intended. If this isn't supposed to be an identity matrix, what is it?
I can send the COLLADA file if it assists in reproducing the (possible) issue.
@ne0ndrag0n I think its because whatever program you used uses different coordinates; its similar I think to my problem above; for me, blender is Z up and Y forward; but when imported it's rotated 90 degrees if I don't have "Experimental apply transforms" enabled.
Similarly I get problems with the Blender bone orientations; depending on their bone roll ASSIMP doesn't import them in properly.
Any chance to get the Collada model? And sorry for my late response!
Kim
Had the same issue when loading a model into opengl based C++ engine. Flipping Y and Z coordinates on load solved the problem for me.
@ruzannakamalyan @kimkulling I just came across the same issue. A model (fbx) that is correctly rotated when dragging into Unity's project folder structure is rotated 90 degree around the x axis relative to its coordinate system when imported through TriLib. When I do the following in the AssetLoader.cs (703) its correct, but since it depends on the model I can't do that:
unityVertices[v] = AssimpInterop.aiMesh_GetVertex(mesh, v);
unityVertices[v] = Matrix4x4.Rotate(Quaternion.Euler(-90, 0, 0)) * unityVertices[v];
Since this is an AssimpInterop call (native) I don't even know how to fix that.
Did you guys have a solution for this, implemented or recommended or anything?
I also am currently facing this issue. Is there any solution? Other than manually fixing matrix while parsing? I am using aiProcess_MakeLeftHanded, since I am using DirectX. however, its still rotated sideways. You would have to flip the y, and z axis, but internally it might be calculating using wrong rotation.
I am using blender exporting to collada.
I was pretty sure that this one should be fixed already. But unfortunately it seems to be still there.
I encountered a strange version of this bug where only the mesh y and z are swapped, the skeleton is properly oriented.
The model is a collada file, that seemingly got exported from Max. It can be found here:
https://www.models-resource.com/wii_u/supersmashbrosforwiiu/model/11907/
The flags I used to import the model are:
[:JoinIdenticalVertices, :CalcTangentSpace, :FlipWindingOrder, :Triangulate, :FlipUVs]
(from my ruby bindings)
I would add that, though the model is facing upwards in blender, the skeleton is aligned to the model.
@kimkulling I guess the error is caused because the root node is transformed when a different Y axis value is found, but the application that loads the model isn't aware of this orientation and reset the root node rotation according the values user passes. I've fixed it in TriLib by adding a new node on the top of the root node, to mantain the original matrix.
I'm having the same issue using latest assimp code built from source in git. The problem shows up in open3dmod too - in both cases the object is on its side.
But if I open the same file in Blender (2.79 or 2.80b) or in the Windows 3D file viewer, it is oriented properly.
File is attached.
Edit: I also imported it into UE4 and uploaded it to https://viewer.autodesk.com and they also show it oriented as expected.
encountering the same issue with Assimp.Net (3) (also loading via Unity), when I perform -90 rotation to correct for YZ flip.
To solve I have to flip each vectors X-Axis manually, and also apply reverse winding order.
(winding order to fix faces becoming inverted).
This also requires me to invert my normals manually as well.
This seems like a matrix issue within assimp.
Unity Workaround (Assimp.Net) (assumes you dont need tangents, you you can just flip X axis there too), you do not need to adjust UVs.
// Per Vertex:
#if ASSIMP_BUG_WORKAROUND
vert.x = -vert.x;
nrm .x = -nrm.x;
#endif
#if ASSIMP_BUG_WORKAROUND
// Assimp Config (to solve faces flipping and facing inwards)
steps |= PostProcessSteps.FlipWindingOrder;
#endif
I also have this issue on a few models. On these models, this seems to be caused by the"UpAxis" and "FrontAxis" (GlobalSettings) properties not being used. Assimp reads these and saves them, but does not seem to use them for anything. Should these be applied to the root node transform maybe?
I can't find much documentation about "UpAxis" and "FrontAxis", but after some testing I have the impression that:
0 = X
1= Y
2= Z
Example:
GlobalSettings: {
Version: 1000
Properties70: {
P: "UpAxis", "int", "Integer", "",2
P: "UpAxisSign", "int", "Integer", "",1
P: "FrontAxis", "int", "Integer", "",1
P: "FrontAxisSign", "int", "Integer", "",-1
P: "CoordAxis", "int", "Integer", "",0
P: "CoordAxisSign", "int", "Integer", "",1
P: "OriginalUpAxis", "int", "Integer", "",2
P: "OriginalUpAxisSign", "int", "Integer", "",1
.... more...
}
}
Update:
Assimp reads the axis properties (GlobalSettings), and stores them in in the aiScene's metadata.
They can be accessed like this:
int upAxis = 0;
scene->mMetaData->Get<int>("UpAxis", upAxis);
int upAxisSign = 1;
scene->mMetaData->Get<int>("UpAxisSign", upAxisSign);
etc..
Converting the 0,1,2 values to unit vectors vectors (right, up, forward), constructing a matrix from these and multiplying the scene's root node transform by it solved the issue for me.
Creating the matrix:
aiVector3D upVec = upAxis == 0 ? aiVector3D(upAxisSign,0,0) : upAxis == 1 ? aiVector3D(0, upAxisSign,0) : aiVector3D(0, 0, upAxisSign);
aiVector3D forwardVec = frontAxis == 0 ? aiVector3D(frontAxisSign, 0, 0) : frontAxis == 1 ? aiVector3D(0, frontAxisSign, 0) : aiVector3D(0, 0, frontAxisSign);
aiVector3D rightVec = coordAxis == 0 ? aiVector3D(coordAxisSign, 0, 0) : coordAxis == 1 ? aiVector3D(0, coordAxisSign, 0) : aiVector3D(0, 0, coordAxisSign);
aiMatrix4x4 mat(rightVec.x, rightVec.y, rightVec.z, 0.0f,
upVec.x, upVec.y, upVec.z, 0.0f,
forwardVec.x, forwardVec.y, forwardVec.z, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
And then finally, multiply the scene->mRootNode->mTransformation with this matrix.
@kimkulling should this be done automatically, or is it better to leave it up to the developer? It seems like FBXSDK does this automatically.
And here are some test models:
XYZ arrows.zip
To test, open "XYZ arrows ascii.FBX" and modify the axis information (under "GlobalSettings").
If anyone wants to test that their results are correct, you can open the model in FBX Review to compare.
@mlavik1 thanks for your job, works fine
I would say do it automatically makes sense for me. As far as I know previous users encountered the sme problem before.
+1 to that issue. If any1 could add a setting/config where we could specify up/front/right axis and let the system auto convert it to correct axis that would be great!
And if any1 can remove the darn "_$AssimpFbx$_" transform hierarchies for FBX imports that would be a lot of help too... half of my data import out of wack :- )
+1 to this issue.
+1 would kill for a real fix
+1, guys it's been over 4 years since it was opened..
Most helpful comment
Update:
Assimp reads the axis properties (GlobalSettings), and stores them in in the aiScene's metadata.
They can be accessed like this:
etc..
Converting the 0,1,2 values to unit vectors vectors (right, up, forward), constructing a matrix from these and multiplying the scene's root node transform by it solved the issue for me.
Creating the matrix:
And then finally, multiply the
scene->mRootNode->mTransformationwith this matrix.@kimkulling should this be done automatically, or is it better to leave it up to the developer? It seems like FBXSDK does this automatically.