• Advertisement
  • Popular Tags

  • Popular Now

  • Advertisement
  • Similar Content

    • By fleissi
      Hey guys!

      I'm new here and I recently started developing my own rendering engine. It's open source, based on OpenGL/DirectX and C++.
      The full source code is hosted on github:
      https://github.com/fleissna/flyEngine

      I would appreciate if people with experience in game development / engine desgin could take a look at my source code. I'm looking for honest, constructive criticism on how to improve the engine.
      I'm currently writing my master's thesis in computer science and in the recent year I've gone through all the basics about graphics programming, learned DirectX and OpenGL, read some articles on Nvidia GPU Gems, read books and integrated some of this stuff step by step into the engine.

      I know about the basics, but I feel like there is some missing link that I didn't get yet to merge all those little pieces together.

      Features I have so far:
      - Dynamic shader generation based on material properties
      - Dynamic sorting of meshes to be renderd based on shader and material
      - Rendering large amounts of static meshes
      - Hierarchical culling (detail + view frustum)
      - Limited support for dynamic (i.e. moving) meshes
      - Normal, Parallax and Relief Mapping implementations
      - Wind animations based on vertex displacement
      - A very basic integration of the Bullet physics engine
      - Procedural Grass generation
      - Some post processing effects (Depth of Field, Light Volumes, Screen Space Reflections, God Rays)
      - Caching mechanisms for textures, shaders, materials and meshes

      Features I would like to have:
      - Global illumination methods
      - Scalable physics
      - Occlusion culling
      - A nice procedural terrain generator
      - Scripting
      - Level Editing
      - Sound system
      - Optimization techniques

      Books I have so far:
      - Real-Time Rendering Third Edition
      - 3D Game Programming with DirectX 11
      - Vulkan Cookbook (not started yet)

      I hope you guys can take a look at my source code and if you're really motivated, feel free to contribute :-)
      There are some videos on youtube that demonstrate some of the features:
      Procedural grass on the GPU
      Procedural Terrain Engine
      Quadtree detail and view frustum culling

      The long term goal is to turn this into a commercial game engine. I'm aware that this is a very ambitious goal, but I'm sure it's possible if you work hard for it.

      Bye,

      Phil
    • By tj8146
      I have attached my project in a .zip file if you wish to run it for yourself.
      I am making a simple 2d top-down game and I am trying to run my code to see if my window creation is working and to see if my timer is also working with it. Every time I run it though I get errors. And when I fix those errors, more come, then the same errors keep appearing. I end up just going round in circles.  Is there anyone who could help with this? 
       
      Errors when I build my code:
      1>Renderer.cpp 1>c:\users\documents\opengl\game\game\renderer.h(15): error C2039: 'string': is not a member of 'std' 1>c:\program files (x86)\windows kits\10\include\10.0.16299.0\ucrt\stddef.h(18): note: see declaration of 'std' 1>c:\users\documents\opengl\game\game\renderer.h(15): error C2061: syntax error: identifier 'string' 1>c:\users\documents\opengl\game\game\renderer.cpp(28): error C2511: 'bool Game::Rendering::initialize(int,int,bool,std::string)': overloaded member function not found in 'Game::Rendering' 1>c:\users\documents\opengl\game\game\renderer.h(9): note: see declaration of 'Game::Rendering' 1>c:\users\documents\opengl\game\game\renderer.cpp(35): error C2597: illegal reference to non-static member 'Game::Rendering::window' 1>c:\users\documents\opengl\game\game\renderer.cpp(36): error C2597: illegal reference to non-static member 'Game::Rendering::window' 1>c:\users\documents\opengl\game\game\renderer.cpp(43): error C2597: illegal reference to non-static member 'Game::Rendering::window' 1>Done building project "Game.vcxproj" -- FAILED. ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========  
       
      Renderer.cpp
      #include <GL/glew.h> #include <GLFW/glfw3.h> #include "Renderer.h" #include "Timer.h" #include <iostream> namespace Game { GLFWwindow* window; /* Initialize the library */ Rendering::Rendering() { mClock = new Clock; } Rendering::~Rendering() { shutdown(); } bool Rendering::initialize(uint width, uint height, bool fullscreen, std::string window_title) { if (!glfwInit()) { return -1; } /* Create a windowed mode window and its OpenGL context */ window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL); if (!window) { glfwTerminate(); return -1; } /* Make the window's context current */ glfwMakeContextCurrent(window); glViewport(0, 0, (GLsizei)width, (GLsizei)height); glOrtho(0, (GLsizei)width, (GLsizei)height, 0, 1, -1); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glfwSwapInterval(1); glEnable(GL_SMOOTH); glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glEnable(GL_TEXTURE_2D); glLoadIdentity(); return true; } bool Rendering::render() { /* Loop until the user closes the window */ if (!glfwWindowShouldClose(window)) return false; /* Render here */ mClock->reset(); glfwPollEvents(); if (mClock->step()) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glfwSwapBuffers(window); mClock->update(); } return true; } void Rendering::shutdown() { glfwDestroyWindow(window); glfwTerminate(); } GLFWwindow* Rendering::getCurrentWindow() { return window; } } Renderer.h
      #pragma once namespace Game { class Clock; class Rendering { public: Rendering(); ~Rendering(); bool initialize(uint width, uint height, bool fullscreen, std::string window_title = "Rendering window"); void shutdown(); bool render(); GLFWwindow* getCurrentWindow(); private: GLFWwindow * window; Clock* mClock; }; } Timer.cpp
      #include <GL/glew.h> #include <GLFW/glfw3.h> #include <time.h> #include "Timer.h" namespace Game { Clock::Clock() : mTicksPerSecond(50), mSkipTics(1000 / mTicksPerSecond), mMaxFrameSkip(10), mLoops(0) { mLastTick = tick(); } Clock::~Clock() { } bool Clock::step() { if (tick() > mLastTick && mLoops < mMaxFrameSkip) return true; return false; } void Clock::reset() { mLoops = 0; } void Clock::update() { mLastTick += mSkipTics; mLoops++; } clock_t Clock::tick() { return clock(); } } TImer.h
      #pragma once #include "Common.h" namespace Game { class Clock { public: Clock(); ~Clock(); void update(); bool step(); void reset(); clock_t tick(); private: uint mTicksPerSecond; ufloat mSkipTics; uint mMaxFrameSkip; uint mLoops; uint mLastTick; }; } Common.h
      #pragma once #include <cstdio> #include <cstdlib> #include <ctime> #include <cstring> #include <cmath> #include <iostream> namespace Game { typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; typedef unsigned long ulong; typedef float ufloat; }  
      Game.zip
    • By lxjk
      Hi guys,
      There are many ways to do light culling in tile-based shading. I've been playing with this idea for a while, and just want to throw it out there.
      Because tile frustums are general small compared to light radius, I tried using cone test to reduce false positives introduced by commonly used sphere-frustum test.
      On top of that, I use distance to camera rather than depth for near/far test (aka. sliced by spheres).
      This method can be naturally extended to clustered light culling as well.
      The following image shows the general ideas

       
      Performance-wise I get around 15% improvement over sphere-frustum test. You can also see how a single light performs as the following: from left to right (1) standard rendering of a point light; then tiles passed the test of (2) sphere-frustum test; (3) cone test; (4) spherical-sliced cone test
       

       
      I put the details in my blog post (https://lxjk.github.io/2018/03/25/Improve-Tile-based-Light-Culling-with-Spherical-sliced-Cone.html), GLSL source code included!
       
      Eric
    • By Fadey Duh
      Good evening everyone!

      I was wondering if there is something equivalent of  GL_NV_blend_equation_advanced for AMD?
      Basically I'm trying to find more compatible version of it.

      Thank you!
    • By Jens Eckervogt
      Hello guys, 
       
      Please tell me! 
      How do I know? Why does wavefront not show for me?
      I already checked I have non errors yet.
      using OpenTK; using System.Collections.Generic; using System.IO; using System.Text; namespace Tutorial_08.net.sourceskyboxer { public class WaveFrontLoader { private static List<Vector3> inPositions; private static List<Vector2> inTexcoords; private static List<Vector3> inNormals; private static List<float> positions; private static List<float> texcoords; private static List<int> indices; public static RawModel LoadObjModel(string filename, Loader loader) { inPositions = new List<Vector3>(); inTexcoords = new List<Vector2>(); inNormals = new List<Vector3>(); positions = new List<float>(); texcoords = new List<float>(); indices = new List<int>(); int nextIdx = 0; using (var reader = new StreamReader(File.Open("Contents/" + filename + ".obj", FileMode.Open), Encoding.UTF8)) { string line = reader.ReadLine(); int i = reader.Read(); while (true) { string[] currentLine = line.Split(); if (currentLine[0] == "v") { Vector3 pos = new Vector3(float.Parse(currentLine[1]), float.Parse(currentLine[2]), float.Parse(currentLine[3])); inPositions.Add(pos); if (currentLine[1] == "t") { Vector2 tex = new Vector2(float.Parse(currentLine[1]), float.Parse(currentLine[2])); inTexcoords.Add(tex); } if (currentLine[1] == "n") { Vector3 nom = new Vector3(float.Parse(currentLine[1]), float.Parse(currentLine[2]), float.Parse(currentLine[3])); inNormals.Add(nom); } } if (currentLine[0] == "f") { Vector3 pos = inPositions[0]; positions.Add(pos.X); positions.Add(pos.Y); positions.Add(pos.Z); Vector2 tc = inTexcoords[0]; texcoords.Add(tc.X); texcoords.Add(tc.Y); indices.Add(nextIdx); ++nextIdx; } reader.Close(); return loader.loadToVAO(positions.ToArray(), texcoords.ToArray(), indices.ToArray()); } } } } } And It have tried other method but it can't show for me.  I am mad now. Because any OpenTK developers won't help me.
      Please help me how do I fix.

      And my download (mega.nz) should it is original but I tried no success...
      - Add blend source and png file here I have tried tried,.....  
       
      PS: Why is our community not active? I wait very longer. Stop to lie me!
      Thanks !
  • Advertisement
  • Advertisement
Sign in to follow this  

OpenGL OpenGL 2.1 Gimbal lock

This topic is 1004 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi everyone; I have this project for school where i need to create a software that manipulates 3D objects , i'm using OpenGL 2.1 along side with SDL 1.2.

I'm now trying to implement some kind of rotation on the objects , this way : The user selects the needed object , once it's done , he can access the rotation mode by hitting "R" , then he hits X ,Y or Z to select the desired rotation axis; at first i went with something like this : 

glrotated(angles.x,1,0,0);
glrotated(angles.y,0,1,0);
glrotated(angles.z,0,0,1);
//Drawing my object

but of course it didn't work; the first rotations worked ok , but then it started to turn around an invisible axis every time ( i think it is the axis of the universe , the global one). Let me show you the video i have taken , to illustrate what i'm saying : 

.

after looking on the net for a while , i found that quaternion could solve my problem ... Here's what my code looks like now :

 

The method that displays my teapot to the screen :

void Teapot::PrintObj()
{
        glLoadName(_NameStack);
        glPushMatrix();
        Translated(axeX,axeY,axeZ);

        RotatedX(angles.x);
        RotatedY(angles.y);
        RotatedZ(angles.z);
    
        glScaled(ObjSize.x,ObjSize.y,ObjSize.z);
glColor3ub(_Color.red,_Color.green,_Color.blue);
glutSolidTeapot(2);

if(_Selected){WiredTeapot();Guizmo();}

        glPopMatrix();
};

the angles.x , angles.y and angles.z are stored within the class ; they are modified by an other method this way :

void Scene::ProjRotation(SDL_MouseMotionEvent &event,int X,int Y,int Z)
{

int a;
int b;
int c;
    for(_compt=_OjebctScene.begin();_compt!=_OjebctScene.end();_compt++)
    {

    if ((*_compt)->IsSelected())
    {
        if(X==1 && Y==0 && Z==0)
                {
                    a=event.y % 360;
                    if(a % 5 == 0)
                    {
                    (*_compt)->setAlpha(a);
                    }

                }
       else if(Y==1 && X==0 && Z==0)
                {
                      b=event.y % 360;
                      if(b % 5 == 0)
                        {
                        (*_compt)->setBeta(b);

                        }
                }
        else if(Z==1 && Y==0 && X==0)
                {
                      c=event.y % 360;
                      if(c % 5 == 0)
                        {
                    (*_compt)->setGamma(c);

                        }
                }

    }
    }
}

the ObjScene vector contains pointers to all the objects on the scene , i first try to find the selected item ; then with an event on the mouse , i send the input to the angles.x , angles.y or angles.z;

 

all of this leads us now to the RotatedX() , RotatedY() and RotatedZ() methods , that are charged with handling the rotation ; here's the code of RotatedX() to show you what i have done :

void Object3D::RotatedX(double angle)
{

rotZ=vector_normalize(rotZ);//I normalize the 3 vectors : rotX , rotY and rotZ are the 3 axis , stored in the class too
rotX=vector_normalize(rotX);
rotY=vector_normalize(rotY);

rotX.x=1;
rotX.y=0;
rotX.z=0;

quaternion Q = make_rotation_quaternion_from_axis_and_angle(rotX,angle);// I create a quaternion based on the axis and angle
quaternion_fill_opengl_rotation_matrix(Q,mat);// i create the equivalent matrix to the quaternion
glm::mat4 RotationMatrix = glm::make_mat4(mat);
glm::vec4 vecRoty = glm::vec4(rotY.x,rotY.y,rotY.z,0)*RotationMatrix ;// i rotate the rotY vector , so next time the rotation won't be done around the (0,1,0) vector , but around the new position of Y;

rotY.x = vecRoty[0];
rotY.y = vecRoty[1];
rotY.z = vecRoty[2];// I update the new value of rotY so it is stored;

rotY=vector_normalize(rotY);// i think this is useless , but just to be cautious

glm::vec4 vecRotz = glm::vec4(rotZ.x,rotZ.y,rotZ.z,0)*RotationMatrix; // same thing with the Z axis , i rotate it to get a rotation around the new position of Z , not the (0,0,1) axis;
rotZ.x = vecRotz[0];
rotZ.y = vecRotz[1];
rotZ.z = vecRotz[2];// I store the new value in rotZ;

rotZ=vector_normalize(rotZ);//same , normalizing rotZ;


glMultMatrixf(mat); // then i apply the rotation to the scene to update the displaying of the teapot

}

i hope all of this is clear for you , i'm just getting started with openGL and had till yesterday no idea about quaternions , i don't know if the algorithm behind my code is wrong , but there's obviously something i am missing.

Share this post


Link to post
Share on other sites
Advertisement


but of course it didn't work; the first rotations worked ok , but then it started to turn around an invisible axis every time ( i think it is the axis of the universe , the global one). Let me show you the video i have taken , to illustrate what i'm saying : 
.

Thing is that a rotation around an axis ever occurs in the global space. You want to rotate around a local space axis. Before any rotation, the local axes are coincident with the global axes, so the first rotation seems to rotate around a local axis. So, if you want to rotate around an axis, compute its co-ordinates in global space and apply it.

 

An example: Without any prior rotation, the sequence

  glrotated(angles.x,1,0,0);

  glrotated(angles.y,0,1,0);
  glrotated(angles.z,0,0,1);
means that the object is first rotated around the x axis which is coincident with the local x axis. The local y and z axes will remain as they are but only in object local space; in any space, especially the global one which is the important one here, those both axes will be altered. Then the rotation around the y axis is applied. At this moment the local y and z axes are no longer co-incident with their global ones. Since rotation occurs around the global axis, you see the effect shown in your video. For the 3rd rotation around the z axis the same principle holds, except that now 2 prior rotations have altered the situation.

 


after looking on the net for a while , i found that quaternion could solve my problem ...

Quaternions do not help against gimbal lock. Well, you are not suffering from gimbal lock either. Your problem is to not understand space transformations.

 

For example: You perform Euler rotation by rotating around the x axis, then rotating around the y axis, then rotating around the z axis, each time with a specific angle. For the next frame you start over, using separately accumulated angles. That's wrong for what you want. You should instead store the current orientation either as rotation matrix or as quaternion, and apply the next partial rotation on top of it. That means to incrementally change orientation without using Euler angles.

 

 

Please ask if you need more support. You know, the forum rules allow to help on homework; they just forbid to give ready-to-use solutions.

Share this post


Link to post
Share on other sites

Thanks a lot for the quick replay biggrin.png .

 

 

 


For example: You perform Euler rotation by rotating around the x axis, then rotating around the y axis, then rotating around the z axis, each time with a specific angle. For the next frame you start over, using separately accumulated angles. That's wrong for what you want. You should instead store the current orientation either as rotation matrix or as quaternion, and apply the next partial rotation on top of it. That means to incrementally change orientation without using Euler angles.

 

So basically , from what i understood , every time i call one of my rotatedX() , rotatedY() or rotatedZ() method , i need to calculate the adequate matrix right ? for example if i'm the rotatedX() function , it means that the angles.x is varying (but here again i'm using angles huh ?) so i need to calculate this matrix :

 

|1     0        0      0|
|0 cos(a) -sin(a) 0|
|0 sin(a) cos(a)  0|
|0      0     0        1|

 

Where a is my angles.x in the case , then i need to just glMultMatrix() this matrix to the stack ?

EDIT : isn't that what already happens when i call the glrotated() ? i don't really understand how i can get rid of the angles by the way :/

Edited by Hdjo

Share this post


Link to post
Share on other sites

The difference is this: ATM you have a triplet of Euler angles in use to store the current orientation. When you want to alter the orientation you change one of the Euler angles. To perform the transformation you call glRotate for each of the current angles. So you compute the current orientation matrix as

     Rn := Z( cn ) * Y( bn ) * X( an )

where X, Y, and Z denote the rotation matrices with the respective axis, the triplet a, b, c denote the Euler angles, and n denotes the current time step index.

 

Now what is suggested is an incremental approach where you remember the orientation from the previous step and advance it accordingly to the currently selected axis and angle, like so

    Rn := D( pn, dn ) * Rn-1  w/  R0 := I

where D denotes the delta rotation computed from the current axis of rotation pn and the current delta angle of rotation dn. In this approach you do not have the Euler angles anymore. Notice that the formerly used orientation matrix Rn-1 plays a role.

 

 

Notice please that the above solution of incremental rotation has an accuracy problem. The more steps are done (i.e. the higher the n) the more will the orientation matrix differ from a proper rotation transform. That is because in the matrix you have 9 variables for the rotation while only 3 are needed to express the rotation. Hence you need 6 constraints. These are known as pairwise orthogonality and unit length for each of the 3 column/row vectors in the matrix. So, from time to time you need to re-orthonormalize the matrix. There are standard methods to do so. At this point using a quaternion instead of a rotation matrix has an advantage. A quaternion has 4 variables only, which gives a higher numerical stability. Well, if you may have noticed, also a quaternion must have a problem because it has 4 variables although only 3 are needed. And yes, there is also a constraint for quaternions: It must be of unit length (so only the sub-class of so-called unit-quaternions are useful for us here). But this constraint is easier to maintain than the orthonormalization is. On the other hand, doing all the math with quaternion is not easy either. So I suggest you to first go with matrices.

Edited by haegarr

Share this post


Link to post
Share on other sites

i wrote this bit of code based on what you said (or based on what i understood to be more precise :P )

void Object3D::RotatedX(double angle)
{
float mat[16];
vector_normalize(rotX);//rotx is (1,0,0)
quaternion Q=make_rotation_quaternion_from_axis_and_angle(rotX,angle);// i created a quaternion from the axis and angle
quaternion_fill_opengl_rotation_matrix(Q,mat);// i converted it to a matrix , now i have the D( pn, dn ) you were talking about ( i guess ?)
glm::mat4 vecMat=glm::make_mat4(mat);//using the glm to do the maths

R = vecMat * R; // R is the recurrence matrix , i initialized it to the Id matrix in the constructor;

double dArray[16];
const float *pSource = (const float*)glm::value_ptr(R);
for (int i = 0; i < 16; ++i)
    dArray[i] = pSource[i]; // conversion of the R matrix to a double matrix[16]

glMultMatrixd(dArray);// i apply the changes;

}

well , after doing this , it is still not working , the teapot is now constantly spinning , it doesn't stop ; i don't know if the problem is still here or somewhere else though :P.

Share this post


Link to post
Share on other sites

There is at least one issue:

 

That R is a matrix that differs from the identity matrix as soon as the first angle different from 0 is applied as transformation. So it follows the formula accordingly to my post above:

      Rn := Dn * Rn-1

 

