Can a node have two parents?

Return to Scripting Issues

Can a node have two parents?

Postby Thaumaturge » Thu Oct 12, 2017 3:08 pm

Excluding instancing, does Panda3D have a means of parenting a node to two parents?

Let me explain: I'm using Panda3D's portal-culling mechanism, and it seems to work well. However, I'm uncertain of what to do about objects that straddle the boundaries of cells. I've found little information in my searches thus far (although I do fear that searching is not my strong suit). However, one answer that's come up a few times is to simply consider the object to be in both cells. Since Panda's cells are node hierarchies, this would seem to suggest having an object parented to the root-nodes of multiple cells.

So, is this feasible? If not, is there another approach that I might take?

I currently have fixed elements (like doors) simply not take part in portal-culling, but that seems potentially inefficient, especially once I move on to larger levels. As to mobile objects, the result may vary: Tall, thin objects (such as humans) might not be serious issues, as they seems likely to cross fairly quickly. Broader objects (such as pushable tables) could easily end up stopped partway through a doorway, and thus seem to blink out of existence if viewed from the wrong position and angle.
MWAHAHAHAHA!!!

I have a website now! It holds information and a dev-blog for my nascent video-game, A Door to the Mists.
User avatar
Thaumaturge
 
Posts: 1592
Joined: Sat Jun 07, 2008 6:34 pm
Location: Cape Town, South Africa

Re: Can a node have two parents?

Postby rdb » Tue Oct 17, 2017 4:14 am

Yes, a node can have multiple parents. I think using node().addChild(...) will not remove the node from its previous parent, but check the list of parents to be sure.

Of course, this results in the node being visited more than once during rendering, if both cells are being rendered, causing it to be rendered twice. This is how instancing works.

It also means there are two possible NodePaths to the node, which will give different properties depending on the properties assigned to the parent.
rdb
 
Posts: 11166
Joined: Mon Dec 04, 2006 5:58 am
Location: Netherlands

Re: Can a node have two parents?

Postby Thaumaturge » Tue Oct 17, 2017 1:05 pm

I see--thank you.

Hmm... The possibly-variable properties shouldn't be a major issue in my case, I think. There are some potential problems, but they might be solved in the design of the levels, I imagine.

Is there a way around the "double rendering" issue? If not, is there another potential solution to the issue of objects straddling cell-borders?
MWAHAHAHAHA!!!

I have a website now! It holds information and a dev-blog for my nascent video-game, A Door to the Mists.
User avatar
Thaumaturge
 
Posts: 1592
Joined: Sat Jun 07, 2008 6:34 pm
Location: Cape Town, South Africa

Re: Can a node have two parents?

Postby Thaumaturge » Sat Nov 04, 2017 1:07 pm

I had an idea regarding this: How feasible would it be for me to add a new flag to NodePaths/Nodes (the latter, I imagine, but accessible through the former) that indicates whether a Node may be multiply-rendered, with a guard added during scene-graph traversal that skips a node if it has been rendered before?

Something like this, in pseudocode:

Node:
Code: Select all
bool mayRenderMoreThanOnce;
bool hasBeenRenderedThisPass;


In the scene-graph code:
Code: Select all
// While traversing the graph...
if (currentNode.mayRenderMoreThanOnce || !currentNode.hasBeenRenderedThisPass)
 {
  currentNode.hasBeenRenderedThisPass = true;
  // Render the node as usual...
 }


Of course, this would presumably call for some means of clearing the "hasBeenRenderedThisPass" flag... Perhaps

I'm not currently using instancing, so there's no conflict there. (In any case, the "mayRenderMoreThanOnce" flag could simply be set for instanced nodes.)

Thoughts?
MWAHAHAHAHA!!!

I have a website now! It holds information and a dev-blog for my nascent video-game, A Door to the Mists.
User avatar
Thaumaturge
 
Posts: 1592
Joined: Sat Jun 07, 2008 6:34 pm
Location: Cape Town, South Africa

Re: Can a node have two parents?

Postby rdb » Sat Nov 04, 2017 3:44 pm

Instead of a boolean, you could make it a frame number: if the frame number matches the current frame being rendered, you know it's already been rendered, if it's less, it still needs to be rendered. That prevents you from having to traverse all the nodes to clear it after each rendering.

If you have to render the scene multiple times from multiple points of view (eg. with shadows or reflections), a frame index wouldn't do, and you would instead have to assign a global number that you increase every time Panda is about to traverse the scene for rendering.

