1,2 mil tris9,38 × 2,94 × 12,4 m
Use no código
Fazer remix no editorstarfighter.js · 270 linhas
Módulo ES autocontido — depende apenas do three. Chame a factory e adicione o grupo à sua cena.
/**
* Starfighter — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 1,196 · Size (W × H × D): 9.38 × 2.94 × 12.42 m
*
* Usage:
* import { createStarfighter } from './starfighter.js';
*
* const model = createStarfighter();
* 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);
}
// 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 createStarfighter() {
const root = new THREE.Group();
root.name = 'Starfighter';
// Materials
const hullMat = new THREE.MeshStandardMaterial({ name: 'hull', color: 0xd5dbe2, roughness: 0.4, metalness: 0.35, flatShading: true });
const accentMat = new THREE.MeshStandardMaterial({ name: 'accent', color: 0xe8742f, roughness: 0.45, metalness: 0.2, flatShading: true });
const glassMat = new THREE.MeshStandardMaterial({ name: 'glass', color: 0x1f2c3a, roughness: 0.15, metalness: 0.35 });
const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x3a3f48, roughness: 0.55, metalness: 0.5, flatShading: true });
const glowMat = new THREE.MeshStandardMaterial({ name: 'glow', color: 0x46c9ff, roughness: 0.4, emissive: 0x46c9ff, emissiveIntensity: 1.6, flatShading: true });
// Shared geometries
const boxGeo = new THREE.BoxGeometry(0.04, 0.22, 1.3);
const boxGeo2 = new THREE.BoxGeometry(2.2, 0.02, 0.2);
const cylinderGeo = new THREE.CylinderGeometry(0.09, 0.09, 2.6, 6);
const cylinderGeo2 = new THREE.CylinderGeometry(0.045, 0.045, 0.7, 6);
const sphereGeo = new THREE.SphereGeometry(0.07, 6, 4);
const cylinderGeo3 = new THREE.CylinderGeometry(0.52, 0.6, 3.6, 10);
const cylinderGeo4 = new THREE.CylinderGeometry(0.65, 0.65, 0.28, 10);
const cylinderGeo5 = new THREE.CylinderGeometry(0.46, 0.46, 0.02, 10);
const cylinderGeo6 = new THREE.CylinderGeometry(0.62, 0.62, 0.25, 10);
const cylinderGeo7 = new THREE.CylinderGeometry(0.44, 0.44, 0.04, 10);
const coneGeo = new THREE.ConeGeometry(0.4, 1.1, 10);
const extrudeGeo = extrude([[-3, 0], [-4.9, 0], [-5.25, 1.35], [-4.55, 1.35]], 0.08, [], [0.03, 0.03, 1]);
const extrudeGeo2 = extrude([[-4.9, 1.1], [-5.19, 1.1], [-5.25, 1.35], [-4.55, 1.35], [-4.62, 1.1]], 0.1);
const cylinderGeo8 = new THREE.CylinderGeometry(0.24, 0.3, 0.12, 8);
const cylinderGeo9 = new THREE.CylinderGeometry(0.07, 0.07, 0.6, 6);
// Parts
const ship = new THREE.Group();
ship.name = 'ship';
root.add(ship);
const fuselage = new THREE.Mesh(lathe([[0, -4.9], [0.82, -4.9], [1.05, -3.5], [1.1, -1], [0.95, 1.5], [0.6, 3.6], [0.24, 5.4], [0, 6.1]], 6), hullMat);
fuselage.name = 'fuselage';
fuselage.position.set(0, 1.3, 0);
fuselage.rotation.set(deg(90), 0, 0);
fuselage.scale.set(1, 1, 0.6);
ship.add(fuselage);
const noseTip = new THREE.Mesh(lathe([[0.27, 5.25], [0.13, 5.75], [0, 6.12]], 6), accentMat);
noseTip.name = 'noseTip';
noseTip.position.set(0, 1.3, 0);
noseTip.rotation.set(deg(90), 0, 0);
noseTip.scale.set(1.04, 1, 0.624);
ship.add(noseTip);
const cockpit = new THREE.Mesh(new THREE.SphereGeometry(0.55, 12, 5, 0, Math.PI * 2, 0, Math.PI / 2), glassMat);
cockpit.name = 'cockpit';
cockpit.position.set(0, 1.6, 1.75);
cockpit.scale.set(0.82, 0.95, 2.5);
ship.add(cockpit);
const canopyFrame = new THREE.Mesh(new THREE.BoxGeometry(0.12, 0.08, 1.2), darkMat);
canopyFrame.name = 'canopyFrame';
canopyFrame.position.set(0, 2.1, 1.3);
ship.add(canopyFrame);
const intakeL = new THREE.Mesh(boxGeo, darkMat);
intakeL.name = 'intakeL';
intakeL.position.set(0.85, 1.3, 0.2);
ship.add(intakeL);
const intakeR = new THREE.Mesh(boxGeo, darkMat);
intakeR.name = 'intakeR';
intakeR.position.set(-0.85, 1.3, 0.2);
ship.add(intakeR);
const wingL = new THREE.Group();
wingL.name = 'wingL';
wingL.position.set(0, 1.18, 0);
wingL.rotation.set(0, 0, deg(-5));
ship.add(wingL);
const extrude9 = new THREE.Mesh(extrude([[0.3, 1.1], [4.5, -2.15], [4.65, -3.35], [0.3, -3.8]], 0.1, [], [0.04, 0.05, 1]), hullMat);
extrude9.rotation.set(deg(90), 0, 0);
wingL.add(extrude9);
const box10 = new THREE.Mesh(boxGeo2, accentMat);
box10.position.set(2.4, 0.095, -2.2);
box10.rotation.set(0, deg(37), 0);
wingL.add(box10);
const cannonL = new THREE.Mesh(cylinderGeo, darkMat);
cannonL.name = 'cannonL';
cannonL.position.set(4.62, 0, -1.9);
cannonL.rotation.set(deg(90), 0, 0);
wingL.add(cannonL);
const barrelL = new THREE.Mesh(cylinderGeo2, accentMat);
barrelL.name = 'barrelL';
barrelL.position.set(4.62, 0, -0.3);
barrelL.rotation.set(deg(90), 0, 0);
wingL.add(barrelL);
const tipLightL = new THREE.Mesh(sphereGeo, glowMat);
tipLightL.name = 'tipLightL';
tipLightL.position.set(4.62, 0, -3.25);
wingL.add(tipLightL);
const wingR = new THREE.Group();
wingR.name = 'wingR';
wingR.position.set(0, 1.18, 0);
wingR.rotation.set(0, 0, deg(5));
ship.add(wingR);
const extrude15 = new THREE.Mesh(extrude([[-0.3, 1.1], [-4.5, -2.15], [-4.65, -3.35], [-0.3, -3.8]], 0.1, [], [0.04, 0.05, 1]), hullMat);
extrude15.rotation.set(deg(90), 0, 0);
wingR.add(extrude15);
const box16 = new THREE.Mesh(boxGeo2, accentMat);
box16.position.set(-2.4, 0.095, -2.2);
box16.rotation.set(0, deg(-37), 0);
wingR.add(box16);
const cannonR = new THREE.Mesh(cylinderGeo, darkMat);
cannonR.name = 'cannonR';
cannonR.position.set(-4.62, 0, -1.9);
cannonR.rotation.set(deg(90), 0, 0);
wingR.add(cannonR);
const barrelR = new THREE.Mesh(cylinderGeo2, accentMat);
barrelR.name = 'barrelR';
barrelR.position.set(-4.62, 0, -0.3);
barrelR.rotation.set(deg(90), 0, 0);
wingR.add(barrelR);
const tipLightR = new THREE.Mesh(sphereGeo, glowMat);
tipLightR.name = 'tipLightR';
tipLightR.position.set(-4.62, 0, -3.25);
wingR.add(tipLightR);
const engineL = new THREE.Group();
engineL.name = 'engineL';
engineL.position.set(1.22, 1.25, 0);
ship.add(engineL);
const nacelle = new THREE.Mesh(cylinderGeo3, hullMat);
nacelle.name = 'nacelle';
nacelle.position.set(0, 0, -3.3);
nacelle.rotation.set(deg(-90), 0, 0);
engineL.add(nacelle);
const intakeRing = new THREE.Mesh(cylinderGeo4, accentMat);
intakeRing.name = 'intakeRing';
intakeRing.position.set(0, 0, -1.62);
intakeRing.rotation.set(deg(90), 0, 0);
engineL.add(intakeRing);
const intake = new THREE.Mesh(cylinderGeo5, darkMat);
intake.name = 'intake';
intake.position.set(0, 0, -1.475);
intake.rotation.set(deg(90), 0, 0);
engineL.add(intake);
const nozzle = new THREE.Mesh(cylinderGeo6, darkMat);
nozzle.name = 'nozzle';
nozzle.position.set(0, 0, -5.05);
nozzle.rotation.set(deg(90), 0, 0);
engineL.add(nozzle);
const exhaustGlow = new THREE.Mesh(cylinderGeo7, glowMat);
exhaustGlow.name = 'exhaustGlow';
exhaustGlow.position.set(0, 0, -5.19);
exhaustGlow.rotation.set(deg(90), 0, 0);
engineL.add(exhaustGlow);
const exhaustPlume = new THREE.Mesh(coneGeo, glowMat);
exhaustPlume.name = 'exhaustPlume';
exhaustPlume.position.set(0, 0, -5.75);
exhaustPlume.rotation.set(deg(-90), 0, 0);
engineL.add(exhaustPlume);
const tailFin = new THREE.Group();
tailFin.name = 'tailFin';
tailFin.position.set(0, 0.4, 0);
tailFin.rotation.set(0, 0, deg(-22));
engineL.add(tailFin);
const extrude28 = new THREE.Mesh(extrudeGeo, hullMat);
extrude28.rotation.set(0, deg(-90), 0);
tailFin.add(extrude28);
const extrude29 = new THREE.Mesh(extrudeGeo2, accentMat);
extrude29.rotation.set(0, deg(-90), 0);
tailFin.add(extrude29);
const engineR = new THREE.Group();
engineR.name = 'engineR';
engineR.position.set(-1.22, 1.25, 0);
ship.add(engineR);
const nacelle2 = new THREE.Mesh(cylinderGeo3, hullMat);
nacelle2.name = 'nacelle';
nacelle2.position.set(0, 0, -3.3);
nacelle2.rotation.set(deg(-90), 0, 0);
engineR.add(nacelle2);
const intakeRing2 = new THREE.Mesh(cylinderGeo4, accentMat);
intakeRing2.name = 'intakeRing';
intakeRing2.position.set(0, 0, -1.62);
intakeRing2.rotation.set(deg(90), 0, 0);
engineR.add(intakeRing2);
const intake2 = new THREE.Mesh(cylinderGeo5, darkMat);
intake2.name = 'intake';
intake2.position.set(0, 0, -1.475);
intake2.rotation.set(deg(90), 0, 0);
engineR.add(intake2);
const nozzle2 = new THREE.Mesh(cylinderGeo6, darkMat);
nozzle2.name = 'nozzle';
nozzle2.position.set(0, 0, -5.05);
nozzle2.rotation.set(deg(90), 0, 0);
engineR.add(nozzle2);
const exhaustGlow2 = new THREE.Mesh(cylinderGeo7, glowMat);
exhaustGlow2.name = 'exhaustGlow';
exhaustGlow2.position.set(0, 0, -5.19);
exhaustGlow2.rotation.set(deg(90), 0, 0);
engineR.add(exhaustGlow2);
const exhaustPlume2 = new THREE.Mesh(coneGeo, glowMat);
exhaustPlume2.name = 'exhaustPlume';
exhaustPlume2.position.set(0, 0, -5.75);
exhaustPlume2.rotation.set(deg(-90), 0, 0);
engineR.add(exhaustPlume2);
const tailFin2 = new THREE.Group();
tailFin2.name = 'tailFin';
tailFin2.position.set(0, 0.4, 0);
tailFin2.rotation.set(0, 0, deg(22));
engineR.add(tailFin2);
const extrude38 = new THREE.Mesh(extrudeGeo, hullMat);
extrude38.rotation.set(0, deg(-90), 0);
tailFin2.add(extrude38);
const extrude39 = new THREE.Mesh(extrudeGeo2, accentMat);
extrude39.rotation.set(0, deg(-90), 0);
tailFin2.add(extrude39);
const noseGearStrut = new THREE.Mesh(new THREE.CylinderGeometry(0.07, 0.07, 0.8, 6), darkMat);
noseGearStrut.name = 'noseGearStrut';
noseGearStrut.position.set(0, 0.5, 3);
ship.add(noseGearStrut);
const noseGearPad = new THREE.Mesh(cylinderGeo8, darkMat);
noseGearPad.name = 'noseGearPad';
noseGearPad.position.set(0, 0.06, 3);
ship.add(noseGearPad);
const mainGearLStrut = new THREE.Mesh(cylinderGeo9, darkMat);
mainGearLStrut.name = 'mainGearLStrut';
mainGearLStrut.position.set(1.22, 0.4, -3);
ship.add(mainGearLStrut);
const mainGearLPad = new THREE.Mesh(cylinderGeo8, darkMat);
mainGearLPad.name = 'mainGearLPad';
mainGearLPad.position.set(1.22, 0.06, -3);
ship.add(mainGearLPad);
const mainGearRStrut = new THREE.Mesh(cylinderGeo9, darkMat);
mainGearRStrut.name = 'mainGearRStrut';
mainGearRStrut.position.set(-1.22, 0.4, -3);
ship.add(mainGearRStrut);
const mainGearRPad = new THREE.Mesh(cylinderGeo8, darkMat);
mainGearRPad.name = 'mainGearRPad';
mainGearRPad.position.set(-1.22, 0.06, -3);
ship.add(mainGearRPad);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createStarfighter;
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









