Skip to content

Instantly share code, notes, and snippets.

@Hotrian
Last active April 20, 2024 07:11
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Hotrian/8dfbe55afea456ebb7bd4489385e133c to your computer and use it in GitHub Desktop.
Save Hotrian/8dfbe55afea456ebb7bd4489385e133c to your computer and use it in GitHub Desktop.
Example code for simple Quad and Cube meshes built through code.
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshFilter)), RequireComponent(typeof(MeshRenderer))]
public class ProtoMesh : MonoBehaviour
{
#region Helper Properties
// Simple helpers to cache the MeshFilter and MeshRenderer
public MeshRenderer MyMeshRenderer
{
get { return _myMeshRenderer ?? (_myMeshRenderer = gameObject.GetComponent<MeshRenderer>()); }
}
public MeshFilter MyMeshFilter
{
get { return _myMeshFilter ?? (_myMeshFilter = gameObject.GetComponent<MeshFilter>()); }
}
private MeshRenderer _myMeshRenderer;
private MeshFilter _myMeshFilter;
#endregion
#region Unity Methods
// Use this for initialization
void Start()
{
GenerateMesh();
}
#endregion
public void GenerateMesh()
{
if (MyMeshFilter == null || MyMeshRenderer == null)
{
Debug.LogError("MeshFilter/MeshRenderer Reference Lost!");
return;
}
// Create lists to store our mesh data in
var vertices = new List<Vector3>();
var triangles = new List<int>();
var normals = new List<Vector3>();
var uvs = new List<Vector2>();
// Derived classes will fill the mesh data here
_generateMesh(vertices, triangles, normals, uvs);
// Generate a Mesh
var mesh = new Mesh
{
vertices = vertices.ToArray(),
triangles = triangles.ToArray(),
normals = normals.ToArray(),
uv = uvs.ToArray()
};
// Assign the Mesh
MyMeshFilter.mesh = mesh;
}
// Override in derived classes
protected virtual void _generateMesh(List<Vector3> vertices, List<int> triangles, List<Vector3> normals, List<Vector2> uvs)
{
Debug.LogWarning("_generateMesh() isn't being overridden or base() is being called!");
}
// Master class for simple geometry
public static class BaseMeshData
{
const float TileSize = 1.001f; // 1f shows seams
#region Cube Data
/*
* 0 - Right - x+
* 1 - Left - x-
* 2 - Top - y+
* 3 - Bottom - y-
* 4 - Back - z+
* 5 - Front - z-
*/
public static readonly Vector3[][] CubeVerts =
{
new[]{ new Vector3( TileSize, 0f, 0f), new Vector3(TileSize, 0f, TileSize), new Vector3(TileSize, TileSize, 0f), new Vector3(TileSize, TileSize, TileSize)},
new[]{ new Vector3( 0f, 0f, TileSize), new Vector3(0f, 0f, 0f), new Vector3(0f, TileSize, TileSize), new Vector3(0f, TileSize, 0f)},
new[]{ new Vector3( 0f, TileSize, 0f), new Vector3(TileSize, TileSize, 0f), new Vector3(0f, TileSize, TileSize), new Vector3(TileSize, TileSize, TileSize)},
new[]{ new Vector3( TileSize, 0f, 0f), new Vector3(0f, 0f, 0f), new Vector3(TileSize, 0f, TileSize), new Vector3(0f, 0f, TileSize)},
new[]{ new Vector3( TileSize, 0f, TileSize), new Vector3(0f, 0f, TileSize), new Vector3(TileSize, TileSize, TileSize), new Vector3(0f, TileSize, TileSize)},
new[]{ new Vector3( 0f, 0f, 0f), new Vector3(TileSize, 0f, 0f), new Vector3(0f, TileSize, 0f), new Vector3(TileSize, TileSize, 0f)}
};
public static readonly int[][] CubeTris =
{
new[]{ 1, 0, 2, 2, 3, 1},
new[]{ 1, 0, 2, 2, 3, 1},
new[]{ 1, 0, 2, 2, 3, 1},
new[]{ 1, 0, 2, 2, 3, 1},
new[]{ 1, 0, 2, 2, 3, 1},
new[]{ 1, 0, 2, 2, 3, 1}
};
public static readonly Vector3[] CubeNorms =
{
new Vector3( 1f, 0f, 0f),
new Vector3(-1f, 0f, 0f),
new Vector3( 0f, 1f, 0f),
new Vector3( 0f,-1f, 0f),
new Vector3( 0f, 0f, 1f),
new Vector3( 0f, 0f,-1f)
};
public static readonly Vector2[][] CubeUVs =
{
new[] { new Vector2( 0f, 0f), new Vector2( 1f, 0f), new Vector2( 0f, 1f), new Vector2( 1f, 1f)},
new[] { new Vector2( 0f, 0f), new Vector2( 1f, 0f), new Vector2( 0f, 1f), new Vector2( 1f, 1f)},
new[] { new Vector2( 0f, 0f), new Vector2( 1f, 0f), new Vector2( 0f, 1f), new Vector2( 1f, 1f)},
new[] { new Vector2( 0f, 0f), new Vector2( 1f, 0f), new Vector2( 0f, 1f), new Vector2( 1f, 1f)},
new[] { new Vector2( 0f, 0f), new Vector2( 1f, 0f), new Vector2( 0f, 1f), new Vector2( 1f, 1f)},
new[] { new Vector2( 0f, 0f), new Vector2( 1f, 0f), new Vector2( 0f, 1f), new Vector2( 1f, 1f)},
};
#endregion
#region Quad Data
public static readonly Vector3[] QuadVerts = CubeVerts[5];
public static readonly int[] QuadTris = CubeTris[5];
public static readonly Vector3 QuadNorm = CubeNorms[5];
public static readonly Vector2[] QuadUVs = CubeUVs[5];
#endregion
}
}
using System.Collections.Generic;
using UnityEngine;
public class SimpleMeshCube : ProtoMesh
{
protected override void _generateMesh(List<Vector3> vertices, List<int> triangles, List<Vector3> normals, List<Vector2> uvs)
{
// Do not call base._generateMesh(); due to the Debug.LogWarning in the base method
// Generating a cube is a bit trickier, but it's basically generating a quad 6 times in different directions
// The thing to remember here, is that as we add more vertices we have to keep count so we know which
// vertices must be stitched together.
var count = 0;
// Loop through the faces of this Cube
for (var j = 0; j < BaseMeshData.CubeVerts.Length; j++)
{
// Add the base data to the mesh, in this case we are adding quads to form a cube
vertices.AddRange(BaseMeshData.CubeVerts[j]);
uvs.AddRange(BaseMeshData.CubeUVs[j]);
// We must now manually add the indices because we are
// building multiple template quads together into a single mesh.
for (var i = 0; i < BaseMeshData.CubeTris[j].Length; i++)
{
triangles.Add(count + BaseMeshData.CubeTris[j][i]);
}
// Because each of the vertices in a quad are facing the same direction, we just copy the one Normal direction for each vertex
// This cube is just 6 quads, so the operation is the same.
for (var i = 0; i < BaseMeshData.CubeVerts[j].Length; i++)
{
normals.Add(BaseMeshData.CubeNorms[j]);
}
// We must count the number of vertices added in each step in order to
// stitch the next quad properly.
count += BaseMeshData.CubeVerts[j].Length;
}
}
}
using System.Collections.Generic;
using UnityEngine;
public class SimpleMeshQuad : ProtoMesh
{
protected override void _generateMesh(List<Vector3> vertices, List<int> triangles, List<Vector3> normals, List<Vector2> uvs)
{
// Do not call base._generateMesh(); due to the Debug.LogWarning in the base method
// Add the base data to the mesh
vertices.AddRange(BaseMeshData.QuadVerts);
triangles.AddRange(BaseMeshData.QuadTris);
uvs.AddRange(BaseMeshData.QuadUVs);
// Because each of the vertices in a quad are facing the same direction, we just copy the one Normal direction for each vertex
for (var i = 0; i < BaseMeshData.QuadVerts.Length; i++)
{
normals.Add(BaseMeshData.QuadNorm);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment