<What is a Scene Graph?|User's Guide|Batches>

Spatial

See Javadoc

Definition

Spatial defines the base class for all elements in the scene graph. There are two major types of Spatials (Geometry and Nodes). These derive from Spatial and will be covered in detail in other sections, but in general terms, Geometry maintains leaf nodes, while Node maintains parent nodes (or internal nodes). So, Geometry maintains actual graphical data, while Node maintains the scene graph elements.

The Spatial class manages a link to a parent, local and world transforms, and world bounding volumes. It also maintains the list of RenderStates as well as Controllers.

This is the foundation upon which jME is built. This class defines how a scene can be built.

Scene Management

As Spatial makes up the basis of the scene graph, it is responsible for managing the important data elements of the scenegraph. The leaf elements, Geometry, contain the data for rendering, but all other elements maintain the orientation and location in the world as well as the BoundingVolumes that contain the data. These two elements transforms and boundings) are arguably the most important in the scene graph. The scene graph information is built in two passes, a downward pass to propogate transforms and an updward pass for boundings.

Transform Pass

Spatial's updateWorldData propogates from the root node down to each leaf node. Each parent updates its: Translation, rotation and scale (adjusted by the parent) and then calls the updateWorldData on the children. This allows the transforms to be inherited down the tree.

Bounding Pass

Spatial's updateWorldBound method starts at the leaf nodes, working up the tree to the root node. Each Node merges the boundings of its children into a single all encompassing bounding.

Updating

There are a number of update methods contained in Spatial. These methods handle “building” and optimizing the scene graph. In most cases, you will only call updateGeometricState, as this method takes care of setting up the scene graph completely. In most situations, calling updateGeometricState on your root node will be all you need to do.

However, if you desire better control, you can call updateWorldBounds and updateWorldVectors individually. updateWorldBounds will transform the bounding of the Spatial into world coordinates as well as any necessary updates (what these updates are depends on the subclass, Geometry or Node).

Now, when would you want to call these update methods? The easy answer (especially if you plan on just using updateGeometricState) is whenever you've changed a node. This means changing its rotation, location and/or scale. So, moving a Spatial will require an update call. It should be noted that transforming a Node should invoke both calls to update the world vectors as well as the bounds. This is another argument for use of updateGeometricState. However, if you change the model bounds of a Geometry, but not its position, you can make a call to updateWorldBounds instead. However, to propogate the new boundings to the root of the tree a call to propogateBoundToRoot is required. While updateGeometricState takes care of this as well.

Orientation

You can manually set the rotation value of the Spatial by calling the setLocalRotation method. However, there exist a couple convience methods to help you out.

First, lookAt will face the Spatial at a certain point in space. By supplying the point and the vector that defines the world's up vector, the Spatial will be rotated to face this point.

Secondly, rotateUpTo allows you to supply a vector defining the normal of the Spatial, and rotate the Spatial such that it's “up” is this normal. This is particularly useful for things such as terrain following.

Drawing

Drawing the Spatial makes use of the Renderer to display the graphics to the display. To begin the rendering process, the Renderer is obtained and the Spatial is sent to its draw method.

Renderer determines the best course of action for the object that it has just received for rendering. In the case of Spatial, it simply calls Spatial's onDraw method passing itself as the parameter.

Spatial then calculates the visibility of the Spatial. If it is visible, the draw method of the Spatial is called. Spatial defines draw as an abstract method, therefore, the subclasses handle this call differently. In the case of Node, the children's onDraw method is called, while Geometry applies the RenderStates and TriMesh then draws its data to the display.

So, the steps are as follows:

  1. Renderer's draw method is called passing a Spatial as the parameter.
  2. Renderer calls the Spatial's onDraw method
  3. Spatial determines if it is visible
  4. If so, it calls its own draw method
  5. If the subclass is a Node go to 2, if subclass is Geometry go to next.
  6. Apply render state attributes
  7. If subclass is a TriMesh, draw data to screen.

Culling

During each call to onDraw the Spatial tests itself against the Camera's view frustum to determine its visibility. The world BoundingVolume of this Spatial is used for comparison.

RenderStates

RenderStates define how an image will be rendered to the screen. These states are maintained by Spatial (as well as the Geometry subclass). Spatial maintains two static arrays of RenderStates, and one instance array.

defaultStateList is a static array that contains all the default RenderStates. Where default is the state being disabled. If nothing is specified for this Spatial and the Spatial does not inherit a parent's state this default is used.

currentStates is a static array that defines the current OpenGL state list. That is, the state of OpenGL. This is useful for minimizing state changes (which can be very costly). If the current state is the same as a state we want to switch to, we don't switch.

renderStateList holds unique RenderStates for this Spatial. That is, any render state defined for this Spatial using setRenderState is stored here.

