HDK fundamentals
Before we continue working with the HDK, we need to know some fundamentals.
Learn to fly
To navigate the scene you can use WASD + Space on your keyboard.
When mouse is in pointer lock mode, the mouse cursor is hidden and you can move the camera around by moving the mouse. Press Esc to exit pointer lock mode.
You enter fly mode by pressing V on your keyboard. In fly mode you can fly around in the scene. This way you can move freely to get a better overview of your creation.
Press Space to go up and C to go down.
Exit fly mode by pressing V again.
To fly faster you can hold down Shift.
Press R to respawn. If you have added multiple spawn points, pressing R again will cycle through them.
Press G to see avatars position and rotation. Click to copy the position and rotation to clipboard.
And lets not forget the most important key, 1 to dance.
You'll find more emotes under 2-6. Or press B for an overview of them all.
Adding an object
Pre-defined objects in HDK are called Prefabs. A prefab can consist of a single object but can also be built up by multiple objects, particles, animations and even have behaviours attached to it. All prefabs can be found in the Asset Browser (opens in a new tab).
You add a Prefab to the scene like this:
<Prefab id="cube_01" />
This will add a cube to the scene. The cube is a basic 2x2x2 cube. One unit in Hiber3D is equal to one meter, so the cube is 2x2x2 meters, 1 meter = 3.3 feet.
Unless specified, a cube is placed in the center of the scene, where the player spawns by default. That is not preferable. We want to place the cube at a specific location.
<Prefab id="cube_01" z={5} />
This will place the cube 5 units in the z-direction, which is by default in front of the avatar.
Asset Browser
In the Asset Browser you can find all the prefabs you can use in your scene. You can also find materials, sounds and environments.
Open Asset Browser (opens in a new tab)
Scene graph
HDK represents the world as a Scene graph (opens in a new tab) with HNode
as its fundamental building block. All components, such as Prefab
, are HNode
s under-the-hood. A scene graph consists of nodes where each node has exactly one parent and zero or more children. If you position, rotate or scale a node, the change will, in addition to affecting the node itself, propagate to the node's descendents. For example, when a parent node is moved, all its children (and descendents further down) are moved with it.
The scene graph is a powerful concept because it allows us to position nodes according to the current context without having to take the bigger picture into account. For example, if a chair is a child of a room and the room is a child of a house, the chair's position does not need to change if one decides to change where the room should be located inside the house, or even if the room should be moved to an entirely different house. One can "furnish" the room once independently of where the room is to be used.
Position, rotation and scale
The combination of position
, rotation
and scaling
of an object is called a transform
. You can alter the transform of a node with these properties:
x = left/right
y = up/down
z = forward/backward
rotX = euler angle rotation around x-axis (degrees)
rotY = euler angle rotation around y-axis (degrees)
rotZ = euler angle rotation around z-axis (degrees)
scaleX = scale on x-axis
scaleY = scale on y-axis
scaleZ = scale on z-axis
scale = scale uniformly on all axis
Rotations are represented as Euler angles (opens in a new tab) in degrees. But uses Quaternions (opens in a new tab) under the hood.
As a result of the scene graph, a node exists within the reference frame of its parent. This means that the transform values of a node are interpreted as relative to the node's parent.
Groups
A common use case of the scene graph is to group nodes together. This is powerful if you want to rotate, scale, move or animate an entire group of objects. You can group objects together by placing them inside of a component, such as the HNode
:
<HNode y={2} z={5} rotX={45} rotY={20}>
<Prefab id="cube_01" material="t_rainbow_02" />
<Prefab id="cube_01" material="t_rainbow_02" x={5} />
<Prefab id="cube_01" material="t_rainbow_02" x={-5} />
</HNode>
Material
To change the material of a Prefab you can use the material
property, which takes a string with the name of the material.
<Prefab id="cube_01" material="t_rainbow_02" />
Available materials can be found in the Asset Browser (opens in a new tab).
Components
HNode
and Prefab (opens in a new tab) are built-in components. Components are the building blocks of HDK. You can create your own components, but HDK also contains a number of components for handling common tasks.
More in-depth documentation about the available components can be found here: HDK React Components (opens in a new tab) and HDK React (opens in a new tab)
When you wrap an object in another component you sometimes need to move the child objects properties to the wrapping component for the desired result. This is especially the case for animations, as they are dependent on a frame of reference.
Given a Prefab like this,
<Prefab id="cube_01" z={5} rotX={45} />
When you wrap it in a component, such as Hovering
, you might need to move the child's transform properties to the component to ensure that object hovers at the right spot, and in the right way:
<Hovering z={5} rotX={45}>
<Prefab id="cube_01" />
</Hovering>
Random
A component that provides random seed context to its children.
Since we want to have the same sequence of random values every time we render the scene, we need to use a random seed algorithm. This algorithm is based on the seed value that is passed to the Random component. It will generate the same sequence of random values when given the same seed. This ensures that objects will not reposition themselves everytime you re-render the scene. If you want another set of random values, you can use a different seed value.
More info on how to use random seed and random context can be found here: Random (opens in a new tab)
Don't use JavaScript's Math.random()
function if you want consistent and predictable behavior in your scene.
Environment
All available environments can be found in the Asset Browser (opens in a new tab).
To change the environment in the render
function you can do like this:
render(<World />, { environment: 'sunrise_01' });
Debugging
Sometimes it's easy to get disoriented as you rotate and displace objects. In addition to the global positioning and rotational transformation props all components have, there is also a special attribute called showAxisMarker
that will add a three dimensional marker showing you the local orientation of the object.
<Prefab id="cube_01" rotX={27} showAxisMarker />
Several components have other similar debugging options showing, for example, the sphere of a LookAtSensor
, or the radius of Distribute
items and gaps.
It's also a good practice to tag your components with the optional name
property, and use the information when outputting debugging information.
Custom Components
Components are the building blocks of HDK. Since HDK is build on top of React, you can use all the power of React to easily create your own components. Here's an example of a component creating "Modern Art" using the random seed component (opens in a new tab).
type ModernArtProps = {
numberOfSegments?: number;
};
const ModernArt: HDKComponent<ModernArtProps> = ({ numberOfSegments = 4, ...props }) => {
const pieceOfArt = [];
const random = useRandom();
for (let index = 0; index < numberOfSegments; index++) {
pieceOfArt.push(
<Prefab
id="rounded_cube_01"
scaleX={random.range(0.5, 2)}
scaleY={random.range(1, 3)}
scaleZ={random.range(0.5, 2)}
x={random.range(-2, 2)}
y={index * 1.5}
z={random.range(-2, 2)}
rotX={random.range(-20, 20)}
rotY={random.range(0, 360)}
rotZ={random.range(-20, 20)}
material={random.fromArray(['t_sci_fi_tile_03', 't_sci_fi_tile_06', 't_metal_02', 't_metal_03'])}>
{props.children}
</Prefab>
);
}
return <HNode {...props}>{pieceOfArt}</HNode>;
};
You can then use the component like this:
<ModernArt numberOfSegments={20} />