# Spatial

This is an introduction to the concept of Spatials, the elements of the 3D scene graph. The scene graph is a data structure that manages all objects in your 3D world. For example, the scene graph keeps track of the 3D models that you load and position. When you extend a Java class from com.jme3.app.SimpleApplication, you automatically inherit the scene graph and its rootNode.

The rootNode is the central element of the scene graph. Even if the scenegraph is empty, it always has at least its rootNode. All other Spatials are attached to the rootNode in a parent-child relationship. If you think you need to understand the scene graph concept better, please read Scenegraph for dummies first.

## Node versus Geometry

In your Java code, a Spatial is either a com.jme3.scene.Node or a com.jme3.scene.Geometry. You use the two for different purposes:

| com.jme3.scene.Spatial
Purpose: | A Spatial is an abstract data structure that stores transformations (translation, rotation, scale) of elements of the scene graph. Spatials can be saved and loaded using the AssetManager.
| com.jme3.scene.Geometry | com.jme3.scene.Node
Visibility: | A Geometry represents a visible 3-D object in the scene graph. | A Node is an invisible "handle" for a group of objects in the scene graph.

Purpose:

Use Geometries to represent an object's looks: Every Geometry contains a polygon mesh and a material, specifying its shape, color, texture, and opacity/transparency.
You can attach a Geometry to a Node.

Use Nodes to structure and group Geometries and other Nodes. Every Node is attached to one parent node, and each node can have zero or more children attached to itself. When you transform a parent node, all its children are transformed as well.

Content: | Transformations; custom user data; mesh, material; | Transformations; custom user data; no mesh, no material.
Examples: | Box, sphere, player, building, terrain, vehicle, missiles, NPCs, etc… | The rootNode, the guiNode, an audio node, a custom grouping node, etc…

You never create a Spatial with `Spatial s = new Spatial();`! A Spatial is an abstract concept, like a mammal (there is no actual creature called "mammal" walking around here). You create a Node, or load a Geometry object. Some methods however require a Spatial argement: This is because they are able to accept both Nodes and Geometries as arguments. In this case, you must cast a Node or Geometry to Spatial.

### Mesh

The polygon Mesh inside a Geometry can be one of three things:

- Shapes: The simplest type of Meshes are jME's default Shapes such as cubes and spheres. You can use several Shapes to build complex Geometries. Shapes are built-in and can be created without using the AssetManager.
- 3D Models: 3D models and scenes are also made up of meshes, but are more complex than Shapes. You create Models and Scenes in external 3D Mesh Editors and export them as Ogre XML or Wavefront OBJ. Use the Asset Manager to load models into a your jME3 game.
- Custom Meshes: Advanced users can create Custom Meshes programmatically.

## How to Add Fields and Methods to a Spatial

You can include custom Java objects in Nodes and Geometries. This is useful for maintaining information about a game element, such as health, budget, ammunition, inventory, equipment, etc for players, or landmark locations for terrains, and much more.

You do not need to create a custom class that extends Node or Geometry to be able to add custom fields to a spatial – use the setUserData() method instead. Neither do need to create a custom class that extends Node to be able to add custom accessor methods to this spatial – use a Control instead. Where ever the spatial is accessible, you can also access the object's game data and accessors.

For example when you initialize your custom PlayerControl class:

    // init custom data fields in this Control's Spatial (Node or Geometry)
    spatial.setUserData("Health", 100);

In your PlayerControl, you offer accessors that manipulate and get this custom data:

    public int getHealth() {
      return (Integer)spatial.getUserData("Health");
    }
    public void setHealth(int h) {
      spatial.setUserData("Health",h);
    }

Elsewhere in your code, you can access this data wherever you have access to the spatial.

    health = player_node.getControl(PlayerControl.class).getHealth();
    ...
    player_node.getControl(PlayerControl.class).setHealth(99);

You can add as many data objects (including Strings, Integers, Floats, Arrays,) to a Spatial as you need. Just make sure to label them with different Strings (`health`, `inventory`, `equipment`, etc). The saved data can also be custom Java objects if you make the Java class implement the Savable interface. When you save a Spatial as a j3o file, the custom data is saved too, and it will be restored the next time you load the j3o!

You can list all data keys that are already defined for one Spatial:

    for(String key : spatial.getUserDataKeys()){
          System.out.println(spatial.getName()+"'s keys: "+key);
    }

## How to Access a Named Sub-Mesh

Often after you load a scene or model, you need to access a part of it as an individual Geometry in the scene graph. Maybe you want to swap a character's weapon, or you want to play a door-opening animation. First you need to know the unique name of the sub-mesh.

1. Open the model in a 3D mesh editor, or in the jMonkeyEngine SDK's Scene Composer.
2. Find out the existing names of sub-meshes in the model.
3. Assign unique names to sub-meshes in the model if neccessary.

In the following example, the Node `house` is the loaded model. The sub-meshes in the Node are called its children. The String, here `door 12`, is the name of the mesh that you are searching.

    Geometry submesh = (Geometry) houseScene.getChild("door 12");

view online version