Received: by oss.sgi.com id ; Fri, 13 Oct 2000 16:05:25 -0700 Received: from mail.tgs.com ([209.75.36.9]:57609 "EHLO sight.tgs.com") by oss.sgi.com with ESMTP id ; Fri, 13 Oct 2000 16:05:05 -0700 Received: from DECnet-Mail11.sight.tgs.com by sight.tgs.com (8.8.8/1.1.10.5/07Jul98-0113PM) id QAA0000005674; Fri, 13 Oct 2000 16:04:00 -0700 (PDT) Date: Fri, 13 Oct 2000 16:04:00 -0700 (PDT) Message-Id: <200010132304.QAA0000005674@sight.tgs.com> Mime-Version: 1.0 From: mmh@tgs.com (Mike Heck) To: SMTP@tgs.com Cc: "info-inventor-dev@oss.sgi.com"@tgs.com Subject: RE: Open Inventor and VRML Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Sender: owner-info-inventor-dev@oss.sgi.com Precedence: bulk Return-Path: X-Orcpt: rfc822;info-inventor-dev-outgoing > 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