-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
444 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
70
Components/Transform/Drivers/MultiValueArithmeticDriver.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
Oops, something went wrong.