532 üçgen0,28 × 0,48 × 0,29 m
Kodda kullan
Editörde remix’lecat.js · 303 satır
Bağımsız bir ES modülü — yalnızca three paketine bağımlıdır. Fabrika fonksiyonunu çağırıp dönen grubu sahnene ekle.
/**
* Cat — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 532 · Size (W × H × D): 0.28 × 0.48 × 0.28 m
*
* Usage:
* import { createCat } from './cat.js';
*
* const model = createCat();
* 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);
}
export function createCat() {
const root = new THREE.Group();
root.name = 'Cat';
// Materials
const furMat = new THREE.MeshStandardMaterial({ name: 'fur', color: 0xe39a4c, roughness: 0.9, flatShading: true });
const stripeMat = new THREE.MeshStandardMaterial({ name: 'stripe', color: 0x8d5f2f, roughness: 0.9, flatShading: true });
const whiteMat = new THREE.MeshStandardMaterial({ name: 'white', color: 0xf7f1e8, roughness: 0.95, flatShading: true });
const pinkMat = new THREE.MeshStandardMaterial({ name: 'pink', color: 0xf2a0ab, roughness: 0.6, flatShading: true });
const eyeMat = new THREE.MeshStandardMaterial({ name: 'eye', color: 0x1a1618, roughness: 0.25, flatShading: true });
const shineMat = new THREE.MeshStandardMaterial({ name: 'shine', color: 0xffffff, roughness: 0.3, flatShading: true });
const collarMat = new THREE.MeshStandardMaterial({ name: 'collar', color: 0xd8363f, roughness: 0.6, flatShading: true });
const goldMat = new THREE.MeshStandardMaterial({ name: 'gold', color: 0xf2c14c, roughness: 0.3, metalness: 0.65, flatShading: true });
// Shared geometries
const boxGeo = new THREE.BoxGeometry(0.05, 0.15, 0.05);
const boxGeo2 = new THREE.BoxGeometry(0.056, 0.025, 0.06);
const boxGeo3 = new THREE.BoxGeometry(0.07, 0.11, 0.14);
const boxGeo4 = new THREE.BoxGeometry(0.055, 0.035, 0.1);
const boxGeo5 = new THREE.BoxGeometry(0.058, 0.037, 0.025);
const boxGeo6 = new THREE.BoxGeometry(0.006, 0.07, 0.022);
const boxGeo7 = new THREE.BoxGeometry(0.156, 0.022, 0.06);
const boxGeo8 = new THREE.BoxGeometry(0.075, 0.004, 0.004);
const boxGeo9 = new THREE.BoxGeometry(0.042, 0.052, 0.01);
const boxGeo10 = new THREE.BoxGeometry(0.016, 0.016, 0.006);
const boxGeo11 = new THREE.BoxGeometry(0.014, 0.035, 0.006);
const boxGeo12 = new THREE.BoxGeometry(0.006, 0.014, 0.05);
const boxGeo13 = new THREE.BoxGeometry(0.006, 0.014, 0.04);
// Parts
const legFL = new THREE.Group();
legFL.name = 'legFL';
legFL.position.set(0.045, 0.175, 0.055);
root.add(legFL);
const forelegL = new THREE.Mesh(boxGeo, furMat);
forelegL.name = 'forelegL';
forelegL.position.set(0, -0.075, 0);
legFL.add(forelegL);
const pawFL = new THREE.Mesh(boxGeo2, whiteMat);
pawFL.name = 'pawFL';
pawFL.position.set(0, -0.1625, 0.006);
legFL.add(pawFL);
const legFR = new THREE.Group();
legFR.name = 'legFR';
legFR.position.set(-0.045, 0.175, 0.055);
root.add(legFR);
const forelegR = new THREE.Mesh(boxGeo, furMat);
forelegR.name = 'forelegR';
forelegR.position.set(0, -0.075, 0);
legFR.add(forelegR);
const pawFR = new THREE.Mesh(boxGeo2, whiteMat);
pawFR.name = 'pawFR';
pawFR.position.set(0, -0.1625, 0.006);
legFR.add(pawFR);
const legBL = new THREE.Group();
legBL.name = 'legBL';
legBL.position.set(0.072, 0.08, -0.04);
root.add(legBL);
const haunchL = new THREE.Mesh(boxGeo3, furMat);
haunchL.name = 'haunchL';
haunchL.position.set(0, -0.025, -0.005);
legBL.add(haunchL);
const hindFootL = new THREE.Mesh(boxGeo4, furMat);
hindFootL.name = 'hindFootL';
hindFootL.position.set(0, -0.0625, 0.07);
legBL.add(hindFootL);
const pawBL = new THREE.Mesh(boxGeo5, whiteMat);
pawBL.name = 'pawBL';
pawBL.position.set(0, -0.0625, 0.115);
legBL.add(pawBL);
const haunchStripe = new THREE.Mesh(boxGeo6, stripeMat);
haunchStripe.name = 'haunchStripe';
haunchStripe.position.set(0.038, -0.01, -0.02);
haunchStripe.rotation.set(deg(25), 0, 0);
legBL.add(haunchStripe);
const legBR = new THREE.Group();
legBR.name = 'legBR';
legBR.position.set(-0.072, 0.08, -0.04);
root.add(legBR);
const haunchR = new THREE.Mesh(boxGeo3, furMat);
haunchR.name = 'haunchR';
haunchR.position.set(0, -0.025, -0.005);
legBR.add(haunchR);
const hindFootR = new THREE.Mesh(boxGeo4, furMat);
hindFootR.name = 'hindFootR';
hindFootR.position.set(0, -0.0625, 0.07);
legBR.add(hindFootR);
const pawBR = new THREE.Mesh(boxGeo5, whiteMat);
pawBR.name = 'pawBR';
pawBR.position.set(0, -0.0625, 0.115);
legBR.add(pawBR);
const haunchStripe2 = new THREE.Mesh(boxGeo6, stripeMat);
haunchStripe2.name = 'haunchStripe';
haunchStripe2.position.set(-0.038, -0.01, -0.02);
haunchStripe2.rotation.set(deg(25), 0, 0);
legBR.add(haunchStripe2);
const body = new THREE.Group();
body.name = 'body';
root.add(body);
const torso = new THREE.Group();
torso.name = 'torso';
torso.position.set(0, 0.12, -0.03);
torso.rotation.set(deg(-15), 0, 0);
body.add(torso);
const chestBox = new THREE.Mesh(new THREE.BoxGeometry(0.15, 0.2, 0.14), furMat);
chestBox.name = 'chestBox';
torso.add(chestBox);
const chest = new THREE.Mesh(new THREE.BoxGeometry(0.1, 0.14, 0.012), whiteMat);
chest.name = 'chest';
chest.position.set(0, 0, 0.073);
torso.add(chest);
const stripeBack = new THREE.Mesh(boxGeo7, stripeMat);
stripeBack.name = 'stripeBack';
stripeBack.position.set(0, 0.05, -0.045);
torso.add(stripeBack);
const stripeBack2 = new THREE.Mesh(boxGeo7, stripeMat);
stripeBack2.name = 'stripeBack';
stripeBack2.position.set(0, -0.01, -0.045);
torso.add(stripeBack2);
const tail = new THREE.Group();
tail.name = 'tail';
tail.position.set(0, 0.021, -0.1);
root.add(tail);
const tailSeg1 = new THREE.Mesh(new THREE.BoxGeometry(0.042, 0.1336, 0.042), furMat);
tailSeg1.name = 'tailSeg1';
tailSeg1.position.set(0.05, 0, 0);
tailSeg1.rotation.set(deg(-90), 0, deg(-90));
tail.add(tailSeg1);
const tailSeg2 = new THREE.Mesh(new THREE.BoxGeometry(0.042, 0.1601, 0.042), furMat);
tailSeg2.name = 'tailSeg2';
tailSeg2.position.set(0.12, 0, 0.06);
tailSeg2.rotation.set(deg(-90), 0, deg(-161.5651));
tail.add(tailSeg2);
const tailStripe = new THREE.Mesh(new THREE.BoxGeometry(0.048, 0.0253, 0.048), stripeMat);
tailStripe.name = 'tailStripe';
tailStripe.position.set(0.12, 0, 0.06);
tailStripe.rotation.set(deg(-90), 0, deg(-161.5651));
tail.add(tailStripe);
const tailSeg3 = new THREE.Mesh(new THREE.BoxGeometry(0.042, 0.1321, 0.042), stripeMat);
tailSeg3.name = 'tailSeg3';
tailSeg3.position.set(0.12, 0, 0.165);
tailSeg3.rotation.set(deg(-90), 0, deg(156.0375));
tail.add(tailSeg3);
const collar = new THREE.Group();
collar.name = 'collar';
collar.position.set(0, 0.222, 0);
collar.rotation.set(deg(-12), 0, 0);
root.add(collar);
const collarBand = new THREE.Mesh(new THREE.BoxGeometry(0.165, 0.035, 0.15), collarMat);
collarBand.name = 'collarBand';
collar.add(collarBand);
const bell = new THREE.Mesh(new THREE.IcosahedronGeometry(0.02, 0), goldMat);
bell.name = 'bell';
bell.position.set(0, -0.024, 0.08);
collar.add(bell);
const head = new THREE.Group();
head.name = 'head';
head.position.set(0, 0.245, 0.015);
root.add(head);
const skull = new THREE.Mesh(new THREE.BoxGeometry(0.21, 0.17, 0.16), furMat);
skull.name = 'skull';
skull.position.set(0, 0.075, 0.035);
head.add(skull);
const muzzle = new THREE.Mesh(new THREE.BoxGeometry(0.09, 0.05, 0.03), whiteMat);
muzzle.name = 'muzzle';
muzzle.position.set(0, 0.03, 0.125);
head.add(muzzle);
const nose = new THREE.Mesh(new THREE.BoxGeometry(0.032, 0.02, 0.012), pinkMat);
nose.name = 'nose';
nose.position.set(0, 0.054, 0.141);
head.add(nose);
const mouth = new THREE.Mesh(new THREE.BoxGeometry(0.02, 0.016, 0.008), stripeMat);
mouth.name = 'mouth';
mouth.position.set(0, 0.018, 0.142);
head.add(mouth);
const whisker = new THREE.Mesh(boxGeo8, whiteMat);
whisker.name = 'whisker';
whisker.position.set(0.075, 0.035, 0.135);
whisker.rotation.set(0, deg(12), deg(8));
head.add(whisker);
const whisker2 = new THREE.Mesh(boxGeo8, whiteMat);
whisker2.name = 'whisker';
whisker2.position.set(0.075, 0.019, 0.135);
whisker2.rotation.set(0, deg(12), deg(-8));
head.add(whisker2);
const whisker3 = new THREE.Mesh(boxGeo8, whiteMat);
whisker3.name = 'whisker';
whisker3.position.set(-0.075, 0.035, 0.135);
whisker3.rotation.set(0, deg(-12), deg(-8));
head.add(whisker3);
const whisker4 = new THREE.Mesh(boxGeo8, whiteMat);
whisker4.name = 'whisker';
whisker4.position.set(-0.075, 0.019, 0.135);
whisker4.rotation.set(0, deg(-12), deg(8));
head.add(whisker4);
const eyeL = new THREE.Mesh(boxGeo9, eyeMat);
eyeL.name = 'eyeL';
eyeL.position.set(0.055, 0.095, 0.118);
head.add(eyeL);
const eyeShineL = new THREE.Mesh(boxGeo10, shineMat);
eyeShineL.name = 'eyeShineL';
eyeShineL.position.set(0.064, 0.107, 0.124);
head.add(eyeShineL);
const eyeR = new THREE.Mesh(boxGeo9, eyeMat);
eyeR.name = 'eyeR';
eyeR.position.set(-0.055, 0.095, 0.118);
head.add(eyeR);
const eyeShineR = new THREE.Mesh(boxGeo10, shineMat);
eyeShineR.name = 'eyeShineR';
eyeShineR.position.set(-0.046, 0.107, 0.124);
head.add(eyeShineR);
const earL = new THREE.Group();
earL.name = 'earL';
earL.position.set(0.06, 0.154, 0.015);
earL.rotation.set(deg(-4), 0, deg(-10));
head.add(earL);
const earOuterL = new THREE.Mesh(extrude([[-0.045, 0], [0.045, 0], [0.012, 0.085]], 0.025), furMat);
earOuterL.name = 'earOuterL';
earL.add(earOuterL);
const earInnerL = new THREE.Mesh(extrude([[-0.027, 0.008], [0.027, 0.008], [0.008, 0.06]], 0.008), pinkMat);
earInnerL.name = 'earInnerL';
earInnerL.position.set(0, 0, 0.0155);
earL.add(earInnerL);
const earR = new THREE.Group();
earR.name = 'earR';
earR.position.set(-0.06, 0.154, 0.015);
earR.rotation.set(deg(-4), 0, deg(10));
head.add(earR);
const earOuterR = new THREE.Mesh(extrude([[-0.045, 0], [0.045, 0], [-0.012, 0.085]], 0.025), furMat);
earOuterR.name = 'earOuterR';
earR.add(earOuterR);
const earInnerR = new THREE.Mesh(extrude([[-0.027, 0.008], [0.027, 0.008], [-0.008, 0.06]], 0.008), pinkMat);
earInnerR.name = 'earInnerR';
earInnerR.position.set(0, 0, 0.0155);
earR.add(earInnerR);
const foreheadStripe = new THREE.Mesh(new THREE.BoxGeometry(0.016, 0.045, 0.006), stripeMat);
foreheadStripe.name = 'foreheadStripe';
foreheadStripe.position.set(0, 0.13, 0.118);
head.add(foreheadStripe);
const foreheadStripe2 = new THREE.Mesh(boxGeo11, stripeMat);
foreheadStripe2.name = 'foreheadStripe';
foreheadStripe2.position.set(0.03, 0.135, 0.118);
foreheadStripe2.rotation.set(0, 0, deg(15));
head.add(foreheadStripe2);
const cheekStripe = new THREE.Mesh(boxGeo12, stripeMat);
cheekStripe.name = 'cheekStripe';
cheekStripe.position.set(0.108, 0.065, 0.075);
head.add(cheekStripe);
const cheekStripe2 = new THREE.Mesh(boxGeo13, stripeMat);
cheekStripe2.name = 'cheekStripe';
cheekStripe2.position.set(0.108, 0.035, 0.07);
head.add(cheekStripe2);
const foreheadStripe3 = new THREE.Mesh(boxGeo11, stripeMat);
foreheadStripe3.name = 'foreheadStripe';
foreheadStripe3.position.set(-0.03, 0.135, 0.118);
foreheadStripe3.rotation.set(0, 0, deg(-15));
head.add(foreheadStripe3);
const cheekStripe3 = new THREE.Mesh(boxGeo12, stripeMat);
cheekStripe3.name = 'cheekStripe';
cheekStripe3.position.set(-0.108, 0.065, 0.075);
head.add(cheekStripe3);
const cheekStripe4 = new THREE.Mesh(boxGeo13, stripeMat);
cheekStripe4.name = 'cheekStripe';
cheekStripe4.position.set(-0.108, 0.035, 0.07);
head.add(cheekStripe4);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createCat;
Puanlar ve yorumlar
0 yorum
Henüz yorum yok. Bu modeli nasıl kullandığını ya da neyin daha iyi olabileceğini paylaş.
Benzer modeller
Aynı kategori ya da benzer etiketler









