Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 5 of 5

Thread: How to rotate a local oriented object by the global lookat axis?

  1. #1
    Junior Member Newbie
    Join Date
    Feb 2014
    Posts
    17

    How to rotate a local oriented object by the global lookat axis?

    For example, in blender, I have a rigged mesh where each bone has a local orientation.

    However when I rotate the bone imported to an OpenGL application for Skinning/Animations, if I do glm::rotate(angle, axis); the rotation is along it's "local" axis from within Blender, and not according to the "global" Z axis of my View.

    Using glm, how would I rotate it so it appears to be rotating about an orthogonal point in my screen instead of about it's local axis?

    Does this make sense?

    Example:



    In red, is a rotation I "want", it just happens that the original roll of the Head bone is oriented so it "appears" correct, but if I were to rotate the Mesh then obviously the bone will not rotate in the correct way as it is still rotating along it's local z.

    The arm bone in yellowish green, rotates along it's local z as well.

    Basically I would want the arm rotation, to be like the head rotation. Facing the camera.

    Code :
    	glm::mat4 CurrentNodeTransform;
    	CopyaiMat(&this->getScene()->mRootNode->FindNode(boneName.c_str())->mTransformation, CurrentNodeTransform);
     
    	//glm::mat4 newRotation = glm::rotate(angle, glm::vec3(axis.x, axis.y, axis.z));
    	glm::mat4 newRotation = glm::rotate(angle, glm::vec3(0.0, 0.0, 1.0));
     
    	// NEED GLOBAL ROTATION
    	//CurrentNodeTransform = newRotation * CurrentNodeTransform;
    	CurrentNodeTransform = (CurrentNodeTransform * newRotation);
     
    	CopyGlMatToAiMat(CurrentNodeTransform, this->getScene()->mRootNode->FindNode(boneName.c_str())->mTransformation);

    Basically I fetch the local rotation of the joint, rotate it, and apply it back to the heirarchy of the rig.

    How would I get it so it matches the axis of the "View"?

  2. #2
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,926
    Quote Originally Posted by RaenirSalazar View Post
    Using glm, how would I rotate it so it appears to be rotating about an orthogonal point in my screen instead of about it's local axis?
    Obtain the transformation from bone space to view space (i.e. the view transformation multiplied by the global bone transformation). Invert it to get the transformation from view space to bone space. Transform the vector (0,0,1,0) by the inverse to get the bone-space rotation axis.

  3. #3
    Junior Member Newbie
    Join Date
    Feb 2014
    Posts
    17
    I tried this:

    Code :
    	glm::mat4 BoneToView = View * CurrentNodeTransform;
    	glm::mat4 BoneToViewInverse = glm::inverse(BoneToView);
    	glm::vec4 BoneSpaceRotationAxis = BoneToViewInverse * glm::vec4(0, 0, 1, 0);
    	glm::mat4 newRotation = glm::rotate(angle, glm::vec3(BoneSpaceRotationAxis));
     
    	CurrentNodeTransform = CurrentNodeTransform * newRotation;

    And doesn't appear to work, I'll swap around the multiplications in case I got the order wrong. Did you mean something else by "Transform the vector (0,0,1,0) by the inverse to get the bone-space rotation axis." then multiplying it?

    e: For example trying to rotate the Leg; I get {0, -0.99, 0.1} (rounding down slightly) as the resulting axis of rotation, but still appears to rotate about it's Y axis, do I need to normalize it?

    Oh and just in case I'll also go and reexport my model in case I was playing with the Bone rolls.

    result:


    The rotations still seem relative to their Y (lengthwise) axis.
    Last edited by RaenirSalazar; 10-27-2016 at 09:44 AM.

  4. #4
    Junior Member Newbie
    Join Date
    Feb 2014
    Posts
    17

    This is with glm::vec4(0, 1, 0, 0); as the vector I am multiplying BoneToViewInverse by.

    Circles are if it's rotating as though it were facing the screen, lines otherwise to show that its rotating about that line.

  5. #5
    Junior Member Newbie
    Join Date
    Feb 2014
    Posts
    17
    Got it.

    Code :
    glm::mat4 LocalNodeTransform;
    glm::mat4 GlobalNodeTransform;
    CopyaiMat(&this->getScene()->mRootNode->FindNode(boneName.c_str())
    ->mTransformation, LocalNodeTransform);
    FindBone(boneName, this->getScene()->mRootNode, glm::mat4(1.0), GlobalNodeTransform);
    //glm::mat4 newRotation = glm::rotate(angle, glm::vec3(axis.x, axis.y, axis.z));
     
     
    glm::mat4 View = glm::lookAt(
        glm::vec3(0, 0, 1), // Camera in World Space
        glm::vec3(0, 0, 0), // and looks at 
        glm::vec3(0, 1, 0)  // Head is up (set to 0,-1,0 to look upside-down)
        );
     
    // NEED GLOBAL ROTATION
    //CurrentNodeTransform = newRotation * CurrentNodeTransform;
    //CurrentNodeTransform = (CurrentNodeTransform * newRotation);
     
    glm::mat4 BoneToView = GlobalNodeTransform * View;
    glm::mat4 BoneToViewInverse = glm::inverse(BoneToView);
    glm::vec4 BoneSpaceRotationAxis = BoneToViewInverse * glm::vec4(0, 0, 1, 0);
    printf("Printing BoneSpaceRotationAxis");
    PrintVector3(glm::normalize(BoneSpaceRotationAxis));
    glm::mat4 newRotation = glm::rotate(angle, 
    glm::normalize(glm::vec3(BoneSpaceRotationAxis)));
     
    LocalNodeTransform = LocalNodeTransform * newRotation;
     
    CopyGlMatToAiMat(LocalNodeTransform, this->getScene()->mRootNode->
    FindNode(boneName.c_str())->mTransformation);

    Somehow I screwed up that second to last line.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •