OpenGL the problem of figure rotation (the figure begins to shift) - opengl

I draw two figures, in this method I rotate only one of them.but applying successive transformations over these two figures, I ran into a rotation problem.I can consistently apply scaling, offset to these figures separately and everything works fine, in the sense that by changing one figure, the previous one retains its previous state. But it doesn't work the same way with rotations. I do the displacement of the figure, and then the rotation of the other, then again the transformation over the first figure, and the second figure that I rotated begins to change its position too, although it should not do this. Tell me, what is the problem?
private void rotateARL(float x)
{
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT);
Gl.glPushMatrix();
Gl.glMatrixMode(Gl.GL_MODELVIEW);
Gl.glScaled(s2, s2, 1);
Gl.glRotated(ang2, 0, 0, 1);
Gl.glTranslatef(dx2, dy2, dz2);
draw2();
Gl.glPopMatrix();
Gl.glPushMatrix();
Gl.glMatrixMode(Gl.GL_MODELVIEW);
Gl.glScaled(s1, s1, 1);
Gl.glTranslatef(dx1, dy1, dz1);
ang1 += x;
Gl.glRotated(ang1, 0, 0, 1);
draw1(points1);
Gl.glPopMatrix();
simpleOpenGlControl1.Invalidate();
}

Related

Rotating object in OpenGL around specific point

I'm modelling Newtons Cradle and I am having trouble with wires/strings rotation as they currently rotate around their centre instead of where they are attached to the frame. There seem to be very little info online apart from " Translate to rotation point, rotate, translate back" which does not seem to work.
std::stack<glm::mat4>model;
model.push(glm::mat4(1.0f));
model.top() = glm::translate(model.top(), glm::vec3(x, y, z));
model.top() = glm::rotate(model.top(), vx, glm::vec3(1, 0, 0)); //rotating in clockwise direction around x-axis
model.top() = glm::rotate(model.top(), vy, glm::vec3(0, 1, 0)); //rotating in clockwise direction around y-axis
model.top() = glm::rotate(model.top(), vz, glm::vec3(0, 0, 1)); //rotating in clockwise direction around z-axis
model.top() = glm::scale(model.top(), glm::vec3(scale/40, scale*5, scale/40));//scale equally in all axis
model.top() = glm::translate(model.top(), glm::vec3(-x, -y, -z));
glUniformMatrix4fv(modelID, 1, GL_FALSE, &model.top()[0][0]);
glm::mat3 normalmatrix = glm::transpose(glm::inverse(glm::mat3(View * model.top())));
glUniformMatrix3fv(normalmatrixID, 1, GL_FALSE, &normalmatrix[0][0])
This is the bit that translates and rotates or its current iteration, stack really does nothing at the moment.
If my problem is unclear imagine analogue clock arm, it will rotate around the clock centre at its end and not by arms itself centre. I know there is no native implementation to rotate object around specific point in OpenGl
As a side note, there is no longer any "native" implementation of any matrix stuff in OpenGL (outside of GLSL).
Your problem here is that you're only setting the top() matrix to a value instead of accumulating the transformations by multiplying them together.
You will probably also later notice a problem where it doesn't move back into the same spot (after making it multiply the matrices together). This is because you're scaling the object down a lot before translating back to the original spot. The order of your transformations matter.
A tutorial like this one that provides an in-depth explanation of all of this stuff will likely be very useful to you:
http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/

Apply multiple transformations to view

