# Model, license and viewer notes

Checked 2026-10-07. This is a local interactive concept, not a production wrap template or a Tesla-endorsed configurator.

## Actual vehicle mesh

`assets/car-model.glb` is the original “2024 Tesla Model 3” GLB, with embedded textures and attribution preserved. It represents the refreshed Model 3/Highland body. Exact Performance trim details, dimensions, panel tolerances and final printed logo placement are **not** certified by this file. It is not a procedural substitute and is not a 2D image presented as 3D.

- Embedded artist: [RBLXSupercars](https://sketchfab.com/RBLXSupercars).
- Current download-page uploader: [brandonleong28](https://sketchfab.com/3d-models/tesla-model-3-2024-36c52f3f89f6439c90310f14e8ff33f2).
- License: [Creative Commons Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0/).
- Original source recorded inside the GLB: https://sketchfab.com/3d-models/2024-tesla-model-3-fd22be415215453693d67e33aa7812d0 (original model API returned “Not found” during this check; retained for provenance).
- [Current Sketchfab public model API](https://api.sketchfab.com/v3/models/36c52f3f89f6439c90310f14e8ff33f2) independently returned `isDownloadable: true`, license slug `by`, CC BY 4.0 URL, and “Author must be credited. Commercial use is allowed.” Snapshot preserved in `assets/sketchfab-source-metadata.json`. This agrees with `asset.extras.license` inside the downloaded GLB. Both the embedded artist and current uploader are credited because they differ.
- Downloaded from this [public copy at a pinned commit](https://github.com/erictfree/Carbon-Footprint-AI-Visualizer/blob/af4bef33ca371b24c1f043486f09a13571f4919b/models/tesla-model-3-2024/source/2024_tesla_model_3.glb). [Repository attribution](https://github.com/erictfree/Carbon-Footprint-AI-Visualizer/blob/af4bef33ca371b24c1f043486f09a13571f4919b/models/tesla-model-3-2024/CREDITS.md).
- Original bytes: **8,706,568**. SHA-256: `6ef6933d93ee0812d4049446a38e9b46273cab03b21be1e2ef1d502eccdb684b`.
- `assets/model-metadata.json` records embedded attribution and hash. No geometry or embedded textures are modified on disk.

Runtime changes are our new viewer code: orientation/scale normalization, materials and lighting, original color panels and stripes, a complete blank geometric livery, and locally uploaded logo textures. No race numbers appear on the car. The original vehicle silhouette is preserved; no trim-specific spoiler is invented. Surface mapping is for visual discussion with a wrap shop. Actual artwork needs their measured vehicle template and approval. No Tesla endorsement or sponsor affiliation is implied.

The model's CC BY attribution is a requirement when sharing the model/viewer or its adapted visual output. Keep the visible credit footer and include credit in exported concepts. Tesla and its model names remain trademarks of their respective owner. Sponsor logos remain their owners' property; this tool does not grant rights to those logos.

## Dependencies and original work

Three.js and its official OrbitControls, GLTFLoader, BufferGeometryUtils, SkeletonUtils and DecalGeometry modules are vendored by the main application with their license. No CDN, model host, external font, remote HDRI, analytics, upload endpoint, or logo network request is used by `car-viewer.js`. It loads only the local GLB. Logo pixels are drawn into a canvas locally.

The studio environment, lighting, livery canvases, controls integration, zone configuration and upload placement code are original work for this prototype. The Three.js `DecalGeometry` helper projects logos onto the actual 3D body mesh.

## Viewer API

```js
import { createCarViewer, MODEL_INFO } from './car-viewer.js';
const viewer = await createCarViewer({ container, onReady, onError });
```

The promise resolves after the local vehicle is loaded, decals are ready and animation starts. `onReady(viewer)` is also called at that point. WebGL/load errors call `onError(error)` and reject the promise. The host should show a helpful failure state. The returned methods:

- `setPalette({base, accent})`: six-digit `#rrggbb` colors. Missing keys keep prior values. Repaints the body and original geometric wrap art without replacing uploaded logos.
- `setConceptLivery(options)`: retained as a compatibility method. The current viewer always starts with a finished blank geometric livery and has no built-in sponsor images. Uploaded logos remain independent of the wrap and palette changes.
- `setZone('left' | 'right' | 'hood' | 'rear')`: selects the target for subsequent logo/transform changes; returns that zone's saved transform. Each zone retains an independent logo and transform.
- `setLogo(loadedImageOrNull)`: image must already be decoded/loaded. `null` removes the uploaded logo and leaves the finished wrap blank in that area. Transparent logo pixels stay transparent. No upload or remote lookup is performed. Host validates file type/size and manages object URLs.
- `setLogoTransform({scale, x, y, rotation})`: partial update. Scale is clamped to `.25–1.8`; `x` and `y` to `-1–1`; rotation is degrees `-180–180`. At `x=y=0`, the logo is centered. Positive `y` moves it upward; `x` moves right on the panel. The normalized position means a proportion of available travel after scaling/rotation, rather than a world-space distance. Logo fit is reduced if needed so the rotated bounding rectangle remains within its panel. Thus extreme scale values can reach a fit ceiling. Root sliders may deliberately expose the narrower ranges `.3–1.8`, `±.65`, and `±45°`.
- `setView('front' | 'rear' | 'left' | 'right' | 'iso')`, `resetCamera()`: presets; user can orbit and zoom. Front is negative Z. No panning, underground view or unbounded zoom.
- `setAutoRotate(boolean)`: defaults off.
- `exportPNG()`: returns the rendered canvas as a PNG data URL, from the current camera, at least 1600 pixels wide (same aspect ratio), then restores the on-screen renderer size. The host adds visible concept/attribution text when offering download.
- `dispose()`: stops animation, removes observer and controls, releases model/texture/WebGL resources, removes canvas.

Responsive sizing uses `ResizeObserver`, high DPI capped at 2. The host owns keyboard-accessible view/zone controls, file validation, selected-zone labels, captions/credit, and any download composition. This viewer does not save to a server or browser storage.
