1,6 mil tris0,85 × 0,84 × 0,67 m
Úsalo en código
Hacer remix en el editorghost.js · 172 líneas
Módulo ES autónomo — solo depende de three. Llama a la función factory y añade el grupo a tu escena.
/**
* Ghost — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 1,596 · Size (W × H × D): 0.85 × 0.83 × 0.67 m
*
* Usage:
* import { createGhost } from './ghost.js';
*
* const model = createGhost();
* model.position.set(0, 0, 0);
* scene.add(model);
*/
import * as THREE from 'three';
const deg = THREE.MathUtils.degToRad;
// Revolve a 2D profile [[radius, y], ...] around the Y axis.
function lathe(points, segments, phiStart = 0, phiLength = Math.PI * 2) {
return new THREE.LatheGeometry(points.map(([x, y]) => new THREE.Vector2(x, y)), segments, phiStart, phiLength);
}
export function createGhost() {
const root = new THREE.Group();
root.name = 'Ghost';
// Materials
const sheetMat = new THREE.MeshStandardMaterial({ name: 'sheet', color: 0xeef1fb, roughness: 0.55, emissive: 0x9fc2ff, emissiveIntensity: 0.22, flatShading: true });
const faceMat = new THREE.MeshStandardMaterial({ name: 'face', color: 0x1d1a26, roughness: 0.3, flatShading: true });
const mouthMat = new THREE.MeshStandardMaterial({ name: 'mouth', color: 0x2d1830, roughness: 0.6, flatShading: true });
const blushMat = new THREE.MeshStandardMaterial({ name: 'blush', color: 0xf5a3b8, roughness: 0.7, flatShading: true });
const shineMat = new THREE.MeshStandardMaterial({ name: 'shine', color: 0xffffff, roughness: 0.3, flatShading: true });
// Shared geometries
const latheGeo = lathe([[0, 0], [0.03, 0.01], [0.055, 0.035], [0.075, 0.08], [0.088, 0.16], [0.06, 0.19], [0, 0.2]], 7);
const latheGeo2 = lathe([[0, 0], [0.03, 0.01], [0.055, 0.035], [0.075, 0.08], [0.088, 0.125], [0.06, 0.155], [0, 0.165]], 7);
const sphereGeo = new THREE.SphereGeometry(0.07, 8, 6);
const sphereGeo2 = new THREE.SphereGeometry(0.042, 8, 6);
const sphereGeo3 = new THREE.SphereGeometry(0.012, 4, 3);
const sphereGeo4 = new THREE.SphereGeometry(0.03, 6, 4);
// Parts
const body = new THREE.Group();
body.name = 'body';
root.add(body);
const sheet = new THREE.Mesh(lathe([[0, 0.13], [0.33, 0.115], [0.325, 0.2], [0.3, 0.34], [0.28, 0.48], [0.265, 0.6], [0.225, 0.71], [0.15, 0.79], [0.07, 0.825], [0, 0.835]], 14), sheetMat);
sheet.name = 'sheet';
body.add(sheet);
const hem = new THREE.Group();
hem.name = 'hem';
root.add(hem);
const hemDrip1 = new THREE.Mesh(latheGeo, sheetMat);
hemDrip1.name = 'hemDrip1';
hemDrip1.position.set(0.0426, 0, 0.2818);
hemDrip1.rotation.set(deg(-13.8428), 0, deg(2.0921));
hem.add(hemDrip1);
const hemDrip2 = new THREE.Mesh(latheGeo2, sheetMat);
hemDrip2.name = 'hemDrip2';
hemDrip2.position.set(0.1896, 0, 0.1923);
hemDrip2.rotation.set(deg(-9.9693), 0, deg(9.8292));
hem.add(hemDrip2);
const hemDrip3 = new THREE.Mesh(latheGeo, sheetMat);
hemDrip3.name = 'hemDrip3';
hemDrip3.position.set(0.2812, 0, 0.0466);
hemDrip3.rotation.set(deg(-2.2879), 0, deg(13.8118));
hem.add(hemDrip3);
const hemDrip4 = new THREE.Mesh(latheGeo2, sheetMat);
hemDrip4.name = 'hemDrip4';
hemDrip4.position.set(0.2414, 0, -0.1209);
hemDrip4.rotation.set(deg(6.2674), 0, deg(12.5188));
hem.add(hemDrip4);
const hemDrip5 = new THREE.Mesh(latheGeo, sheetMat);
hemDrip5.name = 'hemDrip5';
hemDrip5.position.set(0.1312, 0, -0.253);
hemDrip5.rotation.set(deg(12.4288), 0, deg(6.444));
hem.add(hemDrip5);
const hemDrip6 = new THREE.Mesh(latheGeo2, sheetMat);
hemDrip6.name = 'hemDrip6';
hemDrip6.position.set(-0.0403, 0, -0.267);
hemDrip6.rotation.set(deg(13.8428), 0, deg(-2.0921));
hem.add(hemDrip6);
const hemDrip7 = new THREE.Mesh(latheGeo, sheetMat);
hemDrip7.name = 'hemDrip7';
hemDrip7.position.set(-0.2001, 0, -0.2029);
hemDrip7.rotation.set(deg(9.9693), 0, deg(-9.8292));
hem.add(hemDrip7);
const hemDrip8 = new THREE.Mesh(latheGeo2, sheetMat);
hemDrip8.name = 'hemDrip8';
hemDrip8.position.set(-0.2664, 0, -0.0441);
hemDrip8.rotation.set(deg(2.2879), 0, deg(-13.8118));
hem.add(hemDrip8);
const hemDrip9 = new THREE.Mesh(latheGeo, sheetMat);
hemDrip9.name = 'hemDrip9';
hemDrip9.position.set(-0.2548, 0, 0.1276);
hemDrip9.rotation.set(deg(-6.2674), 0, deg(-12.5188));
hem.add(hemDrip9);
const hemDrip10 = new THREE.Mesh(latheGeo2, sheetMat);
hemDrip10.name = 'hemDrip10';
hemDrip10.position.set(-0.1243, 0, 0.2397);
hemDrip10.rotation.set(deg(-12.4288), 0, deg(-6.444));
hem.add(hemDrip10);
const armL = new THREE.Group();
armL.name = 'armL';
armL.position.set(0.2543, 0.45, 0.02);
armL.rotation.set(0, deg(-15), deg(25));
root.add(armL);
const armNubL = new THREE.Mesh(sphereGeo, sheetMat);
armNubL.name = 'armNubL';
armNubL.position.set(0.085, 0, 0);
armNubL.scale.set(1.55, 0.72, 0.75);
armL.add(armNubL);
const armR = new THREE.Group();
armR.name = 'armR';
armR.position.set(-0.2543, 0.45, 0.02);
armR.rotation.set(0, deg(15), deg(-25));
root.add(armR);
const armNubR = new THREE.Mesh(sphereGeo, sheetMat);
armNubR.name = 'armNubR';
armNubR.position.set(-0.085, 0, 0);
armNubR.scale.set(1.55, 0.72, 0.75);
armR.add(armNubR);
const face = new THREE.Group();
face.name = 'face';
root.add(face);
const eyeL = new THREE.Mesh(sphereGeo2, faceMat);
eyeL.name = 'eyeL';
eyeL.position.set(0.085, 0.58, 0.2416);
eyeL.rotation.set(0, deg(18), 0);
eyeL.scale.set(0.75, 1.3, 0.5);
face.add(eyeL);
const eyeShineL = new THREE.Mesh(sphereGeo3, shineMat);
eyeShineL.name = 'eyeShineL';
eyeShineL.position.set(0.077, 0.605, 0.2596);
face.add(eyeShineL);
const cheekL = new THREE.Mesh(sphereGeo4, blushMat);
cheekL.name = 'cheekL';
cheekL.position.set(0.15, 0.51, 0.224);
cheekL.rotation.set(0, deg(32), 0);
cheekL.scale.set(1, 0.55, 0.45);
face.add(cheekL);
const eyeR = new THREE.Mesh(sphereGeo2, faceMat);
eyeR.name = 'eyeR';
eyeR.position.set(-0.085, 0.58, 0.2416);
eyeR.rotation.set(0, deg(-18), 0);
eyeR.scale.set(0.75, 1.3, 0.5);
face.add(eyeR);
const eyeShineR = new THREE.Mesh(sphereGeo3, shineMat);
eyeShineR.name = 'eyeShineR';
eyeShineR.position.set(-0.093, 0.605, 0.2596);
face.add(eyeShineR);
const cheekR = new THREE.Mesh(sphereGeo4, blushMat);
cheekR.name = 'cheekR';
cheekR.position.set(-0.15, 0.51, 0.224);
cheekR.rotation.set(0, deg(-32), 0);
cheekR.scale.set(1, 0.55, 0.45);
face.add(cheekR);
const mouth = new THREE.Mesh(new THREE.SphereGeometry(0.045, 8, 6), mouthMat);
mouth.name = 'mouth';
mouth.position.set(0, 0.47, 0.2674);
mouth.scale.set(0.8, 1.05, 0.5);
face.add(mouth);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createGhost;
Valoraciones y comentarios
0 comentarios
Aún no hay comentarios. Cuenta cómo usaste este modelo o qué se podría mejorar.
Modelos relacionados
Misma categoría o etiquetas similares









