Skip to content

Commit

Permalink
Added component-wise min and max functions for vectors
Browse files Browse the repository at this point in the history
  • Loading branch information
0xafbf committed Jan 29, 2023
1 parent d01ac9c commit 164b42a
Show file tree
Hide file tree
Showing 10 changed files with 141 additions and 20 deletions.
8 changes: 8 additions & 0 deletions core/math/vector3.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ struct _NO_DISCARD_ Vector3 {
return x < y ? (y < z ? Vector3::AXIS_Z : Vector3::AXIS_Y) : (x < z ? Vector3::AXIS_Z : Vector3::AXIS_X);
}

Vector3 min(const Vector3 &p_vector3) const {
return Vector3(MIN(x, p_vector3.x), MIN(y, p_vector3.y), MIN(z, p_vector3.z));
}

Vector3 max(const Vector3 &p_vector3) const {
return Vector3(MAX(x, p_vector3.x), MAX(y, p_vector3.y), MAX(z, p_vector3.z));
}

_FORCE_INLINE_ real_t length() const;
_FORCE_INLINE_ real_t length_squared() const;

Expand Down
8 changes: 8 additions & 0 deletions core/math/vector3i.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ struct _NO_DISCARD_ Vector3i {
Vector3i::Axis min_axis_index() const;
Vector3i::Axis max_axis_index() const;

Vector3i min(const Vector3i &p_vector3i) const {
return Vector3i(MIN(x, p_vector3i.x), MIN(y, p_vector3i.y), MIN(z, p_vector3i.z));
}

Vector3i max(const Vector3i &p_vector3i) const {
return Vector3i(MAX(x, p_vector3i.x), MAX(y, p_vector3i.y), MAX(z, p_vector3i.z));
}

_FORCE_INLINE_ int64_t length_squared() const;
_FORCE_INLINE_ double length() const;

Expand Down
8 changes: 8 additions & 0 deletions core/math/vector4.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ struct _NO_DISCARD_ Vector4 {
Vector4::Axis min_axis_index() const;
Vector4::Axis max_axis_index() const;

Vector4 min(const Vector4 &p_vector4) const {
return Vector4(MIN(x, p_vector4.x), MIN(y, p_vector4.y), MIN(z, p_vector4.z), MIN(w, p_vector4.w));
}

Vector4 max(const Vector4 &p_vector4) const {
return Vector4(MAX(x, p_vector4.x), MAX(y, p_vector4.y), MAX(z, p_vector4.z), MAX(w, p_vector4.w));
}

_FORCE_INLINE_ real_t length_squared() const;
bool is_equal_approx(const Vector4 &p_vec4) const;
bool is_zero_approx() const;
Expand Down
8 changes: 8 additions & 0 deletions core/math/vector4i.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ struct _NO_DISCARD_ Vector4i {
Vector4i::Axis min_axis_index() const;
Vector4i::Axis max_axis_index() const;

Vector4i min(const Vector4i &p_vector4i) const {
return Vector4i(MIN(x, p_vector4i.x), MIN(y, p_vector4i.y), MIN(z, p_vector4i.z), MIN(w, p_vector4i.w));
}

Vector4i max(const Vector4i &p_vector4i) const {
return Vector4i(MAX(x, p_vector4i.x), MAX(y, p_vector4i.y), MAX(z, p_vector4i.z), MAX(w, p_vector4i.w));
}

_FORCE_INLINE_ int64_t length_squared() const;
_FORCE_INLINE_ double length() const;

Expand Down
92 changes: 74 additions & 18 deletions core/variant/variant_utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -540,23 +540,51 @@ struct VariantUtilityFunctions {
r_error.expected = 2;
return Variant();
}
Variant base = *p_args[0];
Variant ret;
const Variant &base = *p_args[0];
const Variant::Type base_type = base.get_type();
Variant ret = base;

for (int i = 1; i < p_argcount; i++) {
bool valid;
Variant::evaluate(Variant::OP_LESS, base, *p_args[i], ret, valid);
if (!valid) {
const Variant &x = *p_args[i];
if (x.get_type() != base_type) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.expected = base.get_type();
r_error.expected = base_type;
r_error.argument = i;
return Variant();
}
if (ret.booleanize()) {
base = *p_args[i];
switch (base_type) {
case Variant::INT: {
ret = MAX(VariantInternalAccessor<int64_t>::get(&ret), VariantInternalAccessor<int64_t>::get(&x));
} break;
case Variant::FLOAT: {
ret = MAX(VariantInternalAccessor<double>::get(&ret), VariantInternalAccessor<double>::get(&x));
} break;
case Variant::VECTOR2: {
ret = VariantInternalAccessor<Vector2>::get(&ret).max(VariantInternalAccessor<Vector2>::get(&x));
} break;
case Variant::VECTOR2I: {
ret = VariantInternalAccessor<Vector2i>::get(&ret).max(VariantInternalAccessor<Vector2i>::get(&x));
} break;
case Variant::VECTOR3: {
ret = VariantInternalAccessor<Vector3>::get(&ret).max(VariantInternalAccessor<Vector3>::get(&x));
} break;
case Variant::VECTOR3I: {
ret = VariantInternalAccessor<Vector3i>::get(&ret).max(VariantInternalAccessor<Vector3i>::get(&x));
} break;
case Variant::VECTOR4: {
ret = VariantInternalAccessor<Vector4>::get(&ret).max(VariantInternalAccessor<Vector4>::get(&x));
} break;
case Variant::VECTOR4I: {
ret = VariantInternalAccessor<Vector4i>::get(&ret).max(VariantInternalAccessor<Vector4i>::get(&x));
} break;
default: {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
return Variant();
}
}
}
r_error.error = Callable::CallError::CALL_OK;
return base;
return ret;
}

static inline double maxf(double x, double y) {
Expand All @@ -573,23 +601,51 @@ struct VariantUtilityFunctions {
r_error.expected = 2;
return Variant();
}
Variant base = *p_args[0];
Variant ret;
const Variant &base = *p_args[0];
const Variant::Type base_type = base.get_type();
Variant ret = base;

for (int i = 1; i < p_argcount; i++) {
bool valid;
Variant::evaluate(Variant::OP_GREATER, base, *p_args[i], ret, valid);
if (!valid) {
const Variant &x = *p_args[i];
if (x.get_type() != base_type) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.expected = base.get_type();
r_error.expected = base_type;
r_error.argument = i;
return Variant();
}
if (ret.booleanize()) {
base = *p_args[i];
switch (base_type) {
case Variant::INT: {
ret = MIN(VariantInternalAccessor<int64_t>::get(&ret), VariantInternalAccessor<int64_t>::get(&x));
} break;
case Variant::FLOAT: {
ret = MIN(VariantInternalAccessor<double>::get(&ret), VariantInternalAccessor<double>::get(&x));
} break;
case Variant::VECTOR2: {
ret = VariantInternalAccessor<Vector2>::get(&ret).min(VariantInternalAccessor<Vector2>::get(&x));
} break;
case Variant::VECTOR2I: {
ret = VariantInternalAccessor<Vector2i>::get(&ret).min(VariantInternalAccessor<Vector2i>::get(&x));
} break;
case Variant::VECTOR3: {
ret = VariantInternalAccessor<Vector3>::get(&ret).min(VariantInternalAccessor<Vector3>::get(&x));
} break;
case Variant::VECTOR3I: {
ret = VariantInternalAccessor<Vector3i>::get(&ret).min(VariantInternalAccessor<Vector3i>::get(&x));
} break;
case Variant::VECTOR4: {
ret = VariantInternalAccessor<Vector4>::get(&ret).min(VariantInternalAccessor<Vector4>::get(&x));
} break;
case Variant::VECTOR4I: {
ret = VariantInternalAccessor<Vector4i>::get(&ret).min(VariantInternalAccessor<Vector4i>::get(&x));
} break;
default: {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
return Variant();
}
}
}
r_error.error = Callable::CallError::CALL_OK;
return base;
return ret;
}

static inline double minf(double x, double y) {
Expand Down
6 changes: 4 additions & 2 deletions doc/classes/@GlobalScope.xml
Original file line number Diff line number Diff line change
Expand Up @@ -656,9 +656,10 @@
<method name="max" qualifiers="vararg">
<return type="Variant" />
<description>
Returns the maximum of the given values. This function can take any number of arguments.
Returns the maximum of the given values. This function can take any number of arguments. It does component-wise comparison for vectors.
[codeblock]
max(1, 7, 3, -6, 5) # Returns 7
max(Vector2(2, 4), Vector2(8, 1)) # Returns Vector2(8, 4)
[/codeblock]
</description>
</method>
Expand Down Expand Up @@ -689,9 +690,10 @@
<method name="min" qualifiers="vararg">
<return type="Variant" />
<description>
Returns the minimum of the given values. This function can take any number of arguments.
Returns the minimum of the given values. This function can take any number of arguments. It does component-wise comparison for vectors.
[codeblock]
min(1, 7, 3, -6, 5) # Returns -6
min(Vector2(2, 4), Vector2(8, 1)) # Returns Vector2(2, 1)
[/codeblock]
</description>
</method>
Expand Down
8 changes: 8 additions & 0 deletions tests/core/math/test_vector3.h
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,14 @@ TEST_CASE("[Vector3] Other methods") {
CHECK_MESSAGE(
vector.snapped(Vector3(0.25, 0.25, 0.25)) == Vector3(1.25, 3.5, 5.5),
"Vector3 snapped to 0.25 should give exact results.");

CHECK_MESSAGE(
Vector3(1.2, 2.5, 2.0).is_equal_approx(vector.min(Vector3(3.0, 2.5, 2.0))),
"Vector3 min should return expected value.");

CHECK_MESSAGE(
Vector3(5.3, 3.4, 5.6).is_equal_approx(vector.max(Vector3(5.3, 2.0, 3.0))),
"Vector3 max should return expected value.");
}

TEST_CASE("[Vector3] Plane methods") {
Expand Down
7 changes: 7 additions & 0 deletions tests/core/math/test_vector3i.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,13 @@ TEST_CASE("[Vector3i] Operators") {
TEST_CASE("[Vector3i] Other methods") {
const Vector3i vector = Vector3i(1, 3, -7);

CHECK_MESSAGE(
vector.min(Vector3i(3, 2, 5)) == Vector3i(1, 2, -7),
"Vector3i min should return expected value.");
CHECK_MESSAGE(
vector.max(Vector3i(5, 2, 4)) == Vector3i(5, 3, 4),
"Vector3i max should return expected value.");

CHECK_MESSAGE(
vector.snapped(Vector3i(4, 2, 5)) == Vector3i(0, 4, -5),
"Vector3i snapped should work as expected.");
Expand Down
8 changes: 8 additions & 0 deletions tests/core/math/test_vector4.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,14 @@ TEST_CASE("[Vector4] Other methods") {
CHECK_MESSAGE(
vector.snapped(Vector4(0.25, 0.25, 0.25, 0.25)) == Vector4(1.25, 3.5, 5.5, 1.5),
"Vector4 snapped to 0.25 should give exact results.");

CHECK_MESSAGE(
Vector4(1.2, 2.5, 2.0, 1.6).is_equal_approx(vector.min(Vector4(3.0, 2.5, 2.0, 3.4))),
"Vector4 min should return expected value.");

CHECK_MESSAGE(
Vector4(5.3, 3.4, 5.6, 4.2).is_equal_approx(vector.max(Vector4(5.3, 2.0, 3.0, 4.2))),
"Vector4 max should return expected value.");
}

TEST_CASE("[Vector4] Rounding methods") {
Expand Down
8 changes: 8 additions & 0 deletions tests/core/math/test_vector4i.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,14 @@ TEST_CASE("[Vector4i] Operators") {
TEST_CASE("[Vector3i] Other methods") {
const Vector4i vector = Vector4i(1, 3, -7, 13);

CHECK_MESSAGE(
vector.min(Vector4i(3, 2, 5, 8)) == Vector4i(1, 2, -7, 8),
"Vector4i min should return expected value.");

CHECK_MESSAGE(
vector.max(Vector4i(5, 2, 4, 8)) == Vector4i(5, 3, 4, 13),
"Vector4i max should return expected value.");

CHECK_MESSAGE(
vector.snapped(Vector4i(4, 2, 5, 8)) == Vector4i(0, 4, -5, 16),
"Vector4i snapped should work as expected.");
Expand Down

0 comments on commit 164b42a

Please sign in to comment.