When I try to move an opengl quad outside the size of the main window, it doesn't render.
Say if I have a window 600x800. Then I resize it to be full screen. Once I move the quad(player) outside the defined window properties, it disappears.
I think this is essential because I'm working on a top down RPG and he will be moving around on the x and y plane. Also if that isn't enough, how would I make a camera that keeps the player in the center...
So far I have
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 845, 0, 520, -1, 1);
glMatrixMode(GL_MODELVIEW);
I havent been able to test it due to the first problem
On the part to keep the camera in the center. Just translate everything -x, -y relative to the camera/player's position.
glTranslatef(-cameraX, -cameraY, 0);
So when you move the player change the players position and translate everything the opposite way.
Related
I'm working on a scroll-box in minecraft.
The scroll-box has one problem, some controls will render outside of the box, so i decided to look up if it's possible to prevent that.
I found stencils, but it doesn't work out, maybe i did something wrong?
GL11.glEnable(GL11.GL_BLEND);
GL11.glEnable(GL11.GL_STENCIL_TEST);
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glDisable(GL11.GL_DEPTH_TEST);
GL11.glClearStencil(0);
GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT);
GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 1);
GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE);
and this is the line of rendering the scroll-box background:
Vector4d color = new Vector4d(140, 140, 140, 255);
RenderHelper2D.drawGradientRect(1, 1, this.width-1, this.height-1, color, color);
http://i.imgur.com/Ycg7AKo.png (It's the black outlined gray pattern)
GL11.glBlendFunc(GL11.GL_ONE_MINUS_DST_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glStencilFunc(GL11.GL_EQUAL, 1, 1);
GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP );
render all objectives inside the scroll-box (the buttons). Which shouldn't be shown outside of the box.
gui.drawForeground(renderer);
and reset everything
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glColorMask(true, true, true, true);
GL11.glDisable(GL11.GL_STENCIL_TEST);
I think you are looking for glScissor
It lets you basically assign a rectangular cropping window on your screen, and whatever you draw, nothing will ever be drawn outside of this rectangle.
Don't forget to call glEnable(GL_SCISSOR_TEST) before and glDisable(GL_SCISSOR_TEST) after you draw your scroll box. It won't work without the enable, and it won't stop without the disable ;)
Keep in mind that the values supplied to glScissor are integers for the origin and the width and height of the desired cropping window, the origin being defined as the lower left. Thus,
glEnable(GL_SCISSOR_TEST)
glScissor(0,0,100,100)
:: DRAW YOUR CONTROLS HERE ::
glDisable(GL_SCISSOR_TEST)
will create a 100x100 cropping window in the lower left corner of your screen.
You can use stencilbuffers if you want, but those are for more complicated tasks. Since UI usually works with rectangles, glScissor is perfect for it.
I have a quad drawn on the screen, positioned at the top of the screen and centred. As I resize the screen so it is not as high, the quad appears to move in the opposite direction from what it should, IE, up at the same rate it should be going down on my monitor.
It is constantly being set to be at the top of the screen and centred each loop, before rendering.
this.location[0] = (Display.getWidth()/2)-(this.size[0]/2);
this.location[1] = 0;
Then I render the quad and print out its Y location. this consistently returns 0, no matter what I resize the window to. By printing out the mouse coordinates I can confirm that the top of the screen is 0 when it is resized. Why is it then, that even though I am setting the quad to be at 0, then rendering it exactly after, it still isn't drawn at 0?
Is there some Opengl or LWJGL concept I don't understand?
Here's the Opengl Setup code.
GL11.glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,Display.getWidth(),Display.getHeight(),0 ,1, -1);
glMatrixMode(GL_MODELVIEW);
Since nobody has answered this, and I have found a solution, inefficient as it may be, here's an answer.
I Changed the line
glOrtho(0,Display.getWidth(),Display.getHeight(), 0 ,1, -1);
to
glOrtho(0,Display.getWidth(), 0,Display.getHeight(),1, -1);
Which means instead of the top being the top, the top is now the bottom of the screen. I then had to create another variable inside my box class, called realY which is the actual y coordinate of the box/quad's left hand corner.
Then with some simple math (this.realY = (Display.getHeight() - this.location[1])-this.size[1];) I convert the input Y into the upside down version of itself, so 0 becomes the height of the screen, and vise versa
To me, this seems like a inefficient solution, and more of a workaround. If anyone has a better answer, please post it.
I was trying to follow example codes to simply display a rectangle on a black background, but it didn't seem to be displaying. What I did was
private static void initGL(){
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,Display.getWidth(),0,Display.getHeight(),-1,1);
glMatrixMode(GL_MODELVIEW);
glDisable(GL_DEPTH_TEST); //2D mode
glColor3f(0.5f, 0.0f, 1.0f);
glBegin(GL_QUADS);
glVertex2f(-0.75, 0.75);
glVertex2f(-0.75, -0.75);
glVertex2f(0.75, -0.75);
glVertex2f(0.75, 0.75);
glEnd();
}
It doesn't display anything on the screen except for a black background. Does anyone know what I might have done wrong? I'm using lwjgl in eclipse.
First things first: You only have to run the whole
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,Display.getWidth(),0,Display.getHeight(),-1,1);
glMatrixMode(GL_MODELVIEW);
thing once during your program, probably shortly after you run Display.create().
Also, you're tessellating using the wrong vertices. You wrote
glVertex2f(-0.75, 0.75);
glVertex2f(-0.75, -0.75);
glVertex2f(0.75, -0.75);
glVertex2f(0.75, 0.75);
which means draw a rectangle from (-0.75, -0.75) pixels to (0.75, 0.75) pixels. This is too small to be noticed. My guess is you assumed glVertex2f deals with fractions of the display width. It does not. glVertex2f deals with actual coordinates, it just allows fractional pixels, unlike glVertex2i (this is useful believe it or not, it helps with smoother animations). Something like
glVertex2f(100F, 100F);
places a vertex at (100, 100), and is effectively equivalent to
glVertex2i(100, 100);
Also, remember that negative pixels will be rendered off the screen, because OpenGL's origin of the coordinate system, (0, 0), is in the lower left and behaves like the first quadrant from the coordinate system in math class, not like the traditional computer coordinate system with (0, 0) in the upper left.
As for the the black background, LWJGL's Display has a black background by default, so it's recommended to draw a quad with your background color that covers the entire display width and height. One quad won't really affect your performance.
glVertex2f uses same size units as your glOrtho so unless your display width and height are in units of ones, like 10 or less, you may not see anything!
I am making a 3d game with LWJGL. In this game, whenever I press an arrow key, I want the screen to rotate in that direction, regardless of the current orientation. I am struggling to implement this in code. Using three glRotatef functions based off of a rotation vector3f, does not accomplish this. Rotating up and down work because glRotatef(rotation.x, 1, 0, 0) is called first, but left and right only work when your not looking up or down. If you are, you rotate around a universal y axis, and camera spins. I saw that another implementation could use gluLookAt(), but I imagine I would encounter the same problem.
EDIT
I thought I solved my issue by changing the order by which glRotatef()'s where called depending on the direction I want to rotate. I thought this would work because in my game, I will only be rotating one axis at a time. It worked somewhat but in some orientations it doesn't.
if(updown){
glRotatef(rotation.x, 1, 0, 0);
glRotatef(rotation.y, 0, 1, 0);
} else if(leftright){
glRotatef(rotation.y, 0, 1, 0);
glRotatef(rotation.x, 1, 0, 0);
}
glTranslatef(position.x, position.y, position.z);
gluLookAt would probably get you there much quicker, but you would need to manually rotate the eye coordinate about the origin coordinate. With gluLookAt you also need to calculate an up vector if you plan to rotate around all 3 axes.
I have a hunch you just need to add a glTranslate before you do your glRotate so that the camera has something to orbit around.
If you show some code you might be able to get more help.
I am over this issue and have moved on. Because I am only going to rotate one axis 90 degrees at a time, I went through all 64 possible orientations and applied the necesary transforations manualy.
I've been working on a very simple game, and I've decided to include some basic textures. I was experimenting with the code, and for some reason, I have no idea why, I cannot get the textures to map correctly. Right now, I am simply trying to map a green rectangle (512 x 64 .png file) to the bottom of a screen of size 640 x 480. This green rectangle is supposed to represent the ground. Here is an image of my failed attempt:
Here is the relevent code:
In the Boot class I have created I call this function:
public void initGL() {
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, gameWidth, gameHeight, 0, 1, -1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glEnable(GL11.GL_TEXTURE_2D);
}
In the ground class I have created, I call a draw function. The texture is loaded in the Boot class, and set as a protected variable which I bind and use in the ground.draw() function.
public void draw() {
this.texture.bind();
GL11.glLoadIdentity();
GL11.glTranslatef(0, 0, 0);
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0, 0);
GL11.glVertex2f(0, 480 - height);
GL11.glTexCoord2f(1, 0);
GL11.glVertex2f(640, 480 - height);
GL11.glTexCoord2f(1, 1);
GL11.glVertex2f(640, 480);
GL11.glTexCoord2f(0, 1);
GL11.glVertex2f(0, 480);
GL11.glEnd();
}
Also, if you'll note above I have a GL11.glTranslatef call. I can get my ground texture in the right position if I simply make the 2nd argument for this function large enough to displace it further in the y direction, however I don't wish to do it this way. I really don't know how the texture ended up in this location in the first place, and I would like to figure out why.
I think there is a problem with your matrices :
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, gameWidth, gameHeight, 0, 1, -1);
I never really used OpenGL fixed pipeline but what I see or actually DON"T SEE is where you multiply your matrices. You must multiply the model matrix of your quad with projection matrix which is glOrtho(). ( glPushMatrix/glPopMatrix )
So in your scenario you should :
Push Ortho matrix.
Push camera(view) matrix (if exists).
Push Model Matrix.
Pop Model Matrix.
Pop camera (view) matrix (if exists).
Pop Ortho matrix.
If the Ortho never changes I think you need to push it only once.
Also make sure you take into account ortho coordinates changes because depending on glOrtho() setup the world center going to be different from the center of the screen.Usually top left or bottom left corner.
The bottom line is : while I don't recommend you using the old and deprecated OpenGL at all, you should take a look how the transformations are done the right way in the numerous online tutorials.Also here