You apply it (as far as the shown code snippet let me follow the implementation) by multiplying it with the current matrix M on the stack:

      Mn := Rn * Mn-1

 

Now, what happens at the next time step?

     Mn+1 := Rn+1 * Mn = Dn+1 * RnMn

 

However, it should have been something different, namely

     Dn+1 * Rn

because R already accumulates all the incremental rotations (your solution accumulates them twice, in R and in M).

 

Therefore you either need to load the identity matrix (glLoadIdentity) before doing the glMultMatrix, so that

     Mn := Rn * I

or else you use the shortcut to replace the current top matrix on the stack with your own by using glLoadMatrix, so that

     Mn := Rn

 
 
BTW: The glMultMatrix and glLoadMatrix functions exist for float argument arrays, too; using them would unburden you from doing a float to double conversion.
Edited by haegarr

Share this post


Link to post
Share on other sites


That R is a matrix that differs from the identity matrix as soon as the first angle different from 0 is applied as transformation. So it follows the formula accordingly to my post above:

 

Yes , i initialized the R matrix to identity in the constructor , this way , whenever i enter that method the first time it's Id , but then its value changes following that equation.

 

I understand that i need to load the matrix and not multiply it because the stack automatically multiplies matrices passed by glMultMatrix() ; so i tried to glloadmatrix() the R matrix i computed , but the result is really weird ! is my code up above really correct ?

