Craft provides extended capabilities to Codea that make it much easier to create 3D scenes, physics and game logic. Craft introduces a number of new classes. These include craft.entity
, which is the basic building block of 3D scenes.
Several systems are introduced, including:
craft.scene
- The core class in craft, draws and updates all other objects and systems
craft.physics
- Physics settings and helper functions
craft.voxels
- Streaming voxel terrain, block types and helper functions
craft.ar
- Augmented Reality, world tracking and helper functions
Each system can be used to access built-in objects, change settings or trigger specialised features.
scene = craft.scene()
In order to use craft you must make a scene. Scenes are used to create, update and draw all entities and components. Scenes also control basic things, such as ambient lighting, fog, the sky and contain references to some built-in entities.
Built-in entities include:
a main camera
that renders the scene by default
a 'sun' which is a directional light
a 'sky' which is a renderer
with a Materials:Skybox
material used to draw the background
camera | entity, the main camera entity (contains a camera component) |
sun | entity, the sun entity (contains a directional light component) |
sky | sky, the sky entity (contains a renderer with a Skybox material) |
ambientColor | color, the ambient light color (for materials with lighting) |
fogEnabled | bool, turns fog on and off |
fogNear | float, the distance where fog begins |
fogFar | float, the distance where fog reaches maximum density |
fogColor | color, the color of the fog |
renderBatchCount | int, the current number of batches being rendered (the less the better performance you can expect) |
renderBatchCullCount | int, the current number of batches saved by frustum culling |
myEntity = scene:entity()
Entities are flexible objects that can be customised to change their appearance and behaviour. You can customise an entity by adding components. Each type of component serves a different purpose. Renderer components change entity appearance, physics components give entities physical behaviour.
model | model, the model used for drawing this entity (stored within the attached renderer component) |
material | material, the material used for drawing this entity (stored within the attached renderer component) |
position | vec3, the position of this entity in local coordinate space |
worldPosition | vec3, the position of this entity in world coordinate space |
rotation | quat, the rotation of this entity in local coordinate space |
worldRotation | quat, the rotation of this entity in world coordinate space |
scale | vec3, the scale of this entity in local coordinate space |
x | float, the x position of this entity in local coordinate space |
y | float, the y position of this entity in local coordinate space |
z | float, the z position of this entity in local coordinate space |
eulerAngles | vec3, the rotation of this entity in local coordinate space expressed in euler angles |
parent | entity, the parent of this entity (in the transform hierarchy) |
children | table [readonly], an array of children entities attached to this entity |
active | bool, turn on and off to enable and disable entity in the scene |
myEntity:add( craft.renderer, myModel ) myEntity:add( craft.shape.box, vec3(1,1,1) ) myEntity:add( LuaClass, p1, p2, p3, ... )
Adds a component to this entity. There are several built-in components that can be added, such as craft.renderer
, craft.shape.box
and others. Lua classes can also be added as a component. Any additional parameters beyond the type will be forwarded to the component itself. For Lua classes the first parameter passed to the init()
function will be the entity itself (followed by the rest of the arguments) allowing it to be stored for later use.
Some special callback methods can be implemented in Lua classes to provide extra functionality.
The update()
method will be called once per frame (useful for animations and game logic). The fixedUpdate()
method will be called once per physics update (useful for physics related behaviour).
If the component is successfully added, the component will be returned. Only one of a given component type can be added at a time.
type | type, the type of component to add to this entity |
object, the component added to this entity
myEntity:get( craft.renderer ) myEntity:get( craft.shape.box ) myEntity:get( craft.rigidbody ) myEntity:get( LuaClass )
Gets a component of a particular type attached to this entity. If the component does not exist, nil is returned.
type | type, the type of component to get from this entity |
object, the requested component (or nil if it does not exist)
myEntity:remove( craft.renderer ) myEntity:remove( craft.shape.box ) myEntity:get( craft.rigidbody ) myEntity:remove( LuaClass )
Removes a component of a particular type attached to this entity, if it exists.
type | type, the type of component to remove from this entity |
myEntity:destroy()
Marks this entity for destruction in the next frame. Any children will also be marked for destruction.
myEntity:transformPoint(point)
Transforms a point from local space into world space using this entity's transform.
point | vec3, the point to transform |
vec3, the transformed point
myEntity:inverseTransformPoint(point)
Transforms a point from world space into local space using this entity's transform.
point | vec3, the point to transform |
vec3, the transformed point
myEntity:transformDirection(point)
Transforms a direction from local space into world space using this entity's transform.
direction | vec3, the direction to transform |
vec3, the transformed direction
myEntity:inverseTransformDirection(direction)
Transforms a direction from world space into local space using this entity's transform.
direction | vec3, the direction to transform |
myEntity:add(craft.camera, fov, nearPlane, farPlane, false) myEntity:add(craft.camera, orthoSize, nearPlane, farPlane, true)
A component used to draw the scene from its point of view.
fieldOfView | float, the field of view of the camera in degrees |
ortho | bool, orthographic rendering mode for this camera |
nearPlane | float, the near plane for the camera (the closest thing that can be rendered) |
farPlane | float, the far plane for the camera (the farthest thing that can be rendered) |
clearDepthEnabled | bool, the depth clearing flag for the camera (when set to true the existing depth buffer will be cleared before rendering) |
clearColorEnabled | bool, the color clearing flag for the camera (when set to true the existing color buffer will be cleared before rendering) |
clearColor | color, the color to use when clearing the color buffer before rendering with the camera |
entity | entity, the entity that the camera is attached to |
myCamera:screenToWorld( position )
Converts a position given in screen coordinates (x, y) and a depth value (z) to world space relative to this camera.
position | vec3, the position to convert to world space |
vec3
origin, dir = myCamera:screenToRay( position )
Converts a position in screen coordinates (x, y) to a ray in the form of an origin and direction relative to this camera.
position | vec2, the position to generate a ray with |
vec3, vec3
myCamera:worldToScreen( screenPos )
Converts a position given in world coordinates to screen coordinates relative to this camera.
position | vec3, the position to convert to screen space |
vec2
myCamera:viewport(x, y, width, height) x, y, w, h = myCamera:viewport()
Sets or gets the current viewport using normalized coordinates. Can be used for adjusting the rendered area of the camera relative to the screen. For instance, calling camera:viewport(0.0, 0.0, 0.5, 1.0)
will render the camera to only the left half of the screen.
x | float, the x position of the viewport |
y | float, the y position of the viewport |
width | float, the width viewport |
height | float, height of the viewport |
x, y, w, h
myEntity:add(craft.renderer, model)
A component used to draw a 3D model in the scene. Renderers can be attached to entities by using entity:add(craft.renderer)
or by setting entity.model
and entity.material
directly.
material | material, the material to apply to this renderer |
model | model, the model to render |
myEntity:add(craft.light, DIRECTIONAL) myEntity:add(craft.light, SPOT) myEntity:add(craft.light, POINT)
A component that casts light onto the scene. Different types of lights can be used to achieve different lighting effects, these include: DIRECTIONAL
, SPOT
and POINT
. The position and rotation of the entity controls the position and rotation of the attached light source. By default the scene contains a single directional light known as the sun
.
The scene also contains an ambient light controlled by scene.ambientColor
. The ambient light term is added to the emission of all other lights and is generally used for simulating scattered environmental light.
type | the type of light, can be DIRECTIONAL, SPOT, POINT |
color | color, the color of the light |
intensity | float, how intense the emitted light is (can be higher than one) |
distance | float, how far the light can travel (only applies for spot and point lights) |
angle | float, the spread angle of the light (only applies to spot lights) |
penumbra | float, the angle where light intensity begins to fade (only applies to spot lights) |
decay | float, the rate at which the intensity of the light fades due to distance (only applies to spot and point lights) |
mask | bitmask, the mask for which renderers should be effected by this light source |
DIRECTIONAL
This constant specifies the directional light type. Directional lights simulate an infinitely distant light source where all rays are parallel (similar to the sun). The position of a directional light is ignored.
int
SPOT
This constant specifies the spot light type. Spotlights simulate a cone of light within a specified angle (see the angle
property). The distance
and decay
properties define how far the light travels and how quickly the intensity falls off over distance.
The penumbra
property defines how hard the edge of the spotlight is. The closer this value is to angle
the harder the edge will appear. Setting this to zero will give the appearance of very soft spotlight.
int
POINT
This constant specifies the point light type. Point lights simulate a omnidirectional light source emitting from a single point. The distance
and decay
properties define how far the light travels and how quickly the intensity falls off over distance.
int
myMaterial = craft.material(asset.builtin.Materials.Basic) myMaterial = craft.material(asset.builtin.Materials.Standard) myMaterial = craft.material(asset.builtin.Materials.Specular) myMaterial = craft.material(asset.builtin.Materials.Skybox)
This type represents a surface material. Materials are used to control the physical appearance of 3D objects, such as models, sky boxes and voxels.
Set the material property on a craft.renderer
component to apply a given material to it. Materials are built out of modular shaders with a set of dynamic properties.
Each named property has a different effect on the material's appearance. For instance, the map
property can be set with an image or asset string to change the surface appearance of the Standard
material. Other properties can change the normals, roughness, metalness and reflectiveness of materials.
blendMode | int, the blend mode to use for this material (can be NORMAL, ADDITIVE or MULTIPLY) |
renderQueue | int, the render queue to use for this material (can be OPAQUE or TRANSPARENT) |
myModel = craft.model() myModel = craft.model( asset )
This type represents a model. Used in conjunction with a craft.renderer
component to draw 3D objects.
Existing model assets can be loaded by using craft.model(asset)
, supported 3D model formats are .obj
, .fbx
, .stl
and .blend
.
Models are made up of a number of triangles, which are in-turn made up of vertices. Each vertex has a number of attributes that control their appearance, such as position
, color
and normal
.
To make a triangle you must set the indices of the model using the indices
property. You can resize the number of indices and vertices by using the resizeIndices()
and resizeVertices()
functions.
vertexCount | int, the number of vertices in this model |
indexCount | int, the number of indices in this model |
positions | array, the positions of the vertices of this model |
normals | array, the normals of the vertices of this model |
colors | array, the colors of the vertices of this model |
uvs | array, the uvs of the vertices of this model |
indices | array, the primitive indices of this model used to form triangles |
material | material, the material for this model (overridden by renderer materials) |
myModel = craft.model.cube() myModel = craft.model.cube(size) myModel = craft.model.cube(size, offset)
Creates a cube model with the specified size and offset. By default the size parameter is set to (1,1,1), and the offset parameter is (0,0,0).
size | vec3, the size of the cube |
offset | vec3, the offset of the center of the cube |
myModel = craft.model.icosphere(radius) myModel = craft.model.icosphere(radius, subdivisions) myModel = craft.model.icosphere(radius, subdivisions, flat)
Creates an icosphere model. An icosphere is a geodesic dome made from equally sized triangles. The number of subdivisions specified will control how dense the sphere is (increasing the number of triangles). Setting the icosphere to flat will created faceted faces, otherwise the icosphere will have a smooth appearance.
radius | float, the radius of the icosphere |
subdivisions | int, the number of subdivisions to apply the base icosphere |
myModel = craft.model.plane() myModel = craft.model.plane(size) myModel = craft.model.plane(size, offset)
Creates a horizontal plane model with the specified size and offset. By default the size parameter is set to (1, 1), and the offset parameter is (0, 0, 0).
size | vec2, the size of the plane (x, z dimensions) |
offset | vec3, the offset of the center of the plane |
myModel:resizeVertices( size )
Sets the number of vertices in the model.
size | int, the number of vertices |
myModel:resizeIndices( size )
Sets the number of indices in the model where each set of 3 indices forms a triangle.
size | int, the number of indices |
myModel:position( index ) myModel:position( index, p ) myModel:position( index, x, y, z )
Set or get the position for a vertex within this model.
Use with only the index
parameter to return the x, y, z values of a vertex position (as 3 separate values).
index | int, |
x, y, z = myModel:normal( index ) myModel:normal( index, n ) myModel:normal( index, x, y, z )
Set or get the normal for a vertex within this model.
Use with only the index
parameter to return the x, y, z values of a vertex normal (as 3 separate values).
index | int, |
r, g, b, a = myModel:color( index ) myModel:color( index, c ) myModel:color( index, r, g, b, a )
Set or get the color for a vertex within this model.
Use with only the index
parameter to return the r, g, b, a values of a vertex color (as 4 separate values).
index | int, |
u, v = myModel:uv( index ) myModel:uv( index, p ) myModel:uv( index, u, v )
Set or get the uv for a vertex within this model.
Use with only the index
parameter to return the u, v values of a vertex uv (as 2 separate values).
index | int, index of the vertex to access |
myModel.submeshCount
This returns the number of submeshes available in the model. It can be used to find the range of indices needed for the getMaterial
and setMaterial
methods
Note that submeshes are indexed from 1 to submeshCount
mat = myModel:getMaterial() mat = myModel:getMaterial( index )
Get the material for a submesh within this model. You can use the submeshCount
property of the model to get the number of submeshes with distinct materials
Note that submeshes are indexed from 1 to submeshCount
. If an index is not provided it defaults to 1
index | int, index of the submesh to access, starting at 1 |
myModel:setMaterial( material ) myModel:setMaterial( material, index )
Set the material for a submesh within this model. You can use the submeshCount
property of the model to get the number of submeshes with distinct materials
Note that submeshes are indexed from 1 to submeshCount
. If an index is not provided it defaults to 1
material | Craft material to apply to the submesh at this index |
index | int, index of the submesh to access, starting at 1 |
myModel:addElement( index1, index2, ..., indexN )
Adds a variable number of indices to the model. Each index must be within the range 1..model.vertexCount
index | int, |
myModel:clear()
Clears all buffers in all submeshes associated with this model. Effectively removing all its geometry
This is useful for re-using a model object multiple times
myModel:split() myModel:split( index )
This function modifies the model geometry to ensure that each triangle has unique vertices. So that no triangle shares vertex indexes with its neighbours. Calling this will increase the number of vertices in the model (if it is not already split)
The index parameter (defaults to 1) allows you to specify which submesh is split. If a model has multiple submeshes you will need to call split
multiple times, one for each submesh up to submeshCount
index | int, index of the submesh to access, starting at 1 |
The system governing all 3D physics in a scene.
paused | bool, use to pause and unpause the physics simulation |
gravity | vec3, the current force of gravity effecting all rigidbodies (measured in ms^2) |
scene.physics:raycast(origin, direction, distance) scene.physics:raycast(origin, direction, distance, group) scene.physics:raycast(origin, direction, distance, group, mask)
Performs a raycast in the scene against any rigidbodies with attached shapes.
origin | vec3, the origin of the ray |
direction | vec3, the direction of the ray |
distance | float, the maximum distance the ray can travel |
group | int, the group of the ray (used for filtering) |
mask | int, the mask of the ray (used for filtering) |
table, if the raycast intersects a rigidbody this function will return a table containing the following key-value pairs:
entity => entity hit
point => point of intersection
normal => normal at the point of intersection
fraction => fraction of total ray length from start to intersecton point
uv => the uv coordinates of the hit location (if the target has an attached model shape)
barycentric => the barycentric coordinates of triangle hit location (if the target has an attached model shape)
triangleIndex => the index of the triangle hit (if the target has an attached model shape)
scene.physics:spherecast(origin, direction, distance, radius) scene.physics:spherecast(origin, direction, distance, radius, group) scene.physics:spherecast(origin, direction, distance, radius, group, mask)
Performs a spherecast in the scene against any rigidbodies with attached shapes. A spherecast works by projecting a sphere in the direction of the cast and detecting any shapes that it intersects.
origin | vec3, the origin of the spherecast |
direction | vec3, the direction of the spherecast |
distance | float, the maximum distance the spherecast can travel |
radius | float, the radius of the spherecast |
group | bitmask, the group of the ray (used for filtering) |
mask | bitmask, the mask of the ray (used for filtering) |
table, if the spherecast intersects a rigidbody this function will return a table containing the following key-value pairs:
entity => entity hit
point => point of intersection
normal => normal at the point of intersection
fraction => fraction of total ray length from start to intersecton point
myRigidbody = myEntity:add( craft.rigidbody, STATIC ) myRigidbody = myEntity:add( craft.rigidbody, KINEMATIC ) myRigidbody = myEntity:add( craft.rigidbody, DYNAMIC, mass )
This type represents a 3D rigidbody. Attach this to an entity to make it respond to forces and collisions. When creating a rigidbody you must specify the type you want to create. Refer to the documentation for DYNAMIC
, STATIC
and KINEMATIC
for more details.
type | the type of the body, can be STATIC, DYNAMIC or KINEMATIC |
mass | float, the mass of the rigid body in kilograms |
centerOfMass | vec3, the center of mass of the rigid body in world space |
linearVelocity | vec3, the current linear velocity of the body in meters per second |
angularVelocity | vec3, the angular velocity of the body in degrees per second |
awake | bool, is the rigid body currently awake |
sleepingAllowed | bool, is sleeping allowed for this rigid body |
linearDamping | float, linear damping factor, slows rigid body movement over time |
angularDamping | float, angular damping factor, slows rigid body rotation over time |
friction | float, sliding friction factor |
rollingFriction | float, rolling friction factor |
restitution | float, restitution factor, the bounceyness of this rigid body |
group | bitmask, the collision filtering group for this rigid body |
mask | bitmask, the collision filtering mask for this rigid body |
DYNAMIC
This constant specifies the dynamic body type. Dynamic bodies move under the influence of collisions, forces, joints and gravity.
int
STATIC
This constant specifies the static body type. Static bodies are unaffected by forces and collisions. They also do not collide with other static or kinematic bodies.Also note that you cannot attach two static/kinematic bodies together with a joint.
int
KINEMATIC
This constant specifies the kinematic body type. Kinematic bodies are unaffected by forces and collisions. Unlike static bodies, kinematic bodies are meant to be moved, usually by setting linear velocity directly. They also do not collide with other static or kinematic bodies. Also note that you cannot attach two static/kinematic bodies together with a joint.
int
myBody:applyForce( force ) myBody:applyForce( force, worldPoint )
Applies a force to this rigidbody. If worldPoint
is not specified then the force will be applied to the center of the rigidbody.
force | vec3, the amount of force (in newtons per second) to apply as a vector |
worldPoint | vec3, the point to apply the force from, in world coordinates |
myBody:applyTorque( torque )
Applies torque to this rigidbody.
force | vec3, the amount of torque (in newton meters per second) to apply as a vector |
myShape = myEntity:add(craft.shape.box, size) myShape = myEntity:add(craft.shape.box, size, offset)
This component represents a box physics shape. Attach this to an entity with a rigidbody to make it respond to physical forces.
size | vec3, the size of the box |
offset | vec3, the offset of the box (center) |
myShape = myEntity:add(craft.shape.sphere, radius) myShape = myEntity:add(craft.shape.sphere, radius, offset)
This component represents a sphere physics shape. Attach this to an entity with a rigidbody to make it respond to physical forces.
myShape = myEntity:add(craft.shape.model, model)
This component represents an arbitrary physics shape made from a model. Attach this to an entity with a rigidbody to make it respond to physical forces.
myShape = myEntity:add(craft.shape.capsule, radius, height)
This component represents a capsule physics shape. Attach this to an entity with a rigidbody to make it respond to physical forces.
craft.voxels
The voxel system, used to manage streaming voxel terrain.
Initially no voxels exist as the terrain is completely empty. Using voxels:resize()
will create an empty patch of terrain, consisting of empty blocks.
Once some terrain has been allocated voxels:generate()
can be used to generate the landscape one chunk at a time via a multi-threaded generation system. See the Voxel Terrain
project for an example of how this works.
Using voxels:enableStorage(storage)
allows voxels to be saved to a project subfolder with the specified name. As a technical note, volumes and chunks are saved as zlib compressed json files. Block types, scheduled updates and block entities are all saved. If a block id changes due to inserting a new block type of removing an existing one, the loaded chunk/volume may change unexpectedly.
coordinates | vec3, the viewing coordinates to stream voxels around (in world coordinates) |
visibleRadius | float, the radius (in chunks) to stream around the viewing coordinates |
visibleChunks | int, the number of chunks that are loaded and potentially visible in the scene |
generatingChunks | int, the number of chunks that are currently being generated |
meshingChunks | int, the number of chunks that are currently being meshed (turned into models) |
scene.voxels:resize( vec3(100, 1, 100) ) scene.voxels:resize( vec3(100, 1, 100), vec3(16, 128, 16) )
Resizes the voxel terrain to a specified size divided into chunks, which can be generated and streamed efficiently.
sizeInChunks | vec3, the total size of the world in chunks (y is limited to 1 at this time) |
chunkSize | vec3, the size of each chunk (default is 16x128x16) |
scene.voxels:generate(generationCode, generationFunction)
Triggers voxel terrain generation using lua code provided as a string and the number of a function to call.
The specified function must exist within generationCode
and must take a single parameter which is the chunk that will be generated. See craft.volume
for available methods for manipulating chunks.
generationCode | string, the lua code to use for multi-threaded generation |
generationFunction | string, the name of the function within |
scene.voxels:get ( coord, key ) scene.voxels:get ( coord, key1, key2, ... keyN ) scene.voxels:get ( coord, keyArray )
Gets data from a block at a particular location using the specified key(s). There are a number that can be used for different block data:
BLOCK_ID
- Get this block's id (int)
BLOCK_NAME
- Get this block's name (string)
BLOCK_STATE
- Get this block's state (int)
COLOR
- Get this block's tint color (color), only works for tinted blocks
To get custom block properties, use a string with the name of that property. When called with no keys specified a block instance will be returned which has methods which can be called directly.
coord | vec3 or (x,y,z), the coordinate of the block (in world coordinates) to get the data from |
key | the key of the data to get for this block |
multiple, the values associated with the block's keys (or nil if it does not exist)
scene.voxels:set ( coord, key, value ) scene.voxels:set ( coord, key1, value1, ... keyN, valueN ) scene.voxels:set ( coord, keyValueTable )
Sets data on a block at a particular location for the specified key(s). There are several that can be used for different block data:
BLOCK_ID
- Set this blocks id (int), effectively changing the type of block
BLOCK_NAME
- Set this blocks name (string), effectively changing the type of block
BLOCK_STATE
- Set this blocks state (int)
COLOR
- Set this blocks tint color (color), only works for tinted blocks
If a block changes its own type then it will behave as the new block and will trigger any destroyed()
and created()
callbacks.
To modify custom block properties, use a string with the name of that property.
coord | vec3 or (x,y,z), the coordinate of the block (in world coordinates) to set the data for |
key | the key of the data to set for this block |
value | the value to set the data to |
scene.voxels:fill ( key ) scene.voxels:fill ( key1, key2, ... keyN ) scene.voxels:fill ( keyArray )
Sets the current fill block. Takes the same parameters as voxels.set
.
This is used for basic drawing operations such as sphere
, box
and line
.
key | the key of the data to use for the fill |
value | the value of the data to use for the fill |
scene.voxels:fillStyle ( style )
Sets the current fill style. There are several styles that can be used:
REPLACE
- Replace fill style, new blocks will replace any existing ones
UNION
- Union fill style, new blocks will only replace empty ones
UNTERSECT
- Intersect style, new blocks will only replace non-existing ones
CLEAR
- Clear style, new blocks will clear any existing blocks
style | the style to use |
scene.voxels:block ( coord )
Sets a single block using the current fill()
and fillStyle()
settings.
coord | vec3 or (x,y,z), the coordinate to place the block |
scene.voxels:sphere ( coord, radius ) scene.voxels:sphere ( x, y, z, radius )
Sets a sphere shaped array of blocks using the coord
and radius
coord | vec3 or (x,y,z), the coordinate of the sphere to place |
radius | float, the radius of the sphere to place |
scene.voxels:box ( min, max ) scene.voxels:box ( x1, y1, z1, x2, y2, z2 )
Sets a box shaped array of blocks using the minimum and maximum coordinates supplied.
min | vec3 or (x,y,z), the coordinate of the minimum corner of the box |
max | vec3 or (x,y,z), the coordinate of the maximum corner of the box |
scene.voxels:line ( start, end ) scene.voxels:line ( x1, y1, z1, x2, y2, z2 )
Sets a line shaped array of blocks using the minimum and maximum coordinates supplied.
start | vec3 or (x,y,z), the coordinate of the start of the line |
end | vec3 or (x,y,z), the coordinate of the end of the line |
scene.voxels:updateBlock ( coord, ticks ) scene.voxels:updateBlock ( x, y, z, ticks )
Schedules a block update for the block at a specified coordinate. The ticks
parameter controls how long in the future before the update will occur. Each tick is roughly 1/60th of a second. Using 0 will cause an update to occur next frame.
Block updates call the blockUpdate(ticks)
method on scripted blocks. Block updates can be triggered inside a scripted block itself by using self:schedule(ticks)
.
coord | vec3 or (x,y,z), the coordinate of the block to update |
ticks | ticks, the number of ticks to wait for the update |
scene.voxels:raycast( start, direction, distance, callback )
Performs a raycast on the voxel terrain. The callback provided must follow the signature:
function callback(coord, id, face)
The coord
parameter (vec3) contains the coordinate of the current voxel encountered.
If coord
is nil, this means the raycast has gone outside of the bounds of the voxel terrain (i.e. no voxel found).
The id
parameter contains the id of the current voxel encountered.
The face
parameter (vec3) contains the direction of the face hit by the raycast (i.e. vec3(0,1,0) would be the top).
At each step the callback function can return true
or false
. Returning true
will terminate the raycast early, false
will continue the raycast until the maximum distance is reached.
origin | vec3, the origin of the ray |
direction | vec3, the direction of the ray |
distance | vec3, the maximum distance the ray can travel |
callback | function, a callback that will be called for each voxel encountered |
scene.voxels:iterateBounds( min, max, callback )
Iterates through all blocks within the min and max bounds provided sending the information to a callback function.
The callback function should take the following form function myCallback(x, y, z, id)
.
min | vec3 or (x,y,z), the coordinate of the minimum corner of the box |
max | vec3 or (x,y,z), the coordinate of the maximum corner of the box |
callback | function, the function to callback for each block encountered |
scene.voxels:isRegionLoaded( min, max )
Checks if all the voxels within the min and max bounds are currently loaded. This is useful for generating more complex structures that make require adjacent areas to be loaded.
min | vec3 or (x,y,z), the coordinate of the minimum corner of the box |
max | vec3 or (x,y,z), the coordinate of the maximum corner of the box |
scene.voxels:enableStorage( storageName )
Enables storage within the voxel system. This causes regions to be saved within the project inside a folder named storageName
.
storageName | string, the name of the storage folder to use |
scene.voxels:disableStorage()
Disables storage.
scene.voxels:deleteStorage( storageName )
Deletes a particular storage folder (if it exists).
storageName | string, the name of the storage folder to delete |
This type represents a specific voxel block variant. You can create a block type via scene.voxels.blocks:new( name )
.
By default a block type has the appearance of a white cube (1x1x1 units). A block type's appearance can be customised by adding and removing cubes of various sizes, changing their textures or applying tints.
A block type's behaviour can be customised by enabling scriping and adding special methods to it:
blockType:created()
- called when the block is created
blockType:destroyed()
- called when the block is destroyed (removed)
blockType:buildModel(model)
- called when the block is about to be modeled
Instances of scripted blocks cannot store additional data in their tables unless they are set to dynamic
. Non-dynamic blocks have up to 32 bits of state that can be used to store per-block data (see block.state
for more information). Dynamic blocks can store additional values in their tables. Dynamic blocks come with their own entity, which can be used to render custom models, or animate them in ways static blocks cannot.
Scripted and dynamic blocks use significantly more resources than standard non-scripted blocks and care must be taken to avoid using too much memory or slowing down the voxel system. A good rule of thumb is to match the complexity of a custom block to how often it is used.
Please note that any properties marked instance only
can only be accessed via block instances, i.e. those created by setting voxels and passed into callbacks.
id | int, the id of this block type |
name | string, the name of this block type |
state | type, the state of this block |
geometry | int, the type of geometry to generate, can be EMPTY, SOLID, TRANSPARENT or TRANSLUCENT |
renderPass | int, the type of render pass to use, can be OPAQUE or TRANSLUCENT |
tinted | bool, whether this block type supports tinting (changing color) |
scripted | bool, whether this block type supports scripting |
dynamic | bool, whether this block type is dynamic |
x | int, the x location of this block (instance only) |
y | int, the y location of this block (instance only) |
z | int, the z location of this block (instance only) |
myBlock:get ( key ) myBlock:get ( key1, key2, ... keyN ) myBlock:get ( keyArray )
Gets data from this block for the specified key. There are a number of that can be used for different block data.
BLOCK_ID
- Get this block's id (int)
BLOCK_NAME
- Get this block's name (string)
BLOCK_STATE
- Get this block's state (int)
COLOR
- Get this block's tint color (color), only works for tinted blocks
To get custom block properties, use a string with the name of that property.
key | the key of the data to set on this block |
myBlock:set ( key, value ) myBlock:set ( key1, value1, ... keyN, valueN ) myBlock:set ( keyValueTable )
Sets data on this block for the specified key. There are a number of that can be used for different block data.
BLOCK_ID
- Set this blocks id (int), effectively changing the type of block
BLOCK_NAME
- Set this blocks name (string), effectively changing the type of block
BLOCK_STATE
- Set this blocks state (int)
COLOR
- Set this blocks tint color (color), only works for tinted blocks
If a block changes its own type then it will behave as the new block and will trigger any destroyed()
and created()
callbacks.
To modify custom block properties, use a string with the name of that property.
key | the key of the data to set on this block |
value | the value to set the data to |
myEntity:add(craft.volume, x, y, z)
This component represents a 3D voxel volume. Voxel volume components store block data as well as handling rendering and physics.
sx, sy, sz = myVolume:size()
Returns the size of this volume in voxels as 3 components (x, y, z).
size of the volume as 3 separate values
myVolume:get ( key ) myVolume:get ( key1, key2, ... keyN ) myVolume:get ( keyArray )
Gets data from a block at a particular location using the specified key(s). There are a number that can be used for different block data:
BLOCK_ID
- Get this block's id (int)
BLOCK_NAME
- Get this block's name (string)
BLOCK_STATE
- Get this block's state (int)
COLOR
- Get this block's tint color (color), only works for tinted blocks
To get custom block properties, use a string with the name of that property.
coord | vec3 or (x,y,z), the coordinate of the block (in world coordinates) to get the data from |
key | the key of the data to get for this block |
multiple, the values associated with the block's keys (or nil if it does not exist)
myVolume:set( x, y, z, id ) myVolume:set( coord, id ) myVolume:set( x, y, z, name ) myVolume:set( coord, name ) myVolume:set( x, y, z, key1, value1, ... keyN, valueN ) myVolume:set( coord, keyValueTable ) myVolume:set( x, y, z, keyValueTable )
Sets a block within this volume at the coordinates given (x, y, z). Coordinates can be supplied as either a vec3, or as a set of 3 numbers.
x | number, the x location of the block to set |
y | number, the y location of the block to set |
z | number, the z location of the block to set |
myVolume:resize( x, y, z )
Resizes the volume to a specific size.
x | float, the width of the volume |
y | float, the height of the volume |
z | float, the depth of the volume |
myVolume:load( asset.documents.MyVoxelModel )
Loads a saved volume.
asset | asset key, the name of the asset to load |
myVolume:save( asset.documents.MyVoxelModel )
Saves a volume as a voxel asset.
asset | asset key, the name of the asset to save |
The Augmented Reality (AR) system. Please note that to use the AR feature your device must possess an A9 or greater processor. To determine if your device supports AR, use craft.ar.isSupported
.
Only some devices support AR face tracking - these include devices with a TrueDepth camera, such as the iPhone X product line (X, XR, XS, XS Max) and iPad Pro 2018 and above models. To determine if your device supports AR face tracking, use craft.ar.isFaceTrackingSupported
.
To enable AR, use scene.ar:run()
. This will use the sky to render the camera feed to the background. If you do not want to display the camera feed, simply disable the sky. To disable AR you can call the pause()
function.
To enable AR face tracking supply an addition parameter in the form of scene.ar:run(AR_FACE_TRACKING)
.
In world tracking configuration the AR system will automatically try to detect and estimate horizontal and vertical planes in the scene. To be notified of when this happens you must set the anchor callbacks, such as scene.ar.didAddAnchors
. These will be called with an array of anchor objects which contain a position
and extent
which can be used for positioning objects in the world.
To interact with the AR world, use hitTest(screenPoint, options)
, and check the array of hitTestResult objects for any intersections.
isSupported | bool [static, readonly], use to determine if your device supports AR |
isFaceTrackingSupported | bool [static, readonly], use to determine if your device supports AR face tracking |
isRunning | bool [readonly], use to determine if AR is currenly active |
planeDetection | bool, enable and disable plane detection |
trackingState | enum [readonly], the current tracking state - can be |
trackingStateReason | enum [readonly], the reason for the current tracking state (if |
didAddAnchors | function, the function to call when one or more anchors is added to the AR system |
didUpdateAnchors | function, the function to call when one or more anchors is updated |
didRemoveAnchors | function, the function to call when one or more anchors is removed |
scene.ar:run() scene.ar:run(AR_WORLD_TRACKING) scene.ar:run(AR_FACE_TRACKING)
Enables AR if possible. This overrides the sky's visuals as well as the main camera's transform and projection matrix.
trackingType | constant, the type of tracking to use (i.e. |
scene.ar:pause()
Pauses AR.
scene.ar:hitTest( screenPoint )
Performs a hit test (raycast) against the AR world. Any objects that are hit by the ray are returned as a list of craft.ar.hitTestResult
.
The options parameter is a bitmask with the following flags:
AR_FEATURE_POINT
- Search for feature points
AR_ESTIMATED_PLANE
- Search for estimated horizontal surfaces
AR_EXISTING_PLANE
- Search for detected planes
AR_EXISTING_PLANE_CLIPPED
- Search for detected planes (clipped to edges)
screenPoint | vec2, the screen point to check for hits in the AR world |
options | bitmask, the options to use for finding things in the AR world |
array, the hitTestResult objects (if any) resulting from this hit test
scene.ar:makeFaceModel(blendShapes)
Generates an AR face model from the supplied blend shape table. This table is in the same format as the one supplied by the face anchor blendShapes
property.
blendShapes | table, the table of blend shapes to use to construct the model |
An anchor in the AR world. These can represent a point (single location) or a plane (flat surface). The identifier
property is useful for uniquely identifying anchors that are automatically created by plane detection.
When running an AR face tracking session, the anchor will contain additional data, such as blendShapes
and faceModel
.
The blendShapes
property returns a table of facial expression data, where each key is a string relating to the expression and the corresponding value is a number between 0 and 1. There are a very large number of keys and so you may find it useful to use the AR Face example project to browse though them.
type | int, the type of anchor |
identifier | string, the unique identifier for this anchor |
position | vec3, the position of this anchor (in the AR world) |
extent | vec3, the extent of this anchor (for planes) |
faceModel | model, a 3D model representing the detected face (for faces) |
blendShapes | table, a table of blend shapes representing various facial expressions (for faces) |
leftEyePosition | vec3, the position (in local face coordinates) of the left eye (for faces) |
leftEyeRotation | quat, the rotation (in local face coordinates) of the left eye (for faces) |
rightEyePosition | vec3, the position (in local face coordinates) of the right eye (for faces) |
rightEyeRotation | quat, the rotation (in local face coordinates) of the right eye (for faces) |
lookAtPoint | vec3, the estimated location that the eyes are currently looking at in local face coordinates (for faces) |
A hit test result that is returned by the ar:hitTest()
function.
The type
of hittest can be
type | int, the type of hit test |
identifier | string, the unique identifier for this anchor |
position | vec3, the position of this anchor (in the AR world) |
extent | vec3, the extent of this anchor (for planes) |
AR_WORLD_TRACKING
This constant specifies the AR world tracking session type used in the ar.run()
method.
int
AR_FACE_TRACKING
This constant specifies the AR face tracking session type used in the ar.run()
method.
int
AR_NOT_AVAILABLE
This constant specifies that AR world tracking is not currently available. Returned by ar.trackingState
.
int
AR_LIMITED
This constant specifies that AR world tracking is currently limited. Returned by ar.trackingState
, with further details returned by ar.trackingStateReason
.
int
AR_NORMAL
This constant specifies that AR world tracking is currently normal. Returned by ar.trackingState
.
int
AR_NONE
This constant specifies that AR world tracking is not currently limited. Returned by ar.trackingStateReason
.
int
AR_EXCESSIVE_MOTION
This constant specifies that AR world tracking is currently limited due to excessive device motion. Returned by ar.trackingStateReason
.
int
AR_INSUFFICIENT_FEATURES
This constant specifies that AR world tracking is currently limited due to insufficient feature points. This could be due to a lack of contrasting features on surfaces (such as a white table or mirrored surface). Returned by ar.trackingStateReason
.
int
AR_FEATURE_POINT
Used by ar:hitTest
as a mask for detecting feature points during hit test.
int
AR_ESTIMATED_PLANE
Used by ar:hitTest
as a mask for detecting estimated planes during hit test.
int
AR_EXISTING_PLANE
Used by ar:hitTest
as a mask for detecting existing planes during hit test.
int
AR_EXISTING_PLANE_CLIPPED
Used by ar:hitTest
as a mask for detecting existing planes (clipped to edges) during hit test.
int
The noise library contains a series of noise modules that can be used to generate a large variety of procedural content.
Use getValue(x,y,z)
to generate a scalar noise value. Some modules take a number of inputs (set with setSource(input)
).
Noise modules fall into the following catagories:
Generators
- These modules generate values directly and require no inputs
Transformers
- These modules transform their inputs in some way to create a new effect
Refer to each individual module's documentation to see how they work.
n = craft.noise.perlin()
A perlin noise generator module. Zero inputs.
octaves | int, the number of octaves, controlling the detail of the noise |
frequency | float, the frequency of the first octave |
persistence | float, the persistence controls how rough the noise produced is |
lacunarity | float, the lucunarity controls the multiplier between successive octaves |
seed | int, the seed |
n = craft.noise.rigidMulti()
A rigid multi-fractal noise generator module. Zero inputs.
octaves | int, the number of octaves, controlling the detail of the noise |
frequency | float, the frequency of the first octave |
lacunarity | float, the lucunarity controls the multiplier between successive octaves |
seed | int, the seed |
n = craft.noise.billow()
A billow noise generator module. Zero inputs.
octaves | int, the number of octaves, controlling the detail of the noise |
frequency | float, the frequency of the first octave |
persistence | float, the persistence controls how rough the noise produced is |
lacunarity | float, the lucunarity controls the multiplier between successive octaves |
seed | int, the seed |
n = craft.noise.turbulence()
Transformer module that distorts input using turbulent noise. One input.
frequency | float, the frequency of the turbulence |
roughness | float, how rough the turbulence is |
power | float, how much distortion to apply |
seed | int, the seed |
n = craft.noise.cache()
Caches the source module value when evaluated at the same coordinates more than once. This can improve performance when an expensive module may be evaluated more than once within a single noise tree. One input.
n = craft.noise.const(value)
Constant noise module. Returns a constant value at any location. Zero inputs.
n = craft.noise.select()
Selects one of two noise modules based on the output of the control module and the set bounds. Three inputs.
n = craft.noise.gradient()
Returns a gradient in the y-axis mapped from zero to one. Zero inputs.
n = craft.noise.min()
Returns the minimum of two noise modules. Two inputs.
n = craft.noise.max()
Returns the maximum of two noise modules. Two inputs.
n = craft.noise.add()
Returns the addition of two noise modules. Two inputs.
n = craft.noise.multiply()
Returns the multiplication of two noise modules. Two inputs.
n = craft.noise.invert()
Returns the negative of the source noise module. One inputs.
n = craft.noise.abs()
Returns the absolute version of the source noise module. One input.
n = craft.noise.merge()
Returns the first non-zero value of two noise modules. Two inputs.
n = craft.noise.scaleOffset()
Scales and offsets the output of a noise module. One input.
n = craft.noise.displace()
Displaces the coordinates of a noise module using three other noise modules. Four inputs.
n = craft.noise.scale()
Scales the coordinates of the input source module. One input.