Updated Sphere generation
Some checks failed
Gitea Actions Demo / Scan the project (push) Failing after 7s
Some checks failed
Gitea Actions Demo / Scan the project (push) Failing after 7s
This commit is contained in:
parent
cf6fb35eb2
commit
8470304859
|
@ -1 +0,0 @@
|
|||
global using Xunit;
|
|
@ -1,29 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="3.2.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Nebulix\Nebulix.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -1,12 +0,0 @@
|
|||
using Nebulix.InputSystem;
|
||||
|
||||
namespace Nebulix.Test
|
||||
{
|
||||
public class TestInputSystem
|
||||
{
|
||||
[Fact]
|
||||
public void IfSingleKeyIsPressed_InputIsKeyPressedShouldReturnTrue()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
36
Nebulix/ArrayExtensions.cs
Normal file
36
Nebulix/ArrayExtensions.cs
Normal file
|
@ -0,0 +1,36 @@
|
|||
using System.Numerics;
|
||||
using Silk.NET.Maths;
|
||||
|
||||
namespace Nebulix
|
||||
{
|
||||
public static class ArrayExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Copies the given arrays to the start of this array. The order of <paramref name="arrays"/> is preserved
|
||||
/// </summary>
|
||||
/// <param name="arrays">The arrays copied into this array</param>
|
||||
public static void CopyFrom(this Array array, params Array[] arrays)
|
||||
{
|
||||
int lastIndex = 0;
|
||||
for (int i = 0; i < arrays.Length; i++)
|
||||
{
|
||||
arrays[i].CopyTo(array, lastIndex);
|
||||
lastIndex += arrays[i].Length;
|
||||
}
|
||||
}
|
||||
|
||||
public static T[] ExtractComponents<T>(this Vector3D<T>[] array) where T : unmanaged, IFormattable, IEquatable<T>, IComparable<T>
|
||||
{
|
||||
T[] result = new T[array.Length * 3]; // * 3 cause a Vector3D has 3 components
|
||||
int resultIdx = 0;
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
result[resultIdx] = array[i].X;
|
||||
result[resultIdx + 1] = array[i].Y;
|
||||
result[resultIdx + 2] = array[i].Z;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,19 +5,29 @@ namespace Nebulix.Rendering
|
|||
public sealed class Mesh
|
||||
{
|
||||
public float[] Vertices { get => vertices; set { vertices = value; regenerate = true; } }
|
||||
public float[] Indices { get => indices; set { indices = value; regenerate = true; } }
|
||||
public float[] Normals { get => normals; }
|
||||
public nuint[] Indices { get => indices; set { indices = value; regenerate = true; } }
|
||||
|
||||
private uint vao = 0, vbo = 0, ebo = 0;
|
||||
private bool regenerate = true;
|
||||
|
||||
private float[] vertices = [];
|
||||
private float[] indices = [];
|
||||
private nuint[] indices = [];
|
||||
private float[] normals = [];
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
vertices = [];
|
||||
indices = [];
|
||||
}
|
||||
|
||||
// getting called by "Engine" which currently is in other assembly, meaning I probably need to make this public
|
||||
internal void Use(GL gl)
|
||||
public void CalculateNormals()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
// getting called by "Engine" which currently is in another assembly, meaning I probably need to make this public
|
||||
// needs to be change for the real engine
|
||||
public void Use(GL gl)
|
||||
{
|
||||
if (regenerate) Generate(gl);
|
||||
|
||||
|
@ -44,7 +54,7 @@ namespace Nebulix.Rendering
|
|||
gl.BindBuffer(BufferTargetARB.ArrayBuffer, vbo);
|
||||
gl.BufferData(BufferTargetARB.ArrayBuffer, (nuint)(data.Length * sizeof(float)), data, BufferUsageARB.StaticDraw);
|
||||
|
||||
ReadOnlySpan<float> indicesData = new(indices);
|
||||
ReadOnlySpan<nuint> indicesData = new(indices);
|
||||
gl.BindBuffer(BufferTargetARB.ElementArrayBuffer, ebo);
|
||||
gl.BufferData(BufferTargetARB.ElementArrayBuffer, (nuint)(indicesData.Length * sizeof(uint)), indicesData, BufferUsageARB.StaticDraw);
|
||||
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
namespace Engine_silk.NET
|
||||
{
|
||||
public static class ArrayExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Copies the given arrays to the start of this array. The order of <paramref name="arrays"/> is preserved
|
||||
/// </summary>
|
||||
/// <param name="arrays">The arrays copied into this array</param>
|
||||
public static void CopyFrom(this Array array, params Array[] arrays)
|
||||
{
|
||||
int lastIndex = 0;
|
||||
for (int i = 0; i < arrays.Length; i++)
|
||||
{
|
||||
arrays[i].CopyTo(array, lastIndex);
|
||||
lastIndex += arrays[i].Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,11 +7,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Engine_silk.NET", "Engine_s
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nebulix", "..\Nebulix\Nebulix.csproj", "{0DEED1E3-932E-47C3-AF2D-FCA74000908E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nebulix.Test", "..\Nebulix.Test\Nebulix.Test.csproj", "{60B8C905-7AC4-45EE-BAB1-26D3F826124B}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{0DEED1E3-932E-47C3-AF2D-FCA74000908E} = {0DEED1E3-932E-47C3-AF2D-FCA74000908E}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -26,10 +21,6 @@ Global
|
|||
{0DEED1E3-932E-47C3-AF2D-FCA74000908E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0DEED1E3-932E-47C3-AF2D-FCA74000908E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0DEED1E3-932E-47C3-AF2D-FCA74000908E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{60B8C905-7AC4-45EE-BAB1-26D3F826124B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{60B8C905-7AC4-45EE-BAB1-26D3F826124B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{60B8C905-7AC4-45EE-BAB1-26D3F826124B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{60B8C905-7AC4-45EE-BAB1-26D3F826124B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -31,7 +31,6 @@ public static class Program
|
|||
private static uint _vao, _vbo, _ebo;
|
||||
|
||||
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
WindowOptions options = WindowOptions.Default with
|
||||
|
@ -158,9 +157,6 @@ public static class Program
|
|||
_gl.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, 8 * sizeof(float), (void*)(6 * sizeof(float)));
|
||||
|
||||
_texture = new Texture2D(_gl, "images/container.png", ImageFormat.RGBA);
|
||||
|
||||
Sphere s = new(_gl, 1, 10);
|
||||
s.GetVertices();
|
||||
}
|
||||
|
||||
private static void OnUpdate(double deltaTime)
|
||||
|
|
165
src/Sphere.cs
165
src/Sphere.cs
|
@ -1,123 +1,96 @@
|
|||
using Nebulix.Rendering;
|
||||
using Nebulix;
|
||||
using Nebulix.Rendering;
|
||||
using Silk.NET.Maths;
|
||||
using Silk.NET.OpenGL;
|
||||
|
||||
namespace Engine_silk.NET
|
||||
{
|
||||
// TODO: Think about just creating a cube with a certain resolution and then use this cube to generate the Sphere.
|
||||
// also maybe make an ISphere and call this class "CubeSphere"?
|
||||
public class Sphere(GL gl, float radius, uint resolution)
|
||||
public class Sphere(uint resolution)
|
||||
{
|
||||
private readonly Face[] sphereFaces = new Face[6];
|
||||
public void CreateSphere()
|
||||
{
|
||||
uint _vao, _vbo, _ebo;
|
||||
|
||||
_vao = gl.CreateVertexArray();
|
||||
gl.BindVertexArray(_vao);
|
||||
|
||||
ReadOnlySpan<float> verticesData = GetVertices();
|
||||
|
||||
_vbo = gl.GenBuffer();
|
||||
gl.BindBuffer(BufferTargetARB.ArrayBuffer, _vbo);
|
||||
gl.BufferData(BufferTargetARB.ArrayBuffer, (nuint)(verticesData.Length * sizeof(float)), verticesData, BufferUsageARB.StaticDraw);
|
||||
|
||||
}
|
||||
|
||||
public void RenderSphere()
|
||||
Vector3D<float>[] directions =
|
||||
{
|
||||
Vector3D<float>.UnitZ, -Vector3D<float>.UnitZ,
|
||||
Vector3D<float>.UnitY, -Vector3D<float>.UnitY,
|
||||
Vector3D<float>.UnitX, -Vector3D<float>.UnitX
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// TODO: make this private after testing
|
||||
public ReadOnlySpan<float> GetVertices()
|
||||
for (int i = 0; i < sphereFaces.Length; i++)
|
||||
{
|
||||
var front = GetSide(Vector3D<float>.UnitZ).Item1;
|
||||
var back = GetSide(-Vector3D<float>.UnitZ).Item1;
|
||||
var up = GetSide(Vector3D<float>.UnitY).Item1;
|
||||
var down = GetSide(-Vector3D<float>.UnitY).Item1;
|
||||
var left = GetSide(Vector3D<float>.UnitX).Item1;
|
||||
var right = GetSide(-Vector3D<float>.UnitX).Item1;
|
||||
|
||||
var finalArray = new float[front.Length + back.Length + up.Length + down.Length + left.Length + right.Length];
|
||||
finalArray.CopyFrom(front, back, up, down, left, right);
|
||||
|
||||
return new ReadOnlySpan<float>(finalArray);
|
||||
}
|
||||
|
||||
|
||||
[Obsolete("Use Sphere.GetFace(Vector3D<float>) instead")]
|
||||
private (float[], float[]) GetSide(Vector3D<float> localUp)
|
||||
{
|
||||
|
||||
float stepSize = 2f / resolution;
|
||||
|
||||
List<float> vertices = new((int)(3 * resolution * resolution * 2)); // resolution * resolution == number of rows/columns; 3 * ... == each vertex has 3 positions; 2 * ... == vertex also needs normal
|
||||
|
||||
Vector3D<float> position = localUp;
|
||||
for (uint y = 0; y <= resolution; y++)
|
||||
{
|
||||
for (uint x = 0; x <= resolution; x++)
|
||||
{
|
||||
uint i = x + y * resolution;
|
||||
Vector2D<float> percent = new Vector2D<float>(x, y) / (resolution - 1);
|
||||
//Vector3D<float> pointOnUnitCube = localUp + (percent.X - 0.5f) * stepSize *
|
||||
|
||||
if (localUp.X != 0)
|
||||
{
|
||||
position.Y = x * stepSize - 1;
|
||||
position.Z = y * stepSize - 1;
|
||||
}
|
||||
else if (localUp.Y != 0)
|
||||
{
|
||||
position.X = x * stepSize - 1;
|
||||
position.Z = y * stepSize - 1;
|
||||
}
|
||||
else if (localUp.Z != 0)
|
||||
{
|
||||
position.X = x * stepSize - 1;
|
||||
position.Y = y * stepSize - 1;
|
||||
}
|
||||
vertices.AddRange([position.X, position.Y, position.Z, localUp.X, localUp.Y, localUp.Z]);
|
||||
// TODO: Refactor so that a face gets a mesh it can only change the contents of (should improve performance)
|
||||
sphereFaces[i] = new Face(directions[i], resolution);
|
||||
}
|
||||
}
|
||||
|
||||
List<uint> indices = new((int)(resolution * resolution * 6)); // ... * 6 == one quad has 6 indices and we have resolution * resolution quads
|
||||
Console.WriteLine($"Indices size before Loop: {indices.Capacity}");
|
||||
|
||||
uint vi = 0; // vertexIndex
|
||||
for (uint i = 0; i < vertices.Count; i += 6)
|
||||
public void RenderSphere(GL gl) // Will not be needed
|
||||
{
|
||||
if ((vi + 1) % resolution == 0)
|
||||
// Use default shader etc. to render the sphere
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
vi++;
|
||||
continue;
|
||||
Mesh m = sphereFaces[i].GetMesh();
|
||||
m.Use(gl);
|
||||
}
|
||||
|
||||
indices.AddRange([vi, vi+1, vi+1+resolution,
|
||||
vi, vi+1+resolution, vi+resolution]);
|
||||
vi++;
|
||||
}
|
||||
|
||||
Console.WriteLine($"Indices size after Loop: {indices.Count}");
|
||||
|
||||
return (vertices.ToArray(), []);
|
||||
}
|
||||
|
||||
// https://youtu.be/QN39W020LqU?si=a66D1Lnic1vNaC6l&t=89
|
||||
// https://github.com/SebLague/Procedural-Planets/blob/master/Procedural%20Planet%20E01/Assets/TerrainFace.cs
|
||||
/// <param name="localUp">The unit vector in which the side should point. E.g. Vector.UnitX</param>
|
||||
public Mesh GetFace(Vector3D<float> localUp)
|
||||
{
|
||||
// this all probably needs to be rewritten to use the "Face" record below and split the stuff better
|
||||
return new Mesh();
|
||||
}
|
||||
}
|
||||
|
||||
internal record struct Face
|
||||
{
|
||||
public Face()
|
||||
{
|
||||
private readonly Vector3D<float> _localX;
|
||||
private readonly Vector3D<float> _localY;
|
||||
|
||||
private readonly Vector3D<float> _localUp;
|
||||
private readonly uint _resolution;
|
||||
|
||||
public Face(Vector3D<float> localUp, uint resolution)
|
||||
{
|
||||
_localX = new(localUp.Y, localUp.Z, localUp.X);
|
||||
_localY = Vector3D.Cross(localUp, _localX);
|
||||
_localUp = localUp;
|
||||
_resolution = resolution;
|
||||
}
|
||||
|
||||
internal Mesh GetMesh()
|
||||
{
|
||||
var vertices = new Vector3D<float>[_resolution * _resolution];
|
||||
// _resolution - 1 because the vertices index starts at 0
|
||||
// * 6 because each triangle needs 3 points and each small quad has 2 triangles 3*2 = 6
|
||||
nuint[] indices = new nuint[(_resolution - 1) * (_resolution - 1) * 6];
|
||||
int triangleIndex = 0;
|
||||
|
||||
uint i;
|
||||
for (uint y = 0; y < _resolution; y++)
|
||||
{
|
||||
for (uint x = 0; x < _resolution; x++)
|
||||
{
|
||||
i = x + y * _resolution;
|
||||
Vector2D<float> percent = new Vector2D<float>(x, y) / (_resolution - 1);
|
||||
// place vertex on correct position of the plane to easily calculate indices
|
||||
Vector3D<float> vertexPosition = _localUp + (percent.X - 0.5f) * 2 * _localX + (percent.Y - 0.5f) * 2 * _localY;
|
||||
vertices[i] = Vector3D.Normalize(vertexPosition); // normalise vertex position to get it to be "on the sphere" and not "on the plane"
|
||||
|
||||
if (x != _resolution - 1 && y != _resolution - 1) // we didn't reach the bottom right point yet
|
||||
{
|
||||
indices[triangleIndex] = i;
|
||||
indices[triangleIndex + 1] = i + _resolution + 1;
|
||||
indices[triangleIndex + 2] = i + _resolution;
|
||||
|
||||
indices[triangleIndex + 3] = i;
|
||||
indices[triangleIndex + 4] = i + 1;
|
||||
indices[triangleIndex + 5] = i + _resolution + 1;
|
||||
|
||||
triangleIndex += 6; // doing it this way is faster than doing indices[triangleIndex++] (takes about double the time)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Mesh m = new Mesh();
|
||||
m.Vertices = vertices.ExtractComponents();
|
||||
m.Indices = indices;
|
||||
|
||||
return m;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user