here's a screen of what it looks like : 

 

gleaeWn.png?1

 

yes , that is the Teapot taking all the screen :p . 

Share this post


Link to post
Share on other sites

I admit that judging the rotation is a bit problematic now ;)

 
However, I'm a bit confused now. In the OP there is the routine Teapot::PrintObj(). It has a pair of glPushMatrix() / glPopMatrix() what made me thought that before Teapot::PrintObj() is invoked just the view matrix is on the stack. But then the new rotation as was active with post #5 should have worked well. Because you've reported that it does spin endlessly, I concluded that the push / pop was replaced. Perhaps not … my mistake.
 
Unfortunately I cannot see the entire relevant code. So I tell how it should look like.
 
a) Before Teapot::PrintObj() is invoked, only the view matrix is on the matrix stack.
b) Inside Teapot::PrintObj() and before any transformation is put on the stack, a glPushMatrix() is done.
c) The 1st transform is the glTranslate() as shown in the OP.
d) The 2nd transform is a glMultMatrix() with R (no glLoadIdentity() nor glLoadMatrix() here).
e) The 3rd transform is the glScale() as shown in the OP.
f) Then perform the rendering.
g) Before leaving Teapot::PrintObj() do glPopMatrix().
 
If the code follows those scheme, and the  teapot still spins "without reason", then the problem lies perhaps in the input section. E.g. the Dn from above is allowed to differ from the identity matrix if and only if the user actually causes a rotation (i.e. you must not accumulate onto the angle used to compute Dn; the angle is either a delta angle when the belonging key is pressed (or whatever), or it is zero if not).

