index.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  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. import CameraController from "./CameraController.js";
  6. export default class App {
  7. constructor(engine) {
  8. this.engine = engine
  9. var scene = new BABYLON.Scene(engine);
  10. this.scene = scene
  11. scene.collisionsEnabled = true;
  12. // Lights
  13. var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, -1, 0), scene);
  14. light.intensity = 1.0;
  15. light.specular = BABYLON.Color3.Black();
  16. var light2 = new BABYLON.HemisphericLight("dir01", new BABYLON.Vector3(0, 1, 0), scene);
  17. light2.intensity = 0.1;
  18. light2.position = new BABYLON.Vector3(0, 5, 5);
  19. // Skybox
  20. var skybox = BABYLON.MeshBuilder.CreateBox("skyBox", { size: 1000.0 }, scene);
  21. var skyboxMaterial = new BABYLON.StandardMaterial("skyBox", scene);
  22. skyboxMaterial.backFaceCulling = false;
  23. skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("textures/environment.env", scene);
  24. skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
  25. skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
  26. skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
  27. skybox.material = skyboxMaterial;
  28. this.hasVideoTexture = true
  29. this.init()
  30. this.bindEvents()
  31. setTimeout(() => this.bindSocketEvents(), 1000)
  32. // document.getElementById("enterBtn").onclick = () => {
  33. // document.getElementById("houseTexture").play();
  34. // document.getElementById("houseTextureReverse").play();
  35. // document.getElementById("mask").style.zIndex = "-10000"
  36. // }
  37. }
  38. init() {
  39. // document.getElementById("houseTexture").onplay = () => {
  40. // console.error("video play!")
  41. // }
  42. // window.ty =()=>{
  43. // document.getElementById("houseTexture").play();
  44. // }
  45. this.initVideo = true
  46. this.isReverse = false
  47. let self = this
  48. BABYLON.SceneLoader.ImportMesh("", "../scenes/house/", "close_to_bottom_L.glb", this.scene, async function (newMeshes, particleSystems, skeletons, animationGroups) {
  49. self.house = newMeshes
  50. // self.house[0].position = new BABYLON.Vector3(0, 0, -0.5)
  51. let houseVideo = document.getElementById("houseTexture")
  52. newMeshes.forEach(m => {
  53. // m.scaling.scaleInPlace(100);
  54. m._geometry && (m.checkCollisions = true)
  55. if(m.material)
  56. {
  57. BABYLON.Effect.ShadersStore['aFragmentShader'] = houseShader.fragment;
  58. BABYLON.Effect.ShadersStore['aVertexShader'] = houseShader.vertex;
  59. let shaderMaterial = new BABYLON.ShaderMaterial("shader", self.scene, { vertex: "a", fragment: "a", }, {
  60. attributes: houseShader.attributes,
  61. uniforms: houseShader.uniforms,
  62. defines: houseShader.defines
  63. });
  64. let videoTexture = new BABYLON.VideoTexture("", houseVideo, self.scene)
  65. // document.getElementById("houseTexture0").play()
  66. // document.getElementById("houseTexture0").loop = "loop"
  67. shaderMaterial.setTexture("texture_video", videoTexture)
  68. shaderMaterial.setVector3("focal_width_height", new BABYLON.Vector3(
  69. 864 * window.innerWidth / settings.video.width, // 1500
  70. settings.video.width * window.innerHeight / settings.video.height,
  71. window.innerHeight
  72. // 864 * window.innerHeight / settings.video.width, // 1500
  73. // settings.video.width * window.innerWidth / settings.video.height,
  74. // window.innerWidth
  75. ))
  76. shaderMaterial.setFloat("isYUV", 0)
  77. if(self.hasVideoTexture) m.material = shaderMaterial
  78. }
  79. });
  80. self.charactorManager = new CharactorManager(self)
  81. await self.charactorManager.readPointData()
  82. setTimeout(() => {
  83. window.connection.socket.emit("getRotateVideoUrl", {
  84. videoPath: "0/0",
  85. sceneCode: settings.sceneCode,
  86. roomId: settings.roomId,
  87. userId: settings.userId,
  88. });
  89. window.connection.socket.emit("getRotateVideoUrl", {
  90. videoPath: "0/0_rotate" ,
  91. sceneCode: settings.sceneCode,
  92. roomId: settings.roomId,
  93. userId: settings.userId,
  94. });
  95. self.charactorManager.importCharactorModel("../scenes/charactors/", "man_YXL.glb")
  96. }, 1500)
  97. });
  98. this.cameraController = new CameraController(self)
  99. }
  100. bindEvents() {
  101. // let ray = new BABYLON.Ray(new BABYLON.Vector3(0,0,0), new BABYLON.Vector3(0,0,1), 50);
  102. // document.getElementById("renderCanvas").addEventListener("click", (pointerInfo) => {
  103. // if(this.mouseMoving) return
  104. // // console.error("click")
  105. // let pickPoint = this.screenToWorld({x: pointerInfo.x, y: pointerInfo.y})
  106. // ray.origin = pickPoint
  107. // ray.direction = BABYLON.Vector3.Normalize( this.cameraController.camera.position.clone().subtract(pickPoint) )
  108. // let pickInfo = ray.intersectsMeshes(this.house)[0];
  109. // if(pickInfo.hit && this.house.indexOf(pickInfo.pickedMesh)) {
  110. // this.charactorManager.clickHouse()
  111. // }
  112. // })
  113. // document.getElementById("renderCanvas").addEventListener("pointerdown", (pointerInfo) => {
  114. // console.error("down")
  115. // this.cameraController.startMouseRotate({event: pointerInfo})
  116. // this.mouseMoving = false
  117. // })
  118. // document.getElementById("renderCanvas").addEventListener("pointerup", (pointerInfo) => {
  119. // this.cameraController.endMouseRotate()
  120. // // console.error("up")
  121. // })
  122. // document.getElementById("renderCanvas").addEventListener("pointermove", (pointerInfo) => {
  123. // if(this.cameraController.lastFramePoint) {
  124. // // console.error("move")
  125. // this.cameraController.mouseRotating({event: pointerInfo})
  126. // this.mouseMoving = true
  127. // }
  128. // })
  129. this.scene.onPointerObservable.add((pointerInfo) => {
  130. switch (pointerInfo.type) {
  131. case BABYLON.PointerEventTypes.POINTERDOWN:
  132. // this.mouseMoving = false
  133. this.cameraController.startMouseRotate(pointerInfo)
  134. break;
  135. case BABYLON.PointerEventTypes.POINTERUP:
  136. this.cameraController.endMouseRotate()
  137. break;
  138. case BABYLON.PointerEventTypes.POINTERMOVE:
  139. if(this.cameraController.lastFramePoint) {
  140. // this.mouseMoving = true
  141. this.cameraController.mouseRotating(pointerInfo)
  142. }
  143. break;
  144. case BABYLON.PointerEventTypes.POINTERWHEEL:
  145. break;
  146. case BABYLON.PointerEventTypes.POINTERPICK:
  147. break;
  148. case BABYLON.PointerEventTypes.POINTERTAP:
  149. // !this.mouseMoving &&
  150. if(pointerInfo.pickInfo.hit && this.house.indexOf(pointerInfo.pickInfo.pickedMesh)) {
  151. this.charactorManager.clickHouse()
  152. }
  153. break;
  154. case BABYLON.PointerEventTypes.POINTERDOUBLETAP:
  155. break;
  156. }
  157. });
  158. this.scene.onBeforeAnimationsObservable.add(() => {
  159. if(this.charactorManager && this.charactorManager.charactor)
  160. this.charactorManager.onBeforeAnimation()
  161. })
  162. this.scene.onBeforeRenderObservable.add(() => {
  163. this.cameraController.updateCameraPos()
  164. })
  165. }
  166. bindSocketEvents() {
  167. let walkPointsTemp = []
  168. // 获得旋转视频
  169. window.connection.socket.on('getRotateVideoUrl', async(data) => {
  170. console.log("[3D] getRotateVideoUrl: ", data)
  171. const url = data
  172. let video = data.indexOf("_rotate") > -1
  173. ? document.getElementById("houseTextureReverse")
  174. : document.getElementById("houseTexture")
  175. video.src = url
  176. // 页面刷新后初次加载视频
  177. if(this.initVideo) {
  178. // this.updateHouseVideo(video, true)
  179. this.initVideo = false
  180. this.cameraController.camera.minZ = 0.001
  181. }
  182. })
  183. // 获得行走视频
  184. window.connection.socket.on('getVideoUrl', async(data) => {
  185. console.log("[3D] getVideoUrl: ", data)
  186. const urlArr = data
  187. if(this.charactorManager.charactor.actionType.split("-")[1] != "Walking") {
  188. // TODO 目前禁止临时拐弯
  189. let path = walkPointsTemp.map((point, i) => {
  190. return {
  191. id: point.id,
  192. point: new BABYLON.Vector3(-point.location.x, 0, point.location.z),
  193. video: urlArr[i] ? common.createVideoElement0(urlArr[i]) : null,
  194. }
  195. })
  196. // 行走时锁定camera
  197. console.log("Walk Start: ", path)
  198. this.cameraController.lockCamera(true)
  199. this.charactorManager.charactor.startWalk(path, this.charactorManager)
  200. }
  201. })
  202. // 获得行走路径
  203. window.connection.socket.on("getRoute", (data) => {
  204. console.log("[3D] getRoute", data);
  205. if(!data || data.length < 2) return
  206. walkPointsTemp = data
  207. let dir = this.charactorManager.getVideoDirecNum()
  208. let videoNames = []
  209. for(let i = 0; i < data.length-1; i++) {
  210. videoNames.push(data[i].id + "/" + data[i].id + "_" + data[i+1].id + "_" + dir)
  211. }
  212. this.getSocketVideoType = "walkPath"
  213. let sendData = {
  214. videoList: videoNames,
  215. sceneCode: settings.sceneCode,
  216. roomId: settings.roomId,
  217. userId: settings.userId,
  218. }
  219. console.log("[3D] send(getVideoUrl): ", sendData);
  220. connection.socket.emit("getVideoUrl", sendData);
  221. });
  222. }
  223. updateHouseVideo(video, notPlay) {
  224. let videoTexture = new BABYLON.VideoTexture("", video, this.scene)
  225. this.hasVideoTexture && this.house.forEach(mesh => {
  226. mesh.material && mesh.material.setTexture("texture_video", videoTexture)
  227. })
  228. !notPlay && video.play()
  229. }
  230. async updateHouseVideoBlob(blobUrl, notPlay) {
  231. let video = await common.createVideoElement(blobUrl)
  232. // video.loop = "loop"
  233. let videoTexture = new BABYLON.VideoTexture("", video, this.scene)
  234. this.hasVideoTexture && this.house.forEach(mesh => {
  235. mesh.material && mesh.material.setTexture("texture_video", videoTexture)
  236. })
  237. !notPlay && video.play()
  238. }
  239. screenToWorld(point) {
  240. let camera = this.cameraController.camera
  241. const viewport = camera.viewport.toGlobal(this.engine.getRenderWidth(), this.engine.getRenderHeight());
  242. return BABYLON.Vector3.Unproject(new BABYLON.Vector3(point.x, point.y, 0), viewport.width, viewport.height,
  243. BABYLON.Matrix.Identity(), camera.getViewMatrix(), camera.getProjectionMatrix());
  244. }
  245. worldToSceen(point) {
  246. let camera = this.cameraController.camera
  247. const viewPort = camera.viewport.toGlobal(this.engine.getRenderWidth(), this.engine.getRenderHeight());
  248. return BABYLON.Vector3.Project(point, BABYLON.Matrix.Identity(), this.scene.getTransformMatrix(), viewPort);
  249. }
  250. }