Sign in to follow this  
Misantes

OpenGL OpenGl translating with quaternion based view/camera

Recommended Posts

Alright, first let me promise this will be the last thread on quaternions I will make tongue.png Also, I would usually post this in the beginners section, but it feels a little out of place there, so mods, please feel free to relocate this if it does indeed belong there. But, that said, I am rather new to OpenGL, so please keep that mind when responding (you're of course welcome to respond however you'd like, but I'm much less likely to understand it smile.png)

 

So, I'm able to successfully rotate the Camera around using quaternions. Where I'm running into difficulties is moving the Camera around the worldspace (or the worldspace around the camera). To clarify, so there is less confusion(I'm rather new and I'll certainly misuse opengl nomenclature in this post, but I'll try to be clear) when I say camera I mean a View matrix in a matrix:

glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;

The biggest issue I've had is that translating by the quaterion or quaternion-based matrix seems to not produce the results I'm going for, as often the axis I'm trying to move along will be represented by a zero in the quaternion and therefore translates by zero when multiplied by a vector (if my math is correct, which it may not be). I'm probably explaining this poorly, so to illustrate, imagine I'm "rolling" the view matrix by rotating along the Z axis. If I try translating by glm::vec3(0,0,10) everything will seemingly work and I'll move forward in the world(or the world backward, whichever). However, any time the quaternion is not rotating along the Z axis(say, I'm rotating the camera to the left, along the X axis), if I try translating by the same glm::vec3(0,0,10), it will of course not move forward (I'm assuming again, that it's because it's now multiplying the vector.z by zero).

 

What I've tried doing so far is rotating the view matrix around using the quaternion-based matrix, but translating the models/world in the ModelMatrix. This works great, except of course they will not translate in the direction I'm trying to translate in, as they're being moved in world space rather than the camera space. If I rotate them first, then translate, this works better, but suffers from the same problem mentioned above, where if it's not along the Z axis, it won't translate in the Z axis direction.

 

I've tried, instead of translating by a vector of (0,0,10) to something like (10,10,10), which doesn't work, because it now translates on the axis I'm rotating on (i.e. moving up when I'm rotating left, etc, which makes total sense in hindsight).

 

I've also tried translating instead in the ViewMatrix and then translating and rotating the models in the ModelMatrix, but they rotate around the world center instead of the ViewMatrix center. If I had to guess(and I'm certain you'll correct me if I'm wrong), I think this is probably the direction I need to head in, but I need to rotate them around the location of the "camera." But, I'm having difficulty implementing this.

 

I've tried rotating in the ViewMatrix, and then for the ModelMatrix rotating, translating, then rotating back using the conjugate of the original quaternion, but had really weird outcomes as well. It's possible I'm using the conjugate wrong, or ordering things incorrectly when using it.

 

Anyhow, I've tried dozens of other things which all haven't worked for various (in hindsight, obvious) reasons. I'm feeling a little on the discouraged side, but thought I would ask here at this point.

 

Here is some relevant code. Please forgive any spaghettiness as I've redone it a hundred times, and much of it is just a hacky-workaround to try to debug exactly what it's doing. I've left it in it's current ugly condition, so as to not accidentally delete what may actually be the problem. I'll of course clean it up once it's working.

//generation of the quaternion. axisX, axisY etc are passed in on keypresses. For clarity, this is always
//a "1.f" on keypress. I.e. on keypress "A", the axisY would be "1". They're reset to zero at the beginning of this function if key isn't still pressed.
    
   if(axisZ != 0 ||  axisX != 0 || axisY != 0 )//workaround to be able to move forward for debugging purposes
    {
        rotQuat = glm::quat(angleIn, axisX, axisY, axisZ);
    }
    else
    {
        rotQuat = glm::quat(angleIn, axisX, axisY, 1);
    }
     /*below is workaround to handle multiple axis rotation. There's probably a better way, but
    I'm still in  the process of learning/implementing that*/

    glm::quat quatx = glm::quat(angleInx, axisX, 0, 0);
    glm::quat quaty = glm::quat(angleInx, 0, axisY, 0);
    glm::quat quatz = glm::quat(angleInx, 0, 0, axisZ);

    if(axisY != 0 && axisX != 0)
      {
       rotQuat = glm::mix(quatx, quaty, .5f);
      }
    else if(axisZ != 0 && axisY != 0)
      {
       rotQuat = glm::mix(quaty, quatz, .5f);
      }
    else if(axisZ != 0 && axisX != 0)
      {
       rotQuat = glm::mix(quatx, quatz, .5f);
      }

    glm::mat4 RotationMatrix = mat4_cast(rotQuat);
    //movement below is a glm::vec3(0,0,1), usually.
    ViewMatrix =  glm::translate(movement)*RotationMatrix* ViewMatrix;
   //ModelMatrix = glm::RotationMatrix * ModelMatrix; //this and viewmatrix above are often changed trying to solve this. Don't take them too literally here, as they're the likely culprit.
    SkyboxViewMatrix = RotationMatrix * SkyboxViewMatrix;

