Skip to content

Commit

Permalink
Porting
Browse files Browse the repository at this point in the history
  • Loading branch information
Xlinka committed Nov 29, 2023
1 parent bb922b4 commit ee8744a
Show file tree
Hide file tree
Showing 7 changed files with 444 additions and 0 deletions.
46 changes: 46 additions & 0 deletions Components/Mesh/MengerSponge.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using Elements.Assets;
using Elements.Core;
using FrooxEngine;
using System;

namespace Obsidian
{
[Category(new string[] { "Obsidian/Assets/Procedural Meshes" })]
public class MengerSpongeMesh : ProceduralMesh
{
[Range(1, 4)] public readonly Sync<int> Subdivisions;
private MengerSponge sponge;
private int _subdivisions;

protected override void OnAwake()
{
base.OnAwake();
Subdivisions.Value = 1;
}

protected override void PrepareAssetUpdateData()
{
_subdivisions = Subdivisions.Value;
}

protected override void ClearMeshData()
{
sponge = null;
}

protected override void UpdateMeshData(MeshX meshx)
{
bool value = false;
if (sponge == null || sponge.Subdivisions != _subdivisions)
{
sponge?.Remove();
sponge = new MengerSponge(meshx, _subdivisions);
value = true;
}

sponge.Subdivisions = Subdivisions.Value;
sponge.Update();
uploadHint[MeshUploadHint.Flag.Geometry] = value;
}
}
}
103 changes: 103 additions & 0 deletions Components/Mesh/MengerSpongeMesh.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
using Elements.Assets;
using Elements.Core;
using System;
using System.Collections.Generic;

namespace Obsidian
{
public class MengerSponge : MeshXShape
{
public int Subdivisions;

public MengerSponge(MeshX mesh, int subdivisions) : base(mesh)
{
Subdivisions = subdivisions;
mesh.Clear();
GenerateSponge(mesh, Subdivisions, float3.Zero, 1);
}

private void GenerateSponge(MeshX mesh, int level, float3 center, float size)
{
if (level == 0)
{
GenerateCube(mesh, center, size);
}
else
{
float newSize = size / 3;
int newLevel = level - 1;

for (int x = -1; x <= 1; x++)
{
for (int y = -1; y <= 1; y++)
{
for (int z = -1; z <= 1; z++)
{
if (x == 0 && y == 0 || x == 0 && z == 0 || y == 0 && z == 0)
continue;


float3 newCenter = center + new float3(x * newSize, y * newSize, z * newSize);
GenerateSponge(mesh, newLevel, newCenter, newSize);
}
}
}
}
}

private void GenerateCube(MeshX mesh, float3 center, float size)
{
float halfSize = size / 2;
var cubeVertices = new float3[]
{
center + new float3(-halfSize, -halfSize, -halfSize),
center + new float3(halfSize, -halfSize, -halfSize),
center + new float3(halfSize, -halfSize, halfSize),
center + new float3(-halfSize, -halfSize, halfSize),
center + new float3(-halfSize, halfSize, -halfSize),
center + new float3(halfSize, halfSize, -halfSize),
center + new float3(halfSize, halfSize, halfSize),
center + new float3(-halfSize, halfSize, halfSize),
};
//fixed array
var cubeTriangles = new int[]
{
0, 1, 2, 0, 2, 3, 2, 1, 6, 6, 1, 5, 0, 4, 5, 0, 5, 1,
6, 7, 3, 6, 3, 2, 7, 6, 5, 7, 5, 4, 4, 0, 3, 4, 3, 7,
};

//leaving this here due to it can cause funky generation

//var cubeTriangles = new int[]
//{
// 0, 2, 1, 0, 3, 2, 2, 3, 6, 6, 3, 7, 0, 7, 3, 0, 4, 7,
// 6, 5, 2, 5, 1, 2, 1, 5, 0, 5, 4, 0, 4, 5, 7, 5, 6, 7,
//};

for (int i = 0; i < cubeTriangles.Length; i += 3)
{
int vertexCount = mesh.VertexCount;
mesh.SetVertexCount(vertexCount + 3);

mesh.SetVertex(vertexCount, cubeVertices[cubeTriangles[i]]);
mesh.SetVertex(vertexCount + 1, cubeVertices[cubeTriangles[i + 1]]);
mesh.SetVertex(vertexCount + 2, cubeVertices[cubeTriangles[i + 2]]);

float3 normal = MathX.Cross(
cubeVertices[cubeTriangles[i + 1]] - cubeVertices[cubeTriangles[i]],
cubeVertices[cubeTriangles[i + 2]] - cubeVertices[cubeTriangles[i]]).Normalized;
mesh.SetNormal(vertexCount, normal);
mesh.SetNormal(vertexCount + 1, normal);
mesh.SetNormal(vertexCount + 2, normal);

mesh.AddTriangle(vertexCount, vertexCount + 1, vertexCount + 2);
}
}

public override void Update()
{
Mesh.RecalculateNormals(AllTriangles);
Mesh.RecalculateTangents(AllTriangles);
}
}
}
115 changes: 115 additions & 0 deletions Components/Mesh/SierpinskiPyramid.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
using Elements.Assets;
using Elements.Core;
using System;
using System.Collections.Generic;


