Sign in to follow this  

Yay, more scene graph stuff... To sum it up, Creating Complex Entities

This topic is 4302 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Alrighty, I'll use a torch object for an example, what is this thing made out of? 1. Torch stick geometry 2. Particle Emitter 3. Light 4. Maybe even an ambient sound generator (crackling) Now, What I want to do ultimately, is be able to do something nifty like this.
 AddObjectToScene(torch); 
Looks overly simple doesn't it? Well it is! But there are a few unforseen issues... We need the add object function to create nodes required for the object it is being passed, the torch I passed it will be of type ObjectInfo.. I need to create a generic object that can contain the information required for creating scene nodes for a complex object. That is the easy part. The hard part is this, properly linking all these nodes once created, in the correct tree structure!!! We can't have a light and then a geometry and then a particle emitter.. We need a geometry, a particle emitter, and a light, do you see what I mean? So in a structure, ObjectInfo, we need to contain the order, from top to bottom, of the complex object's nodes. Something like, level 1 is a transformation node, it has one child, level 2 is a geometry node, which has 3 children, level 3 is a this and a this and a this, and has no children, end. How can I go about accomplishing this?

Share this post


Link to post
Share on other sites
Quote:

We can't have a light and then a geometry and then a particle emitter.. We need a geometry, a particle emitter, and a light, do you see what I mean?


No, not at all. Short of doing something like putting the light into the torch model, why would the order matter?

Standard faire composite pattern with factories.

You do Factory(torch), which does Factory(model torch) [which might make other Factory calls to assemble the model], Factory(emitter fire), Factory(light fire)... and makes them children of the torch object with the proper orientation. It then returns a generic torch object which either you work with or is used by a 'higher' factory.

The actual factory definition method can vary. XML definitions are not uncommon, direct hardcoding isn't too uncommon though impractical for art-heavy games. Personally, I've found that almost empty constructors/factory parameters really help here. Focus on building the object; let the caller care about positioning, orientation, coloring...

Or perhaps I am just misunderstanding?

Share this post


Link to post
Share on other sites
Hmmm,

It does matter, for when we add Transformation into the equation..

Lets use a truck model now

We have:

A Dof(transformation), for each node
A truck body geometry, 4 wheel geometries
Attached to the truck as well, is a particle emitter, for exhaust or something


So thats 6 DOF nodes scattered all in between this complex object

It needs to be in this hierarchy


DOF NODE (Transformation)
|
|
------Truck Body
|
|
---- DOF, DOF, DOF, DOF, DOF
| | | | |
| | | | |
Wheel Wheel WheelWheel Particle Em




It has to be set up that way, or else we'll have some real goofy transformation issues, The wheel's and the particle emitter's location are relative to the truck body. The truck body is probably relative to terrain, or a race track..

Straight up, it has to go in this order, or it just won't work.

Share this post


Link to post
Share on other sites
Hmm, what would a non model be?

Like, the truck model with the extra particle emitter thrown on top?


Or the torch with the ambient sound and particles thrown on the top?

Share this post


Link to post
Share on other sites
Erm, no?


truck
|
\----\-----\----- wheel wheel wheel wheel


Turns into :

Identity -> push truck matrix ->

render truck -> push WheelA matrix -> render Wheel
<- pop WheelA matrix <-
-> push WheelB matrix -> render Wheel
[and so on] <-

NOT:

Identity -> push truck matrix ->

render truck -> push WheelA matrix -> render Wheel
-> push WheelB relative to WheelA matrix -> render Wheel
-> push WheelC relative to WheelB matrix...


Entity geometry is based off of parent, not neighbor. The wheels [or really any object] can be in any order, since the matrix state on call is the Truck's. Right?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I've seen engines that run AAA games written by so-called "brilliant" folks that are compelte crap and don't even use any type of hierarchael systems, so kudos for trying to get this to work. However, I suspect that at this point you have a serious issue with your system if the sibling nodes are order dependent in order to get a specific effect. :D

If you're doing it in a correct and proper way, order shouldn't matter.


Share this post


Link to post
Share on other sites
Okay, please don't post if you don't know what you are talking about.

Okay, on the wheeled truck

DOF
Truck
DOF
Wheel


After the second dof node, NO, it doesn't matter in what order each wheel comes.

Now lets add three more wheels


DOF NODE - parent of truck
TRUCK - parent of 4 dof's
DOF, DOF, DOF, DOF - each dof is a parent of a wheel
WHEEL, WHEEL, WHEEL, WHEEL - each wheel is a leaf

the first dof must come first
the truck must come next
the four wheel dofs must come next
the 4 wheels are on the next level

I'm sorry if I'm getting short, but I'm putting my question out there plain and simple and it is being ignored..

How do I store this information in a structure, or in a file?

EDIT:

I can draw a picture if I'm still not coming across, I did not mean for there to be confusion with "siblings being relative to each other", that is not the case, and how it came off to look that way I'm not quite sure of.

Share this post


Link to post
Share on other sites
You will assume the DOFs are all part of a higher DOF. Basically collections to the parent. If every object in the tree is a collection of aggregates(inherited from a common base class). All parts added to each objects collection become that objects child. This is where UML shines by allowing you to define relationships, collections, actors, entities etc. The base clase should also have an overable pure virtual function to identify the object via two methods. One static and one dynamic. The static defines the concrete form of the class such as Wheel. The dynamic one is the dynamic property such as "Truck Wheel", "Bicycle Wheel". From these methods the classes can be persisted with the named parent to rebuild the tree on load. You may want to store movable objects as loose collections with the position and state of the object. Store the world and it's objects states in another. This avoids unnecessary complexity of the storage model.

Your truck justs owns four wheels, if it looses one then one is removed from the list and cardinality reduces to 3. By calling Truck->AddWheel( pWheel) the parent will call Identify() for that wheel and if it is not a truck wheel then reject it else add it to it's tree. It's up to the parent node to call it's children to render, evolve, rotate, update state, force state etc. Remember the tree is a dynamic entity. Where each child is a branch with children unless it is a leaf node. This is why you have to know what the child is for when you persist the tree are need to query the objects for specific objects. A query may occur then the game requires confiscation such as take away all the matches or check all wheels for grease.

This subject gets more involved with all the available patterns which takes time to learn and master.

Share this post


Link to post
Share on other sites
It came off that way because I couldn't think of any possble way that assembly of an object:


SceneGraphNode Truck = ModelManager.Load("truck");
SceneGraphNode Wheel = ModelManager.Load("wheel");

Wheel.SetTransform( /* front left of truck */ );
Truck.Add(Wheel);

Wheel=ModelManager.Load("wheel");

Wheel.SetTransform( /* front right of truck */ );
Truck.Add(Wheel);

...

return(Truck);


Was not completely obvious to someone who's made functional scene graph code.

Quote:

The actual factory definition method can vary. XML definitions are not uncommon, direct hardcoding isn't too uncommon though impractical for art-heavy games.

Share this post


Link to post
Share on other sites
Quote:
Original post by Shamino
Okay, please don't post if you don't know what you are talking about.


Lol i love that, thats how you thank people who are trying to help you?

Besides, it looks to me like it might be you who does not understand what hes talking about. I honestly cant think of a way to explain it better than how Telastyn has already put it.

Quote:
Original post by Shamino
Okay, on the wheeled truck

DOF
Truck
DOF
Wheel


After the second dof node, NO, it doesn't matter in what order each wheel comes.

Now lets add three more wheels


DOF NODE - parent of truck
TRUCK - parent of 4 dof's
DOF, DOF, DOF, DOF - each dof is a parent of a wheel
WHEEL, WHEEL, WHEEL, WHEEL - each wheel is a leaf

the first dof must come first
the truck must come next
the four wheel dofs must come next
the 4 wheels are on the next level


Each wheel is a child of a Truck. The Truck should be a scene node with its world transformation.

Each wheel is its own node, and hence has its own transformation. Each wheel is relative to the truck, and there is no relationship between any of the wheels (not as far as the scene graph is concerned at least)

Lets say our Truck is of dimensions 10 units long, 5 units high, and 5 units wide. The front left wheel without a transformation would be placed right in the middle of the truck, we want to move it. Hence, each wheel might look like this:


Wheel.SetTransform(-4, -2.5, -2) // FRONT RIGHT
Wheel2.SetTransform(-4, -2.5, 2) // FRONT LEFT
Wheel3.SetTransform(4, -2.5, -2) // BACK RIGHT
Wheel4.SetTransform(4, -2.5, 2) // BACK LEFT


It might not demonstrate it that well, but hopefully shows the point. Each wheel has -2.5 for Y since the wheels are underneath the car, then its own translation depending on which corner of the truck its near. From here we just attach those scenenodes to the Truck

Truck.attach(Wheel);
Truck.attach(Wheel1);

..etc....

Note here that the Order does not matter, because they are only relative to the truck. You could add these nodes in any order, and it will still work.

For the original question, your node might just include the geometry, particle emitter and a light in one node (subclass SceneNode to create TorchNode maybe) and then you can position it anywhere the same way as demonstrated above.

Anyway, this is probably one of my less helpful replies but since your scene graph appears fundamentally broken to me if nodes need to be ordered in that way, then maybe reading this post and what Telastyn said will help make sense of it.

Share this post


Link to post
Share on other sites
Saying that something is "crap" beacause it doesn't have any hierarchy is probably too strong. You can make fine games and great graphics systems without a hirarchical scene graph (or, in fact, a scene _graph_ at all). It all depends on what your approach and your needs are.

Compare to file systems: You can have a file system API that synchronously opens a file (fopen()). Or you can have a file system that asynchronously opens a file and notifies you back (SIGIO). Or you can have a file system that looks like it's memory (mmap()). Or you can have a file system that looks like it's structured data (MySQL). No one approach is right for all needs.

Share this post


Link to post
Share on other sites
Thanks to the help of a friend I now understand *how* the structure is set up...

But I still don't understand how to, hm, convert it from file to code?

Bubba on cboard.cprogramming.com
Quote:

Code:

ObjectInfo
{
int ObjectID;
int NumGeometryNodes;
int NumDOFNodes;

ObjectInfo *m_pNextNode;
ObjectInfo *m_pPrevNode;



// any other nodes we might have
};


Or use the STL list, vector, etc.

For example a quadtree structure:


Code:

struct QuadTreeNode
{
int m_iType; //Node or leaf?

QuadTreeNode *m_pUL; //Upper left child
QuadTreeNode *m_pUR; //Upper right child
QuadTreeNode *m_pLL; //Lower left child
QuadTreeNode *m_pLR; //Lower right child

D3DXVECTOR3 m_vecMin,m_vecMax; //Bounding box

Object *m_pObjectArray; //Objects in this node
int m_iNumObjects; //Number of objects in node
};



Code:

class CTerrain
{
QuadTreeNode *m_pRoot; //Start of quad tree
....
....
};


I understand how the stuff is linked together.

The root node holds a vector of children, each child of the root holds its own vector of children. So in theory I'll be able to simply add a base node to my tree and the rest will kinda just, follow.

But lets see, if, in an editor, we set the hierarchy up, so that the truck is the base node, and has 4 children, for the 4 wheels...

How do we hold this information in a file, ready to be converted to hard code in my project? I understand how the stuff is linked together, but how do I interpret a file to create the links and link them in the right way?

Share this post


Link to post
Share on other sites
Quote:

Anyway, this is probably one of my less helpful replies but since your scene graph appears fundamentally broken to me if nodes need to be ordered in that way, then maybe reading this post and what Telastyn said will help make sense of it.


Again, don't reply if you don't know what you are talking about, please read above posts, please get it through your skull that in my graph the wheels aren't relative to each other, I never said that. Ever.

Share this post


Link to post
Share on other sites
Shamino, you don't know what you are talking about (or you wouldn't be asking questions), you are therefor unfit to judge whether or somebody replying to you knows what they are talking about. Do not jump to the conclusion that "somebody misunderstanding you" implies "somebody doesn't know what they are talking about," and don't reply in such harsh tones or nobody will afford you the courtesy of answering your question.

That said, what I believe is causing some misunderstanding is your assertion that: "Straight up, it has to go in this order, or it just won't work." (your first post), in which the "order" you were referring to was the hierarchical order (wheels are children of truck which are children of some other root, perhaps the racetrack) but could have been misinterpreted to mean that the wheel and particle emitter nodes must be ordered (within their level in the hierarchy) exactly as you listed in your example.

Also your assertion that "We can't have a light and then a geometry and then a particle emitter.. We need a geometry, a particle emitter, and a light, do you see what I mean?" is confusing and implies that order within a given hierarchy level matters (it doesn't, obviously, as long as those three entities are children of the appropriate transformation node, any combination of their orders within the children list will produce the same scene).

Telastyn's examples are clear enough solutions to what you appear to be stumbling over, however. I would recommend you avoid the use of "Bubba on cboard.cprogramming.com"'s direct example as it favors raw pointers over safe abstractions like std::vector for the list of children and such.

Care to restate your question more clearly, if Telastyn's posts are actually helping you?

Share this post


Link to post
Share on other sites
And again, the question still remains..
Quote:

So in a structure, ObjectInfo, we need to contain the order, from top to bottom, of the complex object's nodes.

Something like, level 1 is a transformation node, it has one child, level 2 is a geometry node, which has 3 children, level 3 is a this and a this and a this, and has no children, end.

How can I go about accomplishing this?


I know how to add children to my nodes, how to do this, and this, and that. I know how to do everything telastyn and everyone else is showing me.

What I don't know how to do is this:

1. I want to create an editor (this isn't the problem)
2. I need to save information regarding to who is who's daddy in a file.
3. And then convert it to a struct I can pass to an Addtoscene function.

OR, pass the file to the addtoscene function, instead of creating a struct out of it first.

Basically, I want the addtoscene function to take a parameter (base node) that is preconstructed in a file.

So to add a torch for example, we can simply add the torches base node to the tree, and the rest is already built for us.

Sorry for being short, I get cranky without enough sleep :)

And jPetrie you're right, I'm being snippy :), my apologies :)

Share this post


Link to post
Share on other sites
There are a number of ways you could do this.
I'll use XML as an example because it is a naturally hierarchical format and there are parsing libraries, such as TinyXML, readily available, which speed up the entire process.

You could have a collection of prefabricated nodes in a file called prefab_nodes.xml. The node element structure would mimic the approximate logical structure of your C++ struct; you have the node's name, maybe its type, optionally a transformation matrix, optionally a reference to a model or geometry chunk, and optionally references to any child nodes. For example, your torch:

<node name="torch" type="object">
<geometry name="torch.ms3d">
<child name="torch_firesmoke_emitter" transform="1,0,0,0,0,1,0,0,0,0,1,2,0,0,0,1"/>
<child name="torch_crackle_sound"/>
</node>


(Here I've given the emitted a transformation matrix that would be used to offset the emitter relative to the torch node itself two units in the +Z direction). Elsewhere in prefabnodes.xml you'd have defined the nodes you referenced by name:

<node name="torch_firesmoke_emitter" type="emitter">

</node>
<node name="torch_crackle_sound" type="soundeffect">
<sound name="crackle.wav" loops="yes" volume="quiet" />
</node>


And so on. You could even allow your editor to group nodes and save them out to this file.

If XML is not your thing, you can accomplish a similar system using your own custom text or binary format (the DirectX .X file format does this, and its very extensible. You can check out the docs for the file format even if you aren't use DX because it might be a helpful example). In fact I'd recommend considering a binary format since XML can get very large very quickly.

EDIT: I'd typed out the matrix wrong.

[Edited by - jpetrie on March 5, 2006 3:21:57 PM]

Share this post


Link to post
Share on other sites
Well I'm using openGL so x files are out of the case, but however, it is also unfortunate that I've never even really seen XML much less know what it is.

EDIT: Okay, so I understand what XML is, thank you www.xml.com

But, what do I need to know how to do in XML to be able to accomplish my task at hand? I really don't want to look into learning an entire markup language to produce 300 lines of code!

[Edited by - Shamino on March 5, 2006 8:37:47 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
You don't necessarily need XML; you can come up with your own scheme for storing a graph type structure. It could be as simple as assigning a number to each node, and then when you store the nodes in the file you reference pointers to children by using their number. Then when reading the nodes from the file, you restore all the pointers after the nodes are loaded.

Share this post


Link to post
Share on other sites
The .X file article is here, although the code that comes with it is an eyesore. In any case I wasn't neccessarily suggesting you use them (although you could if you wanted, I suppose). Rather, I was suggesting you should look at the X file documentation on MSDN, and possibly cracking open a few .X files (most of them are text format) and seeing how they are structured. It might give you an idea on how you could structure your file format.

XML's very easy to learn to use for something like this. Basically you are specifying (implicitly) a set of hierarchical elements (the <foo> tokens) that have attributes (the foo="bar" bits that go inside the elements). The nesting of the elements within eachother provides the hierarchical structure. You can call your elements and attributes whatever you like -- instead of "node" and "name" in my example, I could have just as easily used "ketchup" and "moscow" and I'd still have the same file, as long as I looked for elements named "ketchup" instead of "node" when I was loading the XML using something like TinyXML.

But again, you can invent your own textual format or use a binary one like the AP suggested. It's entirely up to you, you should use whatever fits your situation the best. One way to think about it would be to pretend you already had the file format designed and an example file sitting on your hard drive. Now you write the code to load a node and its children from that file, and contruct that element of the scene graph using the interface you've already defined for adding new nodes as children of other nodes, setting their transformations, and so on. Once you have this code written, it should suggest what the format of the file should probably be like.

Share this post


Link to post
Share on other sites
That sounds like a good idea jpetrie, but so far I've only seen code snippets in XML, I havn't seen how you would be reading the file to get the right data.

I know how to work the fstream, I'm just not really certain what I'd be looking for...

Creating my own binary hierarchy? Are you serious? You mean with 1's and 0's?!

Either way..

How do you convert from XML strings and text to C++ code?

Do you set string variables = to something from the file and give them a meaning? Uhg.. This is one complex topic..

I'd like to use my own invention if I can, but I really have no idea where to even begin when doing something of this magnitude..

Share this post


Link to post
Share on other sites
Quote:
Original post by jpetrie
there are parsing libraries, such as TinyXML, readily available, which speed up

I looked at it, and it looks like I will use this as well for my scene graph, It also looks like you can write xml with that libary, so you can make an editor for your program.

Share this post


Link to post
Share on other sites
I'm thinking it might be simpler to create my own system, it doesn't have to be very complex, more of a, paint by number type deal... But where to start? How to do this? Who knows..

Share this post


Link to post
Share on other sites

This topic is 4302 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this