This project is a foundational library for 3D projects used in Verse8. It provides essential components to start 3D development.
Vibe Starter 3D is a library designed to easily integrate 3D elements into React applications. Built on Three.js, React Three Fiber, and related technologies, it specifically offers functionality for easily rendering and animating 3D character models in VRM and GLTF/GLB formats.
npm install vibe-starter-3d
-
CharacterRenderer: Unified component for rendering VRM and GLTF/GLB models
-
CharacterRendererRef
: Reference interface providing bounding box information of the model
-
-
View Controllers: Components providing various camera perspectives
-
FreeViewController
: Free camera perspective -
FirstPersonViewController
: First-person perspective -
QuarterViewController
: Quarter view perspective -
SideViewController
: Side view perspective -
FlightViewController
: Flight perspective with configurable handle -
PointToMoveController
: Point-to-move perspective with configurable camera mode and zoom
-
-
NetworkObject: Component for handling network-connected objects
-
NetworkObjectProps
: Defines network object properties -
NetworkObjectHandle
: Handle for manipulating network objects
-
-
controllerUtils: Controller-related utilities
-
position
,camInitDis
,camMinDis
,camMaxDis
,targetHeight
,capsuleRadius
, etc.
-
-
collisionUtils: Collision detection and handling utilities
-
isInCollisionGroup
,createLocalPlayerCollisionGroups
,collisionGroups
, etc.
-
-
typeUtils: Type conversion utilities between Three.js and React Three Fiber
-
toVector3
,toVector3Array
,toQuaternion
,toQuaternionArray
etc.
-
-
Animation-related Types:
-
AnimationType
: Defines animation types such as 'IDLE', 'WALK', 'RUN', 'JUMP', etc. -
AnimationConfig
: Provides animation settings (loop, duration, clampWhenFinished, etc.) -
AnimationConfigMap
: Maps action types to animation settings
-
-
CharacterResource Type:
- Interface defining character model information (name, url, animations)
-
Controller-related Types:
-
ControllerProps
: Defines controller component properties -
ControllerHandle
: Controller handle interface for rigid body reference, offset, etc. -
FollowLightProps
: Settings for following light (position, intensity, color, etc.) -
ControllerMode
: Controller modes such as 'CameraBasedMovement', 'FixedCamera', 'PointToMove', etc.
-
-
Animation Constants:
-
ANIMATION_KEYWORDS
: Keyword mapping for identifying animation types
-
-
Collision Group Constants:
-
CollisionGroup
: Defines collision detection groups (Default, Player, Enemy, NPC, Projectile, etc.)
-
Below is the complete list of collision groups used in the Rapier physics engine. Each value represents a group index between 0 and 15.
Group | Value | Description |
---|---|---|
Default |
0 | General object (default) |
Player |
1 | Player character |
Enemy |
2 | Enemy character |
NPC |
3 | Neutral character |
Projectile |
4 | Projectile |
Environment |
5 | Walls, floors, roads, structures, etc. |
Item |
6 | Interactive or acquirable item |
Trigger |
7 | Event trigger |
UI |
8 | For UI raycast |
Sensor |
9 | Invisible sensor (vision, proximity, etc.) |
DeadBody |
10 | Deceased unit |
LocalPlayer |
11 | Self in multiplayer |
RemotePlayer |
12 | Other user characters in multiplayer |
Vehicle |
13 | Vehicle/mount |
Terrain |
14 | Terrain for special judgment |
Particle |
15 | Particle effect (for hit judgment or to ignore) |
Note: The rigid bodies of all controller components (
FreeViewController
,FirstPersonViewController
,QuarterViewController
,SideViewController
,FlightViewController
) are automatically set to theLocalPlayer
collision group. This is handled internally through thecreateLocalPlayerCollisionGroups
function.
The CharacterRenderer
component is a unified component for rendering and animating 3D character models in VRM and GLTF/GLB formats. It allows controlling various aspects like visibility, resource information, animation configuration, and current action state through its props.
The CharacterRenderer
component accepts the following CharacterRendererProps
:
Property | Type | Description | Default Value |
---|---|---|---|
visible |
boolean |
Determines whether the character model is displayed on the screen. | true |
characterResource |
CharacterResource |
Character resource containing model and animation information. | Required |
animationConfigMap |
Partial<AnimationConfigMap<ActionType>> |
A map defining animation settings for each action type. | Required |
currentActionRef |
RefObject<ActionType | undefined> |
A Ref object pointing to the current character action. | Required |
targetHeight |
number |
Target height for the character model. | Optional |
disableAnimationAdjustmentToModelProportion |
boolean |
If true, animation won't be adjusted to fit the model's body proportion (GLTF/GLB only). | Optional |
onAnimationComplete |
(action: ActionType) => void |
Optional callback function invoked when a specific animation completes. | Optional |
onSizeChange |
(boundingBox: THREE.Box3) => void |
Optional callback function invoked when the model's bounding box size information changes. | Optional |
children |
React.ReactNode |
Optional child components to render inside the CharacterRenderer . |
Optional |
Note:
CharacterRenderer
provides aCharacterRendererRef
interface accessible viaforwardRef
. This interface allows accessing theboundingBox
(THREE.Box3 | null
) information of the currently rendered model.
Interface exposed externally by the controller component.
Property | Type | Description |
---|---|---|
rigidBodyRef |
React.RefObject<RapierRigidBody> |
Reference to the physics rigid body |
offsetY |
number |
Y-axis offset value |
Defines the basic properties of all controller components. FreeViewController, FirstPersonViewController, QuarterViewController, and SideViewController all inherit (extend) this interface.
Property | Type | Description | Default Value |
---|---|---|---|
position |
Vector3 |
Initial position of the rigid body | [0, 5, 0] |
camInitDis |
number |
Initial camera distance | -4 |
camMinDis |
number |
Minimum camera zoom-in distance | -4 |
camMaxDis |
number |
Maximum camera zoom-out distance | -4 |
targetHeight |
number |
Character height (m) | 1.6 |
floatHeight |
number |
Height above ground (m) | 0.01 |
followLight |
FollowLightProps |
Settings for the following light (e.g., position, intensity, color) | - |
followCameraForward |
boolean |
Whether to follow camera direction | false |
children |
React.ReactNode |
Child components to render inside | - |
userData |
object |
Associates custom data with the controller's RigidBody. This data can be useful for identifying specific RigidBodies in collision detection callbacks or managing related additional information (e.g., userData={{ type: 'Player', id: 'user123' }} ). See
|
- |
Defines settings for the light that follows the controller.
Property | Type | Description | Default Value |
---|---|---|---|
position |
Vector3 |
Light position offset relative to the controller. Defaults to [0, 1, 0] (shining down from above). |
[0, 1, 0] |
intensity |
number |
Light intensity. | 1 |
color |
Color |
Light color. |
0xffffff (white) |
shadowCameraNear |
number |
Near plane for the shadow camera's perspective frustum. | 0.5 |
shadowCameraFar |
number |
Far plane for the shadow camera's perspective frustum. | 50 |
shadowCameraLeft |
number |
Left plane for the shadow camera's perspective frustum. | -20 |
shadowCameraRight |
number |
Right plane for the shadow camera's perspective frustum. | 20 |
shadowCameraTop |
number |
Top plane for the shadow camera's perspective frustum. | 20 |
shadowCameraBottom |
number |
Bottom plane for the shadow camera's perspective frustum. | -20 |
shadowMapSize |
number[] |Vector2
|
Shadow map size (width, height). Must be powers of 2. Higher values improve shadow quality but increase computation time. | [2048, 2048] |
shadowBias |
number |
Shadow map bias. Very tiny adjustments (e.g., 0.0001) can help reduce shadow artifacts. | 0 |
shadowNormalBias |
number |
Offset along the object normal for shadow map queries. Helps reduce shadow acne, especially at shallow angles. | 0 |
Defines properties for the quarter view controller. (extends ControllerProps
)
Property | Type | Description | Default Value |
---|---|---|---|
followCharacter |
boolean |
Whether to follow the character | false |
inputMode |
'keyboard' | 'pointToMove'
|
Input mode | 'pointToMove' |
cameraMode |
'perspective' | 'orthographic'
|
Camera mode | 'perspective' |
Note: This interface inherits all properties from ControllerProps
.
Defines properties for the side view controller. (extends ControllerProps
)
Property | Type | Description | Default Value |
---|---|---|---|
cameraMode |
'perspective' | 'orthographic'
|
Camera mode | 'orthographic' |
Note: This interface inherits all properties from ControllerProps
.
Defines properties for the flight view controller. (Does not inherit ControllerProps)
Property | Type | Description | Default Value |
---|---|---|---|
minSpeed |
number |
Minimum flight speed (m/s) | 0 |
maxSpeed |
number |
Maximum flight speed (m/s) | 120 |
speedIncreasePerSecond |
number |
Speed increase per second (m/s) | 20 |
speedDecreasePerSecond |
number |
Speed decrease per second (m/s) | 80 |
pitchRotationSpeed |
number |
Pitch rotation speed | 0.5 |
rollRotationSpeed |
number |
Roll rotation speed | Math.PI |
directionRotationAcceleration |
number |
Direction rotation acceleration | 0.3 |
maxRollAngle |
number |
Maximum roll angle | Math.PI / 2 |
maxPitchAngle |
number |
Maximum pitch angle | Math.PI / 2 |
hitBodySize |
Vector3 |
Body size for collision detection | [1, 0.6, 3] |
followLightOffset |
Vector3 |
Light offset position | [-20, 30, 0] |
cameraOffset |
Vector3 |
Camera offset position | [0, 3, 15] |
onIntersectionEnter |
(event: CollisionPayload) => void |
Callback when collision starts | - |
onIntersectionExit |
(event: CollisionPayload) => void |
Callback when collision ends | - |
userData |
object |
Associates custom data with the controller's RigidBody. Useful for identifying specific RigidBodies in collision callbacks or managing related info (e.g., userData={{ type: 'Vehicle', id: 'falcon01' }} ). See
|
- |
Defines properties for the point-to-move view controller. (extends ControllerProps
)
Property | Type | Description | Default Value |
---|---|---|---|
followCharacter |
boolean |
Whether the camera follows the character | false |
cameraMode |
'perspective' | 'orthographic'
|
Camera mode | 'perspective' |
maxVelLimit |
number |
Maximum velocity limit for the character | 3 |
sprintMult |
number |
Multiplier for sprint speed | 2 |
zoom |
number |
Camera zoom level (adjusts distance and angle) | 1 |
Note: This interface inherits all properties from ControllerProps
.
- useMouseControls: Hook for mouse controls
-
useGame: Hook for managing game state, particularly for
moveToPoint
used in point-and-click movement.-
setMoveToPoint(point: THREE.Vector3)
: Function to set the target point for movement. -
moveToPoint: THREE.Vector3
: Current target point for movement.
-
-
useControllerState: Hook providing access to the controller's internal state.
-
rigidBody: RapierRigidBody | null
: Reference to the controller's Rapier rigid body. -
childrenGroup: THREE.Group | null
: Reference to the group containing children rendered inside the controller. -
userData: { [key: string]: any }
: Object containing additional user-defined data associated with the controller's state. -
setEnableInput: (enabled: boolean) => void
: Function to enable or disable controller input. -
setPosition: (position: THREE.Vector3) => void
: Function to set the controller's position. -
setRotation: (rotation: THREE.Quaternion) => void
: Function to set the controller's rotation. -
setVelocity: (velocity: THREE.Vector3) => void
: Function to set the controller's velocity. -
setMoveToPoint: (point: THREE.Vector3 | null) => void
: Function to set the target point for point-to-move navigation. -
isPointMoving: boolean
: Indicates whether the controller is currently moving towards a point.
-
import { CharacterRenderer } from 'vibe-starter-3d';
import { useRef } from 'react';
function MyCharacter() {
const actionRef = useRef<string>();
const characterResource = {
url: '/models/my-character.vrm',
animations: {
idle: '/animations/idle.fbx',
},
};
const animationConfig = {
idle: { loop: true },
};
return <CharacterRenderer characterResource={characterResource} animationConfigMap={animationConfig} currentActionRef={actionRef} />;
}
import { FreeViewController } from 'vibe-starter-3d';
function My3DScene() {
return <FreeViewController>{/* Typically place Player objects here */}</FreeViewController>;
}
import { FirstPersonViewController } from 'vibe-starter-3d';
function My3DScene() {
return <FirstPersonViewController>{/* Important: Never place character models here! */}</FirstPersonViewController>;
}
Important: Since FirstPersonViewController provides a first-person perspective, you should not place character models inside the controller. This is because the camera would be positioned inside the character model, causing obscured vision or camera clipping issues. In first-person perspective, the controller itself already acts as the player, so a separate character model is not needed. If necessary, place only weapon or hand models separately, and use full character models only in third-person perspectives.
import { useGame } from 'vibe-starter-3d';
import * as THREE from 'three';
function MyComponent() {
// Get the function to set the movement target point
const setMoveToPoint = useGame((state) => state.setMoveToPoint);
// Example: Set the target point when the user clicks
const handleCanvasClick = (event: MouseEvent) => {
// Assuming you have a way to calculate the 3D point from the click event
const clickPoint = new THREE.Vector3(/* calculated 3D coordinates */);
setMoveToPoint(clickPoint);
};
// ... rest of your component logic
}
import { useControllerState } from 'vibe-starter-3d';
import { useEffect, useRef } from 'react';
import { RapierRigidBody } from '@react-three/rapier';
function MyComponentInsideController() {
// Access the controller's rigid body and childrenGroup
const { rigidBody, childrenGroup, userData } = useControllerState();
const playerRef = useRef<RapierRigidBody>(null);
useEffect(() => {
if (rigidBody) {
console.log('Controller rigid body is available:', rigidBody);
// Example: Store the rigid body reference if needed
playerRef.current = rigidBody;
}
if (childrenGroup) {
// Example: Current controller Y offset
console.log('Current controller Y offset:', childrenGroup.position.y);
}
// Example: Accessing custom data if set via ControllerProps
console.log('User data from controller:', userData);
}, [rigidBody, childrenGroup, userData]);
// IMPORTANT: This component must be placed *inside* a controller component
// (e.g., FreeViewController, FirstPersonViewController) for the hook to work.
return <mesh>{/* Your component's visual representation */}</mesh>;
}
// Example Usage within a Controller:
// <FreeViewController >
// <MyComponentInsideController />
// </FreeViewController>
- React
- Three.js
- React Three Fiber
- React Three Drei
- Rapier Physics Engine
- VRM (Virtual Reality Model)