<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>video_resume_set_test</title> <link rel="stylesheet" href="../css/dot.css" type="text/css" /> </head> <body> <div id="WebGL-output"> <div class="point"></div> </div> <script type="module"> import * as THREE from "https://unpkg.com/three@0.126.1/build/three.module.js"; import { PointerLockControls } from "https://unpkg.com/three@0.126.1/examples/jsm/controls/PointerLockControls.js"; import { GLTFLoader } from "https://unpkg.com/three@0.126.1/examples/jsm/loaders/GLTFLoader.js"; import { FBXLoader } from "https://unpkg.com/three@0.126.1/examples/jsm/loaders/FBXLoader.js"; let camera; let scene; let renderer; let model; let moveForward = false; let moveBackward = false; let moveLeft = false; let moveRight = false; let moveUp = false; let moveDown = false; let controls; function init() { //シーンの作成 scene = new THREE.Scene(); scene.background = new THREE.Color(0x111111); // 背景色 //カメラの作成 camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); //カメラセット camera.position.set(0, 0, 0); // カメラの位置 camera.lookAt(new THREE.Vector3(0, 0, 0)); //ライトの作成 const light = new THREE.SpotLight(0xffffff, 1.0); light.position.set(100, 500, 500); scene.add(light); light.castShadow = true; // 補助線 // const axesHelper = new THREE.AxesHelper(500); // scene.add(axesHelper); // const gridHelper = new THREE.GridHelper(15, 15); // scene.add(gridHelper); // カメラコントロールの作成 controls = new PointerLockControls(camera, document.body); document.addEventListener("click", function () { controls.lock(); }); // controls.addEventListener("lock", function () { }); // controls.addEventListener("unlock", function () { }); // キーボードのキーを押したの際の処理 document.addEventListener("keydown", function (event) { switch (event.key) { case "w": case "ArrowUp": moveForward = true; break; case "s": case "ArrowDown": moveBackward = true; break; case "a": case "ArrowLeft": moveLeft = true; break; case "d": case "ArrowRight": moveRight = true; break; case "e": moveUp = true; break; case "q": moveDown = true; break; } }); // キーボードのキーを離した際の処理 document.addEventListener("keyup", function (event) { switch (event.key) { case "w": case "ArrowUp": moveForward = false; break; case "s": case "ArrowDown": moveBackward = false; break; case "a": case "ArrowLeft": moveLeft = false; break; case "d": case "ArrowRight": moveRight = false; break; case "e": moveUp = false; break; case "q": moveDown = false; break; } }); // レンダラーの作成 renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true, }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.physicallyCorrectLight = true; // const mouse = new THREE.Vector2(); let resumePageCounter = {}; // Class 資料のページ数を記録する let videoPlayPauseFlag = {} // Videoの再生停止状況を監視する // load videoAndResume.csv fetch("../csv/videoAndResume.csv") .then((response) => { return response.text(); }) .then((data) => { let result = data.split(/\r?\n|\r/).map((e) => { return e.split(","); }); console.log(result); console.log(result[1].length); //オブジェクトの作成(初期化) for (let makeNumber = 1; makeNumber < result.length; makeNumber++) { // for (let makeNumber = 1; makeNumber < result.length; makeNumber++) { let videoMesh = makeVideo(makeNumber, result[makeNumber][0], result[makeNumber][1]) let resumeMesh = makeResume(result[makeNumber][7], makeNumber) makeGroup(makeNumber, videoMesh, resumeMesh, result[makeNumber][2], result[makeNumber][3],result[makeNumber][4], result[makeNumber][5], result[makeNumber][6]); } console.log(resumePageCounter); // raycaster document.addEventListener("click", (event) => { event.preventDefault(); const raycaster = new THREE.Raycaster(); const mouse = new THREE.Vector2(); mouse.x = 0; mouse.y = 0; raycaster.setFromCamera(mouse, camera); const intersects = raycaster.intersectObjects(scene.children, true); if (intersects.length > 0) { console.log(intersects[0].object); //resumeのページ切替 for (let number = 1; number < result.length; number++) { if (intersects[0].object.name == result[number][7]) { //result[1][0]はmakeNumberと同じ数字になる(result"[1]"[0]の"[1]"の部分は後で変数にする) resumePageCounter[number] += 1; //resumePageCounter = {makeNumber: pageNumber} const resumeMesh = makeResume(result[number][resumePageCounter[number] + 7], number); intersects[0].object.parent.add(resumeMesh); // console.log(resumePageCounter); } if (resumePageCounter[number] == result[1].length - 8) { resumePageCounter[number] = -1; // console.log(resumePageCounter); } } // const planeGeometry = new THREE.PlaneGeometry(16.25, 10); // const planeMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 }); // const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial); // planeMesh.position.set(0, 0, -0.001); // scene.add(planeMesh); //video for (let number = 1; number <= Object.keys(videoPlayPauseFlag).length; number++) { if (intersects[0].object.name == number) { // console.log(intersects[0].object.children); let audio = intersects[0].object.children; let videoTagId = document.getElementById(`${number}`); // console.log(document.getElementById(number)); startStopVideoAndAudio(number, videoTagId, audio); } } } }) }) .catch((error) => { console.log(error); }); function makeGroup(makeNumber, videoMesh, resumeMesh, rotationX, rotationY, x, y, z) { resumePageCounter[makeNumber] = 0 videoPlayPauseFlag[makeNumber] = false // videoMeshとresumeMeshのgroup化 const group = new THREE.Group(); group.add(videoMesh); group.add(resumeMesh); group.rotation.x = THREE.MathUtils.degToRad(rotationX) group.rotation.y = THREE.MathUtils.degToRad(rotationY); group.position.set(x, y, z); group.name = `group${makeNumber}` scene.add(group); console.log(group); //objectのサイズとその中心位置を調べる // const box3 = new THREE.Box3().setFromObject(group); // const objectSize = new THREE.Vector3(); // box3.getSize(objectSize); // console.log(objectSize); // box3.getCenter(objectSize); // console.log(objectSize); } function makeVideo(objName, videoPath, audioPath) { // 動画オブジェクトの作成 const video = document.createElement("video"); // videoタグの作成 document.body.appendChild(video); // videoタグをbodyタグに追加(DOM) video.style.display = "none"; // videoがweb画面に表示させないようにする video.src = videoPath; video.autoplay = false; // 検索エンジンの規約に違反するため自動再生しないようにする video.preload = "auto"; video.loop = true; video.muted = true; // 検索エンジンの規約に違反するため動画は動画、音は音で作成する必要があるためミュートにする video.id = objName; //idを一意に決定する const videoTexture = new THREE.VideoTexture(video); videoTexture.minFilter = THREE.LinearFilter; videoTexture.magFilter = THREE.LinearFilter; videoTexture.wrapS = THREE.ClampToEdgeWrapping; videoTexture.wrapT = THREE.ClampToEdgeWrapping; const videoGeometry = new THREE.PlaneGeometry(3, 2); const videoMaterial = new THREE.MeshBasicMaterial({ map: videoTexture, color: 0xffffff }); const videoMesh = new THREE.Mesh(videoGeometry, videoMaterial); videoMesh.position.set(-0.875, 0, 0); videoMesh.name = objName; scene.add(videoMesh); // console.log(videoMesh); // console.log(videoMesh.geometry.parameters.width); //objectの幅 const audioListener = new THREE.AudioListener(); camera.add(audioListener); const audioLoader = new THREE.AudioLoader(); const positionalAudio = new THREE.PositionalAudio(audioListener); audioLoader.load(audioPath, function (buffer) { positionalAudio.setBuffer(buffer); positionalAudio.setRefDistance(100); positionalAudio.pause(); // 自動再生しないように停止しておく positionalAudio.name = objName; // nameを一意に決定する }); videoMesh.add(positionalAudio); return videoMesh } function makeResume(texturePath, makeNumber) { // 資料オブジェクトの作成 const resumeGeometry = new THREE.BoxGeometry(1.5, 1.5 * Math.sqrt(2), 0.01); const loadPhoto = new THREE.TextureLoader().load(texturePath); let resumeMaterial = new THREE.MeshBasicMaterial({ map: loadPhoto }); const resumeMesh = new THREE.Mesh(resumeGeometry, resumeMaterial); resumeMesh.castShadow = true; resumeMesh.position.set(1.625, 0, 0); resumeMesh.name = texturePath; scene.add(resumeMesh); // console.log(resumeMesh.geometry.parameters.width); //objectの幅 return resumeMesh; } // let flag = false; function startStopVideoAndAudio(flagNumber, videoTagId, audio) { // trueなら停止 falseなら再生 if (videoPlayPauseFlag[flagNumber] == false) { videoTagId.play(); audio[0].play(); videoPlayPauseFlag[flagNumber] = true; } else { videoTagId.pause(); audio[0].pause(); videoPlayPauseFlag[flagNumber] = false; } } //Box Helper function boxHelper(object) { let box = new THREE.BoxHelper(object, 0xffff00); scene.add(box); } // boxHelper(resumeMesh); // boxHelper(videoMesh); // boxHelper(group); const planeGeometry = new THREE.PlaneGeometry(20, 20); const flooringTexture = new THREE.TextureLoader().load("../texture_photo/flooring.jpg") flooringTexture.wrapS = THREE.RepeatWrapping; flooringTexture.wrapT = THREE.RepeatWrapping; flooringTexture.repeat.set(15, 15); const planeMaterial = new THREE.MeshBasicMaterial({ map: flooringTexture }); const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial); planeMesh.rotation.x = THREE.MathUtils.degToRad(-90); planeMesh.position.set(0, -1.5, 0); scene.add(planeMesh); // 画面の大きさが変更されたときに動的に修正 function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } window.addEventListener("resize", onWindowResize); document .getElementById("WebGL-output") .appendChild(renderer.domElement); } function animate() { requestAnimationFrame(animate); updateCameraPosition(); renderer.render(scene, camera); } function updateCameraPosition() { const speed = 0.1; // 移動速度 //.moveForward(Number) で前、.moveRightで右に if (moveForward) controls.moveForward(speed); if (moveBackward) controls.moveForward(-speed); if (moveRight) controls.moveRight(speed); if (moveLeft) controls.moveRight(-speed); //getObject()で直接カメラの操作 //controls.getObject()の時点でカメラのプロパティに切り替わる if (moveUp) controls.getObject().position.y += speed; if (moveDown) controls.getObject().position.y -= speed; } // 関数の実行 window.onload = function () { init(); animate(); } </script> </body> </html>