[Solved] Create curve as specified by movement of camera

Hey all,

I’m attempting to create a program that allows you to sketch a curve from the first, rather than third, person perspective. I chose Panda3D because it looked simple yet powerful but I seem to have hit a snag.

I’ve coded movement for the camera whose path will specify the curve but cannot seem to be able to implement the curve sketching itself. I’m coding it in python and I want is a method that I can call in each of the movement tasks for the camera that will add a vertex to the line based on the camera’s location.

This seems to be a perfect place for splines and I found “PieceWise curve” in the API which looks promising but I can’t, for the life of me, figure out from the documentation how to use it. Further research turned up the Rope class but when trying to import it (using the specified call at the top of it’s API page) it says that “base” is not defined on line 13. I’ve looked through the forums for curve sketching and the like but everything I found is either too vague or dealing with getting curves to look good rather than to appear at all.

I’d appreciate any help I can get, even if it’s just a nudge in the right direction.

Thanks!

it aint the highest performance approach. but it might help you. not entirely sure tho.
[Motion path & line classes)

That’s absolutely perfect - the curves should be fairly short so this is great. Thanks!

Hey,

Sorry to bother again. I’ve written my application with ThomasEgi’s method built in (thanks again!) but it doesn’t tend not to work very well with over a couple hundred points to be drawn.

All I now need is a faster algoritm or data structure for rending curves given a list of vertices. Is this a solved problem in Panda3D or am I expected to code something like this for myself? I think that the Piecewise curve data structure looks about right but I cannot for the life of me figure out how it works.

You can try the CurveFitter class, which sort of does what you’re asking for. Don’t be distracted by PiecewiseCurve, that’s just part of the implementation of a generic curve class, and has nothing to do with constructing a curve that fits a set of points.

David

That looks pretty perfect. How do you render curves created with this though? Here’s the jist of what I’ve coded so far:

curve = CurveFitter() 

def add_vertex(pos, hpr):
    curve.addXyzHpr(len(points),pos, hpr)

def draw_curve():
    curve.computeTangents(1) # want the scale to remain intact
    curve_to_draw = curve.makeNurbs()
    # Code to actually render the curve!
    # ???

Sorry, I’m fairly good with python but the Panda3D Api has me a bit confused.

Yeah, the problem with CurveFitter is that it is written with the older NurbsCurve interface, whereas the RopeNode is written with the newer NurbsCurveEvaluator interface.

You see, in Panda we currently have two competing curve API’s. We are in the (very slow) process of migrating from the older interface to the newer one. There unfortunately aren’t any systems remaining to render curves in the old curve API’s, unless you roll your own.

In order to use the NurbsCurve that is produced by the CurveFitter, you might find it easiest to convert it wholesale into a NurbsCurveEvaluator, by iterating through the knots and CV’s, and creating a new NCE object with those same knots and CV’s. Then you can create a RopeNode to render it.

David

Is it possible to use NCE directly by just adding the points and rendering it? I might be misreading it, but it seems like a bit of a waste to dump all my data into CurveFitter just to copy it across when the both create NURBS curves. I’ve tried doing this but I seem to be missing something - nothing seems to render.

		# Setup curves
		global curve, rope, points
                points = []
		curve = NurbsCurveEvaluator()
		rope_node = RopeNode('rope')
		rope_node.setCurve(curve)
		rope_node.setRenderMode(RopeNode.RMThread)
		ropeNP = render.attachNewNode(rope) # What I'm assuming I'm doing wrong

...

	def add_point(self, pos):
		global points, curve, rope
		print len(points)
		points.append(pos)
		curve.reset(len(points)) # inefficient, TODO
		for i in xrange(len(points)):
			curve.setVertex(i, points[i])

What this should be doing is drawing a nice neat curve with all the point in “points” in it adding points every time “add_point” is called but instead is producing nothing. I’m sorry to be a bother but I simply don’t seem to understand.

That looks generally right. You can also examine the code in Rope.py for a working example of its use; Rope.py is intended to provide an easier interface to the low-level RopeNode class.

Here’s some sample code that demonstrates using Rope successfully:

import direct.directbase.DirectStart
from direct.showutil.Rope import Rope

r = Rope()
r.setup(4, [(None, (-10, 0, 0)),
            (None, (0, 0, 15)),
            (None, (6, 0, -12)),
            (None, (10, 0, 0))])
r.setPos(0, 30, 0)
r.reparentTo(render)
r.ropeNode.setNumSubdiv(30)

run()

Note, though, that this approach will not pass directly through any of your points, except the first point and the last point. Instead, it will pass kind of close to them. This is the nature of NURBS curves. Also, you don’t want to have too many points if you want a smooth curve. If this is acceptable to your design requirements, then this is a perfectly reasonable solution, and you don’t need CurveFitter.

David

Thanks! That does the trick.