i'm reading and loading .obj files, i want to have 4 different view ports all with different perspectives, my main problem is trying to keep the original aspect ration of the object and prevent it from changing with window re-size or transformations like rotation.
This is what i'm trying to get:
This is what i'm getting (in fullscreen):
A portion of my display code:
GL2 gl = drawable.getGL().getGL3bc();
gl.glEnable(GL_DEPTH_TEST);
gl.glDepthFunc(GL_LEQUAL);
gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
gl.glOrtho(xMin - (0.1 * (xMax - xMin)), xMax
+ (0.1 * (xMax - xMin)), yMin - (0.1 * (yMax - yMin)), yMax
+ (0.1 * (yMax - yMin)), zMin - (0.1 * (zMax - zMin)), zMax
+ (0.1 * (zMax - zMin)));
gl.glMatrixMode(GL_PROJECTION);
gl.glViewport(0, 0, width / 2, height / 2);
gl.glLoadIdentity();
gl.glPushMatrix();
gl.glRotatef(-90f, 1f, 0f, 0f);
draw(gl);
gl.glPopMatrix();
gl.glViewport(width / 2, height / 2, width / 2, height / 2);
gl.glLoadIdentity();
gl.glPushMatrix();
gl.glRotated(-90, 0, 1, 0);
draw(gl);
gl.glPopMatrix();
gl.glViewport(0, height / 2, width / 2, height / 2);
gl.glLoadIdentity();
gl.glPushMatrix();
draw(gl);
gl.glPopMatrix();
xMax,yMin are the maximum and minimum values of the x axis in the points given in the .obj file.
height and width are the current dimensions of the window.
xMax,yMin are the maximum and minimum values of the x axis in the points given in the .obj file. height and width are the current dimensions of the window.
Well, this is most likely your problem. By setting an orthogonal view that relies on the minimum and maximum values of each coordinate, you will be actually distorting the object, because such a region doesn't have the same aspect ratio as the window. To make it clearer, if you were to put the entire model inside a box and take a picture of it, the application would stretch it so that the Y and X coordinates (assuming Y as the up-down axis) make part of the entire viewport. This would be seen as enlarging the "picture"'s width, or squeezing the height.
So you should adjust these parameters to remove the distortion. Since the model is tall (larger in Y than X), I suggest applying this trick before setting the orthogonal view:
xMin = xMin * width / height;
xMax = xMax * width / height;
Related
I create a 2d game similar to a classic diepio. I created a system for positioning the player's barrel in a specific direction. The updated angle is sent to the server. When the player clicks, the server creates a missile. This only works correctly when the barrel is attached to the center of the player's body. When I want to move the barrel away from the center of the body, there is a problem. I don't know how to update the server-side position where the projectile spawns.
In the image below, the barrel rotates around the center of the player's body. I marked the missile's flight path with the red line.
On this image, the barrels also have a rotation axis in the player's center, but have been shifted to the side. The green line marked the route the missile should take. Unfortunately, I don't know how to do it correctly.
How to update the projectile's spawn point by a given distance (e.g. 10) from the basic distance (if the barrel was not moved) based on the player's angle of rotation and his position?
Projectile spawn method:
float angle = (float) ((player.getRotation() + 90) * Math.PI / 180f);
float forceX = (float) Math.cos(angle);
float forceY = (float) Math.sin(angle);
spawnProjectile(player.getPosition().x + (forceX * 3f), player.getPosition().y + (forceY * 3f));
If I understood your question correctly, you want to find the two points marked in orange in the following image:
Since you know the direction in which the missiles should fly (the red line), the distance from the center position (e.g. 10) and you know that there is a 90° angle between the movement vector of the missile (red line) and the connection line between the two starting positions of the missiles (marked as black line in the image) you can calculate the resulting positions like this:
float angle = (float) ((player.getRotation() + 90) * Math.PI / 180f);
float forceX = (float) Math.cos(angle);
float forceY = (float) Math.sin(angle);
// the center point (start of the red line in the image)
float centerX = player.getPosition().x + (forceX * 3f);
float centerY = player.getPosition().y + (forceY * 3f);
float offsetFromCenterDistanceFactor = 1f; // increase this value to increase the distance between the center of the player and the starting position of the missile
// the vector towards one of the starting positions
float offsetX1 = forceY * offsetFromCenterDistanceFactor;
float offsetY1 = -forceX * offsetFromCenterDistanceFactor;
// the vector towards the other starting position
float offsetX2 = -offsetX1;
float offsetY2 = -offsetY1;
//spawn the upper missile
spawnProjectile(centerX + offsetX1, centerY + offsetY1);
//spawn the lower missile
spawnProjectile(centerX + offsetX2, centerY + offsetY2);
For more detail on the calculation of the orthogonal vectors see this answer.
As I have it understood, a projection matrix scales a polygon depending on how far away or close it is from the camera. Though I might be completely wrong. My question is, how does the projection matrix "know" to show the sides of the following cube, as the camera moves, when the matrix is only supposed "scale" polygons?
Notice in the image, the cube is off to the right side of the screen, by moving the camera to the left. If the camera is moved in the opposite direction (to the right) in order to center the cube, the side of the cube will disappear as expected.
Here is my matrix code:
private void createProjectionMatrix(){
float aspectRatio = (float) Display.getWidth() / (float) Display.getHeight();
float y_scale = (float) ((1f / Math.tan(Math.toRadians(FOV/2f))) * aspectRatio);
float x_scale = y_scale / aspectRatio;
float frustum_length = FAR_PLANE - NEAR_PLANE;
projectionMatrix = new Matrix4f();
projectionMatrix.m00 = x_scale;
projectionMatrix.m11 = y_scale;
projectionMatrix.m22 = -((FAR_PLANE + NEAR_PLANE) / frustum_length);
projectionMatrix.m23 = -1;
projectionMatrix.m32 = -((2 * NEAR_PLANE * FAR_PLANE) / frustum_length);
projectionMatrix.m33 = 0;
}
The function of a projection matrix (in the context of graphics APIs, such as OpenGL) is to transform vertex positions from view-space into clip-space.
Clip space is generally a unit box (although in D3D it's a half-unit box). If a vertex position after being transformed into clip-space does not lie within that unit box, then it is clipped. This is essentially how the system "knows" the cube is visible on the screen.
Let's say I want a sprite to be circulating around certain point. I could draw a circle around this point using drawOval method but how to get specific coordinates of this oval on which moving sprite could be drawn on.
To get all points on the circumference of an ellipse (or oval), you can use the following formula (posX and posY are coords of the center of the oval and width and height are the width and height of the oval respectively):
x = posX + cos(angle) * width * 0.5
y = posY + sin(angle) * height * 0.5
Where angle goes from 0 to 2 * PI radians.
You can increment angle by something like delta_time * speed where delta_time is the time it took to render the last frame (or rather, time since the last frame) in seconds and speed is the speed (in unit/second) at which you want the sprite to move.
i have created a 10x10 grid in the center of the screen in android, now i would like to give each square in the grid a coordinate. for example top left square in the grid would be 0 then 1, 2,3 and so on. But i dont know how to do this. i am trying to do this in a draw class which extends view. my code of what i am trying is below
public int coordinates(int posX, int posY){
int startX = (screenWidth / 2) - (rectSide / 2);
int startY = (screenHeight / 2) - (rectSide / 2);
//for(int i=0; i<=10000; i+=100){
xCoord = (startX + (posX*100));
yCoord = (startY + (posY*100));
}
You know you start at point 0,0 top left. So assuming you have equally spaces squares you can just do the screen height / 10 to get how far apart each square should be in the y direction. And then do the same for the x direction. Say your screen was 1000 pixels tall.
Then your grid at position (0,1) would be at (0,100) pixels. (0,2) would be (0,200) you are just multiplying the y coordinate by the height of each square in the grid.
I'm currently working on a simple textured rectangle class using LWJGL (GL11). This is what I have so far in the draw method.
glEnable(GL_TEXTURE_2D);
color.bind();
glBegin(GL_QUADS);
t.bind();
if (centered)
{
glTexCoord2d(0, 0);
glVertex2d(x - (width / 2), y - (height / 2));
glTexCoord2d(t.getWidth(), 0);
glVertex2d(x + (width / 2), y - (height / 2));
glTexCoord2d(t.getWidth(), t.getHeight());
glVertex2d(x + (width / 2), y + (height / 2));
glTexCoord2d(0, t.getHeight());
glVertex2d(x - (width / 2), y + (height / 2));
}
else
{
glTexCoord2d(0, 0);
glVertex2d(x, y);
glTexCoord2d(t.getWidth(), 0);
glVertex2d(x + width, y);
glTexCoord2d(t.getWidth(), t.getHeight());
glVertex2d(x + width, y + height);
glTexCoord2d(0, t.getHeight());
glVertex2d(x, y + height);
}
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
The problem is with the second to last line (glBindTexture(GL_TEXTURE_2D, 0)). If I leave this on, the image will display for a split second (probably one frame) and then turn solid white. If I comment this out, it will display, but always displays the last texture that was loaded. Any ideas?
I think it's because you are binding your texture between the glBegin() and glEnd() calls. This is invalid. I'm guessing when you leave the glBindTexture(GL_TEXTURE_2D, 0) call off, then the binding is taking effect the next frame. Not sure why it would work for one frame, though.
You can use glGetError to see if there are any errors generated.