Skip to content

Commit

Permalink
feat: add subdivision, fix face orientation
Browse files Browse the repository at this point in the history
  • Loading branch information
Em3rgencyLT committed Nov 9, 2021
1 parent a9713b4 commit 9695d48
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 34 deletions.
32 changes: 27 additions & 5 deletions Assets/Code/Hexasphere/Face.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,20 @@ public class Face
public Face(Point point1, Point point2, Point point3, bool trackFaceInPoints = true)
{
_id = Guid.NewGuid().ToString();
_points = new List<Point> {point1, point2, point3};
if (trackFaceInPoints)
{
_points.ForEach(point => point.AssignFace(this));
}

float centerX = (point1.Position.x + point2.Position.x + point3.Position.x) / 3;
float centerY = (point1.Position.y + point2.Position.y + point3.Position.y) / 3;
float centerZ = (point1.Position.z + point2.Position.z + point3.Position.z) / 3;
_centerPoint = new Point(new Vector3(centerX, centerY, centerZ));

_points = IsNormalPointingAwayFromPoint(_centerPoint, GetNormal(point1, point2, point3)) ?
new List<Point> {point1, point2, point3} :
new List<Point> {point1, point3, point2};

if (trackFaceInPoints)
{
_points.ForEach(point => point.AssignFace(this));
}
}

public string ID => _id;
Expand Down Expand Up @@ -63,5 +67,23 @@ private bool IsPointPartOfFace(Point point)
{
return _points.Any(facePoint => facePoint.ID == point.ID);
}

public static Vector3 GetNormal(Point point1, Point point2, Point point3)
{
Vector3 u = point2.Position - point1.Position;
Vector3 v = point3.Position - point1.Position;

float x = u.y * v.z - u.z * v.y;
float y = u.z * v.x - u.x * v.z;
float z = u.x * v.y - u.y * v.x;

return new Vector3(x, y, z);
}

public static bool IsNormalPointingAwayFromPoint(Point point, Vector3 normal)
{
Vector3 pos = point.Position;
return pos.x * normal.x >= 0 && pos.y * normal.y >= 0 && pos.z * normal.z >= 0;
}
}
}
76 changes: 50 additions & 26 deletions Assets/Code/Hexasphere/Hexasphere.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ public class Hexasphere
private static float _tao = Mathf.PI / 2;
private List<Point> _points;
private const float DefaultSize = 100f;
private const float PointComparisonAccuracy = 0.00001f;
private const float PointComparisonAccuracy = 0.000001f;

private static readonly List<Point> _corners = new List<Point>
private static readonly List<Point> Corners = new List<Point>
{
new Point(new Vector3(DefaultSize, _tao * DefaultSize, 0f)),
new Point(new Vector3(-DefaultSize, _tao * DefaultSize, 0f)),
Expand All @@ -30,28 +30,29 @@ public class Hexasphere
new Point(new Vector3(-_tao * DefaultSize, 0f, -DefaultSize))
};

