MyBlockZ - Voxel Engine

Hi,

as mentioned in another post i took code from moonkey and zzeug as starting point and created my own voxel kit.

Here is the latest video of what i have done so far:

I created a system with a Voxel Classwith coordinate which can be added removed.
Adding physics on large custom meshes(especially when modifying the meshes) can take long, so bound voxels together to tiles.
The tiles (16x1x16 atm) are put in nodes for culling optimizations.

Now i will try to add some paging for endless world.

Some notes:
World is created in 9 Seconds and is 256x20x256 in size.
Fps 300-400

Thank you for this engine! It just took me 4-5 days to get this far.

3 Likes

Kewl, afaik none fo the voxel/block world code in the update center is really maintained so if you want to add your library you’re welcome.

Ok i will fix some issues and willt try to beutify my code and doc (which is nonexistent atm) and contribute my library before i will start to create my real game from it :wink:

Ok solved many issues. Now i am having some difficulties with a timing problem and i am not sure on which side it is.

As usual i demonstrate with a video:

@Kiessar said: Ok i will fix some issues and willt try to beutify my code and doc (which is nonexistent atm) and contribute my library before i will start to create my real game from it ;)
I'm sure many people will be happy about that :)

About your problem: Idk exactly what you mean by “timing issue” but it looks like the collision shape is not always updated? Is that happening off the main thread?

Yes i only use one thread(main) at the moment to avoid timing issues …
Ok here comes the ugly code: [java]

    physicSpace.remove(t.getRigid());
    this.geometry.setMesh(getMesh());

    geometry.removeControl(rigid);
    rigid = new RigidBodyControl(0);
    geometry.addControl(rigid);
    physicSpace.add(t.getRigid());

[/java]

Thats how i update a geometry and its rigidbodycontrol.

Unfortunately i optimzied some other things and now it happens really rare and i couldn’t create a reproducable case.

That code doesn’t look like it can work as it either changes the control off the main thread or creates the collision shape on the main thread. The former would be a good cause for all kinds of strangeness and the latter would thwart its purpose. What has to happen is basically this (pseudo code, called from the main thread):

[java]public void updateCollisionShape(){
final Mesh mesh = spatial.getMesh();
//execute creation on external thread
collisionShapeProcessor.exec(new Callable(){
public void call(){
final CollisionShape shape = CollsionShapeFactory.createShape(mesh);
//now send this back to render thread (or to physics thread directly, but it won’t make much of a difference)
app.enqueue(new Callable(){
public void call(){
//recreate or set new collision shape to rigidbody, won’t make much of a difference either way
spatial.getControl(RigidBodyControl.class).setCollisionShape(shape);
}
});
}
});
}[/java]

If you look at our multithreading tips in the wiki, you could also make it via a managed Future so you can cancel the collision shape generation. This simple asynchronous code I posted will just create a collision shape for each time the update is called (or the user changes a block)… You might want to have control over the creation to be able to stop it.

Edit: Sorry I misunderstood your “yes” :smiley: So its not threaded atm… Since you have other issues you should probably leave it that way for now :wink: But for later ^^

I am still working on it :wink:
I just finished the paging, but the problem of recreating the collision shape gets kinda heavy now!
So i will try to put in your fix now! What are "collisionShapeProcessor " and “CollsionShapeFactory” can’t find this classes.

CollisionShapeFactory is in the package com.jme3.bullet.util.
As for the collisionShapeProcessor, @normen should know that. He’s the one that wrote it. xD

Its just an executor, for tasks, its something you have to create. Basic java multithreading, check the wiki. CollisionShapeFactory, its a typo. Copy-paste kills :wink:

Thx for your support!
I am getting a NullPointerException with code as follows:
Main.Class:
[java]
final ScheduledThreadPoolExecutor collisionShapeProcessor = new ScheduledThreadPoolExecutor(4);

public void updateCollisionShape(final Geometry geo) {

    //execute creation on external thread
    collisionShapeProcessor.execute(new Runnable() {
        public void run() {
            final CollisionShape shape = CollisionShapeFactory.createDynamicMeshShape(geo);
            //now send this back to render thread (or to physics thread directly, but it won’t make much of a difference)
            enqueue(new Callable() {
                public Object call() throws Exception {
                    geo.getControl(RigidBodyControl.class).setCollisionShape(shape);
                    return null;
                }
            });
        }
    });
}

[/java]

Tile.class
[java]
public Tile(Vector3i position) {
geometry = new Geometry("Tile " + position);
this.position = position;
this.rigid = new RigidBodyControl(0.0f);
geometry.addControl(rigid);
}

[/java]

java.lang.NullPointerException at com.jme3.bullet.objects.PhysicsRigidBody.preRebuild(PhysicsRigidBody.java:122) at com.jme3.bullet.objects.PhysicsRigidBody.rebuildRigidBody(PhysicsRigidBody.java:113) at com.jme3.bullet.control.RigidBodyControl.setSpatial(RigidBodyControl.java:101) at com.jme3.scene.Spatial.addControl(Spatial.java:591) at mygame.Tile.(Tile.java:36) at mygame.TileManager.addTile(TileManager.java:40) at mygame.Main.generateFloor(Main.java:336) at mygame.Main.simpleInitApp(Main.java:261) at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:225) at com.jme3.system.lwjgl.LwjglAbstractDisplay.initInThread(LwjglAbstractDisplay.java:130) at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:207) at java.lang.Thread.run(Thread.java:662)

I will start to refactor/clean/document and hopefully contribute this evening :wink:

Your geometry has no mesh data.

Jup realized to late sorry.

Another
[java]
final CollisionShape shape = CollisionShapeFactory.createDynamicMeshShape(geo);
[/java]

Shape is null.

java.lang.NullPointerException at com.jme3.bullet.objects.PhysicsRigidBody.setCollisionShape(PhysicsRigidBody.java:528) at mygame.Main$1$1.call(Main.java:505)
@Kiessar said: Jup realized to late sorry.

Another
[java]
final CollisionShape shape = CollisionShapeFactory.createDynamicMeshShape(geo);
[/java]

Shape is null.

java.lang.NullPointerException at com.jme3.bullet.objects.PhysicsRigidBody.setCollisionShape(PhysicsRigidBody.java:528) at mygame.Main$1$1.call(Main.java:505)

I’m not sure what you are asking now. If the geometry has no mesh data then I’d expect this not to be able to create a collision mesh either.

Something is wrong the the “geo” that you are passing in… given the previous error, make sure you’ve actually given it a mesh.

If all the tiles are cubes, just do something like this:

[java]
public Tile(Vector3i position) {
geometry = new Geometry(“Tile ” + position);
geometry.setMesh(new Box(Vector3f.ZERO, box dimensions here));
this.position = position;
this.rigid = new RigidBodyControl(0.0f);
geometry.addControl(rigid);
}
[/java]

That should help with the null mesh problems. Although generally you’ll get an output saying something like “Geoemtry has null mesh!” if your mesh is null. Is there anywhere in the code you assign a mesh to the geometry?

Works now!
Called update method elsewhere (before Mesh was set).

Is there another way to call enqueue?
I don’t want to give my TileManager an reference to an Application.

Without a reference to app you obviously cannot enqueue cause you enqueue to the app… Theres various ways to access the variables apart from passing it in a constructor, welcome to code design ^^

Hm yup i should have thought about before asking stupid question…
But i thought there could be an Interface but that i could(and have now) have checked myself.

Continueing with programming -> stopping stupid questions :smiley:

Normally, tile manager might be an app state… and then would have been passed what it needed on initialize. Or at least the tile manager could be held and managed by an app state.

It’s kind of the “jme way”.