# Core Types

All types below are exported from `@glyphcss/core` unless marked with `glyphcss`
(the vanilla package).

## Geometry primitives

| Type | Description | Used in |
|---|---|---|
| `Vec2` | `[u, v]` tuple — UV coordinates | `TextureTriangle.uvs`, polygon UVs |
| `Vec3` | `[x, y, z]` tuple — world-space point or vector | Vertices, directions, hotspot anchors |
| `Polygon` | N coplanar vertices + optional color/texture | Helper generators, mesh parsers |
| `TextureTriangle` | 3 vertices + 3 UV pairs + optional color | Parser-internal type for UV-mapped meshes |
| `WireframeEdge` | `from`/`to` Vec3 pair + optional weight/color | `buildRasterizeContext` wireframe mode (`glyphcss`) |

```ts
type Vec2 = [number, number];
type Vec3 = [number, number, number];

interface Polygon {
  vertices: Vec3[];
  color?: string;
  texture?: string;
  uvs?: Vec2[];
}

interface TextureTriangle {
  vertices: [Vec3, Vec3, Vec3];
  uvs: [Vec2, Vec2, Vec2];
  color?: string;
}

interface WireframeEdge {
  from: Vec3;
  to: Vec3;
  weight?: EdgeWeight;  // 1 | 2 | 3
  color?: string;
}
```

## Render mode and glyph mapping

| Type | Description | Used in |
|---|---|---|
| `RenderMode` | `"wireframe" \| "solid" \| "voxel" \| "ink"` | `RasterizeContextOptions.mode`, all framework props |
| `CharRamp` | `string[]` — index 0 = darkest, last = brightest | Solid-mode Lambert → glyph mapping |
| `EdgeWeight` | `1 \| 2 \| 3` — thin / normal / core | `WireframeEdge.weight` |

```ts
type RenderMode = "wireframe" | "solid" | "voxel" | "ink";
type CharRamp = string[];          // e.g. [" ", ".", ":", "-", "=", "+", "*", "#", "%", "@"]
type EdgeWeight = 1 | 2 | 3;
```

## Lighting

| Type | Description | Used in |
|---|---|---|
| `GlyphDirectionalLight` | Single distant light source | `GlyphSceneOptions.directionalLight` |
| `GlyphAmbientLight` | Uniform fill light | `GlyphSceneOptions.ambientLight` |

```ts
interface GlyphDirectionalLight {
  direction: Vec3;     // source vector from surface toward the distant light
  intensity?: number;  // default 1
  color?: string;      // hex, default white
}

interface GlyphAmbientLight {
  intensity?: number;  // default 0.4
  color?: string;      // hex, default white
}
```

## Shadows

| Type | Description | Used in |
|---|---|---|
| `GlyphShadowOptions` | Shadow-map configuration. `undefined` on the scene = shadows off | `GlyphSceneOptions.shadow`, `<GlyphScene shadow={…}>` |

```ts
interface GlyphShadowOptions {
  color?: string;      // shadow tint hex; default "#000000"
  opacity?: number;    // darkness 0..1 toward color; default 0.25
  lift?: number;       // depth bias — prevents self-shadow acne; default 0.05
  maxExtend?: number;  // accepted but NOT READ — the volume is fitted to the casters' own bounds
}
```

Shadow flags on meshes (`GlyphMeshTransform`, `<GlyphMesh>`, `<glyph-mesh>`):

| Field / prop / attribute | Default | Description |
|---|---|---|
| `castShadow` / `cast-shadow` | `false` | This mesh casts shadows onto `receiveShadow` surfaces |
| `receiveShadow` / `receive-shadow` | `false` | This mesh receives shadows. Both flags on the same mesh = self-shadow |

`GlyphGround` sets `receiveShadow=true` and `castShadow=false` by default.

Detail / density on meshes (`GlyphMeshTransform`, `<GlyphMesh>`, `<glyph-mesh>`) — see the [Density & Detail guide](/guides/density/):

| Field / prop / attribute | Type | Default | Description |
|---|---|---|---|
| `density` | `number` | `1` (shared grid) | Render this mesh at `density`× the scene resolution, in its own `<pre>` |
| `fontSize` / `font-size` | `number \| string` | — | Explicit cell size (px or CSS length). Overrides `density` |
| `lineHeight` / `line-height` | `number` | — | Explicit cell line-height. Overrides `density` |
| `transparent` | `boolean` | `false` | See-through: doesn't occlude / isn't occluded (pops into its own `<pre>`) |

Browser-only (detail layers measure the live cell size); works with any camera (orthographic, perspective, FPV).

## Grid and scene

| Type | Description | Used in |
|---|---|---|
| `GridSize` | `{ cols, rows, cellAspect }` | `buildRasterizeContext`, camera `project()` |
| `SceneContext` | Normalized polygons + scene bbox + warnings | The `.context` field of `buildSceneContext({ polygons })`'s `SceneContextBuildResult`. The rasterizer takes `RasterizeContext` from `buildRasterizeContext`, not this |

```ts
interface GridSize {
  cols: number;
  rows: number;
  cellAspect: number;  // cellH / cellW — typically ~2.0
}
```

## Hotspots

| Type | Description | Used in |
|---|---|---|
| `Hotspot` | A 3D anchor that projects to a 2D hitbox | `scene.addHotspot()`, `projectHotspots()` |
| `HotspotCell` | Projected result for one frame | `projectHotspots()` return value |

```ts
interface Hotspot {
  id: string;
  at: Vec3;
  size?: [number, number];  // cols × rows in cells; default [1, 1]
}

interface HotspotCell {
  id: string;
  col: number;
  row: number;
  depth: number;    // camera-space Z; use for z-index
  visible: boolean; // false when behind camera or off-grid
}
```

## Parse results

| Type | Description | Used in |
|---|---|---|
| `ParseResult` | Unified output of all polygon-emitting parsers | `parseObj`, `parseGltf`, `loadMesh` |
| `ParseAnimationClip` | Metadata for one animation in a glTF file | `ParseResult.animation.clips` |

```ts
interface ParseResult {
  polygons: Polygon[];
  animation?: ParseAnimationController;
  objectUrls: string[];
  dispose: () => void;    // revoke blob URLs — always call on unmount
  warnings: string[];
  metadata?: {
    triangleCount?: number;
    meshes?: string[];
    materials?: string[];
    animations?: ParseAnimationClip[];
    sourceBytes?: number;
  };
}

interface ParseAnimationClip {
  index: number;
  name: string;
  duration: number;   // seconds
  channelCount: number;
}
```

## Animation

| Type | Description | Used in |
|---|---|---|
| `GlyphAnimationMixer` | Drives one or more animation actions against a mesh target | `createGlyphAnimationMixer()` |
| `GlyphAnimationAction` | Per-clip playback state | `mixer.clipAction()` |

```ts
// Minimal usage — requires a glTF/GLB file with embedded animation clips.
// Replace "/character.glb" with the path to your own animated mesh.
import { createGlyphAnimationMixer, LoopRepeat, loadMesh } from "@glyphcss/core";

const { polygons, animation } = await loadMesh("/character.glb");
const mixer = createGlyphAnimationMixer(meshHandle, animation!);

const action = mixer.clipAction("walk");
action.setLoop(LoopRepeat, Infinity).play();

// In your animation loop (requestAnimationFrame):
mixer.update(deltaSeconds);
```
