Creating collision boxes for Meshes

     One of the difficult parts of using Meshes in Minetest for nodes has always been figuring out the collision/selection boxes. Many times it's possible to just use a full node collision box for nodes smaller than a full box, but sometimes you need more precision. In the past I always used the trial and error approach. Change one value, launch the game, place the node, and see which face moved and how much more it needs to be moved. Rinse and repeat, for all six faces, objects that had more than one collision box just meant that I needed to do more cycles to get everything set. Recently during a live stream it came to me that it should be possible to create collision boxes with the OBJ file data. A basic box in OBJ format looks a little something like this.
# Blender v2.79 (sub 5) OBJ File: ''
# www.blender.org
o Ear.001_Cube.003
v -0.700000 -0.400000 -0.100000
v -0.700000 -0.100000 -0.100000
v -0.700000 -0.400000 -0.400000
v -0.700000 -0.100000 -0.400000
v -0.500000 -0.400000 -0.100000
v -0.500000 -0.100000 -0.100000
v -0.500000 -0.400000 -0.400000
v -0.500000 -0.100000 -0.400000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
s off
f 1//1 2//1 4//1 3//1
f 3//2 4//2 8//2 7//2
f 7//3 8//3 6//3 5//3
f 5//4 6//4 2//4 1//4
f 3//5 7//5 5//5 1//5
f 8//6 4//6 2//6 6//6

​The first three lines are junk and all of the lines after the eleventh can also be ignored leaving us with just this data.

v -0.700000 -0.400000 -0.100000
v -0.700000 -0.100000 -0.100000
v -0.700000 -0.400000 -0.400000
v -0.700000 -0.100000 -0.400000
v -0.500000 -0.400000 -0.100000
v -0.500000 -0.100000 -0.100000
v -0.500000 -0.400000 -0.400000
v -0.500000 -0.100000 -0.400000

This is an array of all the vertices that make up the cube, one for each corner, they are arranged in columns of X, Y, and Z.

A collision box in Minetest looks like this
{X1, Y1, Z1, X2, Y2, Z2}
where X1, Y1, and Z1 are coordinates to one corner of a box, and X2, Y2, and Z2 are the opposite corner.

In Minetest X is East/West, Y is Elevation, and Z is North/South. If your node has param2 = 'facedir' the X and Z might not be correct, and it might be easier to comment out that line of code while working on setting up the collision/selection box. Once you get the hang of it you can leave the param2 line in and expect things to work perfectly.

We can pull the data from the mesh data and insert it into the table in our LUA code. For the first three entires use the lowest X, Y, and Z values, and for the last three use the greatest X, Y, and Z values. The lowest value can be greater than -.5 or .5 if you have a box that is larger, or sit outside of a full node space. Minetest won't mind if you do this, and it won't create any problems, just use the data and see if it works before you start freaking out about it being incorrect.

Here is an example of some OBJ data and the resulting table.

    X         Y        Z
v -0.400000 0.400000 0.900000
v -0.400000 0.600000 0.900000
v -0.400000 0.400000 -0.400000
v -0.400000 0.600000 -0.400000
v 0.200000 0.400000 0.900000
v 0.200000 0.600000 0.900000
v 0.200000 0.400000 -0.400000
v 0.200000 0.600000 -0.400000

 -x  -y   -z    x   y   z
{.4, .4, -.4, -.2, .6, .9}

For some reason that I don't totally understand it is necessary to multiply the X values by negative one for this to work, otherwise your collision box will be offset. I've used this system with six or seven different meshes and it seems to have worked every time. There will likely be some edge cases that I didn't think of, but I did do this method with boxes that did not cover the origin point, 0,0,0 and it still worked perfectly.

I would not recommend using your models obj to get this data, as there will be far too much to look through, it's easier if you create a second mesh that is just a box which contains your model and export that. If you want to do multiple small boxes to cover your entire model you can do that as well, and you use the same method, but create a table for each box. Be sure that you use the same export settings when exporting you collision box mesh as you did the model or you may find that your data doesn't match and you have something that doesn't line up.

Add new comment