import CharactorManager from "./CharactorManager.js"; import common from "./utils/common.js"; import houseShader from "./shaders/houseShader.js"; import settings from "./utils/settings.js"; import CameraController from "./CameraController.js"; export default class App { constructor(engine) { var scene = new BABYLON.Scene(engine); this.scene = scene scene.collisionsEnabled = true; // Lights var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, -1, 0), scene); light.intensity = 1.0; light.specular = BABYLON.Color3.Black(); var light2 = new BABYLON.HemisphericLight("dir01", new BABYLON.Vector3(0, 1, 0), scene); light2.intensity = 0.1; light2.position = new BABYLON.Vector3(0, 5, 5); // Skybox var skybox = BABYLON.MeshBuilder.CreateBox("skyBox", { size: 1000.0 }, scene); var skyboxMaterial = new BABYLON.StandardMaterial("skyBox", scene); skyboxMaterial.backFaceCulling = false; skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("textures/environment.env", scene); skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE; skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0); skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0); skybox.material = skyboxMaterial; this.init() this.bindEvents() setTimeout(() => this.bindSocketEvents(), 1000) } init() { this.initVideo = true this.isReverse = false let self = this BABYLON.SceneLoader.ImportMesh("", "../scenes/house/", "close_to_bottom_L.glb", this.scene, async function (newMeshes, particleSystems, skeletons, animationGroups) { self.house = newMeshes // self.house[0].position = new BABYLON.Vector3(0.6, 2.1, 1.5) // self.house[0].position = new BABYLON.Vector3(-22, 0, 12) let houseVideo = document.getElementById("houseTexture0") setTimeout(() => { window.connection.socket.emit("getRotateVideo", { videoPath: "0/0", sangle: 0, eangle: 360, reverses: false, sceneCode: settings.sceneCode, roomId: settings.roomId, userId: settings.userId, }); window.connection.socket.emit("getRotateVideo", { videoPath: "0/0" , sangle: 0, eangle: 360, reverses: true, sceneCode: settings.sceneCode, roomId: settings.roomId, userId: settings.userId, }); }, 1500) newMeshes.forEach(m => { // m.scaling.scaleInPlace(100); m._geometry && (m.checkCollisions = true) if(m.material) { BABYLON.Effect.ShadersStore['aFragmentShader'] = houseShader.fragment; BABYLON.Effect.ShadersStore['aVertexShader'] = houseShader.vertex; let shaderMaterial = new BABYLON.ShaderMaterial("shader", self.scene, { vertex: "a", fragment: "a", }, { attributes: houseShader.attributes, uniforms: houseShader.uniforms, defines: houseShader.defines }); let videoTexture = new BABYLON.VideoTexture("", houseVideo, self.scene) // document.getElementById("houseTexture0").play() // document.getElementById("houseTexture0").loop = "loop" shaderMaterial.setTexture("texture_video", videoTexture) shaderMaterial.setVector3("focal_width_height", new BABYLON.Vector3( 864 * window.innerWidth / settings.video.width, // 1500 settings.video.width * window.innerHeight / settings.video.height, window.innerHeight // 864 * window.innerHeight / settings.video.width, // 1500 // settings.video.width * window.innerWidth / settings.video.height, // window.innerWidth )) shaderMaterial.setFloat("isYUV", 0) m.material = shaderMaterial } }); self.charactorManager = new CharactorManager(self) await self.charactorManager.readPointData() self.charactorManager.importCharactorModel("../scenes/charactors/", "man_YXL.glb") }); this.cameraController = new CameraController(self) } bindEvents() { this.scene.onPointerObservable.add((pointerInfo) => { switch (pointerInfo.type) { case BABYLON.PointerEventTypes.POINTERDOWN: this.cameraController.startMouseRotate(pointerInfo) break; case BABYLON.PointerEventTypes.POINTERUP: this.cameraController.endMouseRotate() break; case BABYLON.PointerEventTypes.POINTERMOVE: if(this.cameraController.lastFramePoint) this.cameraController.mouseRotating(pointerInfo) break; case BABYLON.PointerEventTypes.POINTERWHEEL: break; case BABYLON.PointerEventTypes.POINTERPICK: break; case BABYLON.PointerEventTypes.POINTERTAP: if(pointerInfo.pickInfo.hit && this.house.indexOf(pointerInfo.pickInfo.pickedMesh)) { this.charactorManager.clickHouse() } break; case BABYLON.PointerEventTypes.POINTERDOUBLETAP: break; } }); this.scene.onBeforeAnimationsObservable.add(() => { if(this.charactorManager && this.charactorManager.charactor) this.charactorManager.onBeforeAnimation() }) this.scene.onBeforeRenderObservable.add(() => { this.cameraController.updateCameraPos() }) } bindSocketEvents() { // 获得旋转视频 window.connection.socket.on('getSocketVideo', async(data) => { console.log("[3D] getSocketVideo: ", data) const blob = new Blob([data], { type: 'application/video' }) const url = URL.createObjectURL(blob) // this.updateHouseVideoBlob(url, true) // let video = common.createVideoElement0(url) // video.loop = "loop" setTimeout(function () { return URL.revokeObjectURL(url) }, 3000) if(this.getWalkVideo) { let path = this.currentPoints.map( (point, index) => { return { point: new BABYLON.Vector3(point.location.x, 0, point.location.z), video: common.createVideoElement0(url) } }) // 行走时锁定camera this.cameraController.lockCamera(true) this.charactorManager.charactor.startWalk(path, this.charactorManager) this.getWalkVideo = false } else { // this.cameraController.rotateCamera(this.cameraController.alphaOffset) if(this.isReverse) { document.getElementById("houseTextureReverse").src = url } else { document.getElementById("houseTexture").src = url } this.isReverse = !this.isReverse if(this.initVideo) { this.updateHouseVideoBlob(url, true) this.initVideo = false } } }) // 获得行走视频 window.connection.socket.on('getVideo', async (data) => { console.log("[3D] getVideo: ", data) const blob = new Blob([data], { type: 'application/video' }) const url = URL.createObjectURL(blob) setTimeout(function () { URL.revokeObjectURL(url) }, 3000) // let path = this.currentPoints.map( (point, index) => { // return { // point: new BABYLON.Vector3(point.location.x, 0, point.location.z), // video: url // await common.createVideoElement0(url) // } // }) // // 行走时锁定camera // this.cameraController.lockCamera(true) // this.charactorManager.charactor.startWalk(path, this.charactorManager) }) // 获得行走路径 window.connection.socket.on("getRoute", (data) => { console.log("[3D] getRoute", data); if(data.length < 2) return data = data.reverse() this.currentPoints = data let dir = this.charactorManager.getVideoDirecNum() let videos = [] for(let i = 0; i < data.length - 1; i++) { videos.push(data[i].id + "/" + data[i].id + "_" + data[i+1].id + "_" + dir) } this.getWalkVideo = true connection.socket.emit("getVideo", { videoList: videos, sceneCode: settings.sceneCode, roomId: settings.roomId, userId: settings.userId, }); }); } updateHouseVideo(video, notPlay) { let videoTexture = new BABYLON.VideoTexture("", video, this.scene) this.house.forEach(mesh => { mesh.material && mesh.material.setTexture("texture_video", videoTexture) }) !notPlay && video.play() } async updateHouseVideoBlob(blobUrl, notPlay) { let video = await common.createVideoElement(blobUrl) // video.loop = "loop" let videoTexture = new BABYLON.VideoTexture("", video, this.scene) this.house.forEach(mesh => { mesh.material && mesh.material.setTexture("texture_video", videoTexture) }) !notPlay && video.play() return video } }