Codels
864 ポリゴン1.35 × 1.05 × 0.67 m
自己完結型の ES モジュールで、依存先は three のみです。ファクトリー関数を呼び出し、返された group をシーンに追加してください。
/**
 * Writing Desk — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 864 · Size (W × H × D): 1.35 × 1.05 × 0.67 m
 *
 * Usage:
 *   import { createDesk } from './desk.js';
 *   
 *   const model = createDesk();
 *   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 createDesk() {
  const root = new THREE.Group();
  root.name = 'Desk';

  // Materials
  const woodMat = new THREE.MeshStandardMaterial({ name: 'wood', color: 0x80502e, roughness: 0.8, flatShading: true });
  const panelMat = new THREE.MeshStandardMaterial({ name: 'panel', color: 0x8f6547, roughness: 0.75, flatShading: true });
  const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x4d301c, roughness: 0.95, flatShading: true });
  const leatherMat = new THREE.MeshStandardMaterial({ name: 'leather', color: 0x3f6148, roughness: 0.7, flatShading: true });
  const brassMat = new THREE.MeshStandardMaterial({ name: 'brass', color: 0xd4a84e, roughness: 0.35, metalness: 0.5, flatShading: true });
  const paperMat = new THREE.MeshStandardMaterial({ name: 'paper', color: 0xf1ead8, roughness: 1, flatShading: true });
  const redMat = new THREE.MeshStandardMaterial({ name: 'red', color: 0xa3413a, roughness: 0.85, flatShading: true });
  const blueMat = new THREE.MeshStandardMaterial({ name: 'blue', color: 0x34557a, roughness: 0.85, flatShading: true });
  const inkMat = new THREE.MeshStandardMaterial({ name: 'ink', color: 0x1d2230, roughness: 0.2, metalness: 0.1, flatShading: true });

  // Shared geometries
  const extrudeGeo = extrude([[0.184, 0.0786], [0.1701, 0.0925], [-0.1701, 0.0925], [-0.184, 0.0786], [-0.184, -0.0786], [-0.1701, -0.0925], [0.1701, -0.0925], [0.184, -0.0786]], 0.008, [], [0.006, 0.006, 1]);
  const boxGeo = new THREE.BoxGeometry(0.01, 0.01, 0.026);
  const cylinderGeo = new THREE.CylinderGeometry(0.005, 0.005, 0.1, 6);
  const cylinderGeo2 = new THREE.CylinderGeometry(0.0318, 0.0226, 0.725, 4);
  const boxGeo2 = new THREE.BoxGeometry(0.21, 0.004, 0.29);

  // Parts
  const top = new THREE.Mesh(extrude([[0.665, 0.3072], [0.6522, 0.32], [-0.6522, 0.32], [-0.665, 0.3072], [-0.665, -0.3072], [-0.6522, -0.32], [0.6522, -0.32], [0.665, -0.3072]], 0.015, [], [0.01, 0.01, 1]), woodMat);
  top.name = 'top';
  top.position.set(0, 0.7425, 0);
  top.rotation.set(deg(-90), 0, 0);
  root.add(top);
  const leatherInlay = new THREE.Mesh(new THREE.BoxGeometry(1.19, 0.004, 0.5), leatherMat);
  leatherInlay.name = 'leatherInlay';
  leatherInlay.position.set(0, 0.761, 0);
  root.add(leatherInlay);
  const pedestalRight = new THREE.Group();
  pedestalRight.name = 'pedestalRight';
  pedestalRight.position.set(0.435, 0, 0);
  root.add(pedestalRight);
  const plinth = new THREE.Mesh(new THREE.BoxGeometry(0.44, 0.06, 0.6), darkMat);
  plinth.name = 'plinth';
  plinth.position.set(0, 0.03, 0);
  pedestalRight.add(plinth);
  const carcass = new THREE.Mesh(new THREE.BoxGeometry(0.42, 0.665, 0.59), woodMat);
  carcass.name = 'carcass';
  carcass.position.set(0, 0.3925, 0);
  pedestalRight.add(carcass);
  const drawer = new THREE.Mesh(extrudeGeo, panelMat);
  drawer.name = 'drawer';
  drawer.position.set(0, 0.1775, 0.303);
  pedestalRight.add(drawer);
  const pull = new THREE.Group();
  pull.name = 'pull';
  pull.position.set(0, 0.2033, 0.313);
  pedestalRight.add(pull);
  const pullPost = new THREE.Mesh(boxGeo, brassMat);
  pullPost.name = 'pullPost';
  pullPost.position.set(-0.045, 0, 0.013);
  pull.add(pullPost);
  const pullPost2 = new THREE.Mesh(boxGeo, brassMat);
  pullPost2.name = 'pullPost';
  pullPost2.position.set(0.045, 0, 0.013);
  pull.add(pullPost2);
  const pullBar = new THREE.Mesh(cylinderGeo, brassMat);
  pullBar.name = 'pullBar';
  pullBar.position.set(0, 0, 0.026);
  pullBar.rotation.set(0, 0, deg(90));
  pull.add(pullBar);
  const drawer2 = new THREE.Mesh(extrudeGeo, panelMat);
  drawer2.name = 'drawer';
  drawer2.position.set(0, 0.3925, 0.303);
  pedestalRight.add(drawer2);
  const pull2 = new THREE.Group();
  pull2.name = 'pull';
  pull2.position.set(0, 0.4183, 0.313);
  pedestalRight.add(pull2);
  const pullPost3 = new THREE.Mesh(boxGeo, brassMat);
  pullPost3.name = 'pullPost';
  pullPost3.position.set(-0.045, 0, 0.013);
  pull2.add(pullPost3);
  const pullPost4 = new THREE.Mesh(boxGeo, brassMat);
  pullPost4.name = 'pullPost';
  pullPost4.position.set(0.045, 0, 0.013);
  pull2.add(pullPost4);
  const pullBar2 = new THREE.Mesh(cylinderGeo, brassMat);
  pullBar2.name = 'pullBar';
  pullBar2.position.set(0, 0, 0.026);
  pullBar2.rotation.set(0, 0, deg(90));
  pull2.add(pullBar2);
  const drawer3 = new THREE.Mesh(extrudeGeo, panelMat);
  drawer3.name = 'drawer';
  drawer3.position.set(0, 0.6075, 0.303);
  pedestalRight.add(drawer3);
  const pull3 = new THREE.Group();
  pull3.name = 'pull';
  pull3.position.set(0, 0.6333, 0.313);
  pedestalRight.add(pull3);
  const pullPost5 = new THREE.Mesh(boxGeo, brassMat);
  pullPost5.name = 'pullPost';
  pullPost5.position.set(-0.045, 0, 0.013);
  pull3.add(pullPost5);
  const pullPost6 = new THREE.Mesh(boxGeo, brassMat);
  pullPost6.name = 'pullPost';
  pullPost6.position.set(0.045, 0, 0.013);
  pull3.add(pullPost6);
  const pullBar3 = new THREE.Mesh(cylinderGeo, brassMat);
  pullBar3.name = 'pullBar';
  pullBar3.position.set(0, 0, 0.026);
  pullBar3.rotation.set(0, 0, deg(90));
  pull3.add(pullBar3);
  const leg = new THREE.Mesh(cylinderGeo2, woodMat);
  leg.name = 'leg';
  leg.position.set(-0.615, 0.3625, 0.265);
  leg.rotation.set(0, deg(45), 0);
  root.add(leg);
  const leg2 = new THREE.Mesh(cylinderGeo2, woodMat);
  leg2.name = 'leg';
  leg2.position.set(-0.615, 0.3625, -0.265);
  leg2.rotation.set(0, deg(45), 0);
  root.add(leg2);
  const stretcher = new THREE.Mesh(new THREE.BoxGeometry(0.024, 0.04, 0.53), woodMat);
  stretcher.name = 'stretcher';
  stretcher.position.set(-0.615, 0.14, 0);
  root.add(stretcher);
  const apronSide = new THREE.Mesh(new THREE.BoxGeometry(0.022, 0.09, 0.53), woodMat);
  apronSide.name = 'apronSide';
  apronSide.position.set(-0.615, 0.68, 0);
  root.add(apronSide);
  const frieze = new THREE.Mesh(new THREE.BoxGeometry(0.84, 0.1, 0.57), woodMat);
  frieze.name = 'frieze';
  frieze.position.set(-0.195, 0.675, -0.01);
  root.add(frieze);
  const centerDrawer = new THREE.Mesh(extrude([[0.294, 0.0268], [0.2893, 0.0315], [-0.2893, 0.0315], [-0.294, 0.0268], [-0.294, -0.0268], [-0.2893, -0.0315], [0.2893, -0.0315], [0.294, -0.0268]], 0.008, [], [0.006, 0.006, 1]), panelMat);
  centerDrawer.name = 'centerDrawer';
  centerDrawer.position.set(-0.195, 0.675, 0.283);
  root.add(centerDrawer);
  const knob = new THREE.Group();
  knob.name = 'knob';
  knob.position.set(-0.195, 0.675, 0.293);
  root.add(knob);
  const knobStem = new THREE.Mesh(new THREE.CylinderGeometry(0.0059, 0.0078, 0.0117, 6), brassMat);
  knobStem.name = 'knobStem';
  knobStem.position.set(0, 0, 0.0059);
  knobStem.rotation.set(deg(90), 0, 0);
  knob.add(knobStem);
  const knobHead = new THREE.Mesh(new THREE.SphereGeometry(0.013, 6, 4), brassMat);
  knobHead.name = 'knobHead';
  knobHead.position.set(0, 0, 0.0163);
  knobHead.scale.set(1, 1, 0.7);
  knob.add(knobHead);
  const modestyPanel = new THREE.Mesh(new THREE.BoxGeometry(0.84, 0.505, 0.02), darkMat);
  modestyPanel.name = 'modestyPanel';
  modestyPanel.position.set(-0.195, 0.3725, -0.265);
  root.add(modestyPanel);
  const paper = new THREE.Mesh(boxGeo2, paperMat);
  paper.name = 'paper';
  paper.position.set(-0.4142, 0.765, -0.0547);
  paper.rotation.set(0, deg(-9.7818), 0);
  root.add(paper);
  const paper2 = new THREE.Mesh(boxGeo2, paperMat);
  paper2.name = 'paper';
  paper2.position.set(-0.4062, 0.769, -0.0715);
  paper2.rotation.set(0, deg(-8.7095), 0);
  root.add(paper2);
  const paper3 = new THREE.Mesh(boxGeo2, paperMat);
  paper3.name = 'paper';
  paper3.position.set(-0.4131, 0.773, -0.0514);
  paper3.rotation.set(0, deg(-7.3073), 0);
  root.add(paper3);
  const paper4 = new THREE.Mesh(boxGeo2, paperMat);
  paper4.name = 'paper';
  paper4.position.set(-0.405, 0.777, -0.0666);
  paper4.rotation.set(0, deg(-13.1512), 0);
  root.add(paper4);
  const paper5 = new THREE.Mesh(boxGeo2, paperMat);
  paper5.name = 'paper';
  paper5.position.set(-0.3985, 0.781, -0.0672);
  paper5.rotation.set(0, deg(-10.135), 0);
  root.add(paper5);
  const book = new THREE.Group();
  book.name = 'book';
  book.position.set(0.425, 0.763, -0.17);
  book.rotation.set(0, deg(8), 0);
  root.add(book);
  const cover = new THREE.Mesh(new THREE.BoxGeometry(0.26, 0.05, 0.19), blueMat);
  cover.name = 'cover';
  cover.position.set(0, 0.025, 0);
  book.add(cover);
  const pages = new THREE.Mesh(new THREE.BoxGeometry(0.248, 0.038, 0.01), paperMat);
  pages.name = 'pages';
  pages.position.set(0, 0.025, 0.094);
  book.add(pages);
  const book2 = new THREE.Group();
  book2.name = 'book';
  book2.position.set(0.425, 0.813, -0.17);
  book2.rotation.set(0, deg(-3), 0);
  root.add(book2);
  const cover2 = new THREE.Mesh(new THREE.BoxGeometry(0.24, 0.045, 0.17), redMat);
  cover2.name = 'cover';
  cover2.position.set(0, 0.0225, 0);
  book2.add(cover2);
  const pages2 = new THREE.Mesh(new THREE.BoxGeometry(0.228, 0.033, 0.01), paperMat);
  pages2.name = 'pages';
  pages2.position.set(0, 0.0225, 0.084);
  book2.add(pages2);
  const book3 = new THREE.Group();
  book3.name = 'book';
  book3.position.set(0.425, 0.858, -0.17);
  book3.rotation.set(0, deg(-14), 0);
  root.add(book3);
  const cover3 = new THREE.Mesh(new THREE.BoxGeometry(0.22, 0.04, 0.16), leatherMat);
  cover3.name = 'cover';
  cover3.position.set(0, 0.02, 0);
  book3.add(cover3);
  const pages3 = new THREE.Mesh(new THREE.BoxGeometry(0.208, 0.028, 0.01), paperMat);
  pages3.name = 'pages';
  pages3.position.set(0, 0.02, 0.079);
  book3.add(pages3);
  const inkwell = new THREE.Mesh(new THREE.CylinderGeometry(0.03, 0.036, 0.045, 7), inkMat);
  inkwell.name = 'inkwell';
  inkwell.position.set(0.175, 0.7855, -0.2);
  root.add(inkwell);
  const inkCap = new THREE.Mesh(new THREE.CylinderGeometry(0.013, 0.016, 0.015, 7), brassMat);
  inkCap.name = 'inkCap';
  inkCap.position.set(0.175, 0.8155, -0.2);
  root.add(inkCap);
  const quill = new THREE.Group();
  quill.name = 'quill';
  quill.position.set(0.179, 0.793, -0.2);
  quill.rotation.set(deg(14), 0, deg(-22));
  root.add(quill);
  const quillShaft = new THREE.Mesh(new THREE.CylinderGeometry(0.003, 0.002, 0.26, 4), paperMat);
  quillShaft.name = 'quillShaft';
  quillShaft.position.set(0, 0.13, 0);
  quill.add(quillShaft);
  const quillVane = new THREE.Mesh(new THREE.OctahedronGeometry(1, 0), paperMat);
  quillVane.name = 'quillVane';
  quillVane.position.set(0, 0.19, 0);
  quillVane.scale.set(0.024, 0.1, 0.004);
  quill.add(quillVane);
  const letter = new THREE.Mesh(new THREE.BoxGeometry(0.21, 0.003, 0.28), paperMat);
  letter.name = 'letter';
  letter.position.set(0, 0.7635, 0.08);
  letter.rotation.set(0, deg(9), 0);
  root.add(letter);
  const pen = new THREE.Mesh(new THREE.CylinderGeometry(0.005, 0.005, 0.15, 5), inkMat);
  pen.name = 'pen';
  pen.position.set(0.17, 0.768, 0.12);
  pen.rotation.set(0, deg(35), deg(90));
  root.add(pen);

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

export default createDesk;

評価とコメント

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

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

0 件のコメント

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

関連モデル

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