I am working on a OpenGL ES application using C++. I run the code on iOS with a few wrapper Obj-c classes that enable me to use gestures (like pan, pinch, rotation).
I use orthographic projection. The code only draws a simple quad for now, and I want to be able to apply any transformations to it using user gesture. That means move it, zoom in and out, rotate (some other derived gestures, like zoom using double-tap etc.).
I thought it will be fine if I simply store origin, scale and angle floats and construct Matrix using each of these, then multiply. That works for simple translation and scale, however, I can't rotate around any point. Now I can't figure out what do I need to be able to rotate around some point, translate, rotate some more around different point.
Here is example how I initialize my matrix
Mat4 Mat4::translation(float tx, float ty)
{
float a[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, tx, ty, 0, 1 };
return Mat4(a);
}
Mat4 Mat4::rotation(float angle)
{
float a[16] = { cosf(angle), sinf(angle), 0, 0, -sinf(angle), cosf(angle), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
return Mat4(a);
}
How can I apply any number of transformations to 2D view in OpenGL(ES), using matrices? These transformations are caused by gestures (pan, pinch, rotate). For pinch and rotation, I know amount and center point in screen coordinates.
I believe your problem boils down to finding out with respect to which reference frame you define your transformations.
In practice, you can specify any trasformation (i.e. translation and rotation in 3D) as a 4x4 matrix, like you've done in your example. If they are defined with respect to the current pose of the object, then you can apply a new one by multiplying the new matrix on the right. If they are specified with respect to a fixed reference frame (e.g. your screen origin which does not move) then you pre-multiply them.
Say you apply two rotations, defined by T_rot_1 and T_rot_2
If transformations are defined wrt reference frame attached to the object:
T_final_wrt_fixed = T_rot_1_wrt_obj * T_rot_2_wrt_obj
If transformations are defined wrt reference to fixed frame:
T_final_wrt_fixed = T_rot_2_wrt_fixed * T_rot_1_wrt_fixed
For more info, check out these slides.
Rotation around arbitrary point is done by translation of the point to origin, rotation around origin and then translating back.

OpenGl Rotation around point

My problem is that I need to rotate a white square around the center of the far left end, and no matter what I try, I cannot seem to do it.
I need to rotate an object around radius, which is radius far from the position (getPosition().x/y), which i have already translated to. I need to rotate it r degrees. If it matters, I am using an orthographic (glOrtho) projection.
So far this what I tried:
//Try 1
glRotatef(r, 0, 0, 1.0f);
glTranslatef(radius, radius, 0);
glBegin(GL_QUADS)
//draw here...
//Try 2
glTranslatef(-radius, -radius, 0);
glRotatef(r, 0, 0, 1.0f);
glTranslatef(radius, radius, 0);
glBegin(GL_QUADS)
//draw here...
//Try 3
glTranslatef(radius + getPosition().x, radius + getPosition().y, 0);
glRotatef(r, 0, 0, 1.0f);
glTranslatef(radius, radius, 0);
glBegin(GL_QUADS)
//draw here...
I have tried Googling and searching on StackOverflow numerous times, with no luck. Two of these "solutions" came from answers found on StackOverflow itself.
All of these attempts rotate around the origin. I have also tried numerous other more nonsensical combinations, to no avail. If it matters, a little bit before this code, I translate the matrix (and don't pop it back out). I don't think this is the problem, as popping the matrix and pushing a new one back on right before any of these attempts does not fix the problem.
Any help would be much appreciated.
So I found the solution:
glTranslatef(radius + getPosition().x, radius + getPosition().y, 0);
glRotatef(r, 0, 0, 1.0f);
glBegin(GL_POLYGON);
It turns out you dont have to translate after the rotation, which is was several sources suggested.

OpenGL "camera" Yaw on wrong axis

I am using gluLookAt() to set the "camera" position and orientation
GLU.gluLookAt(xPosition, yPosition, zPosition,
xPosition + lx, yPosition, zPosition + lz
0, 1, 0);
my lz and lx variables represent my forward vector
lz = Math.cos(angle);
lx = -Math.sin(angle);
When turn around in the 3D world, it appears that I am rotating around an axis that is always infront of me
I know this because my xPosition and yPosition variables stay the same, but I appear to spin around an object when im close to it and I turn.
I know there is not a problem with the maths that I have used here, because I have tried using code from past projects that have worked properly but the problem still remains.
This is what I am doing in the rendering loop
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//draw scene from user perspective
glLoadIdentity();
GLU.gluLookAt(camera.getxPos(), camera.getyPos(), camera.getzPos(),
camera.getxPos()+camera.getLx(), camera.getyPos(), camera.getzPos()+p1.getLz(),
0, 1, 0);
glBegin(GL_QUADS);
glVertex3f(-dim, dim, 0);
glVertex3f(dim, dim, 0);
glVertex3f(dim, 0, 0);
glVertex3f(-dim, 0, 0);
glEnd();
pollInput();
camera.update();
I have tried rendering a box where the player coordinates are and I got this result. The camera appears to be looking from behind the player coordinates. To use an analogy right now its like a 3rd Person game and It should look like a first person game
The small box here is rendered in the camera coordinates, to give some perspective the bigger box is infront.
Solved!
The problem was that I was initially calling gluLookAt() while the matrix mode was set to GL_PROJECTION.
I removed that line and moved it to just after I had set the matrix mode to GL_MODELVIEW and that solved the problem.

OpenGL particles, help controlling direction

I am trying to modify this Digiben sample in order to get the effect of particles that generate from a spot (impact point) and float upwards kind of like the sparks of a fire. The sample has the particles rotating in a circle... I have tried removing the cosine/sine functions and replace them with a normal glTranslate with increasing Y value but I just can't get any real results... could anyone please point out roughly where I should add/modify the translation in this code to obtain that result?
void ParticleMgr::init(){
tex.Load("part.bmp");
GLfloat angle = 0; // A particle's angle
GLfloat speed = 0; // A particle's speed
// Create all the particles
for(int i = 0; i < P_MAX; i++)
{
speed = float(rand()%50 + 450); // Make a random speed
// Init the particle with a random speed
InitParticle(particle[i],speed,angle);
angle += 360 / (float)P_MAX; // Increment the angle so when all the particles are
// initialized they will be equally positioned in a
// circular fashion
}
}
void ParticleMgr::InitParticle(PARTICLE &particle, GLfloat sss, GLfloat aaa)
{
particle.speed = sss; // Set the particle's speed
particle.angle = aaa; // Set the particle's current angle of rotation
// Randomly set the particles color
particle.red = rand()%255;
particle.green = rand()%255;
particle.blue = rand()%255;
}
void ParticleMgr::DrawParticle(const PARTICLE &particle)
{
tex.Use();
// Calculate the current x any y positions of the particle based on the particle's
// current angle -- This will make the particles move in a "circular pattern"
GLfloat xPos = sinf(particle.angle);
GLfloat yPos = cosf(particle.angle);
// Translate to the x and y position and the #defined PDEPTH (particle depth)
glTranslatef(xPos,yPos,PDEPTH);
// Draw the first quad
glBegin(GL_QUADS);
glTexCoord2f(0,0);
glVertex3f(-5, 5, 0);
glTexCoord2f(1,0);
glVertex3f(5, 5, 0);
glTexCoord2f(1,1);
glVertex3f(5, -5, 0);
glTexCoord2f(0,1);
glVertex3f(-5, -5, 0);
glEnd(); // Done drawing quad
// Draw the SECOND part of our particle
tex.Use();
glRotatef(particle.angle,0,0,1); // Rotate around the z-axis (depth axis)
//glTranslatef(0, particle.angle, 0);
// Draw the second quad
glBegin(GL_QUADS);
glTexCoord2f(0,0);
glVertex3f(-4, 4, 0);
glTexCoord2f(1,0);
glVertex3f(4, 4, 0);
glTexCoord2f(1,1);
glVertex3f(4, -4, 0);
glTexCoord2f(0,1);
glVertex3f(-4, -4, 0);
glEnd(); // Done drawing quad
// Translate back to where we began
glTranslatef(-xPos,-yPos,-PDEPTH);
}
void ParticleMgr::run(){
for(int i = 0; i < P_MAX; i++)
{
DrawParticle(particle[i]);
// Increment the particle's angle
particle[i].angle += ANGLE_INC;
}
}
For now I am adding a glPushMatrix(), glTranslate(x, y, z) in the run() function above, right before the loop, with x,y,z as the position of the enemy for placing them on top of the enemy....is that the best place for that?
Thanks for any input!
Using glTranslate and glRotate that way will in fact decrease your program's performance. OpenGL is not a scene graph, so the matrix manipulation functions directly influence the drawing process, i.e. they don't set "object state". The issue you're running into is, that a 4×4 matrix-matrix multiplication involves 64 multiplications and 16 additions. So you're spending 96 times the computing power for moving a particle, than simply update the vertex position directly.
Now to your problem: Like I already told you, glTranslate operates on (a global) matrix state of one of 4 selectable matrices. And the effects accumulate, i.e. each glTranslate will start from the matrix the previous glTranslate left. OpenGL provides a matrix stack, where one can push a copy of the current matrix to work with, then pop to revert to the state before.
However: Matrix manipulation has been removed from OpenGL-3 core and later entirely. OpenGL matrix manipulation never was accelerated (except on one particular graphics workstation made by SGI around 1996). Today it is a anachronism, as every respectable program working with 3D geometry used much more sophisticated matrix manipulation by either own implementation or 3rd party library. OpenGL's matrix stack was just redundant. So I strongly suggest you forget about OpenGL's matrix manipulation functionality and roll your own.