As for instancing, that does break with this approach. It is not easy to determine the value of mayRenderMoreThanOnce, but the way to determine it would be to iterate the graph upwards until you find a node with more than one parent. However that means that in your use case it would return true, since that's exactly what you're telling Panda to do. I think what you really want is to prevent nodes from rendering multiple times with the same transform and state.

So what you could do is, instead of storing a "mayRenderMoreThanOnce" flag, store the accumulated transform and render state of that node in a variable when the traversal gets to it. Then the next time the traverser encounters it, it can check whether it matches the state of the last time you rendered that object, and if so, skip it.


A completely different approach to doing all this would be *after* traversal, by adding code to the relevant CullBin* classes to filter out duplicate CullableObject entries from the lists during sorting. Alternatively, one could change the CullBin*::add_object calls to check whether the object already exists with these parameters before adding it to the list of objects to draw.

This does add additional overhead, of course. However since CullBinStateSorted is the most commonly used bin, and it already sorts the results, it might be simply a matter of checking in draw() whether the object matches the properties of the previous one, and skip it if that's the case. Or, switching it to an inherently sorted and uniquifying container like pset or ov_set.
rdb
 
Posts: 11166
Joined: Mon Dec 04, 2006 5:58 am
Location: Netherlands

Re: Can a node have two parents?

Postby Thaumaturge » Sat Nov 04, 2017 6:59 pm

rdb wrote:Instead of a boolean, you could make it a frame number ...

If you have to render the scene multiple times from multiple points of view (eg. with shadows or reflections), a frame index wouldn't do, and you would instead have to assign a global number that you increase every time Panda is about to traverse the scene for rendering.


A frame number is a good idea, I think. ^_^

However, I am rendering shadows, so as you say, that perhaps won't work. But see below...

rdb wrote:As for instancing, that does break with this approach. ...


As I said above, I'm not using instancing, so I'm happy to leave it broken for this project. If a later project calls for it, I can perhaps revisit the problem--presuming that subsequent changes to the engine between here and there don't obviate doing so, of course.

rdb wrote:A completely different approach to doing all this would be *after* traversal, by adding code to the relevant CullBin* classes to filter out duplicate CullableObject entries from the lists during sorting. ...


Something along these lines occurred to me after I posted--although I didn't at the time know enough to have much more than an inchoate concept. I suspect that this may actually be a better idea.

What about this: use a boolean, as mentioned above. While traversing, set the "hasBeenRenderedThisPass" flag to "false"--this is the step at which it's cleared. In CullBin*--"addObject" looks like a good spot, intuitively--the flag is checked. If it's "false", the object is added, and the flag is set to "true". Otherwise, skip the object and move on.

You mentioned rendering the scene multiple times; when doing so, is the scene graph traversed multiple times? I would imagine so, as different views would result in different culls. If so, and I'm not much mistaken, then this version may well work with multiple renders, as each subsequent traversal clears the flag. If not, it remains an issue...

What do you think?
MWAHAHAHAHA!!!

I have a website now! It holds information and a dev-blog for my nascent video-game, A Door to the Mists.
User avatar
Thaumaturge
 
Posts: 1592
Joined: Sat Jun 07, 2008 6:34 pm
Location: Cape Town, South Africa

Re: Can a node have two parents?

Postby rdb » Wed Nov 08, 2017 5:33 am

Thaumaturge wrote:What about this: use a boolean, as mentioned above. While traversing, set the "hasBeenRenderedThisPass" flag to "false"--this is the step at which it's cleared. In CullBin*--"addObject" looks like a good spot, intuitively--the flag is checked. If it's "false", the object is added, and the flag is set to "true". Otherwise, skip the object and move on.

Possibly, but this would have to be on the Geom then, not on the PandaNode, since the original PandaNode isn't stored in the cull process. And it can't be in CullBin*--addObject, because that is called during the cull traversal, so it has to be called during sort or draw.

This isn't necessary though, because instead of a frame index, you could simply use a "pass index"; a number you increment for each cull pass you do.
rdb
 
Posts: 11166
Joined: Mon Dec 04, 2006 5:58 am
Location: Netherlands

Re: Can a node have two parents?

Postby Thaumaturge » Wed Nov 08, 2017 9:39 am

rdb wrote:This isn't necessary though, because instead of a frame index, you could simply use a "pass index"; a number you increment for each cull pass you do.


Hmm... That makes sense, I think. It wouldn't call for clearing, either; indeed, even having the number eventually overflow would be fine, as we would only be checking for equality.

