sumulige-claude 1.4.1 → 1.5.1
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.
- package/.claude/MEMORY.md +26 -0
- package/.claude/hooks/hook-registry.json +15 -0
- package/.claude/hooks/live-quality.cjs +286 -0
- package/.claude/hooks/plan-gate.cjs +173 -0
- package/.claude/hooks/pre-commit.cjs +15 -4
- package/.claude/quality-gate.json +19 -4
- package/.claude/rules/linus-style.md +54 -0
- package/.claude/rules/web-design-standard.md +207 -0
- package/.claude/settings.json +19 -1
- package/.claude/settings.local.json +13 -3
- package/.claude/skills/react-best-practices/SKILL.md +125 -0
- package/.claude/skills/threejs-fundamentals/SKILL.md +488 -0
- package/.claude/skills/web-design-guidelines/SKILL.md +39 -0
- package/AGENTS.md +0 -54
- package/CHANGELOG.md +107 -0
- package/demos/power-3d-scatter.html +683 -0
- package/package.json +1 -1
- package/prompts/linus-architect.md +71 -0
- package/prompts/software-architect.md +173 -0
- package/prompts/web-designer.md +249 -0
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: threejs-fundamentals
|
|
3
|
+
description: Three.js scene setup, cameras, renderer, Object3D hierarchy, coordinate systems. Use when setting up 3D scenes, creating cameras, configuring renderers, managing object hierarchies, or working with transforms.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Three.js Fundamentals
|
|
7
|
+
|
|
8
|
+
## Quick Start
|
|
9
|
+
|
|
10
|
+
```javascript
|
|
11
|
+
import * as THREE from "three";
|
|
12
|
+
|
|
13
|
+
// Create scene, camera, renderer
|
|
14
|
+
const scene = new THREE.Scene();
|
|
15
|
+
const camera = new THREE.PerspectiveCamera(
|
|
16
|
+
75,
|
|
17
|
+
window.innerWidth / window.innerHeight,
|
|
18
|
+
0.1,
|
|
19
|
+
1000,
|
|
20
|
+
);
|
|
21
|
+
const renderer = new THREE.WebGLRenderer({ antialias: true });
|
|
22
|
+
|
|
23
|
+
renderer.setSize(window.innerWidth, window.innerHeight);
|
|
24
|
+
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
|
|
25
|
+
document.body.appendChild(renderer.domElement);
|
|
26
|
+
|
|
27
|
+
// Add a mesh
|
|
28
|
+
const geometry = new THREE.BoxGeometry(1, 1, 1);
|
|
29
|
+
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
|
|
30
|
+
const cube = new THREE.Mesh(geometry, material);
|
|
31
|
+
scene.add(cube);
|
|
32
|
+
|
|
33
|
+
// Add light
|
|
34
|
+
scene.add(new THREE.AmbientLight(0xffffff, 0.5));
|
|
35
|
+
const dirLight = new THREE.DirectionalLight(0xffffff, 1);
|
|
36
|
+
dirLight.position.set(5, 5, 5);
|
|
37
|
+
scene.add(dirLight);
|
|
38
|
+
|
|
39
|
+
camera.position.z = 5;
|
|
40
|
+
|
|
41
|
+
// Animation loop
|
|
42
|
+
function animate() {
|
|
43
|
+
requestAnimationFrame(animate);
|
|
44
|
+
cube.rotation.x += 0.01;
|
|
45
|
+
cube.rotation.y += 0.01;
|
|
46
|
+
renderer.render(scene, camera);
|
|
47
|
+
}
|
|
48
|
+
animate();
|
|
49
|
+
|
|
50
|
+
// Handle resize
|
|
51
|
+
window.addEventListener("resize", () => {
|
|
52
|
+
camera.aspect = window.innerWidth / window.innerHeight;
|
|
53
|
+
camera.updateProjectionMatrix();
|
|
54
|
+
renderer.setSize(window.innerWidth, window.innerHeight);
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Core Classes
|
|
59
|
+
|
|
60
|
+
### Scene
|
|
61
|
+
|
|
62
|
+
Container for all 3D objects, lights, and cameras.
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
const scene = new THREE.Scene();
|
|
66
|
+
scene.background = new THREE.Color(0x000000); // Solid color
|
|
67
|
+
scene.background = texture; // Skybox texture
|
|
68
|
+
scene.background = cubeTexture; // Cubemap
|
|
69
|
+
scene.environment = envMap; // Environment map for PBR
|
|
70
|
+
scene.fog = new THREE.Fog(0xffffff, 1, 100); // Linear fog
|
|
71
|
+
scene.fog = new THREE.FogExp2(0xffffff, 0.02); // Exponential fog
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Cameras
|
|
75
|
+
|
|
76
|
+
**PerspectiveCamera** - Most common, simulates human eye.
|
|
77
|
+
|
|
78
|
+
```javascript
|
|
79
|
+
// PerspectiveCamera(fov, aspect, near, far)
|
|
80
|
+
const camera = new THREE.PerspectiveCamera(
|
|
81
|
+
75, // Field of view (degrees)
|
|
82
|
+
window.innerWidth / window.innerHeight, // Aspect ratio
|
|
83
|
+
0.1, // Near clipping plane
|
|
84
|
+
1000, // Far clipping plane
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
camera.position.set(0, 5, 10);
|
|
88
|
+
camera.lookAt(0, 0, 0);
|
|
89
|
+
camera.updateProjectionMatrix(); // Call after changing fov, aspect, near, far
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**OrthographicCamera** - No perspective distortion, good for 2D/isometric.
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
// OrthographicCamera(left, right, top, bottom, near, far)
|
|
96
|
+
const aspect = window.innerWidth / window.innerHeight;
|
|
97
|
+
const frustumSize = 10;
|
|
98
|
+
const camera = new THREE.OrthographicCamera(
|
|
99
|
+
(frustumSize * aspect) / -2,
|
|
100
|
+
(frustumSize * aspect) / 2,
|
|
101
|
+
frustumSize / 2,
|
|
102
|
+
frustumSize / -2,
|
|
103
|
+
0.1,
|
|
104
|
+
1000,
|
|
105
|
+
);
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**ArrayCamera** - Multiple viewports with sub-cameras.
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
const cameras = [];
|
|
112
|
+
for (let i = 0; i < 4; i++) {
|
|
113
|
+
const subcamera = new THREE.PerspectiveCamera(40, 1, 0.1, 100);
|
|
114
|
+
subcamera.viewport = new THREE.Vector4(
|
|
115
|
+
Math.floor(i % 2) * 0.5,
|
|
116
|
+
Math.floor(i / 2) * 0.5,
|
|
117
|
+
0.5,
|
|
118
|
+
0.5,
|
|
119
|
+
);
|
|
120
|
+
cameras.push(subcamera);
|
|
121
|
+
}
|
|
122
|
+
const arrayCamera = new THREE.ArrayCamera(cameras);
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**CubeCamera** - Renders environment maps for reflections.
|
|
126
|
+
|
|
127
|
+
```javascript
|
|
128
|
+
const cubeRenderTarget = new THREE.WebGLCubeRenderTarget(256);
|
|
129
|
+
const cubeCamera = new THREE.CubeCamera(0.1, 1000, cubeRenderTarget);
|
|
130
|
+
scene.add(cubeCamera);
|
|
131
|
+
|
|
132
|
+
// Use for reflections
|
|
133
|
+
material.envMap = cubeRenderTarget.texture;
|
|
134
|
+
|
|
135
|
+
// Update each frame (expensive!)
|
|
136
|
+
cubeCamera.position.copy(reflectiveMesh.position);
|
|
137
|
+
cubeCamera.update(renderer, scene);
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### WebGLRenderer
|
|
141
|
+
|
|
142
|
+
```javascript
|
|
143
|
+
const renderer = new THREE.WebGLRenderer({
|
|
144
|
+
canvas: document.querySelector("#canvas"), // Optional existing canvas
|
|
145
|
+
antialias: true, // Smooth edges
|
|
146
|
+
alpha: true, // Transparent background
|
|
147
|
+
powerPreference: "high-performance", // GPU hint
|
|
148
|
+
preserveDrawingBuffer: true, // For screenshots
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
renderer.setSize(width, height);
|
|
152
|
+
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
|
|
153
|
+
|
|
154
|
+
// Tone mapping
|
|
155
|
+
renderer.toneMapping = THREE.ACESFilmicToneMapping;
|
|
156
|
+
renderer.toneMappingExposure = 1.0;
|
|
157
|
+
|
|
158
|
+
// Color space (Three.js r152+)
|
|
159
|
+
renderer.outputColorSpace = THREE.SRGBColorSpace;
|
|
160
|
+
|
|
161
|
+
// Shadows
|
|
162
|
+
renderer.shadowMap.enabled = true;
|
|
163
|
+
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
|
164
|
+
|
|
165
|
+
// Clear color
|
|
166
|
+
renderer.setClearColor(0x000000, 1);
|
|
167
|
+
|
|
168
|
+
// Render
|
|
169
|
+
renderer.render(scene, camera);
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Object3D
|
|
173
|
+
|
|
174
|
+
Base class for all 3D objects. Mesh, Group, Light, Camera all extend Object3D.
|
|
175
|
+
|
|
176
|
+
```javascript
|
|
177
|
+
const obj = new THREE.Object3D();
|
|
178
|
+
|
|
179
|
+
// Transform
|
|
180
|
+
obj.position.set(x, y, z);
|
|
181
|
+
obj.rotation.set(x, y, z); // Euler angles (radians)
|
|
182
|
+
obj.quaternion.set(x, y, z, w); // Quaternion rotation
|
|
183
|
+
obj.scale.set(x, y, z);
|
|
184
|
+
|
|
185
|
+
// Local vs World transforms
|
|
186
|
+
obj.getWorldPosition(targetVector);
|
|
187
|
+
obj.getWorldQuaternion(targetQuaternion);
|
|
188
|
+
obj.getWorldDirection(targetVector);
|
|
189
|
+
|
|
190
|
+
// Hierarchy
|
|
191
|
+
obj.add(child);
|
|
192
|
+
obj.remove(child);
|
|
193
|
+
obj.parent;
|
|
194
|
+
obj.children;
|
|
195
|
+
|
|
196
|
+
// Visibility
|
|
197
|
+
obj.visible = false;
|
|
198
|
+
|
|
199
|
+
// Layers (for selective rendering/raycasting)
|
|
200
|
+
obj.layers.set(1);
|
|
201
|
+
obj.layers.enable(2);
|
|
202
|
+
obj.layers.disable(0);
|
|
203
|
+
|
|
204
|
+
// Traverse hierarchy
|
|
205
|
+
obj.traverse((child) => {
|
|
206
|
+
if (child.isMesh) child.material.color.set(0xff0000);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// Matrix updates
|
|
210
|
+
obj.matrixAutoUpdate = true; // Default: auto-update matrices
|
|
211
|
+
obj.updateMatrix(); // Manual matrix update
|
|
212
|
+
obj.updateMatrixWorld(true); // Update world matrix recursively
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Group
|
|
216
|
+
|
|
217
|
+
Empty container for organizing objects.
|
|
218
|
+
|
|
219
|
+
```javascript
|
|
220
|
+
const group = new THREE.Group();
|
|
221
|
+
group.add(mesh1);
|
|
222
|
+
group.add(mesh2);
|
|
223
|
+
scene.add(group);
|
|
224
|
+
|
|
225
|
+
// Transform entire group
|
|
226
|
+
group.position.x = 5;
|
|
227
|
+
group.rotation.y = Math.PI / 4;
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Mesh
|
|
231
|
+
|
|
232
|
+
Combines geometry and material.
|
|
233
|
+
|
|
234
|
+
```javascript
|
|
235
|
+
const mesh = new THREE.Mesh(geometry, material);
|
|
236
|
+
|
|
237
|
+
// Multiple materials (one per geometry group)
|
|
238
|
+
const mesh = new THREE.Mesh(geometry, [material1, material2]);
|
|
239
|
+
|
|
240
|
+
// Useful properties
|
|
241
|
+
mesh.geometry;
|
|
242
|
+
mesh.material;
|
|
243
|
+
mesh.castShadow = true;
|
|
244
|
+
mesh.receiveShadow = true;
|
|
245
|
+
|
|
246
|
+
// Frustum culling
|
|
247
|
+
mesh.frustumCulled = true; // Default: skip if outside camera view
|
|
248
|
+
|
|
249
|
+
// Render order
|
|
250
|
+
mesh.renderOrder = 10; // Higher = rendered later
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Coordinate System
|
|
254
|
+
|
|
255
|
+
Three.js uses a **right-handed coordinate system**:
|
|
256
|
+
|
|
257
|
+
- **+X** points right
|
|
258
|
+
- **+Y** points up
|
|
259
|
+
- **+Z** points toward viewer (out of screen)
|
|
260
|
+
|
|
261
|
+
```javascript
|
|
262
|
+
// Axes helper
|
|
263
|
+
const axesHelper = new THREE.AxesHelper(5);
|
|
264
|
+
scene.add(axesHelper); // Red=X, Green=Y, Blue=Z
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Math Utilities
|
|
268
|
+
|
|
269
|
+
### Vector3
|
|
270
|
+
|
|
271
|
+
```javascript
|
|
272
|
+
const v = new THREE.Vector3(x, y, z);
|
|
273
|
+
v.set(x, y, z);
|
|
274
|
+
v.copy(otherVector);
|
|
275
|
+
v.clone();
|
|
276
|
+
|
|
277
|
+
// Operations (modify in place)
|
|
278
|
+
v.add(v2);
|
|
279
|
+
v.sub(v2);
|
|
280
|
+
v.multiply(v2);
|
|
281
|
+
v.multiplyScalar(2);
|
|
282
|
+
v.divideScalar(2);
|
|
283
|
+
v.normalize();
|
|
284
|
+
v.negate();
|
|
285
|
+
v.clamp(min, max);
|
|
286
|
+
v.lerp(target, alpha);
|
|
287
|
+
|
|
288
|
+
// Calculations (return new value)
|
|
289
|
+
v.length();
|
|
290
|
+
v.lengthSq(); // Faster than length()
|
|
291
|
+
v.distanceTo(v2);
|
|
292
|
+
v.dot(v2);
|
|
293
|
+
v.cross(v2); // Modifies v
|
|
294
|
+
v.angleTo(v2);
|
|
295
|
+
|
|
296
|
+
// Transform
|
|
297
|
+
v.applyMatrix4(matrix);
|
|
298
|
+
v.applyQuaternion(q);
|
|
299
|
+
v.project(camera); // World to NDC
|
|
300
|
+
v.unproject(camera); // NDC to world
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Matrix4
|
|
304
|
+
|
|
305
|
+
```javascript
|
|
306
|
+
const m = new THREE.Matrix4();
|
|
307
|
+
m.identity();
|
|
308
|
+
m.copy(other);
|
|
309
|
+
m.clone();
|
|
310
|
+
|
|
311
|
+
// Build transforms
|
|
312
|
+
m.makeTranslation(x, y, z);
|
|
313
|
+
m.makeRotationX(theta);
|
|
314
|
+
m.makeRotationY(theta);
|
|
315
|
+
m.makeRotationZ(theta);
|
|
316
|
+
m.makeRotationFromQuaternion(q);
|
|
317
|
+
m.makeScale(x, y, z);
|
|
318
|
+
|
|
319
|
+
// Compose/decompose
|
|
320
|
+
m.compose(position, quaternion, scale);
|
|
321
|
+
m.decompose(position, quaternion, scale);
|
|
322
|
+
|
|
323
|
+
// Operations
|
|
324
|
+
m.multiply(m2); // m = m * m2
|
|
325
|
+
m.premultiply(m2); // m = m2 * m
|
|
326
|
+
m.invert();
|
|
327
|
+
m.transpose();
|
|
328
|
+
|
|
329
|
+
// Camera matrices
|
|
330
|
+
m.makePerspective(left, right, top, bottom, near, far);
|
|
331
|
+
m.makeOrthographic(left, right, top, bottom, near, far);
|
|
332
|
+
m.lookAt(eye, target, up);
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Quaternion
|
|
336
|
+
|
|
337
|
+
```javascript
|
|
338
|
+
const q = new THREE.Quaternion();
|
|
339
|
+
q.setFromEuler(euler);
|
|
340
|
+
q.setFromAxisAngle(axis, angle);
|
|
341
|
+
q.setFromRotationMatrix(matrix);
|
|
342
|
+
|
|
343
|
+
q.multiply(q2);
|
|
344
|
+
q.slerp(target, t); // Spherical interpolation
|
|
345
|
+
q.normalize();
|
|
346
|
+
q.invert();
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Euler
|
|
350
|
+
|
|
351
|
+
```javascript
|
|
352
|
+
const euler = new THREE.Euler(x, y, z, "XYZ"); // Order matters!
|
|
353
|
+
euler.setFromQuaternion(q);
|
|
354
|
+
euler.setFromRotationMatrix(m);
|
|
355
|
+
|
|
356
|
+
// Rotation orders: 'XYZ', 'YXZ', 'ZXY', 'XZY', 'YZX', 'ZYX'
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### Color
|
|
360
|
+
|
|
361
|
+
```javascript
|
|
362
|
+
const color = new THREE.Color(0xff0000);
|
|
363
|
+
const color = new THREE.Color("red");
|
|
364
|
+
const color = new THREE.Color("rgb(255, 0, 0)");
|
|
365
|
+
const color = new THREE.Color("#ff0000");
|
|
366
|
+
|
|
367
|
+
color.setHex(0x00ff00);
|
|
368
|
+
color.setRGB(r, g, b); // 0-1 range
|
|
369
|
+
color.setHSL(h, s, l); // 0-1 range
|
|
370
|
+
|
|
371
|
+
color.lerp(otherColor, alpha);
|
|
372
|
+
color.multiply(otherColor);
|
|
373
|
+
color.multiplyScalar(2);
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### MathUtils
|
|
377
|
+
|
|
378
|
+
```javascript
|
|
379
|
+
THREE.MathUtils.clamp(value, min, max);
|
|
380
|
+
THREE.MathUtils.lerp(start, end, alpha);
|
|
381
|
+
THREE.MathUtils.mapLinear(value, inMin, inMax, outMin, outMax);
|
|
382
|
+
THREE.MathUtils.degToRad(degrees);
|
|
383
|
+
THREE.MathUtils.radToDeg(radians);
|
|
384
|
+
THREE.MathUtils.randFloat(min, max);
|
|
385
|
+
THREE.MathUtils.randInt(min, max);
|
|
386
|
+
THREE.MathUtils.smoothstep(x, min, max);
|
|
387
|
+
THREE.MathUtils.smootherstep(x, min, max);
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
## Common Patterns
|
|
391
|
+
|
|
392
|
+
### Proper Cleanup
|
|
393
|
+
|
|
394
|
+
```javascript
|
|
395
|
+
function dispose() {
|
|
396
|
+
// Dispose geometries
|
|
397
|
+
mesh.geometry.dispose();
|
|
398
|
+
|
|
399
|
+
// Dispose materials
|
|
400
|
+
if (Array.isArray(mesh.material)) {
|
|
401
|
+
mesh.material.forEach((m) => m.dispose());
|
|
402
|
+
} else {
|
|
403
|
+
mesh.material.dispose();
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Dispose textures
|
|
407
|
+
texture.dispose();
|
|
408
|
+
|
|
409
|
+
// Remove from scene
|
|
410
|
+
scene.remove(mesh);
|
|
411
|
+
|
|
412
|
+
// Dispose renderer
|
|
413
|
+
renderer.dispose();
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### Clock for Animation
|
|
418
|
+
|
|
419
|
+
```javascript
|
|
420
|
+
const clock = new THREE.Clock();
|
|
421
|
+
|
|
422
|
+
function animate() {
|
|
423
|
+
const delta = clock.getDelta(); // Time since last frame (seconds)
|
|
424
|
+
const elapsed = clock.getElapsedTime(); // Total time (seconds)
|
|
425
|
+
|
|
426
|
+
mesh.rotation.y += delta * 0.5; // Consistent speed regardless of framerate
|
|
427
|
+
|
|
428
|
+
requestAnimationFrame(animate);
|
|
429
|
+
renderer.render(scene, camera);
|
|
430
|
+
}
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### Responsive Canvas
|
|
434
|
+
|
|
435
|
+
```javascript
|
|
436
|
+
function onWindowResize() {
|
|
437
|
+
const width = window.innerWidth;
|
|
438
|
+
const height = window.innerHeight;
|
|
439
|
+
|
|
440
|
+
camera.aspect = width / height;
|
|
441
|
+
camera.updateProjectionMatrix();
|
|
442
|
+
|
|
443
|
+
renderer.setSize(width, height);
|
|
444
|
+
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
|
|
445
|
+
}
|
|
446
|
+
window.addEventListener("resize", onWindowResize);
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
### Loading Manager
|
|
450
|
+
|
|
451
|
+
```javascript
|
|
452
|
+
const manager = new THREE.LoadingManager();
|
|
453
|
+
|
|
454
|
+
manager.onStart = (url, loaded, total) => console.log("Started loading");
|
|
455
|
+
manager.onLoad = () => console.log("All loaded");
|
|
456
|
+
manager.onProgress = (url, loaded, total) => console.log(`${loaded}/${total}`);
|
|
457
|
+
manager.onError = (url) => console.error(`Error loading ${url}`);
|
|
458
|
+
|
|
459
|
+
const textureLoader = new THREE.TextureLoader(manager);
|
|
460
|
+
const gltfLoader = new GLTFLoader(manager);
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
## Performance Tips
|
|
464
|
+
|
|
465
|
+
1. **Limit draw calls**: Merge geometries, use instancing, atlas textures
|
|
466
|
+
2. **Frustum culling**: Enabled by default, ensure bounding boxes are correct
|
|
467
|
+
3. **LOD (Level of Detail)**: Use `THREE.LOD` for distance-based mesh switching
|
|
468
|
+
4. **Object pooling**: Reuse objects instead of creating/destroying
|
|
469
|
+
5. **Avoid `getWorldPosition` in loops**: Cache results
|
|
470
|
+
|
|
471
|
+
```javascript
|
|
472
|
+
// Merge static geometries
|
|
473
|
+
import { mergeGeometries } from "three/examples/jsm/utils/BufferGeometryUtils.js";
|
|
474
|
+
const merged = mergeGeometries([geo1, geo2, geo3]);
|
|
475
|
+
|
|
476
|
+
// LOD
|
|
477
|
+
const lod = new THREE.LOD();
|
|
478
|
+
lod.addLevel(highDetailMesh, 0);
|
|
479
|
+
lod.addLevel(medDetailMesh, 50);
|
|
480
|
+
lod.addLevel(lowDetailMesh, 100);
|
|
481
|
+
scene.add(lod);
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
## See Also
|
|
485
|
+
|
|
486
|
+
- `threejs-geometry` - Geometry creation and manipulation
|
|
487
|
+
- `threejs-materials` - Material types and properties
|
|
488
|
+
- `threejs-lighting` - Light types and shadows
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: web-design-guidelines
|
|
3
|
+
description: Review UI code for Web Interface Guidelines compliance. Use when asked to "review my UI", "check accessibility", "audit design", "review UX", or "check my site against best practices".
|
|
4
|
+
metadata:
|
|
5
|
+
author: vercel
|
|
6
|
+
version: "1.0.0"
|
|
7
|
+
argument-hint: <file-or-pattern>
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Web Interface Guidelines
|
|
11
|
+
|
|
12
|
+
Review files for compliance with Web Interface Guidelines.
|
|
13
|
+
|
|
14
|
+
## How It Works
|
|
15
|
+
|
|
16
|
+
1. Fetch the latest guidelines from the source URL below
|
|
17
|
+
2. Read the specified files (or prompt user for files/pattern)
|
|
18
|
+
3. Check against all rules in the fetched guidelines
|
|
19
|
+
4. Output findings in the terse `file:line` format
|
|
20
|
+
|
|
21
|
+
## Guidelines Source
|
|
22
|
+
|
|
23
|
+
Fetch fresh guidelines before each review:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
https://raw.githubusercontent.com/vercel-labs/web-interface-guidelines/main/command.md
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Use WebFetch to retrieve the latest rules. The fetched content contains all the rules and output format instructions.
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
When a user provides a file or pattern argument:
|
|
34
|
+
1. Fetch guidelines from the source URL above
|
|
35
|
+
2. Read the specified files
|
|
36
|
+
3. Apply all rules from the fetched guidelines
|
|
37
|
+
4. Output findings using the format specified in the guidelines
|
|
38
|
+
|
|
39
|
+
If no files specified, ask the user which files to review.
|
package/AGENTS.md
CHANGED
|
@@ -442,12 +442,6 @@ Usage notes:
|
|
|
442
442
|
<location>project</location>
|
|
443
443
|
</skill>
|
|
444
444
|
|
|
445
|
-
<skill>
|
|
446
|
-
<name>api-tester</name>
|
|
447
|
-
<description></description>
|
|
448
|
-
<location>project</location>
|
|
449
|
-
</skill>
|
|
450
|
-
|
|
451
445
|
<skill>
|
|
452
446
|
<name>brand-guidelines</name>
|
|
453
447
|
<description>Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.</description>
|
|
@@ -460,12 +454,6 @@ Usage notes:
|
|
|
460
454
|
<location>project</location>
|
|
461
455
|
</skill>
|
|
462
456
|
|
|
463
|
-
<skill>
|
|
464
|
-
<name>code-reviewer-123</name>
|
|
465
|
-
<description></description>
|
|
466
|
-
<location>project</location>
|
|
467
|
-
</skill>
|
|
468
|
-
|
|
469
457
|
<skill>
|
|
470
458
|
<name>design-brain</name>
|
|
471
459
|
<description></description>
|
|
@@ -508,12 +496,6 @@ Usage notes:
|
|
|
508
496
|
<location>project</location>
|
|
509
497
|
</skill>
|
|
510
498
|
|
|
511
|
-
<skill>
|
|
512
|
-
<name>my-skill</name>
|
|
513
|
-
<description></description>
|
|
514
|
-
<location>project</location>
|
|
515
|
-
</skill>
|
|
516
|
-
|
|
517
499
|
<skill>
|
|
518
500
|
<name>pdf</name>
|
|
519
501
|
<description>Comprehensive PDF manipulation toolkit for extracting text and tables, creating new PDFs, merging/splitting documents, and handling forms. When Claude needs to fill in a PDF form or programmatically process, generate, or analyze PDF documents at scale.</description>
|
|
@@ -562,12 +544,6 @@ Usage notes:
|
|
|
562
544
|
<location>project</location>
|
|
563
545
|
</skill>
|
|
564
546
|
|
|
565
|
-
<skill>
|
|
566
|
-
<name>test-skill-name</name>
|
|
567
|
-
<description></description>
|
|
568
|
-
<location>project</location>
|
|
569
|
-
</skill>
|
|
570
|
-
|
|
571
547
|
<skill>
|
|
572
548
|
<name>test-workflow</name>
|
|
573
549
|
<description>Automated testing workflow that combines Playwright testing, Slack GIF recording, and test report generation. Use when user mentions "测试"、"test"、"Playwright" or asks for QA/testing workflows. Automatically generates: (1) Test execution with Playwright, (2) Slack-optimized GIF of test process, (3) Screenshot at each verification point, (4) Markdown test report with embedded screenshots.</description>
|
|
@@ -598,36 +574,6 @@ Usage notes:
|
|
|
598
574
|
<location>project</location>
|
|
599
575
|
</skill>
|
|
600
576
|
|
|
601
|
-
<skill>
|
|
602
|
-
<name>architect</name>
|
|
603
|
-
<description>|</description>
|
|
604
|
-
<location>global</location>
|
|
605
|
-
</skill>
|
|
606
|
-
|
|
607
|
-
<skill>
|
|
608
|
-
<name>builder</name>
|
|
609
|
-
<description>|</description>
|
|
610
|
-
<location>global</location>
|
|
611
|
-
</skill>
|
|
612
|
-
|
|
613
|
-
<skill>
|
|
614
|
-
<name>conductor</name>
|
|
615
|
-
<description>|</description>
|
|
616
|
-
<location>global</location>
|
|
617
|
-
</skill>
|
|
618
|
-
|
|
619
|
-
<skill>
|
|
620
|
-
<name>librarian</name>
|
|
621
|
-
<description>|</description>
|
|
622
|
-
<location>global</location>
|
|
623
|
-
</skill>
|
|
624
|
-
|
|
625
|
-
<skill>
|
|
626
|
-
<name>reviewer</name>
|
|
627
|
-
<description>|</description>
|
|
628
|
-
<location>global</location>
|
|
629
|
-
</skill>
|
|
630
|
-
|
|
631
577
|
</available_skills>
|
|
632
578
|
<!-- SKILLS_TABLE_END -->
|
|
633
579
|
|