Cubes – A Block World Framework [Update Preview]

That division code is correct. Here’s a small test program:
[java] static private int blockIndex(float coord, float chunkSize) {
return (int) Math.floor(coord / chunkSize);
}

static private void test(float a, float b) {
    System.out.println("a: " + a + ", b: " + b + ", chunked: " + blockIndex(a, b));
}

public static void main(String[] args) {
    for (int i = -4; i < 4; i++) {
        test((float) i - 0.1f, 2.0f);
        test((float) i + 0.1f, 2.0f);
    }
}

[/java]

(I’m intentionally not testing the exact borders, as these will usually be prone to round-off errors.)

Things I can think of:

  • You are assuming your code is testing coordinates at -4.0, -3.0, etc., but in reality some round-off error made it slightly less than your assumption for negative values and slightly above for positive ones.
  • You are feeding off-by-one negative values to the division.
  • settings.getChunkSizeX() returns a negative value for negative block locations (that’s not reasonably possible in the code you posted, but I bet you simplified it).
  • getX returns an absolute value, and some code you didn’t show negates the sign afterwards.

I kind of solved it ish. I really didn’t want to work on this again, but you guys are right, it’s a much better idea to get it ironed out. :stuck_out_tongue_winking_eye:

An explanation of the original problem and solution:
I pass the function (gets chunk position given block location) a number.
say the number is positive: (int)Math.floor(blockLocation.getX() / settings.getChunkSizeX()); given 2 will return 0, given 26 will return one, etc. (chunks size is 25)
say the number is negative, though: given -2, the function will return -0, not -1, and given -26 it will return -1, not -2. Consequently, all negative values to find chunk position had to be adjusted by -1, because on my chunk coordinate grid, there is no -0. Chunk positions are relative to a chunk corner, not the center of a chunk.

Now my problem is slightly different: the game will detect the correct chunk using the function, but my block coordinate translator (gets vector3Int block location given a Vector3f coordinate) will intermittently return coordinates that are off by 1 in all three given directions, but ony when passed negative coordinates… I have no idea why, and could use guidance. I’m still using Cubes default block navigator:

(I’m not passing off coordinates, the coords are taken directly from a picker.)
[java] public static Vector3Int getPointedBlockLocation(BlockTerrainControl blockTerrain, Vector3f collisionContactPoint, boolean getNeighborLocation){
Vector3f collisionLocation = Util.compensateFloatRoundingErrors(collisionContactPoint);
Vector3Int blockLocation = new Vector3Int(
(int) (collisionLocation.getX() / blockTerrain.getSettings().getBlockSize()),
(int) (collisionLocation.getY() / blockTerrain.getSettings().getBlockSize()),
(int) (collisionLocation.getZ() / blockTerrain.getSettings().getBlockSize()));
if((blockTerrain.getBlock(blockLocation) != null) == getNeighborLocation){
if((collisionLocation.getX() % blockTerrain.getSettings().getBlockSize()) == 0) {
blockLocation.subtractLocal(1, 0, 0);
}
else if((collisionLocation.getY() % blockTerrain.getSettings().getBlockSize()) == 0){
blockLocation.subtractLocal(0, 1, 0);
}
else if((collisionLocation.getZ() % blockTerrain.getSettings().getBlockSize()) == 0){
blockLocation.subtractLocal(0, 0, 1);
}
}
return blockLocation;
}[/java]

For floor() to work you have to be passing a floating point number. Otherwise, your answer is just returning the integer that you passed it.

Therefore, you must be doing int / int math inside the floor. It’s trivial to check with some debugging or separating out the math and printing it. I’m always surprised how no one seems to think of these simple assumption-checks these days.

Anyway, I suspect if you cast one of those ints to a float then your problem will disappear.

1 Like

Nonono, do NOT adjust the negative chunk numbers by -1!
Chunk numbers of 0 are perfectly fine.

See it as number ranges mapped to integers. With a chunk size of 25.0, you need to map:
[java]
-50.0 <= x < -25.0: -2
-25.0 <= x < 0.0: -1
0.0 <= x < 25.0: 0
25.0 <= x < 50.0: 1
50.0 <= x < 75.0: 2
[/java]
Note the asymmetry - it’s intentional, and happens because we’re mapping intervals (floats) to points (ints). You could achieve a symmetric mapping by shifting the boundaries down by 25/2 = 12.5, like so:
[java]
-62.5 <= x < -37.5: -2
-37.5 <= x < -12.5: -1
-12.5 <= x < 12.5: 0
12.5 <= x < 37.5: 1
37.5 <= x < 62.5: 2
[/java]
It’s not worth it though, since there should be nothing special about zero, negative, or positive coordinates, it’s all contiguous.

In other words, the whole code between lines 7 and 17 should be eliminated.

1 Like

The trick is that:
1 / 2 = 0

Where as:
(float)1 / 2 = 0.5

Big difference when passing those values to floor().

Actually, that’s exactly what I did, pspeed. I figured it might have something to do with integer math, since I’ve had issues in the past. Hooray for actually understanding!

As for ulfgur’s issue, here’s the code that I use:

[java]public Vector3I cpos(Vector3I pos) {
Vector3I chunkp = chunk(pos).mult(Chunk.SIZE);
int x = pos.x - chunkp.x;
int y = pos.y - chunkp.y;
int z = pos.z - chunkp.z;
return new Vector3I(x, y, z);
}[/java]

The method chunk(Vector3I in) looks like this:

[java]public Vector3I chunk(Vector3I pos) {
	int x = (int) FastMath.floor((float)pos.x / Chunk.SIZE);
	int y = (int) FastMath.floor((float)pos.y / Chunk.SIZE);
	int z = (int) FastMath.floor((float)pos.z / Chunk.SIZE);
	return new Vector3I(x, y, z);
}[/java]
1 Like

