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);
}
Related
I am trying to learn how to use box2d (a lot of this code is unashamedly stolen from the legend Dan Shiffman) so I have created a small "game" where a ball rolls in Perlin noise terrain. The obvious problem with my code is that quite quickly the ball just rolls off the screen. I know I will have to change my terrain generation as it won't keep generating as the screen moves but for now I would like to know how to get the screen to move in the first place. I want to keep the the circles x value in the center of the screen.
I have found several similar questions where the answer was to move the world but that seems like a bad idea with box2d. I also found someone mentioning a camera? class but I am a beginner and have no idea what that is or how to use it.
Some of the main code:
void setup() {
size(1000,800);
smooth();
frameRate(30);
sw = new StopWatchTimer();
sw.start();
box2d = new Box2DProcessing(this);
box2d.createWorld();
p = new player(10,10,10);
surface = new Surface();
grav = -50;
box2d.setGravity(0, grav);
}
void draw() {
background(200);
//text(sw.second(),100,100);
box2d.step();
surface.display();
time();
keyTyped();
box2d.setGravity(0, grav);
p.display();
prePos = p.getPos();
}
Some code from the player class:
player(float x, float y, float r_) {
r = r_;
makeBody(x, y, r);
body.setUserData(this);
col = color(175);
}
public void makeBody(float x, float y, float r) {
BodyDef bd = new BodyDef();
bd.position = box2d.coordPixelsToWorld(x, y);
bd.type = BodyType.DYNAMIC;
body = box2d.createBody(bd);
cs = new CircleShape();
cs.m_radius = box2d.scalarPixelsToWorld(r);
fd = new FixtureDef();
fd.shape = cs;
fd.density = 5;
fd.friction = 1;
fd.restitution = .3;
body.createFixture(fd);
}
I am well aware this question is really poorly asked but I was unsure which code would be needed and i'm not a very articulate person so if any clarification or more code is needed to make this understandable don't hesitate to yell at me for it.
You could use the translate() command. You would put in draw with the coordinates of the player as parameters.
I assume that p.getPos() returns a PVector. If this is the case, then draw would look like this:
void draw() {
pushMatrix()
translate(p.getPos().x+width/2,p.getPos().y+height/2); // <--Added Line
background(200);
//text(sw.second(),100,100);
box2d.step();
surface.display();
popMatrix()
time();
keyTyped();
box2d.setGravity(0, grav);
p.display();
prePos = p.getPos();
}
im trying to build a 3D Model, by building dynamically 3D models and translate them to where i need them.
Im starting with a basic model, trying to to achieve what is on the picture bellow. I want to dynamically build two cylinders, and the X,Y,Z of the TOP of my cylinder will be the same X,Y,Z of the BOTTOM of the second Cylinder, like the picture bellow:
For now i have this code:
public static void main(String[] args) throws FileNotFoundException, IOException {
int height = 10;
int radius = 1;
int angle = 0;
BranchGroup objRoot = new BranchGroup();
Cylinder cylinder;
Vector3f last_coordinates = new Vector3f(0f,0f,0f);
TransformGroup transf_group_cylinder = null;
//---- Working ok -----/
//build cylinder
cylinder = new Cylinder(radius, height);
transf_group_cylinder = createTransformGroup_Cylinder(new Vector3f(0f,0f,0f),angle);
transf_group_cylinder.addChild(cylinder);
objRoot.addChild(transf_group_cylinder);
last_coordinates = calculateLastPoint(height/2, angle);
System.out.println(last_coordinates);
//----------------------------//
//build 2nd cylinder
cylinder = new Cylinder(radius, height);
transf_group_cylinder = createTransformGroup_Cylinder(last_coordinates, Math.PI/2);
transf_group_cylinder.addChild(cylinder);
objRoot.addChild(transf_group_cylinder);
OBJWriter objWriter = new OBJWriter("myObj.obj");
objWriter.writeNode(objRoot);
objWriter.close();
}
private static Vector3f calculateLastPoint(int height, int angle) {
float x = (float) (height * Math.sin(angle));
float y = (float) (height * Math.cos(angle));
return new Vector3f(0, x, y);
}
private static TransformGroup createTransformGroup_Cylinder(
Vector3f last_coordinates, double angle) {
TransformGroup transf_group = new TransformGroup();
//position the model
Transform3D transform_origin = new Transform3D();
transform_origin.setTranslation(new Vector3f(0, 0, 0));
// set model in horizontal position
Transform3D transf_horizontal = new Transform3D();
transf_horizontal.rotZ(Math.PI / 2);
transform_origin.mul(transf_horizontal);
// rotate object
Transform3D angleRotation = new Transform3D();
angleRotation.rotX(angle);
transform_origin.mul(angleRotation);
Transform3D transform_xyz = new Transform3D();
transform_xyz.setTranslation(last_coordinates);
transform_origin.mul(transform_xyz); // set Transform for
transf_group.setTransform(transform_origin);
return transf_group;
}
With this code im achieving this:
My first cylinder is ok, but my 2nd cylinder is not placed in a proper place.
I can add any value for the size and angle values, so i need to calculate this two values in a dynamically way.
Can someone help solving this translation problem?
Thank you in advance.
The first step here is to give each cylinder a different color to allow you to see which one is which.
Next: When you create a cylinder, then it's centered at the origin. Since you want to chain them at the end point, you need to move them accordingly: First, you need to move the cylinder (or its transformation matrix) by -half its height to virtually move the "cylinder origin" to it's end.
The next step is that you need to apply the same transformation matrix to the end point (this time plus a full cylinder height), so it lines up with the actual end point.
That said, I would suggest you create a helper function that can create a cylinder between two points. This would allow you to say:
Point endPoint = cylinder(new Point(-1,.5,0), new Point(0,.5,0))
cylinder(endPoint, new Point(0,-.5,0))
...
or even create a helper function which accepts a list of points and creates all the cylinders between them.
I've been looking into getting an object on a two dimensional plane to follow a smooth curve defined by several control points.From what I've found, I'm looking for a Catmull-Rom-Spline.
I've been using LibGDX for my project, and it has its own Catmull-Rom-Spline implementation but I'm having trouble wrapping my head around how it works, as I've had trouble finding documentation or other source code implementing Catmull-Rom-Splines using LibGDX.
I'm looking for either an explanation of the LibGDX Catmull-Rom-Spline implementation or another way to implement a smooth path that implements control points using Catmull-Rom-Splines or another method. All I'm looking for is the ability to generate a path and pass back the x and y coordinates of a point on that path. If anyone has any suggestions or pointers, it would be appreciated. Thanks.
The libgdx Path classes (including CatmullRomSpline) are suitable for both 2D and 3D. So when creating a CatmullRomSpline, you must specify which Vector (Vector2 or Vector3) to use:
CatmullRomSpline<Vector2> path = new CatmulRomSpline<Vector2> ( controlpoints, continuous );
For example:
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
Vector2 cp[] = new Vector2[]{
new Vector2(0, 0), new Vector2(w * 0.25f, h * 0.5f), new Vector2(0, h), new Vector2(w*0.5f, h*0.75f),
new Vector2(w, h), new Vector2(w * 0.75f, h * 0.5f), new Vector2(w, 0), new Vector2(w*0.5f, h*0.25f)
};
CatmullRomSpline<Vector2> path = new CatmullRomSpline<Vector2>(cp, true);
Now you can get the location on the path (ranging from 0 to 1) using the valueAt method:
Vector2 position = new Vector2();
float t = a_vulue_between_0_and_1;
path.valueAt(position, t);
For example:
Vector2 position = new Vector2();
float t = 0;
public void render() {
t = (t + Gdx.graphics.getDeltaTime()) % 1f;
path.valueAt(position, t);
// Now you can use the position vector
}
Here's an example: https://github.com/libgdx/libgdx/blob/master/tests/gdx-tests/src/com/badlogic/gdx/tests/PathTest.java
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.
I'm not sure why my code is (slightly) laggy, and doesn't run reliably at the same speed- I think I must be doing something wrong, as many other games are completely smooth.
The pertinent code in my Renderer class is here:
public void drawPicString(Location location, String string,
RenderParams params) {
//canvas.save();
float rawX = location.getX();
float rawY = location.getY();
Bitmap rawbit = myImageCache.get(string);
//Bitmap rawbit = provider.getBitmap(string);
float thisWidth = rawbit.getWidth();
float thisHeight = rawbit.getHeight();
if(params.shouldResize){
thisWidth = params.resizex;
thisHeight = params.resizey;
}
float leftx = rawX-(thisWidth/2);
float topy = rawY-(thisHeight/2);
Matrix matrix = new Matrix();
matrix.setTranslate(leftx, topy);
if(params.shouldResize){
float toScaleY = ((float)thisHeight)/rawbit.getHeight();
float toScaleX = ((float)thisWidth)/rawbit.getWidth();
matrix.preScale(toScaleX, toScaleY);
}
if(params.shouldRotate){
matrix.preRotate((float)Math.toDegrees(params.myangle),(float)(thisWidth/2.0),(float)(thisHeight/2.0));
}
canvas.drawBitmap(rawbit, matrix, paint);
}
The only other information I can think of that's pertinent is that myImageCache is a cache of bitmaps so that it doesn't have to fetch them from resources every time they're drawn. "canvas" is a canvas drawing on a surfaceview that's passed to it each frame before the drawing begins.
Thanks in advance for any ideas!