Removed core math classes from the lite version.

This commit is contained in:
Relintai 2024-01-07 11:01:24 +01:00
parent 1a7201e938
commit a94242a768
36 changed files with 0 additions and 10286 deletions

View File

@ -1,406 +0,0 @@
/*************************************************************************/
/* aabb.cpp */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/aabb.h"
//--STRIP
real_t AABB::get_volume() const {
return size.x * size.y * size.z;
}
bool AABB::operator==(const AABB &p_rval) const {
return ((position == p_rval.position) && (size == p_rval.size));
}
bool AABB::operator!=(const AABB &p_rval) const {
return ((position != p_rval.position) || (size != p_rval.size));
}
bool AABB::create_from_points(const Vector<Vector3> &p_points) {
if (!p_points.size()) {
return false;
}
Vector3 begin = p_points[0];
Vector3 end = begin;
for (int n = 1; n < p_points.size(); n++) {
const Vector3 &pt = p_points[n];
if (pt.x < begin.x) {
begin.x = pt.x;
}
if (pt.y < begin.y) {
begin.y = pt.y;
}
if (pt.z < begin.z) {
begin.z = pt.z;
}
if (pt.x > end.x) {
end.x = pt.x;
}
if (pt.y > end.y) {
end.y = pt.y;
}
if (pt.z > end.z) {
end.z = pt.z;
}
}
position = begin;
size = end - begin;
return true;
}
void AABB::merge_with(const AABB &p_aabb) {
Vector3 beg_1, beg_2;
Vector3 end_1, end_2;
Vector3 min, max;
beg_1 = position;
beg_2 = p_aabb.position;
end_1 = Vector3(size.x, size.y, size.z) + beg_1;
end_2 = Vector3(p_aabb.size.x, p_aabb.size.y, p_aabb.size.z) + beg_2;
min.x = (beg_1.x < beg_2.x) ? beg_1.x : beg_2.x;
min.y = (beg_1.y < beg_2.y) ? beg_1.y : beg_2.y;
min.z = (beg_1.z < beg_2.z) ? beg_1.z : beg_2.z;
max.x = (end_1.x > end_2.x) ? end_1.x : end_2.x;
max.y = (end_1.y > end_2.y) ? end_1.y : end_2.y;
max.z = (end_1.z > end_2.z) ? end_1.z : end_2.z;
position = min;
size = max - min;
}
bool AABB::is_equal_approx(const AABB &p_aabb) const {
return position.is_equal_approx(p_aabb.position) && size.is_equal_approx(p_aabb.size);
}
AABB AABB::intersection(const AABB &p_aabb) const {
Vector3 src_min = position;
Vector3 src_max = position + size;
Vector3 dst_min = p_aabb.position;
Vector3 dst_max = p_aabb.position + p_aabb.size;
Vector3 min, max;
if (src_min.x > dst_max.x || src_max.x < dst_min.x) {
return AABB();
} else {
min.x = (src_min.x > dst_min.x) ? src_min.x : dst_min.x;
max.x = (src_max.x < dst_max.x) ? src_max.x : dst_max.x;
}
if (src_min.y > dst_max.y || src_max.y < dst_min.y) {
return AABB();
} else {
min.y = (src_min.y > dst_min.y) ? src_min.y : dst_min.y;
max.y = (src_max.y < dst_max.y) ? src_max.y : dst_max.y;
}
if (src_min.z > dst_max.z || src_max.z < dst_min.z) {
return AABB();
} else {
min.z = (src_min.z > dst_min.z) ? src_min.z : dst_min.z;
max.z = (src_max.z < dst_max.z) ? src_max.z : dst_max.z;
}
return AABB(min, max - min);
}
bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip, Vector3 *r_normal) const {
Vector3 c1, c2;
Vector3 end = position + size;
real_t near = -1e20;
real_t far = 1e20;
int axis = 0;
for (int i = 0; i < 3; i++) {
if (p_dir[i] == 0) {
if ((p_from[i] < position[i]) || (p_from[i] > end[i])) {
return false;
}
} else { // ray not parallel to planes in this direction
c1[i] = (position[i] - p_from[i]) / p_dir[i];
c2[i] = (end[i] - p_from[i]) / p_dir[i];
if (c1[i] > c2[i]) {
SWAP(c1, c2);
}
if (c1[i] > near) {
near = c1[i];
axis = i;
}
if (c2[i] < far) {
far = c2[i];
}
if ((near > far) || (far < 0)) {
return false;
}
}
}
if (r_clip) {
*r_clip = c1;
}
if (r_normal) {
*r_normal = Vector3();
(*r_normal)[axis] = p_dir[axis] ? -1 : 1;
}
return true;
}
bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip, Vector3 *r_normal) const {
real_t min = 0, max = 1;
int axis = 0;
real_t sign = 0;
for (int i = 0; i < 3; i++) {
real_t seg_from = p_from[i];
real_t seg_to = p_to[i];
real_t box_begin = position[i];
real_t box_end = box_begin + size[i];
real_t cmin, cmax;
real_t csign;
if (seg_from < seg_to) {
if (seg_from > box_end || seg_to < box_begin) {
return false;
}
real_t length = seg_to - seg_from;
cmin = (seg_from < box_begin) ? ((box_begin - seg_from) / length) : 0;
cmax = (seg_to > box_end) ? ((box_end - seg_from) / length) : 1;
csign = -1.0;
} else {
if (seg_to > box_end || seg_from < box_begin) {
return false;
}
real_t length = seg_to - seg_from;
cmin = (seg_from > box_end) ? (box_end - seg_from) / length : 0;
cmax = (seg_to < box_begin) ? (box_begin - seg_from) / length : 1;
csign = 1.0;
}
if (cmin > min) {
min = cmin;
axis = i;
sign = csign;
}
if (cmax < max) {
max = cmax;
}
if (max < min) {
return false;
}
}
Vector3 rel = p_to - p_from;
if (r_normal) {
Vector3 normal;
normal[axis] = sign;
*r_normal = normal;
}
if (r_clip) {
*r_clip = p_from + rel * min;
}
return true;
}
bool AABB::intersects_plane(const Plane &p_plane) const {
Vector3 points[8] = {
Vector3(position.x, position.y, position.z),
Vector3(position.x, position.y, position.z + size.z),
Vector3(position.x, position.y + size.y, position.z),
Vector3(position.x, position.y + size.y, position.z + size.z),
Vector3(position.x + size.x, position.y, position.z),
Vector3(position.x + size.x, position.y, position.z + size.z),
Vector3(position.x + size.x, position.y + size.y, position.z),
Vector3(position.x + size.x, position.y + size.y, position.z + size.z),
};
bool over = false;
bool under = false;
for (int i = 0; i < 8; i++) {
if (p_plane.distance_to(points[i]) > 0) {
over = true;
} else {
under = true;
}
}
return under && over;
}
Vector3 AABB::get_longest_axis() const {
Vector3 axis(1, 0, 0);
real_t max_size = size.x;
if (size.y > max_size) {
axis = Vector3(0, 1, 0);
max_size = size.y;
}
if (size.z > max_size) {
axis = Vector3(0, 0, 1);
}
return axis;
}
int AABB::get_longest_axis_index() const {
int axis = 0;
real_t max_size = size.x;
if (size.y > max_size) {
axis = 1;
max_size = size.y;
}
if (size.z > max_size) {
axis = 2;
}
return axis;
}
Vector3 AABB::get_shortest_axis() const {
Vector3 axis(1, 0, 0);
real_t max_size = size.x;
if (size.y < max_size) {
axis = Vector3(0, 1, 0);
max_size = size.y;
}
if (size.z < max_size) {
axis = Vector3(0, 0, 1);
}
return axis;
}
int AABB::get_shortest_axis_index() const {
int axis = 0;
real_t max_size = size.x;
if (size.y < max_size) {
axis = 1;
max_size = size.y;
}
if (size.z < max_size) {
axis = 2;
}
return axis;
}
AABB AABB::merge(const AABB &p_with) const {
AABB aabb = *this;
aabb.merge_with(p_with);
return aabb;
}
AABB AABB::expand(const Vector3 &p_vector) const {
AABB aabb = *this;
aabb.expand_to(p_vector);
return aabb;
}
AABB AABB::grow(real_t p_by) const {
AABB aabb = *this;
aabb.grow_by(p_by);
return aabb;
}
void AABB::get_edge(int p_edge, Vector3 &r_from, Vector3 &r_to) const {
ERR_FAIL_INDEX(p_edge, 12);
switch (p_edge) {
case 0: {
r_from = Vector3(position.x + size.x, position.y, position.z);
r_to = Vector3(position.x, position.y, position.z);
} break;
case 1: {
r_from = Vector3(position.x + size.x, position.y, position.z + size.z);
r_to = Vector3(position.x + size.x, position.y, position.z);
} break;
case 2: {
r_from = Vector3(position.x, position.y, position.z + size.z);
r_to = Vector3(position.x + size.x, position.y, position.z + size.z);
} break;
case 3: {
r_from = Vector3(position.x, position.y, position.z);
r_to = Vector3(position.x, position.y, position.z + size.z);
} break;
case 4: {
r_from = Vector3(position.x, position.y + size.y, position.z);
r_to = Vector3(position.x + size.x, position.y + size.y, position.z);
} break;
case 5: {
r_from = Vector3(position.x + size.x, position.y + size.y, position.z);
r_to = Vector3(position.x + size.x, position.y + size.y, position.z + size.z);
} break;
case 6: {
r_from = Vector3(position.x + size.x, position.y + size.y, position.z + size.z);
r_to = Vector3(position.x, position.y + size.y, position.z + size.z);
} break;
case 7: {
r_from = Vector3(position.x, position.y + size.y, position.z + size.z);
r_to = Vector3(position.x, position.y + size.y, position.z);
} break;
case 8: {
r_from = Vector3(position.x, position.y, position.z + size.z);
r_to = Vector3(position.x, position.y + size.y, position.z + size.z);
} break;
case 9: {
r_from = Vector3(position.x, position.y, position.z);
r_to = Vector3(position.x, position.y + size.y, position.z);
} break;
case 10: {
r_from = Vector3(position.x + size.x, position.y, position.z);
r_to = Vector3(position.x + size.x, position.y + size.y, position.z);
} break;
case 11: {
r_from = Vector3(position.x + size.x, position.y, position.z + size.z);
r_to = Vector3(position.x + size.x, position.y + size.y, position.z + size.z);
} break;
}
}
/*
Variant AABB::intersects_segmentv(const Vector3 &p_from, const Vector3 &p_to) const {
Vector3 inters;
if (intersects_segment(p_from, p_to, &inters)) {
return inters;
}
return Variant();
}
Variant AABB::intersects_rayv(const Vector3 &p_from, const Vector3 &p_dir) const {
Vector3 inters;
if (intersects_ray(p_from, p_dir, &inters)) {
return inters;
}
return Variant();
}
*/
AABB::operator String() const {
return "[P: " + position.operator String() + ", S: " + size + "]";
}

View File

@ -1,437 +0,0 @@
#ifndef AABB_H
#define AABB_H
/*************************************************************************/
/* aabb.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/math_defs.h"
#include "core/plane.h"
#include "core/vector3.h"
//--STRIP
/**
* AABB / AABB (Axis Aligned Bounding Box)
* This is implemented by a point (position) and the box size
*/
struct _NO_DISCARD_CLASS_ AABB {
Vector3 position;
Vector3 size;
real_t get_volume() const; /// get area
_FORCE_INLINE_ bool has_no_volume() const {
return (size.x <= 0 || size.y <= 0 || size.z <= 0);
}
_FORCE_INLINE_ bool has_no_surface() const {
return (size.x <= 0 && size.y <= 0 && size.z <= 0);
}
const Vector3 &get_position() const { return position; }
void set_position(const Vector3 &p_pos) { position = p_pos; }
const Vector3 &get_size() const { return size; }
void set_size(const Vector3 &p_size) { size = p_size; }
bool operator==(const AABB &p_rval) const;
bool operator!=(const AABB &p_rval) const;
bool is_equal_approx(const AABB &p_aabb) const;
_FORCE_INLINE_ bool intersects(const AABB &p_aabb) const; /// Both AABBs overlap
_FORCE_INLINE_ bool intersects_inclusive(const AABB &p_aabb) const; /// Both AABBs (or their faces) overlap
_FORCE_INLINE_ bool encloses(const AABB &p_aabb) const; /// p_aabb is completely inside this
AABB merge(const AABB &p_with) const;
void merge_with(const AABB &p_aabb); ///merge with another AABB
AABB intersection(const AABB &p_aabb) const; ///get box where two intersect, empty if no intersection occurs
bool intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip = nullptr, Vector3 *r_normal = nullptr) const;
bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip = nullptr, Vector3 *r_normal = nullptr) const;
_FORCE_INLINE_ bool smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t t0, real_t t1) const;
_FORCE_INLINE_ bool intersects_convex_shape(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count) const;
_FORCE_INLINE_ bool inside_convex_shape(const Plane *p_planes, int p_plane_count) const;
bool intersects_plane(const Plane &p_plane) const;
_FORCE_INLINE_ bool has_point(const Vector3 &p_point) const;
_FORCE_INLINE_ Vector3 get_support(const Vector3 &p_normal) const;
Vector3 get_longest_axis() const;
int get_longest_axis_index() const;
_FORCE_INLINE_ real_t get_longest_axis_size() const;
Vector3 get_shortest_axis() const;
int get_shortest_axis_index() const;
_FORCE_INLINE_ real_t get_shortest_axis_size() const;
AABB grow(real_t p_by) const;
_FORCE_INLINE_ void grow_by(real_t p_amount);
void get_edge(int p_edge, Vector3 &r_from, Vector3 &r_to) const;
_FORCE_INLINE_ Vector3 get_endpoint(int p_point) const;
AABB expand(const Vector3 &p_vector) const;
_FORCE_INLINE_ void project_range_in_plane(const Plane &p_plane, real_t &r_min, real_t &r_max) const;
_FORCE_INLINE_ void expand_to(const Vector3 &p_vector); /** expand to contain a point if necessary */
bool create_from_points(const Vector<Vector3> &p_points);
_FORCE_INLINE_ AABB abs() const {
return AABB(Vector3(position.x + MIN(size.x, 0), position.y + MIN(size.y, 0), position.z + MIN(size.z, 0)), size.abs());
}
//Variant intersects_segmentv(const Vector3 &p_from, const Vector3 &p_to) const;
//Variant intersects_rayv(const Vector3 &p_from, const Vector3 &p_dir) const;
_FORCE_INLINE_ void quantize(real_t p_unit);
_FORCE_INLINE_ AABB quantized(real_t p_unit) const;
_FORCE_INLINE_ void set_end(const Vector3 &p_end) {
size = p_end - position;
}
_FORCE_INLINE_ Vector3 get_end() const {
return position + size;
}
_FORCE_INLINE_ Vector3 get_center() const {
return position + (size * 0.5f);
}
operator String() const;
_FORCE_INLINE_ AABB() {}
inline AABB(const Vector3 &p_pos, const Vector3 &p_size) :
position(p_pos),
size(p_size) {
}
};
inline bool AABB::intersects(const AABB &p_aabb) const {
if (position.x >= (p_aabb.position.x + p_aabb.size.x)) {
return false;
}
if ((position.x + size.x) <= p_aabb.position.x) {
return false;
}
if (position.y >= (p_aabb.position.y + p_aabb.size.y)) {
return false;
}
if ((position.y + size.y) <= p_aabb.position.y) {
return false;
}
if (position.z >= (p_aabb.position.z + p_aabb.size.z)) {
return false;
}
if ((position.z + size.z) <= p_aabb.position.z) {
return false;
}
return true;
}
inline bool AABB::intersects_inclusive(const AABB &p_aabb) const {
if (position.x > (p_aabb.position.x + p_aabb.size.x)) {
return false;
}
if ((position.x + size.x) < p_aabb.position.x) {
return false;
}
if (position.y > (p_aabb.position.y + p_aabb.size.y)) {
return false;
}
if ((position.y + size.y) < p_aabb.position.y) {
return false;
}
if (position.z > (p_aabb.position.z + p_aabb.size.z)) {
return false;
}
if ((position.z + size.z) < p_aabb.position.z) {
return false;
}
return true;
}
inline bool AABB::encloses(const AABB &p_aabb) const {
Vector3 src_min = position;
Vector3 src_max = position + size;
Vector3 dst_min = p_aabb.position;
Vector3 dst_max = p_aabb.position + p_aabb.size;
return (
(src_min.x <= dst_min.x) &&
(src_max.x > dst_max.x) &&
(src_min.y <= dst_min.y) &&
(src_max.y > dst_max.y) &&
(src_min.z <= dst_min.z) &&
(src_max.z > dst_max.z));
}
Vector3 AABB::get_support(const Vector3 &p_normal) const {
Vector3 half_extents = size * 0.5f;
Vector3 ofs = position + half_extents;
return Vector3(
(p_normal.x > 0) ? -half_extents.x : half_extents.x,
(p_normal.y > 0) ? -half_extents.y : half_extents.y,
(p_normal.z > 0) ? -half_extents.z : half_extents.z) +
ofs;
}
Vector3 AABB::get_endpoint(int p_point) const {
switch (p_point) {
case 0:
return Vector3(position.x, position.y, position.z);
case 1:
return Vector3(position.x, position.y, position.z + size.z);
case 2:
return Vector3(position.x, position.y + size.y, position.z);
case 3:
return Vector3(position.x, position.y + size.y, position.z + size.z);
case 4:
return Vector3(position.x + size.x, position.y, position.z);
case 5:
return Vector3(position.x + size.x, position.y, position.z + size.z);
case 6:
return Vector3(position.x + size.x, position.y + size.y, position.z);
case 7:
return Vector3(position.x + size.x, position.y + size.y, position.z + size.z);
};
ERR_FAIL_V(Vector3());
}
bool AABB::intersects_convex_shape(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count) const {
Vector3 half_extents = size * 0.5f;
Vector3 ofs = position + half_extents;
for (int i = 0; i < p_plane_count; i++) {
const Plane &p = p_planes[i];
Vector3 point(
(p.normal.x > 0) ? -half_extents.x : half_extents.x,
(p.normal.y > 0) ? -half_extents.y : half_extents.y,
(p.normal.z > 0) ? -half_extents.z : half_extents.z);
point += ofs;
if (p.is_point_over(point)) {
return false;
}
}
// Make sure all points in the shape aren't fully separated from the AABB on
// each axis.
int bad_point_counts_positive[3] = { 0 };
int bad_point_counts_negative[3] = { 0 };
for (int k = 0; k < 3; k++) {
for (int i = 0; i < p_point_count; i++) {
if (p_points[i].coord[k] > ofs.coord[k] + half_extents.coord[k]) {
bad_point_counts_positive[k]++;
}
if (p_points[i].coord[k] < ofs.coord[k] - half_extents.coord[k]) {
bad_point_counts_negative[k]++;
}
}
if (bad_point_counts_negative[k] == p_point_count) {
return false;
}
if (bad_point_counts_positive[k] == p_point_count) {
return false;
}
}
return true;
}
bool AABB::inside_convex_shape(const Plane *p_planes, int p_plane_count) const {
Vector3 half_extents = size * 0.5f;
Vector3 ofs = position + half_extents;
for (int i = 0; i < p_plane_count; i++) {
const Plane &p = p_planes[i];
Vector3 point(
(p.normal.x < 0) ? -half_extents.x : half_extents.x,
(p.normal.y < 0) ? -half_extents.y : half_extents.y,
(p.normal.z < 0) ? -half_extents.z : half_extents.z);
point += ofs;
if (p.is_point_over(point)) {
return false;
}
}
return true;
}
bool AABB::has_point(const Vector3 &p_point) const {
if (p_point.x < position.x) {
return false;
}
if (p_point.y < position.y) {
return false;
}
if (p_point.z < position.z) {
return false;
}
if (p_point.x > position.x + size.x) {
return false;
}
if (p_point.y > position.y + size.y) {
return false;
}
if (p_point.z > position.z + size.z) {
return false;
}
return true;
}
inline void AABB::expand_to(const Vector3 &p_vector) {
Vector3 begin = position;
Vector3 end = position + size;
if (p_vector.x < begin.x) {
begin.x = p_vector.x;
}
if (p_vector.y < begin.y) {
begin.y = p_vector.y;
}
if (p_vector.z < begin.z) {
begin.z = p_vector.z;
}
if (p_vector.x > end.x) {
end.x = p_vector.x;
}
if (p_vector.y > end.y) {
end.y = p_vector.y;
}
if (p_vector.z > end.z) {
end.z = p_vector.z;
}
position = begin;
size = end - begin;
}
void AABB::project_range_in_plane(const Plane &p_plane, real_t &r_min, real_t &r_max) const {
Vector3 half_extents = size * 0.5f;
Vector3 center(position.x + half_extents.x, position.y + half_extents.y, position.z + half_extents.z);
real_t length = p_plane.normal.abs().dot(half_extents);
real_t distance = p_plane.distance_to(center);
r_min = distance - length;
r_max = distance + length;
}
inline real_t AABB::get_longest_axis_size() const {
real_t max_size = size.x;
if (size.y > max_size) {
max_size = size.y;
}
if (size.z > max_size) {
max_size = size.z;
}
return max_size;
}
inline real_t AABB::get_shortest_axis_size() const {
real_t max_size = size.x;
if (size.y < max_size) {
max_size = size.y;
}
if (size.z < max_size) {
max_size = size.z;
}
return max_size;
}
bool AABB::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t t0, real_t t1) const {
real_t divx = 1 / p_dir.x;
real_t divy = 1 / p_dir.y;
real_t divz = 1 / p_dir.z;
Vector3 upbound = position + size;
real_t tmin, tmax, tymin, tymax, tzmin, tzmax;
if (p_dir.x >= 0) {
tmin = (position.x - p_from.x) * divx;
tmax = (upbound.x - p_from.x) * divx;
} else {
tmin = (upbound.x - p_from.x) * divx;
tmax = (position.x - p_from.x) * divx;
}
if (p_dir.y >= 0) {
tymin = (position.y - p_from.y) * divy;
tymax = (upbound.y - p_from.y) * divy;
} else {
tymin = (upbound.y - p_from.y) * divy;
tymax = (position.y - p_from.y) * divy;
}
if ((tmin > tymax) || (tymin > tmax)) {
return false;
}
if (tymin > tmin) {
tmin = tymin;
}
if (tymax < tmax) {
tmax = tymax;
}
if (p_dir.z >= 0) {
tzmin = (position.z - p_from.z) * divz;
tzmax = (upbound.z - p_from.z) * divz;
} else {
tzmin = (upbound.z - p_from.z) * divz;
tzmax = (position.z - p_from.z) * divz;
}
if ((tmin > tzmax) || (tzmin > tmax)) {
return false;
}
if (tzmin > tmin) {
tmin = tzmin;
}
if (tzmax < tmax) {
tmax = tzmax;
}
return ((tmin < t1) && (tmax > t0));
}
void AABB::grow_by(real_t p_amount) {
position.x -= p_amount;
position.y -= p_amount;
position.z -= p_amount;
size.x += 2 * p_amount;
size.y += 2 * p_amount;
size.z += 2 * p_amount;
}
void AABB::quantize(real_t p_unit) {
size += position;
position.x -= Math::fposmodp(position.x, p_unit);
position.y -= Math::fposmodp(position.y, p_unit);
position.z -= Math::fposmodp(position.z, p_unit);
size.x -= Math::fposmodp(size.x, p_unit);
size.y -= Math::fposmodp(size.y, p_unit);
size.z -= Math::fposmodp(size.z, p_unit);
size.x += p_unit;
size.y += p_unit;
size.z += p_unit;
size -= position;
}
AABB AABB::quantized(real_t p_unit) const {
AABB ret = *this;
ret.quantize(p_unit);
return ret;
}
#endif // AABB_H

File diff suppressed because it is too large Load Diff

View File

@ -1,380 +0,0 @@
#ifndef BASIS_H
#define BASIS_H
/*************************************************************************/
/* basis.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/quaternion.h"
#include "core/vector3.h"
#include "core/vector3i.h"
//--STRIP
struct _NO_DISCARD_CLASS_ Basis {
Vector3 rows[3] = {
Vector3(1, 0, 0),
Vector3(0, 1, 0),
Vector3(0, 0, 1)
};
_FORCE_INLINE_ const Vector3 &operator[](int p_row) const {
return rows[p_row];
}
_FORCE_INLINE_ Vector3 &operator[](int p_row) {
return rows[p_row];
}
void invert();
void transpose();
Basis inverse() const;
Basis transposed() const;
_FORCE_INLINE_ real_t determinant() const;
void from_z(const Vector3 &p_z);
void rotate(const Vector3 &p_axis, real_t p_phi);
Basis rotated(const Vector3 &p_axis, real_t p_phi) const;
void rotate_local(const Vector3 &p_axis, real_t p_phi);
Basis rotated_local(const Vector3 &p_axis, real_t p_phi) const;
void rotate(const Vector3 &p_euler);
Basis rotated(const Vector3 &p_euler) const;
void rotate(const Quaternion &p_quat);
Basis rotated(const Quaternion &p_quat) const;
_FORCE_INLINE_ void rotatev(const Vector3 &p_euler) { rotate(p_euler); }
_FORCE_INLINE_ Basis rotatedv(const Vector3 &p_euler) const { return rotated(p_euler); }
_FORCE_INLINE_ void rotateq(const Quaternion &p_quat) { rotate(p_quat); }
_FORCE_INLINE_ Basis rotatedq(const Quaternion &p_quat) const { return rotated(p_quat); }
Vector3 get_rotation_euler() const;
void get_rotation_axis_angle(Vector3 &p_axis, real_t &p_angle) const;
void get_rotation_axis_angle_local(Vector3 &p_axis, real_t &p_angle) const;
Quaternion get_rotation_quaternion() const;
Vector3 get_rotation() const { return get_rotation_euler(); };
void rotate_to_align(const Vector3 &p_start_direction, const Vector3 &p_end_direction);
Vector3 rotref_posscale_decomposition(Basis &rotref) const;
Vector3 get_euler_xyz() const;
void set_euler_xyz(const Vector3 &p_euler);
Vector3 get_euler_xzy() const;
void set_euler_xzy(const Vector3 &p_euler);
Vector3 get_euler_yzx() const;
void set_euler_yzx(const Vector3 &p_euler);
Vector3 get_euler_yxz() const;
void set_euler_yxz(const Vector3 &p_euler);
Vector3 get_euler_zxy() const;
void set_euler_zxy(const Vector3 &p_euler);
Vector3 get_euler_zyx() const;
void set_euler_zyx(const Vector3 &p_euler);
Vector3 get_euler() const { return get_euler_yxz(); }
void set_euler(const Vector3 &p_euler) { set_euler_yxz(p_euler); }
Quaternion get_quaternion() const;
void set_quaternion(const Quaternion &p_quat);
void get_axis_angle(Vector3 &r_axis, real_t &r_angle) const;
void set_axis_angle(const Vector3 &p_axis, real_t p_phi);
void scale(const Vector3 &p_scale);
Basis scaled(const Vector3 &p_scale) const;
void scale_local(const Vector3 &p_scale);
Basis scaled_local(const Vector3 &p_scale) const;
void scale_orthogonal(const Vector3 &p_scale);
Basis scaled_orthogonal(const Vector3 &p_scale) const;
void make_scale_uniform();
real_t get_uniform_scale() const;
Vector3 get_scale() const;
Vector3 get_scale_abs() const;
Vector3 get_scale_local() const;
void set_axis_angle_scale(const Vector3 &p_axis, real_t p_phi, const Vector3 &p_scale);
void set_euler_scale(const Vector3 &p_euler, const Vector3 &p_scale);
void set_quaternion_scale(const Quaternion &p_quat, const Vector3 &p_scale);
// transposed dot products
_FORCE_INLINE_ real_t tdotx(const Vector3 &v) const {
return rows[0][0] * v[0] + rows[1][0] * v[1] + rows[2][0] * v[2];
}
_FORCE_INLINE_ real_t tdoty(const Vector3 &v) const {
return rows[0][1] * v[0] + rows[1][1] * v[1] + rows[2][1] * v[2];
}
_FORCE_INLINE_ real_t tdotz(const Vector3 &v) const {
return rows[0][2] * v[0] + rows[1][2] * v[1] + rows[2][2] * v[2];
}
bool is_equal_approx(const Basis &p_basis) const;
bool is_equal_approx_ratio(const Basis &a, const Basis &b, real_t p_epsilon = UNIT_EPSILON) const;
bool operator==(const Basis &p_matrix) const;
bool operator!=(const Basis &p_matrix) const;
_FORCE_INLINE_ Vector3 xform(const Vector3 &p_vector) const;
_FORCE_INLINE_ Vector3 xform_inv(const Vector3 &p_vector) const;
_FORCE_INLINE_ Vector3i xform(const Vector3i &p_vector) const;
_FORCE_INLINE_ Vector3i xform_inv(const Vector3i &p_vector) const;
_FORCE_INLINE_ void operator*=(const Basis &p_matrix);
_FORCE_INLINE_ Basis operator*(const Basis &p_matrix) const;
_FORCE_INLINE_ void operator+=(const Basis &p_matrix);
_FORCE_INLINE_ Basis operator+(const Basis &p_matrix) const;
_FORCE_INLINE_ void operator-=(const Basis &p_matrix);
_FORCE_INLINE_ Basis operator-(const Basis &p_matrix) const;
_FORCE_INLINE_ void operator*=(real_t p_val);
_FORCE_INLINE_ Basis operator*(real_t p_val) const;
int get_orthogonal_index() const;
void set_orthogonal_index(int p_index);
void set_diagonal(const Vector3 &p_diag);
bool is_orthogonal() const;
bool is_diagonal() const;
bool is_rotation() const;
Basis slerp(const Basis &p_to, const real_t &p_weight) const;
_FORCE_INLINE_ Basis lerp(const Basis &p_to, const real_t &p_weight) const;
void rotate_sh(real_t *p_values);
operator String() const;
/* create / set */
_FORCE_INLINE_ void set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) {
rows[0][0] = xx;
rows[0][1] = xy;
rows[0][2] = xz;
rows[1][0] = yx;
rows[1][1] = yy;
rows[1][2] = yz;
rows[2][0] = zx;
rows[2][1] = zy;
rows[2][2] = zz;
}
_FORCE_INLINE_ void set(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z) {
set_column(0, p_x);
set_column(1, p_y);
set_column(2, p_z);
}
_FORCE_INLINE_ Vector3 get_column(int i) const {
return Vector3(rows[0][i], rows[1][i], rows[2][i]);
}
_FORCE_INLINE_ void set_column(int p_index, const Vector3 &p_value) {
// Set actual basis axis column (we store transposed as rows for performance).
rows[0][p_index] = p_value.x;
rows[1][p_index] = p_value.y;
rows[2][p_index] = p_value.z;
}
_FORCE_INLINE_ void set_columns(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z) {
set_column(0, p_x);
set_column(1, p_y);
set_column(2, p_z);
}
_FORCE_INLINE_ Vector3 get_row(int i) const {
return Vector3(rows[i][0], rows[i][1], rows[i][2]);
}
_FORCE_INLINE_ void set_row(int i, const Vector3 &p_row) {
rows[i][0] = p_row.x;
rows[i][1] = p_row.y;
rows[i][2] = p_row.z;
}
_FORCE_INLINE_ Vector3 get_axis(int i) const {
return Vector3(rows[0][i], rows[1][i], rows[2][i]);
}
_FORCE_INLINE_ void set_axis(int p_index, const Vector3 &p_value) {
// Set actual basis axis column (we store transposed as rows for performance).
rows[0][p_index] = p_value.x;
rows[1][p_index] = p_value.y;
rows[2][p_index] = p_value.z;
}
_FORCE_INLINE_ Vector3 get_main_diagonal() const {
return Vector3(rows[0][0], rows[1][1], rows[2][2]);
}
_FORCE_INLINE_ void set_zero() {
rows[0].zero();
rows[1].zero();
rows[2].zero();
}
_FORCE_INLINE_ Basis transpose_xform(const Basis &m) const {
return Basis(
rows[0].x * m[0].x + rows[1].x * m[1].x + rows[2].x * m[2].x,
rows[0].x * m[0].y + rows[1].x * m[1].y + rows[2].x * m[2].y,
rows[0].x * m[0].z + rows[1].x * m[1].z + rows[2].x * m[2].z,
rows[0].y * m[0].x + rows[1].y * m[1].x + rows[2].y * m[2].x,
rows[0].y * m[0].y + rows[1].y * m[1].y + rows[2].y * m[2].y,
rows[0].y * m[0].z + rows[1].y * m[1].z + rows[2].y * m[2].z,
rows[0].z * m[0].x + rows[1].z * m[1].x + rows[2].z * m[2].x,
rows[0].z * m[0].y + rows[1].z * m[1].y + rows[2].z * m[2].y,
rows[0].z * m[0].z + rows[1].z * m[1].z + rows[2].z * m[2].z);
}
Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) {
set(xx, xy, xz, yx, yy, yz, zx, zy, zz);
}
void orthonormalize();
Basis orthonormalized() const;
void orthogonalize();
Basis orthogonalized() const;
bool is_symmetric() const;
Basis diagonalize();
// The following normal xform functions are correct for non-uniform scales.
// Use these two functions in combination to xform a series of normals.
// First use get_normal_xform_basis() to precalculate the inverse transpose.
// Then apply xform_normal_fast() multiple times using the inverse transpose basis.
Basis get_normal_xform_basis() const { return inverse().transposed(); }
// N.B. This only does a normal transform if the basis used is the inverse transpose!
// Otherwise use xform_normal().
Vector3 xform_normal_fast(const Vector3 &p_vector) const { return xform(p_vector).normalized(); }
// This function does the above but for a single normal vector. It is considerably slower, so should usually
// only be used in cases of single normals, or when the basis changes each time.
Vector3 xform_normal(const Vector3 &p_vector) const { return get_normal_xform_basis().xform_normal_fast(p_vector); }
static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0));
static Basis from_scale(const Vector3 &p_scale);
operator Quaternion() const { return get_quaternion(); }
Basis(const Quaternion &p_quat) { set_quaternion(p_quat); }
Basis(const Quaternion &p_quat, const Vector3 &p_scale) { set_quaternion_scale(p_quat, p_scale); }
Basis(const Vector3 &p_euler) { set_euler(p_euler); }
Basis(const Vector3 &p_euler, const Vector3 &p_scale) { set_euler_scale(p_euler, p_scale); }
Basis(const Vector3 &p_axis, real_t p_phi) { set_axis_angle(p_axis, p_phi); }
Basis(const Vector3 &p_axis, real_t p_phi, const Vector3 &p_scale) { set_axis_angle_scale(p_axis, p_phi, p_scale); }
_FORCE_INLINE_ Basis(const Vector3 &row0, const Vector3 &row1, const Vector3 &row2) {
rows[0] = row0;
rows[1] = row1;
rows[2] = row2;
}
_FORCE_INLINE_ Basis() {}
};
_FORCE_INLINE_ void Basis::operator*=(const Basis &p_matrix) {
set(
p_matrix.tdotx(rows[0]), p_matrix.tdoty(rows[0]), p_matrix.tdotz(rows[0]),
p_matrix.tdotx(rows[1]), p_matrix.tdoty(rows[1]), p_matrix.tdotz(rows[1]),
p_matrix.tdotx(rows[2]), p_matrix.tdoty(rows[2]), p_matrix.tdotz(rows[2]));
}
_FORCE_INLINE_ Basis Basis::operator*(const Basis &p_matrix) const {
return Basis(
p_matrix.tdotx(rows[0]), p_matrix.tdoty(rows[0]), p_matrix.tdotz(rows[0]),
p_matrix.tdotx(rows[1]), p_matrix.tdoty(rows[1]), p_matrix.tdotz(rows[1]),
p_matrix.tdotx(rows[2]), p_matrix.tdoty(rows[2]), p_matrix.tdotz(rows[2]));
}
_FORCE_INLINE_ void Basis::operator+=(const Basis &p_matrix) {
rows[0] += p_matrix.rows[0];
rows[1] += p_matrix.rows[1];
rows[2] += p_matrix.rows[2];
}
_FORCE_INLINE_ Basis Basis::operator+(const Basis &p_matrix) const {
Basis ret(*this);
ret += p_matrix;
return ret;
}
_FORCE_INLINE_ void Basis::operator-=(const Basis &p_matrix) {
rows[0] -= p_matrix.rows[0];
rows[1] -= p_matrix.rows[1];
rows[2] -= p_matrix.rows[2];
}
_FORCE_INLINE_ Basis Basis::operator-(const Basis &p_matrix) const {
Basis ret(*this);
ret -= p_matrix;
return ret;
}
_FORCE_INLINE_ void Basis::operator*=(real_t p_val) {
rows[0] *= p_val;
rows[1] *= p_val;
rows[2] *= p_val;
}
_FORCE_INLINE_ Basis Basis::operator*(real_t p_val) const {
Basis ret(*this);
ret *= p_val;
return ret;
}
Vector3 Basis::xform(const Vector3 &p_vector) const {
return Vector3(
rows[0].dot(p_vector),
rows[1].dot(p_vector),
rows[2].dot(p_vector));
}
Vector3i Basis::xform_inv(const Vector3i &p_vector) const {
return Vector3i(
(rows[0][0] * p_vector.x) + (rows[1][0] * p_vector.y) + (rows[2][0] * p_vector.z),
(rows[0][1] * p_vector.x) + (rows[1][1] * p_vector.y) + (rows[2][1] * p_vector.z),
(rows[0][2] * p_vector.x) + (rows[1][2] * p_vector.y) + (rows[2][2] * p_vector.z));
}
Vector3i Basis::xform(const Vector3i &p_vector) const {
return Vector3i(
rows[0].dot(p_vector),
rows[1].dot(p_vector),
rows[2].dot(p_vector));
}
Vector3 Basis::xform_inv(const Vector3 &p_vector) const {
return Vector3(
(rows[0][0] * p_vector.x) + (rows[1][0] * p_vector.y) + (rows[2][0] * p_vector.z),
(rows[0][1] * p_vector.x) + (rows[1][1] * p_vector.y) + (rows[2][1] * p_vector.z),
(rows[0][2] * p_vector.x) + (rows[1][2] * p_vector.y) + (rows[2][2] * p_vector.z));
}
real_t Basis::determinant() const {
return rows[0][0] * (rows[1][1] * rows[2][2] - rows[2][1] * rows[1][2]) -
rows[1][0] * (rows[0][1] * rows[2][2] - rows[2][1] * rows[0][2]) +
rows[2][0] * (rows[0][1] * rows[1][2] - rows[1][1] * rows[0][2]);
}
Basis Basis::lerp(const Basis &p_to, const real_t &p_weight) const {
Basis b;
b.rows[0] = rows[0].linear_interpolate(p_to.rows[0], p_weight);
b.rows[1] = rows[1].linear_interpolate(p_to.rows[1], p_weight);
b.rows[2] = rows[2].linear_interpolate(p_to.rows[2], p_weight);
return b;
}
#endif // BASIS_H

View File

@ -1,522 +0,0 @@
/*************************************************************************/
/* color.cpp */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/color.h"
#include "core/math_funcs.h"
//--STRIP
uint32_t Color::to_argb32() const {
uint32_t c = (uint8_t)Math::round(a * 255);
c <<= 8;
c |= (uint8_t)Math::round(r * 255);
c <<= 8;
c |= (uint8_t)Math::round(g * 255);
c <<= 8;
c |= (uint8_t)Math::round(b * 255);
return c;
}
uint32_t Color::to_abgr32() const {
uint32_t c = (uint8_t)Math::round(a * 255);
c <<= 8;
c |= (uint8_t)Math::round(b * 255);
c <<= 8;
c |= (uint8_t)Math::round(g * 255);
c <<= 8;
c |= (uint8_t)Math::round(r * 255);
return c;
}
uint32_t Color::to_rgba32() const {
uint32_t c = (uint8_t)Math::round(r * 255);
c <<= 8;
c |= (uint8_t)Math::round(g * 255);
c <<= 8;
c |= (uint8_t)Math::round(b * 255);
c <<= 8;
c |= (uint8_t)Math::round(a * 255);
return c;
}
uint64_t Color::to_abgr64() const {
uint64_t c = (uint16_t)Math::round(a * 65535);
c <<= 16;
c |= (uint16_t)Math::round(b * 65535);
c <<= 16;
c |= (uint16_t)Math::round(g * 65535);
c <<= 16;
c |= (uint16_t)Math::round(r * 65535);
return c;
}
uint64_t Color::to_argb64() const {
uint64_t c = (uint16_t)Math::round(a * 65535);
c <<= 16;
c |= (uint16_t)Math::round(r * 65535);
c <<= 16;
c |= (uint16_t)Math::round(g * 65535);
c <<= 16;
c |= (uint16_t)Math::round(b * 65535);
return c;
}
uint64_t Color::to_rgba64() const {
uint64_t c = (uint16_t)Math::round(r * 65535);
c <<= 16;
c |= (uint16_t)Math::round(g * 65535);
c <<= 16;
c |= (uint16_t)Math::round(b * 65535);
c <<= 16;
c |= (uint16_t)Math::round(a * 65535);
return c;
}
float Color::get_h() const {
float min = MIN(r, g);
min = MIN(min, b);
float max = MAX(r, g);
max = MAX(max, b);
float delta = max - min;
if (delta == 0) {
return 0;
}
float h;
if (r == max) {
h = (g - b) / delta; // between yellow & magenta
} else if (g == max) {
h = 2 + (b - r) / delta; // between cyan & yellow
} else {
h = 4 + (r - g) / delta; // between magenta & cyan
}
h /= 6.0;
if (h < 0) {
h += 1.0;
}
return h;
}
float Color::get_s() const {
float min = MIN(r, g);
min = MIN(min, b);
float max = MAX(r, g);
max = MAX(max, b);
float delta = max - min;
return (max != 0) ? (delta / max) : 0;
}
float Color::get_v() const {
float max = MAX(r, g);
max = MAX(max, b);
return max;
}
void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
int i;
float f, p, q, t;
a = p_alpha;
if (p_s == 0) {
// acp_hromatic (grey)
r = g = b = p_v;
return;
}
p_h *= 6.0;
p_h = Math::fmod(p_h, 6);
i = Math::floor(p_h);
f = p_h - i;
p = p_v * (1 - p_s);
q = p_v * (1 - p_s * f);
t = p_v * (1 - p_s * (1 - f));
switch (i) {
case 0: // Red is the dominant color
r = p_v;
g = t;
b = p;
break;
case 1: // Green is the dominant color
r = q;
g = p_v;
b = p;
break;
case 2:
r = p;
g = p_v;
b = t;
break;
case 3: // Blue is the dominant color
r = p;
g = q;
b = p_v;
break;
case 4:
r = t;
g = p;
b = p_v;
break;
default: // (5) Red is the dominant color
r = p_v;
g = p;
b = q;
break;
}
}
bool Color::is_equal_approx(const Color &p_color) const {
return Math::is_equal_approx(r, p_color.r) && Math::is_equal_approx(g, p_color.g) && Math::is_equal_approx(b, p_color.b) && Math::is_equal_approx(a, p_color.a);
}
Color Color::clamp(const Color &p_min, const Color &p_max) const {
return Color(
CLAMP(r, p_min.r, p_max.r),
CLAMP(g, p_min.g, p_max.g),
CLAMP(b, p_min.b, p_max.b),
CLAMP(a, p_min.a, p_max.a));
}
void Color::invert() {
r = 1.0 - r;
g = 1.0 - g;
b = 1.0 - b;
}
void Color::contrast() {
r = Math::fmod(r + 0.5, 1.0);
g = Math::fmod(g + 0.5, 1.0);
b = Math::fmod(b + 0.5, 1.0);
}
Color Color::hex(uint32_t p_hex) {
float a = (p_hex & 0xFF) / 255.0;
p_hex >>= 8;
float b = (p_hex & 0xFF) / 255.0;
p_hex >>= 8;
float g = (p_hex & 0xFF) / 255.0;
p_hex >>= 8;
float r = (p_hex & 0xFF) / 255.0;
return Color(r, g, b, a);
}
Color Color::hex64(uint64_t p_hex) {
float a = (p_hex & 0xFFFF) / 65535.0;
p_hex >>= 16;
float b = (p_hex & 0xFFFF) / 65535.0;
p_hex >>= 16;
float g = (p_hex & 0xFFFF) / 65535.0;
p_hex >>= 16;
float r = (p_hex & 0xFFFF) / 65535.0;
return Color(r, g, b, a);
}
Color Color::from_rgbe9995(uint32_t p_rgbe) {
float r = p_rgbe & 0x1ff;
float g = (p_rgbe >> 9) & 0x1ff;
float b = (p_rgbe >> 18) & 0x1ff;
float e = (p_rgbe >> 27);
float m = Math::pow(2, e - 15.0 - 9.0);
float rd = r * m;
float gd = g * m;
float bd = b * m;
return Color(rd, gd, bd, 1.0f);
}
static float _parse_col(const String &p_str, int p_ofs) {
int ig = 0;
for (int i = 0; i < 2; i++) {
int c = p_str[i + p_ofs];
int v = 0;
if (c >= '0' && c <= '9') {
v = c - '0';
} else if (c >= 'a' && c <= 'f') {
v = c - 'a';
v += 10;
} else if (c >= 'A' && c <= 'F') {
v = c - 'A';
v += 10;
} else {
return -1;
}
if (i == 0) {
ig += v * 16;
} else {
ig += v;
}
}
return ig;
}
Color Color::inverted() const {
Color c = *this;
c.invert();
return c;
}
Color Color::contrasted() const {
Color c = *this;
c.contrast();
return c;
}
Color Color::html(const String &p_color) {
String color = p_color;
if (color.length() == 0) {
return Color();
}
if (color[0] == '#') {
color = color.substr(1, color.length() - 1);
}
if (color.length() == 3 || color.length() == 4) {
String exp_color;
for (int i = 0; i < color.length(); i++) {
exp_color += color[i];
exp_color += color[i];
}
color = exp_color;
}
bool alpha = false;
if (color.length() == 8) {
alpha = true;
} else if (color.length() == 6) {
alpha = false;
} else {
ERR_FAIL_V_MSG(Color(), "Invalid color code: " + p_color + ".");
}
int a = 255;
if (alpha) {
a = _parse_col(color, 0);
ERR_FAIL_COND_V_MSG(a < 0, Color(), "Invalid color code: " + p_color + ".");
}
int from = alpha ? 2 : 0;
int r = _parse_col(color, from + 0);
ERR_FAIL_COND_V_MSG(r < 0, Color(), "Invalid color code: " + p_color + ".");
int g = _parse_col(color, from + 2);
ERR_FAIL_COND_V_MSG(g < 0, Color(), "Invalid color code: " + p_color + ".");
int b = _parse_col(color, from + 4);
ERR_FAIL_COND_V_MSG(b < 0, Color(), "Invalid color code: " + p_color + ".");
return Color(r / 255.0, g / 255.0, b / 255.0, a / 255.0);
}
bool Color::html_is_valid(const String &p_color) {
String color = p_color;
if (color.length() == 0) {
return false;
}
if (color[0] == '#') {
color = color.substr(1, color.length() - 1);
}
bool alpha = false;
if (color.length() == 8) {
alpha = true;
} else if (color.length() == 6) {
alpha = false;
} else {
return false;
}
if (alpha) {
int a = _parse_col(color, 0);
if (a < 0) {
return false;
}
}
int from = alpha ? 2 : 0;
int r = _parse_col(color, from + 0);
if (r < 0) {
return false;
}
int g = _parse_col(color, from + 2);
if (g < 0) {
return false;
}
int b = _parse_col(color, from + 4);
if (b < 0) {
return false;
}
return true;
}
String _to_hex(float p_val) {
int v = Math::round(p_val * 255);
v = CLAMP(v, 0, 255);
String ret;
for (int i = 0; i < 2; i++) {
CharType c[2] = { 0, 0 };
int lv = v & 0xF;
if (lv < 10) {
c[0] = '0' + lv;
} else {
c[0] = 'a' + lv - 10;
}
v >>= 4;
String cs = (const CharType *)c;
ret = cs + ret;
}
return ret;
}
String Color::to_html(bool p_alpha) const {
String txt;
txt += _to_hex(r);
txt += _to_hex(g);
txt += _to_hex(b);
if (p_alpha) {
txt = _to_hex(a) + txt;
}
return txt;
}
Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) const {
Color c;
c.set_hsv(p_h, p_s, p_v, p_a);
return c;
}
Color::operator String() const {
return "(" + String::num(r, 4) + ", " + String::num(g, 4) + ", " + String::num(b, 4) + ", " + String::num(a, 4) + ")";
}
Color Color::operator+(const Color &p_color) const {
return Color(
r + p_color.r,
g + p_color.g,
b + p_color.b,
a + p_color.a);
}
void Color::operator+=(const Color &p_color) {
r = r + p_color.r;
g = g + p_color.g;
b = b + p_color.b;
a = a + p_color.a;
}
Color Color::operator-(const Color &p_color) const {
return Color(
r - p_color.r,
g - p_color.g,
b - p_color.b,
a - p_color.a);
}
void Color::operator-=(const Color &p_color) {
r = r - p_color.r;
g = g - p_color.g;
b = b - p_color.b;
a = a - p_color.a;
}
Color Color::operator*(const Color &p_color) const {
return Color(
r * p_color.r,
g * p_color.g,
b * p_color.b,
a * p_color.a);
}
Color Color::operator*(const real_t &rvalue) const {
return Color(
r * rvalue,
g * rvalue,
b * rvalue,
a * rvalue);
}
void Color::operator*=(const Color &p_color) {
r = r * p_color.r;
g = g * p_color.g;
b = b * p_color.b;
a = a * p_color.a;
}
void Color::operator*=(const real_t &rvalue) {
r = r * rvalue;
g = g * rvalue;
b = b * rvalue;
a = a * rvalue;
}
Color Color::operator/(const Color &p_color) const {
return Color(
r / p_color.r,
g / p_color.g,
b / p_color.b,
a / p_color.a);
}
Color Color::operator/(const real_t &rvalue) const {
return Color(
r / rvalue,
g / rvalue,
b / rvalue,
a / rvalue);
}
void Color::operator/=(const Color &p_color) {
r = r / p_color.r;
g = g / p_color.g;
b = b / p_color.b;
a = a / p_color.a;
}
void Color::operator/=(const real_t &rvalue) {
if (rvalue == 0) {
r = 1.0;
g = 1.0;
b = 1.0;
a = 1.0;
} else {
r = r / rvalue;
g = g / rvalue;
b = b / rvalue;
a = a / rvalue;
}
};
Color Color::operator-() const {
return Color(
1.0 - r,
1.0 - g,
1.0 - b,
1.0 - a);
}

View File

@ -1,243 +0,0 @@
#ifndef COLOR_H
#define COLOR_H
/*************************************************************************/
/* color.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/math_funcs.h"
#include "core/ustring.h"
//--STRIP
struct _NO_DISCARD_CLASS_ Color {
union {
struct {
float r;
float g;
float b;
float a;
};
float components[4];
};
bool operator==(const Color &p_color) const { return (r == p_color.r && g == p_color.g && b == p_color.b && a == p_color.a); }
bool operator!=(const Color &p_color) const { return (r != p_color.r || g != p_color.g || b != p_color.b || a != p_color.a); }
uint32_t to_rgba32() const;
uint32_t to_argb32() const;
uint32_t to_abgr32() const;
uint64_t to_rgba64() const;
uint64_t to_argb64() const;
uint64_t to_abgr64() const;
float get_h() const;
float get_s() const;
float get_v() const;
void set_hsv(float p_h, float p_s, float p_v, float p_alpha = 1.0);
_FORCE_INLINE_ float &operator[](int idx) {
return components[idx];
}
_FORCE_INLINE_ const float &operator[](int idx) const {
return components[idx];
}
Color operator+(const Color &p_color) const;
void operator+=(const Color &p_color);
Color operator-() const;
Color operator-(const Color &p_color) const;
void operator-=(const Color &p_color);
Color operator*(const Color &p_color) const;
Color operator*(const real_t &rvalue) const;
void operator*=(const Color &p_color);
void operator*=(const real_t &rvalue);
Color operator/(const Color &p_color) const;
Color operator/(const real_t &rvalue) const;
void operator/=(const Color &p_color);
void operator/=(const real_t &rvalue);
bool is_equal_approx(const Color &p_color) const;
Color clamp(const Color &p_min = Color(0, 0, 0, 0), const Color &p_max = Color(1, 1, 1, 1)) const;
void invert();
void contrast();
Color inverted() const;
Color contrasted() const;
_FORCE_INLINE_ float get_luminance() const {
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
}
_FORCE_INLINE_ Color linear_interpolate(const Color &p_to, float p_weight) const {
Color res = *this;
res.r += (p_weight * (p_to.r - r));
res.g += (p_weight * (p_to.g - g));
res.b += (p_weight * (p_to.b - b));
res.a += (p_weight * (p_to.a - a));
return res;
}
_FORCE_INLINE_ Color darkened(float p_amount) const {
Color res = *this;
res.r = res.r * (1.0f - p_amount);
res.g = res.g * (1.0f - p_amount);
res.b = res.b * (1.0f - p_amount);
return res;
}
_FORCE_INLINE_ Color lightened(float p_amount) const {
Color res = *this;
res.r = res.r + (1.0f - res.r) * p_amount;
res.g = res.g + (1.0f - res.g) * p_amount;
res.b = res.b + (1.0f - res.b) * p_amount;
return res;
}
_FORCE_INLINE_ uint32_t to_rgbe9995() const {
const float pow2to9 = 512.0f;
const float B = 15.0f;
//const float Emax = 31.0f;
const float N = 9.0f;
float sharedexp = 65408.000f; //(( pow2to9 - 1.0f)/ pow2to9)*powf( 2.0f, 31.0f - 15.0f);
float cRed = MAX(0.0f, MIN(sharedexp, r));
float cGreen = MAX(0.0f, MIN(sharedexp, g));
float cBlue = MAX(0.0f, MIN(sharedexp, b));
float cMax = MAX(cRed, MAX(cGreen, cBlue));
// expp = MAX(-B - 1, log2(maxc)) + 1 + B
float expp = MAX(-B - 1.0f, floor(Math::log(cMax) / Math_LN2)) + 1.0f + B;
float sMax = (float)floor((cMax / Math::pow(2.0f, expp - B - N)) + 0.5f);
float exps = expp + 1.0f;
if (0.0 <= sMax && sMax < pow2to9) {
exps = expp;
}
float sRed = Math::floor((cRed / pow(2.0f, exps - B - N)) + 0.5f);
float sGreen = Math::floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f);
float sBlue = Math::floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f);
return (uint32_t(Math::fast_ftoi(sRed)) & 0x1FF) | ((uint32_t(Math::fast_ftoi(sGreen)) & 0x1FF) << 9) | ((uint32_t(Math::fast_ftoi(sBlue)) & 0x1FF) << 18) | ((uint32_t(Math::fast_ftoi(exps)) & 0x1F) << 27);
}
_FORCE_INLINE_ Color blend(const Color &p_over) const {
Color res;
float sa = 1.0 - p_over.a;
res.a = a * sa + p_over.a;
if (res.a == 0) {
return Color(0, 0, 0, 0);
} else {
res.r = (r * a * sa + p_over.r * p_over.a) / res.a;
res.g = (g * a * sa + p_over.g * p_over.a) / res.a;
res.b = (b * a * sa + p_over.b * p_over.a) / res.a;
}
return res;
}
_FORCE_INLINE_ Color to_linear() const {
return Color(
r < 0.04045 ? r * (1.0 / 12.92) : Math::pow((r + 0.055) * (1.0 / (1 + 0.055)), 2.4),
g < 0.04045 ? g * (1.0 / 12.92) : Math::pow((g + 0.055) * (1.0 / (1 + 0.055)), 2.4),
b < 0.04045 ? b * (1.0 / 12.92) : Math::pow((b + 0.055) * (1.0 / (1 + 0.055)), 2.4),
a);
}
_FORCE_INLINE_ Color to_srgb() const {
return Color(
r < 0.0031308 ? 12.92 * r : (1.0 + 0.055) * Math::pow(r, 1.0f / 2.4f) - 0.055,
g < 0.0031308 ? 12.92 * g : (1.0 + 0.055) * Math::pow(g, 1.0f / 2.4f) - 0.055,
b < 0.0031308 ? 12.92 * b : (1.0 + 0.055) * Math::pow(b, 1.0f / 2.4f) - 0.055, a);
}
static Color hex(uint32_t p_hex);
static Color hex64(uint64_t p_hex);
static Color html(const String &p_color);
static bool html_is_valid(const String &p_color);
String to_html(bool p_alpha = true) const;
Color from_hsv(float p_h, float p_s, float p_v, float p_a) const;
static Color from_rgbe9995(uint32_t p_rgbe);
_FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys
operator String() const;
static _FORCE_INLINE_ Color color8(int r, int g, int b) {
return Color(static_cast<float>(r) / 255.0f, static_cast<float>(g) / 255.0f, static_cast<float>(b) / 255.0f);
}
static _FORCE_INLINE_ Color color8(int r, int g, int b, int a) {
return Color(static_cast<float>(r) / 255.0f, static_cast<float>(g) / 255.0f, static_cast<float>(b) / 255.0f, static_cast<float>(a) / 255.0f);
}
_FORCE_INLINE_ void set_r8(int32_t r8) { r = (CLAMP(r8, 0, 255) / 255.0f); }
_FORCE_INLINE_ int32_t get_r8() const { return int32_t(CLAMP(Math::round(r * 255.0f), 0.0f, 255.0f)); }
_FORCE_INLINE_ void set_g8(int32_t g8) { g = (CLAMP(g8, 0, 255) / 255.0f); }
_FORCE_INLINE_ int32_t get_g8() const { return int32_t(CLAMP(Math::round(g * 255.0f), 0.0f, 255.0f)); }
_FORCE_INLINE_ void set_b8(int32_t b8) { b = (CLAMP(b8, 0, 255) / 255.0f); }
_FORCE_INLINE_ int32_t get_b8() const { return int32_t(CLAMP(Math::round(b * 255.0f), 0.0f, 255.0f)); }
_FORCE_INLINE_ void set_a8(int32_t a8) { a = (CLAMP(a8, 0, 255) / 255.0f); }
_FORCE_INLINE_ int32_t get_a8() const { return int32_t(CLAMP(Math::round(a * 255.0f), 0.0f, 255.0f)); }
_FORCE_INLINE_ void set_h(float p_h) { set_hsv(p_h, get_s(), get_v(), a); }
_FORCE_INLINE_ void set_s(float p_s) { set_hsv(get_h(), p_s, get_v(), a); }
_FORCE_INLINE_ void set_v(float p_v) { set_hsv(get_h(), get_s(), p_v, a); }
/**
* No construct parameters, r=0, g=0, b=0. a=255
*/
_FORCE_INLINE_ Color() {
r = 0;
g = 0;
b = 0;
a = 1.0;
}
/**
* RGB / RGBA construct parameters. Alpha is optional, but defaults to 1.0
*/
_FORCE_INLINE_ Color(float p_r, float p_g, float p_b, float p_a = 1.0) {
r = p_r;
g = p_g;
b = p_b;
a = p_a;
}
/**
* Construct a Color from another Color, but with the specified alpha value.
*/
_FORCE_INLINE_ Color(const Color &p_c, float p_a) {
r = p_c.r;
g = p_c.g;
b = p_c.b;
a = p_a;
}
};
bool Color::operator<(const Color &p_color) const {
if (r == p_color.r) {
if (g == p_color.g) {
if (b == p_color.b) {
return (a < p_color.a);
} else {
return (b < p_color.b);
}
} else {
return g < p_color.g;
}
} else {
return r < p_color.r;
}
}
#endif

View File

@ -1,368 +0,0 @@
/*************************************************************************/
/* face3.cpp */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "face3.h"
//--STRIP
int Face3::split_by_plane(const Plane &p_plane, Face3 p_res[3], bool p_is_point_over[3]) const {
ERR_FAIL_COND_V(is_degenerate(), 0);
Vector3 above[4];
int above_count = 0;
Vector3 below[4];
int below_count = 0;
for (int i = 0; i < 3; i++) {
if (p_plane.has_point(vertex[i], (real_t)CMP_EPSILON)) { // point is in plane
ERR_FAIL_COND_V(above_count >= 4, 0);
above[above_count++] = vertex[i];
ERR_FAIL_COND_V(below_count >= 4, 0);
below[below_count++] = vertex[i];
} else {
if (p_plane.is_point_over(vertex[i])) {
//Point is over
ERR_FAIL_COND_V(above_count >= 4, 0);
above[above_count++] = vertex[i];
} else {
//Point is under
ERR_FAIL_COND_V(below_count >= 4, 0);
below[below_count++] = vertex[i];
}
/* Check for Intersection between this and the next vertex*/
Vector3 inters;
if (!p_plane.intersects_segment(vertex[i], vertex[(i + 1) % 3], &inters)) {
continue;
}
/* Intersection goes to both */
ERR_FAIL_COND_V(above_count >= 4, 0);
above[above_count++] = inters;
ERR_FAIL_COND_V(below_count >= 4, 0);
below[below_count++] = inters;
}
}
int polygons_created = 0;
ERR_FAIL_COND_V(above_count >= 4 && below_count >= 4, 0); //bug in the algo
if (above_count >= 3) {
p_res[polygons_created] = Face3(above[0], above[1], above[2]);
p_is_point_over[polygons_created] = true;
polygons_created++;
if (above_count == 4) {
p_res[polygons_created] = Face3(above[2], above[3], above[0]);
p_is_point_over[polygons_created] = true;
polygons_created++;
}
}
if (below_count >= 3) {
p_res[polygons_created] = Face3(below[0], below[1], below[2]);
p_is_point_over[polygons_created] = false;
polygons_created++;
if (below_count == 4) {
p_res[polygons_created] = Face3(below[2], below[3], below[0]);
p_is_point_over[polygons_created] = false;
polygons_created++;
}
}
return polygons_created;
}
bool Face3::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection) const {
//return Geometry::ray_intersects_triangle(p_from, p_dir, vertex[0], vertex[1], vertex[2], p_intersection);
return false;
}
bool Face3::intersects_segment(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection) const {
//return Geometry::segment_intersects_triangle(p_from, p_dir, vertex[0], vertex[1], vertex[2], p_intersection);
return false;
}
bool Face3::is_degenerate() const {
Vector3 normal = vec3_cross(vertex[0] - vertex[1], vertex[0] - vertex[2]);
return (normal.length_squared() < (real_t)CMP_EPSILON2);
}
Face3::Side Face3::get_side_of(const Face3 &p_face, ClockDirection p_clock_dir) const {
int over = 0, under = 0;
Plane plane = get_plane(p_clock_dir);
for (int i = 0; i < 3; i++) {
const Vector3 &v = p_face.vertex[i];
if (plane.has_point(v)) { //coplanar, don't bother
continue;
}
if (plane.is_point_over(v)) {
over++;
} else {
under++;
}
}
if (over > 0 && under == 0) {
return SIDE_OVER;
} else if (under > 0 && over == 0) {
return SIDE_UNDER;
} else if (under == 0 && over == 0) {
return SIDE_COPLANAR;
} else {
return SIDE_SPANNING;
}
}
Vector3 Face3::get_random_point_inside() const {
real_t a = Math::random(0, 1);
real_t b = Math::random(0, 1);
if (a > b) {
SWAP(a, b);
}
return vertex[0] * a + vertex[1] * (b - a) + vertex[2] * (1.0 - b);
}
Plane Face3::get_plane(ClockDirection p_dir) const {
return Plane(vertex[0], vertex[1], vertex[2], p_dir);
}
Vector3 Face3::get_median_point() const {
return (vertex[0] + vertex[1] + vertex[2]) / 3.0;
}
real_t Face3::get_area() const {
return vec3_cross(vertex[0] - vertex[1], vertex[0] - vertex[2]).length() * 0.5;
}
ClockDirection Face3::get_clock_dir() const {
Vector3 normal = vec3_cross(vertex[0] - vertex[1], vertex[0] - vertex[2]);
//printf("normal is %g,%g,%g x %g,%g,%g- wtfu is %g\n",tofloat(normal.x),tofloat(normal.y),tofloat(normal.z),tofloat(vertex[0].x),tofloat(vertex[0].y),tofloat(vertex[0].z),tofloat( normal.dot( vertex[0] ) ) );
return (normal.dot(vertex[0]) >= 0) ? CLOCKWISE : COUNTERCLOCKWISE;
}
bool Face3::intersects_aabb(const AABB &p_aabb) const {
/** TEST PLANE **/
if (!p_aabb.intersects_plane(get_plane())) {
return false;
}
#define TEST_AXIS(m_ax) \
/** TEST FACE AXIS */ \
{ \
real_t aabb_min = p_aabb.position.m_ax; \
real_t aabb_max = p_aabb.position.m_ax + p_aabb.size.m_ax; \
real_t tri_min = vertex[0].m_ax; \
real_t tri_max = vertex[0].m_ax; \
for (int i = 1; i < 3; i++) { \
if (vertex[i].m_ax > tri_max) \
tri_max = vertex[i].m_ax; \
if (vertex[i].m_ax < tri_min) \
tri_min = vertex[i].m_ax; \
} \
\
if (tri_max < aabb_min || aabb_max < tri_min) \
return false; \
}
TEST_AXIS(x);
TEST_AXIS(y);
TEST_AXIS(z);
/** TEST ALL EDGES **/
Vector3 edge_norms[3] = {
vertex[0] - vertex[1],
vertex[1] - vertex[2],
vertex[2] - vertex[0],
};
for (int i = 0; i < 12; i++) {
Vector3 from, to;
p_aabb.get_edge(i, from, to);
Vector3 e1 = from - to;
for (int j = 0; j < 3; j++) {
Vector3 e2 = edge_norms[j];
Vector3 axis = vec3_cross(e1, e2);
if (axis.length_squared() < 0.0001f) {
continue; // coplanar
}
axis.normalize();
real_t minA, maxA, minB, maxB;
p_aabb.project_range_in_plane(Plane(axis, 0), minA, maxA);
project_range(axis, Transform(), minB, maxB);
if (maxA < minB || maxB < minA) {
return false;
}
}
}
return true;
}
Face3::operator String() const {
return String() + vertex[0] + ", " + vertex[1] + ", " + vertex[2];
}
void Face3::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const {
for (int i = 0; i < 3; i++) {
Vector3 v = p_transform.xform(vertex[i]);
real_t d = p_normal.dot(v);
if (i == 0 || d > r_max) {
r_max = d;
}
if (i == 0 || d < r_min) {
r_min = d;
}
}
}
void Face3::get_support(const Vector3 &p_normal, const Transform &p_transform, Vector3 *p_vertices, int *p_count, int p_max) const {
#define _FACE_IS_VALID_SUPPORT_THRESHOLD 0.98
#define _EDGE_IS_VALID_SUPPORT_THRESHOLD 0.05
if (p_max <= 0) {
return;
}
Vector3 n = p_transform.basis.xform_inv(p_normal);
/** TEST FACE AS SUPPORT **/
if (get_plane().normal.dot(n) > (real_t)_FACE_IS_VALID_SUPPORT_THRESHOLD) {
*p_count = MIN(3, p_max);
for (int i = 0; i < *p_count; i++) {
p_vertices[i] = p_transform.xform(vertex[i]);
}
return;
}
/** FIND SUPPORT VERTEX **/
int vert_support_idx = -1;
real_t support_max = 0;
for (int i = 0; i < 3; i++) {
real_t d = n.dot(vertex[i]);
if (i == 0 || d > support_max) {
support_max = d;
vert_support_idx = i;
}
}
/** TEST EDGES AS SUPPORT **/
for (int i = 0; i < 3; i++) {
if (i != vert_support_idx && i + 1 != vert_support_idx) {
continue;
}
// check if edge is valid as a support
real_t dot = (vertex[i] - vertex[(i + 1) % 3]).normalized().dot(n);
dot = ABS(dot);
if (dot < (real_t)_EDGE_IS_VALID_SUPPORT_THRESHOLD) {
*p_count = MIN(2, p_max);
for (int j = 0; j < *p_count; j++) {
p_vertices[j] = p_transform.xform(vertex[(j + i) % 3]);
}
return;
}
}
*p_count = 1;
p_vertices[0] = p_transform.xform(vertex[vert_support_idx]);
}
Vector3 Face3::get_closest_point_to(const Vector3 &p_point) const {
Vector3 edge0 = vertex[1] - vertex[0];
Vector3 edge1 = vertex[2] - vertex[0];
Vector3 v0 = vertex[0] - p_point;
real_t a = edge0.dot(edge0);
real_t b = edge0.dot(edge1);
real_t c = edge1.dot(edge1);
real_t d = edge0.dot(v0);
real_t e = edge1.dot(v0);
real_t det = a * c - b * b;
real_t s = b * e - c * d;
real_t t = b * d - a * e;
if (s + t < det) {
if (s < 0.f) {
if (t < 0.f) {
if (d < 0.f) {
s = CLAMP(-d / a, 0.f, 1.f);
t = 0.f;
} else {
s = 0.f;
t = CLAMP(-e / c, 0.f, 1.f);
}
} else {
s = 0.f;
t = CLAMP(-e / c, 0.f, 1.f);
}
} else if (t < 0.f) {
s = CLAMP(-d / a, 0.f, 1.f);
t = 0.f;
} else {
real_t invDet = 1.f / det;
s *= invDet;
t *= invDet;
}
} else {
if (s < 0.f) {
real_t tmp0 = b + d;
real_t tmp1 = c + e;
if (tmp1 > tmp0) {
real_t numer = tmp1 - tmp0;
real_t denom = a - 2 * b + c;
s = CLAMP(numer / denom, 0.f, 1.f);
t = 1 - s;
} else {
t = CLAMP(-e / c, 0.f, 1.f);
s = 0.f;
}
} else if (t < 0.f) {
if (a + d > b + e) {
real_t numer = c + e - b - d;
real_t denom = a - 2 * b + c;
s = CLAMP(numer / denom, 0.f, 1.f);
t = 1 - s;
} else {
s = CLAMP(-d / a, 0.f, 1.f);
t = 0.f;
}
} else {
real_t numer = c + e - b - d;
real_t denom = a - 2 * b + c;
s = CLAMP(numer / denom, 0.f, 1.f);
t = 1.f - s;
}
}
return vertex[0] + s * edge0 + t * edge1;
}

View File

@ -1,233 +0,0 @@
#ifndef FACE3_H
#define FACE3_H
/*************************************************************************/
/* face3.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/aabb.h"
#include "core/plane.h"
#include "core/transform.h"
#include "core/vector3.h"
//--STRIP
struct _NO_DISCARD_CLASS_ Face3 {
enum Side {
SIDE_OVER,
SIDE_UNDER,
SIDE_SPANNING,
SIDE_COPLANAR
};
Vector3 vertex[3];
/**
*
* @param p_plane plane used to split the face
* @param p_res array of at least 3 faces, amount used in function return
* @param p_is_point_over array of at least 3 booleans, determining which face is over the plane, amount used in function return
* @param _epsilon constant used for numerical error rounding, to add "thickness" to the plane (so coplanar points can happen)
* @return amount of faces generated by the split, either 0 (means no split possible), 2 or 3
*/
int split_by_plane(const Plane &p_plane, Face3 *p_res, bool *p_is_point_over) const;
Plane get_plane(ClockDirection p_dir = CLOCKWISE) const;
Vector3 get_random_point_inside() const;
Side get_side_of(const Face3 &p_face, ClockDirection p_clock_dir = CLOCKWISE) const;
bool is_degenerate() const;
real_t get_area() const;
real_t get_twice_area_squared() const;
Vector3 get_median_point() const;
Vector3 get_closest_point_to(const Vector3 &p_point) const;
bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection = nullptr) const;
bool intersects_segment(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection = nullptr) const;
ClockDirection get_clock_dir() const; ///< todo, test if this is returning the proper clockwisity
void get_support(const Vector3 &p_normal, const Transform &p_transform, Vector3 *p_vertices, int *p_count, int p_max) const;
void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
AABB get_aabb() const {
AABB aabb(vertex[0], Vector3());
aabb.expand_to(vertex[1]);
aabb.expand_to(vertex[2]);
return aabb;
}
bool intersects_aabb(const AABB &p_aabb) const;
_FORCE_INLINE_ bool intersects_aabb2(const AABB &p_aabb) const;
operator String() const;
inline Face3() {}
inline Face3(const Vector3 &p_v1, const Vector3 &p_v2, const Vector3 &p_v3) {
vertex[0] = p_v1;
vertex[1] = p_v2;
vertex[2] = p_v3;
}
};
inline real_t Face3::get_twice_area_squared() const {
Vector3 edge1 = vertex[1] - vertex[0];
Vector3 edge2 = vertex[2] - vertex[0];
return edge1.cross(edge2).length_squared();
}
bool Face3::intersects_aabb2(const AABB &p_aabb) const {
Vector3 perp = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]);
Vector3 half_extents = p_aabb.size * 0.5f;
Vector3 ofs = p_aabb.position + half_extents;
Vector3 sup = Vector3(
(perp.x > 0) ? -half_extents.x : half_extents.x,
(perp.y > 0) ? -half_extents.y : half_extents.y,
(perp.z > 0) ? -half_extents.z : half_extents.z);
real_t d = perp.dot(vertex[0]);
real_t dist_a = perp.dot(ofs + sup) - d;
real_t dist_b = perp.dot(ofs - sup) - d;
if (dist_a * dist_b > 0) {
return false; //does not intersect the plane
}
#define TEST_AXIS(m_ax) \
{ \
real_t aabb_min = p_aabb.position.m_ax; \
real_t aabb_max = p_aabb.position.m_ax + p_aabb.size.m_ax; \
real_t tri_min, tri_max; \
for (int i = 0; i < 3; i++) { \
if (i == 0 || vertex[i].m_ax > tri_max) \
tri_max = vertex[i].m_ax; \
if (i == 0 || vertex[i].m_ax < tri_min) \
tri_min = vertex[i].m_ax; \
} \
\
if (tri_max < aabb_min || aabb_max < tri_min) \
return false; \
}
TEST_AXIS(x);
TEST_AXIS(y);
TEST_AXIS(z);
#undef TEST_AXIS
Vector3 edge_norms[3] = {
vertex[0] - vertex[1],
vertex[1] - vertex[2],
vertex[2] - vertex[0],
};
for (int i = 0; i < 12; i++) {
Vector3 from, to;
switch (i) {
case 0: {
from = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z);
to = Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z);
} break;
case 1: {
from = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z);
to = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z);
} break;
case 2: {
from = Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z);
to = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z);
} break;
case 3: {
from = Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z);
to = Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z);
} break;
case 4: {
from = Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z);
to = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z);
} break;
case 5: {
from = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z);
to = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z);
} break;
case 6: {
from = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z);
to = Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z);
} break;
case 7: {
from = Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z);
to = Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z);
} break;
case 8: {
from = Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z);
to = Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z);
} break;
case 9: {
from = Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z);
to = Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z);
} break;
case 10: {
from = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z);
to = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z);
} break;
case 11: {
from = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z);
to = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z);
} break;
}
Vector3 e1 = from - to;
for (int j = 0; j < 3; j++) {
Vector3 e2 = edge_norms[j];
Vector3 axis = vec3_cross(e1, e2);
if (axis.length_squared() < 0.0001f) {
continue; // coplanar
}
//axis.normalize();
Vector3 sup2 = Vector3(
(axis.x > 0) ? -half_extents.x : half_extents.x,
(axis.y > 0) ? -half_extents.y : half_extents.y,
(axis.z > 0) ? -half_extents.z : half_extents.z);
real_t maxB = axis.dot(ofs + sup2);
real_t minB = axis.dot(ofs - sup2);
if (minB > maxB) {
SWAP(maxB, minB);
}
real_t minT = 1e20, maxT = -1e20;
for (int k = 0; k < 3; k++) {
real_t vert_d = axis.dot(vertex[k]);
if (vert_d > maxT) {
maxT = vert_d;
}
if (vert_d < minT) {
minT = vert_d;
}
}
if (maxB < minT || maxT < minB) {
return false;
}
}
}
return true;
}
#endif // FACE3_H

View File

@ -1,134 +0,0 @@
/*************************************************************************/
/* plane.cpp */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/plane.h"
#include "core/math_funcs.h"
//--STRIP
void Plane::set_normal(const Vector3 &p_normal) {
normal = p_normal;
}
void Plane::normalize() {
real_t l = normal.length();
if (l == 0) {
*this = Plane(0, 0, 0, 0);
return;
}
normal /= l;
d /= l;
}
Plane Plane::normalized() const {
Plane p = *this;
p.normalize();
return p;
}
Vector3 Plane::get_any_point() const {
return get_normal() * d;
}
Vector3 Plane::get_any_perpendicular_normal() const {
static const Vector3 p1 = Vector3(1, 0, 0);
static const Vector3 p2 = Vector3(0, 1, 0);
Vector3 p;
if (ABS(normal.dot(p1)) > 0.99f) { // if too similar to p1
p = p2; // use p2
} else {
p = p1; // use p1
}
p -= normal * normal.dot(p);
p.normalize();
return p;
}
/* intersections */
bool Plane::intersect_3(const Plane &p_plane1, const Plane &p_plane2, Vector3 *r_result) const {
const Plane &p_plane0 = *this;
Vector3 normal0 = p_plane0.normal;
Vector3 normal1 = p_plane1.normal;
Vector3 normal2 = p_plane2.normal;
real_t denom = vec3_cross(normal0, normal1).dot(normal2);
if (Math::is_zero_approx(denom)) {
return false;
}
if (r_result) {
*r_result = ((vec3_cross(normal1, normal2) * p_plane0.d) +
(vec3_cross(normal2, normal0) * p_plane1.d) +
(vec3_cross(normal0, normal1) * p_plane2.d)) /
denom;
}
return true;
}
bool Plane::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection) const {
Vector3 segment = p_dir;
real_t den = normal.dot(segment);
//printf("den is %i\n",den);
if (Math::is_zero_approx(den)) {
return false;
}
real_t dist = (normal.dot(p_from) - d) / den;
//printf("dist is %i\n",dist);
if (dist > (real_t)CMP_EPSILON) { //this is a ray, before the emitting pos (p_from) doesn't exist
return false;
}
dist = -dist;
*p_intersection = p_from + segment * dist;
return true;
}
bool Plane::intersects_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 *p_intersection) const {
Vector3 segment = p_begin - p_end;
real_t den = normal.dot(segment);
//printf("den is %i\n",den);
if (Math::is_zero_approx(den)) {
return false;
}
real_t dist = (normal.dot(p_begin) - d) / den;
//printf("dist is %i\n",dist);
if (dist < (real_t)-CMP_EPSILON || dist > (1 + (real_t)CMP_EPSILON)) {
return false;
}
dist = -dist;
*p_intersection = p_begin + segment * dist;
return true;
}
/* misc */
bool Plane::is_equal_approx(const Plane &p_plane) const {
return normal.is_equal_approx(p_plane.normal) && Math::is_equal_approx(d, p_plane.d);
}
bool Plane::is_equal_approx_any_side(const Plane &p_plane) const {
return (normal.is_equal_approx(p_plane.normal) && Math::is_equal_approx(d, p_plane.d)) || (normal.is_equal_approx(-p_plane.normal) && Math::is_equal_approx(d, -p_plane.d));
}
Plane::operator String() const {
return "[N: " + normal.operator String() + ", D: " + String::num_real(d) + "]";
}

View File

@ -1,107 +0,0 @@
#ifndef PLANE_H
#define PLANE_H
/*************************************************************************/
/* plane.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/vector3.h"
//--STRIP
struct _NO_DISCARD_CLASS_ Plane {
Vector3 normal;
real_t d;
void set_normal(const Vector3 &p_normal);
_FORCE_INLINE_ Vector3 get_normal() const { return normal; }; ///Point is coplanar, CMP_EPSILON for precision
void normalize();
Plane normalized() const;
/* Plane-Point operations */
_FORCE_INLINE_ Vector3 center() const { return normal * d; }
Vector3 get_any_point() const;
Vector3 get_any_perpendicular_normal() const;
_FORCE_INLINE_ bool is_point_over(const Vector3 &p_point) const; ///< Point is over plane
_FORCE_INLINE_ real_t distance_to(const Vector3 &p_point) const;
_FORCE_INLINE_ bool has_point(const Vector3 &p_point, real_t _epsilon = CMP_EPSILON) const;
/* intersections */
bool intersect_3(const Plane &p_plane1, const Plane &p_plane2, Vector3 *r_result = nullptr) const;
bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection) const;
bool intersects_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 *p_intersection) const;
_FORCE_INLINE_ Vector3 project(const Vector3 &p_point) const {
return p_point - normal * distance_to(p_point);
}
/* misc */
Plane operator-() const { return Plane(-normal, -d); }
bool is_equal_approx(const Plane &p_plane) const;
bool is_equal_approx_any_side(const Plane &p_plane) const;
_FORCE_INLINE_ bool operator==(const Plane &p_plane) const;
_FORCE_INLINE_ bool operator!=(const Plane &p_plane) const;
operator String() const;
_FORCE_INLINE_ Plane() :
d(0) {}
_FORCE_INLINE_ Plane(real_t p_a, real_t p_b, real_t p_c, real_t p_d) :
normal(p_a, p_b, p_c),
d(p_d) {}
_FORCE_INLINE_ Plane(const Vector3 &p_normal, real_t p_d);
_FORCE_INLINE_ Plane(const Vector3 &p_point, const Vector3 &p_normal);
_FORCE_INLINE_ Plane(const Vector3 &p_point1, const Vector3 &p_point2, const Vector3 &p_point3, ClockDirection p_dir = CLOCKWISE);
};
bool Plane::is_point_over(const Vector3 &p_point) const {
return (normal.dot(p_point) > d);
}
real_t Plane::distance_to(const Vector3 &p_point) const {
return (normal.dot(p_point) - d);
}
bool Plane::has_point(const Vector3 &p_point, real_t _epsilon) const {
real_t dist = normal.dot(p_point) - d;
dist = ABS(dist);
return (dist <= _epsilon);
}
Plane::Plane(const Vector3 &p_normal, real_t p_d) :
normal(p_normal),
d(p_d) {
}
Plane::Plane(const Vector3 &p_point, const Vector3 &p_normal) :
normal(p_normal),
d(p_normal.dot(p_point)) {
}
Plane::Plane(const Vector3 &p_point1, const Vector3 &p_point2, const Vector3 &p_point3, ClockDirection p_dir) {
if (p_dir == CLOCKWISE) {
normal = (p_point1 - p_point3).cross(p_point1 - p_point2);
} else {
normal = (p_point1 - p_point2).cross(p_point1 - p_point3);
}
normal.normalize();
d = normal.dot(p_point1);
}
bool Plane::operator==(const Plane &p_plane) const {
return normal == p_plane.normal && d == p_plane.d;
}
bool Plane::operator!=(const Plane &p_plane) const {
return normal != p_plane.normal || d != p_plane.d;
}
#endif // PLANE_H

View File

@ -1,909 +0,0 @@
/*************************************************************************/
/* projection.cpp */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/projection.h"
#include "core/aabb.h"
#include "core/math_funcs.h"
#include "core/plane.h"
#include "core/rect2.h"
#include "core/transform.h"
//--STRIP
float Projection::determinant() const {
return matrix[0][3] * matrix[1][2] * matrix[2][1] * matrix[3][0] - matrix[0][2] * matrix[1][3] * matrix[2][1] * matrix[3][0] -
matrix[0][3] * matrix[1][1] * matrix[2][2] * matrix[3][0] + matrix[0][1] * matrix[1][3] * matrix[2][2] * matrix[3][0] +
matrix[0][2] * matrix[1][1] * matrix[2][3] * matrix[3][0] - matrix[0][1] * matrix[1][2] * matrix[2][3] * matrix[3][0] -
matrix[0][3] * matrix[1][2] * matrix[2][0] * matrix[3][1] + matrix[0][2] * matrix[1][3] * matrix[2][0] * matrix[3][1] +
matrix[0][3] * matrix[1][0] * matrix[2][2] * matrix[3][1] - matrix[0][0] * matrix[1][3] * matrix[2][2] * matrix[3][1] -
matrix[0][2] * matrix[1][0] * matrix[2][3] * matrix[3][1] + matrix[0][0] * matrix[1][2] * matrix[2][3] * matrix[3][1] +
matrix[0][3] * matrix[1][1] * matrix[2][0] * matrix[3][2] - matrix[0][1] * matrix[1][3] * matrix[2][0] * matrix[3][2] -
matrix[0][3] * matrix[1][0] * matrix[2][1] * matrix[3][2] + matrix[0][0] * matrix[1][3] * matrix[2][1] * matrix[3][2] +
matrix[0][1] * matrix[1][0] * matrix[2][3] * matrix[3][2] - matrix[0][0] * matrix[1][1] * matrix[2][3] * matrix[3][2] -
matrix[0][2] * matrix[1][1] * matrix[2][0] * matrix[3][3] + matrix[0][1] * matrix[1][2] * matrix[2][0] * matrix[3][3] +
matrix[0][2] * matrix[1][0] * matrix[2][1] * matrix[3][3] - matrix[0][0] * matrix[1][2] * matrix[2][1] * matrix[3][3] -
matrix[0][1] * matrix[1][0] * matrix[2][2] * matrix[3][3] + matrix[0][0] * matrix[1][1] * matrix[2][2] * matrix[3][3];
}
void Projection::set_identity() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
matrix[i][j] = (i == j) ? 1 : 0;
}
}
}
void Projection::set_zero() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
matrix[i][j] = 0;
}
}
}
void Projection::adjust_perspective_znear(real_t p_new_znear) {
real_t zfar = get_z_far();
real_t znear = p_new_znear;
real_t deltaZ = zfar - znear;
matrix[2][2] = -(zfar + znear) / deltaZ;
matrix[3][2] = -2 * znear * zfar / deltaZ;
}
Projection Projection::create_depth_correction(bool p_flip_y) {
Projection proj;
proj.set_depth_correction(p_flip_y);
return proj;
}
Projection Projection::create_light_atlas_rect(const Rect2 &p_rect) {
Projection proj;
proj.set_light_atlas_rect(p_rect);
return proj;
}
Projection Projection::create_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov) {
Projection proj;
proj.set_perspective(p_fovy_degrees, p_aspect, p_z_near, p_z_far, p_flip_fov);
return proj;
}
Projection Projection::create_perspective_hmd(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist) {
Projection proj;
proj.set_perspective(p_fovy_degrees, p_aspect, p_z_near, p_z_far, p_flip_fov, p_eye, p_intraocular_dist, p_convergence_dist);
return proj;
}
Projection Projection::create_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_dist, real_t p_display_width, real_t p_display_to_lens, real_t p_oversample, real_t p_z_near, real_t p_z_far) {
Projection proj;
proj.set_for_hmd(p_eye, p_aspect, p_intraocular_dist, p_display_width, p_display_to_lens, p_oversample, p_z_near, p_z_far);
return proj;
}
Projection Projection::create_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar) {
Projection proj;
proj.set_orthogonal(p_left, p_right, p_bottom, p_top, p_zfar, p_zfar);
return proj;
}
Projection Projection::create_orthogonal_aspect(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov) {
Projection proj;
proj.set_orthogonal(p_size, p_aspect, p_znear, p_zfar, p_flip_fov);
return proj;
}
Projection Projection::create_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far) {
Projection proj;
proj.set_frustum(p_left, p_right, p_bottom, p_top, p_near, p_far);
return proj;
}
Projection Projection::create_frustum_aspect(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov) {
Projection proj;
proj.set_frustum(p_size, p_aspect, p_offset, p_near, p_far, p_flip_fov);
return proj;
}
Projection Projection::create_fit_aabb(const AABB &p_aabb) {
Projection proj;
proj.scale_translate_to_fit(p_aabb);
return proj;
}
Projection Projection::perspective_znear_adjusted(real_t p_new_znear) const {
Projection proj = *this;
proj.adjust_perspective_znear(p_new_znear);
return proj;
}
Plane Projection::get_projection_plane(Projection::Planes p_plane) const {
const real_t *matrix = (const real_t *)this->matrix;
switch (p_plane) {
case PLANE_NEAR: {
Plane new_plane = Plane(matrix[3] + matrix[2],
matrix[7] + matrix[6],
matrix[11] + matrix[10],
matrix[15] + matrix[14]);
new_plane.normal = -new_plane.normal;
new_plane.normalize();
return new_plane;
} break;
case PLANE_FAR: {
Plane new_plane = Plane(matrix[3] - matrix[2],
matrix[7] - matrix[6],
matrix[11] - matrix[10],
matrix[15] - matrix[14]);
new_plane.normal = -new_plane.normal;
new_plane.normalize();
return new_plane;
} break;
case PLANE_LEFT: {
Plane new_plane = Plane(matrix[3] + matrix[0],
matrix[7] + matrix[4],
matrix[11] + matrix[8],
matrix[15] + matrix[12]);
new_plane.normal = -new_plane.normal;
new_plane.normalize();
return new_plane;
} break;
case PLANE_TOP: {
Plane new_plane = Plane(matrix[3] - matrix[1],
matrix[7] - matrix[5],
matrix[11] - matrix[9],
matrix[15] - matrix[13]);
new_plane.normal = -new_plane.normal;
new_plane.normalize();
return new_plane;
} break;
case PLANE_RIGHT: {
Plane new_plane = Plane(matrix[3] - matrix[0],
matrix[7] - matrix[4],
matrix[11] - matrix[8],
matrix[15] - matrix[12]);
new_plane.normal = -new_plane.normal;
new_plane.normalize();
return new_plane;
} break;
case PLANE_BOTTOM: {
Plane new_plane = Plane(matrix[3] + matrix[1],
matrix[7] + matrix[5],
matrix[11] + matrix[9],
matrix[15] + matrix[13]);
new_plane.normal = -new_plane.normal;
new_plane.normalize();
return new_plane;
} break;
}
return Plane();
}
Projection Projection::flipped_y() const {
Projection proj = *this;
proj.flip_y();
return proj;
}
Projection Projection ::jitter_offseted(const Vector2 &p_offset) const {
Projection proj = *this;
proj.add_jitter_offset(p_offset);
return proj;
}
void Projection::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov) {
if (p_flip_fov) {
p_fovy_degrees = get_fovy(p_fovy_degrees, 1.0 / p_aspect);
}
real_t sine, cotangent, deltaZ;
real_t radians = Math::deg2rad(p_fovy_degrees / 2.0);
deltaZ = p_z_far - p_z_near;
sine = Math::sin(radians);
if ((deltaZ == 0) || (sine == 0) || (p_aspect == 0)) {
return;
}
cotangent = Math::cos(radians) / sine;
set_identity();
matrix[0][0] = cotangent / p_aspect;
matrix[1][1] = cotangent;
matrix[2][2] = -(p_z_far + p_z_near) / deltaZ;
matrix[2][3] = -1;
matrix[3][2] = -2 * p_z_near * p_z_far / deltaZ;
matrix[3][3] = 0;
}
void Projection::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist) {
if (p_flip_fov) {
p_fovy_degrees = get_fovy(p_fovy_degrees, 1.0 / p_aspect);
}
real_t left, right, modeltranslation, ymax, xmax, frustumshift;
ymax = p_z_near * tan(Math::deg2rad(p_fovy_degrees / 2.0));
xmax = ymax * p_aspect;
frustumshift = (p_intraocular_dist / 2.0) * p_z_near / p_convergence_dist;
switch (p_eye) {
case 1: { // left eye
left = -xmax + frustumshift;
right = xmax + frustumshift;
modeltranslation = p_intraocular_dist / 2.0;
} break;
case 2: { // right eye
left = -xmax - frustumshift;
right = xmax - frustumshift;
modeltranslation = -p_intraocular_dist / 2.0;
} break;
default: { // mono, should give the same result as set_perspective(p_fovy_degrees,p_aspect,p_z_near,p_z_far,p_flip_fov)
left = -xmax;
right = xmax;
modeltranslation = 0.0;
} break;
}
set_frustum(left, right, -ymax, ymax, p_z_near, p_z_far);
// translate matrix by (modeltranslation, 0.0, 0.0)
Projection cm;
cm.set_identity();
cm.matrix[3][0] = modeltranslation;
*this = *this * cm;
}
void Projection::set_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_dist, real_t p_display_width, real_t p_display_to_lens, real_t p_oversample, real_t p_z_near, real_t p_z_far) {
// we first calculate our base frustum on our values without taking our lens magnification into account.
real_t f1 = (p_intraocular_dist * 0.5) / p_display_to_lens;
real_t f2 = ((p_display_width - p_intraocular_dist) * 0.5) / p_display_to_lens;
real_t f3 = (p_display_width / 4.0) / p_display_to_lens;
// now we apply our oversample factor to increase our FOV. how much we oversample is always a balance we strike between performance and how much
// we're willing to sacrifice in FOV.
real_t add = ((f1 + f2) * (p_oversample - 1.0)) / 2.0;
f1 += add;
f2 += add;
f3 *= p_oversample;
// always apply KEEP_WIDTH aspect ratio
f3 /= p_aspect;
switch (p_eye) {
case 1: { // left eye
set_frustum(-f2 * p_z_near, f1 * p_z_near, -f3 * p_z_near, f3 * p_z_near, p_z_near, p_z_far);
} break;
case 2: { // right eye
set_frustum(-f1 * p_z_near, f2 * p_z_near, -f3 * p_z_near, f3 * p_z_near, p_z_near, p_z_far);
} break;
default: { // mono, does not apply here!
} break;
}
}
void Projection::set_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar) {
set_identity();
matrix[0][0] = 2.0 / (p_right - p_left);
matrix[3][0] = -((p_right + p_left) / (p_right - p_left));
matrix[1][1] = 2.0 / (p_top - p_bottom);
matrix[3][1] = -((p_top + p_bottom) / (p_top - p_bottom));
matrix[2][2] = -2.0 / (p_zfar - p_znear);
matrix[3][2] = -((p_zfar + p_znear) / (p_zfar - p_znear));
matrix[3][3] = 1.0;
}
void Projection::set_orthogonal(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov) {
if (!p_flip_fov) {
p_size *= p_aspect;
}
set_orthogonal(-p_size / 2, +p_size / 2, -p_size / p_aspect / 2, +p_size / p_aspect / 2, p_znear, p_zfar);
}
void Projection::set_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far) {
ERR_FAIL_COND(p_right <= p_left);
ERR_FAIL_COND(p_top <= p_bottom);
ERR_FAIL_COND(p_far <= p_near);
real_t *te = &matrix[0][0];
real_t x = 2 * p_near / (p_right - p_left);
real_t y = 2 * p_near / (p_top - p_bottom);
real_t a = (p_right + p_left) / (p_right - p_left);
real_t b = (p_top + p_bottom) / (p_top - p_bottom);
real_t c = -(p_far + p_near) / (p_far - p_near);
real_t d = -2 * p_far * p_near / (p_far - p_near);
te[0] = x;
te[1] = 0;
te[2] = 0;
te[3] = 0;
te[4] = 0;
te[5] = y;
te[6] = 0;
te[7] = 0;
te[8] = a;
te[9] = b;
te[10] = c;
te[11] = -1;
te[12] = 0;
te[13] = 0;
te[14] = d;
te[15] = 0;
}
void Projection::set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov) {
if (!p_flip_fov) {
p_size *= p_aspect;
}
set_frustum(-p_size / 2 + p_offset.x, +p_size / 2 + p_offset.x, -p_size / p_aspect / 2 + p_offset.y, +p_size / p_aspect / 2 + p_offset.y, p_near, p_far);
}
real_t Projection::get_z_far() const {
const real_t *matrix = (const real_t *)this->matrix;
Plane new_plane = Plane(matrix[3] - matrix[2],
matrix[7] - matrix[6],
matrix[11] - matrix[10],
matrix[15] - matrix[14]);
new_plane.normal = -new_plane.normal;
new_plane.normalize();
return new_plane.d;
}
real_t Projection::get_z_near() const {
const real_t *matrix = (const real_t *)this->matrix;
Plane new_plane = Plane(matrix[3] + matrix[2],
matrix[7] + matrix[6],
matrix[11] + matrix[10],
-matrix[15] - matrix[14]);
new_plane.normalize();
return new_plane.d;
}
Vector2 Projection::get_viewport_half_extents() const {
const real_t *matrix = (const real_t *)this->matrix;
///////--- Near Plane ---///////
Plane near_plane = Plane(matrix[3] + matrix[2],
matrix[7] + matrix[6],
matrix[11] + matrix[10],
-matrix[15] - matrix[14]);
near_plane.normalize();
///////--- Right Plane ---///////
Plane right_plane = Plane(matrix[3] - matrix[0],
matrix[7] - matrix[4],
matrix[11] - matrix[8],
-matrix[15] + matrix[12]);
right_plane.normalize();
Plane top_plane = Plane(matrix[3] - matrix[1],
matrix[7] - matrix[5],
matrix[11] - matrix[9],
-matrix[15] + matrix[13]);
top_plane.normalize();
Vector3 res;
near_plane.intersect_3(right_plane, top_plane, &res);
return Vector2(res.x, res.y);
}
Vector2 Projection::get_far_plane_half_extents() const {
const real_t *matrix = (const real_t *)this->matrix;
///////--- Far Plane ---///////
Plane far_plane = Plane(matrix[3] - matrix[2],
matrix[7] - matrix[6],
matrix[11] - matrix[10],
-matrix[15] + matrix[14]);
far_plane.normalize();
///////--- Right Plane ---///////
Plane right_plane = Plane(matrix[3] - matrix[0],
matrix[7] - matrix[4],
matrix[11] - matrix[8],
-matrix[15] + matrix[12]);
right_plane.normalize();
Plane top_plane = Plane(matrix[3] - matrix[1],
matrix[7] - matrix[5],
matrix[11] - matrix[9],
-matrix[15] + matrix[13]);
top_plane.normalize();
Vector3 res;
far_plane.intersect_3(right_plane, top_plane, &res);
return Vector2(res.x, res.y);
}
bool Projection::get_endpoints(const Transform &p_transform, Vector3 *p_8points) const {
Vector<Plane> planes = get_projection_planes(Transform());
const Planes intersections[8][3] = {
{ PLANE_FAR, PLANE_LEFT, PLANE_TOP },
{ PLANE_FAR, PLANE_LEFT, PLANE_BOTTOM },
{ PLANE_FAR, PLANE_RIGHT, PLANE_TOP },
{ PLANE_FAR, PLANE_RIGHT, PLANE_BOTTOM },
{ PLANE_NEAR, PLANE_LEFT, PLANE_TOP },
{ PLANE_NEAR, PLANE_LEFT, PLANE_BOTTOM },
{ PLANE_NEAR, PLANE_RIGHT, PLANE_TOP },
{ PLANE_NEAR, PLANE_RIGHT, PLANE_BOTTOM },
};
for (int i = 0; i < 8; i++) {
Vector3 point;
bool res = planes[intersections[i][0]].intersect_3(planes[intersections[i][1]], planes[intersections[i][2]], &point);
ERR_FAIL_COND_V(!res, false);
p_8points[i] = p_transform.xform(point);
}
return true;
}
Vector<Plane> Projection::get_projection_planes(const Transform &p_transform) const {
/** Fast Plane Extraction from combined modelview/projection matrices.
* References:
* https://web.archive.org/web/20011221205252/https://www.markmorley.com/opengl/frustumculling.html
* https://web.archive.org/web/20061020020112/https://www2.ravensoft.com/users/ggribb/plane%20extraction.pdf
*/
Vector<Plane> planes;
planes.resize(6);
const real_t *matrix = (const real_t *)this->matrix;
Plane new_plane;
///////--- Near Plane ---///////
new_plane = Plane(matrix[3] + matrix[2],
matrix[7] + matrix[6],
matrix[11] + matrix[10],
matrix[15] + matrix[14]);
new_plane.normal = -new_plane.normal;
new_plane.normalize();
planes.write[0] = p_transform.xform(new_plane);
///////--- Far Plane ---///////
new_plane = Plane(matrix[3] - matrix[2],
matrix[7] - matrix[6],
matrix[11] - matrix[10],
matrix[15] - matrix[14]);
new_plane.normal = -new_plane.normal;
new_plane.normalize();
planes.write[1] = p_transform.xform(new_plane);
///////--- Left Plane ---///////
new_plane = Plane(matrix[3] + matrix[0],
matrix[7] + matrix[4],
matrix[11] + matrix[8],
matrix[15] + matrix[12]);
new_plane.normal = -new_plane.normal;
new_plane.normalize();
planes.write[2] = p_transform.xform(new_plane);
///////--- Top Plane ---///////
new_plane = Plane(matrix[3] - matrix[1],
matrix[7] - matrix[5],
matrix[11] - matrix[9],
matrix[15] - matrix[13]);
new_plane.normal = -new_plane.normal;
new_plane.normalize();
planes.write[3] = p_transform.xform(new_plane);
///////--- Right Plane ---///////
new_plane = Plane(matrix[3] - matrix[0],
matrix[7] - matrix[4],
matrix[11] - matrix[8],
matrix[15] - matrix[12]);
new_plane.normal = -new_plane.normal;
new_plane.normalize();
planes.write[4] = p_transform.xform(new_plane);
///////--- Bottom Plane ---///////
new_plane = Plane(matrix[3] + matrix[1],
matrix[7] + matrix[5],
matrix[11] + matrix[9],
matrix[15] + matrix[13]);
new_plane.normal = -new_plane.normal;
new_plane.normalize();
planes.write[5] = p_transform.xform(new_plane);
return planes;
}
Projection Projection::inverse() const {
Projection cm = *this;
cm.invert();
return cm;
}
void Projection::invert() {
int i, j, k;
int pvt_i[4], pvt_j[4]; /* Locations of pivot matrix */
real_t pvt_val; /* Value of current pivot element */
real_t hold; /* Temporary storage */
real_t determinant = 1.0f;
for (k = 0; k < 4; k++) {
/** Locate k'th pivot element **/
pvt_val = matrix[k][k]; /** Initialize for search **/
pvt_i[k] = k;
pvt_j[k] = k;
for (i = k; i < 4; i++) {
for (j = k; j < 4; j++) {
if (Math::abs(matrix[i][j]) > Math::abs(pvt_val)) {
pvt_i[k] = i;
pvt_j[k] = j;
pvt_val = matrix[i][j];
}
}
}
/** Product of pivots, gives determinant when finished **/
determinant *= pvt_val;
if (Math::is_zero_approx(determinant)) {
return; /** Matrix is singular (zero determinant). **/
}
/** "Interchange" rows (with sign change stuff) **/
i = pvt_i[k];
if (i != k) { /** If rows are different **/
for (j = 0; j < 4; j++) {
hold = -matrix[k][j];
matrix[k][j] = matrix[i][j];
matrix[i][j] = hold;
}
}
/** "Interchange" columns **/
j = pvt_j[k];
if (j != k) { /** If columns are different **/
for (i = 0; i < 4; i++) {
hold = -matrix[i][k];
matrix[i][k] = matrix[i][j];
matrix[i][j] = hold;
}
}
/** Divide column by minus pivot value **/
for (i = 0; i < 4; i++) {
if (i != k) {
matrix[i][k] /= (-pvt_val);
}
}
/** Reduce the matrix **/
for (i = 0; i < 4; i++) {
hold = matrix[i][k];
for (j = 0; j < 4; j++) {
if (i != k && j != k) {
matrix[i][j] += hold * matrix[k][j];
}
}
}
/** Divide row by pivot **/
for (j = 0; j < 4; j++) {
if (j != k) {
matrix[k][j] /= pvt_val;
}
}
/** Replace pivot by reciprocal (at last we can touch it). **/
matrix[k][k] = 1.0 / pvt_val;
}
/* That was most of the work, one final pass of row/column interchange */
/* to finish */
for (k = 4 - 2; k >= 0; k--) { /* Don't need to work with 1 by 1 corner*/
i = pvt_j[k]; /* Rows to swap correspond to pivot COLUMN */
if (i != k) { /* If rows are different */
for (j = 0; j < 4; j++) {
hold = matrix[k][j];
matrix[k][j] = -matrix[i][j];
matrix[i][j] = hold;
}
}
j = pvt_i[k]; /* Columns to swap correspond to pivot ROW */
if (j != k) { /* If columns are different */
for (i = 0; i < 4; i++) {
hold = matrix[i][k];
matrix[i][k] = -matrix[i][j];
matrix[i][j] = hold;
}
}
}
}
void Projection::flip_y() {
for (int i = 0; i < 4; i++) {
matrix[1][i] = -matrix[1][i];
}
}
Projection::Projection() {
set_identity();
}
Projection Projection::operator*(const Projection &p_matrix) const {
Projection new_matrix;
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 4; i++) {
real_t ab = 0;
for (int k = 0; k < 4; k++) {
ab += matrix[k][i] * p_matrix.matrix[j][k];
}
new_matrix.matrix[j][i] = ab;
}
}
return new_matrix;
}
void Projection::set_depth_correction(bool p_flip_y) {
real_t *m = &matrix[0][0];
m[0] = 1;
m[1] = 0.0;
m[2] = 0.0;
m[3] = 0.0;
m[4] = 0.0;
m[5] = p_flip_y ? -1 : 1;
m[6] = 0.0;
m[7] = 0.0;
m[8] = 0.0;
m[9] = 0.0;
m[10] = 0.5;
m[11] = 0.0;
m[12] = 0.0;
m[13] = 0.0;
m[14] = 0.5;
m[15] = 1.0;
}
void Projection::set_light_bias() {
real_t *m = &matrix[0][0];
m[0] = 0.5;
m[1] = 0.0;
m[2] = 0.0;
m[3] = 0.0;
m[4] = 0.0;
m[5] = 0.5;
m[6] = 0.0;
m[7] = 0.0;
m[8] = 0.0;
m[9] = 0.0;
m[10] = 0.5;
m[11] = 0.0;
m[12] = 0.5;
m[13] = 0.5;
m[14] = 0.5;
m[15] = 1.0;
}
void Projection::set_light_atlas_rect(const Rect2 &p_rect) {
real_t *m = &matrix[0][0];
m[0] = p_rect.size.width;
m[1] = 0.0;
m[2] = 0.0;
m[3] = 0.0;
m[4] = 0.0;
m[5] = p_rect.size.height;
m[6] = 0.0;
m[7] = 0.0;
m[8] = 0.0;
m[9] = 0.0;
m[10] = 1.0;
m[11] = 0.0;
m[12] = p_rect.position.x;
m[13] = p_rect.position.y;
m[14] = 0.0;
m[15] = 1.0;
}
Vector4 Projection::xform(const Vector4 &p_vec4) const {
return Vector4(
matrix[0][0] * p_vec4.x + matrix[1][0] * p_vec4.y + matrix[2][0] * p_vec4.z + matrix[3][0] * p_vec4.w,
matrix[0][1] * p_vec4.x + matrix[1][1] * p_vec4.y + matrix[2][1] * p_vec4.z + matrix[3][1] * p_vec4.w,
matrix[0][2] * p_vec4.x + matrix[1][2] * p_vec4.y + matrix[2][2] * p_vec4.z + matrix[3][2] * p_vec4.w,
matrix[0][3] * p_vec4.x + matrix[1][3] * p_vec4.y + matrix[2][3] * p_vec4.z + matrix[3][3] * p_vec4.w);
}
Vector4 Projection::xform_inv(const Vector4 &p_vec4) const {
return Vector4(
matrix[0][0] * p_vec4.x + matrix[0][1] * p_vec4.y + matrix[0][2] * p_vec4.z + matrix[0][3] * p_vec4.w,
matrix[1][0] * p_vec4.x + matrix[1][1] * p_vec4.y + matrix[1][2] * p_vec4.z + matrix[1][3] * p_vec4.w,
matrix[2][0] * p_vec4.x + matrix[2][1] * p_vec4.y + matrix[2][2] * p_vec4.z + matrix[2][3] * p_vec4.w,
matrix[3][0] * p_vec4.x + matrix[3][1] * p_vec4.y + matrix[3][2] * p_vec4.z + matrix[3][3] * p_vec4.w);
}
Plane Projection::xform(const Plane &p_vec4) const {
Plane ret;
ret.normal.x = matrix[0][0] * p_vec4.normal.x + matrix[1][0] * p_vec4.normal.y + matrix[2][0] * p_vec4.normal.z + matrix[3][0] * p_vec4.d;
ret.normal.y = matrix[0][1] * p_vec4.normal.x + matrix[1][1] * p_vec4.normal.y + matrix[2][1] * p_vec4.normal.z + matrix[3][1] * p_vec4.d;
ret.normal.z = matrix[0][2] * p_vec4.normal.x + matrix[1][2] * p_vec4.normal.y + matrix[2][2] * p_vec4.normal.z + matrix[3][2] * p_vec4.d;
ret.d = matrix[0][3] * p_vec4.normal.x + matrix[1][3] * p_vec4.normal.y + matrix[2][3] * p_vec4.normal.z + matrix[3][3] * p_vec4.d;
return ret;
}
Projection::operator String() const {
return "[ X: " + matrix[0].operator String() +
", Y: " + matrix[1].operator String() +
", Z: " + matrix[2].operator String() +
", W: " + matrix[3].operator String() + " ]";
}
real_t Projection::get_aspect() const {
Vector2 vp_he = get_viewport_half_extents();
return vp_he.x / vp_he.y;
}
int Projection::get_pixels_per_meter(int p_for_pixel_width) const {
Vector3 result = xform(Vector3(1, 0, -1));
return int((result.x * 0.5 + 0.5) * p_for_pixel_width);
}
bool Projection::is_orthogonal() const {
return matrix[3][3] == 1.0;
}
real_t Projection::get_fov() const {
const real_t *matrix = (const real_t *)this->matrix;
Plane right_plane = Plane(matrix[3] - matrix[0],
matrix[7] - matrix[4],
matrix[11] - matrix[8],
-matrix[15] + matrix[12]);
right_plane.normalize();
if ((matrix[8] == 0) && (matrix[9] == 0)) {
return Math::rad2deg(Math::acos(Math::abs(right_plane.normal.x))) * 2.0;
} else {
// our frustum is asymmetrical need to calculate the left planes angle separately..
Plane left_plane = Plane(matrix[3] + matrix[0],
matrix[7] + matrix[4],
matrix[11] + matrix[8],
matrix[15] + matrix[12]);
left_plane.normalize();
return Math::rad2deg(Math::acos(Math::abs(left_plane.normal.x))) + Math::rad2deg(Math::acos(Math::abs(right_plane.normal.x)));
}
}
float Projection::get_lod_multiplier() const {
if (is_orthogonal()) {
return get_viewport_half_extents().x;
} else {
float zn = get_z_near();
float width = get_viewport_half_extents().x * 2.0;
return 1.0 / (zn / width);
}
//usage is lod_size / (lod_distance * multiplier) < threshold
}
void Projection::make_scale(const Vector3 &p_scale) {
set_identity();
matrix[0][0] = p_scale.x;
matrix[1][1] = p_scale.y;
matrix[2][2] = p_scale.z;
}
void Projection::scale_translate_to_fit(const AABB &p_aabb) {
Vector3 min = p_aabb.position;
Vector3 max = p_aabb.position + p_aabb.size;
matrix[0][0] = 2 / (max.x - min.x);
matrix[1][0] = 0;
matrix[2][0] = 0;
matrix[3][0] = -(max.x + min.x) / (max.x - min.x);
matrix[0][1] = 0;
matrix[1][1] = 2 / (max.y - min.y);
matrix[2][1] = 0;
matrix[3][1] = -(max.y + min.y) / (max.y - min.y);
matrix[0][2] = 0;
matrix[1][2] = 0;
matrix[2][2] = 2 / (max.z - min.z);
matrix[3][2] = -(max.z + min.z) / (max.z - min.z);
matrix[0][3] = 0;
matrix[1][3] = 0;
matrix[2][3] = 0;
matrix[3][3] = 1;
}
void Projection::add_jitter_offset(const Vector2 &p_offset) {
matrix[3][0] += p_offset.x;
matrix[3][1] += p_offset.y;
}
Projection::operator Transform() const {
Transform tr;
const real_t *m = &matrix[0][0];
tr.basis.rows[0][0] = m[0];
tr.basis.rows[1][0] = m[1];
tr.basis.rows[2][0] = m[2];
tr.basis.rows[0][1] = m[4];
tr.basis.rows[1][1] = m[5];
tr.basis.rows[2][1] = m[6];
tr.basis.rows[0][2] = m[8];
tr.basis.rows[1][2] = m[9];
tr.basis.rows[2][2] = m[10];
tr.origin.x = m[12];
tr.origin.y = m[13];
tr.origin.z = m[14];
return tr;
}
void Projection::set_frustum2(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov) {
set_frustum(p_size, p_aspect, p_offset, p_near, p_far, p_flip_fov);
}
Projection::Projection(const Vector4 &p_x, const Vector4 &p_y, const Vector4 &p_z, const Vector4 &p_w) {
matrix[0] = p_x;
matrix[1] = p_y;
matrix[2] = p_z;
matrix[3] = p_w;
}
Projection::Projection(const Transform &p_transform) {
const Transform &tr = p_transform;
real_t *m = &matrix[0][0];
m[0] = tr.basis.rows[0][0];
m[1] = tr.basis.rows[1][0];
m[2] = tr.basis.rows[2][0];
m[3] = 0.0;
m[4] = tr.basis.rows[0][1];
m[5] = tr.basis.rows[1][1];
m[6] = tr.basis.rows[2][1];
m[7] = 0.0;
m[8] = tr.basis.rows[0][2];
m[9] = tr.basis.rows[1][2];
m[10] = tr.basis.rows[2][2];
m[11] = 0.0;
m[12] = tr.origin.x;
m[13] = tr.origin.y;
m[14] = tr.origin.z;
m[15] = 1.0;
}
Projection::~Projection() {
}

View File

@ -1,167 +0,0 @@
/*************************************************************************/
/* projection.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
#ifndef PROJECTION_H
#define PROJECTION_H
//--STRIP
#include "core/vector.h"
#include "core/math_defs.h"
#include "core/vector3.h"
#include "core/vector4.h"
//--STRIP
struct AABB;
struct Plane;
struct Rect2;
struct Transform;
struct Vector2;
struct _NO_DISCARD_CLASS_ Projection {
enum Planes {
PLANE_NEAR,
PLANE_FAR,
PLANE_LEFT,
PLANE_TOP,
PLANE_RIGHT,
PLANE_BOTTOM
};
Vector4 matrix[4];
_FORCE_INLINE_ const Vector4 &operator[](const int p_axis) const {
DEV_ASSERT((unsigned int)p_axis < 4);
return matrix[p_axis];
}
_FORCE_INLINE_ Vector4 &operator[](const int p_axis) {
DEV_ASSERT((unsigned int)p_axis < 4);
return matrix[p_axis];
}
float determinant() const;
void set_identity();
void set_zero();
void set_light_bias();
void set_depth_correction(bool p_flip_y = true);
void set_light_atlas_rect(const Rect2 &p_rect);
void set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov = false);
void set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist);
void set_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_dist, real_t p_display_width, real_t p_display_to_lens, real_t p_oversample, real_t p_z_near, real_t p_z_far);
void set_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar);
void set_orthogonal(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov = false);
void set_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far);
void set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov = false);
void adjust_perspective_znear(real_t p_new_znear);
static Projection create_depth_correction(bool p_flip_y);
static Projection create_light_atlas_rect(const Rect2 &p_rect);
static Projection create_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov = false);
static Projection create_perspective_hmd(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist);
static Projection create_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_dist, real_t p_display_width, real_t p_display_to_lens, real_t p_oversample, real_t p_z_near, real_t p_z_far);
static Projection create_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar);
static Projection create_orthogonal_aspect(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov = false);
static Projection create_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far);
static Projection create_frustum_aspect(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov = false);
static Projection create_fit_aabb(const AABB &p_aabb);
Projection perspective_znear_adjusted(real_t p_new_znear) const;
Plane get_projection_plane(Planes p_plane) const;
Projection flipped_y() const;
Projection jitter_offseted(const Vector2 &p_offset) const;
static real_t get_fovy(real_t p_fovx, real_t p_aspect) {
return Math::rad2deg(Math::atan(p_aspect * Math::tan(Math::deg2rad(p_fovx) * 0.5)) * 2.0);
}
real_t calculate_fovy(real_t p_fovx, real_t p_aspect) {
return Math::rad2deg(Math::atan(p_aspect * Math::tan(Math::deg2rad(p_fovx) * 0.5)) * 2.0);
}
real_t get_z_far() const;
real_t get_z_near() const;
real_t get_aspect() const;
real_t get_fov() const;
bool is_orthogonal() const;
Vector<Plane> get_projection_planes(const Transform &p_transform) const;
bool get_endpoints(const Transform &p_transform, Vector3 *p_8points) const;
Vector2 get_viewport_half_extents() const;
Vector2 get_far_plane_half_extents() const;
void invert();
Projection inverse() const;
Projection operator*(const Projection &p_matrix) const;
Vector4 xform(const Vector4 &p_vec4) const;
Vector4 xform_inv(const Vector4 &p_vec4) const;
_FORCE_INLINE_ Vector3 xform(const Vector3 &p_vector) const;
Plane xform(const Plane &p_plane) const;
operator String() const;
void scale_translate_to_fit(const AABB &p_aabb);
void add_jitter_offset(const Vector2 &p_offset);
void make_scale(const Vector3 &p_scale);
int get_pixels_per_meter(int p_for_pixel_width) const;
operator Transform() const;
void flip_y();
bool operator==(const Projection &p_cam) const {
for (uint32_t i = 0; i < 4; i++) {
for (uint32_t j = 0; j < 4; j++) {
if (matrix[i][j] != p_cam.matrix[i][j]) {
return false;
}
}
}
return true;
}
bool operator!=(const Projection &p_cam) const {
return !(*this == p_cam);
}
float get_lod_multiplier() const;
_FORCE_INLINE_ void set_perspective1(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov = false) {
set_perspective(p_fovy_degrees, p_aspect, p_z_near, p_z_far, p_flip_fov);
}
_FORCE_INLINE_ void set_perspective2(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist) {
set_perspective(p_fovy_degrees, p_aspect, p_z_near, p_z_far, p_flip_fov, p_eye, p_intraocular_dist, p_convergence_dist);
}
_FORCE_INLINE_ void set_orthogonal1(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar) {
set_orthogonal(p_left, p_right, p_bottom, p_top, p_znear, p_zfar);
}
_FORCE_INLINE_ void set_orthogonal2(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov = false) {
set_orthogonal(p_size, p_aspect, p_znear, p_zfar, p_flip_fov);
}
_FORCE_INLINE_ void set_frustum1(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far) {
set_frustum(p_left, p_right, p_bottom, p_top, p_near, p_far);
}
//Vector2 is incomplete here
void set_frustum2(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov = false);
Projection();
Projection(const Vector4 &p_x, const Vector4 &p_y, const Vector4 &p_z, const Vector4 &p_w);
Projection(const Transform &p_transform);
~Projection();
};
Vector3 Projection::xform(const Vector3 &p_vec3) const {
Vector3 ret;
ret.x = matrix[0][0] * p_vec3.x + matrix[1][0] * p_vec3.y + matrix[2][0] * p_vec3.z + matrix[3][0];
ret.y = matrix[0][1] * p_vec3.x + matrix[1][1] * p_vec3.y + matrix[2][1] * p_vec3.z + matrix[3][1];
ret.z = matrix[0][2] * p_vec3.x + matrix[1][2] * p_vec3.y + matrix[2][2] * p_vec3.z + matrix[3][2];
real_t w = matrix[0][3] * p_vec3.x + matrix[1][3] * p_vec3.y + matrix[2][3] * p_vec3.z + matrix[3][3];
return ret / w;
}
#endif // PROJECTION_H

View File

@ -1,311 +0,0 @@
/*************************************************************************/
/* quaternion.cpp */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/quaternion.h"
#include "core/basis.h"
//--STRIP
real_t Quaternion::angle_to(const Quaternion &p_to) const {
real_t d = dot(p_to);
// acos does clamping.
return Math::acos(d * d * 2 - 1);
}
// set_euler_xyz expects a vector containing the Euler angles in the format
// (ax,ay,az), where ax is the angle of rotation around x axis,
// and similar for other axes.
// This implementation uses XYZ convention (Z is the first rotation).
void Quaternion::set_euler_xyz(const Vector3 &p_euler) {
real_t half_a1 = p_euler.x * 0.5f;
real_t half_a2 = p_euler.y * 0.5f;
real_t half_a3 = p_euler.z * 0.5f;
// R = X(a1).Y(a2).Z(a3) convention for Euler angles.
// Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-2)
// a3 is the angle of the first rotation, following the notation in this reference.
real_t cos_a1 = Math::cos(half_a1);
real_t sin_a1 = Math::sin(half_a1);
real_t cos_a2 = Math::cos(half_a2);
real_t sin_a2 = Math::sin(half_a2);
real_t cos_a3 = Math::cos(half_a3);
real_t sin_a3 = Math::sin(half_a3);
set(sin_a1 * cos_a2 * cos_a3 + sin_a2 * sin_a3 * cos_a1,
-sin_a1 * sin_a3 * cos_a2 + sin_a2 * cos_a1 * cos_a3,
sin_a1 * sin_a2 * cos_a3 + sin_a3 * cos_a1 * cos_a2,
-sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3);
}
// get_euler_xyz returns a vector containing the Euler angles in the format
// (ax,ay,az), where ax is the angle of rotation around x axis,
// and similar for other axes.
// This implementation uses XYZ convention (Z is the first rotation).
Vector3 Quaternion::get_euler_xyz() const {
Basis m(*this);
return m.get_euler_xyz();
}
// set_euler_yxz expects a vector containing the Euler angles in the format
// (ax,ay,az), where ax is the angle of rotation around x axis,
// and similar for other axes.
// This implementation uses YXZ convention (Z is the first rotation).
void Quaternion::set_euler_yxz(const Vector3 &p_euler) {
real_t half_a1 = p_euler.y * 0.5f;
real_t half_a2 = p_euler.x * 0.5f;
real_t half_a3 = p_euler.z * 0.5f;
// R = Y(a1).X(a2).Z(a3) convention for Euler angles.
// Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-6)
// a3 is the angle of the first rotation, following the notation in this reference.
real_t cos_a1 = Math::cos(half_a1);
real_t sin_a1 = Math::sin(half_a1);
real_t cos_a2 = Math::cos(half_a2);
real_t sin_a2 = Math::sin(half_a2);
real_t cos_a3 = Math::cos(half_a3);
real_t sin_a3 = Math::sin(half_a3);
set(sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3,
sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3,
-sin_a1 * sin_a2 * cos_a3 + cos_a1 * cos_a2 * sin_a3,
sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3);
}
// get_euler_yxz returns a vector containing the Euler angles in the format
// (ax,ay,az), where ax is the angle of rotation around x axis,
// and similar for other axes.
// This implementation uses YXZ convention (Z is the first rotation).
Vector3 Quaternion::get_euler_yxz() const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!is_normalized(), Vector3(0, 0, 0), "The quaternion must be normalized.");
#endif
Basis m(*this);
return m.get_euler_yxz();
}
void Quaternion::operator*=(const Quaternion &p_q) {
set(w * p_q.x + x * p_q.w + y * p_q.z - z * p_q.y,
w * p_q.y + y * p_q.w + z * p_q.x - x * p_q.z,
w * p_q.z + z * p_q.w + x * p_q.y - y * p_q.x,
w * p_q.w - x * p_q.x - y * p_q.y - z * p_q.z);
}
Quaternion Quaternion::operator*(const Quaternion &p_q) const {
Quaternion r = *this;
r *= p_q;
return r;
}
bool Quaternion::is_equal_approx(const Quaternion &p_quat) const {
return Math::is_equal_approx(x, p_quat.x) && Math::is_equal_approx(y, p_quat.y) && Math::is_equal_approx(z, p_quat.z) && Math::is_equal_approx(w, p_quat.w);
}
real_t Quaternion::length() const {
return Math::sqrt(length_squared());
}
void Quaternion::normalize() {
*this /= length();
}
Quaternion Quaternion::normalized() const {
return *this / length();
}
bool Quaternion::is_normalized() const {
return Math::is_equal_approx(length_squared(), 1, (real_t)UNIT_EPSILON); //use less epsilon
}
Quaternion Quaternion::inverse() const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The quaternion must be normalized.");
#endif
return Quaternion(-x, -y, -z, w);
}
Quaternion Quaternion::log() const {
Quaternion src = *this;
Vector3 src_v = src.get_axis() * src.get_angle();
return Quaternion(src_v.x, src_v.y, src_v.z, 0);
}
Quaternion Quaternion::exp() const {
Quaternion src = *this;
Vector3 src_v = Vector3(src.x, src.y, src.z);
float theta = src_v.length();
if (theta < CMP_EPSILON) {
return Quaternion(0, 0, 0, 1);
}
return Quaternion(src_v.normalized(), theta);
}
Quaternion Quaternion::slerp(const Quaternion &p_to, const real_t &p_weight) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
#endif
Quaternion to1;
real_t omega, cosom, sinom, scale0, scale1;
// calc cosine
cosom = dot(p_to);
// adjust signs (if necessary)
if (cosom < 0) {
cosom = -cosom;
to1.x = -p_to.x;
to1.y = -p_to.y;
to1.z = -p_to.z;
to1.w = -p_to.w;
} else {
to1.x = p_to.x;
to1.y = p_to.y;
to1.z = p_to.z;
to1.w = p_to.w;
}
// calculate coefficients
if ((1 - cosom) > (real_t)CMP_EPSILON) {
// standard case (slerp)
omega = Math::acos(cosom);
sinom = Math::sin(omega);
scale0 = Math::sin((1 - p_weight) * omega) / sinom;
scale1 = Math::sin(p_weight * omega) / sinom;
} else {
// "from" and "to" quaternions are very close
// ... so we can do a linear interpolation
scale0 = 1 - p_weight;
scale1 = p_weight;
}
// calculate final values
return Quaternion(
scale0 * x + scale1 * to1.x,
scale0 * y + scale1 * to1.y,
scale0 * z + scale1 * to1.z,
scale0 * w + scale1 * to1.w);
}
Quaternion Quaternion::slerpni(const Quaternion &p_to, const real_t &p_weight) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
#endif
const Quaternion &from = *this;
real_t dot = from.dot(p_to);
if (Math::absf(dot) > 0.9999f) {
return from;
}
real_t theta = Math::acos(dot),
sinT = 1 / Math::sin(theta),
newFactor = Math::sin(p_weight * theta) * sinT,
invFactor = Math::sin((1 - p_weight) * theta) * sinT;
return Quaternion(invFactor * from.x + newFactor * p_to.x,
invFactor * from.y + newFactor * p_to.y,
invFactor * from.z + newFactor * p_to.z,
invFactor * from.w + newFactor * p_to.w);
}
Quaternion Quaternion::cubic_slerp(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
#endif
//the only way to do slerp :|
real_t t2 = (1 - p_weight) * p_weight * 2;
Quaternion sp = this->slerp(p_b, p_weight);
Quaternion sq = p_pre_a.slerpni(p_post_b, p_weight);
return sp.slerpni(sq, t2);
}
Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
#endif
Quaternion from_q = *this;
Quaternion pre_q = p_pre_a;
Quaternion to_q = p_b;
Quaternion post_q = p_post_b;
// Align flip phases.
from_q = Basis(from_q).get_rotation_quaternion();
pre_q = Basis(pre_q).get_rotation_quaternion();
to_q = Basis(to_q).get_rotation_quaternion();
post_q = Basis(post_q).get_rotation_quaternion();
// Flip quaternions to shortest path if necessary.
bool flip1 = signbit(from_q.dot(pre_q));
pre_q = flip1 ? -pre_q : pre_q;
bool flip2 = signbit(from_q.dot(to_q));
to_q = flip2 ? -to_q : to_q;
bool flip3 = flip2 ? to_q.dot(post_q) <= 0 : signbit(to_q.dot(post_q));
post_q = flip3 ? -post_q : post_q;
// Calc by Expmap in from_q space.
Quaternion ln_from = Quaternion(0, 0, 0, 0);
Quaternion ln_to = (from_q.inverse() * to_q).log();
Quaternion ln_pre = (from_q.inverse() * pre_q).log();
Quaternion ln_post = (from_q.inverse() * post_q).log();
Quaternion ln = Quaternion(0, 0, 0, 0);
ln.x = Math::cubic_interpolate(ln_from.x, ln_to.x, ln_pre.x, ln_post.x, p_weight);
ln.y = Math::cubic_interpolate(ln_from.y, ln_to.y, ln_pre.y, ln_post.y, p_weight);
ln.z = Math::cubic_interpolate(ln_from.z, ln_to.z, ln_pre.z, ln_post.z, p_weight);
Quaternion q1 = from_q * ln.exp();
// Calc by Expmap in to_q space.
ln_from = (to_q.inverse() * from_q).log();
ln_to = Quaternion(0, 0, 0, 0);
ln_pre = (to_q.inverse() * pre_q).log();
ln_post = (to_q.inverse() * post_q).log();
ln = Quaternion(0, 0, 0, 0);
ln.x = Math::cubic_interpolate(ln_from.x, ln_to.x, ln_pre.x, ln_post.x, p_weight);
ln.y = Math::cubic_interpolate(ln_from.y, ln_to.y, ln_pre.y, ln_post.y, p_weight);
ln.z = Math::cubic_interpolate(ln_from.z, ln_to.z, ln_pre.z, ln_post.z, p_weight);
Quaternion q2 = to_q * ln.exp();
// To cancel error made by Expmap ambiguity, do blends.
return q1.slerp(q2, p_weight);
}
Vector3 Quaternion::get_axis() const {
if (Math::abs(w) > 1 - CMP_EPSILON) {
return Vector3(x, y, z);
}
real_t r = ((real_t)1) / Math::sqrt(1 - w * w);
return Vector3(x * r, y * r, z * r);
}
float Quaternion::get_angle() const {
return 2 * Math::acos(w);
}
Quaternion::operator String() const {
return "(" + String::num_real(x) + ", " + String::num_real(y) + ", " + String::num_real(z) + ", " + String::num_real(w) + ")";
}
void Quaternion::set_axis_angle(const Vector3 &axis, const real_t &angle) {
#ifdef MATH_CHECKS
ERR_FAIL_COND_MSG(!axis.is_normalized(), "The axis Vector3 must be normalized.");
#endif
real_t d = axis.length();
if (d == 0) {
set(0, 0, 0, 0);
} else {
real_t sin_angle = Math::sin(angle * 0.5f);
real_t cos_angle = Math::cos(angle * 0.5f);
real_t s = sin_angle / d;
set(axis.x * s, axis.y * s, axis.z * s,
cos_angle);
}
}

View File

@ -1,232 +0,0 @@
#ifndef QUATERNION_H
#define QUATERNION_H
/*************************************************************************/
/* quaternion.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/math_defs.h"
#include "core/math_funcs.h"
#include "core/vector3.h"
#include "core/ustring.h"
//--STRIP
struct _NO_DISCARD_CLASS_ Quaternion {
union {
struct {
real_t x;
real_t y;
real_t z;
real_t w;
};
real_t components[4];
};
_FORCE_INLINE_ real_t &operator[](int idx) {
return components[idx];
}
_FORCE_INLINE_ const real_t &operator[](int idx) const {
return components[idx];
}
_FORCE_INLINE_ real_t length_squared() const;
bool is_equal_approx(const Quaternion &p_quat) const;
real_t length() const;
void normalize();
Quaternion normalized() const;
bool is_normalized() const;
Quaternion inverse() const;
Quaternion log() const;
Quaternion exp() const;
_FORCE_INLINE_ real_t dot(const Quaternion &p_q) const;
real_t angle_to(const Quaternion &p_to) const;
void set_euler_xyz(const Vector3 &p_euler);
Vector3 get_euler_xyz() const;
void set_euler_yxz(const Vector3 &p_euler);
Vector3 get_euler_yxz() const;
void set_euler(const Vector3 &p_euler) { set_euler_yxz(p_euler); };
Vector3 get_euler() const { return get_euler_yxz(); };
Quaternion slerp(const Quaternion &p_to, const real_t &p_weight) const;
Quaternion slerpni(const Quaternion &p_to, const real_t &p_weight) const;
Quaternion cubic_slerp(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const;
Quaternion spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const;
Vector3 get_axis() const;
float get_angle() const;
void set_axis_angle(const Vector3 &axis, const real_t &angle);
_FORCE_INLINE_ void get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
r_angle = 2 * Math::acos(w);
real_t r = ((real_t)1) / Math::sqrt(1 - w * w);
r_axis.x = x * r;
r_axis.y = y * r;
r_axis.z = z * r;
}
void operator*=(const Quaternion &p_q);
Quaternion operator*(const Quaternion &p_q) const;
Quaternion operator*(const Vector3 &v) const {
return Quaternion(w * v.x + y * v.z - z * v.y,
w * v.y + z * v.x - x * v.z,
w * v.z + x * v.y - y * v.x,
-x * v.x - y * v.y - z * v.z);
}
_FORCE_INLINE_ Vector3 xform(const Vector3 &v) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!is_normalized(), v, "The quaternion must be normalized.");
#endif
Vector3 u(x, y, z);
Vector3 uv = u.cross(v);
return v + ((uv * w) + u.cross(uv)) * ((real_t)2);
}
_FORCE_INLINE_ void operator+=(const Quaternion &p_q);
_FORCE_INLINE_ void operator-=(const Quaternion &p_q);
_FORCE_INLINE_ void operator*=(const real_t &s);
_FORCE_INLINE_ void operator/=(const real_t &s);
_FORCE_INLINE_ Quaternion operator+(const Quaternion &q2) const;
_FORCE_INLINE_ Quaternion operator-(const Quaternion &q2) const;
_FORCE_INLINE_ Quaternion operator-() const;
_FORCE_INLINE_ Quaternion operator*(const real_t &s) const;
_FORCE_INLINE_ Quaternion operator/(const real_t &s) const;
_FORCE_INLINE_ bool operator==(const Quaternion &p_quat) const;
_FORCE_INLINE_ bool operator!=(const Quaternion &p_quat) const;
operator String() const;
inline void set(real_t p_x, real_t p_y, real_t p_z, real_t p_w) {
x = p_x;
y = p_y;
z = p_z;
w = p_w;
}
inline Quaternion(real_t p_x, real_t p_y, real_t p_z, real_t p_w) :
x(p_x),
y(p_y),
z(p_z),
w(p_w) {
}
Quaternion(const Vector3 &axis, const real_t &angle) {
set_axis_angle(axis, angle);
}
Quaternion(const Vector3 &euler) {
set_euler(euler);
}
Quaternion(const Quaternion &p_q) :
x(p_q.x),
y(p_q.y),
z(p_q.z),
w(p_q.w) {
}
Quaternion &operator=(const Quaternion &p_q) {
x = p_q.x;
y = p_q.y;
z = p_q.z;
w = p_q.w;
return *this;
}
Quaternion(const Vector3 &v0, const Vector3 &v1) // shortest arc
{
Vector3 c = v0.cross(v1);
real_t d = v0.dot(v1);
if (d < -1 + (real_t)CMP_EPSILON) {
x = 0;
y = 1;
z = 0;
w = 0;
} else {
real_t s = Math::sqrt((1 + d) * 2);
real_t rs = 1 / s;
x = c.x * rs;
y = c.y * rs;
z = c.z * rs;
w = s * 0.5f;
}
}
inline Quaternion() :
x(0),
y(0),
z(0),
w(1) {
}
};
real_t Quaternion::dot(const Quaternion &p_q) const {
return x * p_q.x + y * p_q.y + z * p_q.z + w * p_q.w;
}
real_t Quaternion::length_squared() const {
return dot(*this);
}
void Quaternion::operator+=(const Quaternion &p_q) {
x += p_q.x;
y += p_q.y;
z += p_q.z;
w += p_q.w;
}
void Quaternion::operator-=(const Quaternion &p_q) {
x -= p_q.x;
y -= p_q.y;
z -= p_q.z;
w -= p_q.w;
}
void Quaternion::operator*=(const real_t &s) {
x *= s;
y *= s;
z *= s;
w *= s;
}
void Quaternion::operator/=(const real_t &s) {
*this *= 1 / s;
}
Quaternion Quaternion::operator+(const Quaternion &q2) const {
const Quaternion &q1 = *this;
return Quaternion(q1.x + q2.x, q1.y + q2.y, q1.z + q2.z, q1.w + q2.w);
}
Quaternion Quaternion::operator-(const Quaternion &q2) const {
const Quaternion &q1 = *this;
return Quaternion(q1.x - q2.x, q1.y - q2.y, q1.z - q2.z, q1.w - q2.w);
}
Quaternion Quaternion::operator-() const {
const Quaternion &q2 = *this;
return Quaternion(-q2.x, -q2.y, -q2.z, -q2.w);
}
Quaternion Quaternion::operator*(const real_t &s) const {
return Quaternion(x * s, y * s, z * s, w * s);
}
Quaternion Quaternion::operator/(const real_t &s) const {
return *this * (1 / s);
}
bool Quaternion::operator==(const Quaternion &p_quat) const {
return x == p_quat.x && y == p_quat.y && z == p_quat.z && w == p_quat.w;
}
bool Quaternion::operator!=(const Quaternion &p_quat) const {
return x != p_quat.x || y != p_quat.y || z != p_quat.z || w != p_quat.w;
}
#endif

View File

@ -1,248 +0,0 @@
/*************************************************************************/
/* rect2.cpp */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/transform_2d.h" // Includes rect2.h but Rect2 needs Transform2D
#include "core/rect2i.h"
//--STRIP
bool Rect2::is_equal_approx(const Rect2 &p_rect) const {
return position.is_equal_approx(p_rect.position) && size.is_equal_approx(p_rect.size);
}
bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos, Point2 *r_normal) const {
real_t min = 0, max = 1;
int axis = 0;
real_t sign = 0;
for (int i = 0; i < 2; i++) {
real_t seg_from = p_from[i];
real_t seg_to = p_to[i];
real_t box_begin = position[i];
real_t box_end = box_begin + size[i];
real_t cmin, cmax;
real_t csign;
if (seg_from < seg_to) {
if (seg_from > box_end || seg_to < box_begin) {
return false;
}
real_t length = seg_to - seg_from;
cmin = (seg_from < box_begin) ? ((box_begin - seg_from) / length) : 0;
cmax = (seg_to > box_end) ? ((box_end - seg_from) / length) : 1;
csign = -1.0;
} else {
if (seg_to > box_end || seg_from < box_begin) {
return false;
}
real_t length = seg_to - seg_from;
cmin = (seg_from > box_end) ? (box_end - seg_from) / length : 0;
cmax = (seg_to < box_begin) ? (box_begin - seg_from) / length : 1;
csign = 1.0;
}
if (cmin > min) {
min = cmin;
axis = i;
sign = csign;
}
if (cmax < max) {
max = cmax;
}
if (max < min) {
return false;
}
}
Vector2 rel = p_to - p_from;
if (r_normal) {
Vector2 normal;
normal[axis] = sign;
*r_normal = normal;
}
if (r_pos) {
*r_pos = p_from + rel * min;
}
return true;
}
bool Rect2::intersects_transformed(const Transform2D &p_xform, const Rect2 &p_rect) const {
//SAT intersection between local and transformed rect2
Vector2 xf_points[4] = {
p_xform.xform(p_rect.position),
p_xform.xform(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y)),
p_xform.xform(Vector2(p_rect.position.x, p_rect.position.y + p_rect.size.y)),
p_xform.xform(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y + p_rect.size.y)),
};
real_t low_limit;
//base rect2 first (faster)
if (xf_points[0].y > position.y) {
goto next1;
}
if (xf_points[1].y > position.y) {
goto next1;
}
if (xf_points[2].y > position.y) {
goto next1;
}
if (xf_points[3].y > position.y) {
goto next1;
}
return false;
next1:
low_limit = position.y + size.y;
if (xf_points[0].y < low_limit) {
goto next2;
}
if (xf_points[1].y < low_limit) {
goto next2;
}
if (xf_points[2].y < low_limit) {
goto next2;
}
if (xf_points[3].y < low_limit) {
goto next2;
}
return false;
next2:
if (xf_points[0].x > position.x) {
goto next3;
}
if (xf_points[1].x > position.x) {
goto next3;
}
if (xf_points[2].x > position.x) {
goto next3;
}
if (xf_points[3].x > position.x) {
goto next3;
}
return false;
next3:
low_limit = position.x + size.x;
if (xf_points[0].x < low_limit) {
goto next4;
}
if (xf_points[1].x < low_limit) {
goto next4;
}
if (xf_points[2].x < low_limit) {
goto next4;
}
if (xf_points[3].x < low_limit) {
goto next4;
}
return false;
next4:
Vector2 xf_points2[4] = {
position,
Vector2(position.x + size.x, position.y),
Vector2(position.x, position.y + size.y),
Vector2(position.x + size.x, position.y + size.y),
};
real_t maxa = p_xform.columns[0].dot(xf_points2[0]);
real_t mina = maxa;
real_t dp = p_xform.columns[0].dot(xf_points2[1]);
maxa = MAX(dp, maxa);
mina = MIN(dp, mina);
dp = p_xform.columns[0].dot(xf_points2[2]);
maxa = MAX(dp, maxa);
mina = MIN(dp, mina);
dp = p_xform.columns[0].dot(xf_points2[3]);
maxa = MAX(dp, maxa);
mina = MIN(dp, mina);
real_t maxb = p_xform.columns[0].dot(xf_points[0]);
real_t minb = maxb;
dp = p_xform.columns[0].dot(xf_points[1]);
maxb = MAX(dp, maxb);
minb = MIN(dp, minb);
dp = p_xform.columns[0].dot(xf_points[2]);
maxb = MAX(dp, maxb);
minb = MIN(dp, minb);
dp = p_xform.columns[0].dot(xf_points[3]);
maxb = MAX(dp, maxb);
minb = MIN(dp, minb);
if (mina > maxb) {
return false;
}
if (minb > maxa) {
return false;
}
maxa = p_xform.columns[1].dot(xf_points2[0]);
mina = maxa;
dp = p_xform.columns[1].dot(xf_points2[1]);
maxa = MAX(dp, maxa);
mina = MIN(dp, mina);
dp = p_xform.columns[1].dot(xf_points2[2]);
maxa = MAX(dp, maxa);
mina = MIN(dp, mina);
dp = p_xform.columns[1].dot(xf_points2[3]);
maxa = MAX(dp, maxa);
mina = MIN(dp, mina);
maxb = p_xform.columns[1].dot(xf_points[0]);
minb = maxb;
dp = p_xform.columns[1].dot(xf_points[1]);
maxb = MAX(dp, maxb);
minb = MIN(dp, minb);
dp = p_xform.columns[1].dot(xf_points[2]);
maxb = MAX(dp, maxb);
minb = MIN(dp, minb);
dp = p_xform.columns[1].dot(xf_points[3]);
maxb = MAX(dp, maxb);
minb = MIN(dp, minb);
if (mina > maxb) {
return false;
}
if (minb > maxa) {
return false;
}
return true;
}
Rect2::operator String() const {
return "[P: " + position.operator String() + ", S: " + size + "]";
}

View File

@ -1,340 +0,0 @@
#ifndef RECT2_H
#define RECT2_H
/*************************************************************************/
/* rect2.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/vector2.h" // also includes math_funcs and ustring
#include "core/vector2i.h"
//--STRIP
struct Transform2D;
struct Rect2i;
struct _NO_DISCARD_CLASS_ Rect2 {
Point2 position;
Size2 size;
const Vector2 &get_position() const { return position; }
void set_position(const Vector2 &p_pos) { position = p_pos; }
const Vector2 &get_size() const { return size; }
void set_size(const Vector2 &p_size) { size = p_size; }
real_t get_area() const { return size.width * size.height; }
_FORCE_INLINE_ Vector2 get_center() const { return position + (size * 0.5f); }
inline bool intersects(const Rect2 &p_rect, const bool p_include_borders = false) const {
if (p_include_borders) {
if (position.x > (p_rect.position.x + p_rect.size.width)) {
return false;
}
if ((position.x + size.width) < p_rect.position.x) {
return false;
}
if (position.y > (p_rect.position.y + p_rect.size.height)) {
return false;
}
if ((position.y + size.height) < p_rect.position.y) {
return false;
}
} else {
if (position.x >= (p_rect.position.x + p_rect.size.width)) {
return false;
}
if ((position.x + size.width) <= p_rect.position.x) {
return false;
}
if (position.y >= (p_rect.position.y + p_rect.size.height)) {
return false;
}
if ((position.y + size.height) <= p_rect.position.y) {
return false;
}
}
return true;
}
inline real_t distance_to(const Vector2 &p_point) const {
real_t dist = 0.0;
bool inside = true;
if (p_point.x < position.x) {
real_t d = position.x - p_point.x;
dist = d;
inside = false;
}
if (p_point.y < position.y) {
real_t d = position.y - p_point.y;
dist = inside ? d : MIN(dist, d);
inside = false;
}
if (p_point.x >= (position.x + size.x)) {
real_t d = p_point.x - (position.x + size.x);
dist = inside ? d : MIN(dist, d);
inside = false;
}
if (p_point.y >= (position.y + size.y)) {
real_t d = p_point.y - (position.y + size.y);
dist = inside ? d : MIN(dist, d);
inside = false;
}
if (inside) {
return 0;
} else {
return dist;
}
}
bool intersects_transformed(const Transform2D &p_xform, const Rect2 &p_rect) const;
bool intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos = nullptr, Point2 *r_normal = nullptr) const;
inline bool encloses(const Rect2 &p_rect) const {
return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) &&
((p_rect.position.x + p_rect.size.x) <= (position.x + size.x)) &&
((p_rect.position.y + p_rect.size.y) <= (position.y + size.y));
}
_FORCE_INLINE_ bool has_no_area() const {
return (size.x <= 0 || size.y <= 0);
}
inline Rect2 clip(const Rect2 &p_rect) const { /// return a clipped rect
Rect2 new_rect = p_rect;
if (!intersects(new_rect)) {
return Rect2();
}
new_rect.position.x = MAX(p_rect.position.x, position.x);
new_rect.position.y = MAX(p_rect.position.y, position.y);
Point2 p_rect_end = p_rect.position + p_rect.size;
Point2 end = position + size;
new_rect.size.x = MIN(p_rect_end.x, end.x) - new_rect.position.x;
new_rect.size.y = MIN(p_rect_end.y, end.y) - new_rect.position.y;
return new_rect;
}
inline Rect2 intersection(const Rect2 &p_rect) const {
Rect2 new_rect = p_rect;
if (!intersects(new_rect)) {
return Rect2();
}
new_rect.position.x = MAX(p_rect.position.x, position.x);
new_rect.position.y = MAX(p_rect.position.y, position.y);
Point2 p_rect_end = p_rect.position + p_rect.size;
Point2 end = position + size;
new_rect.size.x = MIN(p_rect_end.x, end.x) - new_rect.position.x;
new_rect.size.y = MIN(p_rect_end.y, end.y) - new_rect.position.y;
return new_rect;
}
inline Rect2 merge(const Rect2 &p_rect) const { ///< return a merged rect
Rect2 new_rect;
new_rect.position.x = MIN(p_rect.position.x, position.x);
new_rect.position.y = MIN(p_rect.position.y, position.y);
new_rect.size.x = MAX(p_rect.position.x + p_rect.size.x, position.x + size.x);
new_rect.size.y = MAX(p_rect.position.y + p_rect.size.y, position.y + size.y);
new_rect.size = new_rect.size - new_rect.position; //make relative again
return new_rect;
};
inline bool has_point(const Point2 &p_point) const {
if (p_point.x < position.x) {
return false;
}
if (p_point.y < position.y) {
return false;
}
if (p_point.x >= (position.x + size.x)) {
return false;
}
if (p_point.y >= (position.y + size.y)) {
return false;
}
return true;
}
bool is_equal_approx(const Rect2 &p_rect) const;
bool operator==(const Rect2 &p_rect) const { return position == p_rect.position && size == p_rect.size; }
bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; }
inline Rect2 grow(real_t p_by) const {
Rect2 g = *this;
g.grow_by(p_by);
return g;
}
inline void grow_by(real_t p_by) {
position.x -= p_by;
position.y -= p_by;
size.width += p_by * 2;
size.height += p_by * 2;
}
inline Rect2 grow_margin(Margin p_margin, real_t p_amount) const {
Rect2 g = *this;
g = g.grow_individual((MARGIN_LEFT == p_margin) ? p_amount : 0,
(MARGIN_TOP == p_margin) ? p_amount : 0,
(MARGIN_RIGHT == p_margin) ? p_amount : 0,
(MARGIN_BOTTOM == p_margin) ? p_amount : 0);
return g;
}
inline Rect2 grow_side(Side p_side, real_t p_amount) const {
Rect2 g = *this;
g = g.grow_individual((SIDE_LEFT == p_side) ? p_amount : 0,
(SIDE_TOP == p_side) ? p_amount : 0,
(SIDE_RIGHT == p_side) ? p_amount : 0,
(SIDE_BOTTOM == p_side) ? p_amount : 0);
return g;
}
inline Rect2 grow_individual(real_t p_left, real_t p_top, real_t p_right, real_t p_bottom) const {
Rect2 g = *this;
g.position.x -= p_left;
g.position.y -= p_top;
g.size.width += p_left + p_right;
g.size.height += p_top + p_bottom;
return g;
}
_FORCE_INLINE_ Rect2 expand(const Vector2 &p_vector) const {
Rect2 r = *this;
r.expand_to(p_vector);
return r;
}
inline void expand_to(const Vector2 &p_vector) { //in place function for speed
Vector2 begin = position;
Vector2 end = position + size;
if (p_vector.x < begin.x) {
begin.x = p_vector.x;
}
if (p_vector.y < begin.y) {
begin.y = p_vector.y;
}
if (p_vector.x > end.x) {
end.x = p_vector.x;
}
if (p_vector.y > end.y) {
end.y = p_vector.y;
}
position = begin;
size = end - begin;
}
_FORCE_INLINE_ Rect2 abs() const {
return Rect2(Point2(position.x + MIN(size.x, 0), position.y + MIN(size.y, 0)), size.abs());
}
Vector2 get_support(const Vector2 &p_normal) const {
Vector2 half_extents = size * 0.5f;
Vector2 ofs = position + half_extents;
return Vector2(
(p_normal.x > 0) ? -half_extents.x : half_extents.x,
(p_normal.y > 0) ? -half_extents.y : half_extents.y) +
ofs;
}
_FORCE_INLINE_ bool intersects_filled_polygon(const Vector2 *p_points, int p_point_count) const {
Vector2 center = get_center();
int side_plus = 0;
int side_minus = 0;
Vector2 end = position + size;
int i_f = p_point_count - 1;
for (int i = 0; i < p_point_count; i++) {
const Vector2 &a = p_points[i_f];
const Vector2 &b = p_points[i];
i_f = i;
Vector2 r = (b - a);
float l = r.length();
if (l == 0.0f) {
continue;
}
//check inside
Vector2 tg = r.orthogonal();
float s = tg.dot(center) - tg.dot(a);
if (s < 0.0f) {
side_plus++;
} else {
side_minus++;
}
//check ray box
r /= l;
Vector2 ir(1.0f / r.x, 1.0f / r.y);
// lb is the corner of AABB with minimal coordinates - left bottom, rt is maximal corner
// r.org is origin of ray
Vector2 t13 = (position - a) * ir;
Vector2 t24 = (end - a) * ir;
float tmin = MAX(MIN(t13.x, t24.x), MIN(t13.y, t24.y));
float tmax = MIN(MAX(t13.x, t24.x), MAX(t13.y, t24.y));
// if tmax < 0, ray (line) is intersecting AABB, but the whole AABB is behind us
if (tmax < 0 || tmin > tmax || tmin >= l) {
continue;
}
return true;
}
if (side_plus * side_minus == 0) {
return true; //all inside
} else {
return false;
}
}
_FORCE_INLINE_ void set_end(const Vector2 &p_end) {
size = p_end - position;
}
_FORCE_INLINE_ Vector2 get_end() const {
return position + size;
}
operator String() const;
Rect2() {}
Rect2(real_t p_x, real_t p_y, real_t p_width, real_t p_height) :
position(Point2(p_x, p_y)),
size(Size2(p_width, p_height)) {
}
Rect2(const Point2 &p_pos, const Size2 &p_size) :
position(p_pos),
size(p_size) {
}
};
#endif // RECT2_H

View File

@ -1,12 +0,0 @@
/*************************************************************************/
/* rect2i.cpp */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/transform_2d.h" // Includes rect2.h but Rect2 needs Transform2D
//--STRIP
Rect2i::operator String() const {
return "[P: " + position.operator String() + ", S: " + size + "]";
}

View File

@ -1,233 +0,0 @@
#ifndef RECT2I_H
#define RECT2I_H
/*************************************************************************/
/* rect2i.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/vector2i.h" // also includes math_funcs and ustring
//--STRIP
struct _NO_DISCARD_CLASS_ Rect2i {
Point2i position;
Size2i size;
const Point2i &get_position() const { return position; }
void set_position(const Point2i &p_position) { position = p_position; }
const Size2i &get_size() const { return size; }
void set_size(const Size2i &p_size) { size = p_size; }
int get_area() const { return size.width * size.height; }
_FORCE_INLINE_ Vector2i get_center() const { return position + (size / 2); }
inline bool intersects(const Rect2i &p_rect) const {
if (position.x > (p_rect.position.x + p_rect.size.width)) {
return false;
}
if ((position.x + size.width) < p_rect.position.x) {
return false;
}
if (position.y > (p_rect.position.y + p_rect.size.height)) {
return false;
}
if ((position.y + size.height) < p_rect.position.y) {
return false;
}
return true;
}
inline bool encloses(const Rect2i &p_rect) const {
return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) &&
((p_rect.position.x + p_rect.size.x) < (position.x + size.x)) &&
((p_rect.position.y + p_rect.size.y) < (position.y + size.y));
}
_FORCE_INLINE_ bool has_no_area() const {
return (size.x <= 0 || size.y <= 0);
}
inline Rect2i clip(const Rect2i &p_rect) const { /// return a clipped rect
Rect2i new_rect = p_rect;
if (!intersects(new_rect)) {
return Rect2i();
}
new_rect.position.x = MAX(p_rect.position.x, position.x);
new_rect.position.y = MAX(p_rect.position.y, position.y);
Point2 p_rect_end = p_rect.position + p_rect.size;
Point2 end = position + size;
new_rect.size.x = (int)(MIN(p_rect_end.x, end.x) - new_rect.position.x);
new_rect.size.y = (int)(MIN(p_rect_end.y, end.y) - new_rect.position.y);
return new_rect;
}
// Returns the instersection between two Rect2is or an empty Rect2i if there is no intersection
inline Rect2i intersection(const Rect2i &p_rect) const {
Rect2i new_rect = p_rect;
if (!intersects(new_rect)) {
return Rect2i();
}
new_rect.position.x = MAX(p_rect.position.x, position.x);
new_rect.position.y = MAX(p_rect.position.y, position.y);
Point2i p_rect_end = p_rect.position + p_rect.size;
Point2i end = position + size;
new_rect.size.x = MIN(p_rect_end.x, end.x) - new_rect.position.x;
new_rect.size.y = MIN(p_rect_end.y, end.y) - new_rect.position.y;
return new_rect;
}
inline Rect2i merge(const Rect2i &p_rect) const { ///< return a merged rect
Rect2i new_rect;
new_rect.position.x = MIN(p_rect.position.x, position.x);
new_rect.position.y = MIN(p_rect.position.y, position.y);
new_rect.size.x = MAX(p_rect.position.x + p_rect.size.x, position.x + size.x);
new_rect.size.y = MAX(p_rect.position.y + p_rect.size.y, position.y + size.y);
new_rect.size = new_rect.size - new_rect.position; //make relative again
return new_rect;
}
bool has_point(const Point2i &p_point) const {
if (p_point.x < position.x) {
return false;
}
if (p_point.y < position.y) {
return false;
}
if (p_point.x >= (position.x + size.x)) {
return false;
}
if (p_point.y >= (position.y + size.y)) {
return false;
}
return true;
}
bool operator==(const Rect2i &p_rect) const { return position == p_rect.position && size == p_rect.size; }
bool operator!=(const Rect2i &p_rect) const { return position != p_rect.position || size != p_rect.size; }
Rect2i grow(int p_by) const {
Rect2i g = *this;
g.position.x -= p_by;
g.position.y -= p_by;
g.size.width += p_by * 2;
g.size.height += p_by * 2;
return g;
}
void grow_by(int p_by) {
position.x -= p_by;
position.y -= p_by;
size.width += p_by * 2;
size.height += p_by * 2;
}
inline Rect2i grow_margin(Margin p_margin, int p_amount) const {
Rect2i g = *this;
g = g.grow_individual((MARGIN_LEFT == p_margin) ? p_amount : 0,
(MARGIN_TOP == p_margin) ? p_amount : 0,
(MARGIN_RIGHT == p_margin) ? p_amount : 0,
(MARGIN_BOTTOM == p_margin) ? p_amount : 0);
return g;
}
inline Rect2i grow_side(Side p_side, int p_amount) const {
Rect2i g = *this;
g = g.grow_individual((SIDE_LEFT == p_side) ? p_amount : 0,
(SIDE_TOP == p_side) ? p_amount : 0,
(SIDE_RIGHT == p_side) ? p_amount : 0,
(SIDE_BOTTOM == p_side) ? p_amount : 0);
return g;
}
inline Rect2i grow_individual(int p_left, int p_top, int p_right, int p_bottom) const {
Rect2i g = *this;
g.position.x -= p_left;
g.position.y -= p_top;
g.size.width += p_left + p_right;
g.size.height += p_top + p_bottom;
return g;
}
_FORCE_INLINE_ Rect2i expand(const Vector2i &p_vector) const {
Rect2i r = *this;
r.expand_to(p_vector);
return r;
}
inline void expand_to(const Point2i &p_vector) {
Point2i begin = position;
Point2i end = position + size;
if (p_vector.x < begin.x) {
begin.x = p_vector.x;
}
if (p_vector.y < begin.y) {
begin.y = p_vector.y;
}
if (p_vector.x > end.x) {
end.x = p_vector.x;
}
if (p_vector.y > end.y) {
end.y = p_vector.y;
}
position = begin;
size = end - begin;
}
_FORCE_INLINE_ Rect2i abs() const {
return Rect2i(Point2i(position.x + MIN(size.x, 0), position.y + MIN(size.y, 0)), size.abs());
}
_FORCE_INLINE_ void set_end(const Vector2i &p_end) {
size = p_end - position;
}
_FORCE_INLINE_ Vector2i get_end() const {
return position + size;
}
Rect2 to_rect2() const { return Rect2(position, size); }
operator String() const;
operator Rect2() const { return Rect2(position, size); }
Rect2i(const Rect2 &p_r2) :
position(p_r2.position),
size(p_r2.size) {
}
Rect2i() {}
Rect2i(int p_x, int p_y, int p_width, int p_height) :
position(Point2(p_x, p_y)),
size(Size2(p_width, p_height)) {
}
Rect2i(const Point2 &p_pos, const Size2 &p_size) :
position(p_pos),
size(p_size) {
}
};
#endif // RECT2_H

View File

@ -1,258 +0,0 @@
/*************************************************************************/
/* transform.cpp */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/transform.h"
#include "core/math_funcs.h"
//--STRIP
void Transform::invert() {
basis.transpose();
origin = basis.xform(-origin);
}
Transform Transform::inverse() const {
// FIXME: this function assumes the basis is a rotation matrix, with no scaling.
// Transform::affine_inverse can handle matrices with scaling, so GDScript should eventually use that.
Transform ret = *this;
ret.invert();
return ret;
}
void Transform::affine_invert() {
basis.invert();
origin = basis.xform(-origin);
}
Transform Transform::affine_inverse() const {
Transform ret = *this;
ret.affine_invert();
return ret;
}
Transform Transform::rotated(const Vector3 &p_axis, real_t p_angle) const {
// Equivalent to left multiplication
Basis p_basis(p_axis, p_angle);
return Transform(p_basis * basis, p_basis.xform(origin));
}
Transform Transform::rotated_local(const Vector3 &p_axis, real_t p_angle) const {
// Equivalent to right multiplication
Basis p_basis(p_axis, p_angle);
return Transform(basis * p_basis, origin);
}
void Transform::rotate(const Vector3 &p_axis, real_t p_phi) {
*this = rotated(p_axis, p_phi);
}
void Transform::rotate_local(const Vector3 &p_axis, real_t p_phi) {
*this = rotated_local(p_axis, p_phi);
}
void Transform::rotate_basis(const Vector3 &p_axis, real_t p_phi) {
basis.rotate(p_axis, p_phi);
}
void Transform::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up) {
#ifdef MATH_CHECKS
ERR_FAIL_COND(p_eye == p_target);
ERR_FAIL_COND(p_up.length() == 0);
#endif
// Reference: MESA source code
Vector3 v_x, v_y, v_z;
/* Make rotation matrix */
/* Z vector */
v_z = p_eye - p_target;
v_z.normalize();
v_y = p_up;
v_x = v_y.cross(v_z);
#ifdef MATH_CHECKS
ERR_FAIL_COND(v_x.length() == 0);
#endif
/* Recompute Y = Z cross X */
v_y = v_z.cross(v_x);
v_x.normalize();
v_y.normalize();
basis.set(v_x, v_y, v_z);
origin = p_eye;
}
Transform Transform::looking_at(const Vector3 &p_target, const Vector3 &p_up) const {
Transform t = *this;
t.set_look_at(origin, p_target, p_up);
return t;
}
void Transform::scale(const Vector3 &p_scale) {
basis.scale(p_scale);
origin *= p_scale;
}
Transform Transform::scaled(const Vector3 &p_scale) const {
// Equivalent to left multiplication
return Transform(basis.scaled(p_scale), origin * p_scale);
}
Transform Transform::scaled_local(const Vector3 &p_scale) const {
// Equivalent to right multiplication
return Transform(basis.scaled_local(p_scale), origin);
}
void Transform::scale_basis(const Vector3 &p_scale) {
basis.scale(p_scale);
}
void Transform::translate_local(real_t p_tx, real_t p_ty, real_t p_tz) {
translate_local(Vector3(p_tx, p_ty, p_tz));
}
void Transform::translate_local(const Vector3 &p_translation) {
for (int i = 0; i < 3; i++) {
origin[i] += basis[i].dot(p_translation);
}
}
void Transform::translate_localr(real_t p_tx, real_t p_ty, real_t p_tz) {
translate_local(Vector3(p_tx, p_ty, p_tz));
}
void Transform::translate_localv(const Vector3 &p_translation) {
for (int i = 0; i < 3; i++) {
origin[i] += basis[i].dot(p_translation);
}
}
Transform Transform::translated(const Vector3 &p_translation) const {
// Equivalent to left multiplication
return Transform(basis, origin + p_translation);
}
Transform Transform::translated_local(const Vector3 &p_translation) const {
// Equivalent to right multiplication
return Transform(basis, origin + basis.xform(p_translation));
}
void Transform::orthonormalize() {
basis.orthonormalize();
}
Transform Transform::orthonormalized() const {
Transform _copy = *this;
_copy.orthonormalize();
return _copy;
}
void Transform::orthogonalize() {
basis.orthogonalize();
}
Transform Transform::orthogonalized() const {
Transform _copy = *this;
_copy.orthogonalize();
return _copy;
}
bool Transform::is_equal_approx(const Transform &p_transform) const {
return basis.is_equal_approx(p_transform.basis) && origin.is_equal_approx(p_transform.origin);
}
bool Transform::operator==(const Transform &p_transform) const {
return (basis == p_transform.basis && origin == p_transform.origin);
}
bool Transform::operator!=(const Transform &p_transform) const {
return (basis != p_transform.basis || origin != p_transform.origin);
}
void Transform::operator*=(const Transform &p_transform) {
origin = xform(p_transform.origin);
basis *= p_transform.basis;
}
Transform Transform::operator*(const Transform &p_transform) const {
Transform t = *this;
t *= p_transform;
return t;
}
void Transform::operator*=(const real_t p_val) {
origin *= p_val;
basis *= p_val;
}
Transform Transform::operator*(const real_t p_val) const {
Transform ret(*this);
ret *= p_val;
return ret;
}
Transform Transform::spherical_interpolate_with(const Transform &p_transform, real_t p_c) const {
/* not sure if very "efficient" but good enough? */
Transform interp;
Vector3 src_scale = basis.get_scale();
Quaternion src_rot = basis.get_rotation_quaternion();
Vector3 src_loc = origin;
Vector3 dst_scale = p_transform.basis.get_scale();
Quaternion dst_rot = p_transform.basis.get_rotation_quaternion();
Vector3 dst_loc = p_transform.origin;
interp.basis.set_quaternion_scale(src_rot.slerp(dst_rot, p_c).normalized(), src_scale.linear_interpolate(dst_scale, p_c));
interp.origin = src_loc.linear_interpolate(dst_loc, p_c);
return interp;
}
Transform Transform::interpolate_with(const Transform &p_transform, real_t p_c) const {
/* not sure if very "efficient" but good enough? */
Vector3 src_scale = basis.get_scale();
Quaternion src_rot = basis.get_rotation_quaternion();
Vector3 src_loc = origin;
Vector3 dst_scale = p_transform.basis.get_scale();
Quaternion dst_rot = p_transform.basis.get_rotation_quaternion();
Vector3 dst_loc = p_transform.origin;
Transform interp;
interp.basis.set_quaternion_scale(src_rot.slerp(dst_rot, p_c).normalized(), src_scale.linear_interpolate(dst_scale, p_c));
interp.origin = src_loc.linear_interpolate(dst_loc, p_c);
return interp;
}
Transform::operator String() const {
return "[X: " + basis.get_axis(0).operator String() +
", Y: " + basis.get_axis(1).operator String() +
", Z: " + basis.get_axis(2).operator String() +
", O: " + origin.operator String() + "]";
}
Transform::Transform(const Basis &p_basis, const Vector3 &p_origin) :
basis(p_basis),
origin(p_origin) {
}
Transform::Transform(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz) {
basis = Basis(xx, xy, xz, yx, yy, yz, zx, zy, zz);
origin = Vector3(ox, oy, oz);
}
Transform::Transform(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin) :
origin(p_origin) {
basis.set_column(0, p_x);
basis.set_column(1, p_y);
basis.set_column(2, p_z);
}

View File

@ -1,302 +0,0 @@
#ifndef TRANSFORM_H
#define TRANSFORM_H
/*************************************************************************/
/* transform.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/aabb.h"
#include "core/basis.h"
#include "core/plane.h"
#include "core/vector3i.h"
#include "core/pool_vector.h"
//--STRIP
struct _NO_DISCARD_CLASS_ Transform {
Basis basis;
Vector3 origin;
void invert();
Transform inverse() const;
void affine_invert();
Transform affine_inverse() const;
Transform rotated(const Vector3 &p_axis, real_t p_phi) const;
Transform rotated_local(const Vector3 &p_axis, real_t p_phi) const;
void rotate(const Vector3 &p_axis, real_t p_phi);
void rotate_local(const Vector3 &p_axis, real_t p_phi);
void rotate_basis(const Vector3 &p_axis, real_t p_phi);
void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up);
Transform looking_at(const Vector3 &p_target, const Vector3 &p_up) const;
void scale(const Vector3 &p_scale);
Transform scaled(const Vector3 &p_scale) const;
Transform scaled_local(const Vector3 &p_scale) const;
void scale_basis(const Vector3 &p_scale);
void translate_local(real_t p_tx, real_t p_ty, real_t p_tz);
void translate_local(const Vector3 &p_translation);
void translate_localr(real_t p_tx, real_t p_ty, real_t p_tz);
void translate_localv(const Vector3 &p_translation);
Transform translated(const Vector3 &p_translation) const;
Transform translated_local(const Vector3 &p_translation) const;
const Basis &get_basis() const { return basis; }
void set_basis(const Basis &p_basis) { basis = p_basis; }
const Vector3 &get_origin() const { return origin; }
void set_origin(const Vector3 &p_origin) { origin = p_origin; }
void orthonormalize();
Transform orthonormalized() const;
void orthogonalize();
Transform orthogonalized() const;
bool is_equal_approx(const Transform &p_transform) const;
bool operator==(const Transform &p_transform) const;
bool operator!=(const Transform &p_transform) const;
_FORCE_INLINE_ Vector3 xform(const Vector3 &p_vector) const;
_FORCE_INLINE_ Vector3i xform(const Vector3i &p_vector) const;
_FORCE_INLINE_ AABB xform(const AABB &p_aabb) const;
_FORCE_INLINE_ PoolVector<Vector3> xform(const PoolVector<Vector3> &p_array) const;
_FORCE_INLINE_ PoolVector<Vector3i> xform(const PoolVector<Vector3i> &p_array) const;
// NOTE: These are UNSAFE with non-uniform scaling, and will produce incorrect results.
// They use the transpose.
// For safe inverse transforms, xform by the affine_inverse.
_FORCE_INLINE_ Vector3 xform_inv(const Vector3 &p_vector) const;
_FORCE_INLINE_ Vector3i xform_inv(const Vector3i &p_vector) const;
_FORCE_INLINE_ AABB xform_inv(const AABB &p_aabb) const;
_FORCE_INLINE_ PoolVector<Vector3> xform_inv(const PoolVector<Vector3> &p_array) const;
_FORCE_INLINE_ PoolVector<Vector3i> xform_inv(const PoolVector<Vector3i> &p_array) const;
// Safe with non-uniform scaling (uses affine_inverse).
_FORCE_INLINE_ Plane xform(const Plane &p_plane) const;
_FORCE_INLINE_ Plane xform_inv(const Plane &p_plane) const;
// These fast versions use precomputed affine inverse, and should be used in bottleneck areas where
// multiple planes are to be transformed.
_FORCE_INLINE_ Plane xform_fast(const Plane &p_plane, const Basis &p_basis_inverse_transpose) const;
static _FORCE_INLINE_ Plane xform_inv_fast(const Plane &p_plane, const Transform &p_inverse, const Basis &p_basis_transpose);
void operator*=(const Transform &p_transform);
Transform operator*(const Transform &p_transform) const;
void operator*=(const real_t p_val);
Transform operator*(const real_t p_val) const;
Transform spherical_interpolate_with(const Transform &p_transform, real_t p_c) const;
Transform interpolate_with(const Transform &p_transform, real_t p_c) const;
_FORCE_INLINE_ Transform inverse_xform(const Transform &t) const {
Vector3 v = t.origin - origin;
return Transform(basis.transpose_xform(t.basis),
basis.xform(v));
}
void set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t tx, real_t ty, real_t tz) {
basis.set(xx, xy, xz, yx, yy, yz, zx, zy, zz);
origin.x = tx;
origin.y = ty;
origin.z = tz;
}
operator String() const;
Transform(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz);
Transform(const Basis &p_basis, const Vector3 &p_origin = Vector3());
Transform(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin);
Transform() {}
};
_FORCE_INLINE_ Vector3 Transform::xform(const Vector3 &p_vector) const {
return Vector3(
basis[0].dot(p_vector) + origin.x,
basis[1].dot(p_vector) + origin.y,
basis[2].dot(p_vector) + origin.z);
}
_FORCE_INLINE_ Vector3 Transform::xform_inv(const Vector3 &p_vector) const {
Vector3 v = p_vector - origin;
return Vector3(
(basis.rows[0][0] * v.x) + (basis.rows[1][0] * v.y) + (basis.rows[2][0] * v.z),
(basis.rows[0][1] * v.x) + (basis.rows[1][1] * v.y) + (basis.rows[2][1] * v.z),
(basis.rows[0][2] * v.x) + (basis.rows[1][2] * v.y) + (basis.rows[2][2] * v.z));
}
_FORCE_INLINE_ Vector3i Transform::xform(const Vector3i &p_vector) const {
return Vector3i(
basis[0].dot(p_vector) + origin.x,
basis[1].dot(p_vector) + origin.y,
basis[2].dot(p_vector) + origin.z);
}
_FORCE_INLINE_ Vector3i Transform::xform_inv(const Vector3i &p_vector) const {
Vector3i v = p_vector;
v.x -= origin.x;
v.y -= origin.y;
v.z -= origin.z;
return Vector3i(
(basis.rows[0][0] * v.x) + (basis.rows[1][0] * v.y) + (basis.rows[2][0] * v.z),
(basis.rows[0][1] * v.x) + (basis.rows[1][1] * v.y) + (basis.rows[2][1] * v.z),
(basis.rows[0][2] * v.x) + (basis.rows[1][2] * v.y) + (basis.rows[2][2] * v.z));
}
// Neither the plane regular xform or xform_inv are particularly efficient,
// as they do a basis inverse. For xforming a large number
// of planes it is better to pre-calculate the inverse transpose basis once
// and reuse it for each plane, by using the 'fast' version of the functions.
_FORCE_INLINE_ Plane Transform::xform(const Plane &p_plane) const {
Basis b = basis.inverse();
b.transpose();
return xform_fast(p_plane, b);
}
_FORCE_INLINE_ Plane Transform::xform_inv(const Plane &p_plane) const {
Transform inv = affine_inverse();
Basis basis_transpose = basis.transposed();
return xform_inv_fast(p_plane, inv, basis_transpose);
}
_FORCE_INLINE_ AABB Transform::xform(const AABB &p_aabb) const {
/* http://dev.theomader.com/transform-bounding-boxes/ */
Vector3 min = p_aabb.position;
Vector3 max = p_aabb.position + p_aabb.size;
Vector3 tmin, tmax;
for (int i = 0; i < 3; i++) {
tmin[i] = tmax[i] = origin[i];
for (int j = 0; j < 3; j++) {
real_t e = basis[i][j] * min[j];
real_t f = basis[i][j] * max[j];
if (e < f) {
tmin[i] += e;
tmax[i] += f;
} else {
tmin[i] += f;
tmax[i] += e;
}
}
}
AABB r_aabb;
r_aabb.position = tmin;
r_aabb.size = tmax - tmin;
return r_aabb;
}
_FORCE_INLINE_ AABB Transform::xform_inv(const AABB &p_aabb) const {
/* define vertices */
Vector3 vertices[8] = {
Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z),
Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z),
Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z),
Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z),
Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z),
Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z),
Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z),
Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z)
};
AABB ret;
ret.position = xform_inv(vertices[0]);
for (int i = 1; i < 8; i++) {
ret.expand_to(xform_inv(vertices[i]));
}
return ret;
}
PoolVector<Vector3> Transform::xform(const PoolVector<Vector3> &p_array) const {
PoolVector<Vector3> array;
array.resize(p_array.size());
PoolVector<Vector3>::Read r = p_array.read();
PoolVector<Vector3>::Write w = array.write();
for (int i = 0; i < p_array.size(); ++i) {
w[i] = xform(r[i]);
}
return array;
}
PoolVector<Vector3i> Transform::xform(const PoolVector<Vector3i> &p_array) const {
PoolVector<Vector3i> array;
array.resize(p_array.size());
PoolVector<Vector3i>::Read r = p_array.read();
PoolVector<Vector3i>::Write w = array.write();
for (int i = 0; i < p_array.size(); ++i) {
w[i] = xform(r[i]);
}
return array;
}
PoolVector<Vector3> Transform::xform_inv(const PoolVector<Vector3> &p_array) const {
PoolVector<Vector3> array;
array.resize(p_array.size());
PoolVector<Vector3>::Read r = p_array.read();
PoolVector<Vector3>::Write w = array.write();
for (int i = 0; i < p_array.size(); ++i) {
w[i] = xform_inv(r[i]);
}
return array;
}
PoolVector<Vector3i> Transform::xform_inv(const PoolVector<Vector3i> &p_array) const {
PoolVector<Vector3i> array;
array.resize(p_array.size());
PoolVector<Vector3i>::Read r = p_array.read();
PoolVector<Vector3i>::Write w = array.write();
for (int i = 0; i < p_array.size(); ++i) {
w[i] = xform_inv(r[i]);
}
return array;
}
_FORCE_INLINE_ Plane Transform::xform_fast(const Plane &p_plane, const Basis &p_basis_inverse_transpose) const {
// Transform a single point on the plane.
Vector3 point = p_plane.normal * p_plane.d;
point = xform(point);
// Use inverse transpose for correct normals with non-uniform scaling.
Vector3 normal = p_basis_inverse_transpose.xform(p_plane.normal);
normal.normalize();
real_t d = normal.dot(point);
return Plane(normal, d);
}
_FORCE_INLINE_ Plane Transform::xform_inv_fast(const Plane &p_plane, const Transform &p_inverse, const Basis &p_basis_transpose) {
// Transform a single point on the plane.
Vector3 point = p_plane.normal * p_plane.d;
point = p_inverse.xform(point);
// Note that instead of precalculating the transpose, an alternative
// would be to use the transpose for the basis transform.
// However that would be less SIMD friendly (requiring a swizzle).
// So the cost is one extra precalced value in the calling code.
// This is probably worth it, as this could be used in bottleneck areas. And
// where it is not a bottleneck, the non-fast method is fine.
// Use transpose for correct normals with non-uniform scaling.
Vector3 normal = p_basis_transpose.xform(p_plane.normal);
normal.normalize();
real_t d = normal.dot(point);
return Plane(normal, d);
}
#endif // TRANSFORM_H

View File

@ -1,313 +0,0 @@
/*************************************************************************/
/* transform_2d.cpp */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/transform_2d.h"
//--STRIP
void Transform2D::invert() {
// FIXME: this function assumes the basis is a rotation matrix, with no scaling.
// Transform2D::affine_inverse can handle matrices with scaling, so GDScript should eventually use that.
SWAP(columns[0][1], columns[1][0]);
columns[2] = basis_xform(-columns[2]);
}
Transform2D Transform2D::inverse() const {
Transform2D inv = *this;
inv.invert();
return inv;
}
void Transform2D::affine_invert() {
real_t det = basis_determinant();
#ifdef MATH_CHECKS
ERR_FAIL_COND(det == 0);
#endif
real_t idet = 1 / det;
SWAP(columns[0][0], columns[1][1]);
columns[0] *= Vector2(idet, -idet);
columns[1] *= Vector2(-idet, idet);
columns[2] = basis_xform(-columns[2]);
}
Transform2D Transform2D::affine_inverse() const {
Transform2D inv = *this;
inv.affine_invert();
return inv;
}
void Transform2D::rotate(real_t p_phi) {
*this = Transform2D(p_phi, Vector2()) * (*this);
}
real_t Transform2D::get_rotation() const {
return Math::atan2(columns[0].y, columns[0].x);
}
void Transform2D::set_rotation(real_t p_rot) {
Size2 scale = get_scale();
real_t cr = Math::cos(p_rot);
real_t sr = Math::sin(p_rot);
columns[0][0] = cr;
columns[0][1] = sr;
columns[1][0] = -sr;
columns[1][1] = cr;
set_scale(scale);
}
real_t Transform2D::get_skew() const {
real_t det = basis_determinant();
return Math::acos(columns[0].normalized().dot(SGN(det) * columns[1].normalized())) - (real_t)Math_PI * 0.5f;
}
void Transform2D::set_skew(const real_t p_angle) {
real_t det = basis_determinant();
columns[1] = SGN(det) * columns[0].rotated(((real_t)Math_PI * 0.5f + p_angle)).normalized() * columns[1].length();
}
Transform2D::Transform2D(real_t p_rot, const Vector2 &p_pos) {
real_t cr = Math::cos(p_rot);
real_t sr = Math::sin(p_rot);
columns[0][0] = cr;
columns[0][1] = sr;
columns[1][0] = -sr;
columns[1][1] = cr;
columns[2] = p_pos;
}
Transform2D::Transform2D(const real_t p_rot, const Size2 &p_scale, const real_t p_skew, const Vector2 &p_pos) {
columns[0][0] = Math::cos(p_rot) * p_scale.x;
columns[1][1] = Math::cos(p_rot + p_skew) * p_scale.y;
columns[1][0] = -Math::sin(p_rot + p_skew) * p_scale.y;
columns[0][1] = Math::sin(p_rot) * p_scale.x;
columns[2] = p_pos;
}
Size2 Transform2D::get_scale() const {
real_t det_sign = SGN(basis_determinant());
return Size2(columns[0].length(), det_sign * columns[1].length());
}
void Transform2D::set_scale(const Size2 &p_scale) {
columns[0].normalize();
columns[1].normalize();
columns[0] *= p_scale.x;
columns[1] *= p_scale.y;
}
void Transform2D::scale(const Size2 &p_scale) {
scale_basis(p_scale);
columns[2] *= p_scale;
}
void Transform2D::scale_basis(const Size2 &p_scale) {
columns[0][0] *= p_scale.x;
columns[0][1] *= p_scale.y;
columns[1][0] *= p_scale.x;
columns[1][1] *= p_scale.y;
}
void Transform2D::translate(real_t p_tx, real_t p_ty) {
translate(Vector2(p_tx, p_ty));
}
void Transform2D::translate(const Vector2 &p_offset) {
columns[2] += p_offset;
}
void Transform2D::translate_local(real_t p_tx, real_t p_ty) {
translate_local(Vector2(p_tx, p_ty));
}
void Transform2D::translate_local(const Vector2 &p_translation) {
columns[2] += basis_xform(p_translation);
}
void Transform2D::translater(real_t p_tx, real_t p_ty) {
translate(Vector2(p_tx, p_ty));
}
void Transform2D::translatev(const Vector2 &p_offset) {
columns[2] += p_offset;
}
void Transform2D::translate_localr(real_t p_tx, real_t p_ty) {
translate_local(Vector2(p_tx, p_ty));
}
void Transform2D::translate_localv(const Vector2 &p_translation) {
columns[2] += basis_xform(p_translation);
}
void Transform2D::orthonormalize() {
// Gram-Schmidt Process
Vector2 x = columns[0];
Vector2 y = columns[1];
x.normalize();
y = (y - x * (x.dot(y)));
y.normalize();
columns[0] = x;
columns[1] = y;
}
Transform2D Transform2D::orthonormalized() const {
Transform2D on = *this;
on.orthonormalize();
return on;
}
bool Transform2D::is_equal_approx(const Transform2D &p_transform) const {
return columns[0].is_equal_approx(p_transform.columns[0]) && columns[1].is_equal_approx(p_transform.columns[1]) && columns[2].is_equal_approx(p_transform.columns[2]);
}
Transform2D Transform2D::looking_at(const Vector2 &p_target) const {
Transform2D return_trans = Transform2D(get_rotation(), get_origin());
Vector2 target_position = affine_inverse().xform(p_target);
return_trans.set_rotation(return_trans.get_rotation() + (target_position * get_scale()).angle());
return return_trans;
}
bool Transform2D::operator==(const Transform2D &p_transform) const {
for (int i = 0; i < 3; i++) {
if (columns[i] != p_transform.columns[i]) {
return false;
}
}
return true;
}
bool Transform2D::operator!=(const Transform2D &p_transform) const {
for (int i = 0; i < 3; i++) {
if (columns[i] != p_transform.columns[i]) {
return true;
}
}
return false;
}
void Transform2D::operator*=(const Transform2D &p_transform) {
columns[2] = xform(p_transform.columns[2]);
real_t x0, x1, y0, y1;
x0 = tdotx(p_transform.columns[0]);
x1 = tdoty(p_transform.columns[0]);
y0 = tdotx(p_transform.columns[1]);
y1 = tdoty(p_transform.columns[1]);
columns[0][0] = x0;
columns[0][1] = x1;
columns[1][0] = y0;
columns[1][1] = y1;
}
Transform2D Transform2D::operator*(const Transform2D &p_transform) const {
Transform2D t = *this;
t *= p_transform;
return t;
}
void Transform2D::operator*=(const real_t p_val) {
columns[0] *= p_val;
columns[1] *= p_val;
columns[2] *= p_val;
}
Transform2D Transform2D::operator*(const real_t p_val) const {
Transform2D ret(*this);
ret *= p_val;
return ret;
}
Transform2D Transform2D::basis_scaled(const Size2 &p_scale) const {
Transform2D copy = *this;
copy.scale_basis(p_scale);
return copy;
}
Transform2D Transform2D::scaled(const Size2 &p_scale) const {
// Equivalent to left multiplication
Transform2D copy = *this;
copy.scale(p_scale);
return copy;
}
Transform2D Transform2D::scaled_local(const Size2 &p_scale) const {
// Equivalent to right multiplication
return Transform2D(columns[0] * p_scale.x, columns[1] * p_scale.y, columns[2]);
}
Transform2D Transform2D::untranslated() const {
Transform2D copy = *this;
copy.columns[2] = Vector2();
return copy;
}
Transform2D Transform2D::translated(const Vector2 &p_offset) const {
// Equivalent to left multiplication
return Transform2D(columns[0], columns[1], columns[2] + p_offset);
}
Transform2D Transform2D::translated_local(const Vector2 &p_offset) const {
// Equivalent to right multiplication
return Transform2D(columns[0], columns[1], columns[2] + basis_xform(p_offset));
}
Transform2D Transform2D::rotated(const real_t p_angle) const {
// Equivalent to left multiplication
return Transform2D(p_angle, Vector2()) * (*this);
}
Transform2D Transform2D::rotated_local(const real_t p_angle) const {
// Equivalent to right multiplication
return (*this) * Transform2D(p_angle, Vector2()); // Could be optimized, because origin transform can be skipped.
}
real_t Transform2D::basis_determinant() const {
return columns[0].x * columns[1].y - columns[0].y * columns[1].x;
}
Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, real_t p_c) const {
//extract parameters
Vector2 p1 = get_origin();
Vector2 p2 = p_transform.get_origin();
real_t r1 = get_rotation();
real_t r2 = p_transform.get_rotation();
Size2 s1 = get_scale();
Size2 s2 = p_transform.get_scale();
//slerp rotation
Vector2 v1(Math::cos(r1), Math::sin(r1));
Vector2 v2(Math::cos(r2), Math::sin(r2));
real_t dot = v1.dot(v2);
dot = CLAMP(dot, -1, 1);
Vector2 v;
if (dot > 0.9995f) {
v = Vector2::linear_interpolate(v1, v2, p_c).normalized(); //linearly interpolate to avoid numerical precision issues
} else {
real_t angle = p_c * Math::acos(dot);
Vector2 v3 = (v2 - v1 * dot).normalized();
v = v1 * Math::cos(angle) + v3 * Math::sin(angle);
}
//construct matrix
Transform2D res(Math::atan2(v.y, v.x), Vector2::linear_interpolate(p1, p2, p_c));
res.scale_basis(Vector2::linear_interpolate(s1, s2, p_c));
return res;
}
Transform2D::operator String() const {
return "[X: " + columns[0].operator String() +
", Y: " + columns[1].operator String() +
", O: " + columns[2].operator String() + "]";
}

View File

@ -1,305 +0,0 @@
#ifndef TRANSFORM_2D_H
#define TRANSFORM_2D_H
/*************************************************************************/
/* transform_2d.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/pool_vector.h"
#include "core/rect2.h" // also includes vector2, math_funcs, and ustring
#include "core/rect2i.h" // also includes vector2i, math_funcs, and ustring
//--STRIP
struct _NO_DISCARD_CLASS_ Transform2D {
// Warning #1: basis of Transform2D is stored differently from Basis. In terms of columns array, the basis matrix looks like "on paper":
// M = (columns[0][0] columns[1][0])
// (columns[0][1] columns[1][1])
// This is such that the columns, which can be interpreted as basis vectors of the coordinate system "painted" on the object, can be accessed as columns[i].
// Note that this is the opposite of the indices in mathematical texts, meaning: $M_{12}$ in a math book corresponds to columns[1][0] here.
// This requires additional care when working with explicit indices.
// See https://en.wikipedia.org/wiki/Row-_and_column-major_order for further reading.
// Warning #2: 2D be aware that unlike 3D code, 2D code uses a left-handed coordinate system: Y-axis points down,
// and angle is measure from +X to +Y in a clockwise-fashion.
Vector2 columns[3];
_FORCE_INLINE_ real_t tdotx(const Vector2 &v) const { return columns[0][0] * v.x + columns[1][0] * v.y; }
_FORCE_INLINE_ real_t tdoty(const Vector2 &v) const { return columns[0][1] * v.x + columns[1][1] * v.y; }
const Vector2 &operator[](int p_idx) const { return columns[p_idx]; }
Vector2 &operator[](int p_idx) { return columns[p_idx]; }
_FORCE_INLINE_ Vector2 get_axis(int p_axis) const {
ERR_FAIL_INDEX_V(p_axis, 3, Vector2());
return columns[p_axis];
}
_FORCE_INLINE_ void set_axis(int p_axis, const Vector2 &p_vec) {
ERR_FAIL_INDEX(p_axis, 3);
columns[p_axis] = p_vec;
}
_FORCE_INLINE_ Vector2 get_column(int p_colum) const {
ERR_FAIL_INDEX_V(p_colum, 3, Vector2());
return columns[p_colum];
}
_FORCE_INLINE_ void set_column(int p_colum, const Vector2 &p_vec) {
ERR_FAIL_INDEX(p_colum, 3);
columns[p_colum] = p_vec;
}
void invert();
Transform2D inverse() const;
void affine_invert();
Transform2D affine_inverse() const;
void set_rotation(real_t p_rot);
real_t get_rotation() const;
real_t get_skew() const;
void set_skew(const real_t p_angle);
_FORCE_INLINE_ void set_rotation_and_scale(real_t p_rot, const Size2 &p_scale);
_FORCE_INLINE_ void set_rotation_scale_and_skew(const real_t p_rot, const Size2 &p_scale, const real_t p_skew);
void rotate(real_t p_phi);
void scale(const Size2 &p_scale);
void scale_basis(const Size2 &p_scale);
void translate(real_t p_tx, real_t p_ty);
void translate(const Vector2 &p_offset);
void translate_local(real_t p_tx, real_t p_ty);
void translate_local(const Vector2 &p_translation);
void translater(real_t p_tx, real_t p_ty);
void translatev(const Vector2 &p_offset);
void translate_localr(real_t p_tx, real_t p_ty);
void translate_localv(const Vector2 &p_translation);
real_t basis_determinant() const;
Size2 get_scale() const;
void set_scale(const Size2 &p_scale);
_FORCE_INLINE_ const Vector2 &get_origin() const { return columns[2]; }
_FORCE_INLINE_ void set_origin(const Vector2 &p_origin) { columns[2] = p_origin; }
Transform2D basis_scaled(const Size2 &p_scale) const;
Transform2D scaled(const Size2 &p_scale) const;
Transform2D scaled_local(const Size2 &p_scale) const;
Transform2D translated(const Vector2 &p_offset) const;
Transform2D translated_local(const Vector2 &p_offset) const;
Transform2D rotated(const real_t p_angle) const;
Transform2D rotated_local(const real_t p_angle) const;
Transform2D untranslated() const;
void orthonormalize();
Transform2D orthonormalized() const;
bool is_equal_approx(const Transform2D &p_transform) const;
Transform2D looking_at(const Vector2 &p_target) const;
bool operator==(const Transform2D &p_transform) const;
bool operator!=(const Transform2D &p_transform) const;
void operator*=(const Transform2D &p_transform);
Transform2D operator*(const Transform2D &p_transform) const;
void operator*=(const real_t p_val);
Transform2D operator*(const real_t p_val) const;
Transform2D interpolate_with(const Transform2D &p_transform, real_t p_c) const;
_FORCE_INLINE_ Vector2 basis_xform(const Vector2 &p_vec) const;
_FORCE_INLINE_ Vector2 basis_xform_inv(const Vector2 &p_vec) const;
_FORCE_INLINE_ Vector2 xform(const Vector2 &p_vec) const;
_FORCE_INLINE_ Vector2 xform_inv(const Vector2 &p_vec) const;
_FORCE_INLINE_ Rect2 xform(const Rect2 &p_rect) const;
_FORCE_INLINE_ Rect2 xform_inv(const Rect2 &p_rect) const;
_FORCE_INLINE_ Vector2i basis_xform(const Vector2i &p_vec) const;
_FORCE_INLINE_ Vector2i basis_xform_inv(const Vector2i &p_vec) const;
_FORCE_INLINE_ Vector2i xform(const Vector2i &p_vec) const;
_FORCE_INLINE_ Vector2i xform_inv(const Vector2i &p_vec) const;
_FORCE_INLINE_ PoolVector<Vector2> xform(const PoolVector<Vector2> &p_array) const;
_FORCE_INLINE_ PoolVector<Vector2> xform_inv(const PoolVector<Vector2> &p_array) const;
_FORCE_INLINE_ PoolVector<Vector2i> xform(const PoolVector<Vector2i> &p_array) const;
_FORCE_INLINE_ PoolVector<Vector2i> xform_inv(const PoolVector<Vector2i> &p_array) const;
operator String() const;
Transform2D(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy) {
columns[0][0] = xx;
columns[0][1] = xy;
columns[1][0] = yx;
columns[1][1] = yy;
columns[2][0] = ox;
columns[2][1] = oy;
}
Transform2D(const Vector2 &p_x, const Vector2 &p_y, const Vector2 &p_origin) {
columns[0] = p_x;
columns[1] = p_y;
columns[2] = p_origin;
}
Transform2D(real_t p_rot, const Vector2 &p_pos);
Transform2D(const real_t p_rot, const Size2 &p_scale, const real_t p_skew, const Vector2 &p_pos);
Transform2D() {
columns[0][0] = 1.0;
columns[1][1] = 1.0;
}
};
Vector2 Transform2D::basis_xform(const Vector2 &p_vec) const {
return Vector2(
tdotx(p_vec),
tdoty(p_vec));
}
Vector2 Transform2D::basis_xform_inv(const Vector2 &p_vec) const {
return Vector2(
columns[0].dot(p_vec),
columns[1].dot(p_vec));
}
Vector2 Transform2D::xform(const Vector2 &p_vec) const {
return Vector2(
tdotx(p_vec),
tdoty(p_vec)) +
columns[2];
}
Vector2 Transform2D::xform_inv(const Vector2 &p_vec) const {
Vector2 v = p_vec - columns[2];
return Vector2(
columns[0].dot(v),
columns[1].dot(v));
}
Rect2 Transform2D::xform(const Rect2 &p_rect) const {
Vector2 x = columns[0] * p_rect.size.x;
Vector2 y = columns[1] * p_rect.size.y;
Vector2 pos = xform(p_rect.position);
Rect2 new_rect;
new_rect.position = pos;
new_rect.expand_to(pos + x);
new_rect.expand_to(pos + y);
new_rect.expand_to(pos + x + y);
return new_rect;
}
void Transform2D::set_rotation_and_scale(real_t p_rot, const Size2 &p_scale) {
columns[0][0] = Math::cos(p_rot) * p_scale.x;
columns[1][1] = Math::cos(p_rot) * p_scale.y;
columns[1][0] = -Math::sin(p_rot) * p_scale.y;
columns[0][1] = Math::sin(p_rot) * p_scale.x;
}
void Transform2D::set_rotation_scale_and_skew(const real_t p_rot, const Size2 &p_scale, const real_t p_skew) {
columns[0][0] = Math::cos(p_rot) * p_scale.x;
columns[1][1] = Math::cos(p_rot + p_skew) * p_scale.y;
columns[1][0] = -Math::sin(p_rot + p_skew) * p_scale.y;
columns[0][1] = Math::sin(p_rot) * p_scale.x;
}
Rect2 Transform2D::xform_inv(const Rect2 &p_rect) const {
Vector2 ends[4] = {
xform_inv(p_rect.position),
xform_inv(Vector2(p_rect.position.x, p_rect.position.y + p_rect.size.y)),
xform_inv(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y + p_rect.size.y)),
xform_inv(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y))
};
Rect2 new_rect;
new_rect.position = ends[0];
new_rect.expand_to(ends[1]);
new_rect.expand_to(ends[2]);
new_rect.expand_to(ends[3]);
return new_rect;
}
Vector2i Transform2D::basis_xform(const Vector2i &p_vec) const {
return Vector2i(
tdotx(p_vec),
tdoty(p_vec));
}
Vector2i Transform2D::basis_xform_inv(const Vector2i &p_vec) const {
return Vector2i(
columns[0].dot(p_vec),
columns[1].dot(p_vec));
}
Vector2i Transform2D::xform(const Vector2i &p_vec) const {
return Vector2i(
tdotx(p_vec),
tdoty(p_vec)) +
columns[2];
}
Vector2i Transform2D::xform_inv(const Vector2i &p_vec) const {
Vector2i v = p_vec - columns[2];
return Vector2i(
columns[0].dot(v),
columns[1].dot(v));
}
PoolVector<Vector2> Transform2D::xform(const PoolVector<Vector2> &p_array) const {
PoolVector<Vector2> array;
array.resize(p_array.size());
PoolVector<Vector2>::Read r = p_array.read();
PoolVector<Vector2>::Write w = array.write();
for (int i = 0; i < p_array.size(); ++i) {
w[i] = xform(r[i]);
}
return array;
}
PoolVector<Vector2> Transform2D::xform_inv(const PoolVector<Vector2> &p_array) const {
PoolVector<Vector2> array;
array.resize(p_array.size());
PoolVector<Vector2>::Read r = p_array.read();
PoolVector<Vector2>::Write w = array.write();
for (int i = 0; i < p_array.size(); ++i) {
w[i] = xform_inv(r[i]);
}
return array;
}
PoolVector<Vector2i> Transform2D::xform(const PoolVector<Vector2i> &p_array) const {
PoolVector<Vector2i> array;
array.resize(p_array.size());
PoolVector<Vector2i>::Read r = p_array.read();
PoolVector<Vector2i>::Write w = array.write();
for (int i = 0; i < p_array.size(); ++i) {
w[i] = xform(r[i]);
}
return array;
}
PoolVector<Vector2i> Transform2D::xform_inv(const PoolVector<Vector2i> &p_array) const {
PoolVector<Vector2i> array;
array.resize(p_array.size());
PoolVector<Vector2i>::Read r = p_array.read();
PoolVector<Vector2i>::Write w = array.write();
for (int i = 0; i < p_array.size(); ++i) {
w[i] = xform_inv(r[i]);
}
return array;
}
#endif // TRANSFORM_2D_H

View File

@ -1,152 +0,0 @@
/*************************************************************************/
/* vector2.cpp */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/vector2.h"
#include "core/ustring.h"
//--STRIP
real_t Vector2::angle() const {
return Math::atan2(y, x);
}
real_t Vector2::length() const {
return Math::sqrt(x * x + y * y);
}
real_t Vector2::length_squared() const {
return x * x + y * y;
}
void Vector2::normalize() {
real_t l = x * x + y * y;
if (l != 0) {
l = Math::sqrt(l);
x /= l;
y /= l;
}
}
Vector2 Vector2::normalized() const {
Vector2 v = *this;
v.normalize();
return v;
}
bool Vector2::is_normalized() const {
// use length_squared() instead of length() to avoid sqrt(), makes it more stringent.
return Math::is_equal_approx(length_squared(), 1, (real_t)UNIT_EPSILON);
}
real_t Vector2::distance_to(const Vector2 &p_vector2) const {
return Math::sqrt((x - p_vector2.x) * (x - p_vector2.x) + (y - p_vector2.y) * (y - p_vector2.y));
}
real_t Vector2::distance_squared_to(const Vector2 &p_vector2) const {
return (x - p_vector2.x) * (x - p_vector2.x) + (y - p_vector2.y) * (y - p_vector2.y);
}
real_t Vector2::angle_to(const Vector2 &p_vector2) const {
return Math::atan2(cross(p_vector2), dot(p_vector2));
}
real_t Vector2::angle_to_point(const Vector2 &p_vector2) const {
return Math::atan2(y - p_vector2.y, x - p_vector2.x);
}
real_t Vector2::dot(const Vector2 &p_other) const {
return x * p_other.x + y * p_other.y;
}
real_t Vector2::cross(const Vector2 &p_other) const {
return x * p_other.y - y * p_other.x;
}
Vector2 Vector2::sign() const {
return Vector2(SGN(x), SGN(y));
}
Vector2 Vector2::floor() const {
return Vector2(Math::floor(x), Math::floor(y));
}
Vector2 Vector2::ceil() const {
return Vector2(Math::ceil(x), Math::ceil(y));
}
Vector2 Vector2::round() const {
return Vector2(Math::round(x), Math::round(y));
}
Vector2 Vector2::rotated(real_t p_by) const {
Vector2 v;
v.set_rotation(angle() + p_by);
v *= length();
return v;
}
Vector2 Vector2::posmod(const real_t p_mod) const {
return Vector2(Math::fposmod(x, p_mod), Math::fposmod(y, p_mod));
}
Vector2 Vector2::posmodv(const Vector2 &p_modv) const {
return Vector2(Math::fposmod(x, p_modv.x), Math::fposmod(y, p_modv.y));
}
Vector2 Vector2::project(const Vector2 &p_to) const {
return p_to * (dot(p_to) / p_to.length_squared());
}
Vector2 Vector2::snapped(const Vector2 &p_by) const {
return Vector2(
Math::stepify(x, p_by.x),
Math::stepify(y, p_by.y));
}
Vector2 Vector2::limit_length(const real_t p_len) const {
const real_t l = length();
Vector2 v = *this;
if (l > 0 && p_len < l) {
v /= l;
v *= p_len;
}
return v;
}
Vector2 Vector2::move_toward(const Vector2 &p_to, const real_t p_delta) const {
Vector2 v = *this;
Vector2 vd = p_to - v;
real_t len = vd.length();
return len <= p_delta || len < (real_t)CMP_EPSILON ? p_to : v + vd / len * p_delta;
}
// slide returns the component of the vector along the given plane, specified by its normal vector.
Vector2 Vector2::slide(const Vector2 &p_normal) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 must be normalized.");
#endif
return *this - p_normal * this->dot(p_normal);
}
Vector2 Vector2::bounce(const Vector2 &p_normal) const {
return -reflect(p_normal);
}
Vector2 Vector2::reflect(const Vector2 &p_normal) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 must be normalized.");
#endif
return 2 * p_normal * this->dot(p_normal) - *this;
}
bool Vector2::is_equal_approx(const Vector2 &p_v) const {
return Math::is_equal_approx(x, p_v.x) && Math::is_equal_approx(y, p_v.y);
}
Vector2::operator String() const {
return "(" + String::num_real(x) + ", " + String::num_real(y) + ")";
}

View File

@ -1,281 +0,0 @@
#ifndef VECTOR2_H
#define VECTOR2_H
/*************************************************************************/
/* vector2.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/math_funcs.h"
#include "core/error_macros.h"
//--STRIP
class String;
struct _NO_DISCARD_CLASS_ Vector2 {
static const int AXIS_COUNT = 2;
enum Axis {
AXIS_X,
AXIS_Y,
};
union {
struct {
union {
real_t x;
real_t width;
};
union {
real_t y;
real_t height;
};
};
real_t coord[2];
};
_FORCE_INLINE_ real_t &operator[](int p_idx) {
DEV_ASSERT((unsigned int)p_idx < 2);
return coord[p_idx];
}
_FORCE_INLINE_ const real_t &operator[](int p_idx) const {
DEV_ASSERT((unsigned int)p_idx < 2);
return coord[p_idx];
}
_FORCE_INLINE_ void set_all(real_t p_value) {
x = y = p_value;
}
_FORCE_INLINE_ int min_axis() const {
return x < y ? 0 : 1;
}
_FORCE_INLINE_ int max_axis() const {
return x < y ? 1 : 0;
}
void normalize();
Vector2 normalized() const;
bool is_normalized() const;
real_t length() const;
real_t length_squared() const;
Vector2 limit_length(const real_t p_len = 1.0) const;
Vector2 min(const Vector2 &p_vector2) const {
return Vector2(MIN(x, p_vector2.x), MIN(y, p_vector2.y));
}
Vector2 max(const Vector2 &p_vector2) const {
return Vector2(MAX(x, p_vector2.x), MAX(y, p_vector2.y));
}
real_t distance_to(const Vector2 &p_vector2) const;
real_t distance_squared_to(const Vector2 &p_vector2) const;
real_t angle_to(const Vector2 &p_vector2) const;
real_t angle_to_point(const Vector2 &p_vector2) const;
_FORCE_INLINE_ Vector2 direction_to(const Vector2 &p_to) const;
real_t dot(const Vector2 &p_other) const;
real_t cross(const Vector2 &p_other) const;
Vector2 posmod(const real_t p_mod) const;
Vector2 posmodv(const Vector2 &p_modv) const;
Vector2 project(const Vector2 &p_to) const;
Vector2 plane_project(real_t p_d, const Vector2 &p_vec) const;
_FORCE_INLINE_ static Vector2 linear_interpolate(const Vector2 &p_a, const Vector2 &p_b, real_t p_weight);
_FORCE_INLINE_ Vector2 linear_interpolate(const Vector2 &p_to, real_t p_weight) const;
_FORCE_INLINE_ Vector2 slerp(const Vector2 &p_to, real_t p_weight) const;
_FORCE_INLINE_ Vector2 cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_weight) const;
_FORCE_INLINE_ Vector2 bezier_interpolate(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) const;
Vector2 move_toward(const Vector2 &p_to, const real_t p_delta) const;
Vector2 slide(const Vector2 &p_normal) const;
Vector2 bounce(const Vector2 &p_normal) const;
Vector2 reflect(const Vector2 &p_normal) const;
bool is_equal_approx(const Vector2 &p_v) const;
Vector2 operator+(const Vector2 &p_v) const;
void operator+=(const Vector2 &p_v);
Vector2 operator-(const Vector2 &p_v) const;
void operator-=(const Vector2 &p_v);
Vector2 operator*(const Vector2 &p_v1) const;
Vector2 operator*(const real_t &rvalue) const;
void operator*=(const real_t &rvalue);
void operator*=(const Vector2 &rvalue) { *this = *this * rvalue; }
Vector2 operator/(const Vector2 &p_v1) const;
Vector2 operator/(const real_t &rvalue) const;
void operator/=(const real_t &rvalue);
void operator/=(const Vector2 &rvalue) { *this = *this / rvalue; }
Vector2 operator-() const;
bool operator==(const Vector2 &p_vec2) const;
bool operator!=(const Vector2 &p_vec2) const;
bool operator<(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y < p_vec2.y) : (x < p_vec2.x); }
bool operator>(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y > p_vec2.y) : (x > p_vec2.x); }
bool operator<=(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y <= p_vec2.y) : (x < p_vec2.x); }
bool operator>=(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y >= p_vec2.y) : (x > p_vec2.x); }
real_t angle() const;
void set_rotation(real_t p_radians) {
x = Math::cos(p_radians);
y = Math::sin(p_radians);
}
_FORCE_INLINE_ Vector2 abs() const {
return Vector2(Math::abs(x), Math::abs(y));
}
Vector2 rotated(real_t p_by) const;
_FORCE_INLINE_ Vector2 tangent() const {
return Vector2(y, -x);
}
_FORCE_INLINE_ Vector2 orthogonal() const {
return Vector2(y, -x);
}
Vector2 sign() const;
Vector2 floor() const;
Vector2 ceil() const;
Vector2 round() const;
Vector2 snapped(const Vector2 &p_by) const;
real_t aspect() const { return width / height; }
operator String() const;
_FORCE_INLINE_ Vector2(real_t p_x, real_t p_y) {
x = p_x;
y = p_y;
}
_FORCE_INLINE_ Vector2() { x = y = 0; }
};
_FORCE_INLINE_ Vector2 Vector2::plane_project(real_t p_d, const Vector2 &p_vec) const {
return p_vec - *this * (dot(p_vec) - p_d);
}
_FORCE_INLINE_ Vector2 operator*(real_t p_scalar, const Vector2 &p_vec) {
return p_vec * p_scalar;
}
_FORCE_INLINE_ Vector2 Vector2::operator+(const Vector2 &p_v) const {
return Vector2(x + p_v.x, y + p_v.y);
}
_FORCE_INLINE_ void Vector2::operator+=(const Vector2 &p_v) {
x += p_v.x;
y += p_v.y;
}
_FORCE_INLINE_ Vector2 Vector2::operator-(const Vector2 &p_v) const {
return Vector2(x - p_v.x, y - p_v.y);
}
_FORCE_INLINE_ void Vector2::operator-=(const Vector2 &p_v) {
x -= p_v.x;
y -= p_v.y;
}
_FORCE_INLINE_ Vector2 Vector2::operator*(const Vector2 &p_v1) const {
return Vector2(x * p_v1.x, y * p_v1.y);
};
_FORCE_INLINE_ Vector2 Vector2::operator*(const real_t &rvalue) const {
return Vector2(x * rvalue, y * rvalue);
};
_FORCE_INLINE_ void Vector2::operator*=(const real_t &rvalue) {
x *= rvalue;
y *= rvalue;
};
_FORCE_INLINE_ Vector2 Vector2::operator/(const Vector2 &p_v1) const {
return Vector2(x / p_v1.x, y / p_v1.y);
};
_FORCE_INLINE_ Vector2 Vector2::operator/(const real_t &rvalue) const {
return Vector2(x / rvalue, y / rvalue);
};
_FORCE_INLINE_ void Vector2::operator/=(const real_t &rvalue) {
x /= rvalue;
y /= rvalue;
};
_FORCE_INLINE_ Vector2 Vector2::operator-() const {
return Vector2(-x, -y);
}
_FORCE_INLINE_ bool Vector2::operator==(const Vector2 &p_vec2) const {
return x == p_vec2.x && y == p_vec2.y;
}
_FORCE_INLINE_ bool Vector2::operator!=(const Vector2 &p_vec2) const {
return x != p_vec2.x || y != p_vec2.y;
}
Vector2 Vector2::linear_interpolate(const Vector2 &p_to, real_t p_weight) const {
Vector2 res = *this;
res.x += (p_weight * (p_to.x - x));
res.y += (p_weight * (p_to.y - y));
return res;
}
Vector2 Vector2::slerp(const Vector2 &p_to, real_t p_weight) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!is_normalized(), Vector2(), "The start Vector2 must be normalized.");
#endif
real_t theta = angle_to(p_to);
return rotated(theta * p_weight);
}
Vector2 Vector2::bezier_interpolate(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) const {
Vector2 res = *this;
/* Formula from Wikipedia article on Bezier curves. */
real_t omt = (1.0 - p_t);
real_t omt2 = omt * omt;
real_t omt3 = omt2 * omt;
real_t t2 = p_t * p_t;
real_t t3 = t2 * p_t;
return res * omt3 + p_control_1 * omt2 * p_t * 3.0 + p_control_2 * omt * t2 * 3.0 + p_end * t3;
}
Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, const real_t p_weight) const {
Vector2 res = *this;
res.x = Math::cubic_interpolate(res.x, p_b.x, p_pre_a.x, p_post_b.x, p_weight);
res.y = Math::cubic_interpolate(res.y, p_b.y, p_pre_a.y, p_post_b.y, p_weight);
return res;
}
Vector2 Vector2::direction_to(const Vector2 &p_to) const {
Vector2 ret(p_to.x - x, p_to.y - y);
ret.normalize();
return ret;
}
Vector2 Vector2::linear_interpolate(const Vector2 &p_a, const Vector2 &p_b, real_t p_weight) {
Vector2 res = p_a;
res.x += (p_weight * (p_b.x - p_a.x));
res.y += (p_weight * (p_b.y - p_a.y));
return res;
}
typedef Vector2 Size2;
typedef Vector2 Point2;
#endif // VECTOR2_H

View File

@ -1,79 +0,0 @@
/*************************************************************************/
/* vector2i.cpp */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/vector2i.h"
#include "core/ustring.h"
//--STRIP
Vector2i Vector2i::clamp(const Vector2i &p_min, const Vector2i &p_max) const {
return Vector2i(
CLAMP(x, p_min.x, p_max.x),
CLAMP(y, p_min.y, p_max.y));
}
int64_t Vector2i::length_squared() const {
return x * (int64_t)x + y * (int64_t)y;
}
double Vector2i::length() const {
return Math::sqrt((double)length_squared());
}
Vector2i Vector2i::operator+(const Vector2i &p_v) const {
return Vector2i(x + p_v.x, y + p_v.y);
}
void Vector2i::operator+=(const Vector2i &p_v) {
x += p_v.x;
y += p_v.y;
}
Vector2i Vector2i::operator-(const Vector2i &p_v) const {
return Vector2i(x - p_v.x, y - p_v.y);
}
void Vector2i::operator-=(const Vector2i &p_v) {
x -= p_v.x;
y -= p_v.y;
}
Vector2i Vector2i::operator*(const Vector2i &p_v1) const {
return Vector2i(x * p_v1.x, y * p_v1.y);
};
Vector2i Vector2i::operator*(const int &rvalue) const {
return Vector2i(x * rvalue, y * rvalue);
};
void Vector2i::operator*=(const int &rvalue) {
x *= rvalue;
y *= rvalue;
};
Vector2i Vector2i::operator/(const Vector2i &p_v1) const {
return Vector2i(x / p_v1.x, y / p_v1.y);
};
Vector2i Vector2i::operator/(const int &rvalue) const {
return Vector2i(x / rvalue, y / rvalue);
};
void Vector2i::operator/=(const int &rvalue) {
x /= rvalue;
y /= rvalue;
};
Vector2i Vector2i::operator-() const {
return Vector2i(-x, -y);
}
bool Vector2i::operator==(const Vector2i &p_vec2) const {
return x == p_vec2.x && y == p_vec2.y;
}
bool Vector2i::operator!=(const Vector2i &p_vec2) const {
return x != p_vec2.x || y != p_vec2.y;
}
Vector2i::operator String() const {
return "(" + itos(x) + ", " + itos(y) + ")";
}

View File

@ -1,143 +0,0 @@
#ifndef VECTOR2I_H
#define VECTOR2I_H
/*************************************************************************/
/* vector2i.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/error_macros.h"
#include "core/math_funcs.h"
#include "core/vector2.h"
//--STRIP
class String;
struct _NO_DISCARD_CLASS_ Vector2i {
enum Axis {
AXIS_X,
AXIS_Y,
};
union {
struct {
union {
int x;
int width;
};
union {
int y;
int height;
};
};
int coord[2];
};
_FORCE_INLINE_ int &operator[](int p_idx) {
DEV_ASSERT((unsigned int)p_idx < 2);
return coord[p_idx];
}
_FORCE_INLINE_ const int &operator[](int p_idx) const {
DEV_ASSERT((unsigned int)p_idx < 2);
return coord[p_idx];
}
_FORCE_INLINE_ void set_all(int p_value) {
x = y = p_value;
}
_FORCE_INLINE_ int min_axis() const {
return x < y ? 0 : 1;
}
_FORCE_INLINE_ int max_axis() const {
return x < y ? 1 : 0;
}
Vector2i min(const Vector2i &p_vector2i) const {
return Vector2i(MIN(x, p_vector2i.x), MIN(y, p_vector2i.y));
}
Vector2i max(const Vector2i &p_vector2i) const {
return Vector2i(MAX(x, p_vector2i.x), MAX(y, p_vector2i.y));
}
_FORCE_INLINE_ static Vector2i linear_interpolate(const Vector2i &p_a, const Vector2i &p_b, real_t p_weight);
_FORCE_INLINE_ Vector2i linear_interpolate(const Vector2i &p_to, real_t p_weight) const;
Vector2i operator+(const Vector2i &p_v) const;
void operator+=(const Vector2i &p_v);
Vector2i operator-(const Vector2i &p_v) const;
void operator-=(const Vector2i &p_v);
Vector2i operator*(const Vector2i &p_v1) const;
Vector2i operator*(const int &rvalue) const;
void operator*=(const int &rvalue);
Vector2i operator/(const Vector2i &p_v1) const;
Vector2i operator/(const int &rvalue) const;
void operator/=(const int &rvalue);
Vector2i operator-() const;
bool operator<(const Vector2i &p_vec2) const { return (x == p_vec2.x) ? (y < p_vec2.y) : (x < p_vec2.x); }
bool operator>(const Vector2i &p_vec2) const { return (x == p_vec2.x) ? (y > p_vec2.y) : (x > p_vec2.x); }
bool operator<=(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y <= p_vec2.y) : (x < p_vec2.x); }
bool operator>=(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y >= p_vec2.y) : (x > p_vec2.x); }
bool operator==(const Vector2i &p_vec2) const;
bool operator!=(const Vector2i &p_vec2) const;
int64_t length_squared() const;
double length() const;
real_t aspect() const { return width / (real_t)height; }
Vector2i sign() const { return Vector2i(SGN(x), SGN(y)); }
Vector2i abs() const { return Vector2i(ABS(x), ABS(y)); }
Vector2i clamp(const Vector2i &p_min, const Vector2i &p_max) const;
Vector2 to_vector2() const { return Vector2(x, y); }
operator String() const;
operator Vector2() const { return Vector2(x, y); }
inline Vector2i(const Vector2 &p_vec2) {
x = (int)p_vec2.x;
y = (int)p_vec2.y;
}
inline Vector2i(int p_x, int p_y) {
x = p_x;
y = p_y;
}
inline Vector2i() {
x = 0;
y = 0;
}
};
Vector2i Vector2i::linear_interpolate(const Vector2i &p_a, const Vector2i &p_b, real_t p_weight) {
Vector2i res = p_a;
res.x += (p_weight * (p_b.x - p_a.x));
res.y += (p_weight * (p_b.y - p_a.y));
return res;
}
Vector2i Vector2i::linear_interpolate(const Vector2i &p_to, real_t p_weight) const {
Vector2 res = *this;
res.x += (p_weight * (p_to.x - x));
res.y += (p_weight * (p_to.y - y));
return res;
}
typedef Vector2i Size2i;
typedef Vector2i Point2i;
#endif // VECTOR2_H

View File

@ -1,87 +0,0 @@
/*************************************************************************/
/* vector3.cpp */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/vector3.h"
#include "core/basis.h"
//--STRIP
void Vector3::rotate(const Vector3 &p_axis, real_t p_phi) {
*this = Basis(p_axis, p_phi).xform(*this);
}
Vector3 Vector3::rotated(const Vector3 &p_axis, real_t p_phi) const {
Vector3 r = *this;
r.rotate(p_axis, p_phi);
return r;
}
void Vector3::set_axis(int p_axis, real_t p_value) {
ERR_FAIL_INDEX(p_axis, 3);
coord[p_axis] = p_value;
}
real_t Vector3::get_axis(int p_axis) const {
ERR_FAIL_INDEX_V(p_axis, 3, 0);
return operator[](p_axis);
}
void Vector3::snap(const Vector3 &p_val) {
x = Math::stepify(x, p_val.x);
y = Math::stepify(y, p_val.y);
z = Math::stepify(z, p_val.z);
}
Vector3 Vector3::snapped(const Vector3 &p_val) const {
Vector3 v = *this;
v.snap(p_val);
return v;
}
Vector3 Vector3::limit_length(const real_t p_len) const {
const real_t l = length();
Vector3 v = *this;
if (l > 0 && p_len < l) {
v /= l;
v *= p_len;
}
return v;
}
Vector3 Vector3::move_toward(const Vector3 &p_to, const real_t p_delta) const {
Vector3 v = *this;
Vector3 vd = p_to - v;
real_t len = vd.length();
return len <= p_delta || len < (real_t)CMP_EPSILON ? p_to : v + vd / len * p_delta;
}
Basis Vector3::outer(const Vector3 &p_b) const {
Vector3 row0(x * p_b.x, x * p_b.y, x * p_b.z);
Vector3 row1(y * p_b.x, y * p_b.y, y * p_b.z);
Vector3 row2(z * p_b.x, z * p_b.y, z * p_b.z);
return Basis(row0, row1, row2);
}
Basis Vector3::to_diagonal_matrix() const {
return Basis(x, 0, 0,
0, y, 0,
0, 0, z);
}
Vector3 Vector3::clamp(const Vector3 &p_min, const Vector3 &p_max) const {
return Vector3(
CLAMP(x, p_min.x, p_max.x),
CLAMP(y, p_min.y, p_max.y),
CLAMP(z, p_min.z, p_max.z));
}
bool Vector3::is_equal_approx(const Vector3 &p_v) const {
return Math::is_equal_approx(x, p_v.x) && Math::is_equal_approx(y, p_v.y) && Math::is_equal_approx(z, p_v.z);
}
Vector3::operator String() const {
return "(" + String::num_real(x) + ", " + String::num_real(y) + ", " + String::num_real(z) + ")";
}

View File

@ -1,484 +0,0 @@
#ifndef VECTOR3_H
#define VECTOR3_H
/*************************************************************************/
/* vector3.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/math_funcs.h"
#include "core/ustring.h"
//--STRIP
struct Basis;
struct _NO_DISCARD_CLASS_ Vector3 {
static const int AXIS_COUNT = 3;
enum Axis {
AXIS_X,
AXIS_Y,
AXIS_Z,
};
union {
struct {
real_t x;
real_t y;
real_t z;
};
real_t coord[3];
};
_FORCE_INLINE_ const real_t &operator[](int p_axis) const {
DEV_ASSERT((unsigned int)p_axis < 3);
return coord[p_axis];
}
_FORCE_INLINE_ real_t &operator[](int p_axis) {
DEV_ASSERT((unsigned int)p_axis < 3);
return coord[p_axis];
}
void set_axis(int p_axis, real_t p_value);
real_t get_axis(int p_axis) const;
_FORCE_INLINE_ void set_all(real_t p_value) {
x = y = z = p_value;
}
_FORCE_INLINE_ int min_axis() const {
return x < y ? (x < z ? 0 : 2) : (y < z ? 1 : 2);
}
_FORCE_INLINE_ int max_axis() const {
return x < y ? (y < z ? 2 : 1) : (x < z ? 2 : 0);
}
_FORCE_INLINE_ real_t length() const;
_FORCE_INLINE_ real_t length_squared() const;
_FORCE_INLINE_ void normalize();
_FORCE_INLINE_ Vector3 normalized() const;
_FORCE_INLINE_ bool is_normalized() const;
_FORCE_INLINE_ Vector3 inverse() const;
Vector3 limit_length(const real_t p_len = 1.0) const;
_FORCE_INLINE_ void zero();
void snap(const Vector3 &p_val);
Vector3 snapped(const Vector3 &p_val) const;
void rotate(const Vector3 &p_axis, real_t p_phi);
Vector3 rotated(const Vector3 &p_axis, real_t p_phi) const;
/* Static Methods between 2 vector3s */
_FORCE_INLINE_ Vector3 linear_interpolate(const Vector3 &p_to, real_t p_weight) const;
_FORCE_INLINE_ Vector3 slerp(const Vector3 &p_to, real_t p_weight) const;
_FORCE_INLINE_ Vector3 cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_weight) const;
_FORCE_INLINE_ Vector3 bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const;
Vector3 move_toward(const Vector3 &p_to, const real_t p_delta) const;
_FORCE_INLINE_ Vector3 cross(const Vector3 &p_b) const;
_FORCE_INLINE_ real_t dot(const Vector3 &p_b) const;
Basis outer(const Vector3 &p_b) const;
Basis to_diagonal_matrix() const;
_FORCE_INLINE_ Vector3 abs() const;
_FORCE_INLINE_ Vector3 floor() const;
_FORCE_INLINE_ Vector3 sign() const;
_FORCE_INLINE_ Vector3 ceil() const;
_FORCE_INLINE_ Vector3 round() const;
Vector3 clamp(const Vector3 &p_min, const Vector3 &p_max) const;
_FORCE_INLINE_ real_t distance_to(const Vector3 &p_to) const;
_FORCE_INLINE_ real_t distance_squared_to(const Vector3 &p_to) const;
_FORCE_INLINE_ Vector3 posmod(const real_t p_mod) const;
_FORCE_INLINE_ Vector3 posmodv(const Vector3 &p_modv) const;
_FORCE_INLINE_ Vector3 project(const Vector3 &p_to) const;
_FORCE_INLINE_ real_t angle_to(const Vector3 &p_to) const;
_FORCE_INLINE_ real_t signed_angle_to(const Vector3 &p_to, const Vector3 &p_axis) const;
_FORCE_INLINE_ Vector3 direction_to(const Vector3 &p_to) const;
_FORCE_INLINE_ Vector3 slide(const Vector3 &p_normal) const;
_FORCE_INLINE_ Vector3 bounce(const Vector3 &p_normal) const;
_FORCE_INLINE_ Vector3 reflect(const Vector3 &p_normal) const;
bool is_equal_approx(const Vector3 &p_v) const;
inline bool is_equal_approx(const Vector3 &p_v, real_t p_tolerance) const;
inline bool is_equal_approxt(const Vector3 &p_v, real_t p_tolerance) const;
/* Operators */
_FORCE_INLINE_ Vector3 &operator+=(const Vector3 &p_v);
_FORCE_INLINE_ Vector3 operator+(const Vector3 &p_v) const;
_FORCE_INLINE_ Vector3 &operator-=(const Vector3 &p_v);
_FORCE_INLINE_ Vector3 operator-(const Vector3 &p_v) const;
_FORCE_INLINE_ Vector3 &operator*=(const Vector3 &p_v);
_FORCE_INLINE_ Vector3 operator*(const Vector3 &p_v) const;
_FORCE_INLINE_ Vector3 &operator/=(const Vector3 &p_v);
_FORCE_INLINE_ Vector3 operator/(const Vector3 &p_v) const;
_FORCE_INLINE_ Vector3 &operator*=(real_t p_scalar);
_FORCE_INLINE_ Vector3 operator*(real_t p_scalar) const;
_FORCE_INLINE_ Vector3 &operator/=(real_t p_scalar);
_FORCE_INLINE_ Vector3 operator/(real_t p_scalar) const;
_FORCE_INLINE_ Vector3 operator-() const;
_FORCE_INLINE_ bool operator==(const Vector3 &p_v) const;
_FORCE_INLINE_ bool operator!=(const Vector3 &p_v) const;
_FORCE_INLINE_ bool operator<(const Vector3 &p_v) const;
_FORCE_INLINE_ bool operator<=(const Vector3 &p_v) const;
_FORCE_INLINE_ bool operator>(const Vector3 &p_v) const;
_FORCE_INLINE_ bool operator>=(const Vector3 &p_v) const;
operator String() const;
_FORCE_INLINE_ Vector3(real_t p_x, real_t p_y, real_t p_z) {
x = p_x;
y = p_y;
z = p_z;
}
_FORCE_INLINE_ Vector3() { x = y = z = 0; }
};
Vector3 Vector3::cross(const Vector3 &p_b) const {
Vector3 ret(
(y * p_b.z) - (z * p_b.y),
(z * p_b.x) - (x * p_b.z),
(x * p_b.y) - (y * p_b.x));
return ret;
}
real_t Vector3::dot(const Vector3 &p_b) const {
return x * p_b.x + y * p_b.y + z * p_b.z;
}
Vector3 Vector3::abs() const {
return Vector3(Math::abs(x), Math::abs(y), Math::abs(z));
}
Vector3 Vector3::sign() const {
return Vector3(SGN(x), SGN(y), SGN(z));
}
Vector3 Vector3::floor() const {
return Vector3(Math::floor(x), Math::floor(y), Math::floor(z));
}
Vector3 Vector3::ceil() const {
return Vector3(Math::ceil(x), Math::ceil(y), Math::ceil(z));
}
Vector3 Vector3::round() const {
return Vector3(Math::round(x), Math::round(y), Math::round(z));
}
Vector3 Vector3::linear_interpolate(const Vector3 &p_to, real_t p_weight) const {
return Vector3(
x + (p_weight * (p_to.x - x)),
y + (p_weight * (p_to.y - y)),
z + (p_weight * (p_to.z - z)));
}
Vector3 Vector3::slerp(const Vector3 &p_to, const real_t p_weight) const {
// This method seems more complicated than it really is, since we write out
// the internals of some methods for efficiency (mainly, checking length).
real_t start_length_sq = length_squared();
real_t end_length_sq = p_to.length_squared();
if (unlikely(start_length_sq == 0.0f || end_length_sq == 0.0f)) {
// Zero length vectors have no angle, so the best we can do is either lerp or throw an error.
return linear_interpolate(p_to, p_weight);
}
Vector3 axis = cross(p_to);
real_t axis_length_sq = axis.length_squared();
if (unlikely(axis_length_sq == 0.0f)) {
// Colinear vectors have no rotation axis or angle between them, so the best we can do is lerp.
return linear_interpolate(p_to, p_weight);
}
axis /= Math::sqrt(axis_length_sq);
real_t start_length = Math::sqrt(start_length_sq);
real_t result_length = Math::lerp(start_length, Math::sqrt(end_length_sq), p_weight);
real_t angle = angle_to(p_to);
return rotated(axis, angle * p_weight) * (result_length / start_length);
}
Vector3 Vector3::cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight) const {
Vector3 res = *this;
res.x = Math::cubic_interpolate(res.x, p_b.x, p_pre_a.x, p_post_b.x, p_weight);
res.y = Math::cubic_interpolate(res.y, p_b.y, p_pre_a.y, p_post_b.y, p_weight);
res.z = Math::cubic_interpolate(res.z, p_b.z, p_pre_a.z, p_post_b.z, p_weight);
return res;
}
Vector3 Vector3::bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const {
Vector3 res = *this;
/* Formula from Wikipedia article on Bezier curves. */
real_t omt = (1.0 - p_t);
real_t omt2 = omt * omt;
real_t omt3 = omt2 * omt;
real_t t2 = p_t * p_t;
real_t t3 = t2 * p_t;
return res * omt3 + p_control_1 * omt2 * p_t * 3.0 + p_control_2 * omt * t2 * 3.0 + p_end * t3;
}
real_t Vector3::distance_to(const Vector3 &p_to) const {
return (p_to - *this).length();
}
real_t Vector3::distance_squared_to(const Vector3 &p_to) const {
return (p_to - *this).length_squared();
}
Vector3 Vector3::posmod(const real_t p_mod) const {
return Vector3(Math::fposmod(x, p_mod), Math::fposmod(y, p_mod), Math::fposmod(z, p_mod));
}
Vector3 Vector3::posmodv(const Vector3 &p_modv) const {
return Vector3(Math::fposmod(x, p_modv.x), Math::fposmod(y, p_modv.y), Math::fposmod(z, p_modv.z));
}
Vector3 Vector3::project(const Vector3 &p_to) const {
return p_to * (dot(p_to) / p_to.length_squared());
}
real_t Vector3::angle_to(const Vector3 &p_to) const {
return Math::atan2(cross(p_to).length(), dot(p_to));
}
real_t Vector3::signed_angle_to(const Vector3 &p_to, const Vector3 &p_axis) const {
Vector3 cross_to = cross(p_to);
real_t unsigned_angle = Math::atan2(cross_to.length(), dot(p_to));
real_t sign = cross_to.dot(p_axis);
return (sign < 0) ? -unsigned_angle : unsigned_angle;
}
Vector3 Vector3::direction_to(const Vector3 &p_to) const {
Vector3 ret(p_to.x - x, p_to.y - y, p_to.z - z);
ret.normalize();
return ret;
}
/* Operators */
Vector3 &Vector3::operator+=(const Vector3 &p_v) {
x += p_v.x;
y += p_v.y;
z += p_v.z;
return *this;
}
Vector3 Vector3::operator+(const Vector3 &p_v) const {
return Vector3(x + p_v.x, y + p_v.y, z + p_v.z);
}
Vector3 &Vector3::operator-=(const Vector3 &p_v) {
x -= p_v.x;
y -= p_v.y;
z -= p_v.z;
return *this;
}
Vector3 Vector3::operator-(const Vector3 &p_v) const {
return Vector3(x - p_v.x, y - p_v.y, z - p_v.z);
}
Vector3 &Vector3::operator*=(const Vector3 &p_v) {
x *= p_v.x;
y *= p_v.y;
z *= p_v.z;
return *this;
}
Vector3 Vector3::operator*(const Vector3 &p_v) const {
return Vector3(x * p_v.x, y * p_v.y, z * p_v.z);
}
Vector3 &Vector3::operator/=(const Vector3 &p_v) {
x /= p_v.x;
y /= p_v.y;
z /= p_v.z;
return *this;
}
Vector3 Vector3::operator/(const Vector3 &p_v) const {
return Vector3(x / p_v.x, y / p_v.y, z / p_v.z);
}
Vector3 &Vector3::operator*=(real_t p_scalar) {
x *= p_scalar;
y *= p_scalar;
z *= p_scalar;
return *this;
}
_FORCE_INLINE_ Vector3 operator*(real_t p_scalar, const Vector3 &p_vec) {
return p_vec * p_scalar;
}
Vector3 Vector3::operator*(real_t p_scalar) const {
return Vector3(x * p_scalar, y * p_scalar, z * p_scalar);
}
Vector3 &Vector3::operator/=(real_t p_scalar) {
x /= p_scalar;
y /= p_scalar;
z /= p_scalar;
return *this;
}
Vector3 Vector3::operator/(real_t p_scalar) const {
return Vector3(x / p_scalar, y / p_scalar, z / p_scalar);
}
Vector3 Vector3::operator-() const {
return Vector3(-x, -y, -z);
}
bool Vector3::operator==(const Vector3 &p_v) const {
return x == p_v.x && y == p_v.y && z == p_v.z;
}
bool Vector3::operator!=(const Vector3 &p_v) const {
return x != p_v.x || y != p_v.y || z != p_v.z;
}
bool Vector3::operator<(const Vector3 &p_v) const {
if (x == p_v.x) {
if (y == p_v.y) {
return z < p_v.z;
} else {
return y < p_v.y;
}
} else {
return x < p_v.x;
}
}
bool Vector3::operator>(const Vector3 &p_v) const {
if (x == p_v.x) {
if (y == p_v.y) {
return z > p_v.z;
} else {
return y > p_v.y;
}
} else {
return x > p_v.x;
}
}
bool Vector3::operator<=(const Vector3 &p_v) const {
if (x == p_v.x) {
if (y == p_v.y) {
return z <= p_v.z;
} else {
return y < p_v.y;
}
} else {
return x < p_v.x;
}
}
bool Vector3::operator>=(const Vector3 &p_v) const {
if (x == p_v.x) {
if (y == p_v.y) {
return z >= p_v.z;
} else {
return y > p_v.y;
}
} else {
return x > p_v.x;
}
}
_FORCE_INLINE_ Vector3 vec3_cross(const Vector3 &p_a, const Vector3 &p_b) {
return p_a.cross(p_b);
}
_FORCE_INLINE_ real_t vec3_dot(const Vector3 &p_a, const Vector3 &p_b) {
return p_a.dot(p_b);
}
real_t Vector3::length() const {
real_t x2 = x * x;
real_t y2 = y * y;
real_t z2 = z * z;
return Math::sqrt(x2 + y2 + z2);
}
real_t Vector3::length_squared() const {
real_t x2 = x * x;
real_t y2 = y * y;
real_t z2 = z * z;
return x2 + y2 + z2;
}
void Vector3::normalize() {
real_t lengthsq = length_squared();
if (lengthsq == 0) {
x = y = z = 0;
} else {
real_t length = Math::sqrt(lengthsq);
x /= length;
y /= length;
z /= length;
}
}
Vector3 Vector3::normalized() const {
Vector3 v = *this;
v.normalize();
return v;
}
bool Vector3::is_normalized() const {
// use length_squared() instead of length() to avoid sqrt(), makes it more stringent.
return Math::is_equal_approx(length_squared(), 1, (real_t)UNIT_EPSILON);
}
Vector3 Vector3::inverse() const {
return Vector3(1 / x, 1 / y, 1 / z);
}
void Vector3::zero() {
x = y = z = 0;
}
// slide returns the component of the vector along the given plane, specified by its normal vector.
Vector3 Vector3::slide(const Vector3 &p_normal) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 must be normalized.");
#endif
return *this - p_normal * this->dot(p_normal);
}
Vector3 Vector3::bounce(const Vector3 &p_normal) const {
return -reflect(p_normal);
}
Vector3 Vector3::reflect(const Vector3 &p_normal) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 must be normalized.");
#endif
return 2 * p_normal * this->dot(p_normal) - *this;
}
bool Vector3::is_equal_approx(const Vector3 &p_v, real_t p_tolerance) const {
return Math::is_equal_approx(x, p_v.x, p_tolerance) && Math::is_equal_approx(y, p_v.y, p_tolerance) && Math::is_equal_approx(z, p_v.z, p_tolerance);
}
bool Vector3::is_equal_approxt(const Vector3 &p_v, real_t p_tolerance) const {
return Math::is_equal_approx(x, p_v.x, p_tolerance) && Math::is_equal_approx(y, p_v.y, p_tolerance) && Math::is_equal_approx(z, p_v.z, p_tolerance);
}
#endif // VECTOR3_H

View File

@ -1,48 +0,0 @@
/*************************************************************************/
/* vector3i.cpp */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/vector3i.h"
#include "core/vector3.h"
#include "core/ustring.h"
//--STRIP
void Vector3i::set_axis(const int p_axis, const int32_t p_value) {
ERR_FAIL_INDEX(p_axis, 3);
coord[p_axis] = p_value;
}
int32_t Vector3i::get_axis(const int p_axis) const {
ERR_FAIL_INDEX_V(p_axis, 3, 0);
return operator[](p_axis);
}
Vector3i::Axis Vector3i::min_axis() const {
return x < y ? (x < z ? Vector3i::AXIS_X : Vector3i::AXIS_Z) : (y < z ? Vector3i::AXIS_Y : Vector3i::AXIS_Z);
}
Vector3i::Axis Vector3i::max_axis() const {
return x < y ? (y < z ? Vector3i::AXIS_Z : Vector3i::AXIS_Y) : (x < z ? Vector3i::AXIS_Z : Vector3i::AXIS_X);
}
Vector3i Vector3i::clamp(const Vector3i &p_min, const Vector3i &p_max) const {
return Vector3i(
CLAMP(x, p_min.x, p_max.x),
CLAMP(y, p_min.y, p_max.y),
CLAMP(z, p_min.z, p_max.z));
}
Vector3 Vector3i::to_vector3() const {
return Vector3(x, y, z);
}
Vector3i::operator String() const {
return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ")";
}
Vector3i::operator Vector3() const {
return Vector3(x, y, z);
}

View File

@ -1,309 +0,0 @@
/*************************************************************************/
/* vector3i.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
#ifndef VECTOR3I_H
#define VECTOR3I_H
//--STRIP
#include "core/error_macros.h"
#include "core/math_funcs.h"
//--STRIP
class String;
struct Vector3;
struct _NO_DISCARD_CLASS_ Vector3i {
enum Axis {
AXIS_X,
AXIS_Y,
AXIS_Z,
};
union {
struct {
int32_t x;
int32_t y;
int32_t z;
};
int32_t coord[3];
};
_FORCE_INLINE_ const int32_t &operator[](const int p_axis) const {
DEV_ASSERT((unsigned int)p_axis < 3);
return coord[p_axis];
}
_FORCE_INLINE_ int32_t &operator[](const int p_axis) {
DEV_ASSERT((unsigned int)p_axis < 3);
return coord[p_axis];
}
void set_axis(const int p_axis, const int32_t p_value);
int32_t get_axis(const int p_axis) const;
_FORCE_INLINE_ void set_all(int32_t p_value) {
x = y = z = p_value;
}
Vector3i::Axis min_axis() const;
Vector3i::Axis max_axis() const;
_FORCE_INLINE_ int64_t length_squared() const;
_FORCE_INLINE_ double length() const;
_FORCE_INLINE_ void zero();
_FORCE_INLINE_ Vector3i abs() const;
_FORCE_INLINE_ Vector3i sign() const;
Vector3i clamp(const Vector3i &p_min, const Vector3i &p_max) const;
_FORCE_INLINE_ Vector3i linear_interpolate(const Vector3i &p_to, real_t p_weight) const;
/* Operators */
_FORCE_INLINE_ Vector3i &operator+=(const Vector3i &p_v);
_FORCE_INLINE_ Vector3i operator+(const Vector3i &p_v) const;
_FORCE_INLINE_ Vector3i &operator-=(const Vector3i &p_v);
_FORCE_INLINE_ Vector3i operator-(const Vector3i &p_v) const;
_FORCE_INLINE_ Vector3i &operator*=(const Vector3i &p_v);
_FORCE_INLINE_ Vector3i operator*(const Vector3i &p_v) const;
_FORCE_INLINE_ Vector3i &operator/=(const Vector3i &p_v);
_FORCE_INLINE_ Vector3i operator/(const Vector3i &p_v) const;
_FORCE_INLINE_ Vector3i &operator%=(const Vector3i &p_v);
_FORCE_INLINE_ Vector3i operator%(const Vector3i &p_v) const;
_FORCE_INLINE_ Vector3i &operator*=(const int32_t p_scalar);
_FORCE_INLINE_ Vector3i operator*(const int32_t p_scalar) const;
_FORCE_INLINE_ Vector3i &operator/=(const int32_t p_scalar);
_FORCE_INLINE_ Vector3i operator/(const int32_t p_scalar) const;
_FORCE_INLINE_ Vector3i &operator%=(const int32_t p_scalar);
_FORCE_INLINE_ Vector3i operator%(const int32_t p_scalar) const;
_FORCE_INLINE_ Vector3i operator-() const;
_FORCE_INLINE_ bool operator==(const Vector3i &p_v) const;
_FORCE_INLINE_ bool operator!=(const Vector3i &p_v) const;
_FORCE_INLINE_ bool operator<(const Vector3i &p_v) const;
_FORCE_INLINE_ bool operator<=(const Vector3i &p_v) const;
_FORCE_INLINE_ bool operator>(const Vector3i &p_v) const;
_FORCE_INLINE_ bool operator>=(const Vector3i &p_v) const;
Vector3 to_vector3() const;
operator String() const;
operator Vector3() const;
_FORCE_INLINE_ Vector3i() {
x = 0;
y = 0;
z = 0;
}
_FORCE_INLINE_ Vector3i(const int32_t p_x, const int32_t p_y, const int32_t p_z) {
x = p_x;
y = p_y;
z = p_z;
}
};
int64_t Vector3i::length_squared() const {
return x * (int64_t)x + y * (int64_t)y + z * (int64_t)z;
}
double Vector3i::length() const {
return Math::sqrt((double)length_squared());
}
Vector3i Vector3i::abs() const {
return Vector3i(ABS(x), ABS(y), ABS(z));
}
Vector3i Vector3i::sign() const {
return Vector3i(SGN(x), SGN(y), SGN(z));
}
Vector3i Vector3i::linear_interpolate(const Vector3i &p_to, real_t p_weight) const {
return Vector3i(
x + (p_weight * (p_to.x - x)),
y + (p_weight * (p_to.y - y)),
z + (p_weight * (p_to.z - z)));
}
/* Operators */
Vector3i &Vector3i::operator+=(const Vector3i &p_v) {
x += p_v.x;
y += p_v.y;
z += p_v.z;
return *this;
}
Vector3i Vector3i::operator+(const Vector3i &p_v) const {
return Vector3i(x + p_v.x, y + p_v.y, z + p_v.z);
}
Vector3i &Vector3i::operator-=(const Vector3i &p_v) {
x -= p_v.x;
y -= p_v.y;
z -= p_v.z;
return *this;
}
Vector3i Vector3i::operator-(const Vector3i &p_v) const {
return Vector3i(x - p_v.x, y - p_v.y, z - p_v.z);
}
Vector3i &Vector3i::operator*=(const Vector3i &p_v) {
x *= p_v.x;
y *= p_v.y;
z *= p_v.z;
return *this;
}
Vector3i Vector3i::operator*(const Vector3i &p_v) const {
return Vector3i(x * p_v.x, y * p_v.y, z * p_v.z);
}
Vector3i &Vector3i::operator/=(const Vector3i &p_v) {
x /= p_v.x;
y /= p_v.y;
z /= p_v.z;
return *this;
}
Vector3i Vector3i::operator/(const Vector3i &p_v) const {
return Vector3i(x / p_v.x, y / p_v.y, z / p_v.z);
}
Vector3i &Vector3i::operator%=(const Vector3i &p_v) {
x %= p_v.x;
y %= p_v.y;
z %= p_v.z;
return *this;
}
Vector3i Vector3i::operator%(const Vector3i &p_v) const {
return Vector3i(x % p_v.x, y % p_v.y, z % p_v.z);
}
Vector3i &Vector3i::operator*=(const int32_t p_scalar) {
x *= p_scalar;
y *= p_scalar;
z *= p_scalar;
return *this;
}
Vector3i Vector3i::operator*(const int32_t p_scalar) const {
return Vector3i(x * p_scalar, y * p_scalar, z * p_scalar);
}
// Multiplication operators required to workaround issues with LLVM using implicit conversion.
_FORCE_INLINE_ Vector3i operator*(const int32_t p_scalar, const Vector3i &p_vector) {
return p_vector * p_scalar;
}
_FORCE_INLINE_ Vector3i operator*(const int64_t p_scalar, const Vector3i &p_vector) {
return p_vector * p_scalar;
}
_FORCE_INLINE_ Vector3i operator*(const float p_scalar, const Vector3i &p_vector) {
return p_vector * p_scalar;
}
_FORCE_INLINE_ Vector3i operator*(const double p_scalar, const Vector3i &p_vector) {
return p_vector * p_scalar;
}
Vector3i &Vector3i::operator/=(const int32_t p_scalar) {
x /= p_scalar;
y /= p_scalar;
z /= p_scalar;
return *this;
}
Vector3i Vector3i::operator/(const int32_t p_scalar) const {
return Vector3i(x / p_scalar, y / p_scalar, z / p_scalar);
}
Vector3i &Vector3i::operator%=(const int32_t p_scalar) {
x %= p_scalar;
y %= p_scalar;
z %= p_scalar;
return *this;
}
Vector3i Vector3i::operator%(const int32_t p_scalar) const {
return Vector3i(x % p_scalar, y % p_scalar, z % p_scalar);
}
Vector3i Vector3i::operator-() const {
return Vector3i(-x, -y, -z);
}
bool Vector3i::operator==(const Vector3i &p_v) const {
return (x == p_v.x && y == p_v.y && z == p_v.z);
}
bool Vector3i::operator!=(const Vector3i &p_v) const {
return (x != p_v.x || y != p_v.y || z != p_v.z);
}
bool Vector3i::operator<(const Vector3i &p_v) const {
if (x == p_v.x) {
if (y == p_v.y) {
return z < p_v.z;
} else {
return y < p_v.y;
}
} else {
return x < p_v.x;
}
}
bool Vector3i::operator>(const Vector3i &p_v) const {
if (x == p_v.x) {
if (y == p_v.y) {
return z > p_v.z;
} else {
return y > p_v.y;
}
} else {
return x > p_v.x;
}
}
bool Vector3i::operator<=(const Vector3i &p_v) const {
if (x == p_v.x) {
if (y == p_v.y) {
return z <= p_v.z;
} else {
return y < p_v.y;
}
} else {
return x < p_v.x;
}
}
bool Vector3i::operator>=(const Vector3i &p_v) const {
if (x == p_v.x) {
if (y == p_v.y) {
return z >= p_v.z;
} else {
return y > p_v.y;
}
} else {
return x > p_v.x;
}
}
void Vector3i::zero() {
x = y = z = 0;
}
typedef Vector3i Size3i;
typedef Vector3i Point3i;
#endif // VECTOR3I_H

View File

@ -1,163 +0,0 @@
/*************************************************************************/
/* vector4.cpp */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/vector4.h"
#include "core/basis.h"
//--STRIP
void Vector4::set_axis(const int p_axis, const real_t p_value) {
ERR_FAIL_INDEX(p_axis, 4);
components[p_axis] = p_value;
}
real_t Vector4::get_axis(const int p_axis) const {
ERR_FAIL_INDEX_V(p_axis, 4, 0);
return operator[](p_axis);
}
Vector4::Axis Vector4::min_axis() const {
uint32_t min_index = 0;
real_t min_value = x;
for (uint32_t i = 1; i < 4; i++) {
if (operator[](i) <= min_value) {
min_index = i;
min_value = operator[](i);
}
}
return Vector4::Axis(min_index);
}
Vector4::Axis Vector4::max_axis() const {
uint32_t max_index = 0;
real_t max_value = x;
for (uint32_t i = 1; i < 4; i++) {
if (operator[](i) > max_value) {
max_index = i;
max_value = operator[](i);
}
}
return Vector4::Axis(max_index);
}
bool Vector4::is_equal_approx(const Vector4 &p_vec4) const {
return Math::is_equal_approx(x, p_vec4.x) && Math::is_equal_approx(y, p_vec4.y) && Math::is_equal_approx(z, p_vec4.z) && Math::is_equal_approx(w, p_vec4.w);
}
real_t Vector4::length() const {
return Math::sqrt(length_squared());
}
void Vector4::normalize() {
*this /= length();
}
Vector4 Vector4::normalized() const {
return *this / length();
}
bool Vector4::is_normalized() const {
return Math::is_equal_approx(length_squared(), 1, (real_t)UNIT_EPSILON); // Use less epsilon.
}
Vector4 Vector4::limit_length(const real_t p_len) const {
const real_t l = length();
Vector4 v = *this;
if (l > 0 && p_len < l) {
v /= l;
v *= p_len;
}
return v;
}
real_t Vector4::distance_to(const Vector4 &p_to) const {
return (p_to - *this).length();
}
Vector4 Vector4::direction_to(const Vector4 &p_to) const {
Vector4 ret(p_to.x - x, p_to.y - y, p_to.z - z, p_to.w - w);
ret.normalize();
return ret;
}
real_t Vector4::distance_squared_to(const Vector4 &p_to) const {
return (p_to - *this).length_squared();
}
Vector4 Vector4::abs() const {
return Vector4(Math::abs(x), Math::abs(y), Math::abs(z), Math::abs(w));
}
Vector4 Vector4::sign() const {
return Vector4(SGN(x), SGN(y), SGN(z), SGN(w));
}
Vector4 Vector4::floor() const {
return Vector4(Math::floor(x), Math::floor(y), Math::floor(z), Math::floor(w));
}
Vector4 Vector4::ceil() const {
return Vector4(Math::ceil(x), Math::ceil(y), Math::ceil(z), Math::ceil(w));
}
Vector4 Vector4::round() const {
return Vector4(Math::round(x), Math::round(y), Math::round(z), Math::round(w));
}
Vector4 Vector4::linear_interpolate(const Vector4 &p_to, const real_t p_weight) const {
return Vector4(
x + (p_weight * (p_to.x - x)),
y + (p_weight * (p_to.y - y)),
z + (p_weight * (p_to.z - z)),
w + (p_weight * (p_to.w - w)));
}
Vector4 Vector4::cubic_interpolate(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, const real_t p_weight) const {
Vector4 res = *this;
res.x = Math::cubic_interpolate(res.x, p_b.x, p_pre_a.x, p_post_b.x, p_weight);
res.y = Math::cubic_interpolate(res.y, p_b.y, p_pre_a.y, p_post_b.y, p_weight);
res.z = Math::cubic_interpolate(res.z, p_b.z, p_pre_a.z, p_post_b.z, p_weight);
res.w = Math::cubic_interpolate(res.w, p_b.w, p_pre_a.w, p_post_b.w, p_weight);
return res;
}
Vector4 Vector4::posmod(const real_t p_mod) const {
return Vector4(Math::fposmod(x, p_mod), Math::fposmod(y, p_mod), Math::fposmod(z, p_mod), Math::fposmod(w, p_mod));
}
Vector4 Vector4::posmodv(const Vector4 &p_modv) const {
return Vector4(Math::fposmod(x, p_modv.x), Math::fposmod(y, p_modv.y), Math::fposmod(z, p_modv.z), Math::fposmod(w, p_modv.w));
}
void Vector4::snap(const Vector4 &p_step) {
x = Math::stepify(x, p_step.x);
y = Math::stepify(y, p_step.y);
z = Math::stepify(z, p_step.z);
w = Math::stepify(w, p_step.w);
}
Vector4 Vector4::snapped(const Vector4 &p_step) const {
Vector4 v = *this;
v.snap(p_step);
return v;
}
Vector4 Vector4::inverse() const {
return Vector4(1.0f / x, 1.0f / y, 1.0f / z, 1.0f / w);
}
Vector4 Vector4::clamp(const Vector4 &p_min, const Vector4 &p_max) const {
return Vector4(
CLAMP(x, p_min.x, p_max.x),
CLAMP(y, p_min.y, p_max.y),
CLAMP(z, p_min.z, p_max.z),
CLAMP(w, p_min.w, p_max.w));
}
Vector4::operator String() const {
return "(" + String::num_real(x) + ", " + String::num_real(y) + ", " + String::num_real(z) + ", " + String::num_real(w) + ")";
}

View File

@ -1,292 +0,0 @@
/*************************************************************************/
/* vector4.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
#ifndef VECTOR4_H
#define VECTOR4_H
//--STRIP
#include "core/math_defs.h"
#include "core/math_funcs.h"
#include "core/ustring.h"
//--STRIP
struct _NO_DISCARD_CLASS_ Vector4 {
enum Axis {
AXIS_X,
AXIS_Y,
AXIS_Z,
AXIS_W,
};
union {
struct {
real_t x;
real_t y;
real_t z;
real_t w;
};
real_t components[4];
};
_FORCE_INLINE_ real_t &operator[](const int p_axis) {
DEV_ASSERT((unsigned int)p_axis < 4);
return components[p_axis];
}
_FORCE_INLINE_ const real_t &operator[](const int p_axis) const {
DEV_ASSERT((unsigned int)p_axis < 4);
return components[p_axis];
}
_FORCE_INLINE_ void set_all(const real_t p_value);
void set_axis(const int p_axis, const real_t p_value);
real_t get_axis(const int p_axis) const;
Vector4::Axis min_axis() const;
Vector4::Axis max_axis() const;
_FORCE_INLINE_ real_t length_squared() const;
bool is_equal_approx(const Vector4 &p_vec4) const;
real_t length() const;
void normalize();
Vector4 normalized() const;
bool is_normalized() const;
Vector4 limit_length(const real_t p_len = 1.0) const;
_FORCE_INLINE_ void zero();
real_t distance_to(const Vector4 &p_to) const;
real_t distance_squared_to(const Vector4 &p_to) const;
Vector4 direction_to(const Vector4 &p_to) const;
Vector4 abs() const;
Vector4 sign() const;
Vector4 floor() const;
Vector4 ceil() const;
Vector4 round() const;
Vector4 linear_interpolate(const Vector4 &p_to, const real_t p_weight) const;
Vector4 cubic_interpolate(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, const real_t p_weight) const;
Vector4 posmod(const real_t p_mod) const;
Vector4 posmodv(const Vector4 &p_modv) const;
void snap(const Vector4 &p_step);
Vector4 snapped(const Vector4 &p_step) const;
Vector4 clamp(const Vector4 &p_min, const Vector4 &p_max) const;
Vector4 inverse() const;
_FORCE_INLINE_ real_t dot(const Vector4 &p_vec4) const;
_FORCE_INLINE_ void operator+=(const Vector4 &p_vec4);
_FORCE_INLINE_ void operator-=(const Vector4 &p_vec4);
_FORCE_INLINE_ void operator*=(const Vector4 &p_vec4);
_FORCE_INLINE_ void operator/=(const Vector4 &p_vec4);
_FORCE_INLINE_ void operator*=(const real_t &s);
_FORCE_INLINE_ void operator/=(const real_t &s);
_FORCE_INLINE_ Vector4 operator+(const Vector4 &p_vec4) const;
_FORCE_INLINE_ Vector4 operator-(const Vector4 &p_vec4) const;
_FORCE_INLINE_ Vector4 operator*(const Vector4 &p_vec4) const;
_FORCE_INLINE_ Vector4 operator/(const Vector4 &p_vec4) const;
_FORCE_INLINE_ Vector4 operator-() const;
_FORCE_INLINE_ Vector4 operator*(const real_t &s) const;
_FORCE_INLINE_ Vector4 operator/(const real_t &s) const;
_FORCE_INLINE_ bool operator==(const Vector4 &p_vec4) const;
_FORCE_INLINE_ bool operator!=(const Vector4 &p_vec4) const;
_FORCE_INLINE_ bool operator>(const Vector4 &p_vec4) const;
_FORCE_INLINE_ bool operator<(const Vector4 &p_vec4) const;
_FORCE_INLINE_ bool operator>=(const Vector4 &p_vec4) const;
_FORCE_INLINE_ bool operator<=(const Vector4 &p_vec4) const;
operator String() const;
_FORCE_INLINE_ Vector4() {
x = 0;
y = 0;
z = 0;
w = 0;
}
_FORCE_INLINE_ Vector4(real_t p_x, real_t p_y, real_t p_z, real_t p_w) :
x(p_x),
y(p_y),
z(p_z),
w(p_w) {
}
Vector4(const Vector4 &p_vec4) :
x(p_vec4.x),
y(p_vec4.y),
z(p_vec4.z),
w(p_vec4.w) {
}
void operator=(const Vector4 &p_vec4) {
x = p_vec4.x;
y = p_vec4.y;
z = p_vec4.z;
w = p_vec4.w;
}
};
void Vector4::set_all(const real_t p_value) {
x = y = z = p_value;
}
real_t Vector4::dot(const Vector4 &p_vec4) const {
return x * p_vec4.x + y * p_vec4.y + z * p_vec4.z + w * p_vec4.w;
}
real_t Vector4::length_squared() const {
return dot(*this);
}
void Vector4::zero() {
x = y = z = 0;
}
void Vector4::operator+=(const Vector4 &p_vec4) {
x += p_vec4.x;
y += p_vec4.y;
z += p_vec4.z;
w += p_vec4.w;
}
void Vector4::operator-=(const Vector4 &p_vec4) {
x -= p_vec4.x;
y -= p_vec4.y;
z -= p_vec4.z;
w -= p_vec4.w;
}
void Vector4::operator*=(const Vector4 &p_vec4) {
x *= p_vec4.x;
y *= p_vec4.y;
z *= p_vec4.z;
w *= p_vec4.w;
}
void Vector4::operator/=(const Vector4 &p_vec4) {
x /= p_vec4.x;
y /= p_vec4.y;
z /= p_vec4.z;
w /= p_vec4.w;
}
void Vector4::operator*=(const real_t &s) {
x *= s;
y *= s;
z *= s;
w *= s;
}
void Vector4::operator/=(const real_t &s) {
*this *= 1.0f / s;
}
Vector4 Vector4::operator+(const Vector4 &p_vec4) const {
return Vector4(x + p_vec4.x, y + p_vec4.y, z + p_vec4.z, w + p_vec4.w);
}
Vector4 Vector4::operator-(const Vector4 &p_vec4) const {
return Vector4(x - p_vec4.x, y - p_vec4.y, z - p_vec4.z, w - p_vec4.w);
}
Vector4 Vector4::operator*(const Vector4 &p_vec4) const {
return Vector4(x * p_vec4.x, y * p_vec4.y, z * p_vec4.z, w * p_vec4.w);
}
Vector4 Vector4::operator/(const Vector4 &p_vec4) const {
return Vector4(x / p_vec4.x, y / p_vec4.y, z / p_vec4.z, w / p_vec4.w);
}
Vector4 Vector4::operator-() const {
return Vector4(-x, -y, -z, -w);
}
Vector4 Vector4::operator*(const real_t &s) const {
return Vector4(x * s, y * s, z * s, w * s);
}
Vector4 Vector4::operator/(const real_t &s) const {
return *this * (1.0f / s);
}
bool Vector4::operator==(const Vector4 &p_vec4) const {
return x == p_vec4.x && y == p_vec4.y && z == p_vec4.z && w == p_vec4.w;
}
bool Vector4::operator!=(const Vector4 &p_vec4) const {
return x != p_vec4.x || y != p_vec4.y || z != p_vec4.z || w != p_vec4.w;
}
bool Vector4::operator<(const Vector4 &p_v) const {
if (x == p_v.x) {
if (y == p_v.y) {
if (z == p_v.z) {
return w < p_v.w;
}
return z < p_v.z;
}
return y < p_v.y;
}
return x < p_v.x;
}
bool Vector4::operator>(const Vector4 &p_v) const {
if (x == p_v.x) {
if (y == p_v.y) {
if (z == p_v.z) {
return w > p_v.w;
}
return z > p_v.z;
}
return y > p_v.y;
}
return x > p_v.x;
}
bool Vector4::operator<=(const Vector4 &p_v) const {
if (x == p_v.x) {
if (y == p_v.y) {
if (z == p_v.z) {
return w <= p_v.w;
}
return z < p_v.z;
}
return y < p_v.y;
}
return x < p_v.x;
}
bool Vector4::operator>=(const Vector4 &p_v) const {
if (x == p_v.x) {
if (y == p_v.y) {
if (z == p_v.z) {
return w >= p_v.w;
}
return z > p_v.z;
}
return y > p_v.y;
}
return x > p_v.x;
}
_FORCE_INLINE_ Vector4 operator*(const float p_scalar, const Vector4 &p_vec) {
return p_vec * p_scalar;
}
_FORCE_INLINE_ Vector4 operator*(const double p_scalar, const Vector4 &p_vec) {
return p_vec * p_scalar;
}
_FORCE_INLINE_ Vector4 operator*(const int32_t p_scalar, const Vector4 &p_vec) {
return p_vec * p_scalar;
}
_FORCE_INLINE_ Vector4 operator*(const int64_t p_scalar, const Vector4 &p_vec) {
return p_vec * p_scalar;
}
#endif // VECTOR4_H

View File

@ -1,82 +0,0 @@
/*************************************************************************/
/* vector4i.cpp */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/vector4i.h"
#include "core/vector4.h"
#include "core/ustring.h"
//--STRIP
void Vector4i::set_axis(const int p_axis, const int32_t p_value) {
ERR_FAIL_INDEX(p_axis, 4);
coord[p_axis] = p_value;
}
int32_t Vector4i::get_axis(const int p_axis) const {
ERR_FAIL_INDEX_V(p_axis, 4, 0);
return operator[](p_axis);
}
Vector4i::Axis Vector4i::min_axis() const {
uint32_t min_index = 0;
int32_t min_value = x;
for (uint32_t i = 1; i < 4; i++) {
if (operator[](i) <= min_value) {
min_index = i;
min_value = operator[](i);
}
}
return Vector4i::Axis(min_index);
}
Vector4i::Axis Vector4i::max_axis() const {
uint32_t max_index = 0;
int32_t max_value = x;
for (uint32_t i = 1; i < 4; i++) {
if (operator[](i) > max_value) {
max_index = i;
max_value = operator[](i);
}
}
return Vector4i::Axis(max_index);
}
Vector4i Vector4i::clamp(const Vector4i &p_min, const Vector4i &p_max) const {
return Vector4i(
CLAMP(x, p_min.x, p_max.x),
CLAMP(y, p_min.y, p_max.y),
CLAMP(z, p_min.z, p_max.z),
CLAMP(w, p_min.w, p_max.w));
}
Vector4i Vector4i::linear_interpolate(const Vector4i &p_to, const real_t p_weight) const {
return Vector4i(
x + (p_weight * (p_to.x - x)),
y + (p_weight * (p_to.y - y)),
z + (p_weight * (p_to.z - z)),
w + (p_weight * (p_to.w - w)));
}
Vector4 Vector4i::to_vector4() const {
return Vector4(x, y, z, w);
}
Vector4i::operator String() const {
return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ", " + itos(w) + ")";
}
Vector4i::operator Vector4() const {
return Vector4(x, y, z, w);
}
/*
Vector4i::Vector4i(const Vector4 &p_vec4) {
x = p_vec4.x;
y = p_vec4.y;
z = p_vec4.z;
w = p_vec4.w;
}
*/

View File

@ -1,335 +0,0 @@
/*************************************************************************/
/* vector4i.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
#ifndef VECTOR4I_H
#define VECTOR4I_H
//--STRIP
#include "core/error_macros.h"
#include "core/math_funcs.h"
//--STRIP
class String;
struct Vector4;
struct _NO_DISCARD_CLASS_ Vector4i {
enum Axis {
AXIS_X,
AXIS_Y,
AXIS_Z,
AXIS_W,
};
union {
struct {
int32_t x;
int32_t y;
int32_t z;
int32_t w;
};
int32_t coord[4];
};
_FORCE_INLINE_ const int32_t &operator[](const int p_axis) const {
DEV_ASSERT((unsigned int)p_axis < 4);
return coord[p_axis];
}
_FORCE_INLINE_ int32_t &operator[](const int p_axis) {
DEV_ASSERT((unsigned int)p_axis < 4);
return coord[p_axis];
}
_FORCE_INLINE_ void set_all(const int32_t p_value);
void set_axis(const int p_axis, const int32_t p_value);
int32_t get_axis(const int p_axis) const;
Vector4i::Axis min_axis() const;
Vector4i::Axis max_axis() const;
_FORCE_INLINE_ int64_t length_squared() const;
_FORCE_INLINE_ double length() const;
_FORCE_INLINE_ void zero();
_FORCE_INLINE_ Vector4i abs() const;
_FORCE_INLINE_ Vector4i sign() const;
Vector4i clamp(const Vector4i &p_min, const Vector4i &p_max) const;
Vector4i linear_interpolate(const Vector4i &p_to, const real_t p_weight) const;
/* Operators */
_FORCE_INLINE_ Vector4i &operator+=(const Vector4i &p_v);
_FORCE_INLINE_ Vector4i operator+(const Vector4i &p_v) const;
_FORCE_INLINE_ Vector4i &operator-=(const Vector4i &p_v);
_FORCE_INLINE_ Vector4i operator-(const Vector4i &p_v) const;
_FORCE_INLINE_ Vector4i &operator*=(const Vector4i &p_v);
_FORCE_INLINE_ Vector4i operator*(const Vector4i &p_v) const;
_FORCE_INLINE_ Vector4i &operator/=(const Vector4i &p_v);
_FORCE_INLINE_ Vector4i operator/(const Vector4i &p_v) const;
_FORCE_INLINE_ Vector4i &operator%=(const Vector4i &p_v);
_FORCE_INLINE_ Vector4i operator%(const Vector4i &p_v) const;
_FORCE_INLINE_ Vector4i &operator*=(const int32_t p_scalar);
_FORCE_INLINE_ Vector4i operator*(const int32_t p_scalar) const;
_FORCE_INLINE_ Vector4i &operator/=(const int32_t p_scalar);
_FORCE_INLINE_ Vector4i operator/(const int32_t p_scalar) const;
_FORCE_INLINE_ Vector4i &operator%=(const int32_t p_scalar);
_FORCE_INLINE_ Vector4i operator%(const int32_t p_scalar) const;
_FORCE_INLINE_ Vector4i operator-() const;
_FORCE_INLINE_ bool operator==(const Vector4i &p_v) const;
_FORCE_INLINE_ bool operator!=(const Vector4i &p_v) const;
_FORCE_INLINE_ bool operator<(const Vector4i &p_v) const;
_FORCE_INLINE_ bool operator<=(const Vector4i &p_v) const;
_FORCE_INLINE_ bool operator>(const Vector4i &p_v) const;
_FORCE_INLINE_ bool operator>=(const Vector4i &p_v) const;
Vector4 to_vector4() const;
operator String() const;
operator Vector4() const;
_FORCE_INLINE_ Vector4i() {
x = 0;
y = 0;
z = 0;
w = 0;
}
//Vector4i(const Vector4 &p_vec4);
_FORCE_INLINE_ Vector4i(const int32_t p_x, const int32_t p_y, const int32_t p_z, const int32_t p_w) {
x = p_x;
y = p_y;
z = p_z;
w = p_w;
}
};
void Vector4i::set_all(const int32_t p_value) {
x = y = z = p_value;
}
int64_t Vector4i::length_squared() const {
return x * (int64_t)x + y * (int64_t)y + z * (int64_t)z + w * (int64_t)w;
}
double Vector4i::length() const {
return Math::sqrt((double)length_squared());
}
Vector4i Vector4i::abs() const {
return Vector4i(ABS(x), ABS(y), ABS(z), ABS(w));
}
Vector4i Vector4i::sign() const {
return Vector4i(SGN(x), SGN(y), SGN(z), SGN(w));
}
/* Operators */
Vector4i &Vector4i::operator+=(const Vector4i &p_v) {
x += p_v.x;
y += p_v.y;
z += p_v.z;
w += p_v.w;
return *this;
}
Vector4i Vector4i::operator+(const Vector4i &p_v) const {
return Vector4i(x + p_v.x, y + p_v.y, z + p_v.z, w + p_v.w);
}
Vector4i &Vector4i::operator-=(const Vector4i &p_v) {
x -= p_v.x;
y -= p_v.y;
z -= p_v.z;
w -= p_v.w;
return *this;
}
Vector4i Vector4i::operator-(const Vector4i &p_v) const {
return Vector4i(x - p_v.x, y - p_v.y, z - p_v.z, w - p_v.w);
}
Vector4i &Vector4i::operator*=(const Vector4i &p_v) {
x *= p_v.x;
y *= p_v.y;
z *= p_v.z;
w *= p_v.w;
return *this;
}
Vector4i Vector4i::operator*(const Vector4i &p_v) const {
return Vector4i(x * p_v.x, y * p_v.y, z * p_v.z, w * p_v.w);
}
Vector4i &Vector4i::operator/=(const Vector4i &p_v) {
x /= p_v.x;
y /= p_v.y;
z /= p_v.z;
w /= p_v.w;
return *this;
}
Vector4i Vector4i::operator/(const Vector4i &p_v) const {
return Vector4i(x / p_v.x, y / p_v.y, z / p_v.z, w / p_v.w);
}
Vector4i &Vector4i::operator%=(const Vector4i &p_v) {
x %= p_v.x;
y %= p_v.y;
z %= p_v.z;
w %= p_v.w;
return *this;
}
Vector4i Vector4i::operator%(const Vector4i &p_v) const {
return Vector4i(x % p_v.x, y % p_v.y, z % p_v.z, w % p_v.w);
}
Vector4i &Vector4i::operator*=(const int32_t p_scalar) {
x *= p_scalar;
y *= p_scalar;
z *= p_scalar;
w *= p_scalar;
return *this;
}
Vector4i Vector4i::operator*(const int32_t p_scalar) const {
return Vector4i(x * p_scalar, y * p_scalar, z * p_scalar, w * p_scalar);
}
// Multiplication operators required to workaround issues with LLVM using implicit conversion.
_FORCE_INLINE_ Vector4i operator*(const int32_t p_scalar, const Vector4i &p_vector) {
return p_vector * p_scalar;
}
_FORCE_INLINE_ Vector4i operator*(const int64_t p_scalar, const Vector4i &p_vector) {
return p_vector * p_scalar;
}
_FORCE_INLINE_ Vector4i operator*(const float p_scalar, const Vector4i &p_vector) {
return p_vector * p_scalar;
}
_FORCE_INLINE_ Vector4i operator*(const double p_scalar, const Vector4i &p_vector) {
return p_vector * p_scalar;
}
Vector4i &Vector4i::operator/=(const int32_t p_scalar) {
x /= p_scalar;
y /= p_scalar;
z /= p_scalar;
w /= p_scalar;
return *this;
}
Vector4i Vector4i::operator/(const int32_t p_scalar) const {
return Vector4i(x / p_scalar, y / p_scalar, z / p_scalar, w / p_scalar);
}
Vector4i &Vector4i::operator%=(const int32_t p_scalar) {
x %= p_scalar;
y %= p_scalar;
z %= p_scalar;
w %= p_scalar;
return *this;
}
Vector4i Vector4i::operator%(const int32_t p_scalar) const {
return Vector4i(x % p_scalar, y % p_scalar, z % p_scalar, w % p_scalar);
}
Vector4i Vector4i::operator-() const {
return Vector4i(-x, -y, -z, -w);
}
bool Vector4i::operator==(const Vector4i &p_v) const {
return (x == p_v.x && y == p_v.y && z == p_v.z && w == p_v.w);
}
bool Vector4i::operator!=(const Vector4i &p_v) const {
return (x != p_v.x || y != p_v.y || z != p_v.z || w != p_v.w);
}
bool Vector4i::operator<(const Vector4i &p_v) const {
if (x == p_v.x) {
if (y == p_v.y) {
if (z == p_v.z) {
return w < p_v.w;
} else {
return z < p_v.z;
}
} else {
return y < p_v.y;
}
} else {
return x < p_v.x;
}
}
bool Vector4i::operator>(const Vector4i &p_v) const {
if (x == p_v.x) {
if (y == p_v.y) {
if (z == p_v.z) {
return w > p_v.w;
} else {
return z > p_v.z;
}
} else {
return y > p_v.y;
}
} else {
return x > p_v.x;
}
}
bool Vector4i::operator<=(const Vector4i &p_v) const {
if (x == p_v.x) {
if (y == p_v.y) {
if (z == p_v.z) {
return w <= p_v.w;
} else {
return z < p_v.z;
}
} else {
return y < p_v.y;
}
} else {
return x < p_v.x;
}
}
bool Vector4i::operator>=(const Vector4i &p_v) const {
if (x == p_v.x) {
if (y == p_v.y) {
if (z == p_v.z) {
return w >= p_v.w;
} else {
return z > p_v.z;
}
} else {
return y > p_v.y;
}
} else {
return x > p_v.x;
}
}
void Vector4i::zero() {
x = y = z = w = 0;
}
typedef Vector4i Size4i;
typedef Vector4i Point4i;
#endif // VECTOR4I_H

View File

@ -91,97 +91,10 @@
//--STRIP //--STRIP
{{FILE:sfwl/core/string_name.cpp}} {{FILE:sfwl/core/string_name.cpp}}
//--STRIP
//#include "core/aabb.h"
//--STRIP
{{FILE:sfwl/core/aabb.cpp}}
//--STRIP
//#include "core/vector3i.h"
//#include "core/vector3.h"
//#include "core/ustring.h"
//--STRIP
{{FILE:sfwl/core/vector3i.cpp}}
//--STRIP
//#include "core/transform_2d.h"
//--STRIP
{{FILE:sfwl/core/transform_2d.cpp}}
//--STRIP
//#include "core/projection.h"
//#include "core/aabb.h"
//#include "core/math_funcs.h"
//#include "core/plane.h"
//#include "core/rect2.h"
//#include "core/transform.h"
//--STRIP
{{FILE:sfwl/core/projection.cpp}}
//--STRIP
//#include "core/vector3.h"
//#include "core/basis.h"
//--STRIP
{{FILE:sfwl/core/vector3.cpp}}
//--STRIP //--STRIP
//#include "core/pcg.h" //#include "core/pcg.h"
//--STRIP //--STRIP
{{FILE:sfwl/core/pcg.cpp}} {{FILE:sfwl/core/pcg.cpp}}
//--STRIP
//#include "core/vector2.h"
//#include "core/ustring.h"
//--STRIP
{{FILE:sfwl/core/vector2.cpp}}
//--STRIP
//#include "core/basis.h"
//#include "core/math_funcs.h"
//--STRIP
{{FILE:sfwl/core/basis.cpp}}
//--STRIP
//#include "face3.h"
//--STRIP
{{FILE:sfwl/core/face3.cpp}}
//--STRIP
//#include "core/vector4i.h"
//#include "core/vector4.h"
//#include "core/ustring.h"
//--STRIP
{{FILE:sfwl/core/vector4i.cpp}}
//--STRIP
//#include "core/transform.h"
//#include "core/math_funcs.h"
//--STRIP
{{FILE:sfwl/core/transform.cpp}}
//--STRIP
//#include "core/color.h"
//#include "core/math_funcs.h"
//--STRIP
{{FILE:sfwl/core/color.cpp}}
//--STRIP
//#include "core/quaternion.h"
//#include "core/basis.h"
//--STRIP
{{FILE:sfwl/core/quaternion.cpp}}
//--STRIP
//#include "core/plane.h"
//#include "core/math_funcs.h"
//--STRIP
{{FILE:sfwl/core/plane.cpp}}
//--STRIP
//#include "core/vector2i.h"
//#include "core/ustring.h"
//--STRIP
{{FILE:sfwl/core/vector2i.cpp}}
//--STRIP
//#include "core/transform_2d.h" // Includes rect2.h but Rect2 needs Transform2D
//#include "core/rect2i.h"
//--STRIP
{{FILE:sfwl/core/rect2.cpp}}
//--STRIP
//#include "core/transform_2d.h" // Includes rect2.h but Rect2 needs Transform2D
//--STRIP
{{FILE:sfwl/core/rect2i.cpp}}
//--STRIP
//#include "core/vector4.h"
//#include "core/basis.h"
//--STRIP
{{FILE:sfwl/core/vector4.cpp}}
//--STRIP //--STRIP
//#include "file_access.h" //#include "file_access.h"

View File

@ -223,109 +223,6 @@
//Math classes //Math classes
//--STRIP //--STRIP
//--STRIP
//#include "core/math_funcs.h"
//#include "core/ustring.h"
//--STRIP
{{FILE:sfwl/core/color.h}}
//--STRIP
//#include "core/math_funcs.h"
//#include "core/error_macros.h"
//--STRIP
{{FILE:sfwl/core/vector2.h}}
//--STRIP
//#include "core/error_macros.h"
//#include "core/math_funcs.h"
//#include "core/vector2.h"
//--STRIP
{{FILE:sfwl/core/vector2i.h}}
//--STRIP
//#include "core/vector2.h" // also includes math_funcs and ustring
//#include "core/vector2i.h"
//--STRIP
{{FILE:sfwl/core/rect2.h}}
//--STRIP
//#include "core/vector2i.h" // also includes math_funcs and ustring
//--STRIP
{{FILE:sfwl/core/rect2i.h}}
//--STRIP
//#include "core/math_funcs.h"
//#include "core/ustring.h"
//--STRIP
{{FILE:sfwl/core/vector3.h}}
//--STRIP
//#include "core/error_macros.h"
//#include "core/math_funcs.h"
//--STRIP
{{FILE:sfwl/core/vector3i.h}}
//--STRIP
//#include "core/math_defs.h"
//#include "core/math_funcs.h"
//#include "core/ustring.h"
//--STRIP
{{FILE:sfwl/core/vector4.h}}
//--STRIP
//#include "core/error_macros.h"
//#include "core/math_funcs.h"
//--STRIP
{{FILE:sfwl/core/vector4i.h}}
//--STRIP
//#include "core/vector3.h"
//--STRIP
{{FILE:sfwl/core/plane.h}}
//--STRIP
//#include "core/math_defs.h"
//#include "core/plane.h"
//#include "core/vector3.h"
//--STRIP
{{FILE:sfwl/core/aabb.h}}
//--STRIP
//#include "core/math_defs.h"
//#include "core/math_funcs.h"
//#include "core/vector3.h"
//#include "core/ustring.h"
//--STRIP
{{FILE:sfwl/core/quaternion.h}}
//--STRIP
//#include "core/vector.h"
//#include "core/math_defs.h"
//#include "core/vector3.h"
//#include "core/math_defs.h"
//#include "core/math_funcs.h"
//#include "core/ustring.h"
//#include "core/vector4.h"
//--STRIP
{{FILE:sfwl/core/projection.h}}
//--STRIP
//#include "core/quaternion.h"
//#include "core/vector3.h"
//#include "core/vector3i.h"
//--STRIP
{{FILE:sfwl/core/basis.h}}
//--STRIP
//#include "core/pool_vector.h"
//#include "core/rect2.h" // also includes vector2, math_funcs, and ustring
//#include "core/rect2i.h" // also includes vector2i, math_funcs, and ustring
//--STRIP
{{FILE:sfwl/core/transform_2d.h}}
//--STRIP
//#include "core/aabb.h"
//#include "core/plane.h"
//#include "core/transform.h"
//#include "core/vector3.h"
//--STRIP
{{FILE:sfwl/core/face3.h}}
//--STRIP
//#include "core/aabb.h"
//#include "core/basis.h"
//#include "core/plane.h"
//#include "core/vector3i.h"
//#include "core/pool_vector.h"
//--STRIP
{{FILE:sfwl/core/transform.h}}
//--STRIP //--STRIP
//hashfuncs.h Needs most math classes //hashfuncs.h Needs most math classes
//--STRIP //--STRIP