Merge pull request #52338 from lawnjelly/portals_fix_portal_import

Portals - fix import of portal normal + small bug fixes
This commit is contained in:
Rémi Verschelde 2021-09-14 10:21:44 +02:00 committed by GitHub
commit f85ad007c0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 17 deletions

View file

@ -360,6 +360,7 @@ bool Portal::create_from_mesh_instance(const MeshInstance *p_mi) {
Array arrays = rmesh->surface_get_arrays(0);
PoolVector<Vector3> vertices = arrays[VS::ARRAY_VERTEX];
PoolVector<int> indices = arrays[VS::ARRAY_INDEX];
// get the model space verts and find center
int num_source_points = vertices.size();
@ -391,9 +392,28 @@ bool Portal::create_from_mesh_instance(const MeshInstance *p_mi) {
}
}
ERR_FAIL_COND_V(pts_world.size() < 3, false);
// create the normal from 3 vertices .. either indexed, or use the first 3
Vector3 three_pts[3];
if (indices.size() >= 3) {
for (int n = 0; n < 3; n++) {
ERR_FAIL_COND_V(indices[n] >= num_source_points, false);
three_pts[n] = tr_source.xform(vertices[indices[n]]);
}
} else {
for (int n = 0; n < 3; n++) {
three_pts[n] = pts_world[n];
}
}
Vector3 normal = Plane(three_pts[0], three_pts[1], three_pts[2]).normal;
if (_portal_plane_convention) {
normal = -normal;
}
// get the verts sorted with winding, assume that the triangle initial winding
// tells us the normal and hence which way the world space portal should be facing
_sort_verts_clockwise(_portal_plane_convention, pts_world);
_sort_verts_clockwise(normal, pts_world);
// back calculate the plane from *all* the portal points, this will give us a nice average plane
// (in case of wonky portals where artwork isn't bang on)
@ -401,7 +421,14 @@ bool Portal::create_from_mesh_instance(const MeshInstance *p_mi) {
// change the portal transform to match our plane and the center of the portal
Transform tr_global;
tr_global.set_look_at(Vector3(0, 0, 0), _plane.normal, Vector3(0, 1, 0));
// prevent warnings when poly normal matches the up vector
Vector3 up(0, 1, 0);
if (Math::abs(_plane.normal.dot(up)) > 0.9) {
up = Vector3(1, 0, 0);
}
tr_global.set_look_at(Vector3(0, 0, 0), _plane.normal, up);
tr_global.origin = _pt_center_world;
// We can't directly set this global transform on the portal, because the parent node may already
@ -558,23 +585,12 @@ void Portal::_sanitize_points() {
_update_aabb();
}
void Portal::_sort_verts_clockwise(bool portal_plane_convention, Vector<Vector3> &r_verts) {
void Portal::_sort_verts_clockwise(const Vector3 &p_portal_normal, Vector<Vector3> &r_verts) {
// cannot sort less than 3 verts
if (r_verts.size() < 3) {
return;
}
// assume first 3 points determine the desired normal, if these first 3 points are garbage,
// the routine will not work.
Plane portal_plane;
if (portal_plane_convention) {
portal_plane = Plane(r_verts[0], r_verts[2], r_verts[1]);
} else {
portal_plane = Plane(r_verts[0], r_verts[1], r_verts[2]);
}
const Vector3 &portal_normal = portal_plane.normal;
// find centroid
int num_points = r_verts.size();
_pt_center_world = Vector3(0, 0, 0);
@ -590,7 +606,7 @@ void Portal::_sort_verts_clockwise(bool portal_plane_convention, Vector<Vector3>
Vector3 a = r_verts[n] - _pt_center_world;
a.normalize();
Plane p = Plane(r_verts[n], _pt_center_world, _pt_center_world + portal_normal);
Plane p = Plane(r_verts[n], _pt_center_world, _pt_center_world + p_portal_normal);
double smallest_angle = -1;
int smallest = -1;
@ -623,7 +639,7 @@ void Portal::_sort_verts_clockwise(bool portal_plane_convention, Vector<Vector3>
// the wrong way.
Plane plane = Plane(r_verts[0], r_verts[1], r_verts[2]);
if (portal_normal.dot(plane.normal) < 0.0f) {
if (p_portal_normal.dot(plane.normal) < 0.0) {
// reverse winding order of verts
r_verts.invert();
}

View file

@ -110,7 +110,7 @@ private:
void _sanitize_points();
void _update_aabb();
static Vector3 _vec2to3(const Vector2 &p_pt) { return Vector3(p_pt.x, p_pt.y, 0.0); }
void _sort_verts_clockwise(bool portal_plane_convention, Vector<Vector3> &r_verts);
void _sort_verts_clockwise(const Vector3 &p_portal_normal, Vector<Vector3> &r_verts);
Plane _plane_from_points_newell(const Vector<Vector3> &p_pts);
void resolve_links(const LocalVector<Room *, int32_t> &p_rooms, const RID &p_from_room_rid);
void _changed();

View file

@ -873,7 +873,14 @@ void RoomManager::_second_pass_portals(Spatial *p_roomlist, LocalVector<Portal *
String string_link_room = string_link_room_shortname + "-room";
if (string_link_room_shortname != "") {
// try the room name plus the postfix first, this will be the most common case during import
Room *linked_room = Object::cast_to<Room>(p_roomlist->find_node(string_link_room, true, false));
// try the short name as a last ditch attempt
if (!linked_room) {
linked_room = Object::cast_to<Room>(p_roomlist->find_node(string_link_room_shortname, true, false));
}
if (linked_room) {
NodePath path = portal->get_path_to(linked_room);
portal->set_linked_room_internal(path);