1.5K tris1.90 × 3.06 × 1.93 m
Use it in code
Remix in the editorfuel-tank.js · 329 lines
Self-contained ES module — only depends on three. Call the factory and add the group to your scene.
/**
* Fuel Tank — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 1,464 · Size (W × H × D): 1.90 × 3.06 × 1.93 m
*
* Usage:
* import { createFuelTank } from './fuel-tank.js';
*
* const model = createFuelTank();
* 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);
}
// 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 createFuelTank() {
const root = new THREE.Group();
root.name = 'FuelTank';
// Materials
const tankMat = new THREE.MeshStandardMaterial({ name: 'tank', color: 0xd7dbe0, roughness: 0.45, metalness: 0.3, flatShading: true });
const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x2f343c, roughness: 0.6, metalness: 0.35, flatShading: true });
const metalMat = new THREE.MeshStandardMaterial({ name: 'metal', color: 0x7d858f, roughness: 0.4, metalness: 0.6, flatShading: true });
const hazardMat = new THREE.MeshStandardMaterial({ name: 'hazard', color: 0xf2b630, roughness: 0.55, metalness: 0.2, flatShading: true });
const valveMat = new THREE.MeshStandardMaterial({ name: 'valve', color: 0xd8473a, roughness: 0.5, metalness: 0.3, flatShading: true });
const fuelMat = new THREE.MeshStandardMaterial({ name: 'fuel', color: 0x8cff3a, roughness: 0.3, emissive: 0x8cff3a, emissiveIntensity: 1.2, flatShading: true });
const glassMat = new THREE.MeshStandardMaterial({ name: 'glass', color: 0xcdeefa, roughness: 0.1, metalness: 0.1, transparent: true, opacity: 0.45 });
const amberMat = new THREE.MeshStandardMaterial({ name: 'amber', color: 0xffb648, roughness: 0.4, emissive: 0xffa526, emissiveIntensity: 1.3, flatShading: true });
const gaugeMat = new THREE.MeshStandardMaterial({ name: 'gauge', color: 0xf4f6f8, roughness: 0.3, emissive: 0xdff6ff, emissiveIntensity: 0.6, flatShading: true });
// Shared geometries
const cylinderGeo = new THREE.CylinderGeometry(0.055, 0.07, 0.78, 6);
const boxGeo = new THREE.BoxGeometry(0.22, 0.06, 0.22);
const cylinderGeo2 = new THREE.CylinderGeometry(0.705, 0.705, 0.09, 12);
const boxGeo2 = new THREE.BoxGeometry(0.1, 0.06, 0.16);
const boxGeo3 = new THREE.BoxGeometry(0.05, 0.012, 0.02);
const torusGeo = new THREE.TorusGeometry(0.12, 0.018, 3, 8);
const boxGeo4 = new THREE.BoxGeometry(0.22, 0.022, 0.022);
const boxGeo5 = new THREE.BoxGeometry(0.022, 0.22, 0.022);
const cylinderGeo3 = new THREE.CylinderGeometry(0.035, 0.035, 0.06, 6);
// Parts
const skid = new THREE.Mesh(new THREE.BoxGeometry(1.9, 0.1, 1.9), darkMat);
skid.name = 'skid';
skid.position.set(0, 0.05, 0);
root.add(skid);
const deck = new THREE.Mesh(new THREE.BoxGeometry(1.7, 0.04, 1.7), metalMat);
deck.name = 'deck';
deck.position.set(0, 0.12, 0);
root.add(deck);
const hazardPlate = new THREE.Group();
hazardPlate.name = 'hazardPlate';
hazardPlate.position.set(0, 0.07, 0.96);
root.add(hazardPlate);
const plate = new THREE.Mesh(new THREE.BoxGeometry(1.7, 0.14, 0.03), darkMat);
plate.name = 'plate';
hazardPlate.add(plate);
const extrude5 = new THREE.Mesh(extrude([[-0.75, -0.055], [-0.69, -0.055], [-0.63, 0.055], [-0.69, 0.055]], 0.02), hazardMat);
extrude5.position.set(0, 0, 0.012);
hazardPlate.add(extrude5);
const extrude6 = new THREE.Mesh(extrude([[-0.57, -0.055], [-0.51, -0.055], [-0.45, 0.055], [-0.51, 0.055]], 0.02), hazardMat);
extrude6.position.set(0, 0, 0.012);
hazardPlate.add(extrude6);
const extrude7 = new THREE.Mesh(extrude([[-0.39, -0.055], [-0.33, -0.055], [-0.27, 0.055], [-0.33, 0.055]], 0.02), hazardMat);
extrude7.position.set(0, 0, 0.012);
hazardPlate.add(extrude7);
const extrude8 = new THREE.Mesh(extrude([[-0.21, -0.055], [-0.15, -0.055], [-0.09, 0.055], [-0.15, 0.055]], 0.02), hazardMat);
extrude8.position.set(0, 0, 0.012);
hazardPlate.add(extrude8);
const extrude9 = new THREE.Mesh(extrude([[-0.03, -0.055], [0.03, -0.055], [0.09, 0.055], [0.03, 0.055]], 0.02), hazardMat);
extrude9.position.set(0, 0, 0.012);
hazardPlate.add(extrude9);
const extrude10 = new THREE.Mesh(extrude([[0.15, -0.055], [0.21, -0.055], [0.27, 0.055], [0.21, 0.055]], 0.02), hazardMat);
extrude10.position.set(0, 0, 0.012);
hazardPlate.add(extrude10);
const extrude11 = new THREE.Mesh(extrude([[0.33, -0.055], [0.39, -0.055], [0.45, 0.055], [0.39, 0.055]], 0.02), hazardMat);
extrude11.position.set(0, 0, 0.012);
hazardPlate.add(extrude11);
const extrude12 = new THREE.Mesh(extrude([[0.51, -0.055], [0.57, -0.055], [0.63, 0.055], [0.57, 0.055]], 0.02), hazardMat);
extrude12.position.set(0, 0, 0.012);
hazardPlate.add(extrude12);
const extrude13 = new THREE.Mesh(extrude([[0.69, -0.055], [0.75, -0.055], [0.81, 0.055], [0.75, 0.055]], 0.02), hazardMat);
extrude13.position.set(0, 0, 0.012);
hazardPlate.add(extrude13);
const leg1 = new THREE.Mesh(cylinderGeo, metalMat);
leg1.name = 'leg1';
leg1.position.set(0.4596, 0.5, 0.4596);
leg1.rotation.set(deg(-15.7932), deg(-2.2042), deg(15.7932));
root.add(leg1);
const legFoot1 = new THREE.Mesh(boxGeo, darkMat);
legFoot1.name = 'legFoot1';
legFoot1.position.set(0.5657, 0.17, 0.5657);
legFoot1.rotation.set(0, deg(45), 0);
root.add(legFoot1);
const leg2 = new THREE.Mesh(cylinderGeo, metalMat);
leg2.name = 'leg2';
leg2.position.set(0.4596, 0.5, -0.4596);
leg2.rotation.set(deg(15.7932), deg(2.2042), deg(15.7932));
root.add(leg2);
const legFoot2 = new THREE.Mesh(boxGeo, darkMat);
legFoot2.name = 'legFoot2';
legFoot2.position.set(0.5657, 0.17, -0.5657);
legFoot2.rotation.set(0, deg(45), 0);
root.add(legFoot2);
const leg3 = new THREE.Mesh(cylinderGeo, metalMat);
leg3.name = 'leg3';
leg3.position.set(-0.4596, 0.5, -0.4596);
leg3.rotation.set(deg(15.7932), deg(-2.2042), deg(-15.7932));
root.add(leg3);
const legFoot3 = new THREE.Mesh(boxGeo, darkMat);
legFoot3.name = 'legFoot3';
legFoot3.position.set(-0.5657, 0.17, -0.5657);
legFoot3.rotation.set(0, deg(45), 0);
root.add(legFoot3);
const leg4 = new THREE.Mesh(cylinderGeo, metalMat);
leg4.name = 'leg4';
leg4.position.set(-0.4596, 0.5, 0.4596);
leg4.rotation.set(deg(-15.7932), deg(2.2042), deg(-15.7932));
root.add(leg4);
const legFoot4 = new THREE.Mesh(boxGeo, darkMat);
legFoot4.name = 'legFoot4';
legFoot4.position.set(-0.5657, 0.17, 0.5657);
legFoot4.rotation.set(0, deg(45), 0);
root.add(legFoot4);
const vessel = new THREE.Mesh(lathe([[0.001, 0.38], [0.374, 0.452], [0.5848, 0.588], [0.68, 0.78], [0.68, 2.18], [0.5848, 2.372], [0.374, 2.508], [0.001, 2.58]], 12), tankMat);
vessel.name = 'vessel';
vessel.rotation.set(0, deg(15), 0);
root.add(vessel);
const cylinder23 = new THREE.Mesh(cylinderGeo2, darkMat);
cylinder23.position.set(0, 0.8, 0);
cylinder23.rotation.set(0, deg(15), 0);
root.add(cylinder23);
const cylinder24 = new THREE.Mesh(cylinderGeo2, darkMat);
cylinder24.position.set(0, 2.16, 0);
cylinder24.rotation.set(0, deg(15), 0);
root.add(cylinder24);
const hazardBand = new THREE.Mesh(new THREE.CylinderGeometry(0.695, 0.695, 0.2, 16), darkMat);
hazardBand.name = 'hazardBand';
hazardBand.position.set(0, 1.73, 0);
root.add(hazardBand);
const hazardStripe1 = new THREE.Mesh(new THREE.CylinderGeometry(0.702, 0.702, 0.2, 1, 1, false, 0, 0.3927), hazardMat);
hazardStripe1.name = 'hazardStripe1';
hazardStripe1.position.set(0, 1.73, 0);
root.add(hazardStripe1);
const hazardStripe2 = new THREE.Mesh(new THREE.CylinderGeometry(0.702, 0.702, 0.2, 1, 1, false, Math.PI / 4, 0.3927), hazardMat);
hazardStripe2.name = 'hazardStripe2';
hazardStripe2.position.set(0, 1.73, 0);
root.add(hazardStripe2);
const hazardStripe3 = new THREE.Mesh(new THREE.CylinderGeometry(0.702, 0.702, 0.2, 1, 1, false, Math.PI / 2, 0.3927), hazardMat);
hazardStripe3.name = 'hazardStripe3';
hazardStripe3.position.set(0, 1.73, 0);
root.add(hazardStripe3);
const hazardStripe4 = new THREE.Mesh(new THREE.CylinderGeometry(0.702, 0.702, 0.2, 1, 1, false, Math.PI * 0.75, 0.3927), hazardMat);
hazardStripe4.name = 'hazardStripe4';
hazardStripe4.position.set(0, 1.73, 0);
root.add(hazardStripe4);
const hazardStripe5 = new THREE.Mesh(new THREE.CylinderGeometry(0.702, 0.702, 0.2, 1, 1, false, Math.PI, 0.3927), hazardMat);
hazardStripe5.name = 'hazardStripe5';
hazardStripe5.position.set(0, 1.73, 0);
root.add(hazardStripe5);
const hazardStripe6 = new THREE.Mesh(new THREE.CylinderGeometry(0.702, 0.702, 0.2, 1, 1, false, Math.PI * 1.25, 0.3927), hazardMat);
hazardStripe6.name = 'hazardStripe6';
hazardStripe6.position.set(0, 1.73, 0);
root.add(hazardStripe6);
const hazardStripe7 = new THREE.Mesh(new THREE.CylinderGeometry(0.702, 0.702, 0.2, 1, 1, false, Math.PI * 1.5, 0.3927), hazardMat);
hazardStripe7.name = 'hazardStripe7';
hazardStripe7.position.set(0, 1.73, 0);
root.add(hazardStripe7);
const hazardStripe8 = new THREE.Mesh(new THREE.CylinderGeometry(0.702, 0.702, 0.2, 1, 1, false, Math.PI * 1.75, 0.3927), hazardMat);
hazardStripe8.name = 'hazardStripe8';
hazardStripe8.position.set(0, 1.73, 0);
root.add(hazardStripe8);
const box34 = new THREE.Mesh(boxGeo2, metalMat);
box34.position.set(0, 0.79, 0.73);
root.add(box34);
const box35 = new THREE.Mesh(boxGeo2, metalMat);
box35.position.set(0, 2.17, 0.73);
root.add(box35);
const sightGlass = new THREE.Mesh(new THREE.CylinderGeometry(0.05, 0.05, 1.3, 8), glassMat);
sightGlass.name = 'sightGlass';
sightGlass.position.set(0, 1.48, 0.79);
root.add(sightGlass);
const fuelLevel = new THREE.Mesh(new THREE.CylinderGeometry(0.034, 0.034, 0.91, 6), fuelMat);
fuelLevel.name = 'fuelLevel';
fuelLevel.position.set(0, 1.285, 0.79);
root.add(fuelLevel);
const box38 = new THREE.Mesh(boxGeo3, darkMat);
box38.position.set(0.075, 1.155, 0.79);
root.add(box38);
const box39 = new THREE.Mesh(boxGeo3, darkMat);
box39.position.set(0.075, 1.48, 0.79);
root.add(box39);
const box40 = new THREE.Mesh(boxGeo3, darkMat);
box40.position.set(0.075, 1.805, 0.79);
root.add(box40);
const gaugeStem = new THREE.Mesh(new THREE.CylinderGeometry(0.025, 0.025, 0.154, 6), metalMat);
gaugeStem.name = 'gaugeStem';
gaugeStem.position.set(0.4043, 1.13, 0.5994);
gaugeStem.rotation.set(deg(69.3345), deg(-27.6191), deg(-39.1319));
root.add(gaugeStem);
const gauge = new THREE.Group();
gauge.name = 'gauge';
gauge.position.set(0.4641, 1.13, 0.6881);
gauge.rotation.set(0, deg(34), 0);
root.add(gauge);
const gaugeBody = new THREE.Mesh(new THREE.CylinderGeometry(0.12, 0.12, 0.06, 10), darkMat);
gaugeBody.name = 'gaugeBody';
gaugeBody.rotation.set(deg(90), 0, 0);
gauge.add(gaugeBody);
const gaugeFace = new THREE.Mesh(new THREE.CylinderGeometry(0.1, 0.1, 0.01, 10), gaugeMat);
gaugeFace.name = 'gaugeFace';
gaugeFace.position.set(0, 0, 0.03);
gaugeFace.rotation.set(deg(90), 0, 0);
gauge.add(gaugeFace);
const needle = new THREE.Mesh(new THREE.BoxGeometry(0.012, 0.08, 0.01), valveMat);
needle.name = 'needle';
needle.position.set(0.02, 0.025, 0.04);
needle.rotation.set(0, 0, deg(-35));
gauge.add(needle);
const feedPipe = new THREE.Mesh(tube([[0.25, 0.5, 0.2], [0.62, 0.42, 0.42], [0.8, 0.36, 0.5], [0.8, 0.14, 0.5]], 0.05, 8, 5), metalMat);
feedPipe.name = 'feedPipe';
root.add(feedPipe);
const feedFlange = new THREE.Mesh(new THREE.CylinderGeometry(0.085, 0.085, 0.07, 8), darkMat);
feedFlange.name = 'feedFlange';
feedFlange.position.set(0.8, 0.155, 0.5);
root.add(feedFlange);
const feedValveBody = new THREE.Mesh(new THREE.CylinderGeometry(0.075, 0.075, 0.1, 8), metalMat);
feedValveBody.name = 'feedValveBody';
feedValveBody.position.set(0.8, 0.3, 0.5);
root.add(feedValveBody);
const feedValve = new THREE.Group();
feedValve.name = 'feedValve';
feedValve.position.set(0.8, 0.3, 0.6);
root.add(feedValve);
const wheelRim = new THREE.Mesh(torusGeo, valveMat);
wheelRim.name = 'wheelRim';
feedValve.add(wheelRim);
const box51 = new THREE.Mesh(boxGeo4, valveMat);
feedValve.add(box51);
const box52 = new THREE.Mesh(boxGeo5, valveMat);
feedValve.add(box52);
const wheelHub = new THREE.Mesh(cylinderGeo3, metalMat);
wheelHub.name = 'wheelHub';
wheelHub.rotation.set(deg(90), 0, 0);
feedValve.add(wheelHub);
const topFlange = new THREE.Mesh(new THREE.CylinderGeometry(0.08, 0.1, 0.12, 8), darkMat);
topFlange.name = 'topFlange';
topFlange.position.set(0, 2.61, 0);
root.add(topFlange);
const ventPipe = new THREE.Mesh(tube([[0, 2.63, 0], [0, 2.88, 0], [0.12, 3, 0], [0.38, 3, 0]], 0.045, 6, 5), metalMat);
ventPipe.name = 'ventPipe';
root.add(ventPipe);
const ventValveBody = new THREE.Mesh(new THREE.CylinderGeometry(0.065, 0.065, 0.1, 8), metalMat);
ventValveBody.name = 'ventValveBody';
ventValveBody.position.set(0, 2.8, 0);
root.add(ventValveBody);
const ventValve = new THREE.Group();
ventValve.name = 'ventValve';
ventValve.position.set(0, 2.8, 0.1);
root.add(ventValve);
const wheelRim2 = new THREE.Mesh(torusGeo, valveMat);
wheelRim2.name = 'wheelRim';
ventValve.add(wheelRim2);
const box59 = new THREE.Mesh(boxGeo4, valveMat);
ventValve.add(box59);
const box60 = new THREE.Mesh(boxGeo5, valveMat);
ventValve.add(box60);
const wheelHub2 = new THREE.Mesh(cylinderGeo3, metalMat);
wheelHub2.name = 'wheelHub';
wheelHub2.rotation.set(deg(90), 0, 0);
ventValve.add(wheelHub2);
const ventCap = new THREE.Mesh(new THREE.CylinderGeometry(0.06, 0.06, 0.05, 8), darkMat);
ventCap.name = 'ventCap';
ventCap.position.set(0.4, 3, 0);
ventCap.rotation.set(0, 0, deg(90));
root.add(ventCap);
const lightBase = new THREE.Mesh(new THREE.CylinderGeometry(0.06, 0.07, 0.05, 8), darkMat);
lightBase.name = 'lightBase';
lightBase.position.set(-0.36, 2.453, 0.2);
lightBase.rotation.set(0, 0, deg(22));
root.add(lightBase);
const warningLight = new THREE.Mesh(new THREE.SphereGeometry(0.06, 6, 4), amberMat);
warningLight.name = 'warningLight';
warningLight.position.set(-0.38, 2.508, 0.2);
root.add(warningLight);
const labelPanel = new THREE.Mesh(new THREE.BoxGeometry(0.5, 0.3, 0.03), darkMat);
labelPanel.name = 'labelPanel';
labelPanel.position.set(-0.4928, 1.33, -0.4928);
labelPanel.rotation.set(0, deg(-135), 0);
root.add(labelPanel);
const labelStrip = new THREE.Mesh(new THREE.BoxGeometry(0.36, 0.05, 0.02), amberMat);
labelStrip.name = 'labelStrip';
labelStrip.position.set(-0.5128, 1.38, -0.5128);
labelStrip.rotation.set(0, deg(-135), 0);
root.add(labelStrip);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createFuelTank;
Ratings & comments
0 comments
No comments yet. Share how you used this model or what could be better.
Related models
Same category or similar tags









