[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Gnu3dkit-dev] 3D file formats

From: Brent Gulanowski
Subject: Re: [Gnu3dkit-dev] 3D file formats
Date: Tue, 8 Oct 2002 01:30:35 -0400

On Monday, October 7, 2002, at 11:11  PM, Matt Brandt wrote:

Of course I'm afraid of how slow this might be. But if it's workable, every node would in fact be a sort of dictionary. Maybe even a standard NSDictionary. It would be sent a message asking if it had a key matching the attribute. If so, work with the attribute. If not, ask for the children attribute and do the same with them, if they exist. Do you think that that would just be impossibly slow and too generic to be workable? I mean, the attributes would have unique classes, and they would be optimized.

I think that if you just implement this in the straightforward way, where you actually send the message to each child, without cached knowledge of whether or not they are acting on the messages, you will get very slow results very quickly. (did that make sense?)

On the other hand, it is pretty easy to have a child return a status to each message that indicates whether it, or any of it's children, acted on the message, and have the parent cache this status to keep from sending messages that aren't needed. That will quickly prune the message tree so that it won't get too busy. This requires that a child send a message up the parent chain when something enables a message (like adding an attribute).

Yes, you make perfect sense. Before I went off on my dictionary tangent I think the word "cache" drifted through my mind, but I didn't happen to go down that mental pathway. I'm not really recommending a completely generic dictionary implementation, but I do like the idea of communication paths being left unspecified until runtime and then optimized with caching or other techniques. Still some things that are essential should be built right into the class definition.

My feeling is that a graph node is a very unique type of object, but that any variation in graph nodes can be accounted for within the design of a single class. Likewise a geometry container is also very unique, but could hold different kinds of geometry which are identified by some ivar. In fact, the same geometry container can hold multiple representations of that geometry, and the same node of a graph might contain multiple children which each contain different representations of the same scene. Inside the node is a little switch (a reference, not a C switch) pointing to the best child for the current rendering context. When a new context is set, the switches are all set once, prior to the first render, like train track switches, click click click. There is also a switch which will stop the rendering recursion when it is determined that none of the children are being rendered, and the method returns this state, together with a trigger value for toggling the switch, when it returns.

I don't know if the same node should have both regular children and substitution sets. If not, then we're probably back to two classes of node, anyway. I don't know. The difference is a) calling on each (active) child in turn, b) calling at most one child form a set, and c) calling at most one child from each set. I guess the problem with c) is that you have a node which contains containers of containers. NSArrays have the benefit of -makeObjectsPerformSelector:WithObject: (oh, except that the renderWithMask:Frustum: uses a primitive and an object, ergo v0.3 uses a loop -- what complications arise at changing this method to pass only one object?)

Option b) requires using similar logic to the current Switch groups, unless there is maybe a way for the children to decide for themselves which of them should be rendered, instead of their parent node deciding. Actually, if there were a good way to do that, then option c) becomes much easier. The same message gets passed to each set of representations, and they do the work -- and I mean "they" -- no parent object except the node. They organize themselves. In fact, perhaps the node only has to know that there is one of them. They form a little chain, and the node calls the first one. It looks at the rendering context object which is being passed (more verbose than a mask, and containing a frustum), and either decides to render itself, that nobody gets renderered, or calls its next sibling. Results are passed back up to the node. No decision logic in the parent node, only the sibling!

The same pattern can easily be extended to geometry containers, which hang off of leaf nodes. It is a leaf by description, not prescription -- again, like the root. A leaf node has geometry containers for children (these aren't leaves, because they aren't nodes, they are lists of siblings). If they were two-way lists, the one referenced by the parent node would always be the most appropriate one, and you'd only move up or down one step at a time.

The same technique should work in the node representation sets. So, we would have one node object, with a switch that told it whether it had siblings. Then, when checking the rendering info package, and it didn't itself satisfy the requirements to draw, it would cascade the message to it's sibling on one side or the other (not both). With no siblings, it either cascades to its children or replies negative and sets its threshhold trigger. (Likewise, if it does pass the buck, it clears its threshhold trigger.)

Anyway, that's a lot to digest. I'll have written a book by the time this is done with. Actually, being 1)the newbie and 2)a trained writer, I restate my willingness to take over any documentation tasks. Phil, please include documentation objectives amongst those other project objectives I mentioned last message.

Brent Gulanowski                                address@hidden

Pluto Neptune Uranus Saturn Jupiter Mars Earth Venus Mercury Sun
  .      o      o      o      O      .     .     .      .    /\
                                           ^                 \/
                             You are here _|

reply via email to

[Prev in Thread] Current Thread [Next in Thread]