failed trying to procedurally generate a cube sphere
Some checks failed
Gitea Actions Demo / Scan the project (push) Failing after 8s

This commit is contained in:
Daniel 2023-12-22 15:14:26 +01:00
parent eff34ff950
commit 4b681e8a94
5 changed files with 150 additions and 6 deletions

View File

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Silk.NET.Input" Version="2.17.1" />
<PackageReference Include="Silk.NET.Input" Version="2.20.0" />
</ItemGroup>
</Project>

19
src/ArrayExtensions.cs Normal file
View File

@ -0,0 +1,19 @@
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;
}
}
}
}

View File

@ -2,16 +2,16 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Silk.NET.Input" Version="2.17.1" />
<PackageReference Include="Silk.NET.OpenGL" Version="2.17.1" />
<PackageReference Include="Silk.NET.Windowing" Version="2.17.1" />
<PackageReference Include="Silk.NET.Input" Version="2.20.0" />
<PackageReference Include="Silk.NET.OpenGL" Version="2.20.0" />
<PackageReference Include="Silk.NET.Windowing" Version="2.20.0" />
<PackageReference Include="StbImageSharp" Version="2.27.13" />
</ItemGroup>

View File

@ -140,7 +140,7 @@ public static class Program
_vbo = _gl.GenBuffer();
_gl.BindBuffer(BufferTargetARB.ArrayBuffer, _vbo);
_gl.BufferData(BufferTargetARB.ArrayBuffer, (nuint)(vertices.Length * sizeof(float)), verticesData, BufferUsageARB.StaticDraw);
_gl.BufferData(BufferTargetARB.ArrayBuffer, (nuint)(verticesData.Length * sizeof(float)), verticesData, BufferUsageARB.StaticDraw);
//_ebo = _gl.GenBuffer();
//_gl.BindBuffer(BufferTargetARB.ElementArrayBuffer, _ebo);
@ -157,6 +157,9 @@ 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)

122
src/Sphere.cs Normal file
View File

@ -0,0 +1,122 @@
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 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()
{
}
// TODO: make this private after testing
public ReadOnlySpan<float> GetVertices()
{
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);
}
/// <param name="normal">The unit vector in which the side should point. E.g. Vector.Up</param>
private (float[], float[]) GetSide(Vector3D<float> normal)
{
//float upperBound = radius, lowerBound = -radius;
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 = normal;
for (int row = 0; row <= resolution; row++)
{
for (int col = 0; col <= resolution; col++)
{
if (normal.X != 0)
{
position.Y = row * stepSize - 1;
position.Z = col * stepSize - 1;
}
else if (normal.Y != 0)
{
position.X = row * stepSize - 1;
position.Z = col * stepSize - 1;
}
else if (normal.Z != 0)
{
position.X = row * stepSize - 1;
position.Y = col * stepSize - 1;
}
vertices.AddRange([position.X, position.Y, position.Z, normal.X, normal.Y, normal.Z]);
}
}
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)
{
if ((vi + 1) % resolution == 0)
{
vi++;
continue;
}
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(), []);
}
// top left origin, stepsizeX, stepsizeY (maybe index of first vertex?)
// https://youtu.be/QN39W020LqU?si=a66D1Lnic1vNaC6l&t=89
private Face Quad(uint resolution, uint row, uint column)
{
// TODO: change coordinates according to the direction the quad should be looking
// https://catlikecoding.com/unity/tutorials/procedural-meshes/cube-sphere/
float[] vertices = [
1.0f, 1.0f, 0.0f, // top right
1.0f, -1.0f, 0.0f, // bottom right
-1.0f, -1.0f, 0.0f, // bottom left
-1.0f, 1.0f, 0.0f // top left
];
uint[] indices = [
0, 1, 3, // first triangle
1, 2, 3 // second triangle
];
return new Face(vertices, indices);
}
}
internal record struct Face(float[] Vertices, uint[] Indices);
}