import { Box, Capsule, Cone, Cylinder, Group, Mesh, Plane, Primitive, Sphere, Torus } from "@apricot/react";
import type { SceneObject, Vec3 } from "@apricot/react";Transform props#
Every object (shapes, Mesh, Group, Primitive, Instances, Model) takes:
| Prop | Type | Default | Description |
|---|---|---|---|
position |
Vec3 or shared value |
[0, 0, 0] |
Relative to the parent, in units (metres) |
rotation |
Vec3 or shared value |
[0, 0, 0] |
Euler angles in radians, XYZ order |
scale |
number | Vec3 or shared value |
1 |
One number for all axes, or per axis |
type Vec3 = readonly [number, number, number]. Shared values are read every frame without React renders; type them with useDerivedValue<readonly [number, number, number]>(…).
Shared shape props#
Every shape and Mesh takes:
| Prop | Type | Default | Description |
|---|---|---|---|
material |
MaterialInput |
"standard" |
A preset name, { preset, ...options }, or a three.js material (yours: not disposed). See Materials |
color |
colour | the preset's | Overrides the preset's colour. Changes animate |
onPress |
(hit: PressHit) => void |
Called when the object is tapped | |
name |
string |
"" |
The three.js object's name |
visible |
boolean |
true |
Hides the object (and its children) |
castShadow, receiveShadow |
boolean |
decided by the scene | Overrides with <Scene shadows> |
ref |
Ref<SceneObject> |
The three.js mesh | |
children |
ReactNode |
Nested objects, placed relative to this one |
PressHit: { mesh, material, materialIndex, point, distance, instanceId }. point is the world-space Vector3 hit; distance is from the camera.
Shapes#
All shapes are centred on their position.
| Component | Props (default) | Orientation |
|---|---|---|
Box |
size number or [w, h, d] (1), radius edge rounding (0) |
Axis-aligned |
Sphere |
radius (0.5), segments (32) |
|
Cylinder |
radius (0.5), radiusTop (= radius), height (1), segments (32) |
Stands along y |
Cone |
radius (0.5), height (1), segments (32) |
Points up (+y) |
Plane |
size number or [w, h] (1) |
Faces +z. For a floor: rotation={[-Math.PI / 2, 0, 0]} |
Torus |
radius centre to tube middle (0.5), tube thickness (0.15), segments (48) |
Ring in the xy plane (faces +z) |
Capsule |
radius (0.3), length straight middle (0.6), segments (16) |
Along y. Total height = length + 2 * radius |
Changing a size prop rebuilds the geometry; shapes free their geometry on unmount. To animate size, animate scale instead.
Mesh#
| Prop | Type | Description |
|---|---|---|
geometry |
THREE.BufferGeometry (required) |
The shape. Yours: not disposed by the mesh |
Plus the shared shape props and transform props. See Custom geometry.
Group#
An empty node that transforms its children together.
| Prop | Type | Description |
|---|---|---|
name |
string |
|
ref |
Ref<SceneObject> |
The three.js group, for <FollowCamera target>, <Label attach>, <CameraRig follow> |
children |
ReactNode |
Plus transform props.
Primitive#
Adds an existing three.js object as it is.
| Prop | Type | Description |
|---|---|---|
object |
THREE.Object3D (required) |
Any three.js object. Yours: dispose it yourself (disposeObject) |
ref |
Ref<SceneObject> |
The same object |
children |
ReactNode |
Nested under the object |
Plus transform props. Transform props overwrite the object's own position, rotation and scale only when given.
SceneObject#
type SceneObject = THREE.Object3D: what a ref on Box, Group, Model, Vehicle, FollowPath or a light holds. Read or change its position, rotation, scale and visible directly, then call useScene().invalidate() if you changed it outside useFrame.
const box = useRef<SceneObject>(null);
<Box ref={box} />