Math beats Logic!!!

Replacing ugly code with nice clean elegant Math 8)

Oooh, it works! Glitchy, but functional! Thank you guys so muck!

I’m having some glitchyness, but I think (hope) I can work it out on my own. This is great!

Ok, I was wrong. Darned optimism gets me every time.

I corrected the occasional random glitchyness just fine, but I’ve got a recurring issue where picking the back of a block returns an X value that is one too high. For some reason, none of the other dimensions or directions are effected. Any ideas?

I must say, this is a vast improvement over using offsets.

The other thing I need advice on: I need my function to be more flexible, and able to pick the selected block instead of the adjacent facing block. I don’t know how this might be achieved.

Hi, one simple question.

Is there some location where I can download the source for this directly, eg without the sdk?

@Empire Phoenix said: Hi, one simple question.

Is there some location where I can download the source for this directly, eg without the sdk?

Where all of the plugins are:
http://jmonkeyplatform-contributions.googlecode.com

1 Like

Oh, are you doing picking already?

The way I do it is to find the surface normal and compare it to a face. If it’s close enough, I add the surface normal to it divided by 2 (the sides of the block are at 0.5-ish, yeah?) and the result is the right block placement.

As for picking the block itself, you just subtract the surface normal divided by 2, doing floating point division, and then round the number.

Hm this might be a stupid question,

but in the wiki there are some special blocks like the pyramid or the smaller ones,
however in the examples and the source I did not found out how to create those.

Does anyone know?

Don’t quote me on this–I could easily be wrong–but the last time I checked, this was an “upcoming feature” then destroflyer became busy and has not yet implemented it.

I believe the way he does it is that each non-cubic block gets its own geometry.

Inefficient, to be sure, except for when it’d be for things like some of the mods in Minecraft, and base Minecraft itself - y’know, like the brewing stands and stuff.

I was actually doing work on pre-defining some shapes for rendering, that can be put to an orientation. So far I have wedges relatively stable. The nice thing about these is that it’s all data, not objects, so you can have them in meshes as well.

If you are referring to this screenshot:

Those blocks are added to the one geometry like the cubes (And redundant faces like the bottom face of the pyramid block are removed as well) - I don’t know where you read that everyone of them got its own geometry, but that’s just wrong. oO
The feature is also completed and works - I just didnt’ have to time to commit the update, but I have 2 weeks of holidays now and maybe I’ll finally get the time to do so. As I said the project doesn’t have a high priority for me but the update will come, I just don’t want to promise when. :slight_smile:

1 Like

That’s weird, I could’ve sworn that I saw something like that in… somewhere.

But in any case, neat! Apologies for making you sound wronger than you are, apparently.

On an interesting note, I’ve decided to add several things to the engine.

The first thing I added were what I called Builders.

Basically, there’s an instantaneous builder, than can take a set of supplied offsets and block IDs and reconstruct them, offset by the corner that has the lowest value (most negative?) to the most positive.

The other one is a dynamic builder, that places blocks over time. I thought it would be useful to have something like this for copying huge constructions - once I get the hang of threading, you can assign it a build speed and it will plod along on a different thread. I don’t know if my reasoning is correct, but placing stuff over time seems much less “BOOM LAG” like.

After a bit of testing, I think my reasoning has merit, too - I built a castle, set the corners, and copied the castle, first with the instantaneous one. It gave my computer a heart attack - froze the program for a bit.

Constrast with the dynamic one. It took the data, and I gave it a fairly sedate rate (about 10-12 blocks / second, done in batches of 3 / 4 every update) and chugged along for a little while, ended up smooth and slick. So much cooler to watch, too! (Want to animate it slightly, maybe block placement particles?) and wasn’t nearly so… harsh-feeling?

The other thing I’m currently working on is adding in stuff like block shapes (Thanks for the idea, destro! :D) and some form of metadata that makes sense. I also wish to abstract away the pure data from the rendering-related stuff, and gain the ability to rotate these block grids!

Things for the far future would be lighting (baked, probably). Maybe stuff like blocks that change color and texture, and if I can figure out how the heck it works, rotatable blocks.

I’ll be posting my repo at some point in the near future - if anyone’s interested, they can take a look.

I’ll leave this with a final thought: Has anyone tried using something like a BlockSet? It’s not a chunk, it’s a set of blocks (Kinda like my builder Constructs) that are independent of the regular chunk system. I was going to put them in so I could have rotating platforms and stuff. Good idea or one that could use work?

1 Like

Lots of good ideas!

About rotating blocks, was thinking maybe change texture coords to rotate, @pspeed or @destroflyer might have a better solution.

With baked lighting and day/night cycle, that has been a huge problem for myself, big complicated subject, lots of research, hope you plan better than what I did.

Now have a working model, still in testing though, from what I have research there is a few different ways to go about it, I went with a directional light for the control of day/night and sun and moon positions, then in the shader accessing the directional light to make some nice sunsets and sunrises, have a image to control the day/night baked lighting for the voxel mesh which is referenced in the shader from the directional light, this way the shader doesn’t require any variable passing other then directional light which is accessed through LightMode SinglePass, however not using any of the directional light colors in the scene, just using as a reference in the shader, and also using the directional light for the shadows filter.

Some screens.

Also forgot to shout out to @rickard, and his book = jMonkeyEngine 3.0 Cookbook, a few techniques I’m using from his book, like the sun and moon rotations, and the bird particle emitter, and with the same particle emitter technique also created shooting stars.

1 Like