Skip to content

Commit

Permalink
Add OccluderShapePolygon
Browse files Browse the repository at this point in the history
Add OccluderShapePolygon, glue to Occluder and gizmos etc.
  • Loading branch information
lawnjelly committed Feb 1, 2022
1 parent b5eef64 commit 8ea20f5
Show file tree
Hide file tree
Showing 32 changed files with 2,056 additions and 75 deletions.
7 changes: 6 additions & 1 deletion core/local_vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

template <class T, class U = uint32_t, bool force_trivial = false>
class LocalVector {
private:
protected:
U count = 0;
U capacity = 0;
T *data = nullptr;
Expand Down Expand Up @@ -255,4 +255,9 @@ class LocalVector {
}
};

// Integer default version
template <class T, class I = int32_t, bool force_trivial = false>
class LocalVectori : public LocalVector<T, I, force_trivial> {
};

#endif // LOCAL_VECTOR_H
34 changes: 34 additions & 0 deletions core/math/geometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include "geometry.h"

#include "core/local_vector.h"
#include "core/print_string.h"

#include "thirdparty/misc/clipper.hpp"
Expand All @@ -53,6 +54,17 @@ bool Geometry::is_point_in_polygon(const Vector2 &p_point, const Vector<Vector2>
}
*/

void Geometry::OccluderMeshData::clear() {
faces.clear();
vertices.clear();
}

void Geometry::MeshData::clear() {
faces.clear();
edges.clear();
vertices.clear();
}

void Geometry::MeshData::optimize_vertices() {
Map<int, int> vtx_remap;

Expand Down Expand Up @@ -1363,6 +1375,28 @@ Vector<Geometry::PackRectsResult> Geometry::partial_pack_rects(const Vector<Vect
return ret;
}

// Expects polygon as a triangle fan
real_t Geometry::find_polygon_area(const Vector3 *p_verts, int p_num_verts) {
if (!p_verts || (p_num_verts < 3)) {
return 0.0;
}

Face3 f;
f.vertex[0] = p_verts[0];
f.vertex[1] = p_verts[1];
f.vertex[2] = p_verts[1];

real_t area = 0.0;

for (int n = 2; n < p_num_verts; n++) {
f.vertex[1] = f.vertex[2];
f.vertex[2] = p_verts[n];
area += Math::sqrt(f.get_twice_area_squared());
}

return area * 0.5;
}

// adapted from:
// https://stackoverflow.com/questions/6989100/sort-points-in-clockwise-order
void Geometry::sort_polygon_winding(Vector<Vector2> &r_verts, bool p_clockwise) {
Expand Down
29 changes: 27 additions & 2 deletions core/math/geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -555,11 +555,17 @@ class Geometry {
double dot11 = v1.dot(v1);
double dot12 = v1.dot(v2);

// Check for divide by zero
double denom = dot00 * dot11 - dot01 * dot01;
if (denom == 0.0) {
return Vector3(0.0, 0.0, 0.0);
}

// Compute barycentric coordinates
double invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01);
double invDenom = 1.0 / denom;
double b2 = (dot11 * dot02 - dot01 * dot12) * invDenom;
double b1 = (dot00 * dot12 - dot01 * dot02) * invDenom;
double b0 = 1.0f - b2 - b1;
double b0 = 1.0 - b2 - b1;
return Vector3(b0, b1, b2);
}

Expand Down Expand Up @@ -978,6 +984,24 @@ class Geometry {
Vector<Vector3> vertices;

void optimize_vertices();
void clear();
};

// Occluder Meshes contain convex faces which may contain 0 to many convex holes.
// (holes are analogous to portals)
struct OccluderMeshData {
struct Hole {
LocalVectori<uint32_t> indices;
};
struct Face {
Plane plane;
bool two_way = false;
LocalVectori<uint32_t> indices;
LocalVectori<Hole> holes;
};
LocalVectori<Face> faces;
LocalVectori<Vector3> vertices;
void clear();
};

_FORCE_INLINE_ static int get_uv84_normal_bit(const Vector3 &p_vector) {
Expand Down Expand Up @@ -1070,6 +1094,7 @@ class Geometry {
static PoolVector<Plane> build_cylinder_planes(real_t p_radius, real_t p_height, int p_sides, Vector3::Axis p_axis = Vector3::AXIS_Z);
static PoolVector<Plane> build_capsule_planes(real_t p_radius, real_t p_height, int p_sides, int p_lats, Vector3::Axis p_axis = Vector3::AXIS_Z);
static void sort_polygon_winding(Vector<Vector2> &r_verts, bool p_clockwise = true);
static real_t find_polygon_area(const Vector3 *p_verts, int p_num_verts);

static void make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_result, Size2i &r_size);

Expand Down
1 change: 1 addition & 0 deletions core/math/math_funcs.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ class Math {
static _ALWAYS_INLINE_ double abs(double g) { return absd(g); }
static _ALWAYS_INLINE_ float abs(float g) { return absf(g); }
static _ALWAYS_INLINE_ int abs(int g) { return g > 0 ? g : -g; }
static _ALWAYS_INLINE_ int64_t abs(int64_t g) { return g > 0 ? g : -g; }

static _ALWAYS_INLINE_ double fposmod(double p_x, double p_y) {
double value = Math::fmod(p_x, p_y);
Expand Down
45 changes: 45 additions & 0 deletions doc/classes/OccluderShapePolygon.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="OccluderShapePolygon" inherits="OccluderShape" version="3.5">
<brief_description>
Polygon occlusion primitive for use with the [Occluder] node.
</brief_description>
<description>
[OccluderShape]s are resources used by [Occluder] nodes, allowing geometric occlusion culling.
The polygon must be a convex polygon. The polygon points can be created and deleted either in the Editor inspector or by calling [code]set_polygon_points[/code]. The points of the edges can be set by dragging the handles in the Editor viewport.
Additionally each polygon occluder can optionally support a single hole. If you add at least three points in the Editor inspector to the hole, you can drag the edge points of the hole in the Editor viewport.
In general, the lower the number of edges in polygons and holes, the faster the system will operate at runtime, so in most cases you will want to use 4 points for each.
</description>
<tutorials>
</tutorials>
<methods>
<method name="set_hole_point">
<return type="void" />
<argument index="0" name="index" type="int" />
<argument index="1" name="position" type="Vector2" />
<description>
Sets an individual hole point position.
</description>
</method>
<method name="set_polygon_point">
<return type="void" />
<argument index="0" name="index" type="int" />
<argument index="1" name="position" type="Vector2" />
<description>
Sets an individual polygon point position.
</description>
</method>
</methods>
<members>
<member name="hole_points" type="PoolVector2Array" setter="set_hole_points" getter="get_hole_points" default="PoolVector2Array( )">
Allows changing the hole geometry from code.
</member>
<member name="polygon_points" type="PoolVector2Array" setter="set_polygon_points" getter="get_polygon_points" default="PoolVector2Array( 1, -1, 1, 1, -1, 1, -1, -1 )">
Allows changing the polygon geometry from code.
</member>
<member name="two_way" type="bool" setter="set_two_way" getter="is_two_way" default="true">
Specifies whether the occluder should operate one way only, or from both sides.
</member>
</members>
<constants>
</constants>
</class>
5 changes: 5 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1330,6 +1330,11 @@
<member name="rendering/misc/mesh_storage/split_stream" type="bool" setter="" getter="" default="false">
On import, mesh vertex data will be split into two streams within a single vertex buffer, one for position data and the other for interleaved attributes data. Recommended to be enabled if targeting mobile devices. Requires manual reimport of meshes after toggling.
</member>
<member name="rendering/misc/occlusion_culling/max_active_polygons" type="int" setter="" getter="" default="8">
Determines the maximum number of polygon occluders that will be used at any one time.
Although you can have many occluders in a scene, each frame the system will choose from these the most relevant based on a screen space metric, in order to give the best overall performance.
A greater number of polygons can potentially cull more objects, however the cost of culling calculations scales with the number of occluders.
</member>
<member name="rendering/misc/occlusion_culling/max_active_spheres" type="int" setter="" getter="" default="8">
Determines the maximum number of sphere occluders that will be used at any one time.
Although you can have many occluders in a scene, each frame the system will choose from these the most relevant based on a screen space metric, in order to give the best overall performance.
Expand Down
4 changes: 4 additions & 0 deletions editor/plugins/spatial_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3674,7 +3674,11 @@ AABB SpatialEditorViewport::_calculate_spatial_bounds(const Spatial *p_parent, b
}

if (bounds.size == Vector3() && p_parent->get_class_name() != StringName("Spatial")) {
#ifdef TOOLS_ENABLED
bounds = p_parent->get_fallback_gizmo_aabb();
#else
bounds = AABB(Vector3(-0.2, -0.2, -0.2), Vector3(0.4, 0.4, 0.4));
#endif
}

if (!p_exclude_toplevel_transform) {
Expand Down
Loading

0 comments on commit 8ea20f5

Please sign in to comment.