3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Babylon.jsAdvent Calendar 2024

Day 12

今Babylon.jsを知った私がChatGPT先生となにかを作ってみる

Posted at

はじめに

この記事はBabylon.js Advent Calendar 2024の12日目の記事です。

Babylon.jsを今知ったところですが、
とても便利そうなので、ChatGPT先生と一緒に試してみます。

Babylon.jsを知っているかChatGPT先生に聞いてみる。

スクリーンショット 2024-12-20 0.17.04.png

早速プログラムを作ってもらう

スクリーンショット 2024-12-20 0.18.25.png

スクリーンショット 2024-12-20 0.20.20.png

スクリーンショット 2024-12-20 0.21.02.png

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Flower Petal Dance</title>
    <script src="https://cdn.babylonjs.com/babylon.js"></script>
</head>
<body>
<canvas id="renderCanvas" touch-action="none"></canvas>
<input type="file" id="fileInput" accept="audio/*" style="position: absolute; top: 10px; left: 10px; z-index: 1000;">
<script>
    const canvas = document.getElementById("renderCanvas");
    const engine = new BABYLON.Engine(canvas, true);
    const scene = new BABYLON.Scene(engine);
    const camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 2, Math.PI / 4, 20, BABYLON.Vector3.Zero(), scene);
    camera.attachControl(canvas, true);
    const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);

    // 花びらの形状
    const flowerPetal = BABYLON.MeshBuilder.CreateDisc("petal", { radius: 0.5, tessellation: 64 }, scene);
    flowerPetal.rotation.x = Math.PI / 2;

    // マテリアル
    const petalMaterial = new BABYLON.StandardMaterial("petalMaterial", scene);
    petalMaterial.diffuseColor = new BABYLON.Color3(1, 0.5, 0.5);
    flowerPetal.material = petalMaterial;

    // 花びらを大量に生成
    const petals = [];
    for (let i = 0; i < 100; i++) {
        const petalInstance = flowerPetal.clone("petal" + i);
        petalInstance.position = new BABYLON.Vector3(
            Math.random() * 20 - 10,
            Math.random() * 10,
            Math.random() * 20 - 10
        );
        petals.push(petalInstance);
    }

    // 音楽の再生設定
    const fileInput = document.getElementById("fileInput");
    let audioContext = null;
    let analyser = null;
    let frequencyData = null;

    fileInput.addEventListener("change", (event) => {
        const file = event.target.files[0];
        if (file) {
            const audioElement = new Audio(URL.createObjectURL(file));
            audioElement.crossOrigin = "anonymous"; // クロスオリジンの制限を回避
            audioElement.play();

            if (!audioContext) {
                audioContext = new (window.AudioContext || window.webkitAudioContext)();
                analyser = audioContext.createAnalyser();
                analyser.fftSize = 256;
                frequencyData = new Uint8Array(analyser.frequencyBinCount);
            }

            const source = audioContext.createMediaElementSource(audioElement);
            source.connect(analyser);
            analyser.connect(audioContext.destination);
        }
    });

    // アニメーション
    scene.registerBeforeRender(() => {
        if (analyser && frequencyData) {
            analyser.getByteFrequencyData(frequencyData);
            const beatStrength = frequencyData[0] / 255; // 周波数データを正規化

            petals.forEach(petal => {
                petal.position.y += Math.sin(scene.getEngine().getDeltaTime() * 0.001 + Math.random()) * beatStrength;
                petal.rotation.y += beatStrength * 0.1;
            });
        }
    });

    engine.runRenderLoop(() => {
        scene.render();
    });

    window.addEventListener("resize", () => {
        engine.resize();
    });
</script>
</body>
</html>

スクリーンショット 2024-12-20 0.24.04.png
スクリーンショット 2024-12-20 0.25.09.png

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Flower Petal Dance</title>
    <script src="https://cdn.babylonjs.com/babylon.js"></script>
</head>
<body>
<canvas id="renderCanvas" touch-action="none"></canvas>
<input type="file" id="fileInput" accept="audio/*" style="position: absolute; top: 10px; left: 10px; z-index: 1000;">
<script>
    const canvas = document.getElementById("renderCanvas");
    const engine = new BABYLON.Engine(canvas, true);
    const scene = new BABYLON.Scene(engine);
    const camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 2, Math.PI / 4, 20, BABYLON.Vector3.Zero(), scene);
    camera.attachControl(canvas, true);
    const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);

    // 花びらの形状
    const flowerPetal = BABYLON.MeshBuilder.CreateDisc("petal", { radius: 0.5, tessellation: 64 }, scene);
    flowerPetal.rotation.x = Math.PI / 2;

    // マテリアル
    const petalMaterial = new BABYLON.StandardMaterial("petalMaterial", scene);
    flowerPetal.material = petalMaterial;

    // 花びらを大量に生成
    const petals = [];
    for (let i = 0; i < 100; i++) {
        const petalInstance = flowerPetal.clone("petal" + i);
        petalInstance.position = new BABYLON.Vector3(
            Math.random() * 20 - 10,
            Math.random() * 10,
            Math.random() * 20 - 10
        );
        petals.push(petalInstance);
    }

    // 音楽の再生設定
    const fileInput = document.getElementById("fileInput");
    let audioContext = null;
    let analyser = null;
    let frequencyData = null;
    let isPlaying = false;

    fileInput.addEventListener("change", (event) => {
        const file = event.target.files[0];
        if (file) {
            const audioElement = new Audio(URL.createObjectURL(file));
            audioElement.crossOrigin = "anonymous"; // クロスオリジンの制限を回避
            audioElement.play();
            isPlaying = true;

            if (!audioContext) {
                audioContext = new (window.AudioContext || window.webkitAudioContext)();
                analyser = audioContext.createAnalyser();
                analyser.fftSize = 256;
                frequencyData = new Uint8Array(analyser.frequencyBinCount);
            }

            const source = audioContext.createMediaElementSource(audioElement);
            source.connect(analyser);
            analyser.connect(audioContext.destination);

            // 再生終了時にアニメーション停止
            audioElement.addEventListener("ended", () => {
                isPlaying = false;
            });
        }
    });

    // アニメーション
    scene.registerBeforeRender(() => {
        if (isPlaying && analyser && frequencyData) {
            analyser.getByteFrequencyData(frequencyData);
            const beatStrength = frequencyData[0] / 255; // 周波数データを正規化

            petals.forEach(petal => {
                // 花びらの動き
                petal.position.y += Math.sin(scene.getEngine().getDeltaTime() * 0.001 + Math.random()) * beatStrength;
                if (petal.position.y > 10) petal.position.y = -10; // Y座標が上限を超えたらリセット
                petal.rotation.y += beatStrength * 0.1;

                // 色の変化
                const colorFactor = frequencyData[Math.floor(Math.random() * frequencyData.length)] / 255;
                petal.material.diffuseColor = new BABYLON.Color3(colorFactor, 1 - colorFactor, Math.random());
            });
        }
    });

    engine.runRenderLoop(() => {
        scene.render();
    });

    window.addEventListener("resize", () => {
        engine.resize();
    });
</script>
</body>
</html>

スクリーンショット 2024-12-20 0.26.35.png

スクリーンショット 2024-12-20 0.27.10.png

スクリーンショット 2024-12-20 0.26.35.png

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Flower Petal Dance</title>
    <script src="https://cdn.babylonjs.com/babylon.js"></script>
</head>
<body>
<canvas id="renderCanvas" touch-action="none"></canvas>
<input type="file" id="fileInput" accept="audio/*" style="position: absolute; top: 10px; left: 10px; z-index: 1000;">
<script>
    const canvas = document.getElementById("renderCanvas");
    const engine = new BABYLON.Engine(canvas, true);
    const scene = new BABYLON.Scene(engine);
    const camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 2, Math.PI / 4, 20, BABYLON.Vector3.Zero(), scene);
    camera.attachControl(canvas, true);
    const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);

    // 花びらの形状
    const flowerPetal = BABYLON.MeshBuilder.CreateDisc("petal", { radius: 0.5, tessellation: 64 }, scene);
    flowerPetal.rotation.x = Math.PI / 2;

    // マテリアル
    const petalMaterial = new BABYLON.StandardMaterial("petalMaterial", scene);
    flowerPetal.material = petalMaterial;

    // 花びらを大量に生成
    const petals = [];
    for (let i = 0; i < 100; i++) {
        const petalInstance = flowerPetal.clone("petal" + i);
        petalInstance.position = new BABYLON.Vector3(
            Math.random() * 20 - 10,
            Math.random() * 10,
            Math.random() * 20 - 10
        );
        petalInstance.rotation = new BABYLON.Vector3(
            Math.random() * Math.PI,
            Math.random() * Math.PI,
            Math.random() * Math.PI
        );
        petalInstance.colorChangeFactor = Math.random(); // 色変化速度を個別に設定
        petals.push(petalInstance);
    }

    // 音楽の再生設定
    const fileInput = document.getElementById("fileInput");
    let audioContext = null;
    let analyser = null;
    let frequencyData = null;
    let isPlaying = false;

    fileInput.addEventListener("change", (event) => {
        const file = event.target.files[0];
        if (file) {
            const audioElement = new Audio(URL.createObjectURL(file));
            audioElement.crossOrigin = "anonymous"; // クロスオリジンの制限を回避
            audioElement.play();
            isPlaying = true;

            if (!audioContext) {
                audioContext = new (window.AudioContext || window.webkitAudioContext)();
                analyser = audioContext.createAnalyser();
                analyser.fftSize = 256;
                frequencyData = new Uint8Array(analyser.frequencyBinCount);
            }

            const source = audioContext.createMediaElementSource(audioElement);
            source.connect(analyser);
            analyser.connect(audioContext.destination);

            // 再生終了時にアニメーション停止
            audioElement.addEventListener("ended", () => {
                isPlaying = false;
            });
        }
    });

    // アニメーション
    let colorChangeSpeed = 0.01; // 色変化の速さを調整

    scene.registerBeforeRender(() => {
        if (isPlaying && analyser && frequencyData) {
            analyser.getByteFrequencyData(frequencyData);
            const beatStrength = frequencyData[0] / 255; // 周波数データを正規化

            petals.forEach(petal => {
                // 花びらのひらひら動き
                petal.position.y += Math.sin(scene.getEngine().getDeltaTime() * 0.001 + petal.position.x) * 0.05;
                petal.position.x += Math.cos(scene.getEngine().getDeltaTime() * 0.001 + petal.position.z) * 0.02;

                // Y軸を超えたらリセット
                if (petal.position.y > 10) petal.position.y = -10;

                // ゆっくりとした回転
                petal.rotation.x += 0.005;
                petal.rotation.z += 0.003;

                // 色の変化
                petal.colorChangeFactor += colorChangeSpeed * Math.random(); // 個別の色変化速度
                if (petal.colorChangeFactor > 1) petal.colorChangeFactor = 0;
                const colorFactor = petal.colorChangeFactor;
                petal.material.diffuseColor = new BABYLON.Color3(
                    Math.sin(colorFactor * Math.PI),
                    Math.sin((colorFactor + 0.33) * Math.PI),
                    Math.sin((colorFactor + 0.66) * Math.PI)
                );
            });
        }
    });

    engine.runRenderLoop(() => {
        scene.render();
    });

    window.addEventListener("resize", () => {
        engine.resize();
    });
</script>
</body>
</html>

スクリーンショット 2024-12-20 0.28.27.png

スクリーンショット 2024-12-20 0.28.50.png

スクリーンショット 2024-12-20 0.29.31.png

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Flower Petal Dance</title>
    <script src="https://cdn.babylonjs.com/babylon.js"></script>
    <style>
        body, html {
            margin: 0;
            padding: 0;
            overflow: hidden;
            width: 100%;
            height: 100%;
        }
        #renderCanvas {
            display: block;
            width: 100%;
            height: 100%;
        }
        #fileInput {
            position: absolute;
            top: 10px;
            left: 10px;
            z-index: 1000;
        }
    </style>
</head>
<body>
<canvas id="renderCanvas"></canvas>
<input type="file" id="fileInput" accept="audio/*">
<script>
    const canvas = document.getElementById("renderCanvas");
    const engine = new BABYLON.Engine(canvas, true);
    const scene = new BABYLON.Scene(engine);
    const camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 2, Math.PI / 4, 20, BABYLON.Vector3.Zero(), scene);
    camera.attachControl(canvas, true);
    const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);

    // 花びらの形状
    const flowerPetal = BABYLON.MeshBuilder.CreateDisc("petal", { radius: 0.5, tessellation: 64 }, scene);
    flowerPetal.rotation.x = Math.PI / 2;

    // マテリアル
    const petalMaterial = new BABYLON.StandardMaterial("petalMaterial", scene);
    flowerPetal.material = petalMaterial;

    // 花びらを大量に生成
    const petals = [];
    for (let i = 0; i < 100; i++) {
        const petalInstance = flowerPetal.clone("petal" + i);
        petalInstance.position = new BABYLON.Vector3(
            Math.random() * 20 - 10,
            Math.random() * 10,
            Math.random() * 20 - 10
        );
        petalInstance.rotation = new BABYLON.Vector3(
            Math.random() * Math.PI,
            Math.random() * Math.PI,
            Math.random() * Math.PI
        );
        petalInstance.colorChangeFactor = Math.random();
        petals.push(petalInstance);
    }

    // 音楽の再生設定
    const fileInput = document.getElementById("fileInput");
    let audioContext = null;
    let analyser = null;
    let frequencyData = null;
    let isPlaying = false;

    fileInput.addEventListener("change", (event) => {
        const file = event.target.files[0];
        if (file) {
            const audioElement = new Audio(URL.createObjectURL(file));
            audioElement.crossOrigin = "anonymous";
            audioElement.play();
            isPlaying = true;

            if (!audioContext) {
                audioContext = new (window.AudioContext || window.webkitAudioContext)();
                analyser = audioContext.createAnalyser();
                analyser.fftSize = 256;
                frequencyData = new Uint8Array(analyser.frequencyBinCount);
            }

            const source = audioContext.createMediaElementSource(audioElement);
            source.connect(analyser);
            analyser.connect(audioContext.destination);

            // 再生終了時にアニメーション停止
            audioElement.addEventListener("ended", () => {
                isPlaying = false;
            });
        }
    });

    // アニメーション
    let colorChangeSpeed = 0.01;

    scene.registerBeforeRender(() => {
        if (isPlaying && analyser && frequencyData) {
            analyser.getByteFrequencyData(frequencyData);
            const beatStrength = frequencyData[0] / 255;

            petals.forEach(petal => {
                petal.position.y += Math.sin(scene.getEngine().getDeltaTime() * 0.001 + petal.position.x) * 0.05;
                petal.position.x += Math.cos(scene.getEngine().getDeltaTime() * 0.001 + petal.position.z) * 0.02;
                if (petal.position.y > 10) petal.position.y = -10;

                petal.rotation.x += 0.005;
                petal.rotation.z += 0.003;

                petal.colorChangeFactor += colorChangeSpeed * Math.random();
                if (petal.colorChangeFactor > 1) petal.colorChangeFactor = 0;
                const colorFactor = petal.colorChangeFactor;
                petal.material.diffuseColor = new BABYLON.Color3(
                    Math.sin(colorFactor * Math.PI),
                    Math.sin((colorFactor + 0.33) * Math.PI),
                    Math.sin((colorFactor + 0.66) * Math.PI)
                );
            });
        }
    });

    engine.runRenderLoop(() => {
        scene.render();
    });

    window.addEventListener("resize", () => {
        engine.resize();
    });
</script>
</body>
</html>

スクリーンショット 2024-12-20 0.30.12.png

スクリーンショット 2024-12-20 0.31.39.png

スクリーンショット 2024-12-20 0.32.00.png

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Flower Petal Dance</title>
    <script src="https://cdn.babylonjs.com/babylon.js"></script>
    <style>
        body, html {
            margin: 0;
            padding: 0;
            overflow: hidden;
            width: 100%;
            height: 100%;
        }
        #renderCanvas {
            display: block;
            width: 100%;
            height: 100%;
        }
        #fileInput {
            position: absolute;
            top: 10px;
            left: 10px;
            z-index: 1000;
        }
    </style>
</head>
<body>
<canvas id="renderCanvas"></canvas>
<input type="file" id="fileInput" accept="audio/*">
<script>
    const canvas = document.getElementById("renderCanvas");
    const engine = new BABYLON.Engine(canvas, true);
    const scene = new BABYLON.Scene(engine);

    // 背景を白に設定
    scene.clearColor = new BABYLON.Color3(1, 1, 1);

    const camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 2, Math.PI / 4, 20, BABYLON.Vector3.Zero(), scene);
    camera.attachControl(canvas, true);
    const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);

    // 花びらの形状
    const flowerPetal = BABYLON.MeshBuilder.CreateDisc("petal", { radius: 0.5, tessellation: 64 }, scene);
    flowerPetal.rotation.x = Math.PI / 2;

    // マテリアル
    const petalMaterial = new BABYLON.StandardMaterial("petalMaterial", scene);
    flowerPetal.material = petalMaterial;

    // 花びらを大量に生成
    const petals = [];
    const totalPetals = 300; // 花びらの数を増加
    for (let i = 0; i < totalPetals; i++) {
        const petalInstance = flowerPetal.clone("petal" + i);
        petalInstance.position = new BABYLON.Vector3(
            Math.random() * 40 - 20,
            Math.random() * 20,
            Math.random() * 40 - 20
        );
        petalInstance.rotation = new BABYLON.Vector3(
            Math.random() * Math.PI,
            Math.random() * Math.PI,
            Math.random() * Math.PI
        );
        petalInstance.colorChangeFactor = Math.random();
        petals.push(petalInstance);
    }

    // 音楽の再生設定
    const fileInput = document.getElementById("fileInput");
    let audioContext = null;
    let analyser = null;
    let frequencyData = null;
    let isPlaying = false;

    fileInput.addEventListener("change", (event) => {
        const file = event.target.files[0];
        if (file) {
            const audioElement = new Audio(URL.createObjectURL(file));
            audioElement.crossOrigin = "anonymous";
            audioElement.play();
            isPlaying = true;

            if (!audioContext) {
                audioContext = new (window.AudioContext || window.webkitAudioContext)();
                analyser = audioContext.createAnalyser();
                analyser.fftSize = 256;
                frequencyData = new Uint8Array(analyser.frequencyBinCount);
            }

            const source = audioContext.createMediaElementSource(audioElement);
            source.connect(analyser);
            analyser.connect(audioContext.destination);

            // 再生終了時にアニメーション停止
            audioElement.addEventListener("ended", () => {
                isPlaying = false;
            });
        }
    });

    // アニメーション
    let colorChangeSpeed = 0.005; // 色変化をゆっくり

    scene.registerBeforeRender(() => {
        if (isPlaying && analyser && frequencyData) {
            analyser.getByteFrequencyData(frequencyData);
            const beatStrength = frequencyData[0] / 255;

            petals.forEach(petal => {
                // 花びらのひらひら動き
                petal.position.y += Math.sin(scene.getEngine().getDeltaTime() * 0.001 + petal.position.x) * 0.03;
                petal.position.x += Math.cos(scene.getEngine().getDeltaTime() * 0.001 + petal.position.z) * 0.02;
                if (petal.position.y > 20) petal.position.y = -5;

                petal.rotation.x += 0.002;
                petal.rotation.z += 0.001;

                petal.colorChangeFactor += colorChangeSpeed * Math.random();
                if (petal.colorChangeFactor > 1) petal.colorChangeFactor = 0;
                const colorFactor = petal.colorChangeFactor;
                petal.material.diffuseColor = new BABYLON.Color3(
                    Math.sin(colorFactor * Math.PI),
                    Math.sin((colorFactor + 0.33) * Math.PI),
                    Math.sin((colorFactor + 0.66) * Math.PI)
                );
            });
        }
    });

    engine.runRenderLoop(() => {
        scene.render();
    });

    window.addEventListener("resize", () => {
        engine.resize();
    });
</script>
</body>
</html>

スクリーンショット 2024-12-20 0.33.03.png

実行結果

音楽に合わせて?オブジェクトが舞うようになった!
マウス操作で、3D空間を移動、拡大縮小ができる。
とても便利なライブラリ!

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?