Share this post


Link to post
Share on other sites

thanks for your answers , i'm getting a head ache with this , the teapot is still constantly spinning , i even changed the method to test something and i got the same result : here's the method that passes the angles from the mouse event to the angles.x , angles.y and angles.z attribute of the teapot :


void Scene::ProjRotation(SDL_MouseMotionEvent &event,int X,int Y,int Z)
{
int a;
int b;
int c;

    for(_compt=_OjebctScene.begin();_compt!=_OjebctScene.end();_compt++)
    {

    if ((*_compt)->IsSelected())
    {
        if(X==1 && Y==0 && Z==0)
                {
                    a=event.y % 360;
                    if(a % 5 == 0)
                    {
                    (*_compt)->setAlpha(a);
                    }

                }
       else if(Y==1 && X==0 && Z==0)
                {
                      b=event.y % 360;
                      if(b % 5 == 0)
                        {
                        (*_compt)->setBeta(b);

                        }
                }
        else if(Z==1 && Y==0 && X==0)
                {
                      c=event.y % 360;
                      if(c % 5 == 0)
                        {
                    (*_compt)->setGamma(c);

                        }
                }

    }
    }
}

the ObjScene attribute is a vector in a class named Scene ,that contains all the objects in the scene; i first check if the object is selected , then if it is , i select the Axis around which i want to rotate , and send the coordinates of the mouse the my rotation methods as an angle;