private List<Face> _faces = new List<Face>
private List<Face> _faces;
private List<Face> _icosahedronFaces = new List<Face>
{
new Face(_corners[0], _corners[1], _corners[4], false),
new Face(_corners[1], _corners[9], _corners[4], false),
new Face(_corners[4], _corners[9], _corners[5], false),
new Face(_corners[5], _corners[9], _corners[3], false),
new Face(_corners[2], _corners[3], _corners[7], false),
new Face(_corners[3], _corners[2], _corners[5], false),
new Face(_corners[7], _corners[10], _corners[2], false),
new Face(_corners[0], _corners[8], _corners[10], false),
new Face(_corners[0], _corners[4], _corners[8], false),
new Face(_corners[8], _corners[2], _corners[10], false),
new Face(_corners[8], _corners[4], _corners[5], false),
new Face(_corners[8], _corners[5], _corners[2], false),
new Face(_corners[1], _corners[0], _corners[6], false),
new Face(_corners[11], _corners[1], _corners[6], false),
new Face(_corners[3], _corners[9], _corners[11], false),
new Face(_corners[6], _corners[10], _corners[7], false),
new Face(_corners[3], _corners[11], _corners[7], false),
new Face(_corners[11], _corners[6], _corners[7], false),
new Face(_corners[6], _corners[0], _corners[10], false),
new Face(_corners[9], _corners[1], _corners[11], false)
new Face(Corners[0], Corners[1], Corners[4], false),
new Face(Corners[1], Corners[9], Corners[4], false),
new Face(Corners[4], Corners[9], Corners[5], false),
new Face(Corners[5], Corners[9], Corners[3], false),
new Face(Corners[2], Corners[3], Corners[7], false),
new Face(Corners[3], Corners[2], Corners[5], false),
new Face(Corners[7], Corners[10], Corners[2], false),
new Face(Corners[0], Corners[8], Corners[10], false),
new Face(Corners[0], Corners[4], Corners[8], false),
new Face(Corners[8], Corners[2], Corners[10], false),
new Face(Corners[8], Corners[4], Corners[5], false),
new Face(Corners[8], Corners[5], Corners[2], false),
new Face(Corners[1], Corners[0], Corners[6], false),
new Face(Corners[11], Corners[1], Corners[6], false),
new Face(Corners[3], Corners[9], Corners[11], false),
new Face(Corners[6], Corners[10], Corners[7], false),
new Face(Corners[3], Corners[11], Corners[7], false),
new Face(Corners[11], Corners[6], Corners[7], false),
new Face(Corners[6], Corners[0], Corners[10], false),
new Face(Corners[9], Corners[1], Corners[11], false)
};

public Hexasphere(float radius, int divisions, float hexSize)
Expand All @@ -61,13 +62,36 @@ public Hexasphere(float radius, int divisions, float hexSize)
_hexSize = hexSize;

_points = new List<Point>();
_faces = new List<Face>();

Corners.ForEach(point => CachePoint(point));

_icosahedronFaces.ForEach(icoFace =>
{
List<Point> facePoints = icoFace.Points;
List<Point> previousPoints;
List<Point> bottomSide = new List<Point> {facePoints[0]};
List<Point> leftSide = facePoints[0].Subdivide(facePoints[1], divisions, CachePoint);
List<Point> rightSide = facePoints[0].Subdivide(facePoints[2], divisions, CachePoint);
for (int i = 1; i <= divisions; i++)
{
previousPoints = bottomSide;
bottomSide = leftSide[i].Subdivide(rightSide[i], i, CachePoint);
for (int j = 0; j < i; j++)
{
_faces.Add(new Face(previousPoints[j], bottomSide[j], bottomSide[j+1]));
if (j == 0) continue;
_faces.Add(new Face(previousPoints[j-1], previousPoints[j], bottomSide[j]));
}
}
});
}

public List<Face> Faces => _faces;
public List<Point> Points => _points;

public List<Point> Corners => _corners;
public List<Face> Faces => _faces;

public Point GetPointFromCacheIfExists(Point point)
private Point CachePoint(Point point)
{
Point existingPoint = _points.FirstOrDefault(candidatePoint =>
Mathf.Abs(candidatePoint.Position.x - point.Position.x) <= PointComparisonAccuracy &&
Expand Down
7 changes: 4 additions & 3 deletions Assets/Scripts/DrawHexasphere.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Code.Hexasphere;
Expand All @@ -14,15 +15,15 @@ void Start()
_meshFilter = GetComponent<MeshFilter>();
_meshFilter.mesh = mesh;

Hexasphere hexasphere = new Hexasphere(1f, 2, 1f);
mesh.vertices = hexasphere.Corners.Select(point => point.Position).ToArray();
Hexasphere hexasphere = new Hexasphere(1f, 4, 1f);
mesh.vertices = hexasphere.Points.Select(point => point.Position).ToArray();

List<int> triangleList = new List<int>();
hexasphere.Faces.ForEach(face =>
{
face.Points.ForEach(point =>
{
int vertexIndex = hexasphere.Corners.FindIndex(corner => corner.ID == point.ID);
int vertexIndex = hexasphere.Points.FindIndex(corner => corner.ID == point.ID);
triangleList.Add(vertexIndex);
});
});
Expand Down

0 comments on commit 9695d48

Please sign in to comment.