612 Tris0,43 × 0,37 × 0,18 m
Im Code verwenden
Im Editor remixenhealth-pack.js · 118 Zeilen
Eigenständiges ES-Modul — hängt nur von three ab. Ruf die Factory auf und füge die Gruppe deiner Szene hinzu.
/**
* Health Pack — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 612 · Size (W × H × D): 0.43 × 0.37 × 0.18 m
*
* Usage:
* import { createHealthPack } from './health-pack.js';
*
* const model = createHealthPack();
* model.position.set(0, 0, 0);
* scene.add(model);
*/
import * as THREE from 'three';
const deg = THREE.MathUtils.degToRad;
// Extrude a 2D outline along Z (centered). bevel = [thickness, size, segments].
function extrude(outline, depth, holes = [], bevel = null) {
const shape = new THREE.Shape(outline.map(([x, y]) => new THREE.Vector2(x, y)));
for (const hole of holes) shape.holes.push(new THREE.Path(hole.map(([x, y]) => new THREE.Vector2(x, y))));
const options = bevel
? { depth, bevelEnabled: true, bevelThickness: bevel[0], bevelSize: bevel[1], bevelSegments: bevel[2] }
: { depth, bevelEnabled: false };
return new THREE.ExtrudeGeometry(shape, options).translate(0, 0, -depth / 2);
}
// Tube along a smooth curve through the given points.
function tube(path, radius, tubularSegments, radialSegments, closed = false) {
const curve = new THREE.CatmullRomCurve3(path.map(([x, y, z]) => new THREE.Vector3(x, y, z)), closed);
return new THREE.TubeGeometry(curve, tubularSegments, radius, radialSegments, closed);
}
export function createHealthPack() {
const root = new THREE.Group();
root.name = 'HealthPack';
// Materials
const bodyMat = new THREE.MeshStandardMaterial({ name: 'body', color: 0xf1f0ea, roughness: 0.5, flatShading: true });
const crossMat = new THREE.MeshStandardMaterial({ name: 'cross', color: 0xe0353a, roughness: 0.5, flatShading: true });
const trimMat = new THREE.MeshStandardMaterial({ name: 'trim', color: 0x9aa1aa, roughness: 0.4, metalness: 0.6, flatShading: true });
const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x3a3f47, roughness: 0.7, flatShading: true });
// Shared geometries
const boxGeo = new THREE.BoxGeometry(0.392, 0.008, 0.006);
const boxGeo2 = new THREE.BoxGeometry(0.006, 0.008, 0.1332);
const boxGeo3 = new THREE.BoxGeometry(0.045, 0.04, 0.012);
const boxGeo4 = new THREE.BoxGeometry(0.025, 0.012, 0.008);
const boxGeo5 = new THREE.BoxGeometry(0.035, 0.014, 0.04);
// Parts
const case2 = new THREE.Mesh(extrude([[0.165, -0.135], [0.1825, -0.1303], [0.1953, -0.1175], [0.2, -0.1], [0.2, 0.1], [0.1953, 0.1175], [0.1825, 0.1303], [0.165, 0.135], [-0.165, 0.135], [-0.1825, 0.1303], [-0.1953, 0.1175], [-0.2, 0.1], [-0.2, -0.1], [-0.1953, -0.1175], [-0.1825, -0.1303], [-0.165, -0.135]], 0.12, [], [0.022, 0.014, 2]), bodyMat);
case2.name = 'case';
case2.position.set(0, 0.149, 0);
root.add(case2);
const seamFront = new THREE.Mesh(boxGeo, trimMat);
seamFront.name = 'seamFront';
seamFront.position.set(0, 0.2084, 0.081);
root.add(seamFront);
const seamRight = new THREE.Mesh(boxGeo2, trimMat);
seamRight.name = 'seamRight';
seamRight.position.set(0.213, 0.2084, 0);
root.add(seamRight);
const seamBack = new THREE.Mesh(boxGeo, trimMat);
seamBack.name = 'seamBack';
seamBack.position.set(0, 0.2084, -0.081);
root.add(seamBack);
const seamLeft = new THREE.Mesh(boxGeo2, trimMat);
seamLeft.name = 'seamLeft';
seamLeft.position.set(-0.213, 0.2084, 0);
root.add(seamLeft);
const crossFront = new THREE.Mesh(extrude([[-0.025, -0.075], [0.025, -0.075], [0.025, -0.025], [0.075, -0.025], [0.075, 0.025], [0.025, 0.025], [0.025, 0.075], [-0.025, 0.075], [-0.025, 0.025], [-0.075, 0.025], [-0.075, -0.025], [-0.025, -0.025]], 0.006), crossMat);
crossFront.name = 'crossFront';
crossFront.position.set(0, 0.1274, 0.083);
root.add(crossFront);
const crossTop = new THREE.Mesh(extrude([[-0.015, -0.0425], [0.015, -0.0425], [0.015, -0.015], [0.0425, -0.015], [0.0425, 0.015], [0.015, 0.015], [0.015, 0.0425], [-0.015, 0.0425], [-0.015, 0.015], [-0.0425, 0.015], [-0.0425, -0.015], [-0.015, -0.015]], 0.006), crossMat);
crossTop.name = 'crossTop';
crossTop.position.set(-0.12, 0.299, 0);
crossTop.rotation.set(deg(-90), 0, 0);
root.add(crossTop);
const latchR = new THREE.Mesh(boxGeo3, trimMat);
latchR.name = 'latchR';
latchR.position.set(0.132, 0.2084, 0.086);
root.add(latchR);
const latchTabR = new THREE.Mesh(boxGeo4, darkMat);
latchTabR.name = 'latchTabR';
latchTabR.position.set(0.132, 0.1964, 0.093);
root.add(latchTabR);
const latchL = new THREE.Mesh(boxGeo3, trimMat);
latchL.name = 'latchL';
latchL.position.set(-0.132, 0.2084, 0.086);
root.add(latchL);
const latchTabL = new THREE.Mesh(boxGeo4, darkMat);
latchTabL.name = 'latchTabL';
latchTabL.position.set(-0.132, 0.1964, 0.093);
root.add(latchTabL);
const handle = new THREE.Mesh(tube([[-0.075, 0.294, 0], [-0.07, 0.333, 0], [-0.04, 0.353, 0], [0.04, 0.353, 0], [0.07, 0.333, 0], [0.075, 0.294, 0]], 0.012, 18, 6), darkMat);
handle.name = 'handle';
root.add(handle);
const handleMountR = new THREE.Mesh(boxGeo5, trimMat);
handleMountR.name = 'handleMountR';
handleMountR.position.set(0.075, 0.301, 0);
root.add(handleMountR);
const handleMountL = new THREE.Mesh(boxGeo5, trimMat);
handleMountL.name = 'handleMountL';
handleMountL.position.set(-0.075, 0.301, 0);
root.add(handleMountL);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createHealthPack;
Bewertungen & Kommentare
—
Noch keine Bewertungen — gib die erste ab.
5
0
4
0
3
0
2
0
1
0
Melde dich an, um zu bewerten und zu kommentieren.
0 Kommentare
Noch keine Kommentare. Erzähl, wie du dieses Modell genutzt hast oder was besser sein könnte.
Ähnliche Modelle
Gleiche Kategorie oder ähnliche Tags









