Space Building Reference
Getting started with MagicaVoxel
MagicaVoxel is a free 3D pixel art creation tool that can run on Windows and Mac (or under Wine on Linux). It is currently the only way to build content for Cyberdoof.
- First you need to download and install from ephtracy.github.io
- If you are installing on a Mac and experience a blank screen when first opening, follow these instructions to fix
- If you want to jump straight in, download a template space from the publish page, and open it in MagicaVoxel and have a play around
- However, you'll probably want to watch some tutorial videos about how the software works. Check out these awesome tutorials by Pedro Casavecchia
- Once you have something you want to try out in Cyberdoof, click Host Party and under Upload Custom Space select Choose File and browse to your MagicaVoxel project
Building at correct scale
Cyberdoof uses a fixed scale of 10 voxels (volumetric pixel or vx) per meter. This means that a single voxel in your build will be equivalent to 10cm world size.
The maximum build size supported by MagicaVoxel is 2048vx wide by 2048vx deep by 1024vx high. Cyberdoof also supports up to this size, however depending on build density, you may encounter performance issues on builds this size. Please email hello@cyberdoof.com to report any such issues.
Adding video screens and audio sources
To create a screen:
- Create an object inside of MagicaVoxel (using + button in world view)
- Select this object by double-clicking and then change the dimensions of the object and position where you want the screen to be (the actual voxel content will be ignored and replaced with a box with video on all sides)
- Find the object using Project > Show Scene Outline
- Name the object with prefix
video:
followed by whatever you would like the target to be named inside of the Cyberdoof Stream Panel (e.g.video:Main Screen
)
Adding an audio source is very similar:
- Name the object with prefix
audio:
followed by whatever you would like the target to be named inside of the Cyberdoof Stream Panel (e.g.audio:Stage
) - Unlike a video target, this object will render normally, except you will be able to stream spatial audio from the position. You can choose to leave it empty or make an object design that represents an audio source (e.g. speaker)
Lighting and atmosphere
Cyberdoof tries to match the sky, sun position and lighting of your MagicaVoxel scene as much as possible. However, since they use very different rendering systems, there will be a number of differences that will require experimentation to get just right.
The following environment and scene options are supported:
- Sun Angle and Intensity
- Sky modes Uniform (intensity and color) and Atmospheric Scattering (most of the parameters work but will look a bit different and more stylized in Cyberdoof)
- Display Settings > Ground Color and Ground Material (Alt+Click on ground in Render Mode to edit material)
- Fog Density (this effect is quite different in Cyberdoof, so you'll need to experiment to get the desired result in your space)
- Color palette materials Metal and Glass materials have limited support (the individual settings don't do anything right now, but selecting metal will make things shiny and glass will make it semi-transparent)
- If ground material is set to Metal, the ground will be rendered and treated as water (including ripples, reflection and swimming avatars)
Emissive materials cast light much like they do in MagicaVoxels and you can set the brightness of the light source using Emission option. However there are some major differences:
- Cyberdoof uses a simplified lightfield model where light has volume but not direction (whereas MagicaVoxel does full raytracing for all emissive materials).
- The power (radiant flux) option functions as a control of how far the light will travel (whereas in MagicaVoxel it's an exponential multiplier of the emission value)
If you want to add a little extra atmosphere, you can use the Haze object. Add an empty object to your scene, name starting with haze:
(e.g. haze:foggy area
) and position/size the object to your desired area.
On the other hand, if an area is getting too much sunlight, you can add a density volume to reduce the amount of sunlight an area receives. Add an empty object to your scene, name starting with volume/density:
(e.g. volume/density:foggy area
) and position/size the object to your desired area.
Controlling exposure
You can override the default exposure global brightness (of 1) by creating an empty object exposure=EXPOSURE_VALUE:
where EXPOSURE_VALUE
is your desired brightness multiplier. Crank it up for a dreamy bloom effect. This can also be added inside state groups to allow exposure to be controlled from states.
Overriding sun and ambient light colors
It's possible to attach the sun/sky color to a specific palette color (including palette cycle animations). These can also be set from inside states to control the skybox lighting dynamically.
skybox/sun=PALETTE_ID:
set the sunlight color to the correspondingPALETTE_ID
numberskybox/sky=PALETTE_ID:
set the ambient color to the correspondingPALETTE_ID
number
Controlling where avatars spawn
By default avatars will spawn in a random location near the center of your space. However if you prefer, you can use special objects to set locations for avatars to spawn.
- Add a new object to the scene representing the location you would like avatars to spawn
- Find the object using Project > Show Scene Outline
- Name the object
spawn:default
(the namedefault
is needed if you want users to spawn here when joining, however spawn points can also be named other things and can be used in conjunction with respawn zones and entity teleports) - Create as many objects named
spawn:default
as you like -- when people join using the invite link, they will spawn randomly at one of these locations - For advanced control, spawn points can be placed inside state groups to make them only active in certain conditions
Making interactive and wearable items
Turning an object into an item is much like adding other types of special objects:
- Find the object using Project > Show Scene Outline
- If you just want to go with the defaults, add
item:
to the start of the objects name- The text after
item:
will appear to guests when they hover their mouse over the item (e.g.item:Magical Sword
) - this item will attach to your hand by default, but can be moved to head or back
- it will be scaled to half of the voxel size (so it will appear oversized in MagicaVoxel)
- The text after
Add a /type
option to customize the item behavior:
item/stick:
hold the item like a glowstick and wave it arounditem/glove:
item wraps around hand and can be waved arounditem/lantern:
the avatar will hold the item up in front of them like a lanternitem/helmet:
the item will cover the entire head of the avatar like a helmet and be attached to head by defaultitem/neck:
the item will be centered on the neck and be attached to head by defaultitem/face:
the item will attach to the face of the avatar like a mask (and can be placed on walls)item/backpack:
item is attached to avatar's back by default (and can be placed on walls)item/wall:
a regular item but can be attached to wallsitem/fixed:
a regular item but cannot be picked upitem/costume:
attaches to the center of an avatar and can be used to put the avatar inside a larger objectitem/jetpack:
attaches to back by default, emits fire emoji and allows avatars to fly whenspawn=grounded
option activeitem/vehicle:
avatar will sit inside the item (so make it bigger than the avatar) and will be able drive around the spaceitem/magic:
attached avatar will become weightless, glow and hue shiftitem/unlock-KEYNAME:
item can be used to unlock activation of matchingunlock-KEYNAME
buttons
Items default to 0.5
size, however you can set any scale you want using =SCALE
option
- e.g. if you want to scale to one quarter you would name your object
item=0.25:Display Name
- if you want to set the scale and an item type, you'd do this:
item/lantern=0.1:Display Name
Adding animations
- Open the notes panel by clicking the â–¶ twirl button under Palette on the far left of MagicaVoxel's user interface
- Setup the 8 colors you want as part of your cycle on any row in the palette
- Use these 8 colors as slots in your scene, with each color in the row acting as a step offset in the cycle
- Add a note on the chosen row:
cycle:
cycle in order through your 8 colorsrandom:
cycle randomly through your 8 colorsfreeze:
no animation- these more advanced animations are best used with multiple cycle columns in your scene:
offset:
animates filling all slots with the same color before moving to next color in sequence, best used withchase:
cycles through each slot only allowing one to be emissive at a time (like a light chase)
- If you want to add a fade to the animation:
- add
/fade
for smooth transition between colors (e.g.cycle/fade:
) - or
/ping
for emissive flashing ramp effect (e.g.cycle/ping:
)
- add
- Step duration time defaults to 500 ms, but you can change this adding an
=DURATION_MS
option- e.g.
cycle/fade=2000:
for 2000 ms (2 second) delay between animation steps with fade - e.g.
cycle=50:
for 50 ms (0.05 second) delay between animation steps
- e.g.
You can also control palette cycle animations from state
groups. This allows you to override any property of the cycle including its mode and color ids.
palette=1,2,3,4,5,6,7,8:CYCLE_NAME
: override the palette colors for the cycle (can be any number of palette ids too, not restricted to 8)palette/sequence=SEQUENCE_TYPE:CYCLE_NAME
: override the palette sequence,SEQUENCE_TYPE
can becycle
,random
,freeze
,offset
orchase
(see above)palette/mode=MODE_NAME:CYCLE_NAME
: override the cycle mode,MODE_NAME
can beswitch
,fade
orping
(see above)palette/duration=DURATION_MS:CYCLE_NAME
: override the step duration,DURATION_MS
can be any number in milliseconds representing the duration of each step (see above)
Space Interactivity with Object States
You can create states that can be toggled by avatars in your space by clicking specified objects. All objects in a specially named group will show/hide depending on if the state is active.
- place objects inside a group named
state/on:STATE_NAME
to only show when the state is active - place objects inside a group named
state/off:STATE_NAME
to only show when the state is inactive - name an object
button/on=STATE_NAME:BUTTON_NAME
to activate the state namedSTATE_NAME
when used - name an object
button/off=STATE_NAME:BUTTON_NAME
to deactivate the state namedSTATE_NAME
when used - name an object
button/toggle=STATE_NAME:BUTTON_NAME
to toggle the state namedSTATE_NAME
when used
If you want a state to be active by default, you can add an empty object named default/state=on:STATE_NAME
.
You can control whether or not the space has ground in a state by adding a ground/solid:
, ground/water:
, or ground/none:
empty object inside a state group.
Set the default of a state to on using default/state=on:STATE_NAME
.
Conditional buttons based on held items
If you want to allow a state to only be unlocked when specific items are held, you can use unlock
buttons and items. These work the same as normal buttons (with all the same sub types like on
, off
, toggle
etc) except they can only be activated when specific item types are held. The item is removed from the space when the button is triggered.
- create an object to act as the "button" called
unlock-KEYNAME/on=STATE_NAME:BUTTON_TEXT
whereKEYNAME
matches the class of item you want to allow unlocking andSTATE_NAME
/BUTTON_TEXT
same as normal buttons - create your key item named
item/unlock-KEYNAME:ITEM_NAME
whereKEYNAME
matches the same text as the button you want to unlock- it is not currently possible to choose specific item types in addition to it being an
unlock
- it is not currently possible to choose specific item types in addition to it being an
Grouping state changes together with actions
It's also possible to have buttons trigger actions instead of just toggling states.
- create any number of
action
objects (these can be nested inside of other states) and name them somethingaction/toggle=STATE_NAME:ACTION_NAME
action/off=STATE_NAME:ACTION_NAME
action/on=STATE_NAME:ACTION_NAME
- then make a button
button/action=ACTION_NAME:BUTTON_TEXT
You can also make actions that cycle through a set of states turning them on one at a time each time the action is called:
action/next=STATE_1,STATE_2,...:ACTION_NAME
Actions can be inside of other states to make them only trigger when another state is active.
State transitions
You can add one or more effects to make state transitions more interesting. Add any of these inside of the state group:
transition/move=X,Y,Z,DURATION_MS:
(you can also add an additional fourth paramEASE_MODE
that can beeasein
,easeout
oreaseinout
)transition/rotate=X,Y,Z,DURATION_MS:
transition/flash:
transition/group-shake=GROUP_NAME:
(you can make all the objects inside a group namedgroup:GROUP_NAME
shake when this state activates)
Emoji emitters
Add emoji emitters to your space, create an empty object named emitter=EMOJI_NAME:NAME
where EMOJI_NAME
is the shortcode of the emoji.
You can use emitters in combination with Object States (see above) for momentary effects when a state is toggled on or off.
emitter/puff=EMOJI_NAME:NAME
could be used to create a door closing effectemitter/rush=EMOJI_NAME:NAME
could be used to create a whoosh effect (like an airlock breach)
If the emoji aren't travelling the way you want, rotate the object and the emitter direction should follow.
Models: More control over object scaling
By default, all objects in your space will display with a 10 voxels per meter. Some special objects such as entities and items default to half that but that can be overridden using the scale parameter.
However, if you want to add higher resolution objects that are not entities or items, you can use model
and instance
objects to fit things exactly to a specific size.
Create a model:OBJECT_NAME
object with your full resolution object, then use an instance=OBJECT_NAME:
object to reference the model. Your instance object can be any size, and the model will be shrunk to fit inside the bounding box.
If you want your instance to be solid or emit light, you'll need to add voxels to the instance object. These will not be visible in the world, but their effects will be. This means you can have a high res object that still can be climbed on and emit light.
Using models to customize the skybox
You can also use model
objects with the skybox
object.
- create a 256x256x256 object named
model:SKYBOX_OBJECT_NAME
and paint on the outer walls how you would like your skybox to look- if you want to ignore sun/ambient light on your skybox you can use
model/unlit:OBJECT_NAME
- if you want to ignore sun/ambient light on your skybox you can use
- reference this model in an empty object named
skybox/model=SKYBOX_OBJECT_NAME:
and now your model will be scaled up to encompass the entire world. - you can scale it up even further using
skybox/scale=SCALE_MULTIPLIER:
whereSCALE_MULTIPLIER
defaults to be1
and can be as high as32
- when ground is enabled in your space, the skybox will anchor to the bottom by default, or center if ground is hidden -- you can override this using
skybox/anchor=ANCHOR_POSITION:
whereANCHOR_POSITION
is eithercenter
orbottom
Entities
Entities are animatable objects in your space. They can represent characters or vehicles, animals, whatever you want. They can include movement speed, and animation frames. They're a lot like items except they can't be picked up. Instead, their positions are animated by changing states.
You can create an entity in your space by creating a group with the name entity:YOUR_ENTITY_NAME
containing the following objects:
- Any number of
frame:FRAME_NAME
objects -- these represent the animation frames for the entity that are displayed in the world, however you need to add them to an animation to actually see these - Any number of
animation=FRAME_NAME_1,FRAME_NAME_2,...:ANIMATION_NAME
objects. You can name the animationdefault
if you want it to be what plays when no other animation is selected. e.g.animation=dance_1,dance_2:default
for a default 2 frame animation with 200 ms frame duration and a movement speed of 2m/s.
As an alternative to creating animation
and frame
objects, you can also just group many objects together and name the group animation:ANIMATION_NAME
. Make sure that the frames do not have any name specified.
For more advanced use, you can tweak the scale of the entity by adding =SCALE_VALUE
to the entity
group name. e.g. entity=0.5:cool_guy
for an entity that is rendered at half size.
Positioning and setting animations
Position your entities in world using target=YOUR_ENTITY_NAME:NAME_OF_TARGET
objects. Position and rotate these objects where you want the entities to be.
If placed inside a state group, then toggling those states on and off will update the position of the entities. You can also set the animation to something other than default by specifying the animation name as a second value e.g. target=YOUR_ENTITY_NAME,ANIMATION_NAME:NAME_OF_TARGET
, or add a third value representing an animation to play when entity is moving e.g. target=ENTITY_NAME,MOVEMENT_ANIMATION,TARGET_ANIMATION:
.
By default target
will also set the position and rotation, but if you just want to set the animation of an already positioned entity inside of a given state, you can use target/animation=ENTITY_NAME,ANIMATION_NAME:
Entity behaviors
You can customize the way the entity behaves by adding named behaviors. These can be added directly inside the entity
group as empty objects named behavior:BEHAVIOR_NAME
e.g. behavior:billboard
to always face the camera.
Here are a list of the currently supported behaviors:
behavior:billboard
: entity will always face the player camera (great for 2D sprite type effects)behavior:path-align
: entity will rotate to face the direction of movement (great for vehicles)behavior:ease-in
: adding smoothing to the beginning of movement interpolationbehavior:ease-out
: adding smoothing to the end of movement interpolationbehavior:random-sequence
: play animation frames in random orderbehavior:drop-items-on-teleport
: if the player gets teleported by the entity, they will drop all of their itemsbehavior:performer-camera
: when attached to a live performer, the entity position and rotation will be overridden to match attached performer camera
If you want a behavior to only be active for a specific animation, you can use the animation
group and add specific behaviors inside the group.
Linking an entity to a performer
It's possible to link an entity directly to a performer so that the performer can chat and control the entity from the Performer View. This is done when adding the performer and selecting "Link To Entity" option.
When this is enabled (and the performer is live), all of the entity's animations will be listed in the Performer View and can be switched at will.
It's also possible to expose other states to be toggled directly by the performer by adding any number of performer-state:STATE_NAME
empty object directly inside of the entity
group (where STATE_NAME
is the name of the state group you want to allow the performer to toggle). These will then also show up as checkboxes in the Performer View.
Optimizing your space
zone/show:ZONE_NAME
any objects inside this group will not be rendered if you are inside of another group (e.g.zone:OTHER_ZONE_NAME
)zone/hidden:ZONE_NAME
any objects inside this group will not be rendered unless you are actually inside the group
And then you can create portal zones to join multiple zones together:
zone/show=OTHER_ZONE_NAME:ZONE_NAME
will link these two zones together, if you are inside one, the other will still be visible.
Customize collisions, climbable surfaces and other special object types
collider:
makes the vox fully solid regardless of what is in it (invisible walls!)no_collider:
makes the entire vox not solid (opposite of collider)climbable:
makes an object's vertical surfaces climbable (good for ladders, vines etc)slippery:
makes any slope on an object unclimbable, the avatar will slide down whenever attempting to walk/jump up surfacehidden:
makes the object invisible in the space (useful for when you want to temporarily hide something in your scene)
You can also do some more advanced stuff with zones
Make an empty object to cover the area where you want to affect. then name it zone/
zone/weightless:
no gravity in this areazone/gravity:
only gravity in this area (everywhere else avatars will be weightless)zone/respawn:
avatars entering this zone will immediately teleport to one of the default spawn pointszone/respawn=SPAWN_NAME:
avatars entering this zone will immediately teleport to a named spawn pointzone/allow:
if this zone is present, any avatar venturing outside of this zone will be teleported to the current default spawn point
You can also put these zones inside state
groups to allow them to be turned off and on.