Translation notice
This page was translated with machine translation and may contain inaccuracies. If you can help improve it, please open an issue or submit a pull request.
A feasible method to convert OBJ model to json model
keywords OBJ model, json model, Minecraft, geometry structure conversion, voxelization, lightweight model, tangent space
Overview and background
This article aims to study a feasible high-precision, nearly lossless and lightweight method of converting OBJ (Wavefront) to JSON model (Minecraft style) to help artists quickly import the project into the Minecraft scene after completing the design in a general modeling software.
There are significant differences between the two models we considered. The OBJ model defines the geometric structure of the object by vertices and surfaces, with triangular surface meshes as the core (some software also supports polygonal surfaces), and can represent complex geometric structures (such as curved surfaces) with high precision and low polygon count. Minecraft's json model is defined by voxels that have been translated, rotated, and scaled, and usually cannot represent complex surfaces well, or even triangles. Without considering textures and maps, we will next discuss a feasible method to convert OBJ models to json models with acceptable visual effects errors.
Traditional implementation of model voxelization
Method introduction
The traditional way to convert an OBJ model to a voxelized model similar to a json model is to approximate the geometry of the OBJ model with axis-aligned cubes (voxels). The basic idea of this method is:
Place the OBJ model into a 3D mesh
Determine the minimum subdivision mesh
For each grid cell, check if it intersects the OBJ model, and if so, fill a voxel
Optimize the generated voxel model to reduce the number of voxels
Get the final voxel model
Shortcomings of the method
The implementation of this traditional method is simple, but it has shortcomings that cannot be ignored:
The visual error produced by this method is too large (we have not yet defined the error), especially for curved and sloped surfaces, and voxelized models tend to appear very rough.
Achieving high visual accuracy requires the use of very fine meshes, resulting in a massive increase in voxel count and making the model very large and difficult to use in Minecraft.
Even if optimization is performed, such as merging some voxels, or using different levels of detail (LOD) at different locations, the generated voxel model may still contain a large number of redundant voxels, which affects performance and is not conducive to modification by artists.
Improvement method
Define error
In order to better measure the difference between the converted json model and the original OBJ model, and for us to implement the optimization algorithm, we need to define the error values before and after conversion.
Volume error
For the error caused by volume fitting (such as traditional methods), we can use the distortion volume to measure it. The distortion volume is defined as the difference between the union volume of the two models and their intersection volume. Since we will eventually observe the model at various angles, we need to calculate the distortion volume projection area under different viewing angles and take the average value as the final error indicator.
Research points out that convex polyhedron in three-dimensional space isThe average projected area under the action and the surface area of the polyhedron are constant values.For concave polyhedrons (the more general case) this conclusion no longer holds since the faces will occlude each other, but we can approximate the average projected area by sampling multiple viewing angles, and its upper bound is still, in order to simplify the calculation, we use an upper bound to measure the error.
Right now,
inis the surface area of the distortion volume,for perspectiveThe projected area under , integrated over the entire unit sphereproceed on. We useAs an upper bound on the simplified error, this simplifies calculations while ensuring conservative estimates.
surface error
Errors caused by surface fitting(As we will introduce next), we can use the distortion surface area to measure, the distortion surface area is defined as the absolute value of the difference between the surface areas of the two models.
Similarly, we do not consider the influence of occlusion and directly use the sum of the distortion surface area of each subdivision surface as the error metric. The specific calculation formula is related to the fitting method, which we will introduce next, but the idea is similar to the volume error.
Optimization direction
Model complexity can be measured by the number of voxels. We hope that the error and complexity are as small as possible, but the two are often contradictory. Define a cost index that is proportional to the error and complexity (weighted sum measurement is used here), that is
inis the error index,is the number of voxels,is the weight coefficient. We hope that through optimization algorithms, we can makeminimize.
A review of improved voxelization methods
Since Minecraft's json model is defined based on rotatable voxels, we can take advantage of this to better fit the geometry of the OBJ model by allowing the voxels to rotate, thereby reducing errors.
For the original OBJ model, we define connected, parallel triangles as a surface. Triangles in the surface satisfy the following conditions:
Adjacent triangles in the surface have at least two shared vertices
The normal directions of all triangles in the surface are the same (i.e. parallel), and the angle error must be small enough to be considered in actual implementation.
Triangles that meet the above two conditions also belong to the surface if they are adjacent to triangles in the same surface.
For each surface, we calculate its tangent space (tangent space), that is, define a local coordinate system so that the normal direction of the surface is aligned with an axis of the local coordinate system. We then voxelize in this tangent space, using axis-aligned voxels to approximate the geometry of the surface.
Specific implementation steps
Read OBJ model
This step is relatively simple. The OBJ file format is a text format. You can use existing libraries (such as TinyOBJLoader) to parse OBJ files. You only need to extract vertex, normal and face index information. In the file, respectivelyv n fThe first lines represent vertex, normal, and face indices.
Sometimes the normal information may not exist or be unreliable, we can calculate the normal from the vertex and face information. For each triangular face, we can calculate the normal using the cross product:
Sometimes polygonal faces appear in the OBJ model (such as the model exported by Blender). We can triangulate the polygonal faces and convert them into multiple triangular faces for processing.
Construct surface connected components
We traverse all the triangular faces we read, create connected components according to the above definition, and obtain multiple surfaces, each of which is an undirected graph.
Compute tangent space
In each surface, we take the normal of that surface as the normal of the tangent space, take a vector that is not collinear with the normal as the tangent direction(such as the sides of any triangle, normalize them), and then calculate the direction of the bitangent through the cross product
Three vectors form an orthogonal local coordinate system, and we construct a transformation matrix, convert the global coordinate system into a tangent space coordinate system:
Since this matrix is orthogonal, its inverse exists and is equal to its transpose:
coordinate all vertices of the surfaceTransform to tangent space through this matrix:
Find the optimal rectangle in tangent space
In the tangent space, we need to find an optimal rectangle to initially fill the interior of the surface, so that after deleting the area of this rectangle, the number of remaining triangles is minimal. At the same time, since the error in this step can be avoided, we cannot accept any error, that is, to satisfy the rectangle, the conditions must be met:
- Rectangles that satisfy the condition are contained inside the surface.
- Due to artistic requirements, the side length of the rectangle needs to be the smallest element.an integer multiple of
Intuitively, the larger the rectangular area that meets such conditions, the better, but it is smaller than the maximum rectangular area that can be placed in the boundary of the surface. At the same time, there may be certain restrictions on angles and positions to minimize the remaining triangular surfaces.
We can find the optimal rectangle through enumeration. The specific steps are as follows (it can be replaced by a more efficient method to improve performance):
- Extract the boundary vertices of a surface in tangent space
- Align each edge with the coordinate axis respectively, and then useFor LOD, mesh the area within the boundary (only meshes completely contained within the boundary are retained)
- For each grid cell, try making it the lower left corner of a rectangle, then enumerate the possible widths and heights (bothan integer multiple of ), check whether the rectangle is completely contained within the bounds
- For a rectangle that meets the conditions, calculate the number of remaining triangles after deleting the rectangle, and record the rectangle with the smallest number of remaining triangles as the current optimal solution.
Note that after deleting the rectangle, the remaining areas may have non-triangular faces. We need to re-triangulate these areas to ensure that all remaining areas are composed of triangular faces. And for the remaining triangles, we need to recalculate their connected components, and the final measure is the total number of remaining triangle faces.
After determining the rectangle, we multiply it by leftConvert it back to the global coordinate system to obtain a voxelized block (flattened voxel) of the surface.
Process remaining triangles
For triangular surfaces, since there is a minimum element, we first discuss its size. If the length and width of the smallest circumscribed rectangle of the triangle are less than, then the triangle is called small; if the length and width of the largest inscribed rectangle of the triangle are greater than or equal to, the triangle is called large; otherwise it is called medium.
For small triangles, we try two fitting methods:
Fit the triangle using two bounding rectangles. For the vertex corresponding to the largest angle, place two rectangles parallel to the adjacent sides of the vertex inside the triangle so that the inner sides of the two rectangles intersect at a point on the opposite side of the vertex. By taking different intersection points, different fits can be obtained, and the method with the smallest error can be selected. The dimensions of the bounding rectangle need not beAn integer multiple of , but if the solution can be obtainedis an integer multiple of , then selectcan minimize the error in integer multiplessolution.
Calculate the center of gravity of the triangle, and then use the center of gravity as the center directly using aThe rectangle fits the triangle, one side coincides with the side of the triangle, and the error is calculated。
error heredefined as a setof measure, that is, the area of the rectangle beyond the triangle:
$$e_S = \frac{1}{4} \sum_{S \in S_{voxel}, S \notin S_{triangle}} Area(S)$$
Choose the one with the smaller error among the two methods as the fitting method for the small triangle.
For medium triangles, we only consider the method of using two surrounding rectangles. The process is similar to that of small triangles.
For large triangles, we first fit the triangle with three bounding rectangles. Place a rectangle from three vertices along the adjacent sides, with thicknesses of. This creates an inner region that we voxelize (pixel) traditionally, but requires each rectangle to be of sizeAn integer multiple of , and merge adjacent rectangles after processing. At this timeLet the internal region have a solution andThe smallest value, similarly, if the solution can be obtainedis an integer multiple of , then selectcan minimize the error in integer multiplessolution.
To find all rectangles, we multiply them by leftConvert it back to the global coordinate system to obtain the voxelized block of the remaining triangular faces of the surface.
Below we discuss the coverage methods mentioned above in detail:
Double hemming method:

The double wrapping method can fit small triangles well under normal circumstances.


In special cases, it can be found that when the vertices of the rectangle are fixed on the three corners of the triangle, it will be impossible to fit, and the rectangle needs to be extended.
Note: Although this situation can always be avoided by adjusting the position of point D, we are not sure yet whether limiting the position of D is better than allowing the rectangle to be extended, so we choose to allow the rectangle to be extended.
Therefore, the logic of the double wrapping method suitable for general situations is:
Select the maximum angle, recorded as, the adjacent angle is recorded asand, the opposite sides of the three angles are written as。
existTake a little bit, Passdoperpendicular to , respectively from the rayintersection point。
byFor example, ifexistabove, then the rectangleAn edge of, the length of the adjacent side perpendicular to it isIts value is equal toanddistance; ifexistalongOn the extension line of the direction, the rectangleAn edge of, the length of its perpendicular adjacent side is also。
To simplify calculations, we assumeCan't even get itinteger multiples of , so that they are continuous values. After calculating the best value, try to adjust it toan integer multiple of.
So,The difference from the final value is not greater than, the same reasonThe difference from the final value is not greater than。
In general calculations, the anglerectangle onFor example, it is easy to calculate the distortion area as:
In the special case where the rectangle needs to be extended, the distortion area is:
And the critical condition is, when the left side of the equal sign is positive,The projection ofOn the extension line of , when it is negative,The projection ofsuperior.
So we can use amax()function to uniformly represent the distortion area:
The sum of the areas on both sides does not overlap, so the total distortion area is:
The error is the distortion area :
And the constraints are
Using the Lagrange multiplier method, we construct the Lagrange function:
rightTaking the partial derivative and setting it to zero gives us a system of equations:
Notice,It is not differentiable at the critical point, so we need to discuss it case by case:
It is easy to prove that only one side needs to extend the rectangle, that is, there are only three situations:
In a given condition that satisfies the constraints,likeand, then it is a general situation (the critical point is regarded as a general situation);
likeand, then it is extendedsituation;
likeand, then it is extendedsituation.
Substituting the three situations into the above system of equations respectively, find candidate solutions, then calculate the error, and select the solution with the smallest error as the final solution. At this time it willAdjust tois an integer multiple of , and the solution with the smallest adjusted error is selected as the final solution (this may not always be possible).
wraparound
The logic of the wrap-around method suitable for large triangles is:
We use different LOD to determine the internal area, that is, discretize the internal area asgrid,Pick,inis the side length of the largest inscribed rectangle of a triangle andThe integer part of the ratio. For the "large triangle" in our definition,。
Under different LODs, pixelate the internal area (inscribed fitting), that is, within the divided grid, select the grid completely contained within the triangle as the pixel block.
Select three vertices of the triangle, place three rectangles along the adjacent sides., whose thicknesses are respectively. Choose the smallestCover the area that cannot be covered by inscribed fitting, and calculate the distortion area caused by wrapping。
For this step, we need to first select the direction, that is, select one side as the bottom edge. At this time, the determined pixels will generate the left, right, and top borders. For the hypotenuse on the left, we calculate the distance between each grid point of the left boundary and the upper boundary from the hypotenuse, and take the minimum value as, similarly the hypotenuse on the right takes the minimum value as, obviously the bottomis 0.
Calculate different sides as bases separately, and then calculate the distortion area, the choice makesminimal solution.
Next we discuss the distortion areacalculation method.

Consider the general wraparound method, assumingare the thickness of the rectangle on the left, right and bottom sides respectively,are the angles of the left, right and bottom sides respectively, then the distortion areaIt can be expressed as:

When considering that the vertex angle is an obtuse angle, it is obvious that there is no error area near the obtuse angle. Taking the right side as an example, the area of the red triangle can be calculated as
This is just the opposite of the distortion area term we originally calculated here for the rectangle on the right. If we apply the original formula, this term is just the negative value of the area of the red triangle, so we need to remove it.
passmaxrestrictObtain the corrected distortion area:
- Calculate the error value at each LODand number of voxels, choose such that the cost indexThe smallest solution is taken as the final solution.
In this algorithm, the optimal solution is uniquely determined by LOD becauseandare all determined by LOD, so the cost function can be expressed as LOD . Since LOD can only take discrete values, we can find the optimal solution by traversing all possible LODs.
Description of voxel blocks
Now for all the rectangles that have been determined, we need to convert them into the format required by the Minecraft json model. The voxel definition in the Minecraft json model is slightly different on different platforms, but it mainly consists of the following information (we do not consider textures):
Voxel position: Defines the position of the voxel in three-dimensional space. in Bedrock Edition voxel definition
originArrays and Java EditionfromThe array is at this location.Voxel size: Define the length, width, and height of the voxel. in Bedrock Edition voxel definition
sizeThe array is of this size. For Java Edition,toAn array is the sum of position and size.Rotation of the voxel: Defines the rotation angle of the voxel relative to its local coordinate system, which is described by the rotation Euler angles of the three axes. in Bedrock Edition voxel definition
rotationArrays and Java Editionrotation.x,rotation.y,rotation.zThe key is this rotation information.Rotation center: Defines the reference point for voxel rotation. in Bedrock Edition voxel definition
pivotArrays and Java Editionrotation.originThe object is this center of rotation.
In order to confirm these four pieces of information, we need to confirm the transformation matrix from the unit cube to the target rectangle.。
The order of voxel transformation is: first scale, then translate, and finally rotate around the rotation center by 3 Euler angles. Therefore, the transformation matrix can be expressed as:
inRepresents the translation matrix that moves the center of rotation to the origin,A matrix representing rotation around the origin. The order of rotation for each axis is,represents the translation matrix,Represents a scaling matrix.
For the rectangular vertices we get, we first calculate the minimum point, the vector formed by it and adjacent vertices
You can get the position and size of the voxel:
becauseIt is always orthogonal, and the direction and size do not change after the minimum point is translated to the origin, and can be used directly for calculation. We just need to find the rotation matrix that aligns its normal with a vectorThat’s it. Assume that the normal line is, we can calculate the rotation matrix through the following steps:
Calculate axis of rotation,inIt is based on the global coordinate systemaxis.
Calculate rotation angle。
Construct a rotation matrix using Rodrigues' rotation formula:
inis a vectorantisymmetric matrix.
Finally, we can decompose the rotation matrix byto get the Euler angles about each axis.
RememberThe Euler angle of rotation of the axis is, explicitly writeas follows:
Euler angles can be extracted from the matrix:
rememberof theOKThe column elements are, then there is:
Since gimbal deadlock may occur, we need toSelect different calculation methods for the value:
Define a smaller threshold$$\varepsilon = 10^{-6}$$
whenWhen , no universal joint deadlock occurs, and the remaining Euler angles are calculated directly:
whenWhen , a universal joint deadlock occurs and other methods need to be used to calculate Euler angles.
set up
like:
otherwise:
In fact, since the rotation center and rotation axis are arbitrary, there are multiple possible solutions to achieve the same visual effect. In our calculation, the rotation center is the smallest point of the voxel.
Therefore, the four pieces of information we need are as follows:
Bedrock Edition voxel definition:
{
"origin": [v_min.x, v_min.y, v_min.z],
"size": [|d_x|, |d_y|, 0],
"rotation": [rx_in_degrees, ry_in_degrees, rz_in_degrees],
"pivot": [v_min.x, v_min.y, v_min.z]
}Java version voxel definition:
{
"from": [v_min.x, v_min.y, v_min.z],
"to": [v_min.x + |d_x|, v_min.y + |d_y|, v_min.z],
"rotation": {
"origin": [v_min.x, v_min.y, v_min.z],
"x": rx,
"y": ry,
"z": rz
}
}Just write it directly in json format.
remaining questions
Although we proposed a feasible method to convert OBJ models to json models, there are still some remaining issues that need further research and resolution:
The algorithm for finding the optimal rectangle described in the article is relatively complex, especially when dealing with complex surfaces. A more efficient algorithm may be needed to speed up the process.
We regard triangular surfaces as independent from other triangular surfaces. Artists usually hide large chunks of errors in invisible areas (such as closed interiors), thereby reducing the number of cubes and achieving relatively small errors. We have not considered this yet.
The current method mainly takes error as the optimization goal, and in most cases cannot optimize the voxel number (cube number) to the same low level as manual production. Compared with models manually made by artists, automatically converted models usually have higher errors and block numbers.
For very complex geometries, current methods may still fail to achieve ideal visual effects, and the combination of other techniques, such as subdivision surfaces or multi-resolution representations, can be considered in the future to further improve the conversion quality.
But all in all, this tangent space-based voxelization method provides a promising solution for high-precision, lightweight OBJ to json model conversion. According to the ideas in the article, a practical conversion tool can be written to help artists apply design results to Minecraft scenes more efficiently.