With the above workarounds, I can rotate, then move, but, I can't rotate and move. This makes for a pretty unpleasant control scheme.

 

Anyhow, I'm certainly going about this the wrong way, but I'm uncertain where. It's possible in multiple places tongue.png. It's likely I learned how to translate things about incorrectly in the first place, and it's just now biting me. I had no difficulty in translating things when using Euler angles, but my rotations were wrong (I'm building a silly space sim). But, now using quaternions, things are rotating better, but I'm having this current problem.

 

Let me know if you need any other information. And, to those of you who helped me with my initial quaternion mess, feel free to sit this one out smile.png You're welcome to contribute, but I don't want to overtax anyone. I'm new here, and you've been a great community, and I don't want to overstep with too many inane questions (I think this is number 3 in the last two months).

 

Thanks in advance, and cheers smile.png

 

Misantes

Edited by Misantes

Share this post


Link to post
Share on other sites

Alright, so I've found that multiplying a quaternion-based matrix before the rotation matrix and then the translation afterward the RotationMatrix will make it so that the camera keeps translating while rotating, but this seems like a very inelegant solution, and I'm guessing still not the correct way to be going about this. So, technically, things seem to be working, but I'm still open to learning the proper way if anyone has some insights to this.

 

Here's what the workaround looks like now:

    if(glfwGetKey( window, GLFW_KEY_A ) == GLFW_PRESS || glfwGetKey( window, GLFW_KEY_D ) == GLFW_PRESS)
    {
        glm::quat movequat = glm::quat(0,0,1,0);
        glm::mat4 movequatM = mat4_cast(movequat);
        ViewMatrix = translationMatrix * RotationMatrix * movequatM * ViewMatrix;
    }


    else if(glfwGetKey( window, GLFW_KEY_W ) == GLFW_PRESS || glfwGetKey( window, GLFW_KEY_S ) == GLFW_PRESS)
    {
        glm::quat movequat = glm::quat(0,1,0,0);
        glm::mat4 movequatM = mat4_cast(movequat);
        ViewMatrix = translationMatrix * RotationMatrix * movequatM * ViewMatrix;
    }

    else
    {
        glm::quat movequat = glm::quat(0,0,0,1);
        glm::mat4 movequatM = mat4_cast(movequat);
        ViewMatrix = translationMatrix * RotationMatrix * movequatM * ViewMatrix;
    }

 

This seems to fix the multiplying by zero, but again, doesn't feel right (I seem to just be multiplying the rotation matrix by itself, but with no angle). Am I creating the RotationMatrix incorrectly, perhaps, and that's why this workaround is necessary? Anyhow, I'm going wrong somewhere in here, but uncertain where. I'd welcome any help.

Thanks again in advance, smile.png

 

edit* ack, and I didn't mean to bump my own thread, my first post just seemed so long, it felt weird adding to it, and I forgot it would bump it >,< won't happen again.

