This commit is contained in:
Jaime van Kessel 2015-04-24 17:19:51 +02:00
commit d81a2e7a15
4 changed files with 144 additions and 6 deletions

View File

@ -28,7 +28,7 @@ class BuildVolume(SceneNode):
self._disallowed_areas = [] self._disallowed_areas = []
self._disallowed_area_mesh = None self._disallowed_area_mesh = None
self._calculate_aabb = False self.setCalculateBoundingBox(False)
def setWidth(self, width): def setWidth(self, width):
self._width = width self._width = width

32
ConvexHullJob.py Normal file
View File

@ -0,0 +1,32 @@
from UM.Job import Job
from UM.Application import Application
from UM.Math.Polygon import Polygon
import numpy
from ConvexHullNode import ConvexHullNode
class ConvexHullJob(Job):
def __init__(self, node):
super().__init__()
self._node = node
def run(self):
if not self._node or not self._node.getMeshData():
return
mesh = self._node.getMeshData()
vertexData = mesh.getTransformed(self._node.getWorldTransformation()).getVertices()
hull = Polygon(numpy.rint(vertexData[:, [0, 2]]).astype(int))
# First, calculate the normal convex hull around the points
hull = hull.getConvexHull()
# Then, do a Minkowski hull with a simple 1x1 quad to outset and round the normal convex hull.
hull = hull.getMinkowskiHull(Polygon(numpy.array([[-1, -1], [-1, 1], [1, 1], [1, -1]], numpy.float32)))
hull_node = ConvexHullNode(self._node, hull, Application.getInstance().getController().getScene().getRoot())
self._node._convex_hull = hull
delattr(self._node, "_convex_hull_job")

72
ConvexHullNode.py Normal file
View File

@ -0,0 +1,72 @@
from UM.Scene.SceneNode import SceneNode
from UM.Resources import Resources
from UM.Math.Color import Color
from UM.Math.Vector import Vector
from UM.Mesh.MeshData import MeshData
import numpy
class ConvexHullNode(SceneNode):
def __init__(self, node, hull, parent = None):
super().__init__(parent)
self.setCalculateBoundingBox(False)
self._material = None
self._original_parent = parent
self._inherit_orientation = False
self._inherit_scale = False
self._node = node
self._node.transformationChanged.connect(self._onNodePositionChanged)
self._node.parentChanged.connect(self._onNodeParentChanged)
#self._onNodePositionChanged(self._node)
self._hull = hull
hull_points = self._hull.getPoints()
center = (hull_points.min(0) + hull_points.max(0)) / 2.0
mesh = MeshData()
mesh.addVertex(center[0], 0.1, center[1])
for point in hull_points:
mesh.addVertex(point[0], 0.1, point[1])
indices = []
for i in range(len(hull_points) - 1):
indices.append([0, i + 1, i + 2])
indices.append([0, mesh.getVertexCount() - 1, 1])
mesh.addIndices(numpy.array(indices, numpy.int32))
self.setMeshData(mesh)
def render(self, renderer):
if not self._material:
self._material = renderer.createMaterial(Resources.getPath(Resources.ShadersLocation, 'basic.vert'), Resources.getPath(Resources.ShadersLocation, 'color.frag'))
self._material.setUniformValue('u_color', Color(35, 35, 35, 128))
renderer.queueNode(self, material = self._material, transparent = True)
return True
def _onNodePositionChanged(self, node):
#self.setPosition(node.getWorldPosition())
if hasattr(node, "_convex_hull"):
delattr(node, "_convex_hull")
self.setParent(None)
#self._node.transformationChanged.disconnect(self._onNodePositionChanged)
#self._node.parentChanged.disconnect(self._onNodeParentChanged)
def _onNodeParentChanged(self, node):
if node.getParent():
self.setParent(self._original_parent)
else:
self.setParent(None)

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()