Cubes – A Block World Framework [Update Preview]

LOD works by replacing chunks with more coarse-grained chunks.
The main issue for Cubes would be handling the boundaries between finer and coarser chunks.

The algorithms that determine what details to omit and how to blend fine blocks into coarse ones is application-dependent. E.g. if you have just “green” and “brown”, you’ll need to do a majority count, if your can do “10% green and 90% brown” (by interpolating textures or whatever), then you can merge.

For a blocky universe, I’d simply generate coarse blocks and refine them, and directly use the coarse blocks (and stop at a relatively coarse display granularity on purpose to keep the blocky look).
If there are 8 finer blocks per coarser block, the storage overhead is 1/8th for one level, and 1/8th + 1/16th for two levels. That’s negligible.

Okay, so, still hunting down the lighting bug, here is where I’m at:

I decided to start with one of the Cubes test programs so I know for sure that nothing is a factor when it comes to lighting but the lighting itself. The one I chose was the TestPhysics.java.

Here is the original lighting code for that program:
[java]
DirectionalLight directionalLight = new DirectionalLight();
directionalLight.setDirection(lightDirection);
directionalLight.setColor(new ColorRGBA(1f, 1f, 1f, 1.0f));
simpleApplication.getRootNode().addLight(directionalLight);
simpleApplication.getRootNode().attachChild(SkyFactory.createSky(simpleApplication.getAssetManager(), “Textures/cubes/sky.jpg”, true));

    DirectionalLightShadowRenderer directionalLightShadowRenderer = new DirectionalLightShadowRenderer(simpleApplication.getAssetManager(), 2048, 3);
    directionalLightShadowRenderer.setLight(directionalLight);
    directionalLightShadowRenderer.setShadowIntensity(0.3f);
    simpleApplication.getViewPort().addProcessor(directionalLightShadowRenderer);

[/java]

And the result:

Beautiful lighting.

Now, after confirming it all works, I commented out the line that was initializing Lighting, and substituted my own code:

[java]
//CubesTestAssets.initializeEnvironment(this);

    PointLight light = new PointLight();
light.setPosition(new Vector3f(1000, 1000, 1000));
light.setColor(new ColorRGBA(1f, 1f, 1f, 1.0f));
light.setRadius(2000f);
this.rootNode.addLight(light);

getRootNode().attachChild(SkyFactory.createSky(getAssetManager(), "Textures/cubes/sky.jpg", true));

PointLightShadowRenderer plsr = new PointLightShadowRenderer(
	this.assetManager, 2048);
plsr.setLight(light);
plsr.setShadowIntensity(0.3f);
getViewPort().addProcessor(plsr);

[/java]

I tried to keep it as original to the DirectionalLight code as possible while using a PointLight instead.
Here are my results: (The shadow direction is probably off, I chose a random number when plugging in the position of the PointLight)

So… I have no idea. I guess Point Light doesn’t work with cubes at all? Or am I doing something wrong? (I hope I’m missing something.) If nothing else at least I know I’m not overlapping chunks like I and @ulfgur previously thought :stuck_out_tongue:

If someone gets the time and would like to test this code to see if they can replicate the lighting glitch, I’d be very grateful. Here is the pastebin of my edited file. (The edited part is under initBlockTerrain())

Thanks :slight_smile:
(P.S. I’m curious as to why I got different triangle and vertex counts in those two images… I used a seed so it should have generated the exact same terrain. Anyone know?)

A guess… directional light shadows renders the scene one extra time (doubling the counts basically). Point lights will render the scene 6 extra times.

Note: it’s very rare to get to use regular lighting in a block world… it’s likely that in your particularly strange use-case it’s just impossible. (This is why most block worlds bake their lighting in.)

I’m now working with noise. After chatting with echospot and reading a goodly portion of the resources he’s accumulated, I concluded that noise generation is far beyond my math level. Consequently, I’m stuck working with Cubes’s built-in noise generator. The issue is that I want my worlds to be infinite, which is quite a challenge when the generator requires pre-set noise.

My workaround is something like this:

  1. generate a layer of noise.
  2. use the coordinates of a chunk to select four corner values for a chunk.
  3. generate noise for said chunk by using the four corner values.

So, if my noise was like this:
1 2 3 4 1 2 3 5
3 4 5 7 2 5 4 1
2 3 5 6 7 8 3 4
2 3 4 6 2 7 7 2
3 6 5 8 6 9 0 2

the noise for my chunk corners would go like this:
(chunk 0, 0)
1 2
3 4
(chunk 1, 0)
2 3
4 5
(chunk 0, 1)
3 4
2 3
(chunk 1, 1)
4 5
3 5

The thought being that because (I think) the built-in noise uses the diamond-square algorithm, similar corner values would result in similar chunk edges. Not perfect, but similar.

I’ve had some success, but this method ends up generating some fairly violent terrain, even when I set the roughness of both noises to .001:

Imgur
Imgur
Imgur
Imgur

Any idea how I can make the terrain gentler?

I’m also open to suggestions for completely different ways of getting this done. My mediocre math skills and unwillingness to pay for anything are the only limiters! :wink:

Why not just use something like perlin noise or simplex noise and therefore get infinite generation right out of the box?

So were you guys using my codesample? It contains perlin noise generation via my jLibNoise port.

@PewPewKapowie said: And the result:

Beautiful lighting.

The vertical edges look odd to me, either they have some kind of highlight, or the shadows are applied with a horizontal offset.

Also, look at the small green square near the middle of the bottom edge of the image.
Particularly, at the shape on the shadow on top of it.
It should be a triangle, but it has a notch at the top end.

@toolforger said: The vertical edges look odd to me, either they have some kind of highlight, or the shadows are applied with a horizontal offset.

Also, look at the small green square near the middle of the bottom edge of the image.
Particularly, at the shape on the shadow on top of it.
It should be a triangle, but it has a notch at the top end.

Welcome to shadow mapping hard edges. Enjoy your stay. :wink:

2 Likes
@ulfgur said: Any idea how I can make the terrain gentler?

I’m also open to suggestions for completely different ways of getting this done. My mediocre math skills and unwillingness to pay for anything are the only limiters! :wink:

I didn’t quite understand it either, however getting a perlin noise generator is not as hard as you think. I had a tougher time implementing it xD. I think the reason why the terrain is so violent is the chunks, when generated, are all using their own noise generators with no point of reference to an enough number of previous chunk’s noise grid. I produced the same results when I just had my chunks generate their own stuff. Apparently, and this is new to me =D , @sleaker does indeed have a jLibNoise jar in there with utils for generating infinite grids; I’d experiment a bit.

@sleaker I’m having the hardest time trying to implement your awesome greedy mesher. I would just use your Cubed library but Pew and I have done a number to the cubes framework. I keep getting all sorts of face errors and it looks like I’ll need to fix the mesher to generate with the old BlockSkin_TextureLocation system. I’ll keep trying!

@toolforger said: For a blocky universe, I'd simply generate coarse blocks and refine them, and directly use the coarse blocks (and stop at a relatively coarse display granularity on purpose to keep the blocky look). If there are 8 finer blocks per coarser block, the storage overhead is 1/8th for one level, and 1/8th + 1/16th for two levels. That's negligible.

Would you be saying to increase the block size for those chunks or something of the sort? I’m not sure how to do it with Cubes. I was hoping the jME3 LOD Generator would help but the Triangle Reduction method produces messy results and will look even worse when I get sleaker’s greedy mesher working. It actually reduces performance instead of increases. Is there a way to do some sort of Vertex reduction? I think that would look better then on the farther levels start to do triangle reduction. Here’s a shot of the sad results.

I’d put an FPS thing but I can’t get it to show up for some reason, but everything is a lot slower with the LOD implemented.

UPDATE: I’m trying to use the LodGenerator.TriangleReductionMethod.COLLAPSE_COST method with a reduction value of 0.9 but I don’t think its reducing anything. Any ideas?

I’d use larger blocks for more faraway areas.
Think about blocks first; chunks are merely an optimization. You’d probably end up scaling chunk size and block size by the same factor, if only to keep the code simple, but that’s not necessarily the approach that gives the best results.

I don’t know how to do it with Cubes either; Cubes may be unsuitable for LOD.
(I haven’t used Cubes to even say anything remotely relevant about it.)

In general, the issues begin where blocks of different sizes meet. You don’t want these boundaries to stick out visually, you want any pathfinding algorithms to be reasonably stable as the terrain granularity changes, and similar thought for food.
(OTOH it might be enough to simply ignore any issues, get the job done, and see whether the resulting code is good enough. Just keep the code in a state that you can add such things later.)

I don’t think Lod mesh differences are an issue with bloxel terrain as everything is already going to look similar just don’t skip lod factors between them. You need to be generating your own reduced meshes

Been playing with the PointLight some more, this time using a filter instead of a renderer, and using EdgeFilteringMode.PCF8:

Other than the fuzziness, @echospot and I really like these shadows. It’s really unique from other games and if we can just find a way to get rid of that fuzziness and also some flickering shadows that aren’t visible in this picture, it’d be perfect.

Here’s another shot this time using EdgeFilteringMode.Nearest:

Those shadows are pretty much what I was originally going for, except still fuzzy. I prefer PCF8 to be honest.

Update: So I’ve determined the fuzziness is caused by the distance from the light. You are seeing pictures with the light 1000 units away. When it is 3000 away, it looks much worse. When it is 500, it looks much better. It sounds like I’ll be looking into some way of playing with directional lights. Is there a way to tell a directional light to only operate on certain objects? Or is there a way to stop a directional light from being infinite in all directions? I have no idea what I’m going to do to light these planets. It seems like JMonkey (Or probably any Java engine really) doesn’t have the right lights to make what I want to do possible.

So I feel really dumb now for not thinking of this sooner… I added a directional light to each planet, attached to its own node and facing the direction of (planet.location - star.location), with the direction of the light changing as the planet revolves. The result:

Supposed to be a smiley face:

My dirt house at the sunset:

Obviously it needs tweaking. Too bright, the edges are being dumb, etc, etc… I’m making huge progress though so I’m happy for now.

Thanks for putting up with all my problems, monkeys =D

