Tutorial 2: Simplifying a 3D Mesh

< previous page next page >

Within this tutorial, we are going to use RapidCompact CLI to simplify a 3D mesh. This process is sometimes also referred to Mesh Reduction or as Mesh Decimation. The latter term, decimation, is used within the RapidCompact CLI options and settings.

Decimation Parameters

RapidCompact CLI has several settings that can be used to control the decimation process:

The first setting, decimation:method, can be used to specify which method should be used for decimation. There are two methods available: "quadric" (the default) and "edgeLength". The next setting, decimation:boundaryPreservationFactor, specifies how strongly boundaries should be preserved during the decimation process. The last two settings, decimation:collapseUnconnectedVertices and decimation:collapseDistanceThreshold can be used to control (and enable / disable) the collapsing of unconnected, closeby vertices, if desired. We will explore all of these settings by example within the paragraphs. It is worth noting at this point that there is also another setting related to decimation, which is decimation:defaultTarget. This setting, however, is only used when decimation is indirectly invoked using the compact master operation. Within this tutorial, we will not use this master operation (which also does some other things apart from decimating the mesh), but we will instead limit ourselves to the mesh decimation part.

Getting Started

To get started with the decimation functionality of RapidCompact CLI, we will use a simple example mesh of a scanned nefertiti bust, which you can download here.

This mesh has 440K faces, which makes it a medium-sized data set. Although it could already be used like this for many visualization applications, some might require a variant that consists of less triangles, for example for quick rendering in a VR or game context. Another reason for generating a simplified version might be the reduction of bandwidth which is needed to transmit this mesh over a network (for example, for online presentation). Within the following tutorial, we will see how to generate different texture maps, applied on the low-resolution asset, can help us to faithfully preserve the details of the high-resolution original. However, within this tutorial, we will just simplify the 3D geometry of the mesh.

To generate a simplified version of the nefertiti mesh, you can use the following command line:

    rpdx -i nefertiti.ply -d 2000 -e nefertiti-lowpoly.ply
    

This command will generate an OBJ file entitled nefertiti-lowpoly.ply, containing the simplified version of the input mesh. The decimate command, here abbreviated using the shorthand version d, accepts several parameters. By default, a number is interpreted as a target amount of vertices. However, you can also specify a target amount of faces, or a target percentage of vertices or faces. Examples:

The method used by default is the quadric method. There is also another one, which is entitled edgeLength. The edgeLength method is more simple and hence slightly faster, and it produces a resulting mesh where the triangles have a very regular distribution, which can be beneficial for some applications. However, the quadric method will be preferred in most cases, as it preserves features relatively well. The following figure shows a comparison of the results, using a strong simplification to 1% of the original vertices:

If you like, try out different values for decimation:boundaryPreservationFactor, in order to see which influence this parameter has on the final result. For this mesh of the nefertiti bust, it will influence the seam at the bottom, where the mesh is open because it has not been scanned from the bottom. The shape of this seam is pretty random anyway, therefore you may prefer not to explicitly preserve it in this case - above example images were generated with decimation:boundaryPreservationFactor set to zero. Within the next section, we will see where this parameter can come in more handy.

Preserving Boundaries

A common artifact arising during simplification is deformation of open mesh boundaries. To experience this by example, we will use this model of a teapot.

To see what happens when a mesh is simplified without special constraints for the boundaries, set decimation:boundaryPreservationFactor to zero and run this command:

    rpdx -i teapot.obj -d v:500 -e reduced.obj
    

This will produce a reduced teapot that looks like this:

Not very satisfying, you would probably say. What looks especially ugly and "wrong" are the displaced boundary vertices, leading to the handle and spout floating somewhere in the air, instead of being connected to the body of the teapot. The reason for this is that the teapot's spout and handle were actually separate pieces that are not connected to the body's vertices within the original model. In such cases, it helps to apply some special constraints for the mesh boundaries. Setting decimation:boundaryPreservationFactor to 0.5 gives a much nicer result:

Merging Close Vertices

For certain meshes, especially those generated through CAD, the surface may be composed out of several parts, or patches. Such patches are often not explicitly connected at their boundaries, but instead vertex positions of two neighboring patch boundaries will simply match. Without boundary preservation, we might run into problems here, as those boundaries may "crack up" (compare the example of the teapot shown above). In such cases, we can also handle the problem differently: instead of preserving boundaries (using decimation:boundaryPreservationFactor), we can also weld them together. This effectively means that we are allowing the simplification method to merge nearby vertices, regardless of whether they belong to the same surface patch or not. This can be done using the setting decimation:collapseDistanceThreshold, which is a value relative to the model's bounding box diagonal. For this simple example mesh of two bent sheets, setting decimation:collapseDistanceThreshold to zero and performing decimation to 500 vertices will produce a result like this at the boundaries between both patches:

In constrast, by setting decimation:collapseDistanceThreshold to 0.1, we obtain a result where the boundary vertices of both sheets have been "welded" together: