Skip to content

Instantly share code, notes, and snippets.

@cmdr2
Created February 4, 2021 12:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cmdr2/b5aea11b9bd5259b9198f4fdc027061c to your computer and use it in GitHub Desktop.
Save cmdr2/b5aea11b9bd5259b9198f4fdc027061c to your computer and use it in GitHub Desktop.
Simple example usage script for MarchingCubes.cs at https://gist.github.com/cmdr2/b5326aa6fbf3c367747cc5ec31ba831e
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// Simple example usage script for MarchingCubes.cs:
// at: https://gist.github.com/cmdr2/b5326aa6fbf3c367747cc5ec31ba831e
//
// Attach to an empty GameObject in the scene
//
// Not optimized, performs poorly! Written for simple readability
// and clarity, in order to get the most basic 'Marching Cubes'
// implementation working in Unity.
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class MarchingCubesExample : MonoBehaviour {
MeshFilter mf;
void Start() {
mf = GetComponent<MeshFilter>();
mf.sharedMesh = new Mesh();
var grid = GetGrid(Vector3.zero, new Vector3(5, 5, 5), 0.1f);
var tris = MarchingCubes.Polygonize(grid, 0);
RenderTris(tris);
}
void RenderTris(List<MarchingCubes.Triangle> mcTris) {
var verts = new List<Vector3>();
var tris = new List<int>();
var normals = new List<Vector3>();
var uvs = new List<Vector2>();
foreach (var tri in mcTris) {
var n = tris.Count;
verts.AddRange(tri.verts);
tris.Add(n); tris.Add(n+2); tris.Add(n+1);
var normal = Vector3.Cross(tri.verts[2] - tri.verts[0], tri.verts[1] - tri.verts[0]).normalized;
normals.Add(normal); normals.Add(normal); normals.Add(normal);
}
mf.sharedMesh.SetVertices(verts);
mf.sharedMesh.SetTriangles(tris.ToArray(), 0);
mf.sharedMesh.SetNormals(normals);
}
MarchingCubes.GridCell[,,] GetGrid(Vector3 center, Vector3 gridSize, float cellSize) {
var nGrid = gridSize / cellSize;
var nX = Mathf.FloorToInt(nGrid.x);
var nY = Mathf.FloorToInt(nGrid.y);
var nZ = Mathf.FloorToInt(nGrid.z);
var hX = nX * 0.5f;
var hY = nY * 0.5f;
var hZ = nZ * 0.5f;
var grid = new MarchingCubes.GridCell[nX, nY, nZ];
for (int i = 0; i < nX; i++) {
var x = (-hX + i) * cellSize + center.x;
for (int j = 0; j < nY; j++) {
var y = (-hY + j) * cellSize + center.y;
for (int k = 0; k < nZ; k++) {
var z = (-hZ + k) * cellSize + center.z;
var cell = new MarchingCubes.GridCell();
cell.verts[0] = new Vector3(x, y, z + cellSize);
cell.verts[1] = new Vector3(x + cellSize, y, z + cellSize);
cell.verts[2] = new Vector3(x + cellSize, y, z);
cell.verts[3] = new Vector3(x, y, z);
cell.verts[4] = new Vector3(x, y + cellSize, z + cellSize);
cell.verts[5] = new Vector3(x + cellSize, y + cellSize, z + cellSize);
cell.verts[6] = new Vector3(x + cellSize, y + cellSize, z);
cell.verts[7] = new Vector3(x, y + cellSize, z);
PopulateIsovalues(cell);
grid[i, j, k] = cell;
}
}
}
return grid;
}
void PopulateIsovalues(MarchingCubes.GridCell cell) {
for (int i = 0; i < cell.verts.Length; i++) {
cell.isovalue[i] = map(cell.verts[i]);
//print(i + ", " + cell.isovalue[i]);
}
}
float map(Vector3 pos) {
return sdf_smin(
sdf_sphere(pos, new Vector3(-0.7f, 0, 0), 1f),
sdf_sphere(pos, new Vector3(0.7f, 0, 0), 1f),
5
);
}
float sdf_sphere(Vector3 pos, Vector3 center, float radius) {
return Vector3.Distance(pos, center) - radius;
}
float sdf_smin(float a, float b, float k = 32) {
float res = Mathf.Exp(-k*a) + Mathf.Exp(-k*b);
return -Mathf.Log(Mathf.Max(0.0001f, res)) / k;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment