[Scummvm-git-logs] scummvm master -> 087e58ba48171a856544987ded99c5886ca8f048

neuromancer noreply at scummvm.org
Sat Nov 18 16:32:20 UTC 2023


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
1df2cfddbe FREESCAPE: improved shooted object detection and moved sweepAABB implementation to its own file
087e58ba48 NEWS: updated with Freescape recent changes


Commit: 1df2cfddbe1ce1cb803632e39f8765265590c0d3
    https://github.com/scummvm/scummvm/commit/1df2cfddbe1ce1cb803632e39f8765265590c0d3
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-11-18T17:32:14+01:00

Commit Message:
FREESCAPE: improved shooted object detection and moved sweepAABB implementation to its own file

Changed paths:
  A engines/freescape/sweepAABB.cpp
  A engines/freescape/sweepAABB.h
    engines/freescape/area.cpp
    engines/freescape/module.mk


diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index c31451defa9..abcb8b25d5c 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -27,6 +27,7 @@
 #include "freescape/freescape.h"
 #include "freescape/area.h"
 #include "freescape/objects/global.h"
+#include "freescape/sweepAABB.h"
 
 namespace Freescape {
 
@@ -248,14 +249,21 @@ void Area::drawGroup(Freescape::Renderer *gfx, Group* group, bool runAnimation)
 }
 
 Object *Area::shootRay(const Math::Ray &ray) {
-	float size = 16.0 * 8192.0; // TODO: check if this is max size
+	float distance = 16.0 * 8192.0; // TODO: check if this is max distance
+	float size = 16.0 * 8192.0; // TODO: check if this is the max size
+	Math::AABB boundingBox(ray.getOrigin(), ray.getOrigin());
 	Object *collided = nullptr;
 	for (auto &obj : _drawableObjects) {
-		float objSize = obj->getSize().length();
-		if (!obj->isDestroyed() && !obj->isInvisible() && obj->_boundingBox.isValid() && ray.intersectAABB(obj->_boundingBox) && size >= objSize) {
-			debugC(1, kFreescapeDebugMove, "shot obj id: %d", obj->getObjectID());
-			collided = obj;
-			size = objSize;
+		if (!obj->isDestroyed() && !obj->isInvisible()) {
+			GeometricObject *gobj = (GeometricObject *)obj;
+			Math::Vector3d collidedNormal;
+			float collidedDistance = sweepAABB(boundingBox, gobj->_boundingBox, 8192 * ray.getDirection(), collidedNormal);
+			debug("shot obj id: %d with distance %f", obj->getObjectID(), collidedDistance);
+			if (collidedDistance < distance || (collidedDistance == distance && gobj->getSize().length() < size)) {
+				collided = obj;
+				size = gobj->getSize().length();
+				distance = collidedDistance;
+			}
 		}
 	}
 	return collided;
@@ -274,78 +282,6 @@ ObjectArray Area::checkCollisions(const Math::AABB &boundingBox) {
 	return collided;
 }
 
-float lineToPlane(Math::Vector3d const &p, Math::Vector3d const &u,  Math::Vector3d const &v, Math::Vector3d const &n) {
-	float NdotU = n.dotProduct(u);
-	if (NdotU == 0)
-		return INFINITY;
-
-	return n.dotProduct(v - p) / NdotU;
-}
-
-bool between(float x, float a, float b) {
-	return x >= a && x <= b;
-}
-
-float sweepAABB(Math::AABB const &a, Math::AABB const &b, Math::Vector3d const &direction, Math::Vector3d &normal) {
-	Math::Vector3d m = b.getMin() - a.getMax();
-	Math::Vector3d mh = a.getSize() + b.getSize();
-
-	float h = 1.0;
-	float s = 0.0;
-	Math::Vector3d zero;
-
-	// X min
-	s = lineToPlane(zero, direction, m, Math::Vector3d(-1, 0, 0));
-	if (s >= 0 && direction.x() > 0 && s < h && between(s * direction.y(), m.y(), m.y()+mh.y()) && between(s * direction.z(), m.z(), m.z() + mh.z())) {
-		h = s;
-		normal = Math::Vector3d(-1, 0, 0);
-	}
-
-	// X max
-	m.x() = m.x() + mh.x();
-	s = lineToPlane(zero, direction, m, Math::Vector3d(1, 0, 0));
-	if (s >= 0 && direction.x() < 0 && s < h && between(s * direction.y(), m.y(), m.y() + mh.y()) && between(s * direction.z(), m.z(), m.z() + mh.z())) {
-		h = s;
-		normal = Math::Vector3d(1, 0, 0);
-	}
-
-	m.x() = m.x() - mh.x();
-	// Y min
-	s = lineToPlane(zero, direction, m, Math::Vector3d(0, -1, 0));
-	if (s >= 0 && direction.y() > 0 && s < h && between(s * direction.x(), m.x(), m.x() + mh.x()) && between(s * direction.z(), m.z(), m.z() + mh.z())) {
-		h = s;
-		normal = Math::Vector3d(0, -1, 0);
-	}
-
-	// Y max
-	m.y() = m.y() + mh.y();
-	s = lineToPlane(zero, direction, m, Math::Vector3d(0, 1, 0));
-	if (s >= 0 && direction.y() < 0 && s < h && between(s * direction.x(), m.x(), m.x() + mh.x()) && between(s * direction.z(), m.z(), m.z() + mh.z())) {
-		h = s;
-		normal = Math::Vector3d(0, 1, 0);
-	}
-
-	m.y() = m.y() - mh.y();
-
-	// Z min
-	s = lineToPlane(zero, direction, m, Math::Vector3d(0, 0, -1));
-	if (s >= 0 && direction.z() > 0 && s < h && between(s * direction.x(), m.x() , m.x() + mh.x()) && between(s * direction.y(), m.y(), m.y() + mh.y())) {
-		h = s;
-		normal = Math::Vector3d(0, 0, -1);
-	}
-
-	// Z max
-	m.z() = m.z() + mh.z();
-	s = lineToPlane(zero, direction, m, Math::Vector3d(0, 0, 1));
-	if (s >= 0 && direction.z() < 0 && s < h && between(s * direction.x(), m.x(), m.x() + mh.x()) && between(s * direction.y(), m.y(), m.y() + mh.y())) {
-		h = s;
-		normal = Math::Vector3d(0, 0, 1);
-	}
-
-	//debug("%f", h);
-	return h;
-}
-
 extern Math::AABB createPlayerAABB(Math::Vector3d const position, int playerHeight);
 
 Math::Vector3d Area::resolveCollisions(const Math::Vector3d &lastPosition_, const Math::Vector3d &newPosition_, int playerHeight) {
diff --git a/engines/freescape/module.mk b/engines/freescape/module.mk
index c1c7fa3bf49..d6fb3bb9e1e 100644
--- a/engines/freescape/module.mk
+++ b/engines/freescape/module.mk
@@ -35,6 +35,7 @@ MODULE_OBJS := \
 	objects/group.o \
 	objects/sensor.o \
 	scr.o \
+	sweepAABB.o \
 	sound.o \
 	ui.o
 
diff --git a/engines/freescape/sweepAABB.cpp b/engines/freescape/sweepAABB.cpp
new file mode 100644
index 00000000000..a28502d7ab7
--- /dev/null
+++ b/engines/freescape/sweepAABB.cpp
@@ -0,0 +1,102 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "freescape/freescape.h"
+
+namespace Freescape {
+
+/*
+This code is inspired by the Luis Eduard Reis implementation:
+https://luisreis.net/blog/aabb_collision_handling/
+*/
+
+float lineToPlane(Math::Vector3d const &p, Math::Vector3d const &u,  Math::Vector3d const &v, Math::Vector3d const &n) {
+	float NdotU = n.dotProduct(u);
+	if (NdotU == 0)
+		return INFINITY;
+
+	return n.dotProduct(v - p) / NdotU;
+}
+
+bool between(float x, float a, float b) {
+	return x >= a && x <= b;
+}
+
+float sweepAABB(Math::AABB const &a, Math::AABB const &b, Math::Vector3d const &direction, Math::Vector3d &normal) {
+	Math::Vector3d m = b.getMin() - a.getMax();
+	Math::Vector3d mh = a.getSize() + b.getSize();
+
+	float h = 1.0;
+	float s = 0.0;
+	Math::Vector3d zero;
+
+	// X min
+	s = lineToPlane(zero, direction, m, Math::Vector3d(-1, 0, 0));
+	if (s >= 0 && direction.x() > 0 && s < h && between(s * direction.y(), m.y(), m.y()+mh.y()) && between(s * direction.z(), m.z(), m.z() + mh.z())) {
+		h = s;
+		normal = Math::Vector3d(-1, 0, 0);
+	}
+
+	// X max
+	m.x() = m.x() + mh.x();
+	s = lineToPlane(zero, direction, m, Math::Vector3d(1, 0, 0));
+	if (s >= 0 && direction.x() < 0 && s < h && between(s * direction.y(), m.y(), m.y() + mh.y()) && between(s * direction.z(), m.z(), m.z() + mh.z())) {
+		h = s;
+		normal = Math::Vector3d(1, 0, 0);
+	}
+
+	// Y min
+	m.x() = m.x() - mh.x();
+	s = lineToPlane(zero, direction, m, Math::Vector3d(0, -1, 0));
+	if (s >= 0 && direction.y() > 0 && s < h && between(s * direction.x(), m.x(), m.x() + mh.x()) && between(s * direction.z(), m.z(), m.z() + mh.z())) {
+		h = s;
+		normal = Math::Vector3d(0, -1, 0);
+	}
+
+	// Y max
+	m.y() = m.y() + mh.y();
+	s = lineToPlane(zero, direction, m, Math::Vector3d(0, 1, 0));
+	if (s >= 0 && direction.y() < 0 && s < h && between(s * direction.x(), m.x(), m.x() + mh.x()) && between(s * direction.z(), m.z(), m.z() + mh.z())) {
+		h = s;
+		normal = Math::Vector3d(0, 1, 0);
+	}
+
+
+	// Z min
+	m.y() = m.y() - mh.y();
+	s = lineToPlane(zero, direction, m, Math::Vector3d(0, 0, -1));
+	if (s >= 0 && direction.z() > 0 && s < h && between(s * direction.x(), m.x() , m.x() + mh.x()) && between(s * direction.y(), m.y(), m.y() + mh.y())) {
+		h = s;
+		normal = Math::Vector3d(0, 0, -1);
+	}
+
+	// Z max
+	m.z() = m.z() + mh.z();
+	s = lineToPlane(zero, direction, m, Math::Vector3d(0, 0, 1));
+	if (s >= 0 && direction.z() < 0 && s < h && between(s * direction.x(), m.x(), m.x() + mh.x()) && between(s * direction.y(), m.y(), m.y() + mh.y())) {
+		h = s;
+		normal = Math::Vector3d(0, 0, 1);
+	}
+
+	return h;
+}
+
+}
\ No newline at end of file
diff --git a/engines/freescape/sweepAABB.h b/engines/freescape/sweepAABB.h
new file mode 100644
index 00000000000..71110740b6d
--- /dev/null
+++ b/engines/freescape/sweepAABB.h
@@ -0,0 +1,33 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef FREESCAPE_SWEEPAABB_H
+#define FREESCAPE_SWEEPAABB_H
+
+namespace Freescape {
+
+extern float sweepAABB(Math::AABB const &a, Math::AABB const &b, Math::Vector3d const &direction, Math::Vector3d &normal);
+
+}
+
+// End of namespace Freescape
+
+#endif // FREESCAPE_SWEEPAABB_H
\ No newline at end of file


Commit: 087e58ba48171a856544987ded99c5886ca8f048
    https://github.com/scummvm/scummvm/commit/087e58ba48171a856544987ded99c5886ca8f048
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-11-18T17:32:14+01:00

Commit Message:
NEWS: updated with Freescape recent changes

Changed paths:
    NEWS.md


diff --git a/NEWS.md b/NEWS.md
index bffb4a51042..a68979aa188 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -40,6 +40,9 @@ For a more comprehensive changelog of the latest experimental code, see:
  Dragons:
    - Implemented localizations for the copyright screen and main menu.
 
+ Freescape:
+   - Improved collision and projectile detection using sweepAABB
+
  GrimE:
    - Added support for Chinese Grim Fandango.
    - Added support for Russian Grim Fandango translations from Fargus,




More information about the Scummvm-git-logs mailing list