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.hasVideoTexture = true 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, 0, -0.5) let houseVideo = document.getElementById("houseTexture") 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) if(self.hasVideoTexture) m.material = shaderMaterial } }); self.charactorManager = new CharactorManager(self) await self.charactorManager.readPointData() setTimeout(() => { window.connection.socket.emit("getRotateVideoUrl", { videoPath: "0/0", sceneCode: settings.sceneCode, roomId: settings.roomId, userId: settings.userId, }); window.connection.socket.emit("getRotateVideoUrl", { videoPath: "0/0_rotate" , sceneCode: settings.sceneCode, roomId: settings.roomId, userId: settings.userId, }); self.charactorManager.importCharactorModel("../scenes/charactors/", "man_YXL.glb") }, 1500) }); 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() { let walkPointsTemp = [] // 获得旋转视频 window.connection.socket.on('getRotateVideoUrl', async(data) => { console.log("[3D] getRotateVideoUrl: ", data) const url = data let video = data.indexOf("_rotate") > -1 ? document.getElementById("houseTextureReverse") : document.getElementById("houseTexture") video.src = url // 页面刷新后初次加载视频 if(this.initVideo) { // this.updateHouseVideo(video, true) this.initVideo = false this.cameraController.camera.minZ = 0.001 } }) // 获得行走视频 window.connection.socket.on('getVideoUrl', async(data) => { console.log("[3D] getVideoUrl: ", data) const urlArr = data let path = walkPointsTemp.map((point, i) => { return { id: point.id, point: new BABYLON.Vector3(-point.location.x, 0, point.location.z), video: urlArr[i] ? common.createVideoElement0(urlArr[i]) : null, } }) // 行走时锁定camera console.log("Walk Start: ", path) this.cameraController.lockCamera(true) this.charactorManager.charactor.startWalk(path, this.charactorManager) }) // 获得行走路径 window.connection.socket.on("getRoute", (data) => { console.log("[3D] getRoute", data); if(!data || data.length < 2) return walkPointsTemp = data let dir = this.charactorManager.getVideoDirecNum() let videoNames = [] for(let i = 0; i < data.length-1; i++) { videoNames.push(data[i].id + "/" + data[i].id + "_" + data[i+1].id + "_" + dir) } this.getSocketVideoType = "walkPath" let sendData = { videoList: videoNames, sceneCode: settings.sceneCode, roomId: settings.roomId, userId: settings.userId, } console.log("[3D] send(getVideoUrl): ", sendData); connection.socket.emit("getVideoUrl", sendData); }); } updateHouseVideo(video, notPlay) { let videoTexture = new BABYLON.VideoTexture("", video, this.scene) this.hasVideoTexture && 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.hasVideoTexture && this.house.forEach(mesh => { mesh.material && mesh.material.setTexture("texture_video", videoTexture) }) !notPlay && video.play() } }