# Bench3D

A reusable 3D modeling engine extracted from Blockbench. Bench3D provides the core 3D modeling functionality without UI dependencies, making it easy to build custom 3D modeling applications with React, Vue, or any other framework.

## Installation

```bash
npm install bench-3d three
```

Note: `three` is a peer dependency and must be installed separately.

## Import Style (Like Three.js and p5.js)

Bench3D uses the same simple import pattern as Three.js and p5.js:

```typescript
// Namespace import (recommended - like Three.js)
import * as Bench3D from 'bench-3d';

// Use everything through the namespace
const engine = new Bench3D.Bench3D({ canvas: myCanvas });
const project = engine.createProject();
const cube = project.addCube({ size: [16, 16, 16] });
const exporter = new Bench3D.GLTFExporter();
```

```typescript
// Named imports (also works)
import { Bench3D, Project, Cube, GLTFExporter } from 'bench-3d';

const engine = new Bench3D({ canvas: myCanvas });
const project = engine.createProject();
const cube = project.addCube({ size: [16, 16, 16] });
```

**The namespace import (`import * as Bench3D`) is the recommended and primary way to use Bench3D**, just like `import * as THREE from 'three'`.

## TypeScript Support

Bench3D is written in TypeScript and provides full type definitions. All exports are fully typed, and you'll get excellent IDE support with autocomplete and type checking.

```typescript
import * as Bench3D from 'bench-3d';

// Full type safety with namespace import
const engine = new Bench3D.Bench3D({ canvas: myCanvas });
const project: Bench3D.Project = engine.createProject();
const cube: Bench3D.Cube = project.addCube({ size: [16, 16, 16] });
const offset: Bench3D.Vector3 = [10, 0, 0];
```

Type definitions are automatically included when you install the package. No additional `@types` package needed!

## Framework Integration

Bench3D works with React, Vue, and vanilla JavaScript/TypeScript:

### React

```bash
npm install bench-3d-react bench-3d three react react-dom
```

```tsx
import { Bench3DCanvas, useBench3D, useProject } from 'bench-3d-react';

function MyApp() {
  const { project, isReady } = useBench3D();
  const { addCube } = useProject(project);
  
  useEffect(() => {
    if (isReady && project) {
      addCube({ size: [16, 16, 16] });
    }
  }, [isReady, project, addCube]);
  
  return <Bench3DCanvas width={800} height={600} />;
}
```

See [bench-3d-react](../bench-3d-react/README.md) for complete React documentation.

### Vue

```bash
npm install bench-3d-vue bench-3d three vue
```

```vue
<template>
  <Bench3DCanvas :width="800" :height="600" />
</template>

<script setup lang="ts">
import { onMounted } from 'vue';
import { Bench3DCanvas, useBench3D, useProject } from 'bench-3d-vue';

const { project, isReady } = useBench3D();
const { addCube } = useProject(project);

onMounted(() => {
  if (isReady.value && project.value) {
    addCube({ size: [16, 16, 16] });
  }
});
</script>
```

See [bench-3d-vue](../bench-3d-vue/README.md) for complete Vue documentation.

### Vanilla JavaScript/TypeScript

See the [Framework Integration Guide](./FRAMEWORK_INTEGRATION.md) for detailed integration patterns.

## Quick Start

### Namespace Import (Recommended)

```typescript
// Single line import - everything included!
import * as Bench3D from 'bench-3d';

// Create an engine instance
const canvas = document.getElementById('my-canvas') as HTMLCanvasElement;
const engine = new Bench3D.Bench3D({
  canvas: canvas,
  onUpdate: (event) => {
    console.log('Update:', event.type, event.data);
  }
});

// Create a project
const project = engine.createProject({
  name: 'My Model',
  texture_width: 16,
  texture_height: 16
});

// Add geometry
const cube = project.addCube({
  name: 'My Cube',
  size: [16, 16, 16],
  origin: [0, 0, 0]
});

// Transform elements
Bench3D.moveElements([cube], [10, 0, 0] as Bench3D.Vector3);

// Render
engine.render();
```

Both import styles work! Use whichever you prefer.

## Core Features

### Geometry Management
- **Cubes**: Box-based geometry with UV mapping
- **Meshes**: Custom vertex-based geometry with faces
- **Groups**: Organize elements hierarchically
- **Armatures**: Skeletal animation support with bones

### Project System
- Manage multiple projects
- Element and group selection
- Texture management
- Animation system

### Modeling Operations
- Transform operations (move, rotate, scale)
- Selection management
- Geometry manipulation

### Animation System
- Keyframe-based animations
- Timeline markers
- Animator system for bones and elements

### Texturing System
- Texture management
- UV mapping
- Layer support

### Rendering
- Abstracted renderer interface
- Three.js renderer implementation
- Framework-agnostic design

### I/O System
- JSON import/export
- Extensible format system
- Project serialization

## Architecture

Bench3D is structured to separate core functionality from UI:

```
bench3d/
├── core/              # Core modeling engine (no DOM dependencies)
│   ├── geometry/      # Mesh, Cube, geometry operations
│   ├── modeling/     # Transform, editing operations
│   ├── animation/    # Animation system
│   ├── texturing/    # UV mapping, textures
│   ├── rendering/     # Three.js scene management (abstracted)
│   ├── io/           # File format import/export
│   └── project/      # Project management
├── api/              # Public API surface
└── utils/            # Shared utilities
```

## Entry Points

- `bench3d` - Main entry point with all features
- `bench3d/core` - Core-only (without rendering)
- `bench3d/full` - Full features including Three.js renderer

## Framework Integration

Bench3D is designed to work with any UI framework. Here's an example with React:

```typescript
import { Bench3D } from 'bench-3d';
import { useEffect, useRef } from 'react';

function ModelEditor() {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const engineRef = useRef<Bench3D | null>(null);

  useEffect(() => {
    if (canvasRef.current && !engineRef.current) {
      engineRef.current = new Bench3D({
        canvas: canvasRef.current,
      });
      
      const project = engineRef.current.createProject();
      project.addCube({ size: [16, 16, 16] });
      
      const animate = () => {
        engineRef.current?.render();
        requestAnimationFrame(animate);
      };
      animate();
    }
  }, []);

  return <canvas ref={canvasRef} width={800} height={600} />;
}
```

## Building a Full 3D Modeler

Want to build your own 3D modeling application like Blockbench? Bench3D provides all the core functionality you need. See [BUILDING_A_MODELER.md](./BUILDING_A_MODELER.md) for a complete guide on what's included and what you need to build.

**TL;DR**: Bench3D provides ~80% of what you need (all the core modeling operations). You build the remaining 20% (UI, interaction, tools) using your preferred framework.

## License

GPL-3.0-or-later

