I'm working on a game in Java using LWJGL and I'm trying to make it rotate to look at a point in 3D space. I have tried every "lookAt" method I can find on the internet, But I just can't get it to work (The camera just doesn't look in the right direction).
Could you help me figure out how to do this?
EDIT:
Figured it out, Just needed to invert the matrix. Here is the final code if you were having the same issue:
public static Matrix4f lookAt(Vector3f eye, Vector3f center, Vector3f up) {
Vector3f forward = new Vector3f(0, 0, 0);
Vector3f.sub(center, eye, forward);
forward.normalise();
Vector3f side = new Vector3f(0, 0, 0);
Vector3f.cross(forward, up, side);
side.normalise();
Vector3f.cross(side, forward, up);
Matrix4f matrix = new Matrix4f();
matrix.m00 = side.x;
matrix.m01 = side.y;
matrix.m02 = side.z;
matrix.m10 = up.x;
matrix.m11 = up.y;
matrix.m12 = up.z;
matrix.m20 = -forward.x;
matrix.m21 = -forward.y;
matrix.m22 = -forward.z;
matrix.invert();
return matrix;
}
Related
recently I have been implementing 3D AABB's into my game engine, to accomplish rotations I use a simple method of rotating all 8 calculated corners around the center of the box using my Vector3f.rotate() method. But as you may notice below it is very inefficient. If you want to sort though the whole class here is the github (https://github.com/EquilibriumGames/Flounder-Engine/blob/master/src/flounder/physics/AABB.java) otherwise here is the snipit I need help with, I beleve there could be simpler methods out there but I want to know what you think. Thank you!
// Creates the 8 AABB corners and rotates them.
Vector3f FLL = new Vector3f(destination.minExtents.x, destination.minExtents.y, destination.minExtents.z);
Vector3f.rotate(FLL, rotation, FLL);
Vector3f FLR = new Vector3f(destination.maxExtents.x, destination.minExtents.y, destination.minExtents.z);
Vector3f.rotate(FLR, rotation, FLR);
Vector3f FUL = new Vector3f(destination.minExtents.x, destination.maxExtents.y, destination.minExtents.z);
Vector3f.rotate(FUL, rotation, FUL);
Vector3f FUR = new Vector3f(destination.maxExtents.x, destination.maxExtents.y, destination.minExtents.z);
Vector3f.rotate(FUR, rotation, FUR);
Vector3f BUR = new Vector3f(destination.maxExtents.x, destination.maxExtents.y, destination.maxExtents.z);
Vector3f.rotate(BUR, rotation, BUR);
Vector3f BUL = new Vector3f(destination.minExtents.x, destination.maxExtents.y, destination.maxExtents.z);
Vector3f.rotate(BUL, rotation, BUL);
Vector3f BLR = new Vector3f(destination.maxExtents.x, destination.minExtents.y, destination.maxExtents.z);
Vector3f.rotate(BLR, rotation, BLR);
Vector3f BLL = new Vector3f(destination.minExtents.x, destination.minExtents.y, destination.maxExtents.z);
Vector3f.rotate(BLL, rotation, BLL);
destination.minExtents = Maths.min(FLL, Maths.min(FLR, Maths.min(FUL, Maths.min(FUR, Maths.min(BUR, Maths.min(BUL, Maths.min(BLR, BLL)))))));
destination.maxExtents = Maths.max(FLL, Maths.max(FLR, Maths.max(FUL, Maths.max(FUR, Maths.max(BUR, Maths.max(BUL, Maths.max(BLR, BLL)))))));
Hi I am attempting to build OBB's into my 3d java game using lwjgl. Currently I am just attempting to rotate the OBB around using matrix4f's and testing it by rendering the points. So, when I render it, with its xyx=0,0,0 and its angle on the x axis =1 it will rotate fine. But when i move the y axis up say y=5 the rotation will no longer go around the center.
I tried fixing this with translation but It doesnt work. Im also wondering if there is a way to access opengl's push/pop and rotate methods to get those variables for my points because opengl rotate does it perfectly.
This is my OBB class:
public OBB(float x, float y, float z, float angleX, float angleY, float angleZ, float sizeX, float sizeY, float sizeZ){
this.x=x;
this.y=y;
this.z=z;
this.angleX=angleX;
this.angleY=angleY;
this.angleZ=angleZ;
this.sizeX=sizeX;
this.sizeY=sizeY;
this.sizeZ=sizeZ;
posUBR = new Vector3f(x-sizeX,y+sizeY,z+sizeZ);//UpperBackRight
posUBL = new Vector3f(x-sizeX,y+sizeY,z-sizeZ);//UpperBackLeft
posUFL = new Vector3f(x+sizeX,y+sizeY,z-sizeZ);//UpperForLeft
posUFR = new Vector3f(x+sizeX,y+sizeY,z+sizeZ);//UpperForRight
posLBR = new Vector3f(x-sizeX,y-sizeY,z+sizeZ);//LowerBackRight
posLBL = new Vector3f(x-sizeX,y-sizeY,z-sizeZ);//LowerBackLeft
posLFL = new Vector3f(x+sizeX,y-sizeY,z-sizeZ);//LowerForLeft
posLFR = new Vector3f(x+sizeX,y-sizeY,z+sizeZ);//LowerForRight
posUBR=rotMat(posUBR);
posUBL=rotMat(posUBL);
posUFL=rotMat(posUFL);
posUFR=rotMat(posUFR);
posLBR=rotMat(posLBR);
posLBL=rotMat(posLBL);
posLFL=rotMat(posLFL);
posLFR=rotMat(posLFR);
}
This is my rotation method:
public Vector3f rotMatrix(Vector3f point) {
Matrix4f rotationMatrix = new Matrix4f();
rotationMatrix.m00 = point.x;
rotationMatrix.m10 = point.y;
rotationMatrix.m20 = point.z;
rotationMatrix.translate(new Vector3f(-x,-y,-z));
rotationMatrix.rotate(angleX,new Vector3f(1,0,0));
rotationMatrix.rotate(angleY,new Vector3f(0,1,0));
rotationMatrix.rotate(angleZ,new Vector3f(0,0,1));
rotationMatrix.translate(new Vector3f(x,y,-z));
return new Vector3f(rotationMatrix.m00, rotationMatrix.m10, rotationMatrix.m20);
}
public void rotate(){
posUBR=rotMatrix(posUBR);
posUBL=rotMatrix(posUBL);
posUFL=rotMatrix(posUFL);
posUFR=rotMatrix(posUFR);
posLBR=rotMatrix(posLBR);
posLBL=rotMatrix(posLBL);
posLFL=rotMatrix(posLFL);
posLFR=rotMatrix(posLFR);
}
My render function is a bit long to put in here but it basically renders a cube.
Sorry all I needed to do was this set to origin function:
public void setToOrigin(){
posUBR = new Vector3f(0-sizeX,0+sizeY,0+sizeZ);
posUBL = new Vector3f(0-sizeX,0+sizeY,0-sizeZ);
posUFL = new Vector3f(0+sizeX,0+sizeY,0-sizeZ);
posUFR = new Vector3f(0+sizeX,0+sizeY,0+sizeZ);
posLBR = new Vector3f(0-sizeX,0-sizeY,0+sizeZ);
posLBL = new Vector3f(0-sizeX,0-sizeY,0-sizeZ);
posLFL = new Vector3f(0+sizeX,0-sizeY,0-sizeZ);
posLFR = new Vector3f(0+sizeX,0-sizeY,0+sizeZ);
}
I have problem in moving camera behind the car.The camera can not adjusting itself to be directly behind the new direction of the car.
My code:
Vector3 tmpV = new Vector3();
Quaternion quatRotation = new Quaternion();
//chassis is car
chassis.transform.getTranslation(camera.position);
tmpV.set(camera.position).sub(5, 0, 5).y = 0f;
chassis.transform.getRotation(quatRotation);
camera.rotate(quatRotation);
camera.position.add(tmpV.nor().scl(-4f)).y = 4.f;
chassis.transform.getTranslation(tmpV);
camera.lookAt(tmpV);
camera.up.set(Vector3.Y);
It is currently happening when moving right:
What i needs to happen when moving right:
By using of this class from this link
that Xoppa posted in the comment:
camera.desiredLocation.set(new Vector3(0, 5, 5));
camera.transform=chassis.transform;
camera.up.set(Vector3.Y);
My Blender 3D object that was exported with triangulated faces and UV's written doesn't apply the texture properly.
It looks like this:
My render code:
Color.white.bind();
texture.bind();
glBegin(GL_TRIANGLES);
for(ObjFace face : model.faces){
float[] vertex1 = model.vertices[face.indices[0]-1];
float[] vertex2 = model.vertices[face.indices[1]-1];
float[] vertex3 = model.vertices[face.indices[2]-1];
float[] normal1 = model.normals[face.normals[0]-1];
float[] normal2 = model.normals[face.normals[1]-1];
float[] normal3 = model.normals[face.normals[2]-1];
float[] tex1 = model.texCoords[face.texCoords[0]-1];
float[] tex2 = model.texCoords[face.texCoords[1]-1];
float[] tex3 = model.texCoords[face.texCoords[2]-1];
glNormal3f(normal1[0], normal1[1], normal1[2]);
glTexCoord2f(tex1[0], tex1[1]);
glVertex3f(vertex1[0], vertex1[1], vertex1[2]);
glNormal3f(normal2[0], normal2[1], normal2[2]);
glTexCoord2f(tex2[0], tex2[1]);
glVertex3f(vertex2[0], vertex2[1], vertex2[2]);
glNormal3f(normal3[0], normal3[1], normal3[2]);
glTexCoord2f(tex3[0], tex3[1]);
glVertex3f(vertex3[0], vertex3[1], vertex3[2]);
}
glEnd();
The parsing code:
for (int i = 0; i < lines.length; ++i) {
String[] spaced = lines[i].split(" ");
if (lines[i].startsWith("v ")) {
float[] vertices = new float[3];
vertices[0] = parseFloat(spaced[1]);
vertices[1] = parseFloat(spaced[2]);
vertices[2] = parseFloat(spaced[3]);
verticesArray.add(vertices);
} else if (lines[i].startsWith("vn ")) {
float[] normals = new float[3];
normals[0] = parseFloat(spaced[1]);
normals[1] = parseFloat(spaced[2]);
normals[2] = parseFloat(spaced[3]);
normalsArray.add(normals);
} else if (lines[i].startsWith("vt ")) {
float[] texCoords = new float[2];
texCoords[0] = parseFloat(spaced[1]);
texCoords[1] = parseFloat(spaced[2]);
texCoordsArray.add(texCoords);
} else if (lines[i].startsWith("f ")) {
int[] faceIndices = new int[3];
int[] faceNormals = new int[3];
int[] faceTextureCoords = new int[3];
faceIndices[0] = parseInt(spaced[1].split("/")[0]);
faceIndices[1] = parseInt(spaced[2].split("/")[0]);
faceIndices[2] = parseInt(spaced[3].split("/")[0]);
faceNormals[0] = parseInt(spaced[1].split("/")[2]);
faceNormals[1] = parseInt(spaced[2].split("/")[2]);
faceNormals[2] = parseInt(spaced[3].split("/")[2]);
faceTextureCoords[0] = parseInt(spaced[1].split("/")[1]);
faceTextureCoords[1] = parseInt(spaced[2].split("/")[1]);
faceTextureCoords[2] = parseInt(spaced[3].split("/")[1]);
faceArray.add(new ObjFace(faceIndices, faceNormals, faceTextureCoords));
}
}
Although I'm not sure if it could be a problem with my Blender export.
Thanks.
EDIT: Updated pic after I made the texture image's width and height powers of two.
Edit 2: I tried a simple box to make sure that it wasn't the model that was screwing up and tested the face culling. On the box, culling the back faces fixes the problem to some extent however, on the cup it makes little difference.
Edit 3: I included a video to demonstrate what I think is the problem. I think that the triangular glitch is caused by overlapping triangles like with the handle is in front of the actual cup. youtube vid
Is that another instance of the 'textures that have sizes not power of 2' problem ? lwjgl will extend your texture to a power of 2 size, meaning your UV coordinates that are [0...1] will be wrong, they should be [0 ... 0.5783] because the rest is lwjgl padding to reach power of 2. Can't find a reference...
IIRC, in GLES20, the normals for a triangle are indicated by the winding (clock wise or counter clock wise). I'm not sure exactly what GL will understand if you set a normal per vertex (that's for lighting) and none for the triangle. I'm not sure you can set one for a triangle, meaning it will be computed from vertex position+winding. What makes me think it's a problem is the fact that all your quads are half rendered (one triangle in two).
I'm trying to write a little game with third-person-camera and I'm just wondering about gluLookAt function. It works with Opengl 1.1, but I'm using 3.2 one so I need something that can return Matrix4f to me, but I didn't find anything on the Internet except some code in C++ and I found it extremely hard to translate it to the LWJGL (their API's are not the same, no sir). For example, I tried to remake this code (This link) :
// ----------------------------------------------------
// View Matrix
//
// note: it assumes the camera is not tilted,
// i.e. a vertical up vector (remmeber gluLookAt?)
//
void setCamera(float posX, float posY, float posZ,
float lookAtX, float lookAtY, float lookAtZ) {
float dir[3], right[3], up[3];
up[0] = 0.0f; up[1] = 1.0f; up[2] = 0.0f;
dir[0] = (lookAtX - posX);
dir[1] = (lookAtY - posY);
dir[2] = (lookAtZ - posZ);
normalize(dir);
crossProduct(dir,up,right);
normalize(right);
crossProduct(right,dir,up);
normalize(up);
float aux[16];
viewMatrix[0] = right[0];
viewMatrix[4] = right[1];
viewMatrix[8] = right[2];
viewMatrix[12] = 0.0f;
viewMatrix[1] = up[0];
viewMatrix[5] = up[1];
viewMatrix[9] = up[2];
viewMatrix[13] = 0.0f;
viewMatrix[2] = -dir[0];
viewMatrix[6] = -dir[1];
viewMatrix[10] = -dir[2];
viewMatrix[14] = 0.0f;
viewMatrix[3] = 0.0f;
viewMatrix[7] = 0.0f;
viewMatrix[11] = 0.0f;
viewMatrix[15] = 1.0f;
setTranslationMatrix(aux, -posX, -posY, -posZ);
multMatrix(viewMatrix, aux);
}
I can understand everything until "float aux[16]", then it just gets messy in my mind, especially in the end.
Can someone make it clear for me? Maybe someone already made "gluLookAt-clone" or something?
EDIT:
Thank you, Brett, now I must understand how to express that in code). You say that "aux" is a matrix, but we give it only 3 floats, so its better be a vector, BUT if it is a vector, so how do I multiply it with 4x4 ViewMatrix? And I cant find a way to just fill Matrix4f with numbers, there is no methods in lib to do that (most likely that because I'm noob and I can't find it, but hey, I really can't)
FINAL EDIT:
Finally I got it to work. I just wasn't understanding full matrix stuff that was required. Here is final working code, if someone interested(I guess not but whatever)). To deal with it, don't forget to setup projection matrix in the begining.
void setCamera(float posX, float posY, float posZ,
float lookAtX, float lookAtY, float lookAtZ) {
Vector3f dir = new Vector3f(lookAtX - posX, lookAtY - posY, lookAtZ - posZ);
Vector3f up = new Vector3f(0, 1f, 0);
Vector3f right = new Vector3f();
dir.normalise();
Vector3f.cross(dir,up,right);
right.normalise();
Vector3f.cross(right,dir,up);
up.normalise();
Matrix4f aux = new Matrix4f();
viewMatrix = new Matrix4f();
viewMatrix.m00 = right.getX();
viewMatrix.m01 = right.getY();
viewMatrix.m02 = right.getZ();
viewMatrix.m03 = 0.0f;
viewMatrix.m10 = up.getX();
viewMatrix.m11 = up.getY();
viewMatrix.m12 = up.getZ();
viewMatrix.m13 = 0.0f;
viewMatrix.m20 = -dir.getX();
viewMatrix.m21 = -dir.getY();
viewMatrix.m22 = -dir.getZ();
viewMatrix.m23 = 0.0f;
viewMatrix.m30 = 0.0f;
viewMatrix.m31 = 0.0f;
viewMatrix.m32 = 0.0f;
viewMatrix.m33 = 1.0f;
//setup aux as a translation matrix by placing positions in the last column
aux.m30 = -posX;
aux.m31 = -posY;
aux.m32 = -posZ;
//multiplication(in fact translation) viewMatrix with aux
Matrix4f.mul(viewMatrix, aux, viewMatrix);
}
I have a first-person camera class that I use (on OpenGL 3.2) which handles movement: x, y and z positions as well as pitch, yaw and roll. The way that I do this is update positions each cycle and a part of rendering I apply these updates from the camera by creating a new view matrix and sending it as a uniform to my vertex shader.
Here is the method that accomplishes this:
#Override
public void applyTranslations(int uniformLocation) {
viewMatrix = new Matrix4f();
Matrix4f.rotate(MatrixUtils.degreesToRadians(pitch), new Vector3f(1, 0, 0), viewMatrix, viewMatrix);
Matrix4f.rotate(MatrixUtils.degreesToRadians(yaw), new Vector3f(0, 1, 0), viewMatrix, viewMatrix);
Matrix4f.rotate(MatrixUtils.degreesToRadians(roll), new Vector3f(0, 0, 1), viewMatrix, viewMatrix);
Matrix4f.translate(new Vector3f(-x, -y, -z), viewMatrix, viewMatrix);
viewMatrix.store(matrix44Buffer); matrix44Buffer.flip();
glUniformMatrix4(uniformLocation, false, matrix44Buffer);
}
Where uniformLocation is the location of my viewMatrix uniform within my shaders.
Steps are to:
Create a new 4x4 matrix
Apply rotations for x, y and z axes
Apply translation for the x, y and z axes
Send matrix to shaders
The code is just populating the matrix as described in the gluLookAt() documentation.
Up until float aux[16], the code is creating an orthonormal basis (3 mutually perpendicular vectors as 'axes'). The properties of orthogonal rotation matrices allow viewMatrix elements to be set directly. aux is then (presumably) populated as a translation matrix, and the transforms are then concatenated with multMatrix.