Wireframe OBB + VertexArray
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 7m47s
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 7m47s
This commit is contained in:
@@ -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(
|
||||
|
@@ -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.
|
||||
|
82
include/JGL/types/VertexArray.h
Normal file
82
include/JGL/types/VertexArray.h
Normal 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;
|
||||
};
|
||||
|
10
main.cpp
10
main.cpp
@@ -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();
|
||||
|
40
src/JGL.cpp
40
src/JGL.cpp
@@ -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
141
src/types/VertexArray.cpp
Normal 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);
|
||||
}
|
Reference in New Issue
Block a user