Dynamic Rendering of Line Segments - Guidance Plz

This picture shows a trajectory of a ballistic object. The trajectory is a time history of the position of an object.

Here is the code used to render the trajectory path :


# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Function name : MakeTrajectoryNode
#
# Description:
#
#	Create a renderable trajectory scene node from a file based trajectory.
#
# Input(s):
#
#	traj - File based trajectory to build node for.
#	sCount - Number of samples to divide the trajectory into.
#	coordMgr - Coordinate system manager.
#   lineThickness - Optional line thickness (default is 1)
#
# Output(s):
#
#	A renderable scene node for the trajectory.

def MakeTrajectoryNode(traj,coordMgr,sCount,lineThickness=1):

	# Create a set of line segments
	ls = LineSegs()
	ls.setThickness(lineThickness)

	# Get the time basis of the trajectory (min/max sample time)
	timeBasis = traj.timeBasis()
	t0 = float(timeBasis[0])
	t1 = float(timeBasis[1])

	# Compute the time differential between rendered samples
	delT = (t1-t0)/float(sCount)

	# Sample the trajectory and render it
	t = t0
	i = 0
	while t<=t1

		# Get the trajectory state at Time=t
		s = traj.getState(t)

		# Extract the coordinates (simulation frame)
		x,y,z = s[1],s[2],s[3]

		# Transform coordinates to the Panda3D world frame
		xw,yw,zw = coordMgr.simToWorld(x,y,z)

		# Draw a line to the sample from the previous point
		if i==0:
			ls.moveTo(xw,yw,zw)
		else:
			ls.drawTo(xw,yw,zw)
		t = t + delT
		i = i+1

	# Create and return a node with the segments
	node = ls.create()
	return NodePath(node)

While this is nice, it is not quite what I need to do … I have a clock class that I can start/stop/pause that tracks the simulation time. I want to be able to read the time from a clock instance and dynamically update the rendering of the trajectory … that is … I want to render the trajectory as a set of line segments starting at the beginning and going up only to the position represented by the current clock. For example, at time t=45.3 seconds, I want to render only that portion of the trajectory indicated by the yellow line.

Clearly I should not use the above code to do this. I would have to create this node, add it to the scene graph, and delete the old node EVERY SINGLE FRAME. Being a noob to Panda3D I don’t quite know how to approach the problem of dynamically updating the rendering of this object.

Could anyone give me some guidance on how to approach this problem?

Thanks,
Paul

Actually, that’s (almost) exactly what I’d recommend doing. Every single frame. It’s not as bad as it appears; creating the node and adding it to the scene graph is actually quite fast.

You can save a bit of time by keeping your LineSegs object around from one frame to the next, and only adding new vertices to the end of the LineSegs object, rather than re-doing the path from the beginning each time. Of course, you’ll need to record the point at which you left off last frame so you can continue from there.

You’ll still need to remove the old node, and generate a new one with ls.create(), each frame.

David

I have also a same kind of problem than that was described on the first post of this topic: I need a two-dimensional line graph which has to be updateable.

What is the correct way to remove a geomnode which contains those linesegs from a scene graph - or - how I can do the thing that was described on the reply? I have tried detach/removeNodes… even removeAllGeoms but I cant get it to work… How it should be done?

Thanks in advance!

nodePath.detach() or nodePath.removeNode() will do the trick. If it’s not working for some reason, I can’t tell you why not unless you provide more specific information about what you’re doing! Are you sure you’re calling it on the NodePath that represents your geometry?

David

OK… I have this kind of code:

                global j
		j += 0.01
		
		ls = LineSegs()
		ls.reset()
		ls.setThickness(1)
		ls.setColor(0, 1, 0.000, 0.5)
		
		ls.moveTo(0, 0, 0)
		
		for i in range(5):

			
			ls.drawTo(0.2, 0, i*0.1+j)
			ls.moveTo(0, 0, (i+1)*0.1+j)
			
			i += 1
		
		
		node = ls.create(1)		
		
		render2d.attachNewNode(node)

It is supposed to draw five horizontal lines that it indeed does, but I would like to run it in loop so, that when j increases, that bunch of lines moves … somewhere. :wink:

But - the amount of lines also increase. Previous lines are not erased, instead of it another five lines are created. And that resulting mess is something I do not want. So, what should be done to avoid it and get only five lines that move around?

I have tried those detach and remove on “node”, but when it is a type of GeomNode, it is not possible to do those for it. What should I do, how can I get rid of those?

“node” is a GeomNode, not a NodePath. In order to call detach() or removeNode(), you need a NodePath, which remember is a handle to a node.

Fortunately, you have one in the above code–it’s returned from the last call, render2d.attachNewNode(). Just save the return value from that, and you can use that to remove your node later.

np = render2d.attachNewNode(node)
...
np.detach()

David