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.
Related
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 ran into an issue where my vertices were being drawn offscreen. I changed the stride to 0 for all my vertex attribute pointers and now they draw at the correct location.
Here is some code to start this off:
glGenVertexArrays(1, &vertexID);
glBindVertexArray(vertexID);
glGenBuffers(1, &bufferID);
glBindBuffer(GL_ARRAY_BUFFER, bufferID);
GLfloat verts[4 * 2 * 3] = { -0.5, -0.5, 0.0, 1.0,// bottom left
.5, -.5, 0.0, 1.0, // bottom right
-.5, .5, 0.0, 1.0, // top left
0.5, 0.5, 0.0, 1.0,
.5, -.5, 0.0, 1.0, // bottom right
-.5, .5, 0.0, 1.0, // top left// top right
};
GLfloat color[4 * 3 * 2] = {
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f };
GLfloat tex[8] = {
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
0.0f, 1.0f
};
glBufferData(GL_ARRAY_BUFFER, sizeof(verts) + sizeof(color) + sizeof(tex), nullptr, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(verts), verts);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(verts), sizeof(color), color);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(verts) + sizeof(color), sizeof(tex), tex);
glClearColor(0.05f, 0.05f, 0.05f, 1.0f);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 10, NULL);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 10, (const GLvoid *)(sizeof(GLfloat) * 4));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 10, (const GLvoid *)(sizeof(GLfloat) * 8));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
GLuint indices[4] = {
0,2,1,3
};
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_DYNAMIC_DRAW);
and then here is the rendering code
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, texture);
glBindVertexArray(vertexID);
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
//glDrawArrays(GL_TRIANGLES, 0, 6);
glFlush();
SDL_GL_SwapWindow(window);
Okay so here is where I am confused:
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 10, NULL);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 10, (const GLvoid *)(sizeof(GLfloat) * 4));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 10, (const GLvoid *)(sizeof(GLfloat) * 8));
With this above code, the program doesn't render the proper square I am trying to render. If I change the stride to 0 for all of these, then it renders in the correct position. My understanding of it was that i sub buffered 3 sets of information: position, color, and tex coordinates. Therefor I thought the data looked like the following:
There for I set the stride to sizeof(GLFloat) * 10, however, this doesn't work. This makes me assume I also don't have the offset values set correctly. So why is my stride messing up the vertex position?
Therefor I thought the data looked like the following:
But that's not what you told OpenGL.
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(verts), verts);
This tells OpenGL to take the array verts and copy it into the start of the buffer object.
glBufferSubData(GL_ARRAY_BUFFER, sizeof(verts), sizeof(color), color);
This tells OpengL to take the array color, and copy it into the buffer object, but after all of verts.
There's no interleaving here. You buffer stores all of verts, followed by all of color, followed by all of tex. It does not store 4 floats of verts followed by 4 floats of color, followed by 4 floats of tex.
glBufferSubData cannot interleave data for you (well, you could do it in a long series of calls, but that'd be ridiculous). If you want to upload interleaved vertex data, you have to interleave it on the CPU, then upload it.
And setting the strides to 0 doesn't make this work. Well, it doesn't make it work correctly. Your base offsets are still wrong, relative to the data you actually uploaded. You'll get the correct position data, but the colors and texture coordinates will be wrong.
You're uploading your vertex data in blocks:
glBufferData(GL_ARRAY_BUFFER, sizeof(verts) + sizeof(color) + sizeof(tex), nullptr, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(verts), verts);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(verts), sizeof(color), color);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(verts) + sizeof(color), sizeof(tex), tex);
So it ends up like:
<vert 0, ... vert N><color 0, ..., color N><tex 0, ..., tex N>
But your glVertexAttribPointer() calls are claiming the buffer is interleaved like this:
<vert 0><color 0><tex 0><vert 1><color1><tex 1>...
Either interleave the data at upload or adjust your glVertexAttribPointer() calls to take into account the block layout.
I have been attempting to transition my game's prototype renderer from it's immediate mode testing implementation to an actual VAO/VBO implementation. The VBO is rendering on screen, but is refusing to texture. Below is the simplest test class that shows the problem:
public static void main(String[] args) throws Exception {
// VertX,VertY TexX, TexY
float[] data = new float[] {0.0f, 0.0f, 0.25f, 0.75f,
0.0f, 64.0f, 0.25f, 1.0f,
64.0f, 64.0f, 0.5f, 1.0f,
0.0f, 0.0f, 0.25f, 0.75f,
64.0f, 64.0f, 0.5f, 1.0f,
64.0f, 0.0f, 0.5f, 0.75f};
glfwSetErrorCallback(GLFWErrorCallback.createPrint(System.err));
if (!glfwInit())
throw new IllegalStateException("Unable to initialize GLFW");
long window = GLFW.glfwCreateWindow(1600, 900, "TEST", 0, 0);
GLFW.glfwMakeContextCurrent(window);
GL.createCapabilities();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 1600, 900, 0, 0.000001, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
int vboId = glGenBuffers();
int vaoId = glGenVertexArrays();
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindVertexArray(vaoId);
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, data, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, false, 4*Float.BYTES, 0);
glTexCoordPointer(2, GL_FLOAT, 4*Float.BYTES, 4*Float.BYTES);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glTranslatef(50, 50, 0);
Texture t = new Texture(TEST.class.getClassLoader().getResourceAsStream("test/WallFloor.png"));
while (!GLFW.glfwWindowShouldClose(window)) {
GLFW.glfwPollEvents();
GLFW.glfwSwapBuffers(window);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindVertexArray(vaoId);
glEnableVertexAttribArray(0);
t.bind();
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableVertexAttribArray(0);
glBindVertexArray(0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
/* Equivelent immediate mode code - that works
t.bind();
glBegin(GL_TRIANGLES);
glTexCoord2f(0.25f, 0.75f);
glVertex2f(0, 0);
glTexCoord2f(0.25f, 1f);
glVertex2f(0, 64);
glTexCoord2f(0.5f, 0.75f);
glVertex2f(64, 0);
glTexCoord2f(0.5f, 1f);
glVertex2f(64, 64);
glTexCoord2f(0.25f, 1f);
glVertex2f(0, 64);
glTexCoord2f(0.5f, 0.75f);
glVertex2f(64, 0);
glEnd();
*/
}
}
The texture bind call is the following (where wrap = GL_REPEAT and filter = GL_NEAREST):
public void bind()
{
glActiveTexture(GL_TEXTURE0);
glClientActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(target, id);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap);
glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap);
}
Having spent the weekend googling it an not finding an answer, am I doing something horribly wrong? I have also tested using immediate mode, which does still render with a texture.
In addition, you are mixing core profile code (glVertexAttribPointer) with non-core profile (glTexCoordPointer)
But the real problem comes from the wrong stride and offset used. Stride defines how large the data of one vertex is, while the offset specifies how far from the beginning of each vertex the actual data starts. In your case, every vertex consists of 4 floats thus the stride has to be 4 * Float.BYTES. The positions are the first two floats in each vertex (offset 0) while the texture coordinates are the 3rd and 4th floats which means offset = 2 * Float.BYTES. The correct code could look somehow like this (note the usage of glVertexPointer instead of glVertexAttribPointer):
glVertexPointer(2, GL_FLOAT, false, 4*Float.BYTES, 0);
glTexCoordPointer(2, GL_FLOAT, 4*Float.BYTES, 2*Float.BYTES);
Edit
The usage of your VAOs is also wrong. In the initialization you store the glVertexPointer/glTexCoordPointer to the VAO vaoId. But in the rendering code you bind VAO 0 instead. Most probably the attribute settings are not present when drawing. In addition, I'm not absolutely sure whether VAOs work together with fixed function calls. In this case you can remove all of the VAO calls.
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.
My image disappears if I add Opengl transformations.
void renderFileButton()
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glViewport(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 320, 0, 240, -1, 1);
glMatrixMode(GL_MODELVIEW);
glGenBuffers(1, &vertexBufferID);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(file_vertices), file_vertices,
GL_STATIC_DRAW);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(fileButtonVertexData), (GLvoid *)
offsetof(fileButtonVertexData, fileButtonPositionCoordinates));
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, sizeof(fileButtonVertexData), (GLvoid *)
offsetof(fileButtonVertexData, fileButtonTextureCoordinates));
loadsprite("files/sprites/options.png");
glScalef(0, 0, 1);
glRotatef(180, 1, 0, 0);
glTranslatef(0, 0, 0);
glPopMatrix();
}
Could someone tell me where I'm in the wrong here?
You've scaled by zero. That makes the object's size zero. No surprise that it disappears.
In the future, you can troubleshoot by adding one transformation at a time, and trying to add a transformation that doesn't do anything (scale by 1, rotate by 0, translate by 0). Then increase the transformation slowly until you get to your intended value.
Also, your glPopMatrix is undoing all your transformations.
Finally, I don't see any actual rendering. Just a lot of state manipulation.
I found the problem after playing with it all last night. The transformation order was the issue.
glTranslatef(100, 100, 0);
glRotatef(180.0f,0.0f,0.0f,1.0f);
glScalef(-1.0f,1.0f,1.0f);
This does the job, that is all.