1448 ポリゴン1.01 × 0.85 × 1.01 m
コードで使う
エディターでリミックスspring.js · 250 行
自己完結型の ES モジュールで、依存先は three のみです。ファクトリー関数を呼び出し、返された group をシーンに追加してください。
/**
* Spring Bouncer — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 1,448 · Size (W × H × D): 1.01 × 0.85 × 1.01 m
*
* Usage:
* import { createSpring } from './spring.js';
*
* const model = createSpring();
* 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);
}
// 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 createSpring() {
const root = new THREE.Group();
root.name = 'Spring';
// Materials
const baseMat = new THREE.MeshStandardMaterial({ name: 'base', color: 0x323a4a, roughness: 0.6, metalness: 0.3, flatShading: true });
const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x20242c, roughness: 0.7, metalness: 0.3, flatShading: true });
const hazardMat = new THREE.MeshStandardMaterial({ name: 'hazard', color: 0xf5c02a, roughness: 0.55, flatShading: true });
const stripeMat = new THREE.MeshStandardMaterial({ name: 'stripe', color: 0x1d1f25, roughness: 0.7, flatShading: true });
const coilMat = new THREE.MeshStandardMaterial({ name: 'coil', color: 0xd3d9e2, roughness: 0.25, metalness: 0.8, flatShading: true });
const plateMat = new THREE.MeshStandardMaterial({ name: 'plate', color: 0xe8392f, roughness: 0.4, flatShading: true });
const plateTopMat = new THREE.MeshStandardMaterial({ name: 'plateTop', color: 0xec5d54, roughness: 0.45, flatShading: true });
const arrowMat = new THREE.MeshStandardMaterial({ name: 'arrow', color: 0xffffff, roughness: 0.4, emissive: 0xfff4c8, emissiveIntensity: 0.8, flatShading: true });
// Shared geometries
const extrudeGeo = extrude([[-0.5, 0.03], [-0.5, -0.03], [-0.49, -0.03], [-0.43, 0.03]], 0.006);
const extrudeGeo2 = extrude([[-0.42, -0.03], [-0.35, -0.03], [-0.29, 0.03], [-0.36, 0.03]], 0.006);
const extrudeGeo3 = extrude([[-0.28, -0.03], [-0.21, -0.03], [-0.15, 0.03], [-0.22, 0.03]], 0.006);
const extrudeGeo4 = extrude([[-0.14, -0.03], [-0.07, -0.03], [-0.01, 0.03], [-0.08, 0.03]], 0.006);
const extrudeGeo5 = extrude([[0, -0.03], [0.07, -0.03], [0.13, 0.03], [0.06, 0.03]], 0.006);
const extrudeGeo6 = extrude([[0.14, -0.03], [0.21, -0.03], [0.27, 0.03], [0.2, 0.03]], 0.006);
const extrudeGeo7 = extrude([[0.28, -0.03], [0.35, -0.03], [0.41, 0.03], [0.34, 0.03]], 0.006);
const extrudeGeo8 = extrude([[0.42, -0.03], [0.49, -0.03], [0.5, -0.02], [0.5, 0.03], [0.48, 0.03]], 0.006);
const cylinderGeo = new THREE.CylinderGeometry(0.03, 0.03, 0.02, 6);
const extrudeGeo9 = extrude([[0, 0], [0.2, -0.2], [0.2, -0.28], [0, -0.08], [-0.2, -0.28], [-0.2, -0.2]], 0.014);
// Parts
const springBouncer = new THREE.Group();
springBouncer.name = 'springBouncer';
root.add(springBouncer);
const baseBand = new THREE.Mesh(new THREE.BoxGeometry(1, 0.06, 1), hazardMat);
baseBand.name = 'baseBand';
baseBand.position.set(0, 0.03, 0);
springBouncer.add(baseBand);
const base = new THREE.Mesh(new THREE.BoxGeometry(0.96, 0.08, 0.96), baseMat);
base.name = 'base';
base.position.set(0, 0.1, 0);
springBouncer.add(base);
const baseStripesFront = new THREE.Group();
baseStripesFront.name = 'baseStripesFront';
baseStripesFront.position.set(0, 0.03, 0.5);
springBouncer.add(baseStripesFront);
const extrude5 = new THREE.Mesh(extrudeGeo, stripeMat);
extrude5.position.set(0, 0, 0.003);
baseStripesFront.add(extrude5);
const extrude6 = new THREE.Mesh(extrudeGeo2, stripeMat);
extrude6.position.set(0, 0, 0.003);
baseStripesFront.add(extrude6);
const extrude7 = new THREE.Mesh(extrudeGeo3, stripeMat);
extrude7.position.set(0, 0, 0.003);
baseStripesFront.add(extrude7);
const extrude8 = new THREE.Mesh(extrudeGeo4, stripeMat);
extrude8.position.set(0, 0, 0.003);
baseStripesFront.add(extrude8);
const extrude9 = new THREE.Mesh(extrudeGeo5, stripeMat);
extrude9.position.set(0, 0, 0.003);
baseStripesFront.add(extrude9);
const extrude10 = new THREE.Mesh(extrudeGeo6, stripeMat);
extrude10.position.set(0, 0, 0.003);
baseStripesFront.add(extrude10);
const extrude11 = new THREE.Mesh(extrudeGeo7, stripeMat);
extrude11.position.set(0, 0, 0.003);
baseStripesFront.add(extrude11);
const extrude12 = new THREE.Mesh(extrudeGeo8, stripeMat);
extrude12.position.set(0, 0, 0.003);
baseStripesFront.add(extrude12);
const baseStripesRight = new THREE.Group();
baseStripesRight.name = 'baseStripesRight';
baseStripesRight.position.set(0.5, 0.03, 0);
baseStripesRight.rotation.set(0, deg(90), 0);
springBouncer.add(baseStripesRight);
const extrude14 = new THREE.Mesh(extrudeGeo, stripeMat);
extrude14.position.set(0, 0, 0.003);
baseStripesRight.add(extrude14);
const extrude15 = new THREE.Mesh(extrudeGeo2, stripeMat);
extrude15.position.set(0, 0, 0.003);
baseStripesRight.add(extrude15);
const extrude16 = new THREE.Mesh(extrudeGeo3, stripeMat);
extrude16.position.set(0, 0, 0.003);
baseStripesRight.add(extrude16);
const extrude17 = new THREE.Mesh(extrudeGeo4, stripeMat);
extrude17.position.set(0, 0, 0.003);
baseStripesRight.add(extrude17);
const extrude18 = new THREE.Mesh(extrudeGeo5, stripeMat);
extrude18.position.set(0, 0, 0.003);
baseStripesRight.add(extrude18);
const extrude19 = new THREE.Mesh(extrudeGeo6, stripeMat);
extrude19.position.set(0, 0, 0.003);
baseStripesRight.add(extrude19);
const extrude20 = new THREE.Mesh(extrudeGeo7, stripeMat);
extrude20.position.set(0, 0, 0.003);
baseStripesRight.add(extrude20);
const extrude21 = new THREE.Mesh(extrudeGeo8, stripeMat);
extrude21.position.set(0, 0, 0.003);
baseStripesRight.add(extrude21);
const baseStripesBack = new THREE.Group();
baseStripesBack.name = 'baseStripesBack';
baseStripesBack.position.set(0, 0.03, -0.5);
baseStripesBack.rotation.set(0, deg(180), 0);
springBouncer.add(baseStripesBack);
const extrude23 = new THREE.Mesh(extrudeGeo, stripeMat);
extrude23.position.set(0, 0, 0.003);
baseStripesBack.add(extrude23);
const extrude24 = new THREE.Mesh(extrudeGeo2, stripeMat);
extrude24.position.set(0, 0, 0.003);
baseStripesBack.add(extrude24);
const extrude25 = new THREE.Mesh(extrudeGeo3, stripeMat);
extrude25.position.set(0, 0, 0.003);
baseStripesBack.add(extrude25);
const extrude26 = new THREE.Mesh(extrudeGeo4, stripeMat);
extrude26.position.set(0, 0, 0.003);
baseStripesBack.add(extrude26);
const extrude27 = new THREE.Mesh(extrudeGeo5, stripeMat);
extrude27.position.set(0, 0, 0.003);
baseStripesBack.add(extrude27);
const extrude28 = new THREE.Mesh(extrudeGeo6, stripeMat);
extrude28.position.set(0, 0, 0.003);
baseStripesBack.add(extrude28);
const extrude29 = new THREE.Mesh(extrudeGeo7, stripeMat);
extrude29.position.set(0, 0, 0.003);
baseStripesBack.add(extrude29);
const extrude30 = new THREE.Mesh(extrudeGeo8, stripeMat);
extrude30.position.set(0, 0, 0.003);
baseStripesBack.add(extrude30);
const baseStripesLeft = new THREE.Group();
baseStripesLeft.name = 'baseStripesLeft';
baseStripesLeft.position.set(-0.5, 0.03, 0);
baseStripesLeft.rotation.set(0, deg(-90), 0);
springBouncer.add(baseStripesLeft);
const extrude32 = new THREE.Mesh(extrudeGeo, stripeMat);
extrude32.position.set(0, 0, 0.003);
baseStripesLeft.add(extrude32);
const extrude33 = new THREE.Mesh(extrudeGeo2, stripeMat);
extrude33.position.set(0, 0, 0.003);
baseStripesLeft.add(extrude33);
const extrude34 = new THREE.Mesh(extrudeGeo3, stripeMat);
extrude34.position.set(0, 0, 0.003);
baseStripesLeft.add(extrude34);
const extrude35 = new THREE.Mesh(extrudeGeo4, stripeMat);
extrude35.position.set(0, 0, 0.003);
baseStripesLeft.add(extrude35);
const extrude36 = new THREE.Mesh(extrudeGeo5, stripeMat);
extrude36.position.set(0, 0, 0.003);
baseStripesLeft.add(extrude36);
const extrude37 = new THREE.Mesh(extrudeGeo6, stripeMat);
extrude37.position.set(0, 0, 0.003);
baseStripesLeft.add(extrude37);
const extrude38 = new THREE.Mesh(extrudeGeo7, stripeMat);
extrude38.position.set(0, 0, 0.003);
baseStripesLeft.add(extrude38);
const extrude39 = new THREE.Mesh(extrudeGeo8, stripeMat);
extrude39.position.set(0, 0, 0.003);
baseStripesLeft.add(extrude39);
const cylinder40 = new THREE.Mesh(cylinderGeo, coilMat);
cylinder40.position.set(-0.4, 0.15, -0.4);
springBouncer.add(cylinder40);
const cylinder41 = new THREE.Mesh(cylinderGeo, coilMat);
cylinder41.position.set(0.4, 0.15, -0.4);
springBouncer.add(cylinder41);
const cylinder42 = new THREE.Mesh(cylinderGeo, coilMat);
cylinder42.position.set(0.4, 0.15, 0.4);
springBouncer.add(cylinder42);
const cylinder43 = new THREE.Mesh(cylinderGeo, coilMat);
cylinder43.position.set(-0.4, 0.15, 0.4);
springBouncer.add(cylinder43);
const seat = new THREE.Mesh(new THREE.CylinderGeometry(0.36, 0.38, 0.04, 12), darkMat);
seat.name = 'seat';
seat.position.set(0, 0.16, 0);
springBouncer.add(seat);
const coil = new THREE.Group();
coil.name = 'coil';
coil.position.set(0, 0.14, 0);
springBouncer.add(coil);
const wire = new THREE.Mesh(tube([[0.3, 0.06, 0], [0.2427, 0.0692, 0.1763], [0.0927, 0.0783, 0.2853], [-0.0927, 0.0875, 0.2853], [-0.2427, 0.0966, 0.1763], [-0.3, 0.1058, 0], [-0.2427, 0.1149, -0.1763], [-0.0927, 0.1241, -0.2853], [0.0927, 0.1332, -0.2853], [0.2427, 0.1424, -0.1763], [0.3, 0.1516, 0], [0.2427, 0.1607, 0.1763], [0.0927, 0.1699, 0.2853], [-0.0927, 0.179, 0.2853], [-0.2427, 0.1882, 0.1763], [-0.3, 0.1973, 0], [-0.2427, 0.2065, -0.1763], [-0.0927, 0.2156, -0.2853], [0.0927, 0.2248, -0.2853], [0.2427, 0.234, -0.1763], [0.3, 0.2431, 0], [0.2427, 0.2523, 0.1763], [0.0927, 0.2614, 0.2853], [-0.0927, 0.2706, 0.2853], [-0.2427, 0.2797, 0.1763], [-0.3, 0.2889, 0], [-0.2427, 0.298, -0.1763], [-0.0927, 0.3072, -0.2853], [0.0927, 0.3164, -0.2853], [0.2427, 0.3255, -0.1763], [0.3, 0.3347, 0], [0.2427, 0.3438, 0.1763], [0.0927, 0.353, 0.2853], [-0.0927, 0.3621, 0.2853], [-0.2427, 0.3713, 0.1763], [-0.3, 0.3804, 0], [-0.2427, 0.3896, -0.1763], [-0.0927, 0.3988, -0.2853], [0.0927, 0.4079, -0.2853], [0.2427, 0.4171, -0.1763], [0.3, 0.4262, 0], [0.2427, 0.4354, 0.1763], [0.0927, 0.4445, 0.2853], [-0.0927, 0.4537, 0.2853], [-0.2427, 0.4628, 0.1763], [-0.3, 0.472, 0]], 0.045, 63, 6), coilMat);
wire.name = 'wire';
coil.add(wire);
const plate = new THREE.Group();
plate.name = 'plate';
plate.position.set(0, 0.672, 0);
springBouncer.add(plate);
const plateCap = new THREE.Mesh(new THREE.CylinderGeometry(0.36, 0.36, 0.05, 12), darkMat);
plateCap.name = 'plateCap';
plateCap.position.set(0, -0.005, 0);
plate.add(plateCap);
const plateBody = new THREE.Mesh(new THREE.BoxGeometry(0.9, 0.12, 0.9), plateMat);
plateBody.name = 'plateBody';
plateBody.position.set(0, 0.08, 0);
plate.add(plateBody);
const plateLip = new THREE.Mesh(new THREE.BoxGeometry(0.94, 0.04, 0.94), plateMat);
plateLip.name = 'plateLip';
plateLip.position.set(0, 0.08, 0);
plate.add(plateLip);
const plateTop = new THREE.Mesh(new THREE.BoxGeometry(0.78, 0.02, 0.78), plateTopMat);
plateTop.name = 'plateTop';
plateTop.position.set(0, 0.15, 0);
plate.add(plateTop);
const chevron1 = new THREE.Mesh(extrudeGeo9, arrowMat);
chevron1.name = 'chevron1';
chevron1.position.set(0, 0.167, -0.04);
chevron1.rotation.set(deg(-90), 0, 0);
plate.add(chevron1);
const chevron2 = new THREE.Mesh(extrudeGeo9, arrowMat);
chevron2.name = 'chevron2';
chevron2.position.set(0, 0.167, -0.24);
chevron2.rotation.set(deg(-90), 0, 0);
plate.add(chevron2);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createSpring;
評価とコメント
0 件のコメント
まだコメントはありません。このモデルの使い方や改善できる点を共有しましょう。
関連モデル
同じカテゴリまたは似たタグ









