Codels
988 üçgen0,42 × 0,23 × 0,07 m
Bağımsız bir ES modülü — yalnızca three paketine bağımlıdır. Fabrika fonksiyonunu çağırıp dönen grubu sahnene ekle.
/**
 * Blaster Pistol — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 988 · Size (W × H × D): 0.42 × 0.23 × 0.07 m
 *
 * Usage:
 *   import { createBlasterPistol } from './blaster-pistol.js';
 *   
 *   const model = createBlasterPistol();
 *   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 createBlasterPistol() {
  const root = new THREE.Group();
  root.name = 'BlasterPistol';

  // Materials
  const bodyMat = new THREE.MeshStandardMaterial({ name: 'body', color: 0xeceae4, roughness: 0.45, flatShading: true });
  const accentMat = new THREE.MeshStandardMaterial({ name: 'accent', color: 0xff7a3c, roughness: 0.45, flatShading: true });
  const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x2d333d, roughness: 0.7, flatShading: true });
  const metalMat = new THREE.MeshStandardMaterial({ name: 'metal', color: 0x9aa4b0, roughness: 0.35, metalness: 0.7, flatShading: true });
  const glowMat = new THREE.MeshStandardMaterial({ name: 'glow', color: 0x3fe6ff, roughness: 0.3, emissive: 0x3fe6ff, emissiveIntensity: 1.1, flatShading: true });

  // Shared geometries
  const extrudeGeo = extrude([[-0.108, 0.012], [-0.068, 0.012], [-0.047, 0.088], [-0.098, 0.088]], 0.004);
  const extrudeGeo2 = extrude([[-0.12, 0.135], [0.09, 0.135], [0.095, 0.155], [-0.115, 0.155]], 0.004);
  const boxGeo = new THREE.BoxGeometry(0.05, 0.014, 0.004);
  const torusGeo = new THREE.TorusGeometry(0.026, 0.007, 5, 12);
  const cylinderGeo = new THREE.CylinderGeometry(0.02, 0.02, 0.01, 8);

  // Parts
  const body = new THREE.Mesh(extrude([[-0.12, 0], [-0.06, 0], [-0.035, 0.1], [0.06, 0.1], [0.1, 0.112], [0.11, 0.135], [0.105, 0.17], [0.02, 0.18], [-0.09, 0.18], [-0.135, 0.165], [-0.14, 0.125], [-0.105, 0.1]], 0.036, [], [0.009, 0.008, 2]), bodyMat);
  body.name = 'body';
  body.position.set(0, 0.009, 0);
  root.add(body);
  const gripPanelR = new THREE.Mesh(extrudeGeo, darkMat);
  gripPanelR.name = 'gripPanelR';
  gripPanelR.position.set(0, 0.009, 0.028);
  root.add(gripPanelR);
  const stripeR = new THREE.Mesh(extrudeGeo2, accentMat);
  stripeR.name = 'stripeR';
  stripeR.position.set(0, 0.009, 0.028);
  root.add(stripeR);
  const cellR = new THREE.Mesh(boxGeo, glowMat);
  cellR.name = 'cellR';
  cellR.position.set(-0.035, 0.131, 0.028);
  root.add(cellR);
  const gripPanelL = new THREE.Mesh(extrudeGeo, darkMat);
  gripPanelL.name = 'gripPanelL';
  gripPanelL.position.set(0, 0.009, -0.028);
  root.add(gripPanelL);
  const stripeL = new THREE.Mesh(extrudeGeo2, accentMat);
  stripeL.name = 'stripeL';
  stripeL.position.set(0, 0.009, -0.028);
  root.add(stripeL);
  const cellL = new THREE.Mesh(boxGeo, glowMat);
  cellL.name = 'cellL';
  cellL.position.set(-0.035, 0.131, -0.028);
  root.add(cellL);
  const barrel = new THREE.Mesh(new THREE.CylinderGeometry(0.024, 0.024, 0.13, 10), metalMat);
  barrel.name = 'barrel';
  barrel.position.set(0.165, 0.157, 0);
  barrel.rotation.set(0, 0, deg(-90));
  root.add(barrel);
  const coil1 = new THREE.Mesh(torusGeo, glowMat);
  coil1.name = 'coil1';
  coil1.position.set(0.135, 0.157, 0);
  coil1.rotation.set(0, deg(90), 0);
  root.add(coil1);
  const coil2 = new THREE.Mesh(torusGeo, glowMat);
  coil2.name = 'coil2';
  coil2.position.set(0.165, 0.157, 0);
  coil2.rotation.set(0, deg(90), 0);
  root.add(coil2);
  const coil3 = new THREE.Mesh(torusGeo, glowMat);
  coil3.name = 'coil3';
  coil3.position.set(0.195, 0.157, 0);
  coil3.rotation.set(0, deg(90), 0);
  root.add(coil3);
  const muzzle = new THREE.Mesh(new THREE.CylinderGeometry(0.034, 0.03, 0.04, 10), accentMat);
  muzzle.name = 'muzzle';
  muzzle.position.set(0.245, 0.157, 0);
  muzzle.rotation.set(0, 0, deg(-90));
  root.add(muzzle);
  const muzzleGlow = new THREE.Mesh(new THREE.CylinderGeometry(0.017, 0.017, 0.01, 10), glowMat);
  muzzleGlow.name = 'muzzleGlow';
  muzzleGlow.position.set(0.263, 0.157, 0);
  muzzleGlow.rotation.set(0, 0, deg(-90));
  root.add(muzzleGlow);
  const fin = new THREE.Mesh(extrude([[-0.03, 0], [0.05, 0], [0.03, 0.035], [-0.01, 0.035]], 0.012, [], [0.003, 0.003, 1]), accentMat);
  fin.name = 'fin';
  fin.position.set(0, 0.194, 0);
  root.add(fin);
  const powerCell = new THREE.Mesh(new THREE.CapsuleGeometry(0.017, 0.05, 3, 8), glowMat);
  powerCell.name = 'powerCell';
  powerCell.position.set(-0.07, 0.213, 0);
  powerCell.rotation.set(0, 0, deg(90));
  root.add(powerCell);
  const cellCapF = new THREE.Mesh(cylinderGeo, metalMat);
  cellCapF.name = 'cellCapF';
  cellCapF.position.set(-0.035, 0.213, 0);
  cellCapF.rotation.set(0, 0, deg(90));
  root.add(cellCapF);
  const cellCapB = new THREE.Mesh(cylinderGeo, metalMat);
  cellCapB.name = 'cellCapB';
  cellCapB.position.set(-0.105, 0.213, 0);
  cellCapB.rotation.set(0, 0, deg(90));
  root.add(cellCapB);
  const triggerGuard = new THREE.Mesh(new THREE.TorusGeometry(0.032, 0.006, 4, 10, Math.PI), darkMat);
  triggerGuard.name = 'triggerGuard';
  triggerGuard.position.set(0, 0.109, 0);
  triggerGuard.rotation.set(0, 0, deg(180));
  root.add(triggerGuard);
  const trigger = new THREE.Mesh(new THREE.BoxGeometry(0.01, 0.028, 0.012), accentMat);
  trigger.name = 'trigger';
  trigger.position.set(0, 0.097, 0);
  trigger.rotation.set(0, 0, deg(-12));
  root.add(trigger);

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

export default createBlasterPistol;

Puanlar ve yorumlar

—
Henüz puan yok — ilk puanı sen ver.
5
0
4
0
3
0
2
0
1
0

Puan vermek ve yorum yapmak için giriş yap.

0 yorum

Henüz yorum yok. Bu modeli nasıl kullandığını ya da neyin daha iyi olabileceğini paylaş.

Benzer modeller

Aynı kategori ya da benzer etiketler