Thread: [Plib-users] Plib as a Model Loader
Brought to you by:
sjbaker
From: Tyler O. <Xa...@ho...> - 2004-07-08 19:19:34
|
I'm looking at using plib as a model loader for a flight simulator type application I'm making, but that's all I want plib for. (I don't want to use plib as my scene graph library) I've played around with the simple scene graph module and I see that calling ssgCullAndDraw throws out the existing projection and modelview matrices forcing you to use ssg's camera. I would like to use my own camera and not have to use ssg's camera at all. Is there a way to call a draw method of an ssgRoot object that does not throw out the these matrices and leaves the view culling up to the application (it just draws around the current zero point like glutSolidTeapot and such)? If there doesn't exist such a method, would there be an interest for me to create one for you all? Thanks, Tyler |
From: Steve B. <sjb...@ai...> - 2004-07-09 00:35:15
|
Tyler Ohlsen wrote: > I'm looking at using plib as a model loader for a flight simulator type > application I'm making, but that's all I want plib for. (I don't want > to use plib as my scene graph library) The problem with 3D file loaders is that they have to load the model into some kind of data structure. The name for that data structure is a "Scene Graph". Hence, loaders for 3D file formats cannot exist wihout a scene graph. Since rendering stuff out of that scene graph is an easily automatable process - and since it makes a lot of sense to use a C++ class hierarchy to do the work, it follows that the renderer and the file loader are tightly knitted together. Tossing out the renderer in order to get the loaders is not generally a good idea. > I've played around with the simple scene graph module and I see that > calling ssgCullAndDraw throws out the existing projection and modelview > matrices forcing you to use ssg's camera. I would like to use my own > camera and not have to use ssg's camera at all. SSG lets you set both the modelview and projection matrix directly. It's hard to imagine what "your own camera" could be that SSG couldn't already handle. > Is there a way to call a draw method of an ssgRoot object that does not > throw out the these matrices and leaves the view culling up to the > application (it just draws around the current zero point like > glutSolidTeapot and such)? No - because SSG needs to know that those matrices are in order to do field-of-view culling, Range-switched nodes and such. OK - we *could* read those matrices back from OpenGL in order to find out what your camera code set them to - but reading things back from OpenGL is something to be avoided at all costs. So it's better for you tell use what you want them to be and let us send them to OpenGL...that's no different from you sending them to OpenGL - but this is more efficient. > If there doesn't exist such a method, would > there be an interest for me to create one for you all? I don't see any conceivable need for that - but if you can come up with something convincing, we could certainly consider it. ---------------------------- Steve Baker ------------------------- HomeEmail: <sjb...@ai...> WorkEmail: <sj...@li...> HomePage : http://www.sjbaker.org Projects : http://plib.sf.net http://tuxaqfh.sf.net http://tuxkart.sf.net http://prettypoly.sf.net -----BEGIN GEEK CODE BLOCK----- GCS d-- s:+ a+ C++++$ UL+++$ P--- L++++$ E--- W+++ N o+ K? w--- !O M- V-- PS++ PE- Y-- PGP-- t+ 5 X R+++ tv b++ DI++ D G+ e++ h--(-) r+++ y++++ -----END GEEK CODE BLOCK----- |
From: Tyler O. <Xa...@ho...> - 2004-07-15 17:41:41
|
> Tyler Ohlsen wrote: > > I'm looking at using plib as a model loader for a flight simulator > > type application I'm making, but that's all I want plib for. (I don't > > want to use plib as my scene graph library) > > The problem with 3D file loaders is that they have to load the model into > some kind of data structure. The name for that data structure is a > "Scene Graph". Hence, loaders for 3D file formats cannot exist wihout > a scene graph. Since rendering stuff out of that scene graph is an > easily automatable process - and since it makes a lot of sense to use > a C++ class hierarchy to do the work, it follows that the renderer and > the file loader are tightly knitted together. > > Tossing out the renderer in order to get the loaders is not generally a good idea. Loading from a 3D file into a scene graph is one implementation, you don't have to do it that way. I agree that it makes a lot of sense and that most 3D applications are greatly improved by using scene graphs. That being said, it would be nice to have the option to use someone else's scene graph library. Not that yours is lacking in anything, but the option is nice. > > I've played around with the simple scene graph module and I see that > > calling ssgCullAndDraw throws out the existing projection and > > modelview matrices forcing you to use ssg's camera. I would like to > > use my own camera and not have to use ssg's camera at all. > > SSG lets you set both the modelview and projection matrix directly. > > It's hard to imagine what "your own camera" could be that SSG couldn't already handle. Again, this was a matter of preference. I would like to use my own camera if I could (without doing a hack to convert my camera's orientation representation to ssg's camera orientation every frame). > > Is there a way to call a draw method of an ssgRoot object that does > > not throw out the these matrices and leaves the view culling up to the > > application (it just draws around the current zero point like > > glutSolidTeapot and such)? > > No - because SSG needs to know that those matrices are in order to > do field-of-view culling, Range-switched nodes and such. OK - we > *could* read those matrices back from OpenGL in order to find out > what your camera code set them to - but reading things back from > OpenGL is something to be avoided at all costs. > > So it's better for you tell use what you want them to be and let > us send them to OpenGL...that's no different from you sending them > to OpenGL - but this is more efficient. But if you're not using ssg as your scene graph (just as a model loader) then you don't want it to do view culling. Then ssg doesn't need to know the current state of these matrices at all. > > If there doesn't exist such a method, would > > there be an interest for me to create one for you all? > > I don't see any conceivable need for that - but if you > can come up with something convincing, we could certainly consider it. I dug into ssg and came up with the following code. First is an example usage of what this function gives the application programmer. This function has made the integration of ssg (just as a model loader and not a scene graph) into my application much easier. It may not be the most efficient way to do it, but it's not too bad (I know that each leaf's opengl state is forced). Example Usage: --------------------------------- int LoadModel(const char* szFile) { int iListID = glGenLists(1); ssgEntity* oModelEntity = ssgLoad(szFile); ssgRoot* oModel = new ssgRoot; oModel->addKid(oModelEntity); glNewList(iListID, GL_COMPILE); glPushMatrix(); glRotatef(-90, 1,0,0); //ssgRawDraw allows for regular opengl transforms glScalef(0.25f, 0.25f, 0.25f); ssgRawDraw(oModel); glPopMatrix(); glEndList(); delete oModel; delete oModelEntity; return iListID; } void RenderModel(int iListID) { glCallList(iListID); } --------------------------------- You are welcome to integrate this code into plib if you wish. Also, if you have any suggestions of changes I would be glad to hear them. Implementation: ----- ssg.h ----- void ssgRawDraw ( ssgBranch *root ) ; class ssgEntity : public ssgBase { ... virtual void raw_draw ( bool translucent_objects ) = 0 ; ... } class ssgLeaf : public ssgEntity { ... virtual void raw_draw ( bool translucent_objects ) ; ... } class ssgBranch : public ssgEntity { ... virtual void raw_draw ( bool translucent_objects ) ; ... } class ssgTransform : public ssgBaseTransform { ... virtual void raw_draw ( bool translucent_objects ) ; ... } ------- ssg.cxx ------- void ssgRawDraw ( ssgBranch *r ) { r->raw_draw(false); r->raw_draw(true); } ------------- ssgBranch.cxx ------------- void ssgBranch::raw_draw ( bool translucent_objects ) { for ( ssgEntity *e = getKid ( 0 ) ; e != NULL ; e = getNextKid() ) e -> raw_draw ( translucent_objects ) ; } ---------------- ssgTransform.cxx ---------------- void ssgTransform::raw_draw ( bool translucent_objects ) { glPushMatrix () ; glMultMatrixf ( (float *) transform ) ; for ( ssgEntity *e = getKid ( 0 ) ; e != NULL ; e = getNextKid() ) e -> raw_draw ( translucent_objects ) ; glPopMatrix () ; } ----------- ssgLeaf.cxx ----------- void ssgLeaf::raw_draw ( bool translucent_objects ) { if (isTranslucent() != translucent_objects) return; if (hasState()) getState()->force(); draw_geometry () ; } ----------- Thanks for creating a great library =) Tyler Ohlsen |
From: Steve B. <sjb...@ai...> - 2004-07-16 08:34:34
|
Tyler Ohlsen wrote: > Loading from a 3D file into a scene graph is one implementation, you > don't have to do it that way. I agree that it makes a lot of sense and > that most 3D applications are greatly improved by using scene graphs. > That being said, it would be nice to have the option to use someone > else's scene graph library. Not that yours is lacking in anything, but > the option is nice. What other kind of data structure could you load a 3D model into? A big pile of unstructured polygons and vertices I suppose - but that isn't going to make rendering very easy - and it throws away a lot of valuable information from the source model. >>SSG lets you set both the modelview and projection matrix directly. >> >>It's hard to imagine what "your own camera" could be that SSG couldn't >> already handle. > > Again, this was a matter of preference. I would like to use my own > camera if I could (without doing a hack to convert my camera's > orientation representation to ssg's camera orientation every frame). What hack? Just call the SSG function to pass your camera's data (heading, pitch, roll, x, y, z) into SSG. That's *ONE* line of code! It couldn't be much simpler! >>No - because SSG needs to know that those matrices are in order to >>do field-of-view culling, Range-switched nodes and such. OK - we >>*could* read those matrices back from OpenGL in order to find out >>what your camera code set them to - but reading things back from >>OpenGL is something to be avoided at all costs. > > But if you're not using ssg as your scene graph (just as a model loader) > then you don't want it to do view culling. Then ssg doesn't need to > know the current state of these matrices at all. OK - so if you aren't using SSG to render the scene and you don't want the loaders to load into SSG's scene graph - then why the heck are you using SSG? > glNewList(iListID, GL_COMPILE); > glPushMatrix(); > glRotatef(-90, 1,0,0); //ssgRawDraw allows for regular > opengl transforms > glScalef(0.25f, 0.25f, 0.25f); > ssgRawDraw(oModel); > glPopMatrix(); > glEndList(); But this mythical 'ssgRawDraw' function has to traverse the scene graph because the scene graph may contain transforms, selectors, animations and level-of-detail nodes that the loader created for us. Let's look at just one of those things by way of example: Level of detail nodes (ssgRangeSelector). This is something that has been created by the loader from information in the model file. It is a model that has one polygonal representation when it's close to the eye - and a simpler one when it's further away. If you ignore the presence of that node in the file and just render all the polygons mindlessly then you'll see TWO copies of the model being drawn at once - one of which looks really bad when it's close to the eyepoint because it's made of so few polygons - and the other of which will overload your system because it's drawn with so many polygons - even when it's 10 miles away from the camera. So in that case, you **MUST** traverse the scene graph that the loader built for you or the scene won't look right. Now - in order to decide which of those two models to draw, your rendering code (marked here in your example as 'ssgRawDraw') **MUST** be able to figure out the range from the object to the camera. However, it has no way to do that because you only gave the camera matrix to OpenGL - you didn't tell the renderer. The *ONLY* way that ssgRawDraw could possibly figure out that range would be to do a glGetMatrix. The trouble with glGetMatrix is that it (potentially) stalls the graphics pipe...this could make it UNBELIEVABLY slow. So - the rational way to do it is to have your application pass the camera matrix into SSG so that it knows where the camera is without having to read it out of OpenGL....and that's what we have. There simply isn't any other way to make this work. There are other nodes that need this information - ssgCutout for example. Then there is the issue of field-of-view culling. In a typical application, the camera's field of view is something like 60x40 degrees. That means that we are only rendering about a tenth of the objects in the scene on a 'typical' setup. If your 'ssgRawDraw' isn't doing field-of-view culling then it's going to run something like ten times slower than ssgCullAndDraw for the same scene. However, the only way you can possibly do field of view culling is if you know where the camera is...same problem. It is UTTERLY trivial to modify any program that computes a camera position and passes it to OpenGL to pass that position into SSG instead. Truly - it can't take you more than 5 lines of code. Heck - you could even to a glGetMatrix yourself if you couldn't figure any other way. When you take that little baby step, everything else runs at least 10x faster than what you propose - and it also gets things like level-of-detail and billboards right. ---------------------------- Steve Baker ------------------------- HomeEmail: <sjb...@ai...> WorkEmail: <sj...@li...> HomePage : http://www.sjbaker.org Projects : http://plib.sf.net http://tuxaqfh.sf.net http://tuxkart.sf.net http://prettypoly.sf.net -----BEGIN GEEK CODE BLOCK----- GCS d-- s:+ a+ C++++$ UL+++$ P--- L++++$ E--- W+++ N o+ K? w--- !O M- V-- PS++ PE- Y-- PGP-- t+ 5 X R+++ tv b++ DI++ D G+ e++ h--(-) r+++ y++++ -----END GEEK CODE BLOCK----- |