namespace Obsidian
{
// https://answers.unity.com/questions/1477363/infinite-vector-3-generate-method-for-sierpinski-t.html
public class SierpinskiPyramid : MeshXShape
{
public int Subdivisions;

public SierpinskiPyramid(MeshX mesh, int subdivisions) : base(mesh)
{
Subdivisions = subdivisions;
var sTet = new STetrahedron().SubdivideFirst(subdivisions);
mesh.Clear();
mesh.SetVertexCount(sTet.centers.Count * 12);

float s = sTet.Size;
int i = 0;
foreach (var c in sTet.centers)
{
var v0 = c + new float3(0, s, 0);
var v1 = c + new float3(-STetrahedron.s2_3 * s, -STetrahedron.f1_3 * s, -STetrahedron.s2_9 * s);
var v2 = c + new float3(STetrahedron.s2_3 * s, -STetrahedron.f1_3 * s, -STetrahedron.s2_9 * s);
var v3 = c + new float3(0, -STetrahedron.f1_3 * s, STetrahedron.s8_9 * s);

var n = MathX.Cross(v2 - v0, v1 - v0).Normalized;
mesh.SetNormal(i, n);
mesh.SetNormal(i + 1, n);
mesh.SetNormal(i + 2, n);
mesh.AddTriangle(i, i + 1, i + 2);
mesh.SetVertex(i++, v0);
mesh.SetVertex(i++, v2);
mesh.SetVertex(i++, v1);

n = MathX.Cross(v1 - v0, v3 - v0).Normalized;
mesh.SetNormal(i, n);
mesh.SetNormal(i + 1, n);
mesh.SetNormal(i + 2, n);
mesh.AddTriangle(i, i + 1, i + 2);
mesh.SetVertex(i++, v0);
mesh.SetVertex(i++, v1);
mesh.SetVertex(i++, v3);

n = MathX.Cross(v3 - v0, v2 - v0).Normalized;
mesh.SetNormal(i, n);
mesh.SetNormal(i + 1, n);
mesh.SetNormal(i + 2, n);
mesh.AddTriangle(i, i + 1, i + 2);
mesh.SetVertex(i++, v0);
mesh.SetVertex(i++, v3);
mesh.SetVertex(i++, v2);

n = float3.Down;
mesh.SetNormal(i, n);
mesh.SetNormal(i + 1, n);
mesh.SetNormal(i + 2, n);
mesh.AddTriangle(i, i + 1, i + 2);
mesh.SetVertex(i++, v1);
mesh.SetVertex(i++, v2);
mesh.SetVertex(i++, v3);
}

// The following have no effects
// mesh.RecalculateNormals();
// mesh.RecalculateTangents();
// mesh.GetMergedDoubles();
}

public override void Update()
{
Mesh.RecalculateNormals(AllTriangles);
Mesh.RecalculateTangents(AllTriangles);
}

public class STetrahedron
{
public static float s8_9 = MathX.Sqrt(8f / 9f);
public static float s2_9 = MathX.Sqrt(2f / 9f);
public static float s2_3 = MathX.Sqrt(2f / 3f);
public const float f1_3 = 1f / 3f;
public float Size = 1;
public List<float3> centers = new List<float3>();

private STetrahedron Subdivide()
{
var result = new STetrahedron();
float s = result.Size = Size * 0.5f;
if (centers.Count == 0)
centers.Add(float3.Zero);
foreach (var c in centers)
{
result.centers.Add(c + new float3(0, s, 0));
result.centers.Add(c + new float3(-s2_3 * s, -f1_3 * s, -s2_9 * s));
result.centers.Add(c + new float3(s2_3 * s, -f1_3 * s, -s2_9 * s));
result.centers.Add(c + new float3(0, -f1_3 * s, s8_9 * s));
}

return result;
}

public STetrahedron SubdivideFirst(int aCount)
{
var res = this;
Size = aCount;
for (int i = 0; i < aCount; i++)
res = res.Subdivide();
return res;
}
}
}
}
46 changes: 46 additions & 0 deletions Components/Mesh/SierpinskiPyramidMesh.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using Elements.Assets;
using Elements.Core;
using FrooxEngine;
using System;

