commit428243f4a6Author: AsanoRema <asanorema2036@gmail.com> Date: Sat Aug 29 13:43:13 2026 +0300 Squashed commit of the following: commit68e78fa464Author: AsanoRema <asanorema2036@gmail.com> Date: Sat Aug 29 13:41:49 2026 +0300 Updated .gitignore commit9f87122a34Author: AsanoRema <asanorema2036@gmail.com> Date: Sat Aug 29 13:34:57 2026 +0300 Added Dohya commitf6a7547e84Author: AsanoRema <asanorema2036@gmail.com> Date: Fri Aug 21 17:59:13 2026 +0300 Fixed commitb98901c366Author: AsanoRema <asanorema2036@gmail.com> Date: Tue Aug 18 17:37:22 2026 +0300 Added new particle Package commitbb2f4a3b16Author: AsanoRema <asanorema2036@gmail.com> Date: Tue Aug 18 17:17:48 2026 +0300 Map mehanic ready to multiplayer commitc01ff800f6Author: AsanoRema <asanorema2036@gmail.com> Date: Tue Aug 18 16:16:19 2026 +0300 Squashed commit of the following: commit173bbb165cAuthor: henjkey <henjkey@gmail.com> Date: Fri Aug 14 18:51:23 2026 +0500 Mappp commitd559ab338aAuthor: henjkey <henjkey@gmail.com> Date: Thu Aug 13 18:42:41 2026 +0500 Map Controller Coordinates Target System Crosshair System Radar System
259 lines
9.3 KiB
C#
259 lines
9.3 KiB
C#
using UnityEngine;
|
|
|
|
namespace VLB
|
|
{
|
|
public static class MeshGenerator
|
|
{
|
|
const float kMinTruncatedRadius = 0.001f;
|
|
|
|
static float GetAngleOffset(int numSides)
|
|
{
|
|
// rotate square beams so they are properly oriented to scale them more easily
|
|
return numSides == 4 ? (Mathf.PI * 0.25f) : 0f;
|
|
}
|
|
|
|
public static Mesh GenerateConeZ_RadiusAndAngle(float lengthZ, float radiusStart, float coneAngle, int numSides, int numSegments, bool cap, bool doubleSided)
|
|
{
|
|
Debug.Assert(lengthZ > 0f);
|
|
Debug.Assert(coneAngle > 0f && coneAngle < 180f);
|
|
var radiusEnd = lengthZ * Mathf.Tan(coneAngle * Mathf.Deg2Rad * 0.5f);
|
|
|
|
return GenerateConeZ_Radius(lengthZ, radiusStart, radiusEnd, numSides, numSegments, cap, doubleSided);
|
|
}
|
|
|
|
public static Mesh GenerateConeZ_Angle(float lengthZ, float coneAngle, int numSides, int numSegments, bool cap, bool doubleSided)
|
|
{
|
|
return GenerateConeZ_RadiusAndAngle(lengthZ, 0f, coneAngle, numSides, numSegments, cap, doubleSided);
|
|
}
|
|
|
|
public static Mesh GenerateConeZ_Radius(float lengthZ, float radiusStart, float radiusEnd, int numSides, int numSegments, bool cap, bool doubleSided)
|
|
{
|
|
Debug.Assert(lengthZ > 0f);
|
|
Debug.Assert(radiusStart >= 0f);
|
|
Debug.Assert(numSides >= 3);
|
|
Debug.Assert(numSegments >= 0);
|
|
|
|
var mesh = new Mesh();
|
|
bool genCap = cap && radiusStart > 0f;
|
|
|
|
// We use the XY position of the vertices to compute the cone normal in the shader.
|
|
// With a perfectly sharp cone, we couldn't compute accurate normals at its top.
|
|
radiusStart = Mathf.Max(radiusStart, kMinTruncatedRadius);
|
|
|
|
int vertCountSides = numSides * (numSegments + 2);
|
|
int vertCountTotal = vertCountSides;
|
|
|
|
if (genCap)
|
|
vertCountTotal += numSides + 1;
|
|
|
|
// VERTICES
|
|
{
|
|
float angleOffset = GetAngleOffset(numSides);
|
|
|
|
var vertices = new Vector3[vertCountTotal];
|
|
|
|
for (int i = 0; i < numSides; i++)
|
|
{
|
|
float angle = angleOffset + 2 * Mathf.PI * i / numSides;
|
|
float angleCos = Mathf.Cos(angle);
|
|
float angleSin = Mathf.Sin(angle);
|
|
|
|
for (int seg = 0; seg < numSegments + 2; seg++)
|
|
{
|
|
float tseg = (float)seg / (numSegments + 1);
|
|
Debug.Assert(tseg >= 0f && tseg <= 1f);
|
|
float radius = Mathf.Lerp(radiusStart, radiusEnd, tseg);
|
|
vertices[i + seg * numSides] = new Vector3(radius * angleCos, radius * angleSin, tseg * lengthZ);
|
|
}
|
|
}
|
|
|
|
if (genCap)
|
|
{
|
|
int ind = vertCountSides;
|
|
|
|
vertices[ind] = Vector3.zero;
|
|
ind++;
|
|
|
|
for (int i = 0; i < numSides; i++)
|
|
{
|
|
float angle = angleOffset + 2 * Mathf.PI * i / numSides;
|
|
float angleCos = Mathf.Cos(angle);
|
|
float angleSin = Mathf.Sin(angle);
|
|
vertices[ind] = new Vector3(radiusStart * angleCos, radiusStart * angleSin, 0f);
|
|
ind++;
|
|
}
|
|
|
|
Debug.Assert(ind == vertices.Length);
|
|
}
|
|
|
|
if (!doubleSided)
|
|
{
|
|
mesh.vertices = vertices;
|
|
}
|
|
else
|
|
{
|
|
var vertices2 = new Vector3[vertices.Length * 2];
|
|
vertices.CopyTo(vertices2, 0);
|
|
vertices.CopyTo(vertices2, vertices.Length);
|
|
mesh.vertices = vertices2;
|
|
}
|
|
}
|
|
|
|
// UV (used to flags vertices as sides or cap)
|
|
// X: 0 = sides ; 1 = cap
|
|
// Y: 0 = front face ; 1 = back face (doubleSided only)
|
|
{
|
|
var uv = new Vector2[vertCountTotal];
|
|
int ind = 0;
|
|
for (int i = 0; i < vertCountSides; i++)
|
|
uv[ind++] = Vector2.zero;
|
|
|
|
if (genCap)
|
|
{
|
|
for (int i = 0; i < numSides + 1; i++)
|
|
uv[ind++] = new Vector2(1, 0);
|
|
}
|
|
|
|
Debug.Assert(ind == uv.Length);
|
|
|
|
|
|
if (!doubleSided)
|
|
{
|
|
mesh.uv = uv;
|
|
}
|
|
else
|
|
{
|
|
var uv2 = new Vector2[uv.Length * 2];
|
|
uv.CopyTo(uv2, 0);
|
|
uv.CopyTo(uv2, uv.Length);
|
|
|
|
for (int i = 0; i < uv.Length; i++)
|
|
{
|
|
var value = uv2[i + uv.Length];
|
|
uv2[i + uv.Length] = new Vector2(value.x, 1);
|
|
}
|
|
|
|
mesh.uv = uv2;
|
|
}
|
|
}
|
|
|
|
// INDICES
|
|
{
|
|
int triCountSides = numSides * 2 * Mathf.Max(numSegments + 1, 1);
|
|
int indCountSides = triCountSides * 3;
|
|
int indCountTotal = indCountSides;
|
|
|
|
if (genCap)
|
|
indCountTotal += numSides * 3;
|
|
|
|
var indices = new int[indCountTotal];
|
|
int ind = 0;
|
|
|
|
for (int i = 0; i < numSides; i++)
|
|
{
|
|
int ip1 = i + 1;
|
|
if (ip1 == numSides)
|
|
ip1 = 0;
|
|
|
|
for (int k = 0; k < numSegments + 1; ++k)
|
|
{
|
|
var offset = k * numSides;
|
|
|
|
indices[ind++] = offset + i;
|
|
indices[ind++] = offset + ip1;
|
|
indices[ind++] = offset + i + numSides;
|
|
|
|
indices[ind++] = offset + ip1 + numSides;
|
|
indices[ind++] = offset + i + numSides;
|
|
indices[ind++] = offset + ip1;
|
|
}
|
|
}
|
|
|
|
if (genCap)
|
|
{
|
|
for (int i = 0; i < numSides - 1; i++)
|
|
{
|
|
indices[ind++] = vertCountSides;
|
|
indices[ind++] = vertCountSides + i + 2;
|
|
indices[ind++] = vertCountSides + i + 1;
|
|
}
|
|
|
|
indices[ind++] = vertCountSides;
|
|
indices[ind++] = vertCountSides + 1;
|
|
indices[ind++] = vertCountSides + numSides;
|
|
}
|
|
|
|
Debug.Assert(ind == indices.Length);
|
|
|
|
if (!doubleSided)
|
|
{
|
|
mesh.triangles = indices;
|
|
}
|
|
else
|
|
{
|
|
var indices2 = new int[indices.Length * 2];
|
|
indices.CopyTo(indices2, 0);
|
|
|
|
for (int i = 0; i < indices.Length; i += 3)
|
|
{
|
|
indices2[indices.Length + i + 0] = indices[i + 0] + vertCountTotal;
|
|
indices2[indices.Length + i + 1] = indices[i + 2] + vertCountTotal;
|
|
indices2[indices.Length + i + 2] = indices[i + 1] + vertCountTotal;
|
|
}
|
|
|
|
mesh.triangles = indices2;
|
|
}
|
|
}
|
|
|
|
mesh.bounds = ComputeBounds(lengthZ, radiusStart, radiusEnd);
|
|
|
|
Debug.Assert(mesh.vertexCount == GetVertexCount(numSides, numSegments, genCap, doubleSided));
|
|
Debug.Assert(mesh.triangles.Length == GetIndicesCount(numSides, numSegments, genCap, doubleSided));
|
|
|
|
return mesh;
|
|
}
|
|
|
|
public static Bounds ComputeBounds(float lengthZ, float radiusStart, float radiusEnd)
|
|
{
|
|
float maxDiameter = Mathf.Max(radiusStart, radiusEnd) * 2;
|
|
return new Bounds(
|
|
new Vector3(0, 0, lengthZ * 0.5f),
|
|
new Vector3(maxDiameter, maxDiameter, lengthZ)
|
|
);
|
|
}
|
|
|
|
|
|
public static int GetVertexCount(int numSides, int numSegments, bool geomCap, bool doubleSided)
|
|
{
|
|
Debug.Assert(numSides >= 2);
|
|
Debug.Assert(numSegments >= 0);
|
|
|
|
int count = numSides * (numSegments + 2);
|
|
if (geomCap) count += numSides + 1;
|
|
if (doubleSided) count *= 2;
|
|
return count;
|
|
}
|
|
|
|
public static int GetIndicesCount(int numSides, int numSegments, bool geomCap, bool doubleSided)
|
|
{
|
|
Debug.Assert(numSides >= 2);
|
|
Debug.Assert(numSegments >= 0);
|
|
|
|
int count = numSides * (numSegments + 1) * 2 * 3;
|
|
if (geomCap) count += numSides * 3;
|
|
if (doubleSided) count *= 2;
|
|
return count;
|
|
}
|
|
|
|
public static int GetSharedMeshVertexCount()
|
|
{
|
|
return GetVertexCount(Config.Instance.sharedMeshSides, Config.Instance.sharedMeshSegments, true, Config.Instance.requiresDoubleSidedMesh);
|
|
}
|
|
|
|
public static int GetSharedMeshIndicesCount()
|
|
{
|
|
return GetIndicesCount(Config.Instance.sharedMeshSides, Config.Instance.sharedMeshSegments, true, Config.Instance.requiresDoubleSidedMesh);
|
|
}
|
|
}
|
|
}
|