Voxelers/mcthings

Thing build pipeline: create->transform->render

acs opened this issue · 15 comments

acs commented

After thinking during sometime about the Thing lifecycle, I think the best approach is:

  • Things data is created and modified always in memory: for that, we can use the Schematic format. All the blocks and data that are included in the Thing are created in memory in this Y, Z, X format.
  • The operations like rotate and others are done in memory
  • Once we want to show the Thing we need the position and the blocks and data ready. The way to show it (setBlock, setBlocks ...) could be improved in a generic way (use setBlocks for regions sharing the same blocks for example, or do nothing for air blocks ...)

Following this approach for all Things (all work is done in memory until the Thing must be shown) could let McThings to optimize the full process.

So load/create data and process it (rotate, decorate ...) must be done independently of building the Thing inside the engine (Minecraft, Minetest, Blender ...).

So the Thing implementation must not be inside the build method (which is an optimized generic method to build things inside the engine from data in memory) but inside the create method. With the Thing created in memory, we can process it with rotate or scale or find_bounding_box. For example, the to_schematic method will be much easier: just write the memory. You don't need to read the Thing from the already built Thing.

Let's try to implement it. My only doubt is that we could need something that it is only known when you built the Thing. But having the blocks ids and the data, and their position, is all we need AFAIK.

Working in memory is much faster always and abstract us from the engine.

acs commented

In a summary: CREATE (memory)->TRANSFORM (memory)->RENDER (real build).

The current build will be implemented as: create, render

acs commented

Use render or show? Render semantic is much better: "to cause to be or become". We take the data from memory and make real thing with it (inside Minecraft, Minetest, Blender ...). So let's use this word (which is the natural one in computer graphics design).

acs commented

The idea is simple:

  • Create the Thing in memory: use the same API than now, setBlock and setBlocks. But probably I will change it to setVoxel, setVoxels. In Minecraft a voxel is a block, so it will be mapped so setBlock. But it is the same idea than setPixel (vs setPoint).
  • We need the dimensions of the Thing: size (size_x, size_y, size_z) But it is created automatically during the creation of the Thing. We will reuse Vec3 type for it.
  • We have the data list and the blocks_id list (with flattening, only the blocks_id list is needed, but let's support both for legacy and to be more general)
  • The order in the list is the same than in Schematics: width (X), length (Z), height (Y)
  • We have the creation API (setVoxel, setVoxels) and this will be rendered in different engines (Minecraft/Minetest with the RaspberryPI API, Blender with its Python API, Goxel/MagicaVoxel/* if they offer an API ...)
  • Maybe we can have an alias setBlock to setVoxel, setBlocks to setVoxels so it is easier to understand the API. But not sure yet.
  • To have the data in memory will help testing it during creation and transformations.

Let's start implementing it for a block, then a group of blocks and then migrate all to this new system.

acs commented

Probably this ticket should be: Thing pipeline.

Thinking in creating Scenes in MagicaVox I have arrived to: https://github.com/jpaver/opengametools Pretty interesting.

acs commented

First Things created using the new pipeline. Pretty close to have it working in all cases.
Screenshot from 2020-06-18 06-35-15

acs commented

After the refactor to use the new pipeline

Things creators

class Block(Thing):

    def create(self):
        self.set_block(Vec3(self.position.x, self.position.y, self.position.z), self.block)
        self._end_position = self.position

The same code, but implementing create instead of build. And the set_block and set_blocks API are now in Things API (more clear).

Things users

When creating a new Thing, the renderer must be provided:

        self.renderer = RaspberryPi(self.MC_SEVER_HOST, self.MC_SEVER_PORT)
        block = Block(pos, self.renderer)

More clear than before, when the "renderer" was created hiddenly.

acs commented

Next steps:

  • Complete the render implementation for a cuboid (already done for schematics)
  • Convert mcthings, mcthings_extra and mcthings_scenes to the new version
acs commented

All done except:

  1. River and line for unbuilding need the block that they removed. This must be done in the renderer.
  2. McDrawing is no using at all the new pipepline: probably we should have our own sphere and move it to mcthings_extra
  3. World.server must be removed to be sure the Minecraft server is only use through the renderer
  4. We have performance issues strange rotating a schematics. My impression is that it was faster before. There is no reason for the ne slowness. The rotation is done in memory and it should be pretty fast. Research it! fixed
  5. TestScene fails when executing all the tests together fixed
  6. Move all things to then package mcthings.things
acs commented

Ok, all is now in develop brach! And I have created a new release: 0.49.0

So, for future iterations:

  1. River and line for unbuilding need the block that they removed. This must be done in the renderer.
  2. World.server must be removed to be sure the Minecraft server is only use through the renderer
  3. McDrawing is no using at all the new pipepline: probably we should have our own sphere and move it to mcthings_extra
  4. The memory design as a list of BlockMemory including the position for all of them can be improved a lot following the schematic approach. But it is harder to manage it.
acs commented

Next step is to update mcthings_extra and mcthings_scenes to use the 0.49.0 version.

acs commented

Ok, after the work in mcthings_scenes we need to:

  • Move renderer to the World class: we have just one renderer per World ok
  • Improve set_blocks so it can receive any two vertex that are opposite ok
acs commented

All working in mcthings 0.49.3 and mcthings_extra 0.0.16.

Pending to fix all mcthings_scenes! And we will be ready.

Just pending also to fix the building because houses how overlaps. But this is quick!

And "River and line for unbuilding need the block that they removed. This must be done in the renderer."

acs commented

All implemented and working for mcthings_extra (0.0.16) and mcthings_scenes with mcthings 0.49.5.

Pending:

  • fix the building because houses how overlaps. But this is quick! ok
  • And "River and line for unbuilding need the block that they removed. This must be done in the renderer." ok
acs commented

All done, releasing the 0.50.0 version!

https://pypi.org/project/mcthings/0.50.0/

acs commented

As final thoughts:

  • McDrawing is a kind of extra rendering and it does not support the create->transform->render pipeline. It just renders. So at some point it must be moved to mcthings_extra if possible.
  • The memory is not designed for low size. All the blocks have their position (it can be inferred).
  • The memory is storing mcpi.blocks.Block item: so it is pretty close to Minecraft pre-flattening format. This will evolve in the future if the MC pre-flat render is not the main one.

All done!