🎮ArcadeLab

监控人1.0 - 3D模型

by TurboKoala83
175 lines5.4 KB🛠️ Three.js (3D graphics)
▶ Play
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>监控人1.0 - 3D模型</title>
  <style>
    body { margin: 0; overflow: hidden; background: #222; font-family: sans-serif; }
    #info {
      position: absolute; top: 10px; left: 10px; color: #fff;
      background: rgba(0,0,0,0.6); padding: 10px; border-radius: 8px;
      font-size: 13px; z-index: 10;
    }
    #btn {
      position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%);
      padding: 14px 28px; background: #4CAF50; color: #fff; border: none;
      border-radius: 30px; font-size: 16px; z-index: 10;
    }
    #btn:active { background: #388E3C; }
  </style>
</head>
<body>
<div id="info">🖱️ 拖动旋转 | 双指缩放<br>点击下方按钮导出 .obj</div>
<button id="btn">📦 导出 OBJ 模型</button>

<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/exporters/OBJExporter.js"></script>

<script>
// === 场景 ===
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x333333);

const camera = new THREE.PerspectiveCamera(45, innerWidth/innerHeight, 0.1, 100);
camera.position.set(1.5, 1.5, 2.5);

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(innerWidth, innerHeight);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);

const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.target.set(0, 1.2, 0);
controls.update();

// === 灯光 ===
scene.add(new THREE.AmbientLight(0xffffff, 0.6));
const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);
dirLight.position.set(3, 5, 3);
dirLight.castShadow = true;
scene.add(dirLight);
const fillLight = new THREE.DirectionalLight(0x88aaff, 0.3);
fillLight.position.set(-3, 2, -2);
scene.add(fillLight);

// === 材质 ===
const matBlack = new THREE.MeshStandardMaterial({ color: 0x1a1a1a, roughness: 0.8 });
const matWhite = new THREE.MeshStandardMaterial({ color: 0xe8e8e8, roughness: 0.5 });
const matDarkGrey = new THREE.MeshStandardMaterial({ color: 0x333333, roughness: 0.6 });
const matLens = new THREE.MeshStandardMaterial({ 
  color: 0x111111, roughness: 0.1, metalness: 0.9,
  emissive: 0x2244ff, emissiveIntensity: 0.3
});
const matShirt = new THREE.MeshStandardMaterial({ color: 0xf0f0f0, roughness: 0.7 });

// === 角色群组 ===
const cameraman = new THREE.Group();

// 身体(西装)
const body = new THREE.Mesh(new THREE.BoxGeometry(0.36, 0.7, 0.2), matBlack);
body.position.set(0, 0.9, 0);
body.castShadow = true;
cameraman.add(body);

// 双腿
const legGeo = new THREE.CylinderGeometry(0.06, 0.055, 0.55, 8);
const legL = new THREE.Mesh(legGeo, matBlack);
legL.position.set(-0.1, 0.28, 0);
legL.castShadow = true;
cameraman.add(legL);

const legR = new THREE.Mesh(legGeo, matBlack);
legR.position.set(0.1, 0.28, 0);
legR.castShadow = true;
cameraman.add(legR);

// 双臂
const armGeo = new THREE.CylinderGeometry(0.05, 0.045, 0.55, 8);
const armL = new THREE.Mesh(armGeo, matBlack);
armL.position.set(-0.26, 0.95, 0);
armL.rotation.z = 0.15;
armL.castShadow = true;
cameraman.add(armL);

const armR = new THREE.Mesh(armGeo, matBlack);
armR.position.set(0.26, 0.95, 0);
armR.rotation.z = -0.15;
armR.castShadow = true;
cameraman.add(armR);

// 头部(监控摄像头主体)
const head = new THREE.Mesh(new THREE.BoxGeometry(0.22, 0.18, 0.35), matWhite);
head.position.set(0, 1.55, 0);
head.castShadow = true;
cameraman.add(head);

// 镜头
const lens = new THREE.Mesh(new THREE.CylinderGeometry(0.055, 0.055, 0.04, 16), matLens);
lens.position.set(0, 1.55, 0.19);
lens.rotation.x = Math.PI / 2;
cameraman.add(lens);

// 镜头外圈
const lensRing = new THREE.Mesh(new THREE.TorusGeometry(0.06, 0.012, 8, 16), matDarkGrey);
lensRing.position.set(0, 1.55, 0.19);
cameraman.add(lensRing);

// 头部支架
const bracket = new THREE.Mesh(new THREE.BoxGeometry(0.08, 0.08, 0.12), matDarkGrey);
bracket.position.set(0, 1.43, -0.05);
cameraman.add(bracket);

// 领口
const collar = new THREE.Mesh(new THREE.BoxGeometry(0.28, 0.05, 0.02), matShirt);
collar.position.set(0, 1.26, 0.1);
cameraman.add(collar);

// 领带
const tie = new THREE.Mesh(new THREE.BoxGeometry(0.04, 0.2, 0.012), matBlack);
tie.position.set(0, 1.13, 0.105);
cameraman.add(tie);

// 地面
const ground = new THREE.Mesh(
  new THREE.CircleGeometry(2, 32),
  new THREE.MeshStandardMaterial({ color: 0x444444, roughness: 1 })
);
ground.rotation.x = -Math.PI / 2;
ground.position.y = 0;
ground.receiveShadow = true;
scene.add(ground);

scene.add(cameraman);

// === 导出 OBJ ===
document.getElementById('btn').addEventListener('click', () => {
  const exporter = new THREE.OBJExporter();
  const result = exporter.parse(cameraman);
  const blob = new Blob([result], { type: 'text/plain' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = 'cameraman_1.0.obj';
  a.click();
  URL.revokeObjectURL(url);
});

// === 渲染循环 ===
function animate() {
  requestAnimationFrame(animate);
  controls.update();
  renderer.render(scene, camera);
}
animate();

// === 窗口适配 ===
addEventListener('resize', () => {
  camera.aspect = innerWidth / innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(innerWidth, innerHeight);
});
</script>
</body>
</html>

Game Source: 监控人1.0 - 3D模型

Creator: TurboKoala83

Libraries: three

Complexity: moderate (175 lines, 5.4 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: 1-0-3d-turbokoala83" to link back to the original. Then publish at arcadelab.ai/publish.