import CharactorManager from "./CharactorManager.js"; import common from "./common.js"; import houseShader from "./houseShader.js"; import settings from "./settings.js"; export default class App { constructor(engine) { var scene = new BABYLON.Scene(engine); this.scene = scene scene.collisionsEnabled = true; var camera1 = new BABYLON.ArcRotateCamera("camera1", 0, Math.PI / 2, 10, new BABYLON.Vector3(0, 0, 0), scene); scene.activeCamera = camera1; scene.activeCamera.attachControl(scene.canvas, true); camera1.inertia = 0 camera1.minZ = 0 camera1.fov = Math.PI / 2 camera1.fovMode = BABYLON.ArcRotateCamera.FOVMODE_HORIZONTAL_FIXED camera1.lowerBetaLimit = Math.PI / 2 camera1.upperBetaLimit = Math.PI / 2 camera1.lowerRadiusLimit = settings.camera.distanceFromCharactor; camera1.upperRadiusLimit = settings.camera.distanceFromCharactor; camera1.wheelDeltaPercentage = 0.01; camera1.angularSensibilityX /= 2; // camera1.targetScreenOffset = new BABYLON.Vector2(0, -1.65) this.camera = camera1 this.lastCameraAlpha = 0 // camera1.checkCollisions = true; // camera1.collisionRadius = new BABYLON.Vector3(0.1, 0.1, 0.1) // let self = this // var ray = new BABYLON.Ray(new BABYLON.Vector3(0,0,0), new BABYLON.Vector3(0,0,1), 50); // BABYLON.RayHelper.CreateAndShow(ray, scene, new BABYLON.Color3(1, 0.1, 0.1)); // camera1.onCollide = function(mesh) { // let targetPos = camera1.position.clone() // targetPos.y = 1 // ray.origin = self.charactorManager.charactor.mesh.position // ray.direction = BABYLON.Vector3.Normalize( targetPos.subtract(ray.origin) ) // var info = ray.intersectsMesh(mesh); // if(!info.distance) return // camera1.lowerRadiusLimit = Math.max(info.distance - 0.5, 0.2) // camera1.upperRadiusLimit = Math.max(info.distance - 0.5, 0.2) // console.error(info.distance) // } // console.error(camera1) var ray = new BABYLON.Ray(new BABYLON.Vector3(0,0,0), new BABYLON.Vector3(0,0,1), 50); BABYLON.RayHelper.CreateAndShow(ray, scene, new BABYLON.Color3(1, 0.1, 0.1)); this.ray = ray // 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() } init() { let self = this BABYLON.SceneLoader.ImportMesh("", "../scenes/house/", "000.glb", this.scene, function (newMeshes, particleSystems, skeletons, animationGroups) { self.house = newMeshes self.house[0].position = new BABYLON.Vector3(0.6, 2.1, 1.5) newMeshes.forEach(m => { // m.scaling.scaleInPlace(1.4); 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", scene, { vertex: "a", fragment: "a", }, { attributes: houseShader.attributes, uniforms: houseShader.uniforms, defines: houseShader.defines }); let videoTexture = new BABYLON.VideoTexture("", document.getElementById("houseTexture0"), scene) // document.getElementById("houseTexture0").play() // document.getElementById("houseTexture0").loop = "loop" shaderMaterial.setTexture("texture_video", videoTexture) shaderMaterial.setVector3("focal_width_height", new BABYLON.Vector3(735, settings.video.width, settings.video.height)) // 1100 470 860 shaderMaterial.setFloat("isYUV", 0) m.material = shaderMaterial } }); self.charactorManager = new CharactorManager(self) self.charactorManager.importCharactorModel("../scenes/charactors/", "man_YXL.glb") }); } bindEvents() { this.scene.onPointerObservable.add((pointerInfo) => { switch (pointerInfo.type) { case BABYLON.PointerEventTypes.POINTERDOWN: this.pointDown = true break; case BABYLON.PointerEventTypes.POINTERUP: this.pointDown = false break; case BABYLON.PointerEventTypes.POINTERMOVE: if(this.pointDown) this.rotateCamera() 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.updateCameraPos() }) } updateCameraPos() { if(!this.charactorManager || !this.charactorManager.charactor) return // 实时更新相机target let cameraTarget = this.charactorManager.charactor.mesh.position.clone() cameraTarget.y = 1.5 this.camera.target = cameraTarget // 相机碰撞检测 this.ray.origin = cameraTarget this.ray.direction = BABYLON.Vector3.Normalize( this.camera.position.clone().subtract(cameraTarget) ) let info = this.ray.intersectsMeshes(this.house)[0]; const offset = 0.5 if(info.distance > settings.camera.distanceFromCharactor + offset) return this.camera.lowerRadiusLimit = Math.max( info.distance - offset, 0.1 ) this.camera.upperRadiusLimit = Math.max( info.distance - offset, 0.1 ) // console.error(info.pickedPoint, this.camera.position) // let r = this.cameraCollision() // this.camera.lowerRadiusLimit = Math.max( r, 0.1 ) // this.camera.upperRadiusLimit = Math.max( r, 0.1 ) } rotateCamera() { if(!this.charactorManager || !this.charactorManager.charactor) return let charactor = this.charactorManager.charactor if(charactor.actionType.split("-")[1] == "Walking") { // 行走时旋转相机,行走停止 charactor.startWalk([], this.charactorManager) } // 根据单个点位视频的总帧数,计算每一帧的度数,只在度数至少到达一帧时,才去请求视频 else if(Math.abs(this.camera.alpha - this.lastCameraAlpha) >= Math.PI * 2 / settings.rotateVideoFrame) { this.lockCamera(true) let currentPath = charactor.walkData.pathArr[charactor.walkData.currentPoint] let startPoint = (currentPath && currentPath.point) || charactor.mesh.position let sendData = { type: "RotateCamera", point: { x: startPoint.x, y: startPoint.z }, dirc: { from: this.lastCameraAlpha % (Math.PI * 2), to: this.camera.alpha % (Math.PI * 2) } } setTimeout(() => { // this.lastCameraAlpha = this.camera.alpha this.lockCamera(false) }, 10) // todo 发送数据 // common.postData("", sendData).then(response => { // this.updateHouseVideo(response[0].video) // // this.lastCameraAlpha = this.camera.alpha // this.lockCamera(false) // }) this.lastCameraAlpha = this.camera.alpha } } lockCamera(isTrue) { this.camera.lowerAlphaLimit = isTrue ? this.camera.alpha : null this.camera.upperAlphaLimit = isTrue ? this.camera.alpha : null } updateHouseVideo(video) { let videoTexture = new BABYLON.VideoTexture("", video, this.scene) this.house.forEach(mesh => { mesh.material && mesh.material.setTexture("texture_video", videoTexture) }) video.play() } // cameraCollision() { // // if(this.cameraAngle) { // // let {info, point, normal} = this.getRayInfoOnCircle(this.cameraAngle) // // if( // // Math.abs(info.distance - point.clone().subtract(this.ray.origin).length()) < 1 && // // this.ray.origin.clone().subtract(info.pickedPoint).addInPlace(normal).length() <= 3.5 // // ) { // // return this.ray.origin.clone().subtract(info.pickedPoint).addInPlace(normal).length() // // } // // else { // // this.cameraAngle = null // // return 3.5 // // } // // } // for(let i = 0; i < Math.PI * 2; i += Math.PI / 8) { // let {info, point, normal} = this.getRayInfoOnCircle(i) // if( // Math.abs(info.distance - point.clone().subtract(this.ray.origin).length()) < 0.5 && // (this.ray.origin.clone().subtract(info.pickedPoint).addInPlace(normal).length() - 3.5) < 0.5 // ) { // // this.cameraAngle = i // return this.ray.origin.clone().subtract(info.pickedPoint).addInPlace(normal).length() // } // } // // this.cameraAngle = null // return 3.5 // } // getRayInfoOnCircle(angle) { // let normal = new BABYLON.Vector3(0, 0, 0.5) // normal.rotateByQuaternionToRef(BABYLON.Quaternion.RotationAxis(new BABYLON.Vector3(0, 1, 0), angle), normal) // let point = this.camera.position.clone().addInPlace(normal) // 圆上的点坐标 // let direction = BABYLON.Vector3.Normalize( point.clone().subtract(this.ray.origin) ) // var ray = new BABYLON.Ray(this.ray.origin, direction, 50); // let info = ray.intersectsMeshes(this.house)[0]; // return { info: info, point: point, normal: normal } // } }