@series-inc/rundot-3d-engine 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,286 +1,286 @@
1
- # MeshRenderer
2
-
3
- MeshRenderer is a Component that loads and displays 3D meshes from the StowKit asset system. It handles async loading, shadows, and material management automatically.
4
-
5
- ## Quick Start
6
-
7
- ```typescript
8
- import { GameObject, MeshRenderer } from "@series-ai/rundot-3d-engine"
9
-
10
- // The correct pattern: MeshRenderer + child GameObject
11
- const renderer = new MeshRenderer("restaurant_display_Money")
12
- const rendererObject = new GameObject("RendererObject")
13
- rendererObject.addComponent(renderer)
14
- this.gameObject.add(rendererObject)
15
-
16
- // Optional: Position the mesh
17
- rendererObject.position.set(0, 2, 0)
18
- ```
19
-
20
- ## Common Use Cases
21
-
22
- ### Basic Mesh Loading
23
-
24
- ```typescript
25
- class Pickup extends Component {
26
- private rendererObject: GameObject | null = null
27
-
28
- protected onCreate(): void {
29
- // Load mesh using the child GameObject pattern
30
- const renderer = new MeshRenderer("restaurant_display_Money")
31
- this.rendererObject = new GameObject("PickupMesh")
32
- this.rendererObject.addComponent(renderer)
33
- this.gameObject.add(this.rendererObject)
34
-
35
- // Mesh loads async but shows automatically when ready
36
- }
37
- }
38
- ```
39
-
40
- ### Mesh with Custom Shadows
41
-
42
- ```typescript
43
- // Control shadow casting/receiving
44
- const renderer = new MeshRenderer(
45
- "character_mesh",
46
- true, // castShadow
47
- true // receiveShadow
48
- )
49
- ```
50
-
51
- ### Static Mesh (Performance Optimization)
52
-
53
- ```typescript
54
- // For non-moving objects - disables matrix updates
55
- const renderer = new MeshRenderer(
56
- "building_mesh",
57
- true, // castShadow
58
- true, // receiveShadow
59
- true // isStatic - better performance!
60
- )
61
- ```
62
-
63
- ### Custom Material Override
64
-
65
- ```typescript
66
- // Replace default material with custom one
67
- const customMaterial = new THREE.MeshStandardMaterial({
68
- color: 0xff0000,
69
- metalness: 0.5,
70
- roughness: 0.5
71
- })
72
-
73
- const renderer = new MeshRenderer(
74
- "prop_mesh",
75
- true,
76
- true,
77
- false,
78
- customMaterial // Override material
79
- )
80
- ```
81
-
82
- ### Checking Load State
83
-
84
- ```typescript
85
- class MyComponent extends Component {
86
- private meshRenderer?: MeshRenderer
87
-
88
- protected onCreate(): void {
89
- const rendererObject = new GameObject("Mesh")
90
- this.meshRenderer = new MeshRenderer("my_mesh")
91
- rendererObject.addComponent(this.meshRenderer)
92
- this.gameObject.add(rendererObject)
93
- }
94
-
95
- public update(deltaTime: number): void {
96
- if (this.meshRenderer && this.meshRenderer.isLoaded()) {
97
- // Mesh is ready, can get bounds, etc.
98
- const bounds = this.meshRenderer.getBounds()
99
- }
100
- }
101
- }
102
- ```
103
-
104
- ## API Overview
105
-
106
- ### Constructor
107
-
108
- ```typescript
109
- new MeshRenderer(
110
- meshName: string, // StowKit asset name
111
- castShadow?: boolean, // Default: true
112
- receiveShadow?: boolean, // Default: true
113
- isStatic?: boolean, // Default: false
114
- materialOverride?: THREE.Material | null // Default: null
115
- )
116
- ```
117
-
118
- ### Methods
119
-
120
- - `isLoaded(): boolean` - Check if mesh has finished loading
121
- - `getMesh(): THREE.Group | null` - Get the loaded mesh group
122
- - `getMeshName(): string` - Get the asset name
123
- - `getBounds(): THREE.Vector3 | null` - Get mesh bounding box size
124
- - `setVisible(visible: boolean): void` - Show/hide the mesh
125
- - `setMaterial(material: THREE.Material): void` - Override material
126
- - `setStatic(isStatic: boolean): void` - Toggle static optimization
127
- - `forceMatrixUpdate(): void` - Manually update transform (for static meshes)
128
-
129
- ### Lifecycle
130
-
131
- MeshRenderer handles loading automatically:
132
- 1. `onCreate()` - Starts async mesh load from StowKit
133
- 2. `update()` - Polls for load completion
134
- 3. Once loaded - Mesh appears in scene automatically
135
- 4. `onCleanup()` - Disposes geometry, materials, textures
136
-
137
- ## Patterns & Best Practices
138
-
139
- ### Always Use Child GameObject Pattern
140
-
141
- ```typescript
142
- // ✅ CORRECT - Use child GameObject for mesh
143
- private createMeshRenderer(): void {
144
- const renderer = new MeshRenderer("asset_name")
145
- this.rendererObject = new GameObject("RendererObject")
146
- this.rendererObject.addComponent(renderer)
147
- this.gameObject.add(this.rendererObject)
148
-
149
- // Can position/rotate the mesh independently
150
- this.rendererObject.position.set(0, 2, 0)
151
- }
152
-
153
- // ❌ INCORRECT - Don't use StowKitSystem directly
154
- private async createMeshRenderer(): Promise<void> {
155
- const stowkit = StowKitSystem.getInstance()
156
- const mesh = await stowkit.getMesh("asset_name")
157
- this.gameObject.add(mesh.clone())
158
- // Bypasses component lifecycle, harder to manage
159
- }
160
- ```
161
-
162
- ### Position Mesh Relative to Parent
163
-
164
- ```typescript
165
- // Good - Mesh as child allows offset
166
- const character = new GameObject("Character")
167
- const visualsObject = new GameObject("Visuals")
168
- const renderer = new MeshRenderer("character_mesh")
169
- visualsObject.addComponent(renderer)
170
- character.add(visualsObject)
171
-
172
- // Offset visual from collision center
173
- visualsObject.position.set(0, -0.5, 0)
174
- ```
175
-
176
- ### Use Static for Non-Moving Objects
177
-
178
- ```typescript
179
- // Buildings, terrain, props that never move
180
- const renderer = new MeshRenderer("building", true, true, true)
181
- // Saves CPU by disabling matrix updates
182
-
183
- // After moving a static mesh, force update:
184
- renderer.forceMatrixUpdate()
185
- ```
186
-
187
- ### Check Loaded Before Accessing
188
-
189
- ```typescript
190
- public update(deltaTime: number): void {
191
- if (this.meshRenderer?.isLoaded()) {
192
- // Safe to use mesh methods
193
- const bounds = this.meshRenderer.getBounds()
194
- }
195
- }
196
- ```
197
-
198
- ## Anti-Patterns
199
-
200
- ### Don't Load Meshes Directly
201
-
202
- ```typescript
203
- // ❌ Bad - Bypasses component system
204
- const stowkit = StowKitSystem.getInstance()
205
- const mesh = await stowkit.getMesh("mesh_name")
206
- this.gameObject.add(mesh)
207
-
208
- // ✅ Good - Use MeshRenderer component
209
- const renderer = new MeshRenderer("mesh_name")
210
- const meshObj = new GameObject("Mesh")
211
- meshObj.addComponent(renderer)
212
- this.gameObject.add(meshObj)
213
- ```
214
-
215
- ### Don't Forget Cleanup
216
-
217
- ```typescript
218
- // ❌ Bad - MeshRenderer cleans up automatically in onCleanup
219
- // Just dispose the GameObject
220
- this.rendererObject?.dispose()
221
-
222
- // ✅ Good - Let MeshRenderer handle cleanup
223
- // It disposes geometry, materials, textures automatically
224
- ```
225
-
226
- ### Don't Add Multiple MeshRenderers to Same GameObject
227
-
228
- ```typescript
229
- // ❌ Bad - Components of same type conflict
230
- const obj = new GameObject("Object")
231
- obj.addComponent(new MeshRenderer("mesh1")) // Error!
232
- obj.addComponent(new MeshRenderer("mesh2")) // Throws!
233
-
234
- // ✅ Good - Use child GameObjects
235
- const parent = new GameObject("Parent")
236
-
237
- const child1 = new GameObject("Mesh1")
238
- child1.addComponent(new MeshRenderer("mesh1"))
239
- parent.add(child1)
240
-
241
- const child2 = new GameObject("Mesh2")
242
- child2.addComponent(new MeshRenderer("mesh2"))
243
- parent.add(child2)
244
- ```
245
-
246
- ## Performance Tips
247
-
248
- ### Static Meshes
249
-
250
- Static meshes (isStatic=true) skip matrix calculations each frame:
251
- - Use for buildings, terrain, decorations
252
- - Saves significant CPU on scenes with many objects
253
- - Call `forceMatrixUpdate()` if you need to move them
254
-
255
- ### Shadow Configuration
256
-
257
- Shadows have performance cost:
258
- ```typescript
259
- // Disable shadows for small/distant objects
260
- const renderer = new MeshRenderer("prop", false, false)
261
-
262
- // Enable only for important objects
263
- const playerRenderer = new MeshRenderer("player", true, true)
264
- ```
265
-
266
- ### Material Overrides
267
-
268
- Reusing materials is more efficient:
269
- ```typescript
270
- // Share material across multiple MeshRenderers
271
- const sharedMaterial = new THREE.MeshStandardMaterial({ color: 0xff0000 })
272
-
273
- const renderer1 = new MeshRenderer("mesh1", true, true, false, sharedMaterial)
274
- const renderer2 = new MeshRenderer("mesh2", true, true, false, sharedMaterial)
275
- // Both use same material instance - better performance
276
- ```
277
-
278
- ## Related Systems
279
-
280
- - [GameObject](../core/GameObject.md) - Entity class for MeshRenderer
281
- - [Component](../core/Component.md) - Base class for MeshRenderer
282
- - [StowKitSystem](../systems/StowKitSystem.md) - Asset loading system
283
- - [InstancedRenderer](InstancedRenderer.md) - For many copies of same mesh
284
- - [SkeletalRenderer](SkeletalRenderer.md) - For animated characters
285
- - [Mesh Loading Pattern](../patterns/MeshLoading.md) - Detailed pattern guide
286
-
1
+ # MeshRenderer
2
+
3
+ MeshRenderer is a Component that loads and displays 3D meshes from the StowKit asset system. It handles async loading, shadows, and material management automatically.
4
+
5
+ ## Quick Start
6
+
7
+ ```typescript
8
+ import { GameObject, MeshRenderer } from "@series-ai/rundot-3d-engine"
9
+
10
+ // The correct pattern: MeshRenderer + child GameObject
11
+ const renderer = new MeshRenderer("restaurant_display_Money")
12
+ const rendererObject = new GameObject("RendererObject")
13
+ rendererObject.addComponent(renderer)
14
+ this.gameObject.add(rendererObject)
15
+
16
+ // Optional: Position the mesh
17
+ rendererObject.position.set(0, 2, 0)
18
+ ```
19
+
20
+ ## Common Use Cases
21
+
22
+ ### Basic Mesh Loading
23
+
24
+ ```typescript
25
+ class Pickup extends Component {
26
+ private rendererObject: GameObject | null = null
27
+
28
+ protected onCreate(): void {
29
+ // Load mesh using the child GameObject pattern
30
+ const renderer = new MeshRenderer("restaurant_display_Money")
31
+ this.rendererObject = new GameObject("PickupMesh")
32
+ this.rendererObject.addComponent(renderer)
33
+ this.gameObject.add(this.rendererObject)
34
+
35
+ // Mesh loads async but shows automatically when ready
36
+ }
37
+ }
38
+ ```
39
+
40
+ ### Mesh with Custom Shadows
41
+
42
+ ```typescript
43
+ // Control shadow casting/receiving
44
+ const renderer = new MeshRenderer(
45
+ "character_mesh",
46
+ true, // castShadow
47
+ true // receiveShadow
48
+ )
49
+ ```
50
+
51
+ ### Static Mesh (Performance Optimization)
52
+
53
+ ```typescript
54
+ // For non-moving objects - disables matrix updates
55
+ const renderer = new MeshRenderer(
56
+ "building_mesh",
57
+ true, // castShadow
58
+ true, // receiveShadow
59
+ true // isStatic - better performance!
60
+ )
61
+ ```
62
+
63
+ ### Custom Material Override
64
+
65
+ ```typescript
66
+ // Replace default material with custom one
67
+ const customMaterial = new THREE.MeshStandardMaterial({
68
+ color: 0xff0000,
69
+ metalness: 0.5,
70
+ roughness: 0.5
71
+ })
72
+
73
+ const renderer = new MeshRenderer(
74
+ "prop_mesh",
75
+ true,
76
+ true,
77
+ false,
78
+ customMaterial // Override material
79
+ )
80
+ ```
81
+
82
+ ### Checking Load State
83
+
84
+ ```typescript
85
+ class MyComponent extends Component {
86
+ private meshRenderer?: MeshRenderer
87
+
88
+ protected onCreate(): void {
89
+ const rendererObject = new GameObject("Mesh")
90
+ this.meshRenderer = new MeshRenderer("my_mesh")
91
+ rendererObject.addComponent(this.meshRenderer)
92
+ this.gameObject.add(rendererObject)
93
+ }
94
+
95
+ public update(deltaTime: number): void {
96
+ if (this.meshRenderer && this.meshRenderer.isLoaded()) {
97
+ // Mesh is ready, can get bounds, etc.
98
+ const bounds = this.meshRenderer.getBounds()
99
+ }
100
+ }
101
+ }
102
+ ```
103
+
104
+ ## API Overview
105
+
106
+ ### Constructor
107
+
108
+ ```typescript
109
+ new MeshRenderer(
110
+ meshName: string, // StowKit asset name
111
+ castShadow?: boolean, // Default: true
112
+ receiveShadow?: boolean, // Default: true
113
+ isStatic?: boolean, // Default: false
114
+ materialOverride?: THREE.Material | null // Default: null
115
+ )
116
+ ```
117
+
118
+ ### Methods
119
+
120
+ - `isLoaded(): boolean` - Check if mesh has finished loading
121
+ - `getMesh(): THREE.Group | null` - Get the loaded mesh group
122
+ - `getMeshName(): string` - Get the asset name
123
+ - `getBounds(): THREE.Vector3 | null` - Get mesh bounding box size
124
+ - `setVisible(visible: boolean): void` - Show/hide the mesh
125
+ - `setMaterial(material: THREE.Material): void` - Override material
126
+ - `setStatic(isStatic: boolean): void` - Toggle static optimization
127
+ - `forceMatrixUpdate(): void` - Manually update transform (for static meshes)
128
+
129
+ ### Lifecycle
130
+
131
+ MeshRenderer handles loading automatically:
132
+ 1. `onCreate()` - Starts async mesh load from StowKit
133
+ 2. `update()` - Polls for load completion
134
+ 3. Once loaded - Mesh appears in scene automatically
135
+ 4. `onCleanup()` - Disposes geometry, materials, textures
136
+
137
+ ## Patterns & Best Practices
138
+
139
+ ### Always Use Child GameObject Pattern
140
+
141
+ ```typescript
142
+ // ✅ CORRECT - Use child GameObject for mesh
143
+ private createMeshRenderer(): void {
144
+ const renderer = new MeshRenderer("asset_name")
145
+ this.rendererObject = new GameObject("RendererObject")
146
+ this.rendererObject.addComponent(renderer)
147
+ this.gameObject.add(this.rendererObject)
148
+
149
+ // Can position/rotate the mesh independently
150
+ this.rendererObject.position.set(0, 2, 0)
151
+ }
152
+
153
+ // ❌ INCORRECT - Don't use StowKitSystem directly
154
+ private async createMeshRenderer(): Promise<void> {
155
+ const stowkit = StowKitSystem.getInstance()
156
+ const mesh = await stowkit.getMesh("asset_name")
157
+ this.gameObject.add(mesh.clone())
158
+ // Bypasses component lifecycle, harder to manage
159
+ }
160
+ ```
161
+
162
+ ### Position Mesh Relative to Parent
163
+
164
+ ```typescript
165
+ // Good - Mesh as child allows offset
166
+ const character = new GameObject("Character")
167
+ const visualsObject = new GameObject("Visuals")
168
+ const renderer = new MeshRenderer("character_mesh")
169
+ visualsObject.addComponent(renderer)
170
+ character.add(visualsObject)
171
+
172
+ // Offset visual from collision center
173
+ visualsObject.position.set(0, -0.5, 0)
174
+ ```
175
+
176
+ ### Use Static for Non-Moving Objects
177
+
178
+ ```typescript
179
+ // Buildings, terrain, props that never move
180
+ const renderer = new MeshRenderer("building", true, true, true)
181
+ // Saves CPU by disabling matrix updates
182
+
183
+ // After moving a static mesh, force update:
184
+ renderer.forceMatrixUpdate()
185
+ ```
186
+
187
+ ### Check Loaded Before Accessing
188
+
189
+ ```typescript
190
+ public update(deltaTime: number): void {
191
+ if (this.meshRenderer?.isLoaded()) {
192
+ // Safe to use mesh methods
193
+ const bounds = this.meshRenderer.getBounds()
194
+ }
195
+ }
196
+ ```
197
+
198
+ ## Anti-Patterns
199
+
200
+ ### Don't Load Meshes Directly
201
+
202
+ ```typescript
203
+ // ❌ Bad - Bypasses component system
204
+ const stowkit = StowKitSystem.getInstance()
205
+ const mesh = await stowkit.getMesh("mesh_name")
206
+ this.gameObject.add(mesh)
207
+
208
+ // ✅ Good - Use MeshRenderer component
209
+ const renderer = new MeshRenderer("mesh_name")
210
+ const meshObj = new GameObject("Mesh")
211
+ meshObj.addComponent(renderer)
212
+ this.gameObject.add(meshObj)
213
+ ```
214
+
215
+ ### Don't Forget Cleanup
216
+
217
+ ```typescript
218
+ // ❌ Bad - MeshRenderer cleans up automatically in onCleanup
219
+ // Just dispose the GameObject
220
+ this.rendererObject?.dispose()
221
+
222
+ // ✅ Good - Let MeshRenderer handle cleanup
223
+ // It disposes geometry, materials, textures automatically
224
+ ```
225
+
226
+ ### Don't Add Multiple MeshRenderers to Same GameObject
227
+
228
+ ```typescript
229
+ // ❌ Bad - Components of same type conflict
230
+ const obj = new GameObject("Object")
231
+ obj.addComponent(new MeshRenderer("mesh1")) // Error!
232
+ obj.addComponent(new MeshRenderer("mesh2")) // Throws!
233
+
234
+ // ✅ Good - Use child GameObjects
235
+ const parent = new GameObject("Parent")
236
+
237
+ const child1 = new GameObject("Mesh1")
238
+ child1.addComponent(new MeshRenderer("mesh1"))
239
+ parent.add(child1)
240
+
241
+ const child2 = new GameObject("Mesh2")
242
+ child2.addComponent(new MeshRenderer("mesh2"))
243
+ parent.add(child2)
244
+ ```
245
+
246
+ ## Performance Tips
247
+
248
+ ### Static Meshes
249
+
250
+ Static meshes (isStatic=true) skip matrix calculations each frame:
251
+ - Use for buildings, terrain, decorations
252
+ - Saves significant CPU on scenes with many objects
253
+ - Call `forceMatrixUpdate()` if you need to move them
254
+
255
+ ### Shadow Configuration
256
+
257
+ Shadows have performance cost:
258
+ ```typescript
259
+ // Disable shadows for small/distant objects
260
+ const renderer = new MeshRenderer("prop", false, false)
261
+
262
+ // Enable only for important objects
263
+ const playerRenderer = new MeshRenderer("player", true, true)
264
+ ```
265
+
266
+ ### Material Overrides
267
+
268
+ Reusing materials is more efficient:
269
+ ```typescript
270
+ // Share material across multiple MeshRenderers
271
+ const sharedMaterial = new THREE.MeshStandardMaterial({ color: 0xff0000 })
272
+
273
+ const renderer1 = new MeshRenderer("mesh1", true, true, false, sharedMaterial)
274
+ const renderer2 = new MeshRenderer("mesh2", true, true, false, sharedMaterial)
275
+ // Both use same material instance - better performance
276
+ ```
277
+
278
+ ## Related Systems
279
+
280
+ - [GameObject](../core/GameObject.md) - Entity class for MeshRenderer
281
+ - [Component](../core/Component.md) - Base class for MeshRenderer
282
+ - [StowKitSystem](../systems/StowKitSystem.md) - Asset loading system
283
+ - [InstancedRenderer](InstancedRenderer.md) - For many copies of same mesh
284
+ - [SkeletalRenderer](SkeletalRenderer.md) - For animated characters
285
+ - [Mesh Loading Pattern](../patterns/MeshLoading.md) - Detailed pattern guide
286
+