namespace Obsidian
{
[Category(new string[] { "Obsidian/Assets/Procedural Meshes" })]
public class SierpinskiPyramidMesh : ProceduralMesh
{
[Range(1, 9)] public readonly Sync<int> Subdivisions;
private SierpinskiPyramid pyramid;
private int _subdivisions;

protected override void OnAwake()
{
base.OnAwake();
Subdivisions.Value = 1;
}

protected override void PrepareAssetUpdateData()
{
_subdivisions = Subdivisions.Value;
}

protected override void ClearMeshData()
{
pyramid = null;
}

protected override void UpdateMeshData(MeshX meshx)
{
bool value = false;
if (pyramid == null || pyramid.Subdivisions != _subdivisions)
{
pyramid?.Remove();
pyramid = new SierpinskiPyramid(meshx, _subdivisions);
value = true;
}

pyramid.Subdivisions = Subdivisions.Value;
pyramid.Update();
uploadHint[MeshUploadHint.Flag.Geometry] = value;
}
}
}
70 changes: 70 additions & 0 deletions Components/Transform/Drivers/MultiValueArithmeticDriver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using System.Linq;
using Elements.Assets;
using Elements.Core;
using FrooxEngine;

namespace Obsidian;

[Category(new string[] { "Obsidian/Transform/Drivers" })]
[GenericTypes(GenericTypesAttribute.Group.Primitives)]
public class MultiValueArithmeticDriver<T> : Component
{
public static bool IsValidGenericType => Coder<T>.SupportsAddSub;

public enum ArithmeticMode
{
Addition,
Subtraction,
Multiplication,
Division
}

public readonly FieldDrive<T> Target;

public readonly Sync<ArithmeticMode> Mode;

public readonly SyncList<Sync<T>> Values;

protected override void OnChanges()
{
if (!Target.IsLinkValid || Values.Count == 0)
{
return;
}
if (Values.Contains(Target.Target))
{
// don't let the component drive itself, don't want a feedback loop
Target.ReleaseLink();
return;
}
T value = Values[0].Value;
switch (Mode.Value)
{
case ArithmeticMode.Addition:
foreach (Sync<T> sync in Values.Skip(1))
{
value = Coder<T>.Add(value, sync.Value);
}
break;
case ArithmeticMode.Subtraction:
foreach (Sync<T> sync in Values.Skip(1))
{
value = Coder<T>.Sub(value, sync.Value);
}
break;
case ArithmeticMode.Multiplication:
foreach (Sync<T> sync in Values.Skip(1))
{
value = Coder<T>.Mul(value, sync.Value);
}
break;
case ArithmeticMode.Division:
foreach (Sync<T> sync in Values.Skip(1))
{
value = Coder<T>.Div(value, sync.Value);
}
break;
}
Target.Target.Value = value;
}
}
Loading

0 comments on commit ee8744a

Please sign in to comment.