i'm really struggling here nothing seems to work , i tried multiple version and multiple methods but all lead to the same result : either infinit spinning , or rotation around the Global axis (as if i used 3 consecutive  glrotated() ).

Share this post


Link to post
Share on other sites

Hi , Finally solved the problem ; Thanks a lot for the help @Haegarr , it was all based on what you said ; i just committed few mistakes that i corrected , and that i'm going to explain if someone needs this one day :

first , the infinit spinning was due to the R matrix receiving a new value each frame (Rn := Dn * Rn-1) and being passed to the stack ; i added a boolean to control that so only the first transformation is passed (The first transformation when i choose the rotation axis)

Then , the second big mistake i made was to call the glMultMatrix() INSIDE my RotatedX , RotatedY and RotatedZ methods , which was in a way going back to the  Rn := Z( cn ) * Y( bn ) * X( an ) ..

here's the final code of my teapot :

void Teapot::PrintObj()
{
        glLoadName(_NameStack);
        glPushMatrix();
        Translated(axeX,axeY,axeZ);


        RotatedX(Qy.getAngle());
        RotatedY(Qx.getAngle());
        RotatedZ(Qz.getAngle());
        glMultMatrixd(dArray);


        glScaled(ObjSize.x,ObjSize.y,ObjSize.z);

glColor3ub(_Color.red,_Color.green,_Color.blue);
glutSolidTeapot(2);

if(_Selected){WiredTeapot();Guizmo();}

        glPopMatrix();
};

And here's my final RotatedX() method (the method charged with the rotation)

void Object3D::RotatedX(double angle)
{
        Qx.FromAxis(glm::vec3(1,0,0),Qx.getAngle());
        Qx.normalise();

if(ActivateX)
{R=R*Qx.getMatrix();ActivateX=false;}
const float *pSource = (const float*)glm::value_ptr(R);
for (int i = 0; i < 16; ++i)
    dArray[i] = pSource[i];

}

ActivateX is the boolean i was talking about , it takes True when the user hits X to activate the X axis rotation .

Again , Thanks a lot for the help :D

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement