Replace float with real_t in most files, defined at the top of each file via using. Objects such as Vector3 now accept doubles as inputs, and convert to real_t internally. I've added default Vectors such as Vector3.Zero. Other misc C# improvements such as Mathf.RoundToInt(). Color continues to use float only because high precision is not needed for 8-bit color math and to keep things simple. Everything seems to compile and work fine, but testing is requested, as this is the first time I've ever contributed to Godot.
484 lines
14 KiB
C#
484 lines
14 KiB
C#
using System;
|
|
|
|
// file: core/math/aabb.h
|
|
// commit: 7ad14e7a3e6f87ddc450f7e34621eb5200808451
|
|
// file: core/math/aabb.cpp
|
|
// commit: bd282ff43f23fe845f29a3e25c8efc01bd65ffb0
|
|
// file: core/variant_call.cpp
|
|
// commit: 5ad9be4c24e9d7dc5672fdc42cea896622fe5685
|
|
|
|
#if REAL_T_IS_DOUBLE
|
|
using real_t = System.Double;
|
|
#else
|
|
using real_t = System.Single;
|
|
#endif
|
|
|
|
namespace Godot
|
|
{
|
|
public struct AABB : IEquatable<AABB>
|
|
{
|
|
private Vector3 position;
|
|
private Vector3 size;
|
|
|
|
public Vector3 Position
|
|
{
|
|
get
|
|
{
|
|
return position;
|
|
}
|
|
}
|
|
|
|
public Vector3 Size
|
|
{
|
|
get
|
|
{
|
|
return size;
|
|
}
|
|
}
|
|
|
|
public Vector3 End
|
|
{
|
|
get
|
|
{
|
|
return position + size;
|
|
}
|
|
}
|
|
|
|
public bool Encloses(AABB with)
|
|
{
|
|
Vector3 src_min = position;
|
|
Vector3 src_max = position + size;
|
|
Vector3 dst_min = with.position;
|
|
Vector3 dst_max = with.position + with.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));
|
|
}
|
|
|
|
public AABB Expand(Vector3 to_point)
|
|
{
|
|
Vector3 begin = position;
|
|
Vector3 end = position + size;
|
|
|
|
if (to_point.x < begin.x)
|
|
begin.x = to_point.x;
|
|
if (to_point.y < begin.y)
|
|
begin.y = to_point.y;
|
|
if (to_point.z < begin.z)
|
|
begin.z = to_point.z;
|
|
|
|
if (to_point.x > end.x)
|
|
end.x = to_point.x;
|
|
if (to_point.y > end.y)
|
|
end.y = to_point.y;
|
|
if (to_point.z > end.z)
|
|
end.z = to_point.z;
|
|
|
|
return new AABB(begin, end - begin);
|
|
}
|
|
|
|
public real_t GetArea()
|
|
{
|
|
return size.x * size.y * size.z;
|
|
}
|
|
|
|
public Vector3 GetEndpoint(int idx)
|
|
{
|
|
switch (idx)
|
|
{
|
|
case 0:
|
|
return new Vector3(position.x, position.y, position.z);
|
|
case 1:
|
|
return new Vector3(position.x, position.y, position.z + size.z);
|
|
case 2:
|
|
return new Vector3(position.x, position.y + size.y, position.z);
|
|
case 3:
|
|
return new Vector3(position.x, position.y + size.y, position.z + size.z);
|
|
case 4:
|
|
return new Vector3(position.x + size.x, position.y, position.z);
|
|
case 5:
|
|
return new Vector3(position.x + size.x, position.y, position.z + size.z);
|
|
case 6:
|
|
return new Vector3(position.x + size.x, position.y + size.y, position.z);
|
|
case 7:
|
|
return new Vector3(position.x + size.x, position.y + size.y, position.z + size.z);
|
|
default:
|
|
throw new ArgumentOutOfRangeException(nameof(idx), String.Format("Index is {0}, but a value from 0 to 7 is expected.", idx));
|
|
}
|
|
}
|
|
|
|
public Vector3 GetLongestAxis()
|
|
{
|
|
Vector3 axis = new Vector3(1f, 0f, 0f);
|
|
real_t max_size = size.x;
|
|
|
|
if (size.y > max_size)
|
|
{
|
|
axis = new Vector3(0f, 1f, 0f);
|
|
max_size = size.y;
|
|
}
|
|
|
|
if (size.z > max_size)
|
|
{
|
|
axis = new Vector3(0f, 0f, 1f);
|
|
max_size = size.z;
|
|
}
|
|
|
|
return axis;
|
|
}
|
|
|
|
public Vector3.Axis GetLongestAxisIndex()
|
|
{
|
|
Vector3.Axis axis = Vector3.Axis.X;
|
|
real_t max_size = size.x;
|
|
|
|
if (size.y > max_size)
|
|
{
|
|
axis = Vector3.Axis.Y;
|
|
max_size = size.y;
|
|
}
|
|
|
|
if (size.z > max_size)
|
|
{
|
|
axis = Vector3.Axis.Z;
|
|
max_size = size.z;
|
|
}
|
|
|
|
return axis;
|
|
}
|
|
|
|
public real_t GetLongestAxisSize()
|
|
{
|
|
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;
|
|
}
|
|
|
|
public Vector3 GetShortestAxis()
|
|
{
|
|
Vector3 axis = new Vector3(1f, 0f, 0f);
|
|
real_t max_size = size.x;
|
|
|
|
if (size.y < max_size)
|
|
{
|
|
axis = new Vector3(0f, 1f, 0f);
|
|
max_size = size.y;
|
|
}
|
|
|
|
if (size.z < max_size)
|
|
{
|
|
axis = new Vector3(0f, 0f, 1f);
|
|
max_size = size.z;
|
|
}
|
|
|
|
return axis;
|
|
}
|
|
|
|
public Vector3.Axis GetShortestAxisIndex()
|
|
{
|
|
Vector3.Axis axis = Vector3.Axis.X;
|
|
real_t max_size = size.x;
|
|
|
|
if (size.y < max_size)
|
|
{
|
|
axis = Vector3.Axis.Y;
|
|
max_size = size.y;
|
|
}
|
|
|
|
if (size.z < max_size)
|
|
{
|
|
axis = Vector3.Axis.Z;
|
|
max_size = size.z;
|
|
}
|
|
|
|
return axis;
|
|
}
|
|
|
|
public real_t GetShortestAxisSize()
|
|
{
|
|
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;
|
|
}
|
|
|
|
public Vector3 GetSupport(Vector3 dir)
|
|
{
|
|
Vector3 half_extents = size * 0.5f;
|
|
Vector3 ofs = position + half_extents;
|
|
|
|
return ofs + new Vector3(
|
|
(dir.x > 0f) ? -half_extents.x : half_extents.x,
|
|
(dir.y > 0f) ? -half_extents.y : half_extents.y,
|
|
(dir.z > 0f) ? -half_extents.z : half_extents.z);
|
|
}
|
|
|
|
public AABB Grow(real_t by)
|
|
{
|
|
AABB res = this;
|
|
|
|
res.position.x -= by;
|
|
res.position.y -= by;
|
|
res.position.z -= by;
|
|
res.size.x += 2.0f * by;
|
|
res.size.y += 2.0f * by;
|
|
res.size.z += 2.0f * by;
|
|
|
|
return res;
|
|
}
|
|
|
|
public bool HasNoArea()
|
|
{
|
|
return size.x <= 0f || size.y <= 0f || size.z <= 0f;
|
|
}
|
|
|
|
public bool HasNoSurface()
|
|
{
|
|
return size.x <= 0f && size.y <= 0f && size.z <= 0f;
|
|
}
|
|
|
|
public bool HasPoint(Vector3 point)
|
|
{
|
|
if (point.x < position.x)
|
|
return false;
|
|
if (point.y < position.y)
|
|
return false;
|
|
if (point.z < position.z)
|
|
return false;
|
|
if (point.x > position.x + size.x)
|
|
return false;
|
|
if (point.y > position.y + size.y)
|
|
return false;
|
|
if (point.z > position.z + size.z)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
public AABB Intersection(AABB with)
|
|
{
|
|
Vector3 src_min = position;
|
|
Vector3 src_max = position + size;
|
|
Vector3 dst_min = with.position;
|
|
Vector3 dst_max = with.position + with.size;
|
|
|
|
Vector3 min, max;
|
|
|
|
if (src_min.x > dst_max.x || src_max.x < dst_min.x)
|
|
{
|
|
return new 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 new 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 new 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 new AABB(min, max - min);
|
|
}
|
|
|
|
public bool Intersects(AABB with)
|
|
{
|
|
if (position.x >= (with.position.x + with.size.x))
|
|
return false;
|
|
if ((position.x + size.x) <= with.position.x)
|
|
return false;
|
|
if (position.y >= (with.position.y + with.size.y))
|
|
return false;
|
|
if ((position.y + size.y) <= with.position.y)
|
|
return false;
|
|
if (position.z >= (with.position.z + with.size.z))
|
|
return false;
|
|
if ((position.z + size.z) <= with.position.z)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
public bool IntersectsPlane(Plane plane)
|
|
{
|
|
Vector3[] points =
|
|
{
|
|
new Vector3(position.x, position.y, position.z),
|
|
new Vector3(position.x, position.y, position.z + size.z),
|
|
new Vector3(position.x, position.y + size.y, position.z),
|
|
new Vector3(position.x, position.y + size.y, position.z + size.z),
|
|
new Vector3(position.x + size.x, position.y, position.z),
|
|
new Vector3(position.x + size.x, position.y, position.z + size.z),
|
|
new Vector3(position.x + size.x, position.y + size.y, position.z),
|
|
new 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 (plane.DistanceTo(points[i]) > 0)
|
|
over = true;
|
|
else
|
|
under = true;
|
|
}
|
|
|
|
return under && over;
|
|
}
|
|
|
|
public bool IntersectsSegment(Vector3 from, Vector3 to)
|
|
{
|
|
real_t min = 0f;
|
|
real_t max = 1f;
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
real_t seg_from = from[i];
|
|
real_t seg_to = to[i];
|
|
real_t box_begin = position[i];
|
|
real_t box_end = box_begin + size[i];
|
|
real_t cmin, cmax;
|
|
|
|
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 : 0f;
|
|
cmax = seg_to > box_end ? (box_end - seg_from) / length : 1f;
|
|
}
|
|
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 : 0f;
|
|
cmax = seg_to < box_begin ? (box_begin - seg_from) / length : 1f;
|
|
}
|
|
|
|
if (cmin > min)
|
|
{
|
|
min = cmin;
|
|
}
|
|
|
|
if (cmax < max)
|
|
max = cmax;
|
|
if (max < min)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public AABB Merge(AABB with)
|
|
{
|
|
Vector3 beg_1 = position;
|
|
Vector3 beg_2 = with.position;
|
|
Vector3 end_1 = new Vector3(size.x, size.y, size.z) + beg_1;
|
|
Vector3 end_2 = new Vector3(with.size.x, with.size.y, with.size.z) + beg_2;
|
|
|
|
Vector3 min = new Vector3(
|
|
(beg_1.x < beg_2.x) ? beg_1.x : beg_2.x,
|
|
(beg_1.y < beg_2.y) ? beg_1.y : beg_2.y,
|
|
(beg_1.z < beg_2.z) ? beg_1.z : beg_2.z
|
|
);
|
|
|
|
Vector3 max = new Vector3(
|
|
(end_1.x > end_2.x) ? end_1.x : end_2.x,
|
|
(end_1.y > end_2.y) ? end_1.y : end_2.y,
|
|
(end_1.z > end_2.z) ? end_1.z : end_2.z
|
|
);
|
|
|
|
return new AABB(min, max - min);
|
|
}
|
|
|
|
// Constructors
|
|
public AABB(Vector3 position, Vector3 size)
|
|
{
|
|
this.position = position;
|
|
this.size = size;
|
|
}
|
|
|
|
public static bool operator ==(AABB left, AABB right)
|
|
{
|
|
return left.Equals(right);
|
|
}
|
|
|
|
public static bool operator !=(AABB left, AABB right)
|
|
{
|
|
return !left.Equals(right);
|
|
}
|
|
|
|
public override bool Equals(object obj)
|
|
{
|
|
if (obj is AABB)
|
|
{
|
|
return Equals((AABB)obj);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public bool Equals(AABB other)
|
|
{
|
|
return position == other.position && size == other.size;
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return position.GetHashCode() ^ size.GetHashCode();
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return String.Format("{0} - {1}", new object[]
|
|
{
|
|
this.position.ToString(),
|
|
this.size.ToString()
|
|
});
|
|
}
|
|
|
|
public string ToString(string format)
|
|
{
|
|
return String.Format("{0} - {1}", new object[]
|
|
{
|
|
this.position.ToString(format),
|
|
this.size.ToString(format)
|
|
});
|
|
}
|
|
}
|
|
}
|