Edited by Misantes

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Announcements

  • Forum Statistics

    • Total Topics
      628359
    • Total Posts
      2982259
  • Similar Content

    • By test opty
      Hi all,
       
      I'm starting OpenGL using a tut on the Web. But at this point I would like to know the primitives needed for creating a window using OpenGL. So on Windows and using MS VS 2017, what is the simplest code required to render a window with the title of "First Rectangle", please?
       
       
    • By DejayHextrix
      Hi, New here. 
      I need some help. My fiance and I like to play this mobile game online that goes by real time. Her and I are always working but when we have free time we like to play this game. We don't always got time throughout the day to Queue Buildings, troops, Upgrades....etc.... 
      I was told to look into DLL Injection and OpenGL/DirectX Hooking. Is this true? Is this what I need to learn? 
      How do I read the Android files, or modify the files, or get the in-game tags/variables for the game I want? 
      Any assistance on this would be most appreciated. I been everywhere and seems no one knows or is to lazy to help me out. It would be nice to have assistance for once. I don't know what I need to learn. 
      So links of topics I need to learn within the comment section would be SOOOOO.....Helpful. Anything to just get me started. 
      Thanks, 
      Dejay Hextrix 
    • By mellinoe
      Hi all,
      First time poster here, although I've been reading posts here for quite a while. This place has been invaluable for learning graphics programming -- thanks for a great resource!
      Right now, I'm working on a graphics abstraction layer for .NET which supports D3D11, Vulkan, and OpenGL at the moment. I have implemented most of my planned features already, and things are working well. Some remaining features that I am planning are Compute Shaders, and some flavor of read-write shader resources. At the moment, my shaders can just get simple read-only access to a uniform (or constant) buffer, a texture, or a sampler. Unfortunately, I'm having a tough time grasping the distinctions between all of the different kinds of read-write resources that are available. In D3D alone, there seem to be 5 or 6 different kinds of resources with similar but different characteristics. On top of that, I get the impression that some of them are more or less "obsoleted" by the newer kinds, and don't have much of a place in modern code. There seem to be a few pivots:
      The data source/destination (buffer or texture) Read-write or read-only Structured or unstructured (?) Ordered vs unordered (?) These are just my observations based on a lot of MSDN and OpenGL doc reading. For my library, I'm not interested in exposing every possibility to the user -- just trying to find a good "middle-ground" that can be represented cleanly across API's which is good enough for common scenarios.
      Can anyone give a sort of "overview" of the different options, and perhaps compare/contrast the concepts between Direct3D, OpenGL, and Vulkan? I'd also be very interested in hearing how other folks have abstracted these concepts in their libraries.
    • By aejt
      I recently started getting into graphics programming (2nd try, first try was many years ago) and I'm working on a 3d rendering engine which I hope to be able to make a 3D game with sooner or later. I have plenty of C++ experience, but not a lot when it comes to graphics, and while it's definitely going much better this time, I'm having trouble figuring out how assets are usually handled by engines.
      I'm not having trouble with handling the GPU resources, but more so with how the resources should be defined and used in the system (materials, models, etc).
      This is my plan now, I've implemented most of it except for the XML parts and factories and those are the ones I'm not sure of at all:
      I have these classes:
      For GPU resources:
      Geometry: holds and manages everything needed to render a geometry: VAO, VBO, EBO. Texture: holds and manages a texture which is loaded into the GPU. Shader: holds and manages a shader which is loaded into the GPU. For assets relying on GPU resources:
      Material: holds a shader resource, multiple texture resources, as well as uniform settings. Mesh: holds a geometry and a material. Model: holds multiple meshes, possibly in a tree structure to more easily support skinning later on? For handling GPU resources:
      ResourceCache<T>: T can be any resource loaded into the GPU. It owns these resources and only hands out handles to them on request (currently string identifiers are used when requesting handles, but all resources are stored in a vector and each handle only contains resource's index in that vector) Resource<T>: The handles given out from ResourceCache. The handles are reference counted and to get the underlying resource you simply deference like with pointers (*handle).  
      And my plan is to define everything into these XML documents to abstract away files:
      Resources.xml for ref-counted GPU resources (geometry, shaders, textures) Resources are assigned names/ids and resource files, and possibly some attributes (what vertex attributes does this geometry have? what vertex attributes does this shader expect? what uniforms does this shader use? and so on) Are reference counted using ResourceCache<T> Assets.xml for assets using the GPU resources (materials, meshes, models) Assets are not reference counted, but they hold handles to ref-counted resources. References the resources defined in Resources.xml by names/ids. The XMLs are loaded into some structure in memory which is then used for loading the resources/assets using factory classes:
      Factory classes for resources:
      For example, a texture factory could contain the texture definitions from the XML containing data about textures in the game, as well as a cache containing all loaded textures. This means it has mappings from each name/id to a file and when asked to load a texture with a name/id, it can look up its path and use a "BinaryLoader" to either load the file and create the resource directly, or asynchronously load the file's data into a queue which then can be read from later to create the resources synchronously in the GL context. These factories only return handles.
      Factory classes for assets:
      Much like for resources, these classes contain the definitions for the assets they can load. For example, with the definition the MaterialFactory will know which shader, textures and possibly uniform a certain material has, and with the help of TextureFactory and ShaderFactory, it can retrieve handles to the resources it needs (Shader + Textures), setup itself from XML data (uniform values), and return a created instance of requested material. These factories return actual instances, not handles (but the instances contain handles).
       
       
      Is this a good or commonly used approach? Is this going to bite me in the ass later on? Are there other more preferable approaches? Is this outside of the scope of a 3d renderer and should be on the engine side? I'd love to receive and kind of advice or suggestions!
      Thanks!
    • By nedondev
      I 'm learning how to create game by using opengl with c/c++ coding, so here is my fist game. In video description also have game contain in Dropbox. May be I will make it better in future.
      Thanks.
  • Popular Now