Portals - fix import of portal normal + small bug fixes
When converting portal meshes during import, indices were not being taken into account, which could lead to incorrect estimation of the portal direction. This PR now copes with either indexed or non-indexed portal meshes. Added a bug fix to cope with portals pointing almost directly straight up or down, which could cause problems with the lookat transform. Added the ability for named portals to link to short room names (in addition to postfix room names).
This commit is contained in:
parent
98e1b730c8
commit
116e2ce799
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue