Simple voxel engine starter kit

A few things…



First of all, block worlds are not made of cubes… they are made of batched quads. So, for example, just batch the quads by material. If you render whole cubes for every block your world is going to have to be very tiny. You end up rendering 2-3 times as many triangles are required (on average) and if those cubes are all separate geometry your going to spend all of your time traversing the scene graph and very little time actually getting to render anything (poor frame rate for more than 1000 cubes or so, ie: 10x10x10)



Texture atlasing is a way to increase batching by letting you batch all faces into one geometry (still no cubes here) and just giving the vertexes different texture coordinates depending on which sub-part of the texture you want to show.



I’m not trying to be condescending but I do feel the urge to point out that block world engines are not easier than other engines. The graphics look simpler but that’s because of the total flexibility. The engines themselves are actually much harder to write than a regular engine. Creating a level, plopping some characters in to run around, etc. is pretty trivial in comparison. Especially with the support the JME SDK provides.

@pspeed said:
A few things...

First of all, block worlds are not made of cubes... they are made of batched quads. So, for example, just batch the quads by material. If you render whole cubes for every block your world is going to have to be very tiny. You end up rendering 2-3 times as many triangles are required (on average) and if those cubes are all separate geometry your going to spend all of your time traversing the scene graph and very little time actually getting to render anything (poor frame rate for more than 1000 cubes or so, ie: 10x10x10)

Texture atlasing is a way to increase batching by letting you batch all faces into one geometry (still no cubes here) and just giving the vertexes different texture coordinates depending on which sub-part of the texture you want to show.

I'm not trying to be condescending but I do feel the urge to point out that block world engines are not easier than other engines. The graphics look simpler but that's because of the total flexibility. The engines themselves are actually much _harder_ to write than a regular engine. Creating a level, plopping some characters in to run around, etc. is pretty trivial in comparison. Especially with the support the JME SDK provides.

Hello pspeed,
I do understand that voxel engines are not made of boxes. For some reason I had trouble understanding texture coords, but after I read your post, I suddenly understand it now( no idea why ) Anyways, thank you for the help.

Hey, using this approach, does anyone have any ideas to do with the removal/addition of blocks? I’ve been trying to work it out myself, but the only solutions I can come up with are regenerating the mesh completely (which would be extremely intensive).

@azuraesky said:
Hey, using this approach, does anyone have any ideas to do with the removal/addition of blocks? I've been trying to work it out myself, but the only solutions I can come up with are regenerating the mesh completely (which would be extremely intensive).

No, thats what all engines do.
@azuraesky said:
Hey, using this approach, does anyone have any ideas to do with the removal/addition of blocks? I've been trying to work it out myself, but the only solutions I can come up with are regenerating the mesh completely (which would be extremely intensive).


Regenerating the mesh is also not extremely intensive if you do it right.

How check what vertices are on ray?

I have Ray which give me position where map was hit,

but how to check which vertices I should remove?



Sorry for bad Eanglish

hi chris



you have to figure out what block was hit and then update the array or chunk where that block is stored, in case of this simple starter kit I used 1 or 0. So if you want to remove the block and you know exactly which block you hit, set that to 0 in the array and when mesh is regenerated the block will be gone.



I leave it to you to figure out which block you actually hit with your raycast method. So sit down, take a papper and pen and start drawing and you’ll figure it hopefully :wink:

hi moonkey



thanks for answer. I’ll test it tomorrow :wink:

Hi, I am very new to the jmonkey engine and also 3D so when I was playing with the starter kit. I was only able to get a 128x128x64 area rendered and I tried doing some for loops just to get a flat area that went for a fare distance. The problem is that I can get a massive area if I do my own for loops



“for(int x = 0;x<=500;x++)” and all that but I cant figure out how to do it for terrain and also on a large scale map. Can someone help me?