Geometry also maintains a RenderState that defines the final states for the leaf node. This final state is a combination of inherited, unique, merged and default states. More detail can be found in the Geometry entry.

When placing Spatials into the Scene graph you should call updateRenderStates in order to properly inherit the parent's RenderStates.

Controllers

Spatial maintains a list of Controllers that define any action the Spatial is to perform during a given frame. During a call to updateGeometricState the list of controllers are iterated through and their respective update methods are called. To add a Controller to the Spatial call the addController method. Similarly, removal is removeController.

Intersections

Chapter 8 will cover picking and collisions in detail. However, we will cover the basics of intersections and how they are handled in Spatial. Intersection has a number of accuracy levels (BoundingVolume and Triangle accurate). If you are to use triangle accurate intersections a call to Spatial's updateCollisionTree is required. This builds an OBBTree to handle the Triangle tests.

Collisions

Collisions define the intersection of two objects (two Spatials). Three methods in Spatial allow the user to find these intersections and obtain details about them. First, findCollisions takes a Spatial to test againsts and CollisionResults to store the results. While hasCollision does not store results, but returns a boolean value if a collision has occured. Lastly, calculateCollisions will store the collisions in CollisionResults and then call the processCollisions method in the results.

Picking

Picking defines the intersection of the Spatial with a Ray object. Similar to Collisions Spatial defines a findPick method that takes a Ray and PickResults. While calculatePick will process the PickResults.

Misc. Settings

ZOrder

ZOrder is used for the Orthographic mode of the RenderQueue. Because items that are in ortho mode don't necessary have a physical distance between the eye and the object, a method is required to determine what items should be drawn in front of another. If no Z-Order value is set, the item in front is the last one drawn. That is, earlier objects might be overdrawn by later objects.

However, you can set the Z-Order value to define the ordering. You can think of the Z-Order as the priority of the object in the Ortho queue. Where a lower value will be drawn on top of high value objects. That is, if two Quads are drawn in ortho mode and overlap, the Quad with the lower Z-Order will be drawn on top of the other.

LightState and TextureState Combining

The LightState and TextureState is special in the way that it is combined down the scene graph. Normally, a RenderState will overwrite a parent's state. However, LightState and TextureState can combine with it's parent's to provide a cumulative effect.

Lights can combine a states until 8 lights are combined while textures can combine until the max texture units of the graphics card is reached.

Textures defer in that the graphics card ultimately defines how much combining can be done. Because, combining the texture makes use of multitexturing and individual texture units.

How these states are combined is determined by the combine mode that is set for the Spatial.

setLightCombineMode takes either:

  • OFF - Do not light this object. Ignores all lightstates.
  • INHERIT - Inherit mode from parent. This is the default mode.
  • REPLACE - Do not combine light states, just use the most recent one.
  • COMBINE_FIRST - Combine light states starting from the root node and working towards the given Spatial. Ignore disabled states. Stops combining when lights == MAX_LIGHTS_ALLOWED or no more states to combine.
  • COMBINE_CLOSEST - Combine light states starting from the given Spatial and working towards the root. Ignore disabled states. Stops combining when lights == MAX_LIGHTS_ALLOWED or no more states to combine.
  • COMBINE_RECENT_ENABLED - Similar to COMBINE_CLOSEST, but if a disabled state is encountered, it will stop combining at that point. Will also stop combining when lights == MAX_LIGHTS_ALLOWED or no more states to combine.

While the texture combine as:

  • OFF - Do not apply textures to this object.
  • INHERIT - Inherit mode from parent. This is the default mode.
  • REPLACE - Do not add any other textures to the texture units, only use this texture state.
  • COMBINE_FIRST - Combine textures starting from the root node and working towards the given Spatial. Ignore disabled states. Stops combining when the max texture units is reached.
  • COMBINE_CLOSEST - Combine textures starting from the given Spatial and working towards the root. Ignore disabled states. Stops combining when the max texture units is reached.
  • COMBINE_RECENT_ENABLED - Similar to COMBINE_CLOSEST, but if a disabled state is encountered, it will stop combining at that point. Will also stop combining when max texture units is reached or no more states to combine.

Gotchas

  • If you have made a change to a Spatial and getting strange rendering results, the most common culprit is you are not calling the appropriate update methods. We recommend calling updateGeometricState in your update method as its a low cost call. If you have changed the Renderstate of a Spatial call updateRenderStates, this is a fairly expensive call, so should be only called when needed.
  • Similarly, if you remove a Spatial from the tree, a call to updateGeometricState is required. If you add a Spatial, updateGeometricState and updateRenderState.

<What is a Scene Graph?|User's Guide|Batches>


/var/www/wiki/data/pages/spatial.txt · Last modified: 2009/07/28 18:44 (external edit)  
Recent changes · Show pagesource · Login

Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki

subscribe to jME latest jme headlines


site design by bleedcrimson designs © 2008