Creating a terrain from a heightmap - java

I want to create realistic terrain using java and lwjgl.
At now i have double[100][100] with my heightmap and function redering every triangle from a list.
In example - drawing smal "floor" chunk with two triangles:
triangles.add(new Triangle(new Vector3f(x, (float) map[x][z] * 100, z),
new Vector3f(+0.5f, 1, -0.5f),
new Vector3f(-0.5f, 1, -0.5f),
new Vector3f(+0.5f, 1, +0.5f), rgb, rgb, rgb));
triangles.add(new Triangle(new Vector3f(x, (float) map[x][z] * 100, z),
new Vector3f(-0.5f, 1, +0.5f),
new Vector3f(-0.5f, 1, -0.5f),
new Vector3f(+0.5f, 1, +0.5f), rgb, rgb, rgb));
triangles parameters is:
start point XYZ coordinates,
first triangle point "sub" coords,
second triangle point "sub" coords,
third triangle point "sub" coords,
rgb for first point,
rgb color for second point,
rgb color for third point,
I cant do it... I think it is very easy and Im so stupid or so tired. Can you help me?

Related

Transforming the camera using a Matrix4f

I have a 3D scene with one triangle and a camera I want to move around. I stored the camera transformation as a matrix (specificially, a Matrix4f object loaded with the identity).
Here are two examples of methods that would modify that matrix:
This one rotates it a negative amount on the y axis:
public void turnRight() {
getCameraMatrix().rotate(-ROTATION_INTERVAL, new Vector3f(0, 1, 0));
}
This one translates right:
public void right() {
getCameraMatrix().translate(new Vector3f(TRANSLATION_INTERVAL, 0, 0));
}
I set the projection matrix to orthographic (having previously called glViewport()):
public void performProjection() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, Display.getWidth(), 0, Display.getHeight(), 0, 1000);
}
And change the camera position before drawing the scene every time the camera moves:
public void performLook() {
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLoadMatrix(
getAsFloatBuffer() //Gets the FloatBuffer from the matrix.
);
}
However, the effect of this transformation is that the triangle is translated and rotated, not the camera. As an example of how this should happen, if the right() is called, the camera should move right perpendicular to its current orientation, not down some axis.
Any tips on how to do this? (Our assignment forbids modern openGL for some reason.)
EDIT
In case it's useful, the coordinates for the triangle are: (1, 1, 1), (1, 50, 1), (50, 50, 1)
The viewport call is glViewport(0, 0, Display.getWidth(), Display.getHeight());
And finally, the Display dimensions are 640x480
If there's anything about my question that needs clarification, please let me know. Thanks.
EDIT
The camera matrix is the model view matrix in my code. I built it by creating a new Matrix4f object and loading the identity. All subsequent transforms were added to the matrix, whose data is then moved to the model view matrix when performLook() is called. I'm only drawing a single primitive right now, so I haven't yet dealt with object to world transforms.
The render steps are:
1. performProjection()
2. performLook()
3. Clear the screen
4. Draw the primitive
5. Swap the buffers.

Image/Texture scroll/shift (wrap)

Does anyone know whether libGDX has a method for scrolling/shifting an image/texture within itself?
To explain; I would like to be able to scroll the contents (pixels) of an image, either vertically or horizontally within its own region. For example, if an image is shifted 1 pixel to the right, all pixels move 1 to the right and those on the right-most-edge are wrapped to the left-most-edge. The image size does not change, only the positioning of the pixels within it change.
I have mainly been working with the Sprite class, it can do a lot (scale, rotate, etc) but shift/scroll as I need it, isn't there.
Before writting the method myself, I thought I'd ask here...
The following worked for me, this was provided by Kush:
float delta = 0f;
// In the Actors act method
delta += Gdx.graphics.getDeltaTime();
// Horizontal
batch.draw(texture, 0, 0, width, height, 0 + delta * 10, 1, 1 + delta * 10, 0);
// Vertical
batch.draw(texture, 0, 0, width, height, 1, 0 + delta * 10, 0, 1 + delta * 10);
You won't need Sprite for this, draw directly Texture using batch. For wrapping first set
Texture texture = new Texture("example.png");
texture.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);
then draw using uv
batch.draw(texture, x, y, width, height, u, v, u2, v2);
or any other method that suits you in SpriteBatch.

LibGDX detecting the mouse click on mesh triangles

I have been trying to add mouse click detection on the triangles of the mesh, but it seems that I am doing something wrong and I cannot figure out how to solve the problem.
So before explaining the problem I will define the environment(the full code is available at http://pastebin.com/TxfNuYXZ):
Camera position
cam = new OrthographicCamera(10, 9);
cam.position.set(0, 5.35f, 2f);
cam.lookAt(0, 0, 0);
cam.near = 0.5f;
cam.far = 12f;
Mesh renders 4 vertices.
mesh = new Mesh(true, NUM_COLUMNS * NUM_LINES, (NUM_COLUMNS * 6 - 6) * (NUM_LINES - 1), VertexAttribute.Position(), VertexAttribute.ColorUnpacked());
mesh.setVertices(new float[] {
   0, 0, 0, 0, 1, 0, 1,
   1, 0, 0, 0, 1, 0, 1,
   0, 0, 1, 0, 1, 0, 1,
   1, 0, 1, 0, 1, 0, 1 });
mesh.setIndices(new short[] { 2, 0, 1, 2, 3, 1 });
So when I run the application I try to check if the click was done inside some of the triangles of the mesh. Now the result depends on the position of the camera. When the camera has almost top view(like in the following picture), corresponding to around 6 on Y axes, the click point is being correctly translated to the coordinates and corresponds to what is actually being seen.
When I move camera on the Y axes to lower position (around 2 or 3), so the image looks like the following one
the click is being detected in the completely wrong positions (the red line shows the place where the click is detected).. Which seems to be right according to the coordinates, but not according to what is being seen..
I would like to understand what an I missing to be able to detect clicks on what actually is being seen? The code I use to detect the click is the following:
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
Ray ray = cam.getPickRay(screenX, screenY);
Vector3 intersection = new Vector3();
float[] v = new float[NUM_COLUMNS * NUM_LINES * VERTEX_SIZE];
short[] i = new short[(NUM_COLUMNS * 6 - 6) * (NUM_LINES - 1)];
mesh.getIndices(i);
if (Intersector.intersectRayTriangles(ray, mesh.getVertices(v), i, VERTEX_SIZE, intersection)) {
System.out.println(intersection);
}
return false;
}
Thanks a lot for your help!
Basically, after several days of drawing and some math I have found the source of the problem. The Vertex Shader, in order to determine the position of the vertices, was performing a_position * u_projectionViewMatrix multiplication, which was resulting on what was looking fine on the screen, but actually when you compare with actual coordinates of the mesh it was wrong. Now if you check the examples at enter link description here, you can see, that gl_Position is being calculated by multiplying u_projectionViewMatrix * a_position. Making the correct calculation made the trick.
I also had to change the camera to perspective, since the mesh was not rendered how I wanted it to.

Box rotation around multiple axises using Matrix4f

The question change a bit, I figured out how to rotate around a single axis
I want to rotate a box around the Y axis using an angle.
The box has a size, and a Vector3f to signal the rotation.
To rotate the box correctly what I do is rotate the origin position then rotate the origin position plus the size, and use those two references to render the box.
However this rotation does not work correctly and causes rendering artifacts.
This is my code to rotate the positions:
Matrix4f matrix = new Matrix4f();
// Rotate the origin position
Vector3f pos = new Vector3f(new Vector3f(blockX, blockY, blockZ));
matrix.m03 = pos.x;
matrix.m13 = pos.y;
matrix.m23 = pos.z;
Vector3f rot = new Vector3f(new Vector3f(0, 1f, 0f));
Matrix4f.rotate((float) Math.toRadians(45f), rot, matrix, matrix);
Vector3f locationMin = new Vector3f(matrix.m03, matrix.m13, matrix.m23);
// Rotate the position with the size
// Top left back is the position of the block
Vector3f sizeRot = new Vector3f(new Vector3f(blockX + size, blockY + size, blockZ + size));
matrix = new Matrix4f();
matrix.m03 = sizeRot.x;
matrix.m13 = sizeRot.y;
matrix.m23 = sizeRot.z;
rot = new Vector3f(new Vector3f(0, 1f, 0f));
Matrix4f.rotate((float) Math.toRadians(45f), rot, matrix, matrix);
Vector3f locationMax = new Vector3f(matrix.m03, matrix.m13, matrix.m23);
// Then here I use the locationMax and the locationMin to render the cube
What could be wrong with this code? Is the logic I am using to rotate the box correct? as in rotate the origin position then rotate the origin position plus the size..
EDIT: I released that rotating after translating is stupid so instead I just rotated the locationMax which is not translated (it is only the size) then I translated and I still get the same result (Graphical Artifacts).
New Code:
float rx = blockX, ry = blockY, rz = blockZ;
Matrix4f matrix = new Matrix4f();
Vector3f rot = new Vector3f(0, 1f, 0f);
matrix = new Matrix4f();
matrix.m03 = size;
matrix.m13 = size;
matrix.m23 = size;
Matrix4f.rotate((float) Math.toRadians(45f), rot, matrix, matrix);
matrix.translate(new Vector3f(rx, ry, rz), matrix);
float mx = matrix.m03;
float my = matrix.m13;
float mz = matrix.m23;
// Here is use rx, ry, rz and mx, my, mz to render the box
============ * I figured it out (See below)* =============
EDIT:
This is what I ended up doing:
// Origin point
Vector4f a = new Vector4f(blockX, blockY, blockZ, 1);
// Rotate a matrix 45 degrees
Matrix4f mat = new Matrix4f();
mat.rotate((float) Math.toRandians(45f), new Vector3f(
0, 1f, 0), mat);
/* Transform the matrix to each point */
Vector4f c = new Vector4f(size.x, 0, size.z, 1);
Matrix4f.transform(mat, c, c);
Vector4f.add(c, a, c);
Vector4f b = new Vector4f(size.x, 0, 0, 1);
Matrix4f.transform(mat, b, b);
Vector4f.add(b, a, b);
Vector4f d = new Vector4f(0, 0, size.z, 1);
Matrix4f.transform(mat, d, d);
Vector4f.add(d, a, d);
// Here is use a, b, c, and d to render the box.
The problem with this is that I want to rotate around all axises and not only around the Y axis. This makes the code very long and unreadable and There are a lot of bugs when I try to rotate around all axises.
Update Question:
How do I take the above code and make it so I can rotate around all 3 axises. I want to do this so I can have a billboard that will always face the camera.
This is how I calculate the angle between the camera and the object:
Vector3f angle = new Vector3f();
// Calculate the distance between camera and object
Vector3f.sub(game.getCamera().getLocation(),
new Vector3f(blockX, blockY, blockZ), angle);
// Calculate the angle around the Y axis.
float vectorAngle = (float) ((float) Math.atan2(angle.z, angle.x) * -1 + (Math.PI / 2.0f));
Billboards are a very common application of computer graphics (as I'm sure you've noticed, since you're asking the question!)
Ultimately I think you are over complicating the problem, based on:
as in rotate the origin position then rotate the origin position plus the size..
For computer graphics, the most common transformations are Scaling, Translating, and Rotating, and you do these in an order to achieve a desired effect (traditionally you scale, then rotate about the origin, then translate the vertex's position).
Additionally, you will have three main matrices to render a model in 3d: World Matrix, View Matrix, and Projection Matrix. I believe you are having misunderstandings of transforming from Model Space to World Space.
Graphics TRS and Matrix info. If you are having conceptual problems, or this answer is insufficient, I highly recommend looking at this link. I have yet to find a better resource explaining the fundamentals of computer graphics.
So right at the moment, you have your three angles (in degrees, in a Vector3) corresponding to the angle difference in the X,Y, and Z coordinate spaces from your billboard and your camera. With this information, we generate the View matrix by first gathering all of our matrix transformations in one place.
I'm going to assume that you already have your Translation and Scaling matrices, and that they both work. This means that we only need to generate our Rotation matrix, and then transform that matrix with the scaling matrix, and then transforming that matrix by our translation matrix.
X Rotation Matrix
Y Rotation Matrix
Z Rotation Matrix
(Images taken from CodingLabs link above)
So you will generate these three matrices, using the X,Y, and Z angles you calculated earlier, and then transform them to consolidate them into a single matrix, transform that matrix by the scaling matrix, and then transform that matrix by the translation matrix. Now you have your awesome matrix that, when you multiply a a vertex by it, will transform that vertex into the desired size, rotation, and position.
So you transform every single vertex point by this generated matrix.
And then after that, you should be done! Using these techniques will hopefully simplify your code greatly, and set you on the right path :)
So now how about some code?
//I do not guarantee that this code compiles! I did not write it in an IDE nor did I compile it
float angleToRotX = 180f;
float angleToRotY = 90f;
float angleToRotZ = 0f;
// example vertex
Vector4f vertex = new Vector4f(0, 1, 0, 1);
// Rotate vertex's X coordinates by the desired degrees
Matrix4f rotationXMatrix = new Matrix4f();
rotationXMatrix.rotX(angleToRotX);
Matrix4f rotationYMatrix = new Matrix4f();
rotationYMatrix.rotY(angleToRotY);
Matrix4f rotationZMatrix = new Matrix4f();
rotationZMatrix.rotZ(angleToRotZ);
//now let's translate it by 1.5, 1, 1.5 in the X,Y,Z directions
Matrix4f translationMatrix = new Matrix4f();
translationMatrix.setTranslate(new Vector3f(1.5, 1, 1.5));
/*
Now we have our three rotational matrices. So we multiply them (transform them) to get a single matrix to transform all of the points in this model to the desired world coordinates
*/
Matrix4f rotationMatrix = new Matrix4f();
rotationMatrix.mul(rotationXMatrix);
rotationMatrix.mul(rotationYMatrix);
rotationMatrix.mul(rotationZMatrix);
Matrix4f worldMatrix = translationMatrix;
worldMatrix.mul(rotationMatrix);
//now worldMatrix, when applied to a vertex, will rotate it by X,Y,Z degrees about the origin of it's model space, and then translate it by the amount given in translationMatrix
worldMatrix.transform(vertex);
//now vertex should be (1.5, 0, 1.5, 1) with (x,y,z,1)
Now this code could really be simplified, and it is excessively verbose. Try it out! I don't have java downloaded on my machine, but I grabbed the methods from the java documentation Here
Here is an image of what is happening (again, taking from coding labs):
(Advanced Info: Quaternions. These are really cool way of orienting a model in 3d space, however I don't quite understand them to the degree I need to in order to explain it to someone else, and I also believe that your problem is more fundamental)
You could generate the matrix without much hassle. The OpenGL matrix looks like the following:
|lx,ux,vx,px| - lx,ly,lz = the left vector
|ly,uy,vy,py| - ux,uy,uz = the up vector
|lz,uz,vz,pz| - vx,vy,vz = the view vector
|0 ,0 ,0 ,1 | - px,py,pz = the translation
All you need to do, is set px,py,pz to the position of your box in the world,
your view vector to the normalized(camera position - box position), your up comes straight from your camera, and the left is calculated via normalized cross product. It's also good practice to reconstruct the up vector, after left one is derived (by another cross product). That's all there's to it.
My solution aims to save you some time coding, rather than explain everything in detail. Hope that is useful to someone.

opengl rotation texture off center

I wrote some code to get a plain 2d box to face the mouse. It rotated just fine around its center, and everything was working great, but when i put a texture on the box, it did not rotate around the center anymore.
The code:
float imgWidth = texture.getImageWidth()*scale;
float imgHeight = texture.getImageHeight()*scale;
glLoadIdentity();
texture.bind();
glTranslatef(x, y, 0);
glRotated(rotation - 90, 0, 0, 360);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(-imgWidth, -imgHeight);
glTexCoord2f(1, 0);
glVertex2f(imgWidth, -imgHeight);
glTexCoord2f(1,1);
glVertex2f(imgWidth, imgHeight);
glTexCoord2f(0, 1);
glVertex2f(-imgWidth, imgHeight);
glEnd();
The answer is simple but with a complicated background that has to be understood.
OpenGL always rotate something not around its center but takes as center the point (0;0).
This can be an issue because if you translate your object somewhere and then your rotate it, it will rotate not on its center but around the (0;0) point (origin) creating a big rotation, I will say as a planet around the Sun.
Also OpenGL works with matrix, that with very barbaric simplification means that the operation are executed bottom to top.
// store the current model matrix
GL11.glPushMatrix();
// bind to the appropriate texture for this image
this.texture.bind();
// translate to the right location and prepare to draw
GL11.glColor3f(1, 1, 1);
GL11.glTranslated(x + (this.texture.getImageWidth() / 2), y + (this.texture.getImageHeight() / 2), 0);
GL11.glRotated(this.angle, 0, 0, 1);
GL11.glTranslated(-this.texture.getImageWidth() / 2, -this.texture.getImageHeight() / 2, 0);
// draw a quad textured to match the sprite
GL11.glBegin(GL11.GL_QUADS);
{
GL11.glTexCoord2f(0, 0);
GL11.glVertex2f(0, 0);
GL11.glTexCoord2f(0, this.texture.getHeight());
GL11.glVertex2f(0, this.texture.getImageHeight());
GL11.glTexCoord2f(this.texture.getWidth(), this.texture.getHeight());
GL11.glVertex2f(this.texture.getImageWidth(), this.texture.getImageHeight());
GL11.glTexCoord2f(this.texture.getWidth(), 0);
GL11.glVertex2f(this.texture.getImageWidth(), 0);
}
GL11.glEnd();
// restore the model view matrix to prevent contamination
GL11.glPopMatrix();
This means that first I am moving the texture to have its center positioned at (0;0) that means translating it backward half the dimensions.
Then I rotate it, and this is the crucial point, because you are using a strange way to rotate it, maybe the problem it's here, take a look to the javadoc:
SPECIFICATION
void glRotated( GLdouble angle,<br>
GLdouble x,<br>
GLdouble y,<br>
GLdouble z )<br>
void glRotatef( GLfloat angle,<br>
GLfloat x,<br>
GLfloat y,<br>
GLfloat z )<br>
PARAMETERS<br>
angle Specifies the angle of rotation, in degrees.
x, y, z<br>
Specify the x, y, and z coordinates of a vector, respectively.
DESCRIPTION<br>
glRotate produces a rotation of angle degrees around the<br>
vector (x,y,z).
First of all all x,y,z values should be between 0 and 1, if you want to rotate a 2d image then you should use the z axis, so the third param will be 1 that mean that you are rotating your image around the unit vector z.
The angle should be in degree and can be either positive or negative.
Try to change your code according to the documentation and you will have your problem solved.
Also with your quad you are drawing a 2x scaled quad, you are starting from -imageWidth to +imageWidth that means 2 times the width...

Categories