Most of the time 3D nodes represent real world objects, like a screen, or a body part, like a user's head, hand, or eyes (ie cameras).
In the 3D nodes view, you can configure what your VR system looks like "in the real world" : what body parts of your user you're tracking, where are the screens located, how they're seeing the virtual world.
3D nodes are stored as a tree structure. Each node can have many children but only one parent. This hierarchy can be used to represent a user's body and the natural relationship between its body parts. If I move my body, all my body parts are moving with me. If I move my arm, my hand will also move, etc.
Each node has a position and orientation in space with respect to its parent, represented by their X/Y/Z and Yaw/Pitch/Roll properties in Local and World space.
The world position and orientation of a node are computed by combining the transformation (position and orientation) of all its parents. This result is represented as the PositionWorld and OrientationWorld properties. The OrientationWorld read-only property is represented as a Quaternion, whereas the editable orientations are represented as Euler angles. Internally MiddleVR uses quaternions.
There are several types of 3D nodes.
Regular 3D node: this object only represents a reference frame in space. This reference frame can be interpreted how you want. It could be a body part, or a tracking system's base that you use as a reference.
Camera: a view of the world.
Stereoscopic camera: a stereoscopic (S3D) view of the world.
Screens: a physical display surface.
You can create 3D nodes by clicking on the '+' button. You will be presented with a window to choose which 3D node you want to create :
Choose the type of node you want to add and press Add.
Note: The new node will automatically be added as a child of the currently selected node.
A 3D node has several properties that you can modify in the configuration tool.
Table 5.7. 3D Nodes properties
|Name||The name of the 3D node. The name can be used to find a particular node.|
|Tag||A tag is a word representing a semantic information. For example a node can have a "Hand" tag. Another node can also have the same "Hand" tag. You can then find all the nodes that have this particular tag, or behave in a certain way when you find a node with this tag. For example some objects would only react if they are touched by a 3D node that has the "Hand" tag.|
|Parent||The parent is another 3D node. The parent can not be a child of the node.|
|Tracker||When a 3D node has a tracker assigned to it, the position and orientation data of the tracker will automatically be applied to the local position and orientation of the node.|
|X,Y,Z Local||The local position of the node with respect to its parent coordinate system. In meters. Disabled if the node has a Tracker.|
|PositionWorld||The world position, taking into account all the parents' cumulated transforms. In meters.|
|Yaw,Pitch,Roll Local||The local orientation of the node with respect to its parent coordinate system. In degrees. Disabled if the node has a Tracker.|
|OrientationWorld||The world orientation, taking into account all the parents' cumulated transforms, represented as a quaternion.|
A 3D node also has some advanced properties.
Note: The UseTrackerX/Y/Z/Yaw/Pitch/Roll options are only available when the Tracker of the node is not Undefined.
Table 5.8. 3D Nodes advanced properties
|IsFiltered||Filters the data applied from the tracker by using the "One Euro Filter". Enabled only if the node has a tracker. More info: http://www.lifl.fr/~casiez/1euro/|
|CutOffFrequency||Appears only if the filter is active. The "One Euro Filter" is mainly a low-pass filter, which means it reduces the movement jitter of frequencies higher than the cutoff frequency. The default value is 1Hz. The closer you go to 0 Hz, the smoother the movements are, and the higher the lag is.|
|Reactivity||Appears only if the filter is active. Depending on the "Cut Off Frequency" value, the "One Euro Filter" can add some lag to the movement. The "Reactivity" parameter is a scalar value to reduce this lag. You can find more details about this parameter in the filter calibration procedure below. Start from '0' where no reactivity is added and make this value slowly grow to have the best results without bringing back too much jitter.|
|X,Y,Z World||The world position of the node. In meters. Disabled if the node has a Tracker.|
|Yaw,Pitch,Roll World||The world orientation of the node. In degrees. Disabled if the node has a Tracker.|
|UseTrackerX||Applies the X information from the tracker to the node if checked.|
|UseTrackerY||Applies the Y information from the tracker to the node if checked.|
|UseTrackerZ||Applies the Z information from the tracker to the node if checked.|
|UseTrackerYaw||Applies the Yaw information from the tracker to the node if checked.|
|UseTrackerPitch||Applies the Pitch information from the tracker to the node if checked.|
|UseTrackerRoll||Applies the Roll information from the tracker to the node if checked. (Did you guess?)|
You can calibrate a 3D node to have a neutral position and/or orientation. What does it mean ?
It means that:
- its world position is (0,0,0),
- the node orientation is neutral: it is facing the Y axis, with its right looking at the X axis, and up looking at the Z axis.
Note: Only a node without a tracker can have its transformation calibrated. If your node has a tracker, you can either use "Calibrate Parent", or create a child node that you can calibrate
MiddleVR offers different ways of calibrating a node:
- Set Neutral Transformation: This action will set a local transformation such that the world transformation is neutral.
- Set Neutral Position: This action will set a local position such that the world position is (0,0,0), without impacting the orientation.
- Set Neutral Orientation: This action will set a local orientation such that the world orientation is neutral, without impacting the position.
- Calibrate Parent: This action is different from the three others. It will modify the node's parent's transformation so that the current node's transformation is neutral. See below for more information.
The Reset Transform will reset the local transformation of the selected node.
The "Calibrate Parent" action is particularly useful when the parent represents the origin of a tracker (tracker's base), for example the Razer Hydra's base, a Kinect or a camera.
If you want the nodes to be correctly positionned in world space, you have to place the camera node correctly. This can be a tedious task to do manually: you have to measure the distance from the center of world space as well as the correct orientation.
If you set a tracked object at the center of the physical world, with a neutral orientation in the real world, you will notice in MiddleVR that the corresponding node is probably not at a neutral place/orientation.
You can simply select this node in MIddleVR and choose "Calibrate Parent". This will automatically set the transformation of the parent so the selected node gets a neutral transformation. You will also notice that the parent now has a position/orientation corresponding to the physical position/orientation of the tracker's base in world space.
Here is a simple two-step procedure proposed by the authors of the "One Euro Filter" to set the two filter parameters to minimize jitter and lag when tracking human motion:
- First 'Reactivity' is set to 0 and 'CutOffFrequency' to a reasonable middle-ground value such as 1 Hz. Then the body part is held steady or moved at a very low speed while 'CutOffFrequency' is adjusted to remove jitter and preserve an acceptable lag during these slow movements.
- Next, the body part is moved quickly in different directions while 'Reactivity' is increased with a focus on minimizing lag.
Note that parameters 'CutOffFrequency' and 'Reactivity' have clear conceptual relationships: if high speed lag is a problem, increase 'Reactivity'; if slow speed jitter is a problem, decrease 'CutOffFrequency'.
Regular cameras in 3D engines are said to be symmetrical: to compute a correct perspective, they suppose that the viewer is always exactly in front of the center of the screen :
The particularity of a VR camera is that it can be assigned a screen.
A screen is exactly like a window to the virtual world. Once the camera is associated with a screen, its view frustum (pyramid of vision) is always totally constrained by this screen. This means that the view is dependent on the position of the camera but also on the position of the screen. At this point, if the user is not exactly facing the center of the screen, the view frustum will not be symmetrical: the camera is said to be asymmetrical.
In the following pictures, the screen is represented as a grey rectangle. Notice how the camera frustum always matches the screen :
If the camera or the screen moves, the camera frustum will always match the screen.
This is exactly as if you're looking through a window : if the camera is close to the screen, it's like when you stand close to a window : you see a lot of the outside world.
When you go away from the window, your field of view gets narrower. When you move left or right, you see a different part of the world.
Note: When a camera is assigned a screen, its orientation is always constrained to face the normal of the screen.
A screen can be assigned to multiple cameras.
Table 5.9. Camera properties
|VerticalFOV||Vertical field of view, in degrees.|
|Near||The near clipping plane distance.|
|Far||The far clipping plane distance.|
|Screen||Assign a screen if you want asymmetrical cameras.|
|UseViewportAspectRatio||Does this camera use its own AspectRatio or should it use the aspect ratio of its viewport ? Disabled if the node has a Screen.|
|AspectRatio||The aspect ratio of the camera. Disabled if the node has a Screen or if UseViewportAspectRatio is true.|
To get a stereoscopic (S3D) rendering, you need to have two views of the virtual world, like your two eyes do for the real world.
Stereoscopic camera automatically create two cameras, a left and a right camera, as children. Those cameras will act as if there was a screen placed at a distance specified by the "Screen Distance" property. The size of the screen is determined by the screen distance, the field of view of the camera, and its aspect ratio.
Stereoscopic cameras inherit all camera's properties, and they add the the Screen Distance, and the Inter-Eye Distance.
The two main attributes of a screen are its position in space and its size.
Screens are assigned to cameras.
This also means that a screen can be assigned a tracker!
A screen can be assigned to multiple cameras.