Cubes – A Block World Framework [Update Preview]

So, I don’t know if this was addressed already, but how do I properly get negative indexes? Currently, it seems my engine can only handle positive chunk coordinates - I’d like to be able to do negative if possible.

It should be fairly simple, but I could be horribly wrong.

Weeeel, the theory is fairly simple-- replace the int[][][] that stores chunks (found in BlockTerrainManager) with a hashmap or arraylist or other collection, then make minor alterations to the coordinate system.

In practice, this is significantly more complicated. I’ve managed to get my terrain infinite (I’ll share the modified code with you, if you want) but my negative coordinates result in some really screwy bugs–placing nicely during terrain generation, but refusing to modify afterward, etc. I solved this using an offset.

@ulfgur said: I solved this using an offset.

That was going to be my suggestion. :slight_smile: “I want to be able to go to -50,000 X…” “Ok, x = x + 50,000” :slight_smile:

Yeah, I’ve done the hashmap of chunks - that was pretty clear to me that I’d need it. And I went and did a whole lot of testing compilation online (stuff like looping and printing different operations on integers, 1 - 32 and -1 to -32) but I couldn’t nail down what I wanted to do.

If you’d share the code, I’d greatly appreciate it! The infinite terrain generation in positive directions works just fine, in mine, and I’ve managed to get purely negative coordinates within a block of where they’re supposed to be - I’m guessing I’m getting hangups on 0 and -0, maybe, or something like that. Not sure.

Currently, the way I do that is taking the position, and if any of the axis’ are negative, add the negative value (so subtract) from the size of the chunk, and also subtract 1 more to compensate for 0 - 15 index.

If I can’t figure out how to get negative indices working, then an offset may well be the only way to go about things.

You may have to explain how you are doing what you’re doing. For example, if you are trying to turn a float into a cell then 0.0 to 1.0 is 0 but 0.0 to -1.0 is -1… that’s a pretty easy one to get tripped up on. floor() is your friend there.

@ulfgur said: In practice, this is significantly more complicated. I've managed to get my terrain infinite (I'll share the modified code with you, if you want) but my negative coordinates result in some really screwy bugs--placing nicely during terrain generation, but refusing to modify afterward, etc. I solved this using an offset.

It’s better to fix those bugs, rather than fix the symptoms.
Partly because the next one to hack on the code might be bitten by them.
Mostly because they might cause less conspicuous behaviour that will be even harder to connect to the actual bug site.

pspeed’s advice is a good one to look for.
The other would be to set up some minimal example that shows undesired behaviour, find out what values in the data are erroneous, then find out what code generated the erroneous value. Work your way backwards until you find the actual culprit, then fix that.
This can take quite a while (a day or two, more if you’re unlucky), and it won’t give you any new features, but it does wonders for what people will later describe as stability or reliability, so it’s still worth it, just not marketable :slight_smile:

Here is the modified code I’ve been using:

https://code.google.com/p/cubesmod/source/browse/modified+cubes+2.zip

Feel fry to use it for any purpose. I have only one stipulation: if you do end up using this, PLEASE tell me about any fixes/changes you perform so that I can also implement them.

The system is now multithreaded and significantly more stable than the last version. Because I have not yet implemented a mesher (had something bigger to make work, it should come in the next update or three) once the local area has been loaded, runs at around 150 fps. While loading new areas, typically runs at 10-40 fps, but remains more or less playable.

Here’s the function I use to set up the player: (my final variable worldScale is set at 2, I think)
[java]
/**
* sets up the player/camera
*/
public void setUpPlayer()
{
characterNode = new Node();

    player = new BetterCharacterControl(.5f * worldScale - .1f, (2 * worldScale) - .2f, 81);
    player.setJumpForce(player.getJumpForce().mult(worldScale * 1.5f));
    //player.setJumpForce(player.getJumpForce().mult(worldScale * 20));
    player.setGravity(player.getGravity().mult(worldScale * 6f));
    //player.setGravity(new Vector3f(0, 0, 0));
    
    
    characterNode.addControl(player);
    Vector3f playerLoc = new Vector3f(90010, 90150, 90010).multLocal(worldScale);
    //Vector3f playerLoc = new Vector3f(blockSettings.offset, blockSettings.offset, blockSettings.offset);
    player.warp(playerLoc);
    rootNode.attachChild(characterNode);
    bulletAppState.getPhysicsSpace().add(player);
}

[/java]

@Eliwood said: Yeah, I've done the hashmap of chunks - that was pretty clear to me that I'd need it. And I went and did a whole lot of testing compilation online (stuff like looping and printing different operations on integers, 1 - 32 and -1 to -32) but I couldn't nail down what I wanted to do.

If you’d share the code, I’d greatly appreciate it! The infinite terrain generation in positive directions works just fine, in mine, and I’ve managed to get purely negative coordinates within a block of where they’re supposed to be - I’m guessing I’m getting hangups on 0 and -0, maybe, or something like that. Not sure.

Currently, the way I do that is taking the position, and if any of the axis’ are negative, add the negative value (so subtract) from the size of the chunk, and also subtract 1 more to compensate for 0 - 15 index.

If I can’t figure out how to get negative indices working, then an offset may well be the only way to go about things.

@toolforger said: It's better to fix those bugs, rather than fix the symptoms. Partly because the next one to hack on the code might be bitten by them. Mostly because they might cause less conspicuous behaviour that will be even harder to connect to the actual bug site.

pspeed’s advice is a good one to look for.
The other would be to set up some minimal example that shows undesired behaviour, find out what values in the data are erroneous, then find out what code generated the erroneous value. Work your way backwards until you find the actual culprit, then fix that.
This can take quite a while (a day or two, more if you’re unlucky), and it won’t give you any new features, but it does wonders for what people will later describe as stability or reliability, so it’s still worth it, just not marketable :slight_smile:

I fought with tooth and nail to iron out that bug, but I think i’m not quite experienced enough… I agree, I’d much rather cure the bug than the symptom. I even narrowed down where it was occuring, but the whole thing was so odd that I couldn’t solve it.

I called setBlock from my terrain generator, and it worked fine. I called setBlock from my main class, and it tried to fix stuff at the correct coordinates, but either didn’t do anything or modified a completely erronious block. The whole thing was so bizarre that eventually using an offset became my only viable option.

If any of you happen to fix that problem (offset can be countered by modifying the following line in all of the noise generation functions), tell me how. I’d much rather not use an offset.

if((y + yOffset) <= ((noiseValue) + settings.offset))

I’ve been working through a way to take an integer and get two integers from it, to figure out how to get proper negative indices.

My line of thought is that, at (-1, -1, -1), the chunk index would be (-1, -1, -1), and the chunk-relative position would be (chunksizeX, chunksizeY, chunksizeZ)

My chunks are 16 blocks in all 3 axis. So that would mean that, a block at (-1, -1, -1) would be in chunk(-1, -1, -1) and, within the chunk, would be at (15, 15, 15)

So far, (with in being an integer) the variations are:

Math.abs((in < 0 ? (16 + (in % 16 + 1)) : in % 16));
This one wasn’t as close.

Math.abs(in < 0 ? (16 + in % 16) : in);
Decently close.

(in < 0 ? Math.abs(16 - (16 - (in % 16)) % 16) : in % 16);
This was extremely close. Unfortunately, I think it gets hung up on the first negative chunk, because the indices only go from 0 to 14. All the others are fine (0 - 15). I don’t know how to fix that - there are only 15 numbers between -1 and -16, and 0 counts as a number.

Along with a couple others that don’t quite do it.

Honestly, I thought it would be simpler - if i is negative, then % it, get the absolute value, and subtract it from 16.
if not, then just % it and return it.

I was mistaken, it seems.

Anyways, any evaluation on my little methods would be appreciated - lemme know if I’m going in the right direction! :slight_smile:

xChunk = (int)Math.floor(x / chunkSize);

…which I already said but less specifically. Though I did specifically mention floor().

I do understand that that is used for getting chunk indexes. And it’s more efficient than what I was doing.

I don’t, however, believe that applies to my current issue (though I thank you for the indescribably simpler code!)

@Eliwood said: I do understand that that is used for getting chunk indexes. And it's more efficient than what I was doing.

I don’t, however, believe that applies to my current issue (though I thank you for the indescribably simpler code!)

Well, it seemed like there was a lot of issues with have -32 to 0 be -1 and that will do that.

I see where you’re coming from.

An idea that just came to me, in another way, would be to separate the terrain into 4 quadrants, kinda like a quadtree, and depending on whether values are negative or positive, find the quadrant. It removes the need for “negative” coordinates, since you could just manipulate the negatives like positives.

I guess I don’t really understand what the issue is… I handled negative coordinates no problem in all of my terrain engines.

Maybe I’m just not understanding what you’re trying to tell me.

With my knowledge, I can only conclude that I’m going the wrong way when I’m trying to do this.

Like, it should be fairly simple to get a chunk and put a block where it’s supposed to go, and the positive ones work just fine. But whenever I do negative, it just doesn’t want to work - with my current system, blocks sometimes don’t appear.

I’m stumped, honestly. I’ll post the work I have on github tomorrow, and perhaps someone can help me out a bit if they wouldn’t mind.

@Eliwood said: Maybe I'm just not understanding what you're trying to tell me.

With my knowledge, I can only conclude that I’m going the wrong way when I’m trying to do this.

Like, it should be fairly simple to get a chunk and put a block where it’s supposed to go, and the positive ones work just fine. But whenever I do negative, it just doesn’t want to work - with my current system, blocks sometimes don’t appear.

I’m stumped, honestly. I’ll post the work I have on github tomorrow, and perhaps someone can help me out a bit if they wouldn’t mind.

Well, break down the math into multiple steps and see where it’s going wrong.

int xChunk = (int)Math.floor(x / chunkSize);
int xChunkWorld = x * chunkSize;
int xBlock = x - xChunkWorld;

@Eliwood said: Maybe I'm just not understanding what you're trying to tell me.

With my knowledge, I can only conclude that I’m going the wrong way when I’m trying to do this.

Like, it should be fairly simple to get a chunk and put a block where it’s supposed to go, and the positive ones work just fine. But whenever I do negative, it just doesn’t want to work - with my current system, blocks sometimes don’t appear.

I’m stumped, honestly. I’ll post the work I have on github tomorrow, and perhaps someone can help me out a bit if they wouldn’t mind.


You should probably be aware–Cubes has a built-in safety net somewhere that prevents negative coordinates from being used. I think you can find most uses by deleting the function in Utils, then seeing where error messages pop up. It’s been a little while since I tangled with this, though, so I don’t know.

If you do find a solution, please share it. It’s probably the same problem I had before I fixed the symptoms. ; )

Oh. I fixed it.

And it works.

Alright, so to explain what I did…

I used Pspeed’s little code tidbit for the chunk indices, slightly modified:

int index = (int) FastMath.floor((float)pos.x / Chunk.SIZE);

That gives me the right chunk index.

So, with a bit more math, I figured out what I was trying to do with chunk-relative positions:

int x = pos.x % 16; if (x < 0) x = ((Chunk.SIZE) - Math.abs(x));

My former reasoning was actually correct, I just couldn’t implement it correctly, until I did this. As far as I am aware (and I did a loooot of testing) this works universally - negative indices and positive indices both are placed where they need to be, in the correct chunk, and render properly.

1 Like
@Eliwood said: int x = pos.x % 16; if (x < 0) x = ((Chunk.SIZE) - Math.abs(x));

Is chunk size 16? If so, then you’ve just done the really convoluted way of what I did… and I think mine was clearer since really what you want is “index relative to the current chunk” which “x - xCurrentChunk” gives you without even needing a comment explaining “I’m getting x relative to the current chunk location”.

Oh, I finally get what you’re talking about.

Wow, that is a lot simpler.

Derp?

Would you mind posting the code you used?

int chunkX = (int)Math.floor(blockLocation.getX() / settings.getChunkSizeX());

is mine, but it has trouble. The negative coords are always off by one.