index.js 11 KB

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