diff --git a/direct/src/showutil/Rope.py b/direct/src/showutil/Rope.py new file mode 100644 index 0000000000..2576590a32 --- /dev/null +++ b/direct/src/showutil/Rope.py @@ -0,0 +1,97 @@ +from PandaModules import * +import types + +class Rope(NodePath): + """ + This class defines a Nurbs curve whose control vertices are + defined based on points relative to one or more nodes in space, so + that the "rope" will animate as the nodes move around. It uses + the C++ RopeNode class to achieve fancy rendering effects like + thick lines built from triangle strips. + """ + + showRope = base.config.GetBool('show-rope', 1) + + def __init__(self, name = 'Rope'): + self.ropeNode = RopeNode(name) + self.curve = NurbsCurveEvaluator() + self.ropeNode.setCurve(self.curve) + NodePath.__init__(self, self.ropeNode) + self.name = name + + def setup(self, order, verts, knots = None): + # This must be called to define the shape of the curve + # initially, and may be called again as needed to adjust the + # curve's properties. + + # order must be either 1, 2, 3, or 4, and is one more than the + # degree of the curve; most NURBS curves are order 4. + + # verts is a list of (NodePath, point) tuples, defining the + # control vertices of the curve. For each control vertex, the + # NodePath may refer to an arbitrary node in the scene graph, + # indicating the point should be interpreted in the coordinate + # space of that node (and it will automatically move when the + # node is moved), or it may be the empty NodePath or None to + # indicate the point should be interpreted in the coordinate + # space of the Rope itself. Each point value may be either a + # 3-tuple or a 4-tuple (or a VBase3 or VBase4). If it is a + # 3-component vector, it represents a 3-d point in space; a + # 4-component vector represents a point in 4-d homogeneous + # space; that is to say, a 3-d point and an additional weight + # factor (which should have been multiplied into the x y z + # components). + + # knots is optional. If specified, it should be a list of + # floats, and should be of length len(verts) + order. If it + # is omitted, a default knot string is generated that consists + # of the first (order - 1) and last (order - 1) values the + # same, and the intermediate values incrementing by 1. + + self.order = order + self.verts = verts + self.knots = knots + + self.recompute() + + def recompute(self): + # Recomputes the curve after its properties have changed. + # Normally it is not necessary for the user to call this + # directly. + + if not self.showRope: + return + numVerts = len(self.verts) + self.curve.reset(numVerts) + self.curve.setOrder(self.order) + for i in range(numVerts): + nodePath, point = self.verts[i] + if isinstance(point, types.TupleType): + if (len(point) >= 4): + self.curve.setVertex(i, VBase4(point[0], point[1], point[2], point[3])) + else: + self.curve.setVertex(i, VBase3(point[0], point[1], point[2])) + else: + self.curve.setVertex(i, point) + if nodePath: + self.curve.setVertexSpace(i, nodePath) + + if self.knots != None: + for i in range(len(self.knots)): + self.curve.setKnot(i, self.knots[i]) + + self.ropeNode.resetBound(self) + + def getPoints(self, len): + # Returns a list of len points, evenly distributed in + # parametric space on the rope, in the coordinate space of the + # Rope itself. + + result = self.curve.evaluate(self) + numPts = len + ropePts = [] + for i in range(numPts): + pt = Point3() + result.evalPoint(i / float(numPts - 1), pt) + ropePts.append(pt) + return ropePts