664 tris0,86 × 1,50 × 0,64 m
Use no código
Fazer remix no editorskeleton-warrior.js · 304 linhas
Módulo ES autocontido — depende apenas do three. Chame a factory e adicione o grupo à sua cena.
/**
* Skeleton Warrior — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 664 · Size (W × H × D): 0.86 × 1.50 × 0.64 m
*
* Usage:
* import { createSkeletonWarrior } from './skeleton-warrior.js';
*
* const model = createSkeletonWarrior();
* 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 createSkeletonWarrior() {
const root = new THREE.Group();
root.name = 'SkeletonWarrior';
// Materials
const boneMat = new THREE.MeshStandardMaterial({ name: 'bone', color: 0xebe3cf, roughness: 0.75, flatShading: true });
const jointMat = new THREE.MeshStandardMaterial({ name: 'joint', color: 0xcac3b2, roughness: 0.8, flatShading: true });
const socketMat = new THREE.MeshStandardMaterial({ name: 'socket', color: 0x2b2329, roughness: 0.9, flatShading: true });
const glowMat = new THREE.MeshStandardMaterial({ name: 'glow', color: 0xff5a3c, roughness: 0.4, emissive: 0xff5a3c, emissiveIntensity: 1.6, flatShading: true });
const steelMat = new THREE.MeshStandardMaterial({ name: 'steel', color: 0xb4bcc6, roughness: 0.3, metalness: 0.7, flatShading: true });
const ironMat = new THREE.MeshStandardMaterial({ name: 'iron', color: 0x585c66, roughness: 0.55, metalness: 0.5, flatShading: true });
const woodMat = new THREE.MeshStandardMaterial({ name: 'wood', color: 0x83582f, roughness: 0.85, flatShading: true });
const leatherMat = new THREE.MeshStandardMaterial({ name: 'leather', color: 0x5b3a28, roughness: 0.8, flatShading: true });
// Shared geometries
const boxGeo = new THREE.BoxGeometry(0.075, 0.24, 0.075);
const boxGeo2 = new THREE.BoxGeometry(0.11, 0.075, 0.11);
const boxGeo3 = new THREE.BoxGeometry(0.07, 0.22, 0.07);
const boxGeo4 = new THREE.BoxGeometry(0.13, 0.065, 0.2);
const boxGeo5 = new THREE.BoxGeometry(0.11, 0.1, 0.11);
const boxGeo6 = new THREE.BoxGeometry(0.065, 0.2, 0.065);
const boxGeo7 = new THREE.BoxGeometry(0.09, 0.07, 0.09);
const boxGeo8 = new THREE.BoxGeometry(0.06, 0.18, 0.06);
const boxGeo9 = new THREE.BoxGeometry(0.1, 0.1, 0.1);
const boxGeo10 = new THREE.BoxGeometry(0.008, 0.05, 0.008);
const boxGeo11 = new THREE.BoxGeometry(0.1, 0.1, 0.02);
const boxGeo12 = new THREE.BoxGeometry(0.04, 0.04, 0.01);
// Parts
const legL = new THREE.Group();
legL.name = 'legL';
legL.position.set(0.1, 0.6, 0);
root.add(legL);
const thighL = new THREE.Mesh(boxGeo, boneMat);
thighL.name = 'thighL';
thighL.position.set(0, -0.14, 0);
legL.add(thighL);
const kneeL = new THREE.Mesh(boxGeo2, jointMat);
kneeL.name = 'kneeL';
kneeL.position.set(0, -0.29, 0);
legL.add(kneeL);
const shinL = new THREE.Mesh(boxGeo3, boneMat);
shinL.name = 'shinL';
shinL.position.set(0, -0.43, 0);
legL.add(shinL);
const footL = new THREE.Mesh(boxGeo4, boneMat);
footL.name = 'footL';
footL.position.set(0, -0.5675, 0.035);
legL.add(footL);
const legR = new THREE.Group();
legR.name = 'legR';
legR.position.set(-0.1, 0.6, 0);
root.add(legR);
const thighR = new THREE.Mesh(boxGeo, boneMat);
thighR.name = 'thighR';
thighR.position.set(0, -0.14, 0);
legR.add(thighR);
const kneeR = new THREE.Mesh(boxGeo2, jointMat);
kneeR.name = 'kneeR';
kneeR.position.set(0, -0.29, 0);
legR.add(kneeR);
const shinR = new THREE.Mesh(boxGeo3, boneMat);
shinR.name = 'shinR';
shinR.position.set(0, -0.43, 0);
legR.add(shinR);
const footR = new THREE.Mesh(boxGeo4, boneMat);
footR.name = 'footR';
footR.position.set(0, -0.5675, 0.035);
legR.add(footR);
const body = new THREE.Group();
body.name = 'body';
root.add(body);
const pelvis = new THREE.Mesh(new THREE.BoxGeometry(0.3, 0.1, 0.15), boneMat);
pelvis.name = 'pelvis';
pelvis.position.set(0, 0.62, 0);
body.add(pelvis);
const spine = new THREE.Mesh(new THREE.BoxGeometry(0.065, 0.42, 0.065), jointMat);
spine.name = 'spine';
spine.position.set(0, 0.85, -0.04);
body.add(spine);
const rib1 = new THREE.Mesh(new THREE.BoxGeometry(0.304, 0.04, 0.2), boneMat);
rib1.name = 'rib1';
rib1.position.set(0, 0.8, -0.005);
body.add(rib1);
const rib2 = new THREE.Mesh(new THREE.BoxGeometry(0.334, 0.04, 0.2), boneMat);
rib2.name = 'rib2';
rib2.position.set(0, 0.87, -0.005);
body.add(rib2);
const rib3 = new THREE.Mesh(new THREE.BoxGeometry(0.316, 0.04, 0.2), boneMat);
rib3.name = 'rib3';
rib3.position.set(0, 0.94, -0.005);
body.add(rib3);
const rib4 = new THREE.Mesh(new THREE.BoxGeometry(0.286, 0.04, 0.2), boneMat);
rib4.name = 'rib4';
rib4.position.set(0, 1.01, -0.005);
body.add(rib4);
const sternum = new THREE.Mesh(new THREE.BoxGeometry(0.05, 0.25, 0.03), boneMat);
sternum.name = 'sternum';
sternum.position.set(0, 0.91, 0.1);
body.add(sternum);
const collarbone = new THREE.Mesh(new THREE.BoxGeometry(0.44, 0.06, 0.12), boneMat);
collarbone.name = 'collarbone';
collarbone.position.set(0, 1.1, -0.01);
body.add(collarbone);
const belt = new THREE.Mesh(new THREE.BoxGeometry(0.32, 0.05, 0.17), leatherMat);
belt.name = 'belt';
belt.position.set(0, 0.675, 0);
body.add(belt);
const loincloth = new THREE.Mesh(new THREE.BoxGeometry(0.14, 0.16, 0.02), leatherMat);
loincloth.name = 'loincloth';
loincloth.position.set(0, 0.56, 0.085);
body.add(loincloth);
const armL = new THREE.Group();
armL.name = 'armL';
armL.position.set(0.25, 1.1, -0.01);
armL.rotation.set(deg(6), 0, deg(8));
root.add(armL);
const shoulderL = new THREE.Mesh(boxGeo5, jointMat);
shoulderL.name = 'shoulderL';
armL.add(shoulderL);
const upperArmL = new THREE.Mesh(boxGeo6, boneMat);
upperArmL.name = 'upperArmL';
upperArmL.position.set(0, -0.14, 0);
armL.add(upperArmL);
const forearmL = new THREE.Group();
forearmL.name = 'forearmL';
forearmL.position.set(0, -0.26, 0);
forearmL.rotation.set(deg(-35), 0, 0);
armL.add(forearmL);
const elbowL = new THREE.Mesh(boxGeo7, jointMat);
elbowL.name = 'elbowL';
forearmL.add(elbowL);
const lowerArmL = new THREE.Mesh(boxGeo8, boneMat);
lowerArmL.name = 'lowerArmL';
lowerArmL.position.set(0, -0.12, 0);
forearmL.add(lowerArmL);
const handL = new THREE.Mesh(boxGeo9, boneMat);
handL.name = 'handL';
handL.position.set(0, -0.25, 0);
forearmL.add(handL);
const shield = new THREE.Group();
shield.name = 'shield';
shield.position.set(0.08, -0.15, 0.02);
forearmL.add(shield);
const shieldBoard = new THREE.Mesh(new THREE.CylinderGeometry(0.21, 0.21, 0.045, 10), woodMat);
shieldBoard.name = 'shieldBoard';
shieldBoard.rotation.set(0, 0, deg(90));
shield.add(shieldBoard);
const shieldRim = new THREE.Mesh(new THREE.CylinderGeometry(0.215, 0.215, 0.03, 10, 1, false), ironMat);
shieldRim.name = 'shieldRim';
shieldRim.rotation.set(0, 0, deg(90));
shieldRim.scale.set(1, 1.2, 1);
shield.add(shieldRim);
const shieldBoss = new THREE.Mesh(new THREE.CylinderGeometry(0.06, 0.07, 0.04, 8), ironMat);
shieldBoss.name = 'shieldBoss';
shieldBoss.position.set(0.04, 0, 0);
shieldBoss.rotation.set(0, 0, deg(90));
shield.add(shieldBoss);
const shieldBand = new THREE.Mesh(new THREE.BoxGeometry(0.05, 0.4, 0.04), ironMat);
shieldBand.name = 'shieldBand';
shieldBand.position.set(0.025, 0, 0);
shield.add(shieldBand);
const armR = new THREE.Group();
armR.name = 'armR';
armR.position.set(-0.25, 1.1, -0.01);
armR.rotation.set(deg(10), 0, deg(-8));
root.add(armR);
const shoulderR = new THREE.Mesh(boxGeo5, jointMat);
shoulderR.name = 'shoulderR';
armR.add(shoulderR);
const upperArmR = new THREE.Mesh(boxGeo6, boneMat);
upperArmR.name = 'upperArmR';
upperArmR.position.set(0, -0.14, 0);
armR.add(upperArmR);
const forearmR = new THREE.Group();
forearmR.name = 'forearmR';
forearmR.position.set(0, -0.26, 0);
forearmR.rotation.set(deg(-80), 0, 0);
armR.add(forearmR);
const elbowR = new THREE.Mesh(boxGeo7, jointMat);
elbowR.name = 'elbowR';
forearmR.add(elbowR);
const lowerArmR = new THREE.Mesh(boxGeo8, boneMat);
lowerArmR.name = 'lowerArmR';
lowerArmR.position.set(0, -0.12, 0);
forearmR.add(lowerArmR);
const handR = new THREE.Mesh(boxGeo9, boneMat);
handR.name = 'handR';
handR.position.set(0, -0.25, 0);
forearmR.add(handR);
const weapon = new THREE.Group();
weapon.name = 'weapon';
weapon.position.set(0, -0.25, 0);
weapon.rotation.set(deg(95), 0, 0);
forearmR.add(weapon);
const grip = new THREE.Mesh(new THREE.BoxGeometry(0.04, 0.16, 0.04), leatherMat);
grip.name = 'grip';
weapon.add(grip);
const pommel = new THREE.Mesh(new THREE.BoxGeometry(0.055, 0.05, 0.055), ironMat);
pommel.name = 'pommel';
pommel.position.set(0, -0.1, 0);
weapon.add(pommel);
const crossguard = new THREE.Mesh(new THREE.BoxGeometry(0.24, 0.045, 0.06), ironMat);
crossguard.name = 'crossguard';
crossguard.position.set(0, 0.1, 0);
weapon.add(crossguard);
const blade = new THREE.Mesh(extrude([[-0.035, 0], [0.035, 0], [0.035, 0.5], [0, 0.58], [-0.035, 0.5]], 0.02), steelMat);
blade.name = 'blade';
blade.position.set(0, 0.12, 0);
weapon.add(blade);
const fuller = new THREE.Mesh(new THREE.BoxGeometry(0.012, 0.42, 0.024), ironMat);
fuller.name = 'fuller';
fuller.position.set(0, 0.36, 0);
weapon.add(fuller);
const head = new THREE.Group();
head.name = 'head';
head.position.set(0, 1.13, 0);
root.add(head);
const neck = new THREE.Mesh(new THREE.BoxGeometry(0.07, 0.1, 0.07), jointMat);
neck.name = 'neck';
neck.position.set(0, 0.03, -0.03);
head.add(neck);
const skull = new THREE.Mesh(new THREE.BoxGeometry(0.38, 0.3, 0.34), boneMat);
skull.name = 'skull';
skull.position.set(0, 0.22, 0.01);
head.add(skull);
const jaw = new THREE.Mesh(new THREE.BoxGeometry(0.32, 0.07, 0.28), boneMat);
jaw.name = 'jaw';
jaw.position.set(0, 0.03, 0.03);
head.add(jaw);
const mouthGap = new THREE.Mesh(new THREE.BoxGeometry(0.22, 0.035, 0.01), socketMat);
mouthGap.name = 'mouthGap';
mouthGap.position.set(0, 0.075, 0.176);
head.add(mouthGap);
const toothGap2 = new THREE.Mesh(boxGeo10, socketMat);
toothGap2.name = 'toothGap2';
toothGap2.position.set(-0.05, 0.04, 0.171);
head.add(toothGap2);
const toothGap3 = new THREE.Mesh(boxGeo10, socketMat);
toothGap3.name = 'toothGap3';
toothGap3.position.set(0, 0.04, 0.171);
head.add(toothGap3);
const toothGap4 = new THREE.Mesh(boxGeo10, socketMat);
toothGap4.name = 'toothGap4';
toothGap4.position.set(0.05, 0.04, 0.171);
head.add(toothGap4);
const socketL = new THREE.Mesh(boxGeo11, socketMat);
socketL.name = 'socketL';
socketL.position.set(0.085, 0.25, 0.175);
head.add(socketL);
const eyeGlowL = new THREE.Mesh(boxGeo12, glowMat);
eyeGlowL.name = 'eyeGlowL';
eyeGlowL.position.set(0.08, 0.245, 0.188);
head.add(eyeGlowL);
const socketR = new THREE.Mesh(boxGeo11, socketMat);
socketR.name = 'socketR';
socketR.position.set(-0.085, 0.25, 0.175);
head.add(socketR);
const eyeGlowR = new THREE.Mesh(boxGeo12, glowMat);
eyeGlowR.name = 'eyeGlowR';
eyeGlowR.position.set(-0.08, 0.245, 0.188);
head.add(eyeGlowR);
const noseHole = new THREE.Mesh(extrude([[-0.025, 0], [0.025, 0], [0, -0.04]], 0.02), socketMat);
noseHole.name = 'noseHole';
noseHole.position.set(0, 0.19, 0.175);
head.add(noseHole);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createSkeletonWarrior;
Avaliações e comentários
0 comentário
Nenhum comentário ainda. Conte como você usou este modelo ou o que poderia melhorar.
Modelos relacionados
Mesma categoria ou tags parecidas









