I do not know who created the demo to mention the pseudonym. Found an example on the site in the zone RU.
from panda3d.core import *
loadPrcFileData("", "egg-load-old-curves 0")
class NURBSMopath():
def __init__(self, curve, name = None, rotate = False, useEvalTangent = False):
if (name == None):
name = 'nurbsmopath'
self.name = name
self.duration = 1.0
self.node = None
self.loop = False
self.cnpRef = None
self.rope = None
self.evaluator = None
self.nurbs = None
self.tDisplace = 0
self.tCurrent = 0
self.loopNum = 0
self.rotate = rotate
self.useEvalTangent = useEvalTangent
if curve:
if isinstance(curve, str):
self.loadCurves(curve)
elif isinstance(curve, NodePath):
self.cnpRef = curve
self.__extractCurves(curve)
elif isinctance(curve, RopeNode):
self.setCurve(curve)
def loadCurves(self, fname):
if self.cnpRef:
self.cnpRef.detachNode()
self.cnpRef = loader.loadModel(fname, noCache=True)
if self.cnpRef:
if not self.__extractCurves(self.cnpRef):
print ('NURBSMopath: can\'t find any curves in file: %s' % fname)
else:
print ('NURBSMopath: no data in file: %s' % fname)
def setCurve(self, curve):
self.rope = NodePath(curve)
self.evaluator = curve.getCurve()
self.nurbs = self.evaluator.evaluate()
def __extractCurves(self, np):
node = np.node()
if isinstance(node, RopeNode):
self.setCurve(node)
return True
else:
for ch in np.getChildren():
if self.__extractCurves(ch):
return True
def __playTask(self, task):
start, stop = self.getRange()
delta = stop - start
scaled_duration = delta * self.duration
self.loopNum = int(task.time / self.duration)
if (not self.loop) and (self.loopNum > 0):
self.finish()
messenger.send(self.name + '-done')
self.node = None
return task.done
t = self.nurbs.getStartT() + (task.time \
- (self.loopNum * self.duration)) * delta / self.duration \
+ self.tDisplace
self.tCurrent = t
if self.useEvalTangent:
self.goTo_with_default_rotation(self.node, t)
else:
self.goTo(self.node, t)
return task.cont
def getRange(self):
if self.nurbs:
return (self.nurbs.getStartT(), self.nurbs.getEndT())
else:
return (0, 0)
def getMaxT(self):
start, stop = self.getRange()
return stop
def goTo_with_default_rotation(self, node, t):
if node:
p = Point3()
v = Vec3()
self.nurbs.evalPoint(t, p)
self.node.setPos(self.rope, p)
if self.rotate:
self.nurbs.evalTangent(t, v)
v = render.getRelativeVector(self.rope, v)
node.lookAt(node.getPos() + v)
def goTo(self, node, t):
if node:
start, stop = self.getRange()
delta = stop - start
p = Point3()
p0 = Point3()
self.nurbs.evalPoint(t, p)
if self.rotate:
self.nurbs.evalPoint(t + delta*0.001, p0)
if p == p0:
self.nurbs.evalPoint(t - delta*0.001, p0)
v = Vec3(p - p0)
else:
v = Vec3(p0 - p)
#v.normalize()
node.lookAt(node.getPos() + v)
node.setPos(self.rope, p)
def play(self, node, duration = 1.0, resume = False, loop = False):
if self.nurbs:
if not resume:
self.lastTime = 0
self.node = node
self.duration = duration
self.loop = loop
self.stop()
t = taskMgr.add(self.__playTask, self.name + '-play')
else:
print ('NURBSMopath: has no curve.')
def stop(self):
self.tDisplace = self.tCurrent
taskMgr.remove(self.name + '-play')
def finish(self):
start,stop = self.getRange()
self.tDisplace = 0
self.tCurrent = 0
self.lastTime = 0
self.loopNum = 0
taskMgr.remove(self.name + '-play')
if __name__ == "__main__":
from direct.directbase import DirectStart
from direct.interval.MopathInterval import *
from direct.interval.IntervalGlobal import *
test_model = loader.loadModel('zup-axis')
test_model.reparentTo(render)
test_model.setScale(0.2)
nmps = []
for i in range(2):
nmp = NURBSMopath('./nurbs')
nmp.rope.reparentTo(render)
nmp.rope.setH(180 * i)
nmp.rope.setScale(2)
nmps.append(nmp)
seq = Sequence()
for nmp in nmps:
seq.append(MopathInterval(nmp, test_model, name = "Name", duration = 3))
seq.loop()
base.disableMouse()
base.camera.setPos(15,15,15)
base.camera.lookAt(0,0,0)
base.run()
Short version:
from panda3d.core import *
from direct.directbase import DirectStart
from direct.directutil.Mopath import Mopath
from direct.interval.MopathInterval import *
myModel = loader.loadModel('nurbs')
curveNode = myModel.find("**/+NurbsCurve")
myMopath = Mopath()
myMopath.loadNodePath(curveNode)
myMopath.fFaceForward = True
myCube = loader.loadModel("yup-axis")
myCube.setScale(0.1)
myCube.reparentTo(render)
myInterval = MopathInterval(myMopath, myCube, duration=10 ,name = "Name")
myInterval.start()
base.disableMouse()
base.camera.setPos(15,15,15)
base.camera.lookAt(0,0,0)
base.run()
Resources and source .blend for demonstration:
nurbs.blend (404.8 KB)
nurbs.egg (848 Bytes)