Quick question about voxels

is rendering something with vertex’s considered voxel rendering? and if it is would a custom mesh be the thing to use or is there something else that jme has for vertex stuff?

There’s nothing else to use than meshes :slight_smile: Everything you render are meshes, even a jme Box (a cube) is transformed into a mesh in order to render it (look at the simple example in a basic game).

If you have a lot of cubes and build a world upon it, then it is called voxel rendering. The cubes are the voxels, not the cubes vertices. But be aware: it’s not enough to set 3 million jme Box’ in a scene, transform them into Gemoetries and render them. In an ideal scenario you would create one large mesh on the fly that contains all VISIBLE vertices of the cube.

I’m not so sure what is the intention behind your question. So mayb you could give some more background info on what you have in your mind.

1 Like

Well i was just woundering what i should read up on. Like the mesh example puts the mesh into a geometry and ive read that you cant use geometry in voxel games like it starts getting laggy around 100.

The basic logic behind voxel games is pretty easy.

As andreas said you need to merge many voxels on a single mesh before rendering them, so first you need some ‘virtual’ representation of your voxel world in memory, let’s say a three dimensional array of bytes where for every array[x][y][z] you store the voxel_id.

Every user interaction with the world is applied only to the array, then you have a thread that check if the world is changed, if true, it loops inside the array and builds the geometry, to do that you have to check for each face of each voxel if there is another one that is hiding it, if yes, you don’t generate it, else you do.

Of course you can’t do that for the entire world, because the regeneration would be too slow. To resolve that you split the terrain in a three dimensional array of chunks, where every chunk is the array of voxel i were talking about earlier, and you create a single geometry for each chunk and you load/unload them according with the player position.

There is another thing to keep in mind if you are planning to do a game with unlimited terrain like minecraft: positions on jme are expressed with floats, this means that if the player goes too far they go overflow/underflow and start again from the minimum/maximum value, to fix that you need to keep the player at 0,0,0 and move the world around him.

1 Like

Aha … ah … AHHHHH?! Please don’t tell me that I’m coding it the wrong way! I currently programming a voxel game, but my player does not stay at <0, 0, 0>.

Waht do you mean by “floats are overflow”? A float can be quite a big number. Why should the float-position of the player overflow?

On the other hand: nice world if an overflow occurs. That would mean that the player moves from position MAX to MIN, But the chunk management should be able to load the Chunk at the MIN position. So it would be a world that does not end, but also is not infinite. :smile:

but then wouldnt the worlds position overflow?

It depends on the scale you are using and the gameplay (ie if you have teleports or such).

If you take in account this while you are developing, probably yes, even though i don’t know how that is managed inside jme/jwjgl or if it causes issues.

No, because you load only the chunks that are viewed by the player, when they are moved outside its view range they are unloaded.

Well, i canted to explain something in a separate thread but i’ll do it here. There is an easy way to create a mesh corresponding to a cube set. I did it several time in different languages and the method always works. I am currently working on a game engine written in c++ and as it seems that everyone wants to create a cube world i decided to add a cubeset tool in it, by default.

So, here is the method:
Initially you have two Map: one fo cubes, one for faces. Let’s call them “cubes” and “faces”.

The type of cubes is: Map<Point3i, Cube>
where Cube is whatever information you want: a structure, a complexe class, an integer whatever. The only thing we need to be able to do with it is to produce faces (up, right, front, down, left, back).
The type of faces is: Map<Point4i, Face>
Note that it’s a Point->4<-i. Actually, it’s more “Point3iPlusADirection” but we will use a Point4i.
A face is just something that can answer questions like: “what are your texture coords ? What is your color ?”
We also have a Point4i (one for the whole cubeset) named “lookup”.
We also define something (a convention): up is 0, right is 1, front is 2, down is 3, left is 4 and back is 5. Note that if you do: “(dir + 3) % 6” you get the opposite direction of “dir”.
Ok, this is the static part. Now, what happen when we add a cube ? Here is the magic trick:

Parameter: a position Pos, a Cube cube

cubes.put(pos.clone(), cube);
Face exploded[] = cube.getFaces();
lookup.set(Pos.x, Pos.y, Pos.z, 0); 
for ( int i = 0; i < 6; i++ )
{
  Face face = exploded[i];
  int opposite_direction = (i + 3) % 6;
  lookup.setW(opposite_direction);
  /** here is the magic: we check if the face we are about 
    * to add already face (the verb) an other face (the noun)*/
  if ( faces.containsKey(lookup) )
  {
    faces.remove(lookup);
    continue;
  }
  lookup.setW(i);
  faces.put(lookup.clone(), face); //you can use a pool instead of ".clone" lookup
}
}

And it’s just that (to add a cube). You’ll need to tweak it to handle “i want to add a cube where an other cube already exists” etc, but it’s the basic concept: adding a cube is adding 6 face and when 2 face face each other, both of them are removed (actually, only one is removed, the other one is just not added).

To create you mesh, you simply iterate over your collection of faces (cubes are only here for the record).
Bonus: you can have an array of floats like this:

float vertex[] = 
{
  //up
   -1, +1, -1,
   -1, +1, +1,
   +1, +1, +1,
   +1, +1, -1,

  //right
  //etc 
};

It will then be easy to write the vertex datas of a face in the mesh for every face identified by a Point4i (the w34 will be you the base index in your vertex array, and add the x, y, z will give you the face position).

English is not my native tongue, so i am not sure taht you’ll understand me, but i did as well as i could.

P.S: when you remove a cube, you ALWAYS add its adjacent faces in the faces map. There is no questions here, it’s pretty straightforward.

1 Like