Wireframe OBB + VertexArray
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 7m47s

This commit is contained in:
2024-10-31 12:23:27 -04:00
parent 779f212a29
commit 82669b43bc
6 changed files with 265 additions and 14 deletions

View File

@@ -22,7 +22,7 @@ CPMAddPackage(
CPMAddPackage(
NAME J3ML
URL https://git.redacted.cc/josh/j3ml/archive/Release-3.3.zip
URL https://git.redacted.cc/josh/j3ml/archive/Release-3.4.zip
)
CPMAddPackage(

View File

@@ -335,7 +335,7 @@ namespace JGL {
/// @param A The start-point of the line segment.
/// @param B The end-point of the line segment.
/// @param thickness The line-width to draw the line segment with.
void DrawLine(const Color4 &color, const Vector3 &A, const Vector3 &B, float thickness = 1.f);
void DrawLine(const Color4& color, const Vector3& A, const Vector3& B, float thickness = 1.f);
/// Draws a smooth, curved line segment between two control points, with the curve controlled by the two inner points.
@@ -355,7 +355,7 @@ namespace JGL {
/// @param position The point in 3D space at which to draw the Icosahedron.
/// @param radius The size to draw the Icosahedron at.
/// @param thickness The line-width to draw the Icosahedron outline with.
void WireframeIcosahedron(const Color4 &color, const Vector3 &position, float radius, float thickness = 1.f);
void WireframeIcosahedron(const Color4& color, const Vector3& position, float radius, float thickness = 1.f);
/// Draws a solid Icosahedron in 3D space.

View File

@@ -0,0 +1,82 @@
#pragma once
#include <vector>
#include <JGL/types/VRamList.h>
#include <J3ML/LinearAlgebra/Vector3.hpp>
#include <J3ML/Geometry/Triangle.hpp>
#include <J3ML/Geometry/Sphere.hpp>
#include <J3ML/Geometry/AABB.hpp>
#include <J3ML/Geometry/OBB.hpp>
namespace JGL {
/// A point that is part of an object in 3D space.
typedef Vector3 Vertex;
/// A direction vector which describes which way a triangle is facing.
typedef Vector3 Normal;
/// 2D positions that describe how a texture is to be wrapped around a 3D object.
typedef Vector2 TextureCoordinate;
/// A 3D model.
class VertexArray;
}
class JGL::VertexArray {
private:
Sphere me_sphere;
OBB me_obb;
protected:
virtual void CreateMESphere();
virtual void CreateMEOBB();
protected:
VRamList vertices;
VRamList indices;
VRamList normals;
VRamList texture_coordinates;
protected:
/** Intended for low quality version in system memory for calculations to be done on the CPU.
* In some scenarios like complex collision, You'd have to loop over every vertex.
* It makes more sense for performance and memory reasons to store a *much* lower quality version in system memory.
*/
std::vector<Vertex> local_vertices;
std::vector<unsigned int> local_indices;
std::vector<TextureCoordinate> local_texture_coordinates;
std::vector<Normal> local_normals;
public:
/** Don't use these for anything other than drawing because the GPU is gonna spin during read-back */
[[nodiscard]] VRamList GetVertices() const;
[[nodiscard]] VRamList GetIndices() const;
[[nodiscard]] VRamList GetNormals() const;
[[nodiscard]] VRamList GetTextureCoordinates() const;
/** These are for cpu side calculations */
[[nodiscard]] std::vector<Vertex> GetLocalVertices() const;
[[nodiscard]] std::vector<unsigned int> GetLocalIndices() const;
[[nodiscard]] std::vector<TextureCoordinate> GetLocalTextureCoordinates() const;
[[nodiscard]] std::vector<Normal> GetLocalNormals() const;
public:
/// Provides the minimally enclosing bounding sphere of the vertex array given information from the instance.
/// @param scale The scale of the instance.
/// @param translate_part The center of the sphere would be shifted in 3D space by this. Primarily for world space.
[[nodiscard]] Sphere GetMESphere(const Vector3& scale = Vector3::One, const Vector3& translate_part = Vector3::Zero) const;
/// Provides the minimally enclosing bounding sphere of the vertex array given information from the instance.
/// @param instance_matrix A Matrix4x4 which contains scale, rotation, and translation.
/// @param translate Whether or not to translate to world space by the translate part of the Matrix.
[[nodiscard]] Sphere GetMESphere(const Matrix4x4& instance_matrix, bool translate = false) const;
/// Provides the minimally enclosing oriented bounding box of the vertex array given information from the instance.
/// @param rotation_matrix A Matrix3x3 representing rotation in 3D space.
/// @param scale The scale of the instance.
/// @param translate_part The center of the box would be shifted in 3D space by this. Primarily for world space.
[[nodiscard]] OBB GetMEOBB(const Matrix3x3& rotation_matrix, const Vector3& scale = Vector3::One, const Vector3& translate_part = Vector3::Zero) const;
/// Provides the minimally enclosing oriented bounding box of the vertex array given information from the instance.
/// @param instance_matrix A Matrix4x4 which contains scale, rotation, and translation.
/// @param translate Whether or not to translate to world space by the translate part of the Matrix.
[[nodiscard]] OBB GetMEOBB(const Matrix4x4& instance_matrix, bool translate = false) const;
/// Provides the minimally enclosing axis-aligned bounding box of the vertex array given information from the instance.
/// @param rotation_matrix A Matrix3x3 representing rotation in 3D space.
/// @param scale The scale of the instance.
/// @param translate_part The center of the box would be shifted in 3D space by this. Primarily for world space.
[[nodiscard]] AABB GetMEAABB(const Matrix3x3& rotation_matrix, const Vector3& scale = Vector3::One, const Vector3& translate_part = Vector3::Zero) const;
[[nodiscard]] AABB GetMEAABB(const Matrix4x4& instance_matrix, bool translate = false) const;
};

View File

@@ -153,7 +153,7 @@ public:
//J3D::ChangeFOV(fov);
sprite_radians += 0.005;
textAngle.y += .05f;
textAngle.y += (5.f * delta_time);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
@@ -161,18 +161,18 @@ public:
camera->render();
// All 3D elements of the scene and JGL elements *must* be rendered before the 2D stuff
/* if rendering to screen space directly. */
J3D::Begin();
J3D::DrawLine(Colors::Red, {-0.33,-0.125,1}, {-1,-0.125,1});
J3D::DrawLine(Colors::Red, {-0.33,-0.125,1}, {-0.33,0.25,1});
J3D::DrawString(Colors::Red, "JGL Sample Text", {-0.33, -0.1, 1.0f}, 1.f, 32, FreeSans, textAngle, true);
J3D::FillSphere(Colors::Green, {0,0,0.5f}, 0.25f, 10, 10);
//J3D::FillSphere(Colors::Green, {0,0,0.5f}, 0.25f, 10, 10);
//J3D::FillAABB(Colors::Whites::AliceBlue, {0,0,0.5f}, {0.1f, 0.05f, 0.1f});
J3D::WireframeAABB(Colors::Gray, {0,0,0.5f}, {0.11f, 0.06f, 0.11f});
//J3D::WireframeAABB(Colors::Gray, {0,0,0.5f}, {0.11f, 0.06f, 0.11f});
J3D::WireframeOBB(Colors::Red, {0, 0, 1.5f}, {0.11f, 0.06f, 0.11f}, {0,textAngle.y, 0});
J3D::DrawCubicBezierCurve(Colors::Blue, {0,0,0.3}, {0,0,0.5}, {0.2,0,0.3}, {0.2, 0.3, 0.1}, 30);
//J3D::DrawCubicBezierCurve(Colors::Blue, {0,0,0.3}, {0,0,0.5}, {0.2,0,0.3}, {0.2, 0.3, 0.1}, 30);
//J3D::WireframeIcosahedron(Colors::Green, {0,0,0.5f}, 0.125f, 1.f);
J3D::End();

View File

@@ -1230,7 +1230,7 @@ namespace JGL {
glColor4fv(baseColor);
}
void J3D::WireframeAABB(const Color4 &color, const Vector3 &pos, const Vector3 &radii, float thickness) {
void J3D::WireframeAABB(const Color4& color, const Vector3& pos, const Vector3& radii, float thickness) {
if (!inJ3D)
Logger::Error("Drawing J3D element before J3D begin.");
@@ -1356,11 +1356,11 @@ namespace JGL {
FillAABB(color, aabb.Centroid(), aabb.Size());
}
void J3D::WireframeSphere(const Color4 &color, const Sphere &sphere, float thickness, uint sectors, uint stacks) {
void J3D::WireframeSphere(const Color4& color, const Sphere& sphere, float thickness, uint sectors, uint stacks) {
WireframeSphere(color, sphere.Centroid(), sphere.Radius, thickness, sectors, stacks);
}
void J3D::FillSphere(const Color4 &color, const Vector3 &position, float radius, uint sectors, uint stacks) {
void J3D::FillSphere(const Color4 &color, const Vector3& position, float radius, uint sectors, uint stacks) {
if (!inJ3D)
Logger::Error("Drawing J3D element before J3D begin.");
@@ -1397,7 +1397,6 @@ namespace JGL {
}
glColor4ubv(color.ptr());
//glBindBuffer(GL_ARRAY_BUFFER, vertices.size());
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), vertices.data());
glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size()); // TODO: Make it render correctingly!
glColor4fv(baseColor);
@@ -1407,6 +1406,7 @@ namespace JGL {
WireframeAABB(color, aabb.Centroid(), aabb.Size(), thickness);
}
// Why is this here?
float ComputeBinomial(int n, int k)
{
float value = 1.f;
@@ -1420,8 +1420,36 @@ namespace JGL {
return value;
}
void J3D::DrawCubicBezierCurve(const Color4 &color, const Vector3 &controlA, const Vector3 &pointA,
const Vector3 &pointB, const Vector3 &controlB, int subdivisions, float thickness) {
void J3D::WireframeOBB(const Color4& color, const J3ML::Geometry::OBB& obb, float thickness) {
std::array<Vector3, 8> corner_points;
obb.GetCornerPoints(corner_points.data());
std::array<GLuint, 24> indices =
{
0, 1, 1, 2, 2, 3, 3, 0,
4, 5, 5, 6, 6, 7, 7, 4,
0, 4, 1, 5, 2, 6, 3, 7
};
glPushMatrix();
glTranslatef(obb.pos.x, obb.pos.y, obb.pos.z);
glLineWidth(thickness);
glColor4ubv(color.ptr());
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), corner_points.data());
glDrawElements(GL_LINES, indices.size(), GL_UNSIGNED_INT, indices.data());
glColor4fv(baseColor);
glPopMatrix();
}
void J3D::WireframeOBB(const Color4& color, const J3ML::LinearAlgebra::Vector3& position, const J3ML::LinearAlgebra::Vector3& radii,
const J3ML::LinearAlgebra::EulerAngle& orientation, float thickness) {
Matrix3x3 rotation = orientation.ToQuaternion().ToMatrix3x3();
WireframeOBB(color, OBB(position, radii, rotation * Vector3::UnitX, rotation * Vector3::UnitY, rotation * Vector3::UnitZ), thickness);
}
void J3D::DrawCubicBezierCurve(const Color4& color, const Vector3& controlA, const Vector3& pointA,
const Vector3& pointB, const Vector3& controlB, int subdivisions, float thickness) {
Vector3 last = controlA;
const Vector3& first = controlB;
for (int i = 0; i < subdivisions; ++i)

141
src/types/VertexArray.cpp Normal file
View File

@@ -0,0 +1,141 @@
#include <JGL/types/VertexArray.h>
using namespace JGL;
VRamList VertexArray::GetVertices() const {
return vertices;
}
VRamList VertexArray::GetIndices() const {
return indices;
}
JGL::VRamList VertexArray::GetNormals() const {
return normals;
}
VRamList VertexArray::GetTextureCoordinates() const {
return texture_coordinates;
}
std::vector<Vertex> VertexArray::GetLocalVertices() const {
return local_vertices;
}
std::vector<unsigned int> VertexArray::GetLocalIndices() const {
return local_indices;
}
std::vector<TextureCoordinate> VertexArray::GetLocalTextureCoordinates() const {
return local_texture_coordinates;
}
std::vector<Normal> VertexArray::GetLocalNormals() const {
return local_normals;
}
Sphere VertexArray::GetMESphere(const Vector3& scale, const Vector3& translate_part) const {
if (scale == Vector3::One)
return { me_sphere.Position + translate_part, me_sphere.Radius };
float scale_factor = 0;
if (scale.x > scale_factor)
scale_factor = scale.x;
if (scale.y > scale_factor)
scale_factor = scale.y;
if (scale.z > scale_factor)
scale_factor = scale.z;
return { me_sphere.Position + translate_part, me_sphere.Radius * scale_factor };
}
Sphere VertexArray::GetMESphere(const Matrix4x4& instance_matrix, bool translate) const {
Vector3 scale = instance_matrix.GetScale();
Vector3 origin = Vector3::Zero;
if (translate)
origin = instance_matrix.GetTranslatePart();
return GetMESphere(scale, origin);
}
void VertexArray::CreateMESphere() {
Sphere result = {Vector3::Zero, 0};
Vector3 minimum = {std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() };
Vector3 maximum = { std::numeric_limits<float>::lowest(), std::numeric_limits<float>::lowest(), std::numeric_limits<float>::lowest()};
for (const auto& vertex : local_vertices) {
if (vertex.x < minimum.x)
minimum.x = vertex.x;
if (vertex.x > maximum.x)
maximum.x = vertex.x;
if (vertex.y < minimum.y)
minimum.y = vertex.y;
if (vertex.y > maximum.y)
maximum.y = vertex.y;
if (vertex.z < minimum.z)
minimum.z = vertex.z;
if (vertex.z > maximum.z)
maximum.z = vertex.z;
}
result.Position = (minimum + maximum) * 0.5f;
for (const auto& vertex : local_vertices) {
float distance_squared = Vector3::DistanceSquared(result.Position, vertex);
if (distance_squared > result.Radius)
result.Radius = distance_squared;
}
result.Radius = std::sqrt(result.Radius);
me_sphere = result;
}
void VertexArray::CreateMEOBB() {
Vector3 minimum(std::numeric_limits<float>::max());
Vector3 maximum (std::numeric_limits<float>::min());
for (const auto& vertex : local_vertices) {
if (vertex.x < minimum.x)
minimum.x = vertex.x;
if (vertex.x > maximum.x)
maximum.x = vertex.x;
if (vertex.y < minimum.y)
minimum.y = vertex.y;
if (vertex.y > maximum.y)
maximum.y = vertex.y;
if (vertex.z < minimum.z)
minimum.z = vertex.z;
if (vertex.z > maximum.z)
maximum.z = vertex.z;
}
Vector3 position = (minimum + maximum) * 0.5f;
Vector3 half_extents = (maximum - minimum) * 0.5f;
me_obb = { position, half_extents, Vector3::UnitX, Vector3::UnitY, Vector3::UnitZ };
}
OBB VertexArray::GetMEOBB(const Matrix3x3& rotation_matrix, const Vector3& scale, const Vector3& translate_part) const {
Vector3 half_extents = me_obb.r.Mul(scale);
Vector3 axis0 = rotation_matrix * me_obb.axis[0];
Vector3 axis1 = rotation_matrix * me_obb.axis[1];
Vector3 axis2 = rotation_matrix * me_obb.axis[2];
Vector3 position = me_obb.pos + translate_part;
return { position, half_extents, axis0, axis1, axis2 };
}
OBB VertexArray::GetMEOBB(const Matrix4x4& instance_matrix, bool translate) const {
return GetMEOBB(instance_matrix.GetRotatePart(), instance_matrix.GetScale(), translate ? instance_matrix.GetTranslatePart() : Vector3::Zero);
}
AABB VertexArray::GetMEAABB(const Matrix3x3& rotation_matrix, const Vector3& scale, const Vector3& translate_part) const {
/* kind-of a cheat. It's faster to calculate the oriented bounding box and then put the axis-aligned one around that
* than to loop over the whole model like an idiot. You gain back all the speed with the simplicity of the physics anyways. - Redacted */
return GetMEOBB(rotation_matrix, scale, translate_part).MinimalEnclosingAABB();
}
AABB VertexArray::GetMEAABB(const Matrix4x4& instance_matrix, bool translate) const {
return GetMEAABB(instance_matrix.GetRotatePart(), instance_matrix.GetScale(), translate ? instance_matrix.GetTranslatePart() : Vector3::Zero);
}