Files
BITFALL/Assets/Plugins/FImpossible Creations/Plugins - Level Design/Tile Designer/Tile Mesh Setup/TileMeshSetup.CubeGenerator.cs

417 lines
18 KiB
C#
Raw Normal View History

2023-11-30 00:23:23 +08:00
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace FIMSpace.Generating
{
public partial class TileMeshSetup
{
public class CubeGenerator
{
#region Params
public Vector3 Scale;
public Vector3Int Subdivisions;
public float BevelSize;
public int BevelSubdivs;
public bool FaceFront;
public bool FaceBack;
public bool FaceTop;
public bool FaceBottom;
public bool FaceLeft;
public bool FaceRight;
public Vector3 RotateResult = Vector3.zero;
public class CubePlane
{
public List<Vector3> verts;
public List<int> vertsIndexes;
public List<int> tris;
public CubePlane(List<Vector3> baseVert, List<int> baseTris, List<int> vertIds)
{
verts = baseVert;
tris = baseTris;
vertsIndexes = vertIds;
}
public void FindEdgesTopBottom(CubeGenerator g)
{
float limitX = 0.1f * (g.Scale.x);
float limitZ = 0.1f * (g.Scale.z);
for (int v = 0; v < verts.Count; v++)
{
//UnityEngine.Debug.Log("vert["+v+"] = " + verts[v] + " limit = " + limitX);
if (verts[v].x > limitX) EdgeR.Add(vertsIndexes[v]);
else if (verts[v].x < -limitX) EdgeL.Add(vertsIndexes[v]);
if (verts[v].z > limitZ) EdgeF.Add(vertsIndexes[v]);
else if (verts[v].z < -limitZ) EdgeB.Add(vertsIndexes[v]);
}
}
public void FindEdgesLeftRight(CubeGenerator g)
{
float limitZ = 0.1f * (g.Scale.z);
float limitY = 0.1f * (g.Scale.y);
for (int v = 0; v < verts.Count; v++)
{
if (verts[v].z > limitZ) EdgeR.Add(vertsIndexes[v]);
else if (verts[v].z < -limitZ) EdgeL.Add(vertsIndexes[v]);
if (verts[v].y > limitY) EdgeF.Add(vertsIndexes[v]);
else if (verts[v].y < -limitY) EdgeB.Add(vertsIndexes[v]);
}
}
public void FindEdgesFrontBack(CubeGenerator g)
{
float limitX = 0.1f * (g.Scale.x);
float limitY = 0.1f * (g.Scale.y);
for (int v = 0; v < verts.Count; v++)
{
if (verts[v].x > limitX) EdgeR.Add(vertsIndexes[v]);
else if (verts[v].x < -limitX) EdgeL.Add(vertsIndexes[v]);
if (verts[v].y > limitY) EdgeF.Add(vertsIndexes[v]);
else if (verts[v].y < -limitY) EdgeB.Add(vertsIndexes[v]);
}
}
public List<int> EdgeL = new List<int>();
public List<int> EdgeR = new List<int>();
public List<int> EdgeF = new List<int>();
public List<int> EdgeB = new List<int>();
}
CubePlane planeTop;
CubePlane planeBottom;
CubePlane planeLeft;
CubePlane planeRight;
CubePlane planeFront;
CubePlane planeBack;
internal Mesh GenerateMesh()
{
// Lists for the final cube mesh
List<Vector3> verts = new List<Vector3>();
List<Vector3> normals = new List<Vector3>();
List<Vector2> uvs = new List<Vector2>();
List<int> tris = new List<int>();
planeTop = null;
planeBottom = null;
planeLeft = null;
planeRight = null;
planeFront = null;
planeBack = null;
// Non Beveled simple Cube
// Lists for helper plane mesh
float smallest = Scale.x;
if (Scale.y < smallest) smallest = Scale.y;
if (Scale.z < smallest) smallest = Scale.z;
bool areSides = FaceRight || FaceLeft;
bool isUpDown = FaceTop || FaceBottom;
bool isFrontBack = FaceFront || FaceBack;
float bevelV = smallest * BevelSize * 0.9f;
Mesh plane = _GeneratePlane(Subdivisions.x, Subdivisions.z, new Vector2(Scale.x - bevelV * (areSides ? 1f : 0f), Scale.z - bevelV * (isFrontBack ? 1f : 0f)));
List<Vector3> baseVert = new List<Vector3>();
List<Vector2> baseUV = new List<Vector2>();
List<int> baseTris = new List<int>();
List<int> vertIds = new List<int>();
plane.GetVertices(baseVert);
plane.GetUVs(0, baseUV);
plane.GetTriangles(baseTris, 0);
int planeVerts = 0;
if (FaceTop)
{
plane.GetVertices(baseVert);
for (int t = 0; t < baseVert.Count; t++) baseVert[t] = new Vector3(baseVert[t].x, Scale.y / 2f, baseVert[t].z); // - S(baseVert[t].x ) * bevelV
for (int t = 0; t < baseVert.Count; t++) { vertIds.Add(verts.Count); verts.Add(baseVert[t]); normals.Add(Vector3.up); uvs.Add(baseUV[t]); }
for (int t = 0; t < baseTris.Count; t++) tris.Add(baseTris[t] + planeVerts);
planeVerts += baseVert.Count;
planeTop = new CubePlane(baseVert, baseTris, vertIds);
planeTop.FindEdgesTopBottom(this);
}
if (FaceBottom)
{
vertIds.Clear();
plane.GetVertices(baseVert);
for (int t = 0; t < baseVert.Count; t++) baseVert[t] = new Vector3(baseVert[t].x, -Scale.y / 2f, baseVert[t].z);
for (int t = 0; t < baseVert.Count; t++) { vertIds.Add(verts.Count); verts.Add(baseVert[t]); normals.Add(Vector3.up); uvs.Add(baseUV[t]); }
baseTris.Reverse();
for (int t = 0; t < baseTris.Count; t++) tris.Add(baseTris[t] + planeVerts);
planeVerts += baseVert.Count;
planeBottom = new CubePlane(baseVert, baseTris, vertIds);
planeBottom.FindEdgesTopBottom(this);
}
plane = _GeneratePlane(Subdivisions.y, Subdivisions.z, new Vector2(Scale.y - bevelV, Scale.z - bevelV));
plane.GetVertices(baseVert);
plane.GetUVs(0, baseUV);
plane.GetTriangles(baseTris, 0);
if (FaceRight)
{
vertIds.Clear();
plane.GetVertices(baseVert);
for (int t = 0; t < baseVert.Count; t++) baseVert[t] = (new Vector3(-Scale.x / 2f, baseVert[t].x, baseVert[t].z));
for (int t = 0; t < baseVert.Count; t++) { vertIds.Add(verts.Count); verts.Add(baseVert[t]); normals.Add(Vector3.right); uvs.Add(baseUV[t]); }
for (int t = 0; t < baseTris.Count; t++) tris.Add(baseTris[t] + planeVerts);
planeVerts += baseVert.Count;
planeRight = new CubePlane(baseVert, baseTris, vertIds);
planeRight.FindEdgesLeftRight(this);
}
if (FaceLeft)
{
vertIds.Clear();
plane.GetVertices(baseVert);
for (int t = 0; t < baseVert.Count; t++) baseVert[t] = (new Vector3(Scale.x / 2f, baseVert[t].x, baseVert[t].z));
for (int t = 0; t < baseVert.Count; t++) { vertIds.Add(verts.Count); verts.Add(baseVert[t]); normals.Add(Vector3.left); uvs.Add(baseUV[t]); }
baseTris.Reverse();
for (int t = 0; t < baseTris.Count; t++) tris.Add(baseTris[t] + planeVerts);
planeVerts += baseVert.Count;
planeLeft = new CubePlane(baseVert, baseTris, vertIds);
planeLeft.FindEdgesLeftRight(this);
}
plane = _GeneratePlane(Subdivisions.x, Subdivisions.y, new Vector2(Scale.x - bevelV * (areSides ? 1f : 0f), Scale.y - bevelV * (areSides ? 1f : 0f)));
plane.GetVertices(baseVert);
plane.GetUVs(0, baseUV);
plane.GetTriangles(baseTris, 0);
if (FaceBack)
{
vertIds.Clear();
plane.GetVertices(baseVert);
for (int t = 0; t < baseVert.Count; t++) baseVert[t] = (new Vector3(baseVert[t].x, baseVert[t].z, -Scale.z / 2f));
for (int t = 0; t < baseVert.Count; t++) { vertIds.Add(verts.Count); verts.Add(baseVert[t]); normals.Add(Vector3.forward); uvs.Add(baseUV[t]); }
for (int t = 0; t < baseTris.Count; t++) tris.Add(baseTris[t] + planeVerts);
planeVerts += baseVert.Count;
planeBack = new CubePlane(baseVert, baseTris, vertIds);
planeBack.FindEdgesFrontBack(this);
}
if (FaceFront)
{
vertIds.Clear();
plane.GetVertices(baseVert);
for (int t = 0; t < baseVert.Count; t++) baseVert[t] = (new Vector3(baseVert[t].x, baseVert[t].z, Scale.z / 2f));
for (int t = 0; t < baseVert.Count; t++) { vertIds.Add(verts.Count); verts.Add(baseVert[t]); normals.Add(Vector3.back); uvs.Add(baseUV[t]); }
baseTris.Reverse();
for (int t = 0; t < baseTris.Count; t++) tris.Add(baseTris[t] + planeVerts);
planeFront = new CubePlane(baseVert, baseTris, vertIds);
planeFront.FindEdgesFrontBack(this);
}
if (BevelSize > 0f)
{
#region Planes bevel connections
if (FaceTop)
{
if (FaceRight) ConnectAllSubdivsEdgePoly(planeTop.EdgeL, planeRight.EdgeF, tris, verts, false);
if (FaceLeft) ConnectAllSubdivsEdgePoly(planeTop.EdgeR, planeLeft.EdgeF, tris, verts, true);
if (FaceFront) ConnectAllSubdivsEdgePoly(planeTop.EdgeF, planeFront.EdgeF, tris, verts, false);
if (FaceBack) ConnectAllSubdivsEdgePoly(planeTop.EdgeB, planeBack.EdgeF, tris, verts, true);
}
if (FaceBottom)
{
if (FaceRight) ConnectAllSubdivsEdgePoly(planeBottom.EdgeL, planeRight.EdgeB, tris, verts, true);
if (FaceLeft) ConnectAllSubdivsEdgePoly(planeBottom.EdgeR, planeLeft.EdgeB, tris, verts, false);
if (FaceFront) ConnectAllSubdivsEdgePoly(planeBottom.EdgeF, planeFront.EdgeB, tris, verts, true);
if (FaceBack) ConnectAllSubdivsEdgePoly(planeBottom.EdgeB, planeBack.EdgeB, tris, verts, false);
}
if (FaceLeft && FaceBack) ConnectAllSubdivsEdgePoly(planeLeft.EdgeL, planeBack.EdgeR, tris, verts, false);
if (FaceRight && FaceFront) ConnectAllSubdivsEdgePoly(planeRight.EdgeR, planeFront.EdgeL, tris, verts, false);
if (FaceLeft && FaceFront) ConnectAllSubdivsEdgePoly(planeLeft.EdgeR, planeFront.EdgeR, tris, verts, true);
if (FaceRight && FaceBack) ConnectAllSubdivsEdgePoly(planeRight.EdgeL, planeBack.EdgeL, tris, verts, true);
// Fill 8 triangle gaps
#region Top Gaps
if (FaceBack && FaceTop && FaceRight) if (planeBack.EdgeF.Count > 0)
{
tris.Add(planeTop.EdgeL[0]);
tris.Add(planeBack.EdgeL[planeBack.EdgeL.Count - 1]);
tris.Add(planeRight.EdgeL[planeRight.EdgeL.Count - 1]);
}
if (FaceFront && FaceTop && FaceRight) if (planeRight.EdgeF.Count > 0)
{
tris.Add(planeRight.EdgeF[planeRight.EdgeF.Count - 1]);
tris.Add(planeFront.EdgeL[planeFront.EdgeL.Count - 1]);
tris.Add(planeTop.EdgeL[planeTop.EdgeL.Count - 1]);
}
if (FaceBack && FaceTop && FaceLeft) if (planeLeft.EdgeF.Count > 0)
{
tris.Add(planeLeft.EdgeL[planeLeft.EdgeL.Count - 1]);
tris.Add(planeBack.EdgeR[planeBack.EdgeR.Count - 1]);
tris.Add(planeTop.EdgeB[planeTop.EdgeB.Count - 1]);
}
if (FaceFront && FaceTop && FaceLeft) if (planeTop.EdgeF.Count > 0)
{
tris.Add(planeTop.EdgeR[planeTop.EdgeR.Count - 1]);
tris.Add(planeFront.EdgeR[planeFront.EdgeR.Count - 1]);
tris.Add(planeLeft.EdgeR[planeLeft.EdgeR.Count - 1]);
}
#endregion
#region Bottom Gaps
if (FaceBack && FaceBottom && FaceRight) if (planeRight.EdgeF.Count > 0)
{
tris.Add(planeRight.EdgeL[0]);
tris.Add(planeBack.EdgeL[0]);
tris.Add(planeBottom.EdgeL[0]);
}
if (FaceFront && FaceBottom && FaceRight) if (planeBottom.EdgeF.Count > 0)
{
tris.Add(planeBottom.EdgeL[planeBottom.EdgeL.Count - 1]);
tris.Add(planeFront.EdgeL[0]);
tris.Add(planeRight.EdgeR[0]);
}
if (FaceBack && FaceBottom && FaceLeft) if (planeBottom.EdgeB.Count > 0)
{
tris.Add(planeBottom.EdgeB[planeBottom.EdgeB.Count - 1]);
tris.Add(planeBack.EdgeR[0]);
tris.Add(planeLeft.EdgeL[0]);
}
if (FaceFront && FaceBottom && FaceLeft) if (planeLeft.EdgeR.Count > 0)
{
tris.Add(planeLeft.EdgeR[0]);
tris.Add(planeFront.EdgeR[0]);
tris.Add(planeBottom.EdgeR[planeBottom.EdgeR.Count - 1]);
}
#endregion
#endregion
}
// Generate Cube Mesh
Mesh mesh = new Mesh();
FMeshUtils.RotateVertices(RotateResult, verts);
mesh.SetVertices(verts);
mesh.SetTriangles(tris, 0);
mesh.SetNormals(normals);
mesh.SetUVs(0, uvs);
mesh.RecalculateBounds();
mesh.Optimize();
return mesh;
}
void ConnectAllSubdivsEdgePoly(List<int> edgeA, List<int> edgeB, List<int> finalTris, List<Vector3> verts, bool reverse = false)
{
if (BevelSubdivs <= 1)
{
for (int i = 0; i < edgeA.Count - 1; i++)
ConnectEdgePoly(i, edgeA, edgeB, finalTris, reverse);
}
else
{
for (int i = 0; i < edgeA.Count - 1; i++)
{
if (i >= edgeB.Count) break;
Vector3 a1 = verts[edgeA[i]];
Vector3 a2 = verts[edgeA[i + 1]];
Vector3 b1 = verts[edgeB[i]];
Vector3 b2 = verts[edgeB[i + 1]];
Vector3 preV = a1;
Vector3 targetV = a2;
float step = 1f / (float)BevelSubdivs;
for (int b = 0; b < BevelSubdivs; b++)
{
if (b == 0) // Connect with start
{
}
else if (b == BevelSubdivs - 1) // Finalize
{
ConnectEdgePoly(i, edgeA, edgeB, finalTris, reverse);
}
else // Connect extra verts
{
}
}
}
}
}
List<int> _toAddTris = new List<int>();
void ConnectEdgePoly(int startIndex, List<int> edgeA, List<int> edgeB, List<int> finalTris, bool reverse = false)
{
_toAddTris.Clear();
if (startIndex >= edgeB.Count) return;
if (startIndex + 1 >= edgeB.Count) return;
if (startIndex >= edgeA.Count) return;
if (startIndex + 1 >= edgeA.Count) return;
_toAddTris.Add(edgeA[startIndex]);
_toAddTris.Add(edgeB[startIndex]);
_toAddTris.Add(edgeA[startIndex + 1]);
_toAddTris.Add(edgeB[startIndex]);
_toAddTris.Add(edgeB[startIndex + 1]);
_toAddTris.Add(edgeA[startIndex + 1]);
if (reverse) _toAddTris.Reverse();
for (int i = 0; i < _toAddTris.Count; i++) finalTris.Add(_toAddTris[i]);
}
#endregion
}
}
}