Codels
삼각형 1.1천개14.7 × 7.29 × 15.7 m

코드에서 사용하기

에디터에서 리믹스
독립형 ES 모듈이에요 — three에만 의존해요. 팩토리 함수를 호출하고 그룹을 씬에 추가하세요.
/**
 * Asteroid Field — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the model (it floats — pickups, planets)
 * Triangles: 1,080 · Size (W × H × D): 14.71 × 7.29 × 15.74 m
 *
 * Usage:
 *   import { createAsteroidField } from './asteroid-field.js';
 *   
 *   const model = createAsteroidField();
 *   model.position.set(0, 0, 0);
 *   scene.add(model);
 */
import * as THREE from 'three';

const deg = THREE.MathUtils.degToRad;

// Deterministic vertex displacement (organic low-poly look).
function jitter(geometry, amount, seed) {
  const pos = geometry.attributes.position;
  const h = (a, b, c, s) => {
    let x = Math.imul(a, 73856093) ^ Math.imul(b, 19349663) ^ Math.imul(c, 83492791) ^ Math.imul(s, 2654435761);
    x = Math.imul(x ^ (x >>> 16), 2246822507);
    x = Math.imul(x ^ (x >>> 13), 3266489909);
    return ((x ^ (x >>> 16)) >>> 0) / 4294967295 - 0.5;
  };
  for (let i = 0; i < pos.count; i++) {
    const x = pos.getX(i), y = pos.getY(i), z = pos.getZ(i);
    const qx = Math.round(x * 1000), qy = Math.round(y * 1000), qz = Math.round(z * 1000);
    pos.setXYZ(i, x + h(qx, qy, qz, seed) * 2 * amount, y + h(qx, qy, qz, seed + 1) * 2 * amount, z + h(qx, qy, qz, seed + 2) * 2 * amount);
  }
  pos.needsUpdate = true;
  geometry.computeVertexNormals();
  return geometry;
}

export function createAsteroidField() {
  const root = new THREE.Group();
  root.name = 'AsteroidField';

  // Materials
  const aMat = new THREE.MeshStandardMaterial({ name: 'a', color: 0x5f564d, roughness: 0.92, flatShading: true });
  const bMat = new THREE.MeshStandardMaterial({ name: 'b', color: 0x4b453f, roughness: 0.95, flatShading: true });
  const cMat = new THREE.MeshStandardMaterial({ name: 'c', color: 0x706559, roughness: 0.92, flatShading: true });
  const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x3d3732, roughness: 0.95, flatShading: true });

  // Parts
  const field = new THREE.Group();
  field.name = 'field';
  root.add(field);
  const asteroid1 = new THREE.Group();
  asteroid1.name = 'asteroid1';
  asteroid1.position.set(0.0116, -0.4738, -2.6333);
  asteroid1.rotation.set(deg(145.1426), deg(216.9104), deg(116.4156));
  asteroid1.scale.setScalar(1.7982);
  field.add(asteroid1);
  const body = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(1, 1), 0.16, 91), bMat);
  body.name = 'body';
  body.scale.set(0.9728, 0.6241, 0.7184);
  asteroid1.add(body);
  const bulge1 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.3975, 0), 0.0596, 119), darkMat);
  bulge1.name = 'bulge1';
  bulge1.position.set(0.2495, -0.1583, -0.4477);
  bulge1.rotation.set(deg(72.3743), deg(77.9906), 0);
  asteroid1.add(bulge1);
  const bulge2 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.4193, 0), 0.0629, 120), bMat);
  bulge2.name = 'bulge2';
  bulge2.position.set(0.4146, 0.2435, 0.3086);
  bulge2.rotation.set(deg(56.7559), deg(81.3505), 0);
  asteroid1.add(bulge2);
  const asteroid2 = new THREE.Group();
  asteroid2.name = 'asteroid2';
  asteroid2.position.set(-0.6001, 1.8399, 1.4329);
  asteroid2.rotation.set(deg(174.1107), deg(272.4175), deg(166.6608));
  asteroid2.scale.setScalar(1.5744);
  field.add(asteroid2);
  const body2 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(1, 1), 0.16, 92), cMat);
  body2.name = 'body';
  body2.scale.set(1.1601, 0.7332, 0.7468);
  asteroid2.add(body2);
  const bulge12 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.3753, 0), 0.0563, 122), darkMat);
  bulge12.name = 'bulge1';
  bulge12.position.set(0.5703, 0.2225, -0.3209);
  bulge12.rotation.set(deg(5.1557), deg(16.994), 0);
  asteroid2.add(bulge12);
  const bulge22 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.4238, 0), 0.0636, 123), cMat);
  bulge22.name = 'bulge2';
  bulge22.position.set(0.1783, 0.3858, 0.3486);
  bulge22.rotation.set(deg(80.9849), deg(88.8971), 0);
  asteroid2.add(bulge22);
  const asteroid3 = new THREE.Group();
  asteroid3.name = 'asteroid3';
  asteroid3.position.set(-3.0423, -1.5014, 4.8374);
  asteroid3.rotation.set(deg(10.8577), deg(248.3237), deg(116.9973));
  asteroid3.scale.setScalar(1.4495);
  field.add(asteroid3);
  const body3 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(1, 1), 0.16, 93), aMat);
  body3.name = 'body';
  body3.scale.set(1.2353, 0.7346, 0.91);
  asteroid3.add(body3);
  const bulge13 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.4437, 0), 0.0666, 125), darkMat);
  bulge13.name = 'bulge1';
  bulge13.position.set(-0.5342, 0.4103, -0.1268);
  bulge13.rotation.set(deg(40.3818), deg(9.7662), 0);
  asteroid3.add(bulge13);
  const bulge23 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.416, 0), 0.0624, 126), aMat);
  bulge23.name = 'bulge2';
  bulge23.position.set(0.2724, -0.2392, 0.5488);
  bulge23.rotation.set(deg(76.2923), deg(9.2411), 0);
  asteroid3.add(bulge23);
  const asteroid4 = new THREE.Group();
  asteroid4.name = 'asteroid4';
  asteroid4.position.set(2.6248, -2.4443, -4.6295);
  asteroid4.rotation.set(deg(126.911), deg(286.966), deg(178.3325));
  asteroid4.scale.setScalar(1.2307);
  field.add(asteroid4);
  const body4 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(1, 1), 0.16, 94), bMat);
  body4.name = 'body';
  body4.scale.set(1.2521, 0.5914, 0.998);
  asteroid4.add(body4);
  const asteroid5 = new THREE.Group();
  asteroid5.name = 'asteroid5';
  asteroid5.position.set(-3.2591, 2.7709, 0.4343);
  asteroid5.rotation.set(deg(109.3185), deg(343.0207), deg(173.0595));
  asteroid5.scale.setScalar(0.9041);
  field.add(asteroid5);
  const body5 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(1, 1), 0.16, 95), cMat);
  body5.name = 'body';
  body5.scale.set(1.0031, 0.5874, 0.8754);
  asteroid5.add(body5);
  const asteroid6 = new THREE.Group();
  asteroid6.name = 'asteroid6';
  asteroid6.position.set(-3.1083, 1.2854, -5.6789);
  asteroid6.rotation.set(deg(12.9399), deg(274.3123), deg(168.7918));
  asteroid6.scale.setScalar(0.9526);
  field.add(asteroid6);
  const body6 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(1, 1), 0.16, 96), aMat);
  body6.name = 'body';
  body6.scale.set(1.1254, 0.6653, 0.7768);
  asteroid6.add(body6);
  const asteroid7 = new THREE.Group();
  asteroid7.name = 'asteroid7';
  asteroid7.position.set(1.0088, 0.947, -6.3657);
  asteroid7.rotation.set(deg(51.0326), deg(236.0673), deg(159.8164));
  asteroid7.scale.setScalar(0.8082);
  field.add(asteroid7);
  const body7 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(1, 1), 0.16, 97), bMat);
  body7.name = 'body';
  body7.scale.set(1.1772, 0.8463, 0.9262);
  asteroid7.add(body7);
  const asteroid8 = new THREE.Group();
  asteroid8.name = 'asteroid8';
  asteroid8.position.set(6.9121, -0.1321, -1.8939);
  asteroid8.rotation.set(deg(20.5544), deg(132.7213), deg(95.5927));
  asteroid8.scale.setScalar(0.5339);
  field.add(asteroid8);
  const body8 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(1, 1), 0.16, 98), cMat);
  body8.name = 'body';
  body8.scale.set(1.0391, 0.6947, 0.71);
  asteroid8.add(body8);
  const asteroid9 = new THREE.Group();
  asteroid9.name = 'asteroid9';
  asteroid9.position.set(-6.8684, 2.2237, -5.2057);
  asteroid9.rotation.set(deg(93.0306), deg(36.4539), deg(25.8796));
  asteroid9.scale.setScalar(0.4869);
  field.add(asteroid9);
  const body9 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(1, 0), 0.16, 99), aMat);
  body9.name = 'body';
  body9.scale.set(0.9292, 0.5878, 0.8381);
  asteroid9.add(body9);
  const asteroid10 = new THREE.Group();
  asteroid10.name = 'asteroid10';
  asteroid10.position.set(-5.6179, -1.5987, -4.318);
  asteroid10.rotation.set(deg(22.6544), deg(76.2792), deg(136.1208));
  asteroid10.scale.setScalar(0.3918);
  field.add(asteroid10);
  const body10 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(1, 0), 0.16, 100), bMat);
  body10.name = 'body';
  body10.scale.set(1.0192, 0.6217, 0.7342);
  asteroid10.add(body10);
  const asteroid11 = new THREE.Group();
  asteroid11.name = 'asteroid11';
  asteroid11.position.set(-7.0534, -1.7494, 3.6717);
  asteroid11.rotation.set(deg(4.1328), deg(9.4287), deg(47.3407));
  asteroid11.scale.setScalar(0.3927);
  field.add(asteroid11);
  const body11 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(1, 0), 0.16, 101), cMat);
  body11.name = 'body';
  body11.scale.set(1.2292, 0.6503, 0.8636);
  asteroid11.add(body11);
  const asteroid12 = new THREE.Group();
  asteroid12.name = 'asteroid12';
  asteroid12.position.set(3.6384, -2.9736, 6.7699);
  asteroid12.rotation.set(deg(77.0752), deg(121.3613), deg(110.6957));
  asteroid12.scale.setScalar(0.4039);
  field.add(asteroid12);
  const body12 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(1, 0), 0.16, 102), aMat);
  body12.name = 'body';
  body12.scale.set(1.2357, 0.6183, 0.761);
  asteroid12.add(body12);
  const gravel1 = new THREE.Mesh(jitter(new THREE.OctahedronGeometry(0.1532, 0), 0.0306, 287), aMat);
  gravel1.name = 'gravel1';
  gravel1.position.set(1.6952, -2.6248, -8.314);
  gravel1.rotation.set(deg(26.553), deg(12.8744), 0);
  field.add(gravel1);
  const gravel2 = new THREE.Mesh(jitter(new THREE.OctahedronGeometry(0.1642, 0), 0.0328, 288), darkMat);
  gravel2.name = 'gravel2';
  gravel2.position.set(4.3175, 2.2421, -0.1485);
  gravel2.rotation.set(deg(71.3263), deg(84.4855), 0);
  field.add(gravel2);
  const gravel3 = new THREE.Mesh(jitter(new THREE.OctahedronGeometry(0.1676, 0), 0.0335, 289), cMat);
  gravel3.name = 'gravel3';
  gravel3.position.set(-4.7698, -0.8502, -5.8089);
  gravel3.rotation.set(deg(6.3393), deg(75.6595), 0);
  field.add(gravel3);
  const gravel4 = new THREE.Mesh(jitter(new THREE.OctahedronGeometry(0.142, 0), 0.0284, 290), darkMat);
  gravel4.name = 'gravel4';
  gravel4.position.set(6.99, -1.0406, 0.962);
  gravel4.rotation.set(deg(53.5314), deg(60.3496), 0);
  field.add(gravel4);
  const gravel5 = new THREE.Mesh(jitter(new THREE.OctahedronGeometry(0.1191, 0), 0.0238, 291), bMat);
  gravel5.name = 'gravel5';
  gravel5.position.set(5.3283, 1.658, 2.6573);
  gravel5.rotation.set(deg(38.392), deg(76.3117), 0);
  field.add(gravel5);
  const gravel6 = new THREE.Mesh(jitter(new THREE.OctahedronGeometry(0.1105, 0), 0.0221, 292), darkMat);
  gravel6.name = 'gravel6';
  gravel6.position.set(0.9125, -2.7235, 6.4395);
  gravel6.rotation.set(deg(23.6519), deg(24.2344), 0);
  field.add(gravel6);
  const gravel7 = new THREE.Mesh(jitter(new THREE.OctahedronGeometry(0.1049, 0), 0.021, 293), aMat);
  gravel7.name = 'gravel7';
  gravel7.position.set(1.0978, -1.3455, -0.5791);
  gravel7.rotation.set(deg(82.3345), deg(19.7941), 0);
  field.add(gravel7);
  const gravel8 = new THREE.Mesh(jitter(new THREE.OctahedronGeometry(0.1302, 0), 0.026, 294), darkMat);
  gravel8.name = 'gravel8';
  gravel8.position.set(-4.2232, -1.505, -7.2816);
  gravel8.rotation.set(deg(67.6852), deg(0.7139), 0);
  field.add(gravel8);
  const gravel9 = new THREE.Mesh(jitter(new THREE.OctahedronGeometry(0.1202, 0), 0.024, 295), cMat);
  gravel9.name = 'gravel9';
  gravel9.position.set(3.0953, -1.4832, -2.4491);
  gravel9.rotation.set(deg(83.0631), deg(66.3593), 0);
  field.add(gravel9);
  const gravel10 = new THREE.Mesh(jitter(new THREE.OctahedronGeometry(0.1519, 0), 0.0304, 296), darkMat);
  gravel10.name = 'gravel10';
  gravel10.position.set(0.45, -1.9604, 6.5557);
  gravel10.rotation.set(deg(67.0739), deg(66.4162), 0);
  field.add(gravel10);

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

export default createAsteroidField;

평점 및 댓글

—
아직 평점이 없어요 — 첫 평점을 남겨 보세요.
5
0
4
0
3
0
2
0
1
0

평점과 댓글을 남기려면 로그인하세요.

댓글 0개

아직 댓글이 없어요. 이 모델을 어떻게 사용했는지, 어떤 점이 더 나아질 수 있을지 공유해 주세요.

관련 모델

같은 카테고리 또는 비슷한 태그