So, does the following rough code look good to you?

In Node
Code: Select all
static int globalPassCounter;

int passCounter;

Node()
 {
  passCounter = globalPassCounter;
 }


In the traversal code:
Code: Select all
// Before traversal
Node::globalPassCounter++;

// ...
// During traversal, presumably when considering whether to add the node to the bins
if (currentNode.passCounter != Node::globalPassCounter)
 {
  // Add node as per usual
  currentNode.passCounter = Node::globalPassCounter;
 }
MWAHAHAHAHA!!!

I have a website now! It holds information and a dev-blog for my nascent video-game, A Door to the Mists.
User avatar
Thaumaturge
 
Posts: 1592
Joined: Sat Jun 07, 2008 6:34 pm
Location: Cape Town, South Africa

Re: Can a node have two parents?

Postby rdb » Thu Nov 09, 2017 6:50 am

That would be the general idea, yes.

You could probably put this code in CullTraverser::traverse_below(), since that's where it analyzes whether the node should be rendered (and calls node->add_for_draw(this, data)) and whether its children should be visited. You can just check whether the counter matches, and if so, return early from that function.
rdb
 
Posts: 11166
Joined: Mon Dec 04, 2006 5:58 am
Location: Netherlands

Re: Can a node have two parents?

Postby Thaumaturge » Thu Nov 09, 2017 8:01 am

Excellent, and thanks. ^_^

Okay, once I've decided whether I'm moving to 1.10 or attempting to stick with 1.9.4 (as per the "Heap Size" thread), I'll likely take a shot at this. I'll hopefully update this thread once I've done so and tested the result!
MWAHAHAHAHA!!!

I have a website now! It holds information and a dev-blog for my nascent video-game, A Door to the Mists.
User avatar
Thaumaturge
 
Posts: 1592
Joined: Sat Jun 07, 2008 6:34 pm
Location: Cape Town, South Africa

Re: Can a node have two parents?

Postby rdb » Fri Nov 10, 2017 5:20 am

I do want to point out, in case it wasn't yet clear, that such a change could not make it into the main Panda codebase since it would break quite a bit of Panda's design, particularly wrt pipelined rendering and instancing.
rdb
 
Posts: 11166
Joined: Mon Dec 04, 2006 5:58 am
Location: Netherlands

Re: Can a node have two parents?

Postby Thaumaturge » Fri Nov 10, 2017 10:31 am

Don't worry, I do recognise that. It's intended for my own purposes, where instancing isn't called for.

Could you expand on the point regarding pipelined rendering, please? Being a little unfamiliar with that, I would like to check that this change won't break anything that I am using...
MWAHAHAHAHA!!!

I have a website now! It holds information and a dev-blog for my nascent video-game, A Door to the Mists.
User avatar
Thaumaturge
 
Posts: 1592
Joined: Sat Jun 07, 2008 6:34 pm
Location: Cape Town, South Africa

Re: Can a node have two parents?

Postby rdb » Sat Nov 11, 2017 1:21 pm

ie. setting threading-model. There are additional considerations that would need to be taken into account if multiple threads are doing rendering.
rdb
 
Posts: 11166
Joined: Mon Dec 04, 2006 5:58 am
Location: Netherlands

Re: Can a node have two parents?

Postby Thaumaturge » Thu Nov 16, 2017 7:53 pm

Ah, I see--thank you. So, as long as I'm not setting the "threading-model" parameter to something--and thus leaving it in the default state--I should be fine?
MWAHAHAHAHA!!!

I have a website now! It holds information and a dev-blog for my nascent video-game, A Door to the Mists.
User avatar
Thaumaturge
 
Posts: 1592
Joined: Sat Jun 07, 2008 6:34 pm
Location: Cape Town, South Africa

Re: Can a node have two parents?

Postby rdb » Fri Nov 17, 2017 6:28 am

Yes.
rdb
 
Posts: 11166
Joined: Mon Dec 04, 2006 5:58 am
Location: Netherlands

Re: Can a node have two parents?

Postby Thaumaturge » Fri Nov 17, 2017 7:33 am

Excellent, and thank you. ^_^
MWAHAHAHAHA!!!

I have a website now! It holds information and a dev-blog for my nascent video-game, A Door to the Mists.
User avatar
Thaumaturge
 
Posts: 1592
Joined: Sat Jun 07, 2008 6:34 pm
Location: Cape Town, South Africa


Return to Scripting Issues

Who is online

Users browsing this forum: No registered users and 3 guests