-
Notifications
You must be signed in to change notification settings - Fork 282
Mesh Simplifier API
Mattias Edlund edited this page Aug 18, 2021
·
5 revisions
The Mesh Simplifier API is where the actual mesh simplification (or decimation) happens. The algorithm itself is deeply based on Fast Quadric Mesh Simplification, with many modifications. When you want to reduce the triangle count of a mesh, this is the API that you want to use.
You will find the API in the MeshSimplifier
class of the UnityMeshSimplifier
interface. You will have to create an instance of the class before you can use it.
Name | Summary |
---|---|
MeshSimplifier() | Creates a new mesh simplifier. |
MeshSimplifier(Mesh mesh) | Creates a new mesh simplifier and initializes a mesh directly. |
Type | Name | Summary | Default value |
---|---|---|---|
SimplificationOptions | SimplificationOptions | Gets or sets all of the simplification options as a single block. | SimplificationOptions.Default |
bool | Verbose | Gets or sets if verbose information should be printed to the console. | false |
Vector3[] | Vertices | Gets or sets the vertex positions. | null |
int | SubMeshCount | Gets the count of sub-meshes. | |
int | BlendShapeCount | Gets the count of blend shapes. | |
Vector3[] | Normals | Gets or sets the vertex normals. | null |
Vector4[] | Tangents | Gets or sets the vertex tangents. | null |
Vector2[] | UV1 | Gets or sets the vertex 2D UV set 1. | null |
Vector2[] | UV2 | Gets or sets the vertex 2D UV set 2. | null |
Vector2[] | UV3 | Gets or sets the vertex 2D UV set 3. | null |
Vector2[] | UV4 | Gets or sets the vertex 2D UV set 4. | null |
Vector2[] | UV5 | Gets or sets the vertex 2D UV set 5. | null |
Vector2[] | UV6 | Gets or sets the vertex 2D UV set 6. | null |
Vector2[] | UV7 | Gets or sets the vertex 2D UV set 7. | null |
Vector2[] | UV8 | Gets or sets the vertex 2D UV set 8. | null |
Color[] | Colors | Gets or sets the vertex colors. | null |
BoneWeight[] | BoneWeights | Gets or sets the vertex bone weights. | null |
Type | Name | Summary |
---|---|---|
int[][] | GetAllSubMeshTriangles() | Returns the triangle indices for all sub-meshes. |
int[] | GetSubMeshTriangles(int subMeshIndex) | Returns the triangle indices for a specific sub-mesh. |
void | ClearSubMeshes() | Clears out all sub-meshes. |
void | AddSubMeshTriangles(int[] triangles) | Adds a sub-mesh triangle indices for a specific sub-mesh. |
void | AddSubMeshTriangles(int[][] triangles) | Adds several sub-meshes at once with their triangle indices for each sub-mesh. |
Vector2[] | GetUVs2D(int channel) | Returns the UVs (2D) from a specific channel. |
Vector3[] | GetUVs3D(int channel) | Returns the UVs (3D) from a specific channel. |
Vector4[] | GetUVs4D(int channel) | Returns the UVs (4D) from a specific channel. |
void | GetUVs(int channel, List<Vector2> uvs) | Returns the UVs (2D) from a specific channel. |
void | GetUVs(int channel, List<Vector3> uvs) | Returns the UVs (3D) from a specific channel. |
void | GetUVs(int channel, List<Vector4> uvs) | Returns the UVs (4D) from a specific channel. |
void | SetUVs(int channel, IList<Vector2> uvs) | Sets the UVs (2D) for a specific channel. |
void | SetUVs(int channel, IList<Vector3> uvs) | Sets the UVs (3D) for a specific channel. |
void | SetUVs(int channel, IList<Vector4> uvs) | Sets the UVs (4D) for a specific channel. |
void | SetUVs(int channel, IList<Vector4> uvs, int uvComponentCount) | Sets the UVs for a specific channel with a specific count of UV components. |
void | SetUVsAuto(int channel, IList<Vector4> uvs) | Sets the UVs for a specific channel and automatically detects the used components. |
BlendShape[] | GetAllBlendShapes() | Returns all blend shapes. |
BlendShape | GetBlendShape(int blendShapeIndex) | Returns a specific blend shape. |
void | ClearBlendShapes() | Clears all blend shapes. |
void | AddBlendShape(BlendShape blendShape) | Adds a blend shape. |
void | AddBlendShapes(BlendShape[] blendShapes) | Adds several blend shapes. |
void | Initialize(Mesh mesh) | Initializes the algorithm with the original mesh. |
void | SimplifyMesh(float quality) | Simplifies the mesh to a desired quality. |
void | SimplifyMeshLossless() | Simplifies the mesh without losing too much quality. |
Mesh | ToMesh() | Returns the resulting mesh. |
Type | Name | Summary | Default value |
---|---|---|---|
bool | PreserveBorderEdges | If the border edges should be preserved. | false |
bool | PreserveUVSeamEdges | If the UV seam edges should be preserved. | false |
bool | PreserveUVFoldoverEdges | If the UV foldover edges should be preserved. | false |
bool | PreserveSurfaceCurvature | If the discrete curvature of the mesh surface be taken into account during simplification. Taking surface curvature into account can result in good quality mesh simplification, but it can slow the simplification process significantly. | false |
bool | EnableSmartLink | If a feature for smarter vertex linking should be enabled, reducing artifacts in the decimated result at the cost of a slightly more expensive initialization by treating vertices at the same position as the same vertex while separating the attributes. More info here. | true |
double | VertexLinkDistance | The maximum distance between two vertices in order to link them. Note that this value is only used if EnableSmartLink is true. | double.Epsilon |
int | MaxIterationCount | The maximum iteration count. Higher number is more expensive but can bring you closer to your target quality. Sometimes a lower maximum count might be desired in order to lower the performance cost. | 100 |
double | Agressiveness | The agressiveness of the mesh simplification. Higher number equals higher quality, but more expensive to run. | 7.0 |
bool | ManualUVComponentCount | If a manual UV component count should be used (set by UVComponentCount), instead of the automatic detection. | false |
int | UVComponentCount | The UV component count. The same UV component count will be used on all UV channels. | 2 |
Type | Name | Summary |
---|---|---|
string | ShapeName | The name of the blend shape. |
BlendShapeFrame[] | Frames | The blend shape frames. |
Type | Name | Summary |
---|---|---|
float | FrameWeight | The weight of the blend shape frame. |
Vector3[] | DeltaVertices | The delta vertices of the blend shape frame. |
Vector3[] | DeltaNormals | The delta normals of the blend shape frame. |
Vector3[] | DeltaTangents | The delta tangents of the blend shape frame. |
This example will not work with skinned and animated meshes.
using UnityEngine;
public class SimplifyChildren: MonoBehaviour
{
[SerializeField, Range(0f, 1f), Tooltip("The desired quality of the simplified mesh.")]
private float quality = 0.5f;
private void Start()
{
Simplify();
}
private void Simplify()
{
var meshFilters = GetComponentsInChildren<MeshFilter>();
foreach (MeshFilter meshFilter in meshFilters)
{
SimplifyMeshFilter(meshFilter);
}
}
private void SimplifyMeshFilter(MeshFilter meshFilter)
{
Mesh sourceMesh = meshFilter.sharedMesh;
if (sourceMesh == null) // verify that the mesh filter actually has a mesh
return;
// Create our mesh simplifier and setup our entire mesh in it
var meshSimplifier = new UnityMeshSimplifier.MeshSimplifier();
meshSimplifier.Initialize(sourceMesh);
// This is where the magic happens, lets simplify!
meshSimplifier.SimplifyMesh(quality);
// Create our final mesh and apply it back to our mesh filter
meshFilter.sharedMesh = meshSimplifier.ToMesh();
}
}
Please note that this example is only to show the possibility of manually providing vertices etc, in most cases in Unity you will want to use the Initialize
and ToMesh
methods that will take care of most cases automatically, directly through a Mesh.
using UnityEngine;
[RequireComponent(typeof(MeshFilter))]
public class SimplifySimple: MonoBehaviour
{
[SerializeField, Range(0f, 1f), Tooltip("The desired quality of the simplified mesh.")]
private float quality = 0.5f;
private void Start()
{
Simplify();
}
private void Simplify()
{
var meshFilter = GetComponent<MeshFilter>();
if (meshFilter == null) // verify that there is a mesh filter
return;
Mesh sourceMesh = meshFilter.sharedMesh;
if (sourceMesh == null) // verify that the mesh filter actually has a mesh
return;
// Create our mesh simplifier and setup our vertices and indices from all sub meshes in it
var meshSimplifier = new UnityMeshSimplifier.MeshSimplifier();
meshSimplifier.Vertices = sourceMesh.vertices;
for (int i = 0; i < sourceMesh.subMeshCount; i++)
{
meshSimplifier.AddSubMeshTriangles(sourceMesh.GetTriangles(i));
}
// This is where the magic happens, lets simplify!
meshSimplifier.SimplifyMesh(quality);
// Create our new mesh and transfer vertices and indices from all sub meshes
var newMesh = new Mesh();
newMesh.subMeshCount = meshSimplifier.SubMeshCount;
newMesh.vertices = meshSimplifier.Vertices;
for (int i = 0; i < meshSimplifier.SubMeshCount; i++)
{
newMesh.SetTriangles(meshSimplifier.GetSubMeshTriangles(i), 0);
}
meshFilter.sharedMesh = newMesh;
}
}