Basicly I want to open a Door and I thought of using glRotatef.
My Problem is that it is affecting every object which is drawn after it.
Does anyone know how to stop that ?
Door.class
public static void draw(Texture door) {
door.bind();
if(Door_Test.state == "out" && d != 90){
glRotatef(i, 0, 1, 0);
i+=5;
}
glBegin(GL_QUADS);
glColor3f(1f, 1f, 1f);glTexCoord2f(0,0);glVertex3f(-2,3, -15);
glColor3f(1f, 1f, 1f);glTexCoord2f(0,1);glVertex3f(-2,-3, -15);
glColor3f(1f, 1f, 1f);glTexCoord2f(1,1);glVertex3f(2,-3, -15);
glColor3f(1f, 1f, 1f);glTexCoord2f(1,0);glVertex3f(2,3, -15);
glEnd();
}
Common way to do it:
glPushMatrix();
glRotatef(/*...*/);
// Drawing commands here
glPopMatrix();
When you rotate, it rotates the entire scene. So to rotate a single object, you rotate the entire scene, draw your object, then rotate your screen back.
glRotatef(i, 0, 1, 0);
// Draw object.
glRotatef(-i, 0, 1, 0);
As Reto Koradi pointed out, if you continually do this you might have floating point rounding errors that accumulate over time. HolyBlackCat's answer offers a better solution.
Related
I have a problem with skybox textures. If you twist the camera, it creates a feeling that one texture overlays another, as in the screenshot:
Skybox show code:
private void drawSkybox(int texId){
glColor4f(1,1,1,1);
glDepthMask(false);
glEnable(GL_TEXTURE_CUBE_MAP);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, texId);
glBindVertexArray(vao[0]);
glBindBuffer (GL_ARRAY_BUFFER, vbo[0]);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glBindBuffer (GL_ARRAY_BUFFER, 0);
glDepthMask(true);
glDisable(GL_TEXTURE_CUBE_MAP);
}
My opengl paramters:
glEnable(GL_ALPHA_TEST);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glEnable(GL_NORMALIZE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glShadeModel(GL_SMOOTH);
glColorMask (true, true, true, true);
glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
And my call drawSkybox:
glViewport(0, 0, WIDTH, HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-max, max, -1, 1, 10, -10);
glRotated(cameraX, 1f, 0f, 0);
glRotated(cameraY, 0f, 1f, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
drawSkybox(texId);
How i can fix the problem?
I understand that the problem is glDepthMask(false); but how can it be replaced?
If I just remove glDepthMask(false); and replace it with an example with glDepthFunc(GL_LEQUAL); and glDepthFunc(GL_LESS); then the skybox will overlap all other objects and only it will be visible –
Do not change the depth mask or the depth test when you draw the skybox. Keep the depth test function GL_LESS.
private void drawSkybox(int texId){
glColor4f(1,1,1,1);
// glDepthMask(false); <---- DELETE
// [...]
}
But clear the depth buffer again, after drawing the skybox. Draw the skybox first, then the skybox covers the entire screen. Then clear the depth buffer, thus all objects which are draw after, will cover the skybox:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// [...]
drawSkybox(texId);
glClear(GL_DEPTH_BUFFER_BIT);
// render other objects
// [...]
I have a triangle like this;
shapeRenderer.begin(ShapeType.Line);
shapeRenderer.setColor(1, 1, 0, 1);
shapeRenderer.polygon(new float[] { -10, 0, 10, 0, 0, 200 });
shapeRenderer.rotate(0, 0, 1, 1);
shapeRenderer.end();
and I rotate 1 degree in each render. But I want to fix rotation (e.g. 45) to an angle. How can I do this?
Thanks.
To have a fixed rotation you hav to rotate the ShapeRenderer only once.
There are 2 possible ways i can think about:
call shapeRenderer.rotate(0, 0, 1, 45); in the constructor or in create() / show() method
This call rotates your ShapeRenderer by 45° (last parameter) arround the Z-Axis (The 3rd parameter)
call shapeRenderer.rotate(0, 0, 1, 45); in the rendermethod, only if you did not rotate yet. So you have to keep a boolean rotated and only if it is false you call rotate() and set it to true.
To answer the question in your comment: You cannot directly set the rotation, you can only rotate (relative to the current rotation). So i would suggest to store a float rotation, and everytime you rotate your ShapeRenderer you set the new value. To set a rotation in degrees you have to rotate like:
shapeRenderer.rotate(0, 0, 1, newRotation - rotation);
rotation = newRotation;
This works only if you always rotate arround the same axis, in your case the Z-axis. Else you would have to store 3 rotations (x,y,z). If you rotate arround a custom axis, defined by for example (0.1, 0.3, 0.6) you would need to calculate the rotation for all axes. But i don't really know how to do that. I think some Vectormath would do that. But i don't think you need that.
I am making a platformer which I started developing with default java functions, but now am switching to OpenGL for everything. I have done everything like I always do with OpenGL, and what I did works fine in my other OpenGL projects. Now my problem is that LWJGL/OpenGL is scaling my textures in a very strange way.
It seems to be related to my screen's aspect ratio. (8:5)
I already had to flip the screen to make it the right way round, but as you can see the text is working fine, it's just the textured rect, and it isn't even straight on the bottom.
Here are the most important snippets from the two classes which actually use OpenGL:
Metamorph.java (main class)
public static void initGL()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, Display.getWidth(), 0, Display.getHeight(), 1, -1);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glMatrixMode(GL_MODELVIEW);
glClearColor(0, 0, 0, 1);
glDisable(GL_DEPTH_TEST);
}
public void render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glScalef(1.0f, -1.0f, 1.0f);
glTranslatef(0f, -720f, 0f);
//glScalef(1280f/800, 720f/500, 1f);
renderer.render();
Display.update();
Display.sync(60);
}
Renderer.java (rendering stuff)
private void renderMainMenuWithGL()
{
//System.out.println("Main Menu!");
glColor4f(1, 1, 1, 1);
try
{
Texture bg = loadTexture("mockery");
bg.bind();
} catch (Exception e)
{
e.printStackTrace();
}
//drawQuad(0, 0, 1280, 720, 0, 0, 1280, 720);
glPushMatrix();
{
glBegin(GL_QUADS);
glTexCoord2f(0, 0);glVertex2f(0, 0);
glTexCoord2f(0, 1);glVertex2f(0, 720);
glTexCoord2f(1, 1);glVertex2f(1280, 720);
glTexCoord2f(1, 0);glVertex2f(1280, 0);
glEnd();
}
glPopMatrix();
TrueTypeFont f = loadFont(MAINFONT, Font.PLAIN, 50);
TrueTypeFont fb = loadFont(MAINFONT, Font.PLAIN, 48);
int sel = -1;
if(Mouse.getX() > 1000 && Mouse.getX() < 1240 && Mouse.getY() > 282.5F && Mouse.getY()< 737.5F)
sel = Math.round((Mouse.getY() - 337.5F)/75F);
if(sel == 0)
drawStringRight(fb, 1240, 350, "Story", new Color(0xff516b6b));
else
drawStringRight(f, 1240, 350, "Story", new Color(0xff516b6b));
}
private void drawStringRight(TrueTypeFont f, int x, int y, String s, Color c)
{
glPushMatrix();
f.drawString(x-f.getWidth(s), y, s, c);
glPopMatrix();
}
I am also open to advice on file structure/what I did wrong elsewhere, but keep in mind this is heavily WIP
The only possible problem I can see from what you have posted is the scaling and translating you are doing prior to rendering. You should not need to do this with your projection matrix setup the way it is. Other possibilities are that either the dimensions are not really 1280x720 as you think or you have modified one of the matrices further in the code you have not posted. I would try setting both the modelview and projection matrices to the identity matrix and then use glOrtho as you have above immediatly before drawing your quad, and use Display.getWidth and Display.getHeight instead of 1280/720 for the vertex coords.
This works fine for me:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, Display.getWidth(), 0, Display.getHeight(), 1, -1);
glBegin(GL_QUADS);
glTexCoord2f(0,0);
glVertex2i(0, 0);
glTexCoord2f(1,0);
glVertex2i(Display.getWidth(), 0);
glTexCoord2f(1,1);
glVertex2i(Display.getWidth(), Display.getHeight());
glTexCoord2f(0,1);
glVertex2i(0, Display.getHeight());
glEnd();
If this still doesnt work, make sure that the viewport is also set to the entire display: glViewport(0,0,Display.getWidth(),Display.getHeight()).
Aswell, I notice that you are using glPushMatrix() and glPopMatrix before and after drawing, which does nothing and is not needed. Push and pop are used to save the current projection or modelview matrix and then reload it later, so that you can apply transformations inbetween and undo them when needed.
You're setting the projection matrix such that the coordinates of the corners of the window are (0,0) through (1680, 1050), and those are mapped into an area that covers 1280x800 pixels. Then you're drawing a 1280x720 image into it, so the screen coordinates of the image come out to span only 800x500 pixels. If you use 1280x720 in your glOrtho() call, I believe it will fix the issue. That is, you want the size of the window, not the size of the display in that call.
I can't figure out why this:
glPushMatrix();
GL11.glBindTexture(this.target, this.textureID);
glColor3f(1, 1, 1);
glTranslated(posX, posY, 0);
glBegin(GL_QUADS);
{
glTexCoord2d(posXLeft, posYTop);
glVertex2d(0, 0);
glTexCoord2d(posXLeft, posYBottom);
glVertex2d(0, verH);
glTexCoord2d(posXRight, posYBottom);
glVertex2d(verW, verH);
glTexCoord2d(posXRight, posYTop);
glVertex2d(verW, 0);
}
glEnd();
glPopMatrix();
is working perfectly, where posX and posY are obviously the position in pixels, posXLeft etc is the ratio of the texture to show.
But this:
glPushMatrix();
GL11.glBindTexture(this.target, this.textureID);
glColor3f(1, 1, 1);
glTranslated(posX, posY, 0);
glBegin(GL_LINES);
{
glVertex2d(10, 10);
glVertex2d(800, 600);
}
glEnd();
glPopMatrix();
isn't. And it should be even easier to draw lines instead of a piece of a texture.
What I want to reach is to add some zig-zag lines on a texture to simulate cracks as it is damaged or broken, but I can't even draw a single line, so I am stuck here.
Any advice?
You still got texturing enabled in your line drawing code. But you don't specify texture coordinates, so you'll draw your line with a solid color as defined by texture at the currently set texture coordinate.
My suggestion: Disable texturing for drawing that line.
As said by datenwolf you have to disable the texturing, thes thing is that than you have to re-enable it, although you will have problems the next cycle of drawing if that property is not set correctly.
the solution is:
glPushMatrix();
GL11.glBindTexture(this.target, this.textureID);
glColor3f(1, 1, 1);
glDisable(GL_TEXTURE_2D);
glTranslated(posX, posY, 0);
glBegin(GL_LINES);
{
glVertex2d(10, 10);
glVertex2d(800, 600);
}
glEnd();
glEnable(GL_TEXTURE_2D);
glPopMatrix();
and that should solve your problem.
I have a drawn a filled circle using ShapeRenderer and now I want to draw this circle as a transparent one. I am using the following code to do that: But the circle is not coming as transparent. Also, I checked th libgdx API and from the wiki, it says that, need to Create CameraStrategy. Has somebody faced similar issue ever before? If so, please give me some clues. Thanks in advance.
Gdx.gl.glEnable(GL10.GL_BLEND);
Gdx.gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
drawFilledCircle();
Gdx.gl.glDisable(GL10.GL_BLEND);
private void drawFilledCircle(){
shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.begin(ShapeType.FilledCircle);
shapeRenderer.setColor(new Color(0, 1, 0, 1));
shapeRenderer.filledCircle(470, 45, 10);
shapeRenderer.end();
}
The following code is working for me in this case, maybe it will help someone else:
Gdx.gl.glEnable(GL10.GL_BLEND);
Gdx.gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.begin(ShapeType.FilledCircle);
shapeRenderer.setColor(new Color(0, 1, 0, 0.5f));
shapeRenderer.filledCircle(470, 45, 10);
shapeRenderer.end();
Gdx.gl.glDisable(GL10.GL_BLEND);
First we need to enable blending:
Gdx.gl.glEnable(GL10.GL_BLEND);
And make sure that you don't call SpriteBatch.begin() and SpriteBatch.end() between that line of code and your Shaperender.drawSomething() line of code. I don't know why but that's what works in my case
Only this worked for me :
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
//Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); // <<< this line here makes the magic we're after
game.shapeRenderer.setProjectionMatrix(camera.combined);
game.shapeRenderer.begin(ShapeType.Filled);
go.drawShapes();
game.shapeRenderer.end();
//Gdx.gl.glDisable(GL20.GL_BLEND);
Well, there is not really a point in drawing something fully transparent. If you did want to make a half transparent circle, you would have to clear the color buffer by glClearColor before each frame and set Color alpha component to 0.5f.
If you wouldn't clear the buffer, after few render draws, the circle would blend into one with almost solid color.
private void drawFilledCircle(Camera camera){
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear( GL10.GL_COLOR_BUFFER_BIT );
shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.begin(ShapeType.FilledCircle);
shapeRenderer.setColor(new Color(0, 1, 0, 0.5f)); // last argument is alpha channel
shapeRenderer.filledCircle(470, 45, 10);
shapeRenderer.end();
}