Added IcoSphere for testing. Replaced Vector3D<T> with Vector3 since it is more performant
All checks were successful
Gitea Actions Demo / Scan the project (push) Successful in 21s
All checks were successful
Gitea Actions Demo / Scan the project (push) Successful in 21s
This commit is contained in:
parent
0b0d2360d6
commit
3912f2bd9a
|
@ -1,20 +1,20 @@
|
||||||
using Silk.NET.Maths;
|
using System.Numerics;
|
||||||
using Silk.NET.OpenGL;
|
using Silk.NET.OpenGL;
|
||||||
|
|
||||||
namespace Nebulix.Rendering
|
namespace Nebulix.Rendering
|
||||||
{
|
{
|
||||||
public sealed class Mesh
|
public sealed class Mesh
|
||||||
{
|
{
|
||||||
public Vector3D<float>[] Vertices { get => vertices;
|
public Vector3[] Vertices { get => vertices;
|
||||||
set { vertices = value; regenerate = true; normals = new Vector3D<float>[vertices.Length];} }
|
set { vertices = value; regenerate = true; normals = new Vector3[vertices.Length];} }
|
||||||
public uint[] Indices { get => indices; set { indices = value; regenerate = true; } }
|
public uint[] Indices { get => indices; set { indices = value; regenerate = true; } }
|
||||||
|
|
||||||
private uint vao = 0, vbo = 0, ebo = 0;
|
private uint vao, vbo, ebo;
|
||||||
private bool regenerate = true;
|
private bool regenerate = true;
|
||||||
|
|
||||||
private Vector3D<float>[] vertices = [];
|
private Vector3[] vertices = [];
|
||||||
private uint[] indices = [];
|
private uint[] indices = [];
|
||||||
private Vector3D<float>[] normals = [];
|
private Vector3[] normals = [];
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
|
@ -29,13 +29,13 @@ namespace Nebulix.Rendering
|
||||||
uint i0 = indices[i];
|
uint i0 = indices[i];
|
||||||
uint i1 = indices[i+1];
|
uint i1 = indices[i+1];
|
||||||
uint i2 = indices[i+2];
|
uint i2 = indices[i+2];
|
||||||
Vector3D<float> v0 = vertices[i0];
|
Vector3 v0 = vertices[i0];
|
||||||
Vector3D<float> v1 = vertices[i1];
|
Vector3 v1 = vertices[i1];
|
||||||
Vector3D<float> v2 = vertices[i2];
|
Vector3 v2 = vertices[i2];
|
||||||
|
|
||||||
Vector3D<float> normal = Vector3D.Cross(v1-v0, v2-v0);
|
Vector3 normal = Vector3.Cross(v1-v0, v2-v0);
|
||||||
// Commenting this out, will result in the normals being weighted based on the triangle area
|
// Commenting this out, will result in the normals being weighted based on the triangle area
|
||||||
normal = Vector3D.Normalize(normal);
|
normal = Vector3.Normalize(normal);
|
||||||
normals[i0] += normal;
|
normals[i0] += normal;
|
||||||
normals[i1] += normal;
|
normals[i1] += normal;
|
||||||
normals[i2] += normal;
|
normals[i2] += normal;
|
||||||
|
@ -43,7 +43,7 @@ namespace Nebulix.Rendering
|
||||||
|
|
||||||
for (int i = 0; i < normals.Length; i++)
|
for (int i = 0; i < normals.Length; i++)
|
||||||
{
|
{
|
||||||
normals[i] = Vector3D.Normalize(normals[i]); // smoothing for shared vertices
|
normals[i] = Vector3.Normalize(normals[i]); // smoothing for shared vertices
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
using Silk.NET.Maths;
|
using Silk.NET.OpenGL;
|
||||||
using Silk.NET.OpenGL;
|
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using Silk.NET.Maths;
|
||||||
|
|
||||||
namespace Nebulix.Rendering;
|
namespace Nebulix.Rendering;
|
||||||
|
|
||||||
|
@ -35,6 +35,10 @@ public class Shader
|
||||||
_glContext.Uniform1(_glContext.GetUniformLocation(_shaderProgramId, name), value);
|
_glContext.Uniform1(_glContext.GetUniformLocation(_shaderProgramId, name), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetVector(string name, Vector3 value)
|
||||||
|
{
|
||||||
|
_glContext.Uniform3(_glContext.GetUniformLocation(_shaderProgramId, name), value.X, value.Y, value.Z);
|
||||||
|
}
|
||||||
public void SetVector(string name, Vector3D<float> value)
|
public void SetVector(string name, Vector3D<float> value)
|
||||||
{
|
{
|
||||||
_glContext.Uniform3(_glContext.GetUniformLocation(_shaderProgramId, name), value.X, value.Y, value.Z);
|
_glContext.Uniform3(_glContext.GetUniformLocation(_shaderProgramId, name), value.X, value.Y, value.Z);
|
||||||
|
|
35
Nebulix/Vector.cs
Normal file
35
Nebulix/Vector.cs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace Nebulix;
|
||||||
|
|
||||||
|
|
||||||
|
public static class VectorExtensions
|
||||||
|
{
|
||||||
|
public static Vector3 Up(this Vector3 _) => Vector3.UnitY;
|
||||||
|
public static Vector3 Down(this Vector3 _) => -Vector3.UnitY;
|
||||||
|
public static Vector3 Left(this Vector3 _) => Vector3.UnitX;
|
||||||
|
public static Vector3 Right(this Vector3 _) => -Vector3.UnitX;
|
||||||
|
public static Vector3 Front(this Vector3 _) => -Vector3.UnitZ;
|
||||||
|
public static Vector3 Back(this Vector3 _) => -Vector3.UnitZ;
|
||||||
|
|
||||||
|
// Thanks to: https://stackoverflow.com/a/67920029
|
||||||
|
public static Vector3 Slerp(this Vector3 start, Vector3 end, float percent)
|
||||||
|
{
|
||||||
|
// the cosine of the angle between 2 vectors.
|
||||||
|
float dot = Vector3.Dot(start, end);
|
||||||
|
|
||||||
|
// Clamp it to be in the range of Acos()
|
||||||
|
// This may be unnecessary, but floating point precision can be a fickle mistress.
|
||||||
|
Math.Clamp(dot, -1.0f, 1.0f);
|
||||||
|
|
||||||
|
// Acos(dot) returns the angle between start and end,
|
||||||
|
// And multiplying that by percent returns the angle between start and the final result.
|
||||||
|
float theta = (float)Math.Acos(dot) * percent;
|
||||||
|
Vector3 relativeVec = end - start * dot;
|
||||||
|
relativeVec = Vector3.Normalize(relativeVec);
|
||||||
|
|
||||||
|
// Orthonormal basis
|
||||||
|
// The final result.
|
||||||
|
return ((start * (float)Math.Cos(theta)) + (relativeVec * (float)Math.Sin(theta)));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using Silk.NET.Maths;
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Engine_silk.NET;
|
namespace Engine_silk.NET;
|
||||||
|
|
||||||
|
@ -14,19 +14,19 @@ public enum MovementDirection
|
||||||
|
|
||||||
public class Camera
|
public class Camera
|
||||||
{
|
{
|
||||||
public Vector3D<float> Position => _position;
|
public Vector3 Position => _position;
|
||||||
private readonly Vector3D<float> _worldUp;
|
private readonly Vector3 _worldUp;
|
||||||
private Vector3D<float> _position;
|
private Vector3 _position;
|
||||||
private Vector3D<float> _front;
|
private Vector3 _front;
|
||||||
private Vector3D<float> _right;
|
private Vector3 _right;
|
||||||
private Vector3D<float> _up;
|
private Vector3 _up;
|
||||||
private float _yaw;
|
private float _yaw;
|
||||||
private float _pitch;
|
private float _pitch;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The view matrix according to the current camera position and rotation
|
/// The view matrix according to the current camera position and rotation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Matrix4X4<float> ViewMatrix { get => Matrix4X4.CreateLookAt(_position, _position + _front, _worldUp); }
|
public Matrix4x4 ViewMatrix { get => Matrix4x4.CreateLookAt(_position, _position + _front, _worldUp); }
|
||||||
public float MouseSensitivity { get; set; } = 0.1f;
|
public float MouseSensitivity { get; set; } = 0.1f;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Controlls how fast the camera moves if a key is pressed
|
/// Controlls how fast the camera moves if a key is pressed
|
||||||
|
@ -34,14 +34,14 @@ public class Camera
|
||||||
public float MovementSpeed { get; set; }
|
public float MovementSpeed { get; set; }
|
||||||
public float Fov { get; set; }
|
public float Fov { get; set; }
|
||||||
|
|
||||||
public Camera(Vector3D<float> position, float yaw = -90.0f, float pitch = 0, float movementSpeed = 2.5f, float fov = 45.0f)
|
public Camera(Vector3 position, float yaw = -90.0f, float pitch = 0, float movementSpeed = 2.5f, float fov = 45.0f)
|
||||||
{
|
{
|
||||||
_position = position;
|
_position = position;
|
||||||
_yaw = yaw;
|
_yaw = yaw;
|
||||||
_pitch = pitch;
|
_pitch = pitch;
|
||||||
MovementSpeed = movementSpeed;
|
MovementSpeed = movementSpeed;
|
||||||
Fov = fov;
|
Fov = fov;
|
||||||
_worldUp = Vector3D<float>.UnitY;
|
_worldUp = Vector3.UnitY;
|
||||||
|
|
||||||
UpdateCameraVectors();
|
UpdateCameraVectors();
|
||||||
}
|
}
|
||||||
|
@ -99,15 +99,15 @@ public class Camera
|
||||||
|
|
||||||
private void UpdateCameraVectors()
|
private void UpdateCameraVectors()
|
||||||
{
|
{
|
||||||
Vector3D<float> front = new(
|
Vector3 front = new(
|
||||||
MathF.Cos(Maths.Convert.ToRadians(_yaw)) * MathF.Cos(Maths.Convert.ToRadians(_pitch)),
|
MathF.Cos(Maths.Convert.ToRadians(_yaw)) * MathF.Cos(Maths.Convert.ToRadians(_pitch)),
|
||||||
MathF.Sin(Maths.Convert.ToRadians(_pitch)),
|
MathF.Sin(Maths.Convert.ToRadians(_pitch)),
|
||||||
MathF.Sin(Maths.Convert.ToRadians(_yaw)) * MathF.Cos(Maths.Convert.ToRadians(_pitch))
|
MathF.Sin(Maths.Convert.ToRadians(_yaw)) * MathF.Cos(Maths.Convert.ToRadians(_pitch))
|
||||||
);
|
);
|
||||||
_front = Vector3D.Normalize(front);
|
_front = Vector3.Normalize(front);
|
||||||
|
|
||||||
_right = Vector3D.Normalize(Vector3D.Cross(_front, _worldUp));
|
_right = Vector3.Normalize(Vector3.Cross(_front, _worldUp));
|
||||||
_up = Vector3D.Normalize(Vector3D.Cross(_right, _front));
|
_up = Vector3.Normalize(Vector3.Cross(_right, _front));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
183
src/IcoSphere.cs
Normal file
183
src/IcoSphere.cs
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
using System.Numerics;
|
||||||
|
using Nebulix;
|
||||||
|
using Nebulix.Rendering;
|
||||||
|
using Silk.NET.OpenGL;
|
||||||
|
|
||||||
|
namespace Engine_silk.NET;
|
||||||
|
|
||||||
|
public class IcoSphere
|
||||||
|
{
|
||||||
|
private readonly Mesh mesh = new();
|
||||||
|
private readonly int resolution;
|
||||||
|
private readonly IcoSphereGenerator generator = new();
|
||||||
|
|
||||||
|
public IcoSphere(int resolution)
|
||||||
|
{
|
||||||
|
if (resolution < 2)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(resolution), resolution,
|
||||||
|
"Resolution must be greater than 1");
|
||||||
|
this.resolution = resolution;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateSphere()
|
||||||
|
{
|
||||||
|
generator.Generate(resolution);
|
||||||
|
|
||||||
|
mesh.Clear();
|
||||||
|
mesh.Vertices = generator.Vertices;
|
||||||
|
mesh.Indices = Array.ConvertAll(generator.Triangles, x => (uint)x);
|
||||||
|
mesh.CalculateNormals();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RenderSphere(GL gl) // Will not be needed
|
||||||
|
{
|
||||||
|
mesh.Render(gl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thank you Sebastian Lague
|
||||||
|
class IcoSphereGenerator
|
||||||
|
{
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
public Vector3[] Vertices => vertices?.Items ?? Array.Empty<Vector3>();
|
||||||
|
public int[] Triangles => triangles?.Items ?? Array.Empty<int>();
|
||||||
|
|
||||||
|
// Internal:
|
||||||
|
FixedSizeList<Vector3>? vertices;
|
||||||
|
FixedSizeList<int>? triangles;
|
||||||
|
int numDivisions;
|
||||||
|
int numVertsPerFace;
|
||||||
|
|
||||||
|
// Indices of the vertex pairs that make up each of the initial 12 edges
|
||||||
|
static readonly int[] VertexPairs = { 0, 1, 0, 2, 0, 3, 0, 4, 1, 2, 2, 3, 3, 4, 4, 1, 5, 1, 5, 2, 5, 3, 5, 4 };
|
||||||
|
// Indices of the edge triplets that make up the initial 8 faces
|
||||||
|
static readonly int[] EdgeTriplets = { 0, 1, 4, 1, 2, 5, 2, 3, 6, 3, 0, 7, 8, 9, 4, 9, 10, 5, 10, 11, 6, 11, 8, 7 };
|
||||||
|
// The six initial vertices up left back right forward down
|
||||||
|
static readonly Vector3[] BaseVertices = { Vector3.UnitY, -Vector3.UnitX, -Vector3.UnitZ, Vector3.UnitX, Vector3.UnitZ, -Vector3.UnitY };
|
||||||
|
|
||||||
|
public void Generate (int resolution) {
|
||||||
|
numDivisions = Math.Max (0, resolution);
|
||||||
|
numVertsPerFace = ((numDivisions + 3) * (numDivisions + 3) - (numDivisions + 3)) / 2;
|
||||||
|
int numVerts = numVertsPerFace * 8 - (numDivisions + 2) * 12 + 6;
|
||||||
|
int numTrisPerFace = (numDivisions + 1) * (numDivisions + 1);
|
||||||
|
|
||||||
|
vertices = new FixedSizeList<Vector3> (numVerts);
|
||||||
|
triangles = new FixedSizeList<int> (numTrisPerFace * 8 * 3);
|
||||||
|
|
||||||
|
vertices.AddRange (BaseVertices);
|
||||||
|
|
||||||
|
// Create 12 edges, with n vertices added along them (n = numDivisions)
|
||||||
|
Edge[] edges = new Edge[12];
|
||||||
|
for (int i = 0; i < VertexPairs.Length; i += 2) {
|
||||||
|
Vector3 startVertex = vertices.Items[VertexPairs[i]];
|
||||||
|
Vector3 endVertex = vertices.Items[VertexPairs[i + 1]];
|
||||||
|
|
||||||
|
int[] edgeVertexIndices = new int[numDivisions + 2];
|
||||||
|
edgeVertexIndices[0] = VertexPairs[i];
|
||||||
|
|
||||||
|
// Add vertices along edge
|
||||||
|
for (int divisionIndex = 0; divisionIndex < numDivisions; divisionIndex++) {
|
||||||
|
float t = (divisionIndex + 1f) / (numDivisions + 1f);
|
||||||
|
edgeVertexIndices[divisionIndex + 1] = vertices.NextIndex;
|
||||||
|
vertices.Add (startVertex.Slerp(endVertex, t));
|
||||||
|
}
|
||||||
|
edgeVertexIndices[numDivisions + 1] = VertexPairs[i + 1];
|
||||||
|
int edgeIndex = i / 2;
|
||||||
|
edges[edgeIndex] = new Edge (edgeVertexIndices);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create faces
|
||||||
|
for (int i = 0; i < EdgeTriplets.Length; i += 3) {
|
||||||
|
int faceIndex = i / 3;
|
||||||
|
bool reverse = faceIndex >= 4;
|
||||||
|
CreateFace (edges[EdgeTriplets[i]], edges[EdgeTriplets[i + 1]], edges[EdgeTriplets[i + 2]], reverse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateFace (Edge sideA, Edge sideB, Edge bottom, bool reverse)
|
||||||
|
{
|
||||||
|
if (vertices is null) throw new ArgumentException("Vertices cannot be null", nameof(vertices));
|
||||||
|
if (triangles is null) throw new ArgumentException("triangles cannot be null", nameof(triangles));
|
||||||
|
|
||||||
|
int numPointsInEdge = sideA.VertexIndices.Length;
|
||||||
|
var vertexMap = new FixedSizeList<int> (numVertsPerFace);
|
||||||
|
vertexMap.Add (sideA.VertexIndices[0]); // top of triangle
|
||||||
|
|
||||||
|
for (int i = 1; i < numPointsInEdge - 1; i++) {
|
||||||
|
// Side A vertex
|
||||||
|
vertexMap.Add (sideA.VertexIndices[i]);
|
||||||
|
|
||||||
|
// Add vertices between sideA and sideB
|
||||||
|
Vector3 sideAVertex = vertices.Items[sideA.VertexIndices[i]];
|
||||||
|
Vector3 sideBVertex = vertices.Items[sideB.VertexIndices[i]];
|
||||||
|
int numInnerPoints = i - 1;
|
||||||
|
for (int j = 0; j < numInnerPoints; j++) {
|
||||||
|
float t = (j + 1f) / (numInnerPoints + 1f);
|
||||||
|
vertexMap.Add (vertices.NextIndex);
|
||||||
|
vertices.Add (sideAVertex.Slerp(sideBVertex, t));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Side B vertex
|
||||||
|
vertexMap.Add (sideB.VertexIndices[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add bottom edge vertices
|
||||||
|
for (int i = 0; i < numPointsInEdge; i++) {
|
||||||
|
vertexMap.Add (bottom.VertexIndices[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Triangulate
|
||||||
|
int numRows = numDivisions + 1;
|
||||||
|
for (int row = 0; row < numRows; row++) {
|
||||||
|
// vertices down left edge follow quadratic sequence: 0, 1, 3, 6, 10, 15...
|
||||||
|
// the nth term can be calculated with: (n^2 - n)/2
|
||||||
|
int topVertex = ((row + 1) * (row + 1) - row - 1) / 2;
|
||||||
|
int bottomVertex = ((row + 2) * (row + 2) - row - 2) / 2;
|
||||||
|
|
||||||
|
int numTrianglesInRow = 1 + 2 * row;
|
||||||
|
for (int column = 0; column < numTrianglesInRow; column++) {
|
||||||
|
int v0, v1, v2;
|
||||||
|
|
||||||
|
if (column % 2 == 0) {
|
||||||
|
v0 = topVertex;
|
||||||
|
v1 = bottomVertex + 1;
|
||||||
|
v2 = bottomVertex;
|
||||||
|
topVertex++;
|
||||||
|
bottomVertex++;
|
||||||
|
} else {
|
||||||
|
v0 = topVertex;
|
||||||
|
v1 = bottomVertex;
|
||||||
|
v2 = topVertex - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
triangles.Add (vertexMap.Items[v0]);
|
||||||
|
triangles.Add (vertexMap.Items[(reverse) ? v2 : v1]);
|
||||||
|
triangles.Add (vertexMap.Items[(reverse) ? v1 : v2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convenience classes:
|
||||||
|
|
||||||
|
private record Edge(int[] VertexIndices);
|
||||||
|
|
||||||
|
private class FixedSizeList<T>(int size)
|
||||||
|
{
|
||||||
|
public readonly T[] Items = new T[size];
|
||||||
|
public int NextIndex;
|
||||||
|
|
||||||
|
public void Add (T item) {
|
||||||
|
Items[NextIndex] = item;
|
||||||
|
NextIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRange (IEnumerable<T> items) {
|
||||||
|
foreach (var item in items) {
|
||||||
|
Add (item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using Nebulix;
|
using Nebulix;
|
||||||
|
using Silk.NET.Maths;
|
||||||
|
|
||||||
namespace Engine_silk.NET;
|
namespace Engine_silk.NET;
|
||||||
|
|
||||||
|
@ -6,7 +7,6 @@ using Engine_silk.NET.Textures;
|
||||||
using Nebulix.InputSystem;
|
using Nebulix.InputSystem;
|
||||||
using Nebulix.Rendering;
|
using Nebulix.Rendering;
|
||||||
using Silk.NET.Input;
|
using Silk.NET.Input;
|
||||||
using Silk.NET.Maths;
|
|
||||||
using Silk.NET.OpenGL;
|
using Silk.NET.OpenGL;
|
||||||
using Silk.NET.Windowing;
|
using Silk.NET.Windowing;
|
||||||
using System;
|
using System;
|
||||||
|
@ -19,7 +19,6 @@ using System.Numerics;
|
||||||
// Next to do will be cleaning this up by creating a shader class and maybe even an engine class
|
// Next to do will be cleaning this up by creating a shader class and maybe even an engine class
|
||||||
// IEngine -> IEngine.Create(WindowOptions) -> return OpenGLEngine/VulkanEngine maybe?
|
// IEngine -> IEngine.Create(WindowOptions) -> return OpenGLEngine/VulkanEngine maybe?
|
||||||
|
|
||||||
using Vector3 = Silk.NET.Maths.Vector3D<float>;
|
|
||||||
|
|
||||||
public static class Program
|
public static class Program
|
||||||
{
|
{
|
||||||
|
@ -33,7 +32,7 @@ public static class Program
|
||||||
private static Camera _cam;
|
private static Camera _cam;
|
||||||
private static Vector2 _lastMousePosition;
|
private static Vector2 _lastMousePosition;
|
||||||
private static uint _vao, _vbo;
|
private static uint _vao, _vbo;
|
||||||
private static Sphere sphere;
|
private static IcoSphere sphere;
|
||||||
|
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
|
@ -141,7 +140,7 @@ public static class Program
|
||||||
|
|
||||||
|
|
||||||
// Sphere
|
// Sphere
|
||||||
sphere = new Sphere(10);
|
sphere = new IcoSphere(10);
|
||||||
sphere.CreateSphere();
|
sphere.CreateSphere();
|
||||||
_sphereShader =
|
_sphereShader =
|
||||||
new Nebulix.Rendering.Shader(_gl, "./Shaders/Sphere/sphere.vert", "./Shaders/Sphere/sphere.frag");
|
new Nebulix.Rendering.Shader(_gl, "./Shaders/Sphere/sphere.vert", "./Shaders/Sphere/sphere.frag");
|
||||||
|
@ -180,7 +179,7 @@ public static class Program
|
||||||
var difference = (float)(_window.Time * 10);
|
var difference = (float)(_window.Time * 10);
|
||||||
var modelMatrix = Matrix4x4.CreateRotationY(Maths.Convert.ToRadians(difference)) * Matrix4x4.CreateRotationX(Maths.Convert.ToRadians(difference));
|
var modelMatrix = Matrix4x4.CreateRotationY(Maths.Convert.ToRadians(difference)) * Matrix4x4.CreateRotationX(Maths.Convert.ToRadians(difference));
|
||||||
var viewMatrix = _cam.ViewMatrix;
|
var viewMatrix = _cam.ViewMatrix;
|
||||||
var projectionMatrix = Matrix4X4.CreatePerspectiveFieldOfView(Maths.Convert.ToRadians(_cam.Fov), Width / (float)Height, 0.1f, 100.0f);
|
var projectionMatrix = Matrix4x4.CreatePerspectiveFieldOfView(Maths.Convert.ToRadians(_cam.Fov), Width / (float)Height, 0.1f, 100.0f);
|
||||||
|
|
||||||
_shader.Use();
|
_shader.Use();
|
||||||
_shader.SetMatrix("modelMatrix", modelMatrix);
|
_shader.SetMatrix("modelMatrix", modelMatrix);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
using Nebulix;
|
using System.Numerics;
|
||||||
|
using Nebulix;
|
||||||
using Nebulix.Rendering;
|
using Nebulix.Rendering;
|
||||||
using Silk.NET.Maths;
|
|
||||||
using Silk.NET.OpenGL;
|
using Silk.NET.OpenGL;
|
||||||
|
|
||||||
namespace Engine_silk.NET
|
namespace Engine_silk.NET
|
||||||
|
@ -22,14 +22,14 @@ namespace Engine_silk.NET
|
||||||
public void CreateSphere()
|
public void CreateSphere()
|
||||||
{
|
{
|
||||||
// TODO: merge the individual meshes to one mesh
|
// TODO: merge the individual meshes to one mesh
|
||||||
Vector3D<float>[] directions =
|
Vector3[] directions =
|
||||||
[
|
[
|
||||||
Vector3D<float>.UnitZ, -Vector3D<float>.UnitZ,
|
Vector3.UnitZ, -Vector3.UnitZ,
|
||||||
Vector3D<float>.UnitY, -Vector3D<float>.UnitY,
|
Vector3.UnitY, -Vector3.UnitY,
|
||||||
Vector3D<float>.UnitX, -Vector3D<float>.UnitX
|
Vector3.UnitX, -Vector3.UnitX
|
||||||
];
|
];
|
||||||
|
|
||||||
List<Vector3D<float>> vertices = new();
|
List<Vector3> vertices = new();
|
||||||
List<uint> indices = new();
|
List<uint> indices = new();
|
||||||
for (int i = 0; i < directions.Length; i++)
|
for (int i = 0; i < directions.Length; i++)
|
||||||
{
|
{
|
||||||
|
@ -64,24 +64,24 @@ namespace Engine_silk.NET
|
||||||
public Mesh Mesh => _mesh;
|
public Mesh Mesh => _mesh;
|
||||||
|
|
||||||
private readonly Mesh _mesh;
|
private readonly Mesh _mesh;
|
||||||
private readonly Vector3D<float> _localX;
|
private readonly Vector3 _localX;
|
||||||
private readonly Vector3D<float> _localY;
|
private readonly Vector3 _localY;
|
||||||
|
|
||||||
private readonly Vector3D<float> _localUp;
|
private readonly Vector3 _localUp;
|
||||||
private readonly uint _resolution;
|
private readonly uint _resolution;
|
||||||
|
|
||||||
public Face(Vector3D<float> localUp, Mesh mesh, uint resolution)
|
public Face(Vector3 localUp, Mesh mesh, uint resolution)
|
||||||
{
|
{
|
||||||
_mesh = mesh;
|
_mesh = mesh;
|
||||||
_localX = new(localUp.Y, localUp.Z, localUp.X);
|
_localX = new(localUp.Y, localUp.Z, localUp.X);
|
||||||
_localY = Vector3D.Cross(localUp, _localX);
|
_localY = Vector3.Cross(localUp, _localX);
|
||||||
_localUp = localUp;
|
_localUp = localUp;
|
||||||
_resolution = resolution;
|
_resolution = resolution;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void GenerateMesh()
|
internal void GenerateMesh()
|
||||||
{
|
{
|
||||||
var vertices = new Vector3D<float>[_resolution * _resolution];
|
var vertices = new Vector3[_resolution * _resolution];
|
||||||
// _resolution - 1 because the vertices index starts at 0
|
// _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
|
// * 6 because each triangle needs 3 points and each small quad has 2 triangles 3*2 = 6
|
||||||
var indices = new uint[(_resolution - 1) * (_resolution - 1) * 6];
|
var indices = new uint[(_resolution - 1) * (_resolution - 1) * 6];
|
||||||
|
@ -93,9 +93,9 @@ namespace Engine_silk.NET
|
||||||
for (uint x = 0; x < _resolution; x++)
|
for (uint x = 0; x < _resolution; x++)
|
||||||
{
|
{
|
||||||
i = x + y * _resolution;
|
i = x + y * _resolution;
|
||||||
Vector2D<float> percent = new Vector2D<float>(x, y) / (_resolution - 1);
|
Vector2 percent = new Vector2(x, y) / (_resolution - 1);
|
||||||
// place vertex on correct position of the plane to easily calculate indices
|
// 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;
|
Vector3 vertexPosition = _localUp + (percent.X - 0.5f) * 2 * _localX + (percent.Y - 0.5f) * 2 * _localY;
|
||||||
vertices[i] = PointOnCubeToPointOnSphere(vertexPosition);
|
vertices[i] = PointOnCubeToPointOnSphere(vertexPosition);
|
||||||
|
|
||||||
if (x != _resolution - 1 && y != _resolution - 1) // we didn't reach the bottom right point yet
|
if (x != _resolution - 1 && y != _resolution - 1) // we didn't reach the bottom right point yet
|
||||||
|
@ -121,7 +121,7 @@ namespace Engine_silk.NET
|
||||||
|
|
||||||
// Smooth mapping so that the points are not clumped on the former corners of the cube
|
// Smooth mapping so that the points are not clumped on the former corners of the cube
|
||||||
// http://mathproofs.blogspot.com/2005/07/mapping-cube-to-sphere.html
|
// http://mathproofs.blogspot.com/2005/07/mapping-cube-to-sphere.html
|
||||||
private Vector3D<float> PointOnCubeToPointOnSphere(Vector3D<float> point)
|
private Vector3 PointOnCubeToPointOnSphere(Vector3 point)
|
||||||
{
|
{
|
||||||
float x2 = point.X * point.X;
|
float x2 = point.X * point.X;
|
||||||
float y2 = point.Y * point.Y;
|
float y2 = point.Y * point.Y;
|
||||||
|
@ -129,7 +129,7 @@ namespace Engine_silk.NET
|
||||||
float newX = point.X * MathF.Sqrt(1 - y2 / 2 - z2 / 2 + (y2 * z2) / 3);
|
float newX = point.X * MathF.Sqrt(1 - y2 / 2 - z2 / 2 + (y2 * z2) / 3);
|
||||||
float newY = point.Y * MathF.Sqrt(1 - z2 / 2 - x2 / 2 + (z2 * x2) / 3);
|
float newY = point.Y * MathF.Sqrt(1 - z2 / 2 - x2 / 2 + (z2 * x2) / 3);
|
||||||
float newZ = point.Z * MathF.Sqrt(1 - x2 / 2 - y2 / 2 + (x2 * y2) / 3);
|
float newZ = point.Z * MathF.Sqrt(1 - x2 / 2 - y2 / 2 + (x2 * y2) / 3);
|
||||||
return new Vector3D<float>(newX, newY, newZ);
|
return new Vector3(newX, newY, newZ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user