Calculate convex hulls for scene nodes and use it for collision testing

This commit is contained in:
Arjen Hiemstra 2015-04-24 17:14:04 +02:00
parent 952f7b68ec
commit b58a5456cc

View file

@ -9,6 +9,7 @@ from UM.Math.AxisAlignedBox import AxisAlignedBox
from UM.Application import Application from UM.Application import Application
from PlatformPhysicsOperation import PlatformPhysicsOperation from PlatformPhysicsOperation import PlatformPhysicsOperation
from ConvexHullJob import ConvexHullJob
import time import time
import threading import threading
@ -19,7 +20,6 @@ class PlatformPhysics:
self._controller = controller self._controller = controller
self._controller.getScene().sceneChanged.connect(self._onSceneChanged) self._controller.getScene().sceneChanged.connect(self._onSceneChanged)
self._build_volume = volume self._build_volume = volume
self._signal_source = None
self._change_timer = QTimer() self._change_timer = QTimer()
self._change_timer.setInterval(100) self._change_timer.setInterval(100)
@ -39,13 +39,47 @@ class PlatformPhysics:
if not bbox or not bbox.isValid(): if not bbox or not bbox.isValid():
continue continue
# Mark the node as outside the build volume if the bounding box test fails.
if self._build_volume.getBoundingBox().intersectsBox(bbox) != AxisAlignedBox.IntersectionResult.FullIntersection: if self._build_volume.getBoundingBox().intersectsBox(bbox) != AxisAlignedBox.IntersectionResult.FullIntersection:
node._outside_buildarea = True node._outside_buildarea = True
else: else:
node._outside_buildarea = False node._outside_buildarea = False
# Move the node upwards if the bottom is below the build platform.
move_vector = Vector()
if not Float.fuzzyCompare(bbox.bottom, 0.0): if not Float.fuzzyCompare(bbox.bottom, 0.0):
self._signal_source = node move_vector.setY(-bbox.bottom)
op = PlatformPhysicsOperation(node, Vector(0, -bbox.bottom, 0))
Application.getInstance().getOperationStack().push(op) # If there is no convex hull for the node, start calculating it and continue.
self._signal_source = None if not hasattr(node, '_convex_hull'):
if not hasattr(node, '_convex_hull_job'):
job = ConvexHullJob(node)
job.start()
node._convex_hull_job = job
else:
# Check for collisions between convex hulls
for other_node in BreadthFirstIterator(root):
# Ignore root, ourselves and anything that is not a normal SceneNode.
if other_node is root or type(other_node) is not SceneNode or other_node is node:
continue
# Ignore nodes that do not have the right properties set.
if not hasattr(other_node, '_convex_hull') or not other_node.getBoundingBox():
continue
# Check to see if the bounding boxes intersect. If not, we can ignore the node as there is no way the hull intersects.
if node.getBoundingBox().intersectsBox(other_node.getBoundingBox()) == AxisAlignedBox.IntersectionResult.NoIntersection:
continue
# Get the overlap distance for both convex hulls. If this returns None, there is no intersection.
overlap = node._convex_hull.intersectsPolygon(other_node._convex_hull)
if overlap is None:
continue
print(overlap)
move_vector.setX(-overlap[0])
move_vector.setZ(-overlap[1])
if move_vector != Vector():
op = PlatformPhysicsOperation(node, move_vector)
op.push()