Sample Scenegraph Creation |
The following is a simple example of how to create a Shockwave 3D scenegraph. It contains four general procedures:
The scene is a simple cube, with a directional light, and a single camera.
The scene hierarchy has this structure:

Create an IFXCoreServices object.
This object is the core of the entire system. When created, the CoreServices object will create a Scenegraph, as well as several other management objects.
ifxResult = IFXCreateComponent( CID_IFXCoreServices, IID_IFXCoreServices, (void**)&pCoreServices );
Get a handle to the scenegraph from the newly created CoreServices object.
The scenegraph contains all the information of the scene, including model information, scene hierarchy, and animation data.
ifxResult = pCoreServices->GetSceneGraph( &pSceneGraph );
Create an IFXView object.
An IFXView object is the Shockwave 3D equivalent of a camera. It is simply an extended scenegraph node, and does not use a resource like the light and model nodes.
ifxResult = IFXCreateComponent( CID_IFXView, IID_IFXView, (void**)&pView );
Initialize the view object.
All objects created with IFXCreateComponent(), (except the CoreServices and Scenegraph objects) must be initialized with the scenegraph immediately after creation. If not, all calls referencing the objects will fail.
ifxResult = pView->Initialize( pSceneGraph );
Initialize the values in the view object.
These values include field of view, near and far clip planes, and size. Other options include background color, buffer clear values, and position of the view in a device. Because the view is used for rendering, most of these options are set at the time the view becomes active in a rendering device. They can safely be ignored until such time.
ifxResult =
pView->SetSize( WIDTH, HEIGHT );
ifxResult =
pView->SetProjection( FOV_ANGLE );
ifxResult =
pView->SetNearClip( NEAR_CLIP_DISTANCE );
ifxResult =
pView->SetFarClip( FAR_CLIP_DISTANCE );
Add an entry into the scenegraph's Node Hierarchy Palette for the new view.
Because the view is simply an extended scenegraph node, it is placed in the Node Hierarchy Palette. The Shockwave 3D scenegraph expects to find at least one view in the scene named "defaultview." This view is used as the primary camera when the render layer is initialized. (The camera may be changed through the Lingo API at runtime.)
CIFXString viewName("defaultview");
ifxResult =
pSceneGraph->GetPalette( IFXSceneGraph::NODE, &pNodePalette );
ifxResult =
pNodePalette->Add( &viewName, &uiViewID );
Initialize the palette entry at uiViewID with the new view node.
This places the data for the view into the palette, where it will remain until deleted, or the scenegraph is unloaded.
ifxResult = pNodePalette->SetResourcePtr( uiViewID, (IFXUnknown*)pView );
Note: The IFXUnknown data type is the parent type for all Shockwave 3D entities. You must query the view node for a handle of type IFXUnknown, and then place that handle into the palette, as follows:
IFXUnknown *pUnknown = NULL;
ifxResult =
pView->QueryInterface( IID_IFXUnknown, (void**)&pUnknown );
ifxResult =
pNodePalette->SetResourcePtr( uiViewID, pUnknown );
pUnknown->Release();
pUnknown = NULL;
Retrieve the World node from the Node Hierarchy Palette and use it as the parent node of the view.
View nodes can be placed anywhere in the hierarchy, but in this example the camera is connected directly off the World node.
ifxResult =
pNodePalette->Find( (char*)"World", &uiWorldID );
ifxResult =
pNodePalette->GetResourcePtr( uiWorldID, IID_IFXNode,
(void**)&pWorld );
ifxResult =
pView->SetParent( pWorld );
Set the root node of the view to be the World.
The root node of a view is the starting node of the scene branch rendered into the view and is generally set to the world node.
ifxResult = pView->SetRootNode( pWorld );
Create an IFXLightResource object.
This will contain all the data for the light, including color.
ifxResult = IFXCreateComponent( CID_IFXLightResource, IID_IFXLightResource, (void**)&pLightResource );
Initialize the light resource.
ifxResult = pLightResource->Initialize( pSceneGraph );
Set the light data values.
IFXSGVector colorWhite(
1.0f, 1.0f, 1.0f );
ifxResult =
pLightResource->SetType( IFXLightResource::DIRECTIONAL );
ifxResult =
pLightResource->SetColor( colorWhite );
Add an entry into the Light Resource Palette for the new light resource.
CIFXString lightResourceName("lightresource1");
ifxResult =
pSceneGraph->GetPalette( IFXSceneGraph::LIGHT, &pLightPalette );
ifxResult =
pLightPalette->Add( &lightResourceName, &uiLightResourceID );
Initialize the new palette entry with the light resource.
ifxResult = pLightPalette->SetResourcePtr( uiLightResourceID, (IFXUnknown*)pLightResource );
Create an IFXLight object.
This object sits in the scene hierarchy and determines the lights position and direction.
ifxResult = IFXCreateComponent( CID_IFXLight, IID_IFXLight, (void**)&pLight );
Initialize the light.
ifxResult = pLight->Initialize( pSceneGraph );
Set the light to use the light resource created above.
This creates the scene link between the light and the light resource.
ifxResult = pLight->SetLightResourceID( uiLightResourceID );
Set the parent of the light to be the World. As with all nodes, Light nodes can appear anywhere in the scene hierarchy.
ifxResult = pLight->SetParent( pWorld );
Add an entry into the Node Hierarchy Palette for the new Light node.
CIFXString lightName("directionallight1");
ifxResult =
pNodePalette->Add( &lightName, &uiLightID );
Initialize the new palette entry with the Light node.
ifxResult = pNodePalette->SetResourcePtr( uiLightID, (IFXUnknown*)pLight );
Each Model Resource contains both an IFXMeshGroup, and a Style Palette. The IFXMeshGroup is a group of IFXMeshes, each of which is a collection of faces in the model having the same material. Each mesh is identified by its index in the mesh group. This ID value corresponds to an entry in the Style Palette associated with the model. The Style used to render a Model Resource is defined by an entry in the Model node in the Node Hierarchy Palette, which provides the index in the Model Resource's Style Palette of the Style to be used.
Index the materials in a model from 0 to (n-1), where n is the number of materials in the model.
This zero-based index is used to identify face materials when building an IFXAuthorMesh.
When all the IFXAuthorMesh structures are created and placed into an IFXAuthorMeshGroup object, create an IFXAuthorGeomCompiler.
Use the IFXAuthorGeomCompiler to produce a Model Resource object for the given IFXAuthorMeshGroup object.
ifxResult = pAuthorGeomCompiler->Compile( pAuthorMeshGroup, NULL, NULL, &pModelResource );
A Style object must be created for the new Model Resource and placed in the Style Palette. To do this, all the materials and textures used for each shader must be inserted into their respective palettes.
Create and insert each Material into the scenegraph's Material Resouce Palette.
ifxResult = IFXCreateComponent( CID_IFXMaterialResource, IID_IFXMaterialResource, (void**)&pMaterialResource );
ifxResult = pMaterialResource->Initialize( pSceneGraph );
ifxResult = pMaterialResource->SetAmbient( MATERIAL_AMBIENT_COLOR );
ifxResult = pMaterialResource->SetDiffuse( MATERIAL_DIFFUSE_COLOR );
[... continues through all material attributes ...]
ifxResult = pSceneGraph->GetPalette( IFXSceneGraph::MATERIAL, &pMaterialPalette );
ifxResult = pMaterialPalette->Add( MATERIAL_NAME, &uiMaterialID );
ifxResult = pMaterialPalette->SetResourcePtr( uiMaterialID, (IFXUnknown*)pMaterialResource );
Create and insert each Texture into the scenegraph's Texture Resource Palette.
Create a Shader for each mesh in the Model Resource.
Each Shader is initialized with the Material Resource Palette ID of the Material to be used, plus the Texture Resource Palette IDs for any associated Textures. A Shader has a set of flags that determine what parts of the Shader (channels) are to be used. In the case of a simple material shader, only the Material flag is set.
ifxResult =
IFXCreateComponent( CID_IFXShaderLitTexture, IID_IFXShaderLitTexture,
(void**)&pShader );
ifxResult =
pShader->Initialize( pSceneGraph );
ifxResult =
pShader->SetMaterialID( uiMaterialID /*Palette ID of material
created in 3a*/ );
ifxResult =
pShader->SetTextureID( TEXTURE_CHANNEL, TEXTURE_ID );
[... continues through
all enabled/existing texture channels ...]
ifxResult =
pSceneGraph->GetPalette( IFXSceneGraph::SHADER, &pShaderPalette
);
ifxResult =
pShaderPalette->Add( SHADER_NAME, &uiShaderID );
ifxResult =
pShaderPalette->SetResourcePtr( uiShaderID, (IFXUnknown*)pShader );
Create and initialize the Style object using the Shader Palette IDs for each Shader used to render each mesh contained in the Model Resource.
ifxResult =
IFXCreateComponent( CID_IFXStyle, IID_IFXStyle, (void**)&pStyle );
ifxResult =
pStyle->Initialize( pSceneGraph );
ifxResult =
pStyle->SetShaderID( MESH_ID, ASSOCIATED_SHADER_ID );
[... continues for each mesh in the
associated Model Resource ...]
IFXModelData *pModelData
= pModelResource->GetModelData();
ifxResult =
pModelData->GetStylePalette( &pStylePalette );
ifxResult =
pStylePalette->Add( STYLE_NAME, &uiStyleID );
ifxResult =
pStylePalette->SetResourcePtr( uiStyleID, (IFXUnknown*)pStyle );
Initialize the Model Node to specify the Style to be used with the Palette ID of the new Style object. In this instance, when the scenegraph renders the model represented by the Model Node, it will use the Style created to color/texture the Model Resource.
ifxResult = pModel->SetStyleID( uiStyleID );
The scene is complete with these elements in place:
One Directional light, white, pointed down the Z axis (directly into the view)
One Camera
One Model, rendered using Style with ID 1
§See asterisked (*) statement at Legal Information © 2001 Intel Corporation.