Greedy Mesher: Kind of complete

@sleaker I gotta say, after some serious tweaking, I finally got it in, and man is it an improvement.

I’ve gotta figure out how to get the textures tiled again like they were, but chunk generation is flawless.

However I ran into a problem. Whenever I wrap around the planet, the geometry rejects the mesh and gives me an IllegalArgumentException. I have plenty of try-catch clauses for null pointers so I’ll try to hammer the problem out. Any idea though?

I managed to get a shot JUST before the errors usually occurs. Its when I generate to the other side of the spawn point, or any point actually.

@pspeed said: Why not just use something like perlin noise or simplex noise and therefore get infinite generation right out of the box?
I can't use simplex noise, because it's patented. I've been trying to get perlin noise to work, but can't seem to. My math skills are fairly weak. :explode:
@sleaker said: So were you guys using my codesample? It contains perlin noise generation via my jLibNoise port.
Codesample? Do you have a working perlin noise generator? May I steal it, and if so, from where?
@ulfgur said: I can't use simplex noise, because it's patented. I've been trying to get perlin noise to work, but can't seem to. My math skills are fairly weak. :explode:

Codesample? Do you have a working perlin noise generator? May I steal it, and if so, from where?

I’ve posted it already. There is a Java perlin noise implementation in the IsoSurface stuff.

@Dekker3D said: I hacked in a way to have a skin rotate the textures on specific faces, to be able to "rotate" an entire block like the logs and pistons in Minecraft. I don't think it was possible in the code you had so far. Are you interested in my code, or is there a way to do this already?

@Dekker3D
If you still have this, I’d love to know what you did! It would be very helpful. Thanks :slight_smile:

@PewPewKapowie said: @Dekker3D If you still have this, I'd love to know what you did! It would be very helpful. Thanks :)
I've changed a few more things since then, so I can't just diff it all, but this is what I think I did:

First, I added this to BlockSkin_TextureLocation:
[java]public Vector2f[] getTexCoords(int rotation){
Vector2f[] vecs = new Vector2f[4];
for(int i = 0; i < 4; i ++)
{
vecs[i] = texVectors[getVectorNumber(i, rotation)].clone();
vecs[i].x *= width;
vecs[i].y *= height;
vecs[i].x += x;
vecs[i].y += y;
}
return vecs;
}

private int getVectorNumber(int vec, int rot)
{
switch(vec % 4)
{
case 2:
return (3 + rot) % 4;
case 3:
return (2 + rot) % 4;
default:
return (vec + rot) % 4;
}
}

static Vector2f[] texVectors = new Vector2f[]{new Vector2f(0,1), new Vector2f(1,1), new Vector2f(1,0), new Vector2f(0,0)};[/java]
(The width and height lines can be removed if all textures are the same size; x and y should probably be row and column)

In BlockChunk_MeshOptimizer, I changed
[java]private static void addBlockTextureCoordinates(ArrayList<Vector2f> textureCoordinatesList, BlockSkin_TextureLocation textureLocation){
textureCoordinatesList.add(getTextureCoordinates(textureLocation, 0, 0));
textureCoordinatesList.add(getTextureCoordinates(textureLocation, 1, 0));
textureCoordinatesList.add(getTextureCoordinates(textureLocation, 0, 1));
textureCoordinatesList.add(getTextureCoordinates(textureLocation, 1, 1));
}[/java]
into
[java]private static void addBlockTextureCoordinates(ArrayList<Vector2f> textureCoordinatesList, BlockSkin_TextureLocation textureLocation, int textureRotation){
Vector2f[] vecs = textureLocation.getTexCoords(textureRotation);
for(int i = 0; i < 4; i ++)
{
vecs[i].x = vecs[i].x;
vecs[i].y = vecs[i].y;
textureCoordinatesList.add(vecs[i]);
}
}[/java]

This function is referenced in loadMeshData. The textureRotation value comes from [java]blockSkin.getTextureRotation(chunk, tmpLocation, Block.Face.Top)[/java], and that function just returns 0 for now. I haven’t gotten around to making actual block rotation happen, this part only does texture rotation. I’m thinking I’ll just add a class that can take existing rotation/face information and rotate it somehow.

1 Like
@pspeed said: I've posted it already. There is a Java perlin noise implementation in the IsoSurface stuff.
Perused it. You mean this one, right? http://http.developer.nvidia.com/GPUGems3/gpugems3_ch01.html

I understand the concepts: generate a set of semi-random wavelike functions, each tighter and smaller than the last, then smash them all together and read the resulting floats to get block heights.

It’s convincing any of the concrete maths to work that gives me trouble. I tried stealing pseudocode from various tutorials, but I can’t even get halfway through converting them to a usable format. I also found a perlin noise generator liscenced under the GNU LGPL v2.1. I’d use that, but It only wanted to return zeros. :stuck_out_tongue_winking_eye:
It may be that I just need to do more searching…

@Dekker3D
Thanks so much! I’ll let you know if either @echospot or I can get it working. Block rotation isn’t important to us as it’s the same cube no matter what way you look at it. Simply rotating the texture is enough. Thanks! :slight_smile: