File size: 3,608 Bytes
a13f8e3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2c9e7c9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>モザイク画像の3D変換</title>
  <style>
    body { margin: 0; overflow: hidden; }
    canvas { display: block; }
    #upload { position: fixed; top: 10px; left: 10px; z-index: 10; }
  </style>
</head>
<body>
  <input type="file" id="upload" accept="image/*" />
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
  <script>
    // 基本的なThree.jsのセットアップ
    let scene, camera, renderer, controls;
    const cubes = [];
    const pixelSize = 5;  // ピクセル1つあたりの立方体サイズ

    function init() {
      scene = new THREE.Scene();
      camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
      camera.position.z = 300;

      renderer = new THREE.WebGLRenderer();
      renderer.setSize(window.innerWidth, window.innerHeight);
      document.body.appendChild(renderer.domElement);

      animate();
    }

    function animate() {
      requestAnimationFrame(animate);
      cubes.forEach(cube => {
        // 各立方体が中心に集まるように位置を調整
        cube.position.x += (0 - cube.position.x) * 0.02;
        cube.position.y += (0 - cube.position.y) * 0.02;
        cube.position.z += (0 - cube.position.z) * 0.02;
      });
      camera.rotation.y += 0.01;  // カメラの回転
      renderer.render(scene, camera);
    }

    // モザイク画像を生成する関数
    function createMosaicImage(image) {
      const canvas = document.createElement("canvas");
      const ctx = canvas.getContext("2d");
      const width = 50;  // モザイクの幅
      const height = 50; // モザイクの高さ
      canvas.width = width;
      canvas.height = height;

      // 画像を縮小してモザイク化
      ctx.drawImage(image, 0, 0, width, height);
      const imageData = ctx.getImageData(0, 0, width, height).data;

      // 各ピクセルから立方体を作成
      for (let y = 0; y < height; y++) {
        for (let x = 0; x < width; x++) {
          const i = (y * width + x) * 4;
          const r = imageData[i];
          const g = imageData[i + 1];
          const b = imageData[i + 2];
          const color = new THREE.Color(`rgb(${r},${g},${b})`);

          const geometry = new THREE.BoxGeometry(pixelSize, pixelSize, pixelSize);
          const material = new THREE.MeshBasicMaterial({ color });
          const cube = new THREE.Mesh(geometry, material);
          
          // 初期位置をランダムに設定
          cube.position.x = Math.random() * 600 - 300;
          cube.position.y = Math.random() * 600 - 300;
          cube.position.z = Math.random() * 600 - 300;

          // 各ピクセルの位置に立方体を配置
          const targetX = (x - width / 2) * pixelSize;
          const targetY = (y - height / 2) * pixelSize;
          cube.userData = { targetX, targetY, targetZ: 0 };

          cubes.push(cube);
          scene.add(cube);
        }
      }
    }

    // ファイル選択時のイベントリスナー
    document.getElementById("upload").addEventListener("change", (event) => {
      const file = event.target.files[0];
      const reader = new FileReader();
      reader.onload = (e) => {
        const image = new Image();
        image.onload = () => createMosaicImage(image);
        image.src = e.target.result;
      };
      reader.readAsDataURL(file);
    });

    // 初期化
    init();
  </script>
</body>
</html>