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) { this.engine = 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) // document.getElementById("enterBtn").onclick = () => { // document.getElementById("houseTexture").play(); // document.getElementById("houseTextureReverse").play(); // document.getElementById("mask").style.zIndex = "-10000" // } } init() { // document.getElementById("houseTexture").onplay = () => { // console.error("video play!") // } // window.ty =()=>{ // document.getElementById("houseTexture").play(); // } 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() { // let ray = new BABYLON.Ray(new BABYLON.Vector3(0,0,0), new BABYLON.Vector3(0,0,1), 50); // document.getElementById("renderCanvas").addEventListener("click", (pointerInfo) => { // if(this.mouseMoving) return // // console.error("click") // let pickPoint = this.screenToWorld({x: pointerInfo.x, y: pointerInfo.y}) // ray.origin = pickPoint // ray.direction = BABYLON.Vector3.Normalize( this.cameraController.camera.position.clone().subtract(pickPoint) ) // let pickInfo = ray.intersectsMeshes(this.house)[0]; // if(pickInfo.hit && this.house.indexOf(pickInfo.pickedMesh)) { // this.charactorManager.clickHouse() // } // }) // document.getElementById("renderCanvas").addEventListener("pointerdown", (pointerInfo) => { // console.error("down") // this.cameraController.startMouseRotate({event: pointerInfo}) // this.mouseMoving = false // }) // document.getElementById("renderCanvas").addEventListener("pointerup", (pointerInfo) => { // this.cameraController.endMouseRotate() // // console.error("up") // }) // document.getElementById("renderCanvas").addEventListener("pointermove", (pointerInfo) => { // if(this.cameraController.lastFramePoint) { // // console.error("move") // this.cameraController.mouseRotating({event: pointerInfo}) // this.mouseMoving = true // } // }) 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() } screenToWorld(point) { let camera = this.cameraController.camera const viewport = camera.viewport.toGlobal(this.engine.getRenderWidth(), this.engine.getRenderHeight()); return BABYLON.Vector3.Unproject(new BABYLON.Vector3(point.x, point.y, 0), viewport.width, viewport.height, BABYLON.Matrix.Identity(), camera.getViewMatrix(), camera.getProjectionMatrix()); } worldToSceen(point) { let camera = this.cameraController.camera const viewPort = camera.viewport.toGlobal(this.engine.getRenderWidth(), this.engine.getRenderHeight()); return BABYLON.Vector3.Project(point, BABYLON.Matrix.Identity(), this.scene.getTransformMatrix(), viewPort); } }