|
@@ -0,0 +1,286 @@
|
|
|
+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 }
|
|
|
+ // }
|
|
|
+}
|