mirror of
https://github.com/orange-cpp/omath.git
synced 2026-04-19 02:43:27 +00:00
Compare commits
8 Commits
v5.0.0
...
3080faeaa9
| Author | SHA1 | Date | |
|---|---|---|---|
| 3080faeaa9 | |||
| af36c909a4 | |||
| 1041256fac | |||
| 88012e2524 | |||
| 4561dbe0e7 | |||
| b50f759675 | |||
| 85b672fdf3 | |||
| 360734f252 |
4
.idea/editor.xml
generated
4
.idea/editor.xml
generated
@@ -17,7 +17,7 @@
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooManyArgs/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCStyleCast/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCVQualifierCanNotBeAppliedToReference/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassCanBeFinal/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassCanBeFinal/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassIsIncomplete/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeedsConstructorBecauseOfUninitializedMember/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
@@ -110,7 +110,7 @@
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLambdaCaptureNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMayBeConst/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableWithNonTrivialDtorIsNeverUsed/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableWithNonTrivialDtorIsNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLongFloat/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeConst/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeStatic/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
|
||||
@@ -149,10 +149,13 @@ int main()
|
||||
// Check if context is valid using standard GL
|
||||
const GLubyte* renderer = glGetString(GL_RENDERER);
|
||||
const GLubyte* version = glGetString(GL_VERSION);
|
||||
if (renderer && version) {
|
||||
if (renderer && version)
|
||||
{
|
||||
std::cout << "Renderer: " << renderer << "\n";
|
||||
std::cout << "OpenGL version supported: " << version << "\n";
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Failed to get GL_RENDERER or GL_VERSION. Context might be invalid.\n";
|
||||
}
|
||||
|
||||
@@ -162,11 +165,14 @@ int main()
|
||||
if (glewErr != GLEW_OK)
|
||||
{
|
||||
// Ignore NO_GLX_DISPLAY if we have a valid context
|
||||
if (glewErr == GLEW_ERROR_NO_GLX_DISPLAY && renderer) {
|
||||
std::cerr << "GLEW warning: " << glewGetErrorString(glewErr) << " (Ignored because context seems valid)\n";
|
||||
} else {
|
||||
if (glewErr == GLEW_ERROR_NO_GLX_DISPLAY && renderer)
|
||||
{
|
||||
std::cerr << "GLEW warning: " << glewGetErrorString(glewErr) << " (Ignored because context seems valid)\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Failed to initialize GLEW: " << reinterpret_cast<const char*>(glewGetErrorString(glewErr))
|
||||
<< "\n";
|
||||
<< "\n";
|
||||
glfwTerminate();
|
||||
return -1;
|
||||
}
|
||||
@@ -300,11 +306,65 @@ int main()
|
||||
|
||||
static float old_frame_time = glfwGetTime();
|
||||
|
||||
float lastX = 640.0f / 2.0f;
|
||||
float lastY = 480.0f / 2.0f;
|
||||
bool firstMouse = true;
|
||||
bool mouse_capture = false;
|
||||
float mouseSensitivity = 0.1f;
|
||||
// ---------- Main loop ----------
|
||||
static double old_mouse_time = glfwGetTime();
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
glfwPollEvents();
|
||||
omath::Vector3<float> move_dir;
|
||||
if (glfwGetKey(window, GLFW_KEY_W))
|
||||
move_dir += camera.get_forward();
|
||||
|
||||
if (glfwGetKey(window, GLFW_KEY_A))
|
||||
move_dir -= camera.get_right();
|
||||
|
||||
if (glfwGetKey(window, GLFW_KEY_S))
|
||||
move_dir -= camera.get_forward();
|
||||
|
||||
if (glfwGetKey(window, GLFW_KEY_D))
|
||||
move_dir += camera.get_right();
|
||||
|
||||
if (glfwGetKey(window, GLFW_KEY_SPACE))
|
||||
move_dir += camera.get_up();
|
||||
|
||||
if (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL))
|
||||
move_dir -= camera.get_up();
|
||||
|
||||
|
||||
auto delta = glfwGetTime() - old_mouse_time;
|
||||
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) && delta > 0.4)
|
||||
{
|
||||
old_mouse_time = glfwGetTime();
|
||||
mouse_capture = !mouse_capture;
|
||||
|
||||
glfwSetInputMode(window, GLFW_CURSOR, mouse_capture ? GLFW_CURSOR_CAPTURED : GLFW_CURSOR_NORMAL);
|
||||
}
|
||||
if (mouse_capture)
|
||||
{
|
||||
int x, y;
|
||||
glfwGetWindowSize(window, &x, &y);
|
||||
|
||||
camera.set_origin(camera.get_origin() + (move_dir.normalized() * 0.4f));
|
||||
|
||||
double xpos, ypos;
|
||||
glfwGetCursorPos(window, &xpos, &ypos);
|
||||
float xoffset = (float)xpos - x / 2.f;
|
||||
float yoffset = y / 2.f - ypos ; // reversed: y-coordinates go bottom->top for pitch
|
||||
|
||||
xoffset *= mouseSensitivity;
|
||||
yoffset *= mouseSensitivity;
|
||||
|
||||
auto new_angles = camera.get_view_angles();
|
||||
new_angles.pitch += decltype(new_angles.pitch)::from_degrees(yoffset);
|
||||
new_angles.yaw -= decltype(new_angles.yaw)::from_degrees(xoffset);
|
||||
camera.set_view_angles(new_angles);
|
||||
glfwSetCursorPos(window, x / 2., y / 2);
|
||||
}
|
||||
float currentTime = glfwGetTime();
|
||||
float deltaTime = currentTime - old_frame_time;
|
||||
old_frame_time = currentTime;
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
|
||||
namespace omath::collision
|
||||
{
|
||||
template<class V>
|
||||
concept EpaVector = requires(const V& a, const V& b, float s) {
|
||||
template<class V, class FloatingType>
|
||||
concept EpaVector = requires(const V& a, const V& b, FloatingType s) {
|
||||
{ a - b } -> std::same_as<V>;
|
||||
{ a.cross(b) } -> std::same_as<V>;
|
||||
{ a.dot(b) } -> std::same_as<float>;
|
||||
{ a.dot(b) } -> std::same_as<FloatingType>;
|
||||
{ -a } -> std::same_as<V>;
|
||||
{ a * s } -> std::same_as<V>;
|
||||
{ a / s } -> std::same_as<V>;
|
||||
@@ -28,13 +28,18 @@ namespace omath::collision
|
||||
{
|
||||
public:
|
||||
using VectorType = ColliderInterfaceType::VectorType;
|
||||
static_assert(EpaVector<VectorType>, "VertexType must satisfy EpaVector concept");
|
||||
static_assert(EpaVector<VectorType, typename VectorType::ContainedType>,
|
||||
"VertexType must satisfy EpaVector concept");
|
||||
|
||||
private:
|
||||
using FloatingType = VectorType::ContainedType;
|
||||
|
||||
public:
|
||||
struct Result final
|
||||
{
|
||||
VectorType normal{}; // from A to B
|
||||
VectorType penetration_vector;
|
||||
float depth{0.0f};
|
||||
FloatingType depth{0.0};
|
||||
int iterations{0};
|
||||
int num_vertices{0};
|
||||
int num_faces{0};
|
||||
@@ -43,7 +48,7 @@ namespace omath::collision
|
||||
struct Params final
|
||||
{
|
||||
int max_iterations{64};
|
||||
float tolerance{1e-4f}; // absolute tolerance on distance growth
|
||||
FloatingType tolerance{1e-4}; // absolute tolerance on distance growth
|
||||
};
|
||||
// Precondition: simplex.size()==4 and contains the origin.
|
||||
[[nodiscard]]
|
||||
@@ -75,13 +80,13 @@ namespace omath::collision
|
||||
if (heap.empty())
|
||||
break;
|
||||
|
||||
//FIXME: STORE REF VALUE, DO NOT USE
|
||||
// AFTER IF STATEMENT BLOCK
|
||||
// FIXME: STORE REF VALUE, DO NOT USE
|
||||
// AFTER IF STATEMENT BLOCK
|
||||
const Face& face = faces[heap.top().idx];
|
||||
|
||||
// Get the furthest point in face normal direction
|
||||
const VectorType p = support_point(a, b, face.n);
|
||||
const float p_dist = face.n.dot(p);
|
||||
const auto p_dist = face.n.dot(p);
|
||||
|
||||
// Converged if we can’t push the face closer than tolerance
|
||||
if (p_dist - face.d <= params.tolerance)
|
||||
@@ -136,7 +141,7 @@ namespace omath::collision
|
||||
{
|
||||
int i0, i1, i2;
|
||||
VectorType n; // unit outward normal
|
||||
float d; // n · v0 (>=0 ideally because origin is inside)
|
||||
FloatingType d; // n · v0 (>=0 ideally because origin is inside)
|
||||
};
|
||||
|
||||
struct Edge final
|
||||
@@ -146,7 +151,7 @@ namespace omath::collision
|
||||
|
||||
struct HeapItem final
|
||||
{
|
||||
float d;
|
||||
FloatingType d;
|
||||
int idx;
|
||||
};
|
||||
struct HeapCmp final
|
||||
@@ -178,7 +183,7 @@ namespace omath::collision
|
||||
static bool visible_from(const Face& f, const VectorType& p)
|
||||
{
|
||||
// positive if p is in front of the face
|
||||
return f.n.dot(p) - f.d > 1e-7f;
|
||||
return f.n.dot(p) - f.d > static_cast<FloatingType>(1e-7);
|
||||
}
|
||||
|
||||
static void add_edge_boundary(std::pmr::vector<Edge>& boundary, int a, int b)
|
||||
@@ -198,19 +203,20 @@ namespace omath::collision
|
||||
const VectorType& a1 = vertexes[i1];
|
||||
const VectorType& a2 = vertexes[i2];
|
||||
VectorType n = (a1 - a0).cross(a2 - a0);
|
||||
if (n.dot(n) <= 1e-30f)
|
||||
if (n.dot(n) <= static_cast<FloatingType>(1e-30))
|
||||
{
|
||||
n = any_perp_vec(a1 - a0); // degenerate guard
|
||||
}
|
||||
// Ensure normal points outward (away from origin): require n·a0 >= 0
|
||||
if (n.dot(a0) < 0.0f)
|
||||
if (n.dot(a0) < static_cast<FloatingType>(0.0))
|
||||
{
|
||||
std::swap(i1, i2);
|
||||
n = -n;
|
||||
}
|
||||
const float inv_len = 1.0f / std::sqrt(std::max(n.dot(n), 1e-30f));
|
||||
const auto inv_len =
|
||||
static_cast<FloatingType>(1.0) / std::sqrt(std::max(n.dot(n), static_cast<FloatingType>(1e-30)));
|
||||
n = n * inv_len;
|
||||
const float d = n.dot(a0);
|
||||
const auto d = n.dot(a0);
|
||||
return {i0, i1, i2, n, d};
|
||||
}
|
||||
|
||||
@@ -223,7 +229,7 @@ namespace omath::collision
|
||||
|
||||
template<class V>
|
||||
[[nodiscard]]
|
||||
static constexpr bool near_zero_vec(const V& v, const float eps = 1e-7f)
|
||||
static constexpr bool near_zero_vec(const V& v, const FloatingType eps = 1e-7f)
|
||||
{
|
||||
return v.dot(v) <= eps * eps;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace omath::frostbite_engine
|
||||
const auto delta2d = calc_vector_2d_distance(predicted_target_position - projectile.m_origin);
|
||||
const auto height = delta2d * std::tan(angles::degrees_to_radians(projectile_pitch.value()));
|
||||
|
||||
return {predicted_target_position.x, predicted_target_position.y + height, projectile.m_origin.z};
|
||||
return {predicted_target_position.x, projectile.m_origin.y + height, predicted_target_position.z};
|
||||
}
|
||||
// Due to specification of maybe_calculate_projectile_launch_pitch_angle, pitch angle must be:
|
||||
// 89 look up, -89 look down
|
||||
|
||||
@@ -8,5 +8,5 @@
|
||||
|
||||
namespace omath::opengl_engine
|
||||
{
|
||||
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait>;
|
||||
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait, true>;
|
||||
} // namespace omath::opengl_engine
|
||||
@@ -55,7 +55,7 @@ namespace omath::opengl_engine
|
||||
const auto delta2d = calc_vector_2d_distance(predicted_target_position - projectile.m_origin);
|
||||
const auto height = delta2d * std::tan(angles::degrees_to_radians(projectile_pitch.value()));
|
||||
|
||||
return {predicted_target_position.x, predicted_target_position.y + height, projectile.m_origin.z};
|
||||
return {predicted_target_position.x, projectile.m_origin.y + height, predicted_target_position.z};
|
||||
}
|
||||
// Due to specification of maybe_calculate_projectile_launch_pitch_angle, pitch angle must be:
|
||||
// 89 look up, -89 look down
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace omath::unity_engine
|
||||
const auto delta2d = calc_vector_2d_distance(predicted_target_position - projectile.m_origin);
|
||||
const auto height = delta2d * std::tan(angles::degrees_to_radians(projectile_pitch.value()));
|
||||
|
||||
return {predicted_target_position.x, predicted_target_position.y + height, projectile.m_origin.z};
|
||||
return {predicted_target_position.x, projectile.m_origin.y + height, predicted_target_position.z};
|
||||
}
|
||||
// Due to specification of maybe_calculate_projectile_launch_pitch_angle, pitch angle must be:
|
||||
// 89 look up, -89 look down
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace omath::projection
|
||||
requires noexcept(T::calc_projection_matrix(fov, viewport, znear, zfar));
|
||||
};
|
||||
|
||||
template<class Mat4X4Type, class ViewAnglesType, class TraitClass>
|
||||
template<class Mat4X4Type, class ViewAnglesType, class TraitClass, bool inverted_z = false>
|
||||
requires CameraEngineConcept<TraitClass, Mat4X4Type, ViewAnglesType>
|
||||
class Camera final
|
||||
{
|
||||
@@ -80,59 +80,96 @@ namespace omath::projection
|
||||
{
|
||||
m_view_angles = TraitClass::calc_look_at_angle(m_origin, target);
|
||||
m_view_projection_matrix = std::nullopt;
|
||||
m_view_matrix = std::nullopt;
|
||||
}
|
||||
|
||||
protected:
|
||||
[[nodiscard]] Mat4X4Type calc_view_projection_matrix() const noexcept
|
||||
[[nodiscard]]
|
||||
Vector3<float> get_forward() const noexcept
|
||||
{
|
||||
return TraitClass::calc_projection_matrix(m_field_of_view, m_view_port, m_near_plane_distance,
|
||||
m_far_plane_distance)
|
||||
* TraitClass::calc_view_matrix(m_view_angles, m_origin);
|
||||
const auto& view_matrix = get_view_matrix();
|
||||
|
||||
if constexpr (inverted_z)
|
||||
return -Vector3<float>{view_matrix[2, 0], view_matrix[2, 1], view_matrix[2, 2]};
|
||||
return {view_matrix[2, 0], view_matrix[2, 1], view_matrix[2, 2]};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
Vector3<float> get_right() const noexcept
|
||||
{
|
||||
const auto& view_matrix = get_view_matrix();
|
||||
return {view_matrix[0, 0], view_matrix[0, 1], view_matrix[0, 2]};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
Vector3<float> get_up() const noexcept
|
||||
{
|
||||
const auto& view_matrix = get_view_matrix();
|
||||
return {view_matrix[1, 0], view_matrix[1, 1], view_matrix[1, 2]};
|
||||
}
|
||||
|
||||
public:
|
||||
[[nodiscard]] const Mat4X4Type& get_view_projection_matrix() const noexcept
|
||||
{
|
||||
if (!m_view_projection_matrix.has_value())
|
||||
m_view_projection_matrix = calc_view_projection_matrix();
|
||||
m_view_projection_matrix = get_projection_matrix() * get_view_matrix();
|
||||
|
||||
return m_view_projection_matrix.value();
|
||||
}
|
||||
|
||||
[[nodiscard]] const Mat4X4Type& get_view_matrix() const noexcept
|
||||
{
|
||||
if (!m_view_matrix.has_value())
|
||||
m_view_matrix = TraitClass::calc_view_matrix(m_view_angles, m_origin);
|
||||
|
||||
return m_view_matrix.value();
|
||||
}
|
||||
[[nodiscard]] const Mat4X4Type& get_projection_matrix() const noexcept
|
||||
{
|
||||
if (!m_projection_matrix.has_value())
|
||||
m_projection_matrix = TraitClass::calc_projection_matrix(m_field_of_view, m_view_port,
|
||||
m_near_plane_distance, m_far_plane_distance);
|
||||
|
||||
return m_projection_matrix.value();
|
||||
}
|
||||
|
||||
void set_field_of_view(const FieldOfView& fov) noexcept
|
||||
{
|
||||
m_field_of_view = fov;
|
||||
m_view_projection_matrix = std::nullopt;
|
||||
m_projection_matrix = std::nullopt;
|
||||
}
|
||||
|
||||
void set_near_plane(const float near) noexcept
|
||||
{
|
||||
m_near_plane_distance = near;
|
||||
m_view_projection_matrix = std::nullopt;
|
||||
m_projection_matrix = std::nullopt;
|
||||
}
|
||||
|
||||
void set_far_plane(const float far) noexcept
|
||||
{
|
||||
m_far_plane_distance = far;
|
||||
m_view_projection_matrix = std::nullopt;
|
||||
m_projection_matrix = std::nullopt;
|
||||
}
|
||||
|
||||
void set_view_angles(const ViewAnglesType& view_angles) noexcept
|
||||
{
|
||||
m_view_angles = view_angles;
|
||||
m_view_projection_matrix = std::nullopt;
|
||||
m_view_matrix = std::nullopt;
|
||||
}
|
||||
|
||||
void set_origin(const Vector3<float>& origin) noexcept
|
||||
{
|
||||
m_origin = origin;
|
||||
m_view_projection_matrix = std::nullopt;
|
||||
m_view_matrix = std::nullopt;
|
||||
}
|
||||
|
||||
void set_view_port(const ViewPort& view_port) noexcept
|
||||
{
|
||||
m_view_port = view_port;
|
||||
m_view_projection_matrix = std::nullopt;
|
||||
m_projection_matrix = std::nullopt;
|
||||
}
|
||||
|
||||
[[nodiscard]] const FieldOfView& get_field_of_view() const noexcept
|
||||
@@ -283,7 +320,8 @@ namespace omath::projection
|
||||
Angle<float, 0.f, 180.f, AngleFlags::Clamped> m_field_of_view;
|
||||
|
||||
mutable std::optional<Mat4X4Type> m_view_projection_matrix;
|
||||
|
||||
mutable std::optional<Mat4X4Type> m_projection_matrix;
|
||||
mutable std::optional<Mat4X4Type> m_view_matrix;
|
||||
float m_far_plane_distance;
|
||||
float m_near_plane_distance;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user