I'm trying to rotate a triangle around it's center point. I'm aware that OpenGL rotates about the origin so I need to translate the middle point to the origin, then rotate, and translate back. I've commented out this last line to ensure that it at least rotates about its center at the origin. It does not. It appears to be rotating about its old origin despite the translation... Note that ccc4 and ccp generate floats. Here's my code:
ccColor4B colors[] = {
ccc4(255, 0, 0, 255),
ccc4(0, 255, 0, 255),
ccc4(0, 0, 255, 255)
};
CGPoint vertices[] = {
ccp(0,0),
ccp(50,100),
ccp(100,0),
};
CGPoint middle[] = {ccp(50,50)};
CGPoint origin[] = {ccp(0,0)};
// Rotate the triangle
glPushMatrix();
glTranslatef(-50, -50, 0);
glRotatef(45, 0, 0, 1.0);
// glTranslatef(50, 50, 0);
// Draw the triangle
glLineWidth(2);
glVertexPointer(2, GL_FLOAT, 0, vertices);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
glColor4ub(0, 0, 255, 255);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
// Revert rotation, we only want triangle to rotate
glPopMatrix();
// Draw the points
glDisableClientState(GL_COLOR_ARRAY);
glPointSize(5);
glColor4ub(255, 255, 255, 255);
glVertexPointer(2, GL_FLOAT, 0, middle);
glDrawArrays(GL_POINTS, 0, 1);
glPointSize(5);
glColor4ub(0, 255, 0, 255);
glVertexPointer(2, GL_FLOAT, 0, origin);
glDrawArrays(GL_POINTS, 0, 1);
glEnableClientState(GL_COLOR_ARRAY);
// End points
Here's the output:
You need to think of transforms as applying in reverse relative to the order in which you call them.
Actually, it's easier to think in terms of transforming the local coordinate system (LCS), not the object, which allows you to mentally apply transforms in the order they're called. To rotate about the center, translate the LCS to the center, rotate, then translate it back out again:
glTranslatef(50, 50, 0);
glRotatef(45, 0, 0, 1);
glTranslatef(-50, -50, 0);
Related
I'm trying to draw a cube in cabinet perspective. This is the cube in glOrtho:
Other faces:
Back - cyan, Left - magenta, down - blue
This is what I get
This is what I want to achieve
My code:
//init function
glClearColor(1, 1, 1, 1);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-10, 10, -10, 10, 4,6);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(0,0,-lat);//it doesn't show in the window without this.
DisplayAxis();
DisplayObject();
break;
//object initalization. I use glGenList and glCallList to draw it
void InitObject() {
glNewList(k, GL_COMPILE);
glColor3f(1, 0, 0);
glBegin(GL_QUADS);
glVertex3d(0, lat, lat);
glVertex3d(lat, lat, lat);
glVertex3d(lat, 0, lat);
glVertex3d(0, 0, lat);
glEnd();
glColor3f(1, 1, 0);
glBegin(GL_QUADS);
glVertex3d(lat, 0, 0);
glVertex3d(lat, 0, lat);
glVertex3d(lat, lat, lat);
glVertex3d(lat, lat, 0);
glEnd();
glColor3f(0, 1, 0);
glBegin(GL_QUADS);
glVertex3d(0, lat, lat);
glVertex3d(lat, lat, lat);
glVertex3d(lat, lat, 0);
glVertex3d(0, lat, 0);
glEnd();
glColor3f(0, 0, 1);
glBegin(GL_QUADS);
glVertex3d(0, 0, 0);
glVertex3d(lat, 0, 0);
glVertex3d(lat, 0, lat);
glVertex3d(0, 0, lat);
glEnd();
glColor3f(1, 0, 1);
glBegin(GL_QUADS);
glVertex3d(0, 0, lat);
glVertex3d(0, 0, 0);
glVertex3d(0, lat, 0);
glVertex3d(0, lat, lat);
glEnd();
glColor3f(0, 1, 1);
glBegin(GL_QUADS);
glVertex3d(0, lat, 0);
glVertex3d(lat, lat, 0);
glVertex3d(lat, 0, 0);
glVertex3d(0, 0, 0);
glEnd();
glEndList();
}
What am I doing wrong here? I tried some rotations on the object but I get some skewed results(I can post more images if needed).
The object is clipped by the near plane of the Viewing frustum.
Not you have to translate the object along the negativ z axis, to move the object in between the near and far plane of the viewing frustum:
glTranslated(0,0,-lat);//it doesn't show in the window without this.
Since the view space z axis points out out the viewport, you have to shift the object along the negative z axis.
The distance to the near plane is 4 and the distance to the far plane is 6:
glFrustum(-10, 10, -10, 10, 4,6);
The distance to the front of the cube is less than 4, thus it is clipped by the near plane.
Change the frustum, and keep the cube completely in the frustum to solve the issue:
glFrustum(-10, 10, -10, 10, 4,6);
glFrustum(-2.5, 2.5, -2.5, 2.5, 1, 10);
glTranslated(0,0,-lat);
glTranslated(0, 0, -6);
For a good perspective and look at the scene, use a projection matrix (frustum) with a smaller field of view:
glFrustum(-1, 1, -1, 1, 1, 12);
Alternatively you can define the frustum by gluPerspective and set the field of view angle in degrees:
gluPerspective(90, 1, 1, 12);
The view matrix defines the position and viewing direction of the observer (viewer) within the scene.
If you want a different look at the scene the you have to rotate the scene (glRotate):
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(0, 0, -8);
glRotatef(30, 1, 0, 0);
glRotatef(-45, 0, 1, 0);
Alternatively the look at the scene (view matrix) can be defined by gluLookAt . Arguments 1-3 are the position of the observer (x,y, z components of eye or camera position). The Arguments 4-6 are the target point (where the observer looks at). The arguments 7-9 are the upwards vector.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(5, 5, 7, 0, 0, 0, 0, 1, 0);
I'm using opengl, glfw and glew. I want to rotate the tip of the spaceship without moving the whole spaceship when users press on the left and right arrow respectively. I've tried using gltransform glrotate, it does rotate but it also move my spaceship along. The output of the movement of spaces
objects objects::rotateSpaceship(GLFWwindow * window, objects & sp)
{
GLfloat spaceship_angle = sp.getAngle();
GLfloat newAngle = sp.getAngle() + 0.5;
sp.setAngle(newAngle);
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
GLfloat spaceShipRightLine[] =
{
x, y + 80, 0,
x - 50, y - 50, 0
};
GLfloat spaceShipLeftLine[] = {
x, y + 80, 0,
x + 50, y - 50, 0
};
GLfloat spaceShipMiddleLine[] = {
sp.x - 30 ,sp.y,0,
sp.x + 35,sp.y,0
};
glPushMatrix();
glTranslatef(0.0, 0.01, 0.0); // 3. Translate to the object's position.
glRotatef(sp.getAngle(), 0.0, 0.0, 1.0); // 2. Rotate the object.
glTranslatef(0.0, 0.01, 0.0); // 1. Translate to the origin.
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, spaceShipRightLine);
glDrawArrays(GL_LINES, 0, 2);
glDisableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, spaceShipLeftLine);
glDrawArrays(GL_LINES, 0, 2);
glDisableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, spaceShipMiddleLine);
glDrawArrays(GL_LINES, 0, 2);
glDisableClientState(GL_VERTEX_ARRAY);
glPopMatrix();
// Swap front and back buffers
glfwSwapBuffers(window);
// Poll for and process events
glfwPollEvents();
}
glfwTerminate();
return sp;
}
Note, that drawing by glBegin/glEnd sequences and the fixed function matrix stack is deprecated since decades.
Read about Fixed Function Pipeline and see Vertex Specification and Shader for a state of the art way of rendering.
I want to rotate the tip of the spaceship without moving the whole spaceship [...]
First you have to define the pivot, which is the "tip" of the spaceship:
float pivot_x = sp.x;
float pivot_y = sp.y + 80.0f;
To rotate around a pivot you have to define a model matrix, which displaces by the inverted pivot, then rotate (glRotatef) and final transforms back by to the pivot (glTranslate):
glTranslatef(pivot_x, pivot_y, 0);
glRotatef(angle, 0, 0, 1);
glTranslatef(-pivot_x, -pivot_y, 0);
The final code may look like that:
float pivot_x = x;
float pivot_y = y + 80.0f;
glPushMatrix();
glTranslatef(pivot_x, pivot_y, 0 ); // 3. Translate to the object's position.
glRotatef(sp.getAngle(), 0.0, 0.0, 1.0); // 2. Rotate the object.
glTranslatef(-pivot_x, -pivot_y, 0.0); // 1. Translate to the origin.
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, spaceShipRightLine);
glDrawArrays(GL_LINES, 0, 2);
glDisableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, spaceShipLeftLine);
glDrawArrays(GL_LINES, 0, 2);
glDisableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, spaceShipMiddleLine);
glDrawArrays(GL_LINES, 0, 2);
glDisableClientState(GL_VERTEX_ARRAY);
glPopMatrix();
I'm trying to make a Camera's View Matrix and make it zoomable, pannable and rotatable. The Matrix that I'd expect to work is.
Matrix.translateM(matrixView, 0, -camposition.X, -camposition.Y, 0);
Matrix.scaleM(matrixView, 0, zoom, zoom, 1.0f);
Matrix.rotateM(matrixView, 0, camrotation, 0, 0, 1.0f);
Matrix.translateM(matrixView, 0, screenwidth / 2, screenheight / 2, 0);
However it doesn't work this way. I would appreciate if somebody could point me in the right direction.
Here's how I did the model matrix which works:
Matrix.translateM(matrixModel, 0, position.X, position.Y, 0.0f);
Matrix.scaleM(matrixModel, 0, scale.X, scale.Y, 1.0f);
Matrix.rotateM(matrixModel, 0, rotation, 0, 0, 1.0f);
Matrix.translateM(matrixModel, 0, -origin.X, -origin.Y, 0.0f);
And here's the projection matrix aswell:
Matrix.orthoM(matrixProj, 0, 0f, screenWidth, screenHeight, 0, -1, 1);
I multiply them together in the vertex shader like so:
matrixProj * matrixView * matrixModel * vPosition;
I've found the correct order I'll leave it for future developers facing the same problem.
Matrix.translateM(matrixView, 0, screenWidth / 2, screenHeight / 2, 0);
Matrix.scaleM(matrixView, 0, camZoom, camZoom, 1.0f);
Matrix.rotateM(matrixView, 0, camRotation, 0, 0, 1.0f);
Matrix.translateM(matrixView, 0, -camPosition.X, -camPosition.Y, 0);
Keep in mind this is for the View Matrix. For the Model Matrix the above code works just fine.
I'm working on a little OpenTK based 2D graphics library and I'm trying to apply a shader to a Surface object:
public void ApplyTo(Surface surface)
{
using (Surface pong = new Surface())
{
pong.Create(surface.Width, surface.Height);
pong.Clear(0, 0, 0, 0);
GL.Viewport(0, 0, surface.Width, surface.Height);
GL.LoadIdentity();
GL.Ortho(0, 1.0, 1.0, 0.0, 0.0, 4.0);
GL.UseProgram(0);
surface.BindTexture();
pong.BindFramebuffer();
GL.Begin(PrimitiveType.Quads);
GL.TexCoord2(0.0f, 1.0f);
GL.Vertex3(0, 0, 0);
GL.TexCoord2(0.0f, 0.0f);
GL.Vertex3(0, 1, 0);
GL.TexCoord2(1.0f, 0.0f);
GL.Vertex3(1, 1, 0);
GL.TexCoord2(1.0f, 1.0f);
GL.Vertex3(1, 0, 0);
GL.End();
Use(); // calls GL.UseProgram()
pong.BindTexture();
surface.BindFramebuffer();
GL.Begin(PrimitiveType.Quads);
GL.TexCoord2(0.0f, 1.0f);
GL.Vertex3(0, 0, 0);
GL.TexCoord2(0.0f, 0.0f);
GL.Vertex3(0, 1, 0);
GL.TexCoord2(1.0f, 0.0f);
GL.Vertex3(1, 1, 0);
GL.TexCoord2(1.0f, 1.0f);
GL.Vertex3(1, 0, 0);
GL.End();
GL.BindTexture(TextureTarget.Texture2D, 0);
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
}
}
This somehow clears the surface instead of applying the shader. My suspicion is that I'm doing something wrong with the viewport / projection, but what? I hope the provided code is sufficient.
For full screen rendering on a quad, I use that projection:
OpenTK.Matrix4 ortho = OpenTK.Matrix4.CreateOrthographicOffCenter(-1, 1, -1, 1, 1, -1);
Theres a division by 0 somewhere when your vertices are exactly on the near plane, you may also move a bit further on the z axis.
I want to rotate 2d texture in cocos2d-x(opengl es) as i searched i should use rotation matrix
as this :
(x = cos(deg) * x - sin(deg) * y y = sin(deg) * x + cos(deg) * y)
but when i want to implement this formula i fail may code is like(i want original x and y to be same ) :
i updated my code to this but still not working!
GLfloat coordinates[] = {
0.0f, text->getMaxS(),
text->getMaxS(),text->getMaxT(),
0.0f, 0.0f,
text->getMaxS(),0.0f };
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
GLfloat vertices[] = { rect.origin.x, rect.origin.y, 1.0f,
rect.origin.x + rect.size.width, rect.origin.y, 1.0f,
rect.origin.x, rect.origin.y + rect.size.height, 1.0f,
rect.origin.x + rect.size.width, rect.origin.y + rect.size.height, 1.0f };
glMultMatrixf(vertices);
glTranslatef(p1.x, p1.y, 0.0f);
glRotatef(a,0,0,1);
glBindTexture(GL_TEXTURE_2D, text->getName());
glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
glColor4f( 0, 0, 250, 1);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glRotatef(-a, 0.0f, 0.0f, -1.0f);
glPopMatrix();
If you're using OpenGL in two dimensions, you can still use the various transformation functions. For glRotate(), you have to pass it an axis of (0,0,1):
glRotate(angle,0,0,1);
You seem to be confused about a few aspects of OpenGL. At the minute you have this:
glMultMatrixf(vertices);
glTranslatef(p1.x, p1.y, 0.0f);
glRotatef(a,0,0,1);
glBindTexture(GL_TEXTURE_2D, text->getName());
glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
glColor4f( 0, 0, 250, 1);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glRotatef(-a, 0.0f, 0.0f, -1.0f);
glPopMatrix();
That would ostensibly:
// reinterpret your vertices as a matrix; multiply the
// current matrix by the one formed from your vertices
glMultMatrixf(vertices);
// rotate by a degrees, then translate to p1
glTranslatef(p1.x, p1.y, 0.0f);
glRotatef(a,0,0,1);
// bind the relevant texture, supply the vertices
// as vertices this time, supply texture coordinates
glBindTexture(GL_TEXTURE_2D, text->getName());
glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
// set a colour of (0, 0, 1, 1) — probably you
// wanted glColor4ub to set a colour of (0, 0, 250/255, 1)?
glColor4f( 0, 0, 250, 1);
// draw some geometry
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// perform the same rotation as before a second time;
// giving either a and -1, or -a and 1 would have been
// the opposite rotation
glRotatef(-a, 0.0f, 0.0f, -1.0f);
// remove the current matrix from the stack
glPopMatrix();
What you probably want is:
// push the current matrix, so that the following
// transformations can be undone with a pop
glPushMatrix();
// rotate by a degrees, then translate to p1
glTranslatef(p1.x, p1.y, 0.0f);
glRotatef(a,0,0,1);
// bind the relevant texture, supply the vertices
// as vertices this time, supply texture coordinates
glBindTexture(GL_TEXTURE_2D, text->getName());
glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
// set a colour of (0, 0, 250/255, 1)
glColor4ub( 0, 0, 250, 1);
// draw some geometry
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// remove the current matrix from the stack
glPopMatrix();
The current transform matrices are applied to all geometry. You don't flag up which geometry they apply to and which they don't. Pushes and pops should be paired, and are the way you affect transformations from being affected by prior transformations when that's what you want. So you don't manually perform the inverse rotation, and you need to push before you do all the stuff that changes the matrix. I've also switched you to glColor4ub for the reason given above — you appear to be using unsigned bytes to push colours in but OpenGL uses the range from 0.0 to 1.0 to represent a colour. glColor4ub will automatically map from the former to the latter.