Sending up work
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m37s
Build Docs With Doxygen / Explore-Gitea-Actions (push) Successful in 29s

This commit is contained in:
2024-10-23 14:16:41 -04:00
parent 192b93ded4
commit bf794ce092
9 changed files with 266 additions and 12 deletions

View File

@@ -1,4 +1,4 @@
// @file GJK.hpp
/// @file GJK.hpp
/// Implementation of the Gilbert-Johnson-Keerthi (GJK) convex polyhedron intersection test
#pragma once

View File

@@ -0,0 +1,17 @@
/// Josh's 3D Math Library
/// A C++20 Library for 3D Math, Computer Graphics, and Scientific Computing.
/// Developed and Maintained by Josh O'Leary @ Redacted Software.
/// Special Thanks to William Tomasine II and Maxine Hayes.
/// (c) 2024 Redacted Software
/// This work is dedicated to the public domain.
/// @file Parabola.hpp
/// @desc Algorithm for calculating a parabolic curve to be used in instantaneous bullet raycasting.
/// @edit 2024-10-22
#pragma once
namespace J3ML
{
}

View File

@@ -0,0 +1,18 @@
/// Josh's 3D Math Library
/// A C++20 Library for 3D Math, Computer Graphics, and Scientific Computing.
/// Developed and Maintained by Josh O'Leary @ Redacted Software.
/// Special Thanks to William Tomasine II and Maxine Hayes.
/// (c) 2024 Redacted Software
/// This work is dedicated to the public domain.
/// @file Parabola.hpp
/// @desc Algorithm for calculating a parabolic curve to be used in instantaneous bullet raycasting.
/// @edit 2024-10-22
#pragma once
namespace J3ML
{
/// @see class Polygon::Triangulate for current implementation.
}

View File

@@ -0,0 +1,109 @@
/// Josh's 3D Math Library
/// A C++20 Library for 3D Math, Computer Graphics, and Scientific Computing.
/// Developed and Maintained by Josh O'Leary @ Redacted Software.
/// Special Thanks to William Tomasine II and Maxine Hayes.
/// (c) 2024 Redacted Software
/// This work is dedicated to the public domain.
/// @file Icosahedron.hpp
/// @desc Icosahedron class implementation, borrowed from http://www.songho.ca/opengl/gl_sphere.html#icosphere
/// @edit 2024-10-22
/** Polyhedron with 12 vertices, 30 edges, and 20 faces (triangles) for OpenGL
If the radius is r, then the length of the edge is (r / sin(2pi/5))
Vertices of icosahedron are constructed with spherical coords by aligning
the north pole to (0,0,r) and the south pole to (0,0,-r). Other 10 vertices
are computed by rotating 72 degrees along y-axis at the elevation angle
+/- 26.565 (=arctan(1/2)).
The unwrapped (paper model) of icosahedron and texture map look like this:
// (S,0) 3S 5S 7S 9S
// /\ /\ /\ /\ /\ : 1st row (5 triangles) //
// /__\/__\/__\/__\/__\ //
// T \ /\ /\ /\ /\ /\ : 2nd row (10 triangles) //
// \/__\/__\/__\/__\/__\ //
// 2T \ /\ /\ /\ /\ / : 3rd row (5 triangles) //
// \/ \/ \/ \/ \/ //
// 2S 4S 6S 8S (10S,3T)
// where S = 186/2048 = 0.0908203
// T = 322/1024 = 0.3144531
// If a texture size is 2048x1024, S=186, T=322
AUTHOR: Song Ho Ahn (song.ahn@gmail.com)
*/
#include <vector>
#include "Color4.hpp"
#pragma once
namespace J3ML
{
class Icosahedron
{
public:
float radius;
float edgeLength;
Icosahedron(float radius = 1.0f);
float Radius() const { return radius; }
void Radius(float new_radius) {radius = new_radius;}
float EdgeLength() const { return edgeLength;}
void EdgeLength(float new_edge_length) { edgeLength = new_edge_length;}
// for vertex data
unsigned int VertexCount() const;
unsigned int NormalCount() const;
unsigned int TexCoordCount() const;
unsigned int IndexCount() const;
unsigned int LineIndexCount() const;
unsigned int TriangleCount() const;
unsigned int VertexSize() const;
unsigned int NormalSize() const;
unsigned int TexCoordSize() const;
unsigned int IndexSize() const;
unsigned int LineIndexSize() const;
const float* Vertices() const;
const float* Normals() const;
const float* TexCoords() const;
const unsigned int* Indices() const;
const unsigned int* LineIndices() const;
// for interleaved vertices: V/N/T
unsigned int InterleavedVertexCount() const;
unsigned int InterleavedVertexSize() const;
int InterleavedStride() const;
const float* InterleavedVertices() const;
// draw in VertexArray mode
void draw() const;
void drawLines(const Color4& lineColor) const;
void drawWithLines(const Color4& lineColor) const;
protected:
private:
// static functions
static void computeFaceNormal(float v1[3], float v2[3], float v3[3], float n[3]);
// member functions
void updateRadius();
std::vector<float> computeVertices();
void buildVertices();
void buildInterleavedVertices();
void addVertices(float v1[3], float v2[3], float v3[3]);
void addNormals(float n1[3], float n2[3], float n3[3]);
void addTexCoords(float t1[2], float t2[2], float t3[2]);
void addIndices(unsigned int i1, unsigned int i2, unsigned int i3);
void addLineIndices(unsigned int indexFrom);
// member vars
//float radius;
//float edgeLength;
std::vector<float> vertices;
std::vector<float> normals;
std::vector<float> texCoords;
std::vector<unsigned int> indices;
std::vector<unsigned int> lineIndices;
};
}

View File

@@ -1,3 +1,14 @@
/// Josh's 3D Math Library
/// A C++20 Library for 3D Math, Computer Graphics, and Scientific Computing.
/// Developed and Maintained by Josh O'Leary @ Redacted Software.
/// Special Thanks to William Tomasine II and Maxine Hayes.
/// (c) 2024 Redacted Software
/// This work is dedicated to the public domain.
/// @file LineSegment2D.hpp
/// @desc A 2D representation of a finite line between two points.
/// @edit 2024-10-22
#pragma once
#include <J3ML/LinearAlgebra/Vector2.hpp>

View File

@@ -114,8 +114,10 @@ namespace J3ML::Geometry
[[nodiscard]] bool Contains(const Vector3& point, float epsilon) const;
[[nodiscard]] bool Contains(const LineSegment& lineseg) const;
TriangleMesh GenerateUVSphere() const;
TriangleMesh GenerateUVSphere(int subdivisions = 10.f) const;
TriangleMesh GenerateIcososphere() const;
TriangleMesh GenerateCubesphere() const;
void ProjectToAxis(const Vector3 &direction, float &outMin, float &outMax) const;
};

View File

@@ -15,15 +15,17 @@ namespace J3ML::Geometry
TriangleMesh(int expectedPolygonCount = 1000);
public:
//std::vector<Vector3> Vertices;
//std::vector<Vector3> Normals;
//std::vector<Vector3> UVs;
//std::vector<u64> Indices;
std::vector<Vector3> Vertices;
std::vector<Vector3> Normals;
std::vector<Vector3> UVs;
std::vector<u64> Indices;
std::vector<float> GenerateVertexList();
//std::vector<Triangle> GenerateTriangleList();
public:
private:
std::vector<float> cachedVertexList;
//std::vector<Triangle> cachedTriangleList;
};

View File

@@ -0,0 +1,6 @@
#include <J3ML/Geometry/Icosahedron.hpp>
namespace J3ML
{
}

View File

@@ -9,18 +9,107 @@ namespace J3ML::Geometry
return Contains(lineseg.A) && Contains(lineseg.B);
}
TriangleMesh Sphere::GenerateUVSphere() const
TriangleMesh Sphere::GenerateUVSphere(int subdivisions) const
{
// TODO: Implement this later
return TriangleMesh();
// http://www.songho.ca/opengl/gl_sphere.html
TriangleMesh mesh;
float x, y, z, xy; // Vertex Position
float nx, ny, nz, lengthInv = 1.f / Radius; // Vertex Normal
float s, t; // Vertex TexCoord
int sectorCount = subdivisions;
int stackCount = subdivisions;
float sectorStep = 2.f * Math::Pi / sectorCount;
float stackStep = Math::Pi / stackCount;
float sectorAngle, stackAngle;
for (int i = 0; i <= stackCount; ++i)
{
stackAngle = Math::Pi / 2.f - i * stackStep; // starting from pi/2 to -pi/2
xy = Radius * Math::Cos(stackAngle); // r * cos(u)
z = Radius * Math::Sin(stackAngle); // r * sin(u)
// add (sectorCount + 1) vertices per stack
// first and last vertices have same position and normal, but different tex coords
for (int j = 0; j <= sectorCount; ++j)
{
sectorAngle = j * sectorStep; // starting from 0 to 2pi
// vertex position (x, y, z)
x = xy * Math::Cos(sectorAngle);
y = xy * Math::Sin(sectorAngle);
Vector3 vertex = {x, y, z};
mesh.Vertices.push_back(vertex);
// normalized vertex normal (nx, ny, nz)
nx = x * lengthInv;
ny = y * lengthInv;
nz = z * lengthInv;
Vector3 normal = {nx, ny, nz};
mesh.Normals.push_back(normal);
// vertex tex coord (s, t) range between [0, 1]
s = (float)j / sectorCount;
t = (float)i / stackCount;
Vector2 TexCoords = {s, t};
mesh.UVs.push_back(normal);
}
}
return mesh;
}
TriangleMesh Sphere::GenerateIcososphere() const
{
// TODO: Implement this later
return TriangleMesh();
// Generate 12 vertices of an icosahedron for a given radius.
const float h_angle = Math::Pi / 180.f * 72.f; // 72 degree = 360 / 5;
const float v_angle = Math::Atan(1.f / 2.f);
TriangleMesh mesh;
int i1, i2;
float z, xy;
float hAngle1 = -Math::Pi / 2.f - h_angle / 2.f;
float hAngle2 = -Math::Pi / 2;
// the first top vertex at (0,0,r)
Vector3 top_vertex = {0, 0, Radius};
// compute 10 vertices at 1st and 2nd rows
for (int i = 1; i <= 5; ++i)
{
i1 = i * 3; // index for 1st row
i2 = (i + 5) * 3; // index for 2nd row
z = Radius * Math::Sin(v_angle); // elevation
xy = Radius * Math::Cos(v_angle); // length on XY plane
Vector3 vert_0 = {xy * Math::Cos(hAngle1), xy * Math::Sin(hAngle1), z};
Vector3 vert_1 = {xy * Math::Cos(hAngle2), xy * Math::Sin(hAngle2), -z};
// next horizontal angles
hAngle1 += h_angle;
hAngle2 += h_angle;
}
// the last bottom vertex at (0, 0, -r)
i1 = 11 * 3;
Vector3 last_vertex = {0,0, -Radius};
return mesh;
}
void Sphere::ProjectToAxis(const Vector3 &direction, float &outMin, float &outMax) const
{
float d = Vector3::Dot(direction, Position);