Im trying to learn some basic 3D programming, so I’m attemping to make a small mincraft like game. It just a small personal project to learn and have fun coding.
Made cubes, added texture, moveable camera.
Next to do: create a dummy object to attach the camera too, create basic terrain generation, add extra chuncks!
I think I can do this… but any suggestions on creating a First Person view would be welcome!
I don’t know if it’s the best or ‘correct’ method, but what I usually do for mouse-look is in a first-person game is this:
read the relative X/Y movement values of the mouse
use these values to change 2 rotation angle values of your Player object that define where he is looking: Add the relative X movement of the mouse to the rotation angle of your Player class that defines the rotation along the Y axis. Add the relative Y movement of the mouse to the value that defines the rotation along the X axis.
when rendering the 3D scene, the first thing you do is call glTranslate to put the player at the correct position (using its x,y,z location values)
after that, use glRotate to rotate the camera along the Y and X axis using your 2 rotation angle values in your Player object.
when you press forward while the player is on the ground, use one of your rotation angle values (the one that defines the rotation along the Y axis) in your Player object to calculate the updated position.
Like I said, I don’t know if it’s the best method (I’m hardly a 3D expert), but it works for me and is quite easy.
Thank you erikd… Yes that is the way i am going to do it. I have made a start. Just need to do the bit of maths to get that fully working. Thank you for your time, that reasurres me that im aproaching it correctly.
Update:
I have made the 3d camers, you can now walk around. mouse look really done, but you can click on left/right of screen to turn… keys wasd, r & f (look up / down)
Blocks have basic collision detection. Jumping is rubish atm, but it was to test the height collision. whole project will be refactored soon, to make way for chunks, and VBO’s
Changed texture loader to Slick-Util
Support for sprite sheet textures or single textures
Change UVmapping to allow differnt textures on different faces
Added fog
Added chunks
Added First Person View with mouse look
Added a very basic building with helper cube (not fully implimented) (unitil 3d picking)
Lots to do, hoping to have webstart version and playable jar in next update.
I’ve been trying to do the same thing as you’re doing for a long time, could you possibly post some of your chunk code? I.E. the actual creation of your blocks and how you place them? I use
glTranslatef()
, but thats horribly slow and I cant seem to figure out the offsets to correctly render the blocks. If you could help at all I would be very grateful!
There is a post (a recent one) that can help you out on how to generate chunks and place them: http://www.java-gaming.org/topics/voxel-a-start/28942/view.html
Don’t hesitate to look into the “OpenGL Development” section of the site, you’ll find many pieces of information.
You can use display list (instead of VBO) for a start, it’s a bit easier to understand and brings some really good performance.
It’s funny, I actually contributed a little to that thread Thanks for the link though! I read over it again and I think I’m ready to have another try at it.
Thanks for that, ive used that in a 2d game, and for raycasting before. I will probably use this again.
Sure I will share any bits…Ill do that after this update…
Update:Added jumpin, Added player holding block, added collision, added gui placeholder,
added bitmap rendering, added loading and saving of world and all chunks,
added basic 3d picker, placeable different blocks
To do: need to optimise rendering next, and make the 3d picker work correctly.
G0aY1arrrCQ
Video is a little slow, game runs at 160fps (need a lot of optimising) but only 30fps while video capturing!
My chunks have these main properties. The x and z store the chunks position relative to 0,0. so a chunk may be -3,9 which is (-316) blocks in X and (916) in z
then the blocks are bytes, storing the block ID ie 1 for grass or something. 0 for Air.
private int x;
private int z;
private byte[][][] chunk;
The blocks are then say 4,3,7 so it position in the game world is (-316)+4 , 3 , (916)+7
The chunks have a method to set and get blocks
public int getblockID(int x,int y, int z){
return chunk[x][y][z];
}
public void setblockID(int x,int y, int z,byte id){
chunk[x][y][z]=id;
}
at the moment I declare chunks manually with chunks[4] = new Chunk(-1,-1,“AE”);
as you see I have an array of chunks to store them. the “AE” is for the file of that chunk to save it.
the (-1,-1) are the positions as described above.
With regard to drawing the blocks. - Im drawing them 1 at a time which is not the best way,
but yes, you have to reset the view, then translate each block.
Optimisation inclue:
Cull faces,
Make a display list and render all the chunk as 1 object
Render the chunk as a VBO
Dont send chunks to draw that are behind you
when drawing block faces - check for adjacent blocks first…you may not need to draw them
Hmm actually very helpful, however the only part I’m having trouble with is using offsets to render my blocks within the chunk. I use VBOs and I just can’t seem to render out two chunks without hitting 1 fps! Here’s a run down of my chunk class right now:
I have three nested for loops that call a class that creates cubes. Like this:
for(int x = 0; x < CHUNK_WIDTH; x++){
for(int z = 0; z < CHUNK_DEPTH; z++){
for(int y = 0; y < CHUNK_HEIGHT; y++){
glTranslatef(x, z, y);
cube = new BaseCube();
}
}
}
Or something along the lines of that, its pseudo code. Then, I create a new chunk to store the cubes in like this:
private void newChunk(){
glBindBuffer(GL_ARRAY_BUFFER, vbo.vboVHandle);
glVertexPointer(3, GL_FLOAT, 0, 0L);
glBindBuffer(GL_ARRAY_BUFFER, vbo.vboCHandle);
glColorPointer(3, GL_FLOAT, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
for(int x = 0; x < var1; x++){
for(int z = 0; z < var2; z++){
for(int y = 0; y < var3; y++){
glPushMatrix();
glTranslatef(x, y, z);
glDrawArrays(GL_QUADS, 0, 24);
glPopMatrix();
}
}
}
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
}
Its a terrible way to do it obviously, though, because I call
glTranslatef
for 4096 blocks, and then I call it again to translate the chunk. It just isn’t efficient. I was wondering if you used offSets instead of
glTranslatef()
? So for instance, I could do something like this:
private float[] makeCube(float x, float y, float z)
{
int offset = Block.SIZE / 2;
return new float[]
{ x + offset, y + offset, z, x - offset, y + offset, z, x - offset, y + offset, z - Block.SIZE, x + offset, y + offset, z - Block.SIZE, x + offset, y - offset, z - Block.SIZE, x - offset, y - offset, z - Block.SIZE, x - offset, y - offset, z, x + offset, y - offset, z, x + offset, y + offset, z - Block.SIZE, x - offset, y + offset, z - Block.SIZE, x - offset, y - offset, z - Block.SIZE, x + offset, y - offset, z - Block.SIZE, x + offset, y - offset, z, x - offset, y - offset, z, x - offset, y + offset, z, x + offset, y + offset, z, x - offset, y + offset, z - Block.SIZE, x - offset, y + offset, z, x - offset, y - offset, z, x - offset, y - offset, z - Block.SIZE, x + offset, y + offset, z, x + offset, y + offset, z - Block.SIZE, x + offset, y - offset, z - Block.SIZE, x + offset, y - offset, z };
}
I copied that from a different thread. However, it doesn’t work. Can I see your actual block rendering code to see how you do yours?
Thanks!
Hi opiop65,
I will upload my rendering code tomorrow. Had a quick look at ur code, firstly I notice that you are making lots of cube objects in your chunks.
I don’t know what’s in your cube class, but the data that your storing may only need to be 1 byte rather than making a copy of the entire cube class for each block.
I’ll post code tomorrow, but its something like
If(ID==3) cube.render( with texture perimeters’ and so on)
But all my array has is 1 byte for each cube. My cube class is only created once.
I just wanted to say that there is an even faster way to render an chunk,
without using glTranslate at all.
It’s actually quite simple:
First, you need to make a “ChunkRenderer” Class,
this class simply wraps all opengl draw commands that are neede to, well, draw stuff!
The important thing is, that the wrapper-method that draws vertices, applys a translation vector to them.
Basically this:
class ChunkRenderer{
float tx = 0F;
float ty = 0F;
float tz = 0F;
public void setBlockTranslation(int blockX,int blockY,int blockZ){
tx = blockX;
ty = blockY;
tz = blockZ;
}
public void drawVertex3d(float x, float y,float z){
GL11.glVertex3d(tx+x,ty+y,tz+z); //This can be replaced with a method that adds the vertex to an vertexbuffer.
}
}
I use this method in Puzzlez Project, and its very (very) fast.
I can render ~400 (16³m) Chunks at 350 FPS and without a single glTranslate!
Thank you very much! So would I add my block size to tx every time I want to draw a new cube? So for instance:
class ChunkRenderer{
float tx = 0F;
float ty = 0F;
float tz = 0F;
public void setBlockTranslation(int blockX,int blockY,int blockZ){
tx = blockX;
ty = blockY;
tz = blockZ;
}
public void drawVertex3d(float x, float y,float z){
GL11.glVertex3d(tx+x,ty+y,tz+z); //This can be replaced with a method that adds the vertex to an vertexbuffer.
tx += 16;
ty += 16;
tz += 16;
}
}