🎯

r3f-geometry

🎯Skill

from bbeierle12/skill-mcp-claude

VibeIndex|
What it does

Creates and manipulates 3D geometries in React Three Fiber, enabling custom shapes, built-in primitives, and optimized rendering through buffer attributes and instancing.

πŸ“¦

Part of

bbeierle12/skill-mcp-claude(74 items)

r3f-geometry

Installation

pip installInstall dependencies
pip install -r requirements.txt
PythonRun Python server
python skills_manager_api.py
PythonRun Python server
python server.py
pip installInstall Python package
pip install pyinstaller
PythonRun Python server
python -m PyInstaller --onefile --name "SkillsManager" --console ^
Server ConfigurationMCP server configuration block
{ "name": "skill-name", "description": "One-line description", "tags": ["t...
πŸ“– Extracted from docs: bbeierle12/skill-mcp-claude
12Installs
-
AddedFeb 4, 2026

Skill Details

SKILL.md

BufferGeometry creation, built-in geometries, custom geometry with buffer attributes, instanced meshes for rendering thousands of objects, and geometry manipulation. Use when creating custom shapes, optimizing with instancing, or working with vertex data directly.

Overview

# R3F Geometry

Geometry defines the shape of 3D objects via vertices, faces, normals, and UVs stored in buffer attributes.

Quick Start

```tsx

// Built-in geometry

// Custom geometry

attach="attributes-position"

count={3}

array={new Float32Array([0, 0, 0, 1, 0, 0, 0.5, 1, 0])}

itemSize={3}

/>

```

Built-in Geometries

All geometries accept args array matching constructor parameters:

```tsx

// Box: [width, height, depth, widthSegments?, heightSegments?, depthSegments?]

// Sphere: [radius, widthSegments, heightSegments, phiStart?, phiLength?, thetaStart?, thetaLength?]

// Plane: [width, height, widthSegments?, heightSegments?]

// Cylinder: [radiusTop, radiusBottom, height, radialSegments?, heightSegments?, openEnded?]

// Cone: [radius, height, radialSegments?, heightSegments?, openEnded?]

// Torus: [radius, tube, radialSegments, tubularSegments, arc?]

// TorusKnot: [radius, tube, tubularSegments, radialSegments, p?, q?]

// Ring: [innerRadius, outerRadius, thetaSegments?, phiSegments?]

// Circle: [radius, segments?, thetaStart?, thetaLength?]

// Dodecahedron/Icosahedron/Octahedron/Tetrahedron: [radius, detail?]

```

Buffer Attributes

Geometry data lives in typed arrays attached as attributes:

| Attribute | ItemSize | Purpose |

|-----------|----------|---------|

| position | 3 | Vertex positions (x, y, z) |

| normal | 3 | Surface normals for lighting |

| uv | 2 | Texture coordinates (u, v) |

| color | 3 | Per-vertex colors (r, g, b) |

| index | 1 | Triangle indices (optional) |

Custom Geometry from Scratch

```tsx

import { useMemo } from 'react';

import * as THREE from 'three';

function Triangle() {

const geometry = useMemo(() => {

const geo = new THREE.BufferGeometry();

// 3 vertices Γ— 3 components (x, y, z)

const positions = new Float32Array([

-1, -1, 0, // vertex 0

1, -1, 0, // vertex 1

0, 1, 0 // vertex 2

]);

// 3 vertices Γ— 3 components (nx, ny, nz)

const normals = new Float32Array([

0, 0, 1,

0, 0, 1,

0, 0, 1

]);

// 3 vertices Γ— 2 components (u, v)

const uvs = new Float32Array([

0, 0,

1, 0,

0.5, 1

]);

geo.setAttribute('position', new THREE.BufferAttribute(positions, 3));

geo.setAttribute('normal', new THREE.BufferAttribute(normals, 3));

geo.setAttribute('uv', new THREE.BufferAttribute(uvs, 2));

return geo;

}, []);

return (

);

}

```

Declarative Buffer Attributes

```tsx

function Triangle() {

const positions = useMemo(() =>

new Float32Array([-1, -1, 0, 1, -1, 0, 0, 1, 0]),

[]);

return (

attach="attributes-position"

count={3}

array={positions}

itemSize={3}

/>

);

}

```

Indexed Geometry

Use indices to share vertices between triangles:

```tsx

function Quad() {

const geometry = useMemo(() => {

const geo = new THREE.BufferGeometry();

// 4 unique vertices

const positions = new Float32Array([

-1, -1, 0, // 0: bottom-left

1, -1, 0, // 1: bottom-right

1, 1, 0, // 2: top-right

-1, 1, 0 // 3: top-left

]);

// 2 triangles, 6 indices

const indices = new Uint16Array([

0, 1, 2, // first triangle

0, 2, 3 // second triangle

]);

geo.setAttribute('position', new THREE.BufferAttribute(positions, 3));

geo.setIndex(new THREE.BufferAttribute(indices, 1));

geo.computeVertexNormals();

return geo;

}, []);

return (

);

}

```

Dynamic Geometry Updates

```tsx

import { useRef } from 'react';

import { useFrame } from '@react-three/fiber';

import * as THREE from 'three';

function WavingPlane() {

const geometryRef = useRef(null!);

useFrame(({ clock }) => {

const positions = geometryRef.current.attributes.position;

const time = clock.elapsedTime;

for (let i = 0; i < positions.count; i++) {

const x = positions.getX(i);

const y = positions.getY(i);

const z = Math.sin(x 2 + time) Math.cos(y 2 + time) 0.5;

positions.setZ(i, z);

}

positions.needsUpdate = true; // Critical!

geometryRef.current.computeVertexNormals();

});

return (

);

}

```

Instanced Mesh

Render thousands of identical meshes with different transforms in a single draw call:

```tsx

import { useRef, useMemo } from 'react';

import { useFrame } from '@react-three/fiber';

import * as THREE from 'three';

function Particles({ count = 1000 }) {

const meshRef = useRef(null!);

// Pre-allocate transformation objects

const dummy = useMemo(() => new THREE.Object3D(), []);

// Initialize instance matrices

useEffect(() => {

for (let i = 0; i < count; i++) {

dummy.position.set(

(Math.random() - 0.5) * 10,

(Math.random() - 0.5) * 10,

(Math.random() - 0.5) * 10

);

dummy.rotation.set(

Math.random() * Math.PI,

Math.random() * Math.PI,

0

);

dummy.scale.setScalar(0.1 + Math.random() * 0.2);

dummy.updateMatrix();

meshRef.current.setMatrixAt(i, dummy.matrix);

}

meshRef.current.instanceMatrix.needsUpdate = true;

}, [count, dummy]);

// Animate instances

useFrame(({ clock }) => {

for (let i = 0; i < count; i++) {

meshRef.current.getMatrixAt(i, dummy.matrix);

dummy.matrix.decompose(dummy.position, dummy.quaternion, dummy.scale);

dummy.rotation.x += 0.01;

dummy.rotation.y += 0.01;

dummy.updateMatrix();

meshRef.current.setMatrixAt(i, dummy.matrix);

}

meshRef.current.instanceMatrix.needsUpdate = true;

});

return (

);

}

```

Instance Colors

```tsx

function ColoredInstances({ count = 1000 }) {

const meshRef = useRef(null!);

useEffect(() => {

const color = new THREE.Color();

for (let i = 0; i < count; i++) {

color.setHSL(i / count, 1, 0.5);

meshRef.current.setColorAt(i, color);

}

meshRef.current.instanceColor!.needsUpdate = true;

}, [count]);

return (

);

}

```

Instance Attributes (Custom Data)

```tsx

function CustomInstanceData({ count = 1000 }) {

const meshRef = useRef(null!);

// Custom per-instance data

const speeds = useMemo(() => {

const arr = new Float32Array(count);

for (let i = 0; i < count; i++) {

arr[i] = 0.5 + Math.random();

}

return arr;

}, [count]);

useEffect(() => {

// Attach as instanced buffer attribute

meshRef.current.geometry.setAttribute(

'aSpeed',

new THREE.InstancedBufferAttribute(speeds, 1)

);

}, [speeds]);

return (

vertexShader={`

attribute float aSpeed;

varying float vSpeed;

void main() {

vSpeed = aSpeed;

gl_Position = projectionMatrix modelViewMatrix instanceMatrix * vec4(position, 1.0);

}

`}

fragmentShader={`

varying float vSpeed;

void main() {

gl_FragColor = vec4(vSpeed, 0.5, 1.0 - vSpeed, 1.0);

}

`}

/>

);

}

```

Geometry Utilities

Compute Normals

```tsx

const geometry = useMemo(() => {

const geo = new THREE.BufferGeometry();

// ... set positions

geo.computeVertexNormals(); // Auto-calculate smooth normals

return geo;

}, []);

```

Compute Bounding Box/Sphere

```tsx

useEffect(() => {

geometry.computeBoundingBox();

geometry.computeBoundingSphere();

console.log(geometry.boundingBox); // THREE.Box3

console.log(geometry.boundingSphere); // THREE.Sphere

}, [geometry]);

```

Center Geometry

```tsx

const geometry = useMemo(() => {

const geo = new THREE.BoxGeometry(2, 3, 1);

geo.center(); // Move to origin

return geo;

}, []);

```

Merge Geometries

```tsx

import { mergeGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils';

const merged = useMemo(() => {

const box = new THREE.BoxGeometry(1, 1, 1);

const sphere = new THREE.SphereGeometry(0.5, 16, 16);

sphere.translate(0, 1, 0);

return mergeGeometries([box, sphere]);

}, []);

```

Performance Tips

| Technique | When to Use | Impact |

|-----------|-------------|--------|

| Instancing | 100+ identical meshes | Massive |

| Indexed geometry | Shared vertices | Moderate |

| Lower segments | Non-hero geometry | Moderate |

| Merge geometries | Static scene | Moderate |

| Dispose unused | Dynamic loading | Memory |

Disposal

```tsx

useEffect(() => {

return () => {

geometry.dispose(); // Clean up GPU memory

};

}, [geometry]);

```

File Structure

```

r3f-geometry/

β”œβ”€β”€ SKILL.md

β”œβ”€β”€ references/

β”‚ β”œβ”€β”€ buffer-attributes.md # Deep-dive on attribute types

β”‚ β”œβ”€β”€ instancing-patterns.md # Advanced instancing

β”‚ └── procedural-shapes.md # Algorithmic geometry

└── scripts/

β”œβ”€β”€ procedural/

β”‚ β”œβ”€β”€ grid.ts # Grid mesh generator

β”‚ β”œβ”€β”€ terrain.ts # Heightmap terrain

β”‚ └── tube.ts # Custom tube geometry

└── utils/

β”œβ”€β”€ geometry-utils.ts # Merge, center, clone

└── instancing.ts # Instance helpers

```

Reference

  • references/buffer-attributes.md β€” All attribute types and usage
  • references/instancing-patterns.md β€” Advanced instancing techniques
  • references/procedural-shapes.md β€” Generating geometry algorithmically