Codels
828 ポリゴン0.44 × 0.12 × 0.10 m
自己完結型の ES モジュールで、依存先は three のみです。ファクトリー関数を呼び出し、返された group をシーンに追加してください。
/**
 * Magic Scroll — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 828 · Size (W × H × D): 0.43 × 0.12 × 0.10 m
 *
 * Usage:
 *   import { createScroll } from './scroll.js';
 *   
 *   const model = createScroll();
 *   model.position.set(0, 0, 0);
 *   scene.add(model);
 */
import * as THREE from 'three';

const deg = THREE.MathUtils.degToRad;

// 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 createScroll() {
  const root = new THREE.Group();
  root.name = 'Scroll';

  // Materials
  const paperMat = new THREE.MeshStandardMaterial({ name: 'paper', color: 0xe8d29c, roughness: 0.9, flatShading: true });
  const edgeMat = new THREE.MeshStandardMaterial({ name: 'edge', color: 0xb89a63, roughness: 0.9, flatShading: true });
  const woodMat = new THREE.MeshStandardMaterial({ name: 'wood', color: 0x7a4b2a, roughness: 0.8, flatShading: true });
  const ribbonMat = new THREE.MeshStandardMaterial({ name: 'ribbon', color: 0xb8312f, roughness: 0.7, flatShading: true });
  const waxMat = new THREE.MeshStandardMaterial({ name: 'wax', color: 0xa3241f, roughness: 0.45, flatShading: true });

  // Shared geometries
  const cylinderGeo = new THREE.CylinderGeometry(0.011, 0.011, 0.045, 6);
  const sphereGeo = new THREE.SphereGeometry(0.02, 7, 5);
  const torusGeo = new THREE.TorusGeometry(0.017, 0.006, 4, 10);
  const boxGeo = new THREE.BoxGeometry(0.013, 0.003, 0.04);

  // Parts
  const roll = new THREE.Mesh(new THREE.CylinderGeometry(0.042, 0.042, 0.3, 12), paperMat);
  roll.name = 'roll';
  roll.position.set(0, 0.045, 0);
  roll.rotation.set(0, 0, deg(90));
  root.add(roll);
  const rollSpiralR = new THREE.Mesh(tube([[0.151, 0.045, 0.0084], [0.151, 0.0527, 0.0066], [0.151, 0.0568, -0.0019], [0.151, 0.0522, -0.0117], [0.151, 0.0402, -0.0148], [0.151, 0.029, -0.0066], [0.151, 0.028, 0.0087], [0.151, 0.0401, 0.0203], [0.151, 0.0583, 0.0183], [0.151, 0.0694, 0.0019], [0.151, 0.0636, -0.0186], [0.151, 0.0428, -0.0279], [0.151, 0.0209, -0.0175], [0.151, 0.0143, 0.0074], [0.151, 0.0298, 0.0298], [0.151, 0.0585, 0.0325], [0.151, 0.0802, 0.0114]], 0.0028, 26, 3), edgeMat);
  rollSpiralR.name = 'rollSpiralR';
  root.add(rollSpiralR);
  const rollRodR = new THREE.Mesh(cylinderGeo, woodMat);
  rollRodR.name = 'rollRodR';
  rollRodR.position.set(0.17, 0.045, 0);
  rollRodR.rotation.set(0, 0, deg(90));
  root.add(rollRodR);
  const rollKnobR = new THREE.Mesh(sphereGeo, woodMat);
  rollKnobR.name = 'rollKnobR';
  rollKnobR.position.set(0.202, 0.045, 0);
  rollKnobR.scale.set(0.85, 1, 1);
  root.add(rollKnobR);
  const rollSpiralL = new THREE.Mesh(tube([[-0.151, 0.045, 0.0084], [-0.151, 0.0527, 0.0066], [-0.151, 0.0568, -0.0019], [-0.151, 0.0522, -0.0117], [-0.151, 0.0402, -0.0148], [-0.151, 0.029, -0.0066], [-0.151, 0.028, 0.0087], [-0.151, 0.0401, 0.0203], [-0.151, 0.0583, 0.0183], [-0.151, 0.0694, 0.0019], [-0.151, 0.0636, -0.0186], [-0.151, 0.0428, -0.0279], [-0.151, 0.0209, -0.0175], [-0.151, 0.0143, 0.0074], [-0.151, 0.0298, 0.0298], [-0.151, 0.0585, 0.0325], [-0.151, 0.0802, 0.0114]], 0.0028, 26, 3), edgeMat);
  rollSpiralL.name = 'rollSpiralL';
  root.add(rollSpiralL);
  const rollRodL = new THREE.Mesh(cylinderGeo, woodMat);
  rollRodL.name = 'rollRodL';
  rollRodL.position.set(-0.17, 0.045, 0);
  rollRodL.rotation.set(0, 0, deg(90));
  root.add(rollRodL);
  const rollKnobL = new THREE.Mesh(sphereGeo, woodMat);
  rollKnobL.name = 'rollKnobL';
  rollKnobL.position.set(-0.202, 0.045, 0);
  rollKnobL.scale.set(0.85, 1, 1);
  root.add(rollKnobL);
  const ribbonBand = new THREE.Mesh(new THREE.CylinderGeometry(0.045, 0.045, 0.03, 12), ribbonMat);
  ribbonBand.name = 'ribbonBand';
  ribbonBand.position.set(0, 0.045, 0);
  ribbonBand.rotation.set(0, 0, deg(90));
  root.add(ribbonBand);
  const bowLoopR = new THREE.Mesh(torusGeo, ribbonMat);
  bowLoopR.name = 'bowLoopR';
  bowLoopR.position.set(0.018, 0.099, 0.012);
  bowLoopR.rotation.set(0, deg(20), deg(35));
  root.add(bowLoopR);
  const tailR = new THREE.Group();
  tailR.name = 'tailR';
  tailR.position.set(0.006, 0.0874, 0.0225);
  tailR.rotation.set(deg(28), 0, 0);
  root.add(tailR);
  const tailStripR = new THREE.Mesh(boxGeo, ribbonMat);
  tailStripR.name = 'tailStripR';
  tailStripR.position.set(0, 0, 0.012);
  tailStripR.rotation.set(0, deg(22), 0);
  tailR.add(tailStripR);
  const bowLoopL = new THREE.Mesh(torusGeo, ribbonMat);
  bowLoopL.name = 'bowLoopL';
  bowLoopL.position.set(-0.018, 0.099, 0.012);
  bowLoopL.rotation.set(0, deg(-20), deg(-35));
  root.add(bowLoopL);
  const tailL = new THREE.Group();
  tailL.name = 'tailL';
  tailL.position.set(-0.006, 0.0874, 0.0225);
  tailL.rotation.set(deg(28), 0, 0);
  root.add(tailL);
  const tailStripL = new THREE.Mesh(boxGeo, ribbonMat);
  tailStripL.name = 'tailStripL';
  tailStripL.position.set(0, 0, 0.012);
  tailStripL.rotation.set(0, deg(-22), 0);
  tailL.add(tailStripL);
  const knot = new THREE.Mesh(new THREE.SphereGeometry(0.011, 6, 4), ribbonMat);
  knot.name = 'knot';
  knot.position.set(0, 0.093, 0.006);
  root.add(knot);
  const seal = new THREE.Mesh(new THREE.CylinderGeometry(0.024, 0.026, 0.008, 10), waxMat);
  seal.name = 'seal';
  seal.position.set(0, 0.051, 0.048);
  seal.rotation.set(deg(80), 0, 0);
  root.add(seal);

  root.traverse((o) => {
    if (o.isMesh) {
      o.castShadow = true;
      o.receiveShadow = true;
    }
  });
  return root;
}

export default createScroll;

評価とコメント

—
まだ評価はありません。最初の評価をしてみましょう。
5
0
4
0
3
0
2
0
1
0

評価やコメントをするにはログインしてください。

0 件のコメント

まだコメントはありません。このモデルの使い方や改善できる点を共有しましょう。

関連モデル

同じカテゴリまたは似たタグ