@fatalone said:
Hi, I am very new to the jmonkey engine and also 3D so when I was playing with the starter kit. I was only able to get a 128x128x64 area rendered and I tried doing some for loops just to get a flat area that went for a fare distance. The problem is that I can get a massive area if I do my own for loops

"for(int x = 0;x<=500;x++)" and all that but I cant figure out how to do it for terrain and also on a large scale map. Can someone help me?


I will offer the advice that many people wade into "block worlds" thinking that it is somehow easier than a regular 3D game. The truth is that it is much harder.

I don't mean to sound discouraging but if you are just getting into 3D then you might not want to start right from the hardest end first.

How about using 32x32x32 chunks? Would that run faster or not?

sorry If I up the topic but it have an error on this lign :

[java]heightmap = new ImageBasedHeightMap(ImageToAwt.convert(heightMapImage.getImage(), false, false, 0));[/java]



I have replaced it by :

[java]heightMapImage.getImage().setFormat(Format.RGB8);

heightmap = new ImageBasedHeightMap(heightMapImage.getImage());[/java]



edit : all are ok with, I am stupid

Changing the format type doesn’t actually modify the data inside the image. If the heightmap is not in the correct format then it won’t work.



You need to load the format in the correct image or use something to transcode it. Atm I don’t think there is a reliable way to transcode it although there is a contribution I submitted a few weeks back that will provide it if/when it gets added.

@gnales said:
sorry If I up the topic but it have an error on this lign :
[java]heightmap = new ImageBasedHeightMap(ImageToAwt.convert(heightMapImage.getImage(), false, false, 0));[/java]

I have replaced it by :
[java]heightMapImage.getImage().setFormat(Format.RGB8);
heightmap = new ImageBasedHeightMap(heightMapImage.getImage());[/java]

But with that I have a black screen, and I don't now for what ^^

Use the [java]heightMapImage.getImage().setFormat(Format.Luminance8);[/java] if you use the grayscale heightmap.

The name is very irritating.



Did I miss a post? Where is the documentation?



This does not look like a good starting point for voxels to me… :confused:



If you could quickly add some javadoc that would be nice xD

Hello,



This thing really helped. I managed to slightly adapt this code, adding multiple box textures and a very basic terrain generator. However, when I got on to editing terrain in-game (removing and adding boxes), I couldn’t get the mesh to redraw. (It did redraw as far as I know but the changes to the terrain did not appear.) How would editing the mesh happen? Can anyone help?



Thanks in advance!

Hello,
This is my code
[java]
public void removeBlock(int x, int y, int z) {
mapCells[x][y][z] = 0;
lightCells[x][y][z] = 0;
clean();
build();
}

private void clean() {
    vertices.clear();
    normals.clear();
    texCoord.clear();
    indexes.clear();
    verticesColor.clear();
}

[/java]
It removes block by given x,y,z
But how to know x,y,z with ray ?

[java]
results.getCollision(i).getContactPoint();
[/java]

In theory, your blocks should have some kind of scale (or size or something like that). If it doesn’t, then it should be 1. From that, you can cast a ray in your scene, and discover where the block is.

Starting from (0,0,0), and assuming that the block has size of 1wu, that block is located within -0.5<x<0.5 -0.5<y<0.5 -0.5<z<0.5, and for the block located in (1,2,3), it should be within 0.5<x<1.5 1.5<y<0.5 2.5<z<3.5 =]

I try this
[java]
float bsize = 2,5f //block size

int x = (int)Math.ceil(pt.x / bsize);
int y = (int)Math.ceil(pt.y / bsize);
int z = (int)Math.ceil(pt.z / bsize);
[/java]
But it gives wrong results :frowning:

Then you have your maths wrong somewhere, your concept looks fine so you just need to delve deeper into why things aren’t matching up. Try using the debugger or adding some debug statements or similar. Incidentally making bsize static final (so the compiler has a chance to optimise it) or making it 1/2.5f and then multiplying by it will make the code run faster. Multiply is faster than divide.