> I have recently start using TGS Open Inventor for Windows NT but I have to
> confess that I am facing some problems. I am involved in a medical project
> aiming to deliver robotic therapy to patients that have suffered from
> stroke. It has been decided that we will use a combination of virtual and
> real tasks to deliver appiling activities to the user. This surely will help
> in patient's motivation and improve the recovery time. The first prototype
> is intended to go to one hospital at the end of December for clinical
> evaluation.
>
> To start with, I have modelled a virtual room using 3D studio MAX and have
> converted this scene into VRML 97 format. Somehow I have managed to read the
> VRML scene into Open Inventor, but my main problem now is on how to access
> the VRML scene in order to perform actions such as, move objects from one
> location to another, detect when a collison occured, etc. Despit the books
> (The Inventor Mentor, The Inventor Toolmaker, and TGS Extesions User's
> guide) I am still lost! I have been trying to find examples but couldn't.
>
> I wonder if you could help my in this matter, if you have any documentation
> (tutorials, examples, etc) which relates to the problem discribed. Anything
> will help! It is extremely difficult for me at the moment and without having
> yet the abstraction behind computer graphics and the way Open Inventor
> really works adds to my difficulty to solve the problem.
OK, this is kind of a general interest question, so I've adapted
some existing text to your situation, hopefully giving sort of a
mini-tutorial. However there are many ways to organize a scene
graph, based on your application's requirements, so don't assume
this is the only possible way!
There's probably no need to split the VRML file into smaller files.
The more general question is: In your VRML file, what distinguishs
one "object" from another? You need to be able to answer this
question in order to manipulate the objects as separate entities
(you need to know this in order to split the file too :-).
It's almost certain that each "object" will be a collection of nodes
under some sort of grouping node. For example, in a VRML file:
DEF Object27 Transform {
children [
Cone {}
]
}
might be one (trivial) object in the incoming file.
Typically the file creator will assign a name to each grouping node
that represents an independent object. For example, the file creator
might simply assign them names "Object0000" through "Object0953".
Since you are modeling the scene, you should adopt some useful naming
convention. The node names will show up as "DEF name" in the output
VRML file, as above.
When you read the file into Open Inventor (from TGS), each node in
the scene will result in a corresponding node in the scene graph.
The grouping node above is an SoVRMLTransform, for example.
Let's say you wanted to find a particular object programmatically.
If you know the objects all have unique names, you can do this:
SoNode *pNode = SoNode::getByName( "Object51" );
However this only gives you a pointer to the node, it doesn't tell
you anything about where it is in the scene graph. To get that info
use a SearchAction like this (assuming sceneRoot is the root of the
entire scene graph, ie. what SoDB::readAll returned to you):
SoSearchAction sa;
sa.setName( "Object43" );
sa.apply( sceneRoot );
SoPath *pPath = sa.getPath();
SoNode *pNode = pPath->getTail();
If you want to be able to select objects by picking, look at the
discussion about SoSelection and redrawOnSelectionChange in the
Mentor (and other places). Remember though, that picking will
select an actual geometry node, so the node at the tail of the
selection path will be (for example) an SoVRMLIndexedFaceSet. To
get a path to the grouping node that represents the entire object
(which is presumably an ancestor of the geometry node), you have
two choices. You can implement a pickFilterCallback (see the
Mentor for details) or you can "manually" go up the path from the
tail looking for a grouping with an appropriate name.
Now you have the objects identified by some naming scheme and can
can get a pointer (or path) to a specific object.
In order to control "object attributes" like position, scale,
rotation, material, etc in a classic Open Inventor scene graph
you might put a set of attribute nodes as the first children of
each object. For example:
DEF Object35 Separator {
Transform {}
Material {}
... other object nodes ...
}
These nodes don't have to exist when the file is read in, you can
create them when (and if) they are needed, for example, given a
pointer to an object we want to rotate:
// given pNode points to the object's Separator
SoTransform *pTran;
SoNode *pFirstChild = pNode->getChild( 0 );
if (pFirstChild->isOfType(SoTransform::getClassTypeId()))
pTran = (SoTransform*)pFirstChild; // Already got one
else {
pTran = new SoTransform; // Make one
pNode->insertChild( pTran, 0 ); // Put as first child
}
pTran->rotation.setValue( SbRotation( ... // set rotation
There are many variations on this theme, for example giving the
attribute nodes meaningful names. You could also use node kits
for this purpose since they automatically create nodes (that are
part of their catalog) when they are needed.
The position/rotate/scale part is actually easier with VRML nodes!
The grouping node that defines an object will typically be an
SoVRMLTransform node. This node is effectively the combination of
an SoSeparator and an SoTransform. So given a pointer to an object
you want to rotate, you only have to do this:
SoVRMLTransform *pNode = ... // somehow we got this pointer
pNode->rotation.setValue( SbRotation( ... // set rotation
Hope that helps,
-Mike
TGS Inc, http://www.tgs.com
|