index.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. import CharactorManager from "./CharactorManager.js";
  2. import common from "./utils/common.js";
  3. import houseShader from "./shaders/houseShader.js";
  4. import settings from "./utils/settings.js";
  5. export default class App {
  6. constructor(engine) {
  7. var scene = new BABYLON.Scene(engine);
  8. this.scene = scene
  9. scene.collisionsEnabled = true;
  10. var camera1 = new BABYLON.ArcRotateCamera("camera1", 0, Math.PI / 2, 10, new BABYLON.Vector3(0, 0, 0), scene);
  11. scene.activeCamera = camera1;
  12. scene.activeCamera.attachControl(scene.canvas, true);
  13. camera1.inertia = 0
  14. camera1.minZ = 0
  15. camera1.fov = settings.camera.fov
  16. camera1.fovMode = BABYLON.ArcRotateCamera.FOVMODE_HORIZONTAL_FIXED
  17. camera1.lowerBetaLimit = Math.PI / 2
  18. camera1.upperBetaLimit = Math.PI / 2
  19. camera1.lowerRadiusLimit = settings.camera.distanceFromCharactor;
  20. camera1.upperRadiusLimit = settings.camera.distanceFromCharactor;
  21. camera1.angularSensibilityX /= 2;
  22. this.camera = camera1
  23. this.lastCameraAlpha = 0
  24. // camera1.checkCollisions = true;
  25. // camera1.collisionRadius = new BABYLON.Vector3(0.1, 0.1, 0.1)
  26. // let self = this
  27. // var ray = new BABYLON.Ray(new BABYLON.Vector3(0,0,0), new BABYLON.Vector3(0,0,1), 50);
  28. // BABYLON.RayHelper.CreateAndShow(ray, scene, new BABYLON.Color3(1, 0.1, 0.1));
  29. // camera1.onCollide = function(mesh) {
  30. // let targetPos = camera1.position.clone()
  31. // targetPos.y = 1
  32. // ray.origin = self.charactorManager.charactor.mesh.position
  33. // ray.direction = BABYLON.Vector3.Normalize( targetPos.subtract(ray.origin) )
  34. // var info = ray.intersectsMesh(mesh);
  35. // if(!info.distance) return
  36. // camera1.lowerRadiusLimit = Math.max(info.distance - 0.5, 0.2)
  37. // camera1.upperRadiusLimit = Math.max(info.distance - 0.5, 0.2)
  38. // console.error(info.distance)
  39. // }
  40. // console.error(camera1)
  41. // 人物相机射线
  42. this.ray = new BABYLON.Ray(new BABYLON.Vector3(0,0,0), new BABYLON.Vector3(0,0,1), 50);
  43. BABYLON.RayHelper.CreateAndShow(this.ray, scene, new BABYLON.Color3(1, 0.1, 0.1));
  44. // Lights
  45. var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, -1, 0), scene);
  46. light.intensity = 1.0;
  47. light.specular = BABYLON.Color3.Black();
  48. var light2 = new BABYLON.HemisphericLight("dir01", new BABYLON.Vector3(0, 1, 0), scene);
  49. light2.intensity = 0.1;
  50. light2.position = new BABYLON.Vector3(0, 5, 5);
  51. // Skybox
  52. var skybox = BABYLON.MeshBuilder.CreateBox("skyBox", { size: 1000.0 }, scene);
  53. var skyboxMaterial = new BABYLON.StandardMaterial("skyBox", scene);
  54. skyboxMaterial.backFaceCulling = false;
  55. skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("textures/environment.env", scene);
  56. skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
  57. skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
  58. skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
  59. skybox.material = skyboxMaterial;
  60. this.init()
  61. this.bindEvents()
  62. }
  63. init() {
  64. let self = this
  65. BABYLON.SceneLoader.ImportMesh("", "../scenes/house/", "000.glb", this.scene, function (newMeshes, particleSystems, skeletons, animationGroups) {
  66. self.house = newMeshes
  67. self.house[0].position = new BABYLON.Vector3(0.6, 2.1, 1.5)
  68. // self.house[0].position = new BABYLON.Vector3(-22, 0, 12)
  69. newMeshes.forEach(m => {
  70. // m.scaling.scaleInPlace(100);
  71. m._geometry && (m.checkCollisions = true)
  72. if(m.material)
  73. {
  74. BABYLON.Effect.ShadersStore['aFragmentShader'] = houseShader.fragment;
  75. BABYLON.Effect.ShadersStore['aVertexShader'] = houseShader.vertex;
  76. let shaderMaterial = new BABYLON.ShaderMaterial("shader", scene, { vertex: "a", fragment: "a", }, {
  77. attributes: houseShader.attributes,
  78. uniforms: houseShader.uniforms,
  79. defines: houseShader.defines
  80. });
  81. let videoTexture = new BABYLON.VideoTexture("", document.getElementById("houseTexture0"), scene)
  82. // document.getElementById("houseTexture0").play()
  83. // document.getElementById("houseTexture0").loop = "loop"
  84. shaderMaterial.setTexture("texture_video", videoTexture)
  85. // shaderMaterial.setVector3("focal_width_height", new BABYLON.Vector3(735, settings.video.width, settings.video.height)) // 1100 470 860
  86. shaderMaterial.setVector3("focal_width_height", new BABYLON.Vector3(
  87. 735 * window.innerHeight / settings.video.height,
  88. settings.video.width * window.innerHeight / settings.video.height,
  89. window.innerHeight
  90. ))
  91. shaderMaterial.setFloat("isYUV", 0)
  92. m.material = shaderMaterial
  93. }
  94. });
  95. self.charactorManager = new CharactorManager(self)
  96. self.charactorManager.importCharactorModel("../scenes/charactors/", "man_YXL.glb")
  97. });
  98. }
  99. bindEvents() {
  100. this.scene.onPointerObservable.add((pointerInfo) => {
  101. switch (pointerInfo.type) {
  102. case BABYLON.PointerEventTypes.POINTERDOWN:
  103. this.pointDown = true
  104. break;
  105. case BABYLON.PointerEventTypes.POINTERUP:
  106. this.pointDown = false
  107. break;
  108. case BABYLON.PointerEventTypes.POINTERMOVE:
  109. if(this.pointDown) this.rotateCamera()
  110. break;
  111. case BABYLON.PointerEventTypes.POINTERWHEEL:
  112. break;
  113. case BABYLON.PointerEventTypes.POINTERPICK:
  114. break;
  115. case BABYLON.PointerEventTypes.POINTERTAP:
  116. if(pointerInfo.pickInfo.hit && this.house.indexOf(pointerInfo.pickInfo.pickedMesh)) {
  117. this.charactorManager.clickHouse()
  118. }
  119. break;
  120. case BABYLON.PointerEventTypes.POINTERDOUBLETAP:
  121. break;
  122. }
  123. });
  124. this.scene.onBeforeAnimationsObservable.add(() => {
  125. if(this.charactorManager && this.charactorManager.charactor)
  126. this.charactorManager.onBeforeAnimation()
  127. })
  128. this.scene.onBeforeRenderObservable.add(() => {
  129. this.updateCameraPos()
  130. })
  131. }
  132. updateCameraPos() {
  133. if(!this.charactorManager || !this.charactorManager.charactor) return
  134. // 实时更新相机target
  135. let cameraTarget = this.charactorManager.charactor.mesh.position.clone()
  136. cameraTarget.y = settings.camera.height
  137. this.camera.setTarget(cameraTarget)
  138. // 相机碰撞检测
  139. this.ray.origin = cameraTarget
  140. this.ray.direction = BABYLON.Vector3.Normalize( this.camera.position.clone().subtract(cameraTarget) )
  141. let info = this.ray.intersectsMeshes(this.house)[0];
  142. const offset = 0.6
  143. if(!info || info.distance > settings.camera.distanceFromCharactor + offset) return
  144. let charactorVisi = this.charactorManager.charactor.visible
  145. this.camera.lowerRadiusLimit = Math.max( info.distance - offset, 0.1 )
  146. this.camera.upperRadiusLimit = Math.max( info.distance - offset, 0.1 )
  147. // console.error(info.pickedPoint, this.camera.position)
  148. // 根据相机位置更新人物显隐
  149. if(info.distance - offset < 0.25 && charactorVisi) this.charactorManager.charactor.visible = false
  150. if(info.distance - offset >= 0.25 && !charactorVisi) this.charactorManager.charactor.visible = true
  151. // let r = this.cameraCollision()
  152. // this.camera.lowerRadiusLimit = Math.max( r, 0.1 )
  153. // this.camera.upperRadiusLimit = Math.max( r, 0.1 )
  154. }
  155. rotateCamera() {
  156. if(!this.charactorManager || !this.charactorManager.charactor) return
  157. let charactor = this.charactorManager.charactor
  158. if(charactor.actionType.split("-")[1] == "Walking") {
  159. // 行走时旋转相机,行走停止
  160. charactor.startWalk([], this.charactorManager)
  161. }
  162. // 根据单个点位视频的总帧数,计算每一帧的度数,只在度数至少到达一帧时,才去请求视频
  163. else if(Math.abs(this.camera.alpha - this.lastCameraAlpha) >= Math.PI * 2 / settings.rotateVideoFrame)
  164. {
  165. this.lockCamera(true)
  166. let currentPath = charactor.walkData.pathArr[charactor.walkData.currentPoint]
  167. let startPoint = (currentPath && currentPath.point) || charactor.mesh.position
  168. let sendData = {
  169. type: "RotateCamera",
  170. point: { x: startPoint.x, y: startPoint.z },
  171. dirc: {
  172. from: this.lastCameraAlpha % (Math.PI * 2),
  173. to: this.camera.alpha % (Math.PI * 2)
  174. }
  175. }
  176. window.connection.socket.emit("RotateCamera", sendData)
  177. // setTimeout(() => {
  178. // // this.lastCameraAlpha = this.camera.alpha
  179. // this.lockCamera(false)
  180. // }, 10)
  181. // todo 发送数据
  182. // common.postData("", sendData).then(response => {
  183. // this.updateHouseVideo(response[0].video)
  184. // // this.lastCameraAlpha = this.camera.alpha
  185. // this.lockCamera(false)
  186. // })
  187. this.lastCameraAlpha = this.camera.alpha
  188. }
  189. }
  190. lockCamera(isTrue) {
  191. this.camera.lowerAlphaLimit = isTrue ? this.camera.alpha : null
  192. this.camera.upperAlphaLimit = isTrue ? this.camera.alpha : null
  193. }
  194. updateHouseVideo(video) {
  195. let videoTexture = new BABYLON.VideoTexture("", video, this.scene)
  196. this.house.forEach(mesh => {
  197. mesh.material && mesh.material.setTexture("texture_video", videoTexture)
  198. })
  199. video.play()
  200. }
  201. // cameraCollision() {
  202. // // if(this.cameraAngle) {
  203. // // let {info, point, normal} = this.getRayInfoOnCircle(this.cameraAngle)
  204. // // if(
  205. // // Math.abs(info.distance - point.clone().subtract(this.ray.origin).length()) < 1 &&
  206. // // this.ray.origin.clone().subtract(info.pickedPoint).addInPlace(normal).length() <= 3.5
  207. // // ) {
  208. // // return this.ray.origin.clone().subtract(info.pickedPoint).addInPlace(normal).length()
  209. // // }
  210. // // else {
  211. // // this.cameraAngle = null
  212. // // return 3.5
  213. // // }
  214. // // }
  215. // for(let i = 0; i < Math.PI * 2; i += Math.PI / 8) {
  216. // let {info, point, normal} = this.getRayInfoOnCircle(i)
  217. // if(
  218. // Math.abs(info.distance - point.clone().subtract(this.ray.origin).length()) < 0.5 &&
  219. // (this.ray.origin.clone().subtract(info.pickedPoint).addInPlace(normal).length() - 3.5) < 0.5
  220. // ) {
  221. // // this.cameraAngle = i
  222. // return this.ray.origin.clone().subtract(info.pickedPoint).addInPlace(normal).length()
  223. // }
  224. // }
  225. // // this.cameraAngle = null
  226. // return 3.5
  227. // }
  228. // getRayInfoOnCircle(angle) {
  229. // let normal = new BABYLON.Vector3(0, 0, 0.5)
  230. // normal.rotateByQuaternionToRef(BABYLON.Quaternion.RotationAxis(new BABYLON.Vector3(0, 1, 0), angle), normal)
  231. // let point = this.camera.position.clone().addInPlace(normal) // 圆上的点坐标
  232. // let direction = BABYLON.Vector3.Normalize( point.clone().subtract(this.ray.origin) )
  233. // var ray = new BABYLON.Ray(this.ray.origin, direction, 50);
  234. // let info = ray.intersectsMeshes(this.house)[0];
  235. // return { info: info, point: point, normal: normal }
  236. // }
  237. }