| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- from panda3d.core 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 = ConfigVariableBool('show-rope', True, \
- "Set this to false to deactivate the display of ropes.")
-
- 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
- self.order = 0
- self.verts = []
- self.knots = None
-
- 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).
- verts may be a list of dictionaries instead of a list of
- tuples. In this case, each vertex dictionary may have any of
- the following elements:
- 'node' : the NodePath indicating the coordinate space
- 'point' : the 3-D point relative to the node; default (0, 0, 0)
- 'color' : the color of the vertex, default (1, 1, 1, 1)
- 'thickness' : the thickness at the vertex, default 1
- In order to enable the per-vertex color or thickness, you must
- call rope.ropeNode.setUseVertexColor(1) or
- rope.ropeNode.setUseVertexThickness(1).
- 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)
- defaultNodePath = None
- defaultPoint = (0, 0, 0)
- defaultColor = (1, 1, 1, 1)
- defaultThickness = 1
- useVertexColor = self.ropeNode.getUseVertexColor()
- useVertexThickness = self.ropeNode.getUseVertexThickness()
- vcd = self.ropeNode.getVertexColorDimension()
- vtd = self.ropeNode.getVertexThicknessDimension()
-
- for i in range(numVerts):
- v = self.verts[i]
- if isinstance(v, types.TupleType):
- nodePath, point = v
- color = defaultColor
- thickness = defaultThickness
- else:
- nodePath = v.get('node', defaultNodePath)
- point = v.get('point', defaultPoint)
- color = v.get('color', defaultColor)
- thickness = v.get('thickness', defaultThickness)
-
- 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 useVertexColor:
- self.curve.setExtendedVertex(i, vcd + 0, color[0])
- self.curve.setExtendedVertex(i, vcd + 1, color[1])
- self.curve.setExtendedVertex(i, vcd + 2, color[2])
- self.curve.setExtendedVertex(i, vcd + 3, color[3])
- if useVertexThickness:
- self.curve.setExtendedVertex(i, vtd, thickness)
- 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)
- startT = result.getStartT()
- sizeT = result.getEndT() - startT
- numPts = len
- ropePts = []
- for i in range(numPts):
- pt = Point3()
- result.evalPoint(sizeT * i / float(numPts - 1) + startT, pt)
- ropePts.append(pt)
- return ropePts
|