EngineProxy.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. import CircularArray from "./CircularArray.js"
  2. import AssetTypeName from "./enum/AssetTypeName.js"
  3. import AssetClassName from "./enum/AssetClassName.js"
  4. import LoggerLevels from "./enum/LoggerLevels.js"
  5. import EShaderMode from "./enum/EShaderMode.js"
  6. import EFitMode from "./enum/EFitMode.js"
  7. import Http from "./Http.js"
  8. import XSceneManager from "./XSceneManager.js"
  9. import XBillboardManager from "./XBillboardManager.js"
  10. import ModelManager from "./ModelManager.js"
  11. import InitEngineTimeoutError from "./error/InitEngineTimeoutError.js"
  12. import Logger from "./Logger.js"
  13. const logger = new Logger('xverse-bus')
  14. const http = new Http
  15. const blobToDataURI = async i=>new Promise((resolve,reject)=>{
  16. const fileReader = new FileReader;
  17. fileReader.readAsDataURL(i),
  18. fileReader.onload = function(n) {
  19. var o;
  20. resolve((o = n.target) == null ? void 0 : o.result)
  21. }
  22. ,
  23. fileReader.onerror = function(n) {
  24. reject(n)
  25. }
  26. }
  27. )
  28. const urlMap = new Map
  29. , urlTransformer = async(i,e=!1)=>typeof i != "string" ? (console.warn("url transformer error", i),
  30. i) : i.startsWith("blob:") ? i : e ? http.get({
  31. url: i,
  32. useIndexedDb: !0,
  33. key: "url",
  34. isOutPutObjectURL: !1
  35. }) : urlMap.has(i) ? urlMap.get(i) : http.get({
  36. url: i,
  37. useIndexedDb: !0,
  38. key: "url"
  39. }).then(t=>(urlMap.set(i, t),
  40. t));
  41. let sceneManager;
  42. function getSceneManager(i, e) {
  43. return sceneManager || (sceneManager = new XSceneManager(i,e)),
  44. sceneManager
  45. }
  46. export default class EngineProxy{
  47. constructor(xverseRoom) {
  48. E(this, "_tvs", []);
  49. E(this, "isRenderFirstFrame", !1);
  50. E(this, "_idleTime", 0);
  51. E(this, "renderTimer");
  52. E(this, "lightManager");
  53. E(this, "_checkSceneNotReadyCount", 0);
  54. E(this, "_checkSceneDurationFrameNum", 0);
  55. E(this, "_checkSceneFrameCount", 0);
  56. E(this, "timeoutCircularArray", new CircularArray(120,!1,[]));
  57. E(this, "frameCircularArray", new CircularArray(120,!1,[]));
  58. E(this, "interFrameCircularArray", new CircularArray(120,!1,[]));
  59. E(this, "drawCallCntCircularArray", new CircularArray(120,!1,[]));
  60. E(this, "activeFacesCircularArray", new CircularArray(120,!1,[]));
  61. E(this, "renderTimeCircularArray", new CircularArray(120,!1,[]));
  62. E(this, "drawCallTimeCircularArray", new CircularArray(120,!1,[]));
  63. E(this, "animationCircularArray", new CircularArray(120,!1,[]));
  64. E(this, "meshSelectCircularArray", new CircularArray(120,!1,[]));
  65. E(this, "renderTargetCircularArray", new CircularArray(120,!1,[]));
  66. E(this, "regBeforeRenderCircularArray", new CircularArray(120,!1,[]));
  67. E(this, "regAfterRenderCircularArray", new CircularArray(120,!1,[]));
  68. E(this, "renderCnt", 0);
  69. E(this, "renderErrorCount", 0);
  70. E(this, "engineSloppyCnt", 0);
  71. E(this, "systemStuckCnt", 0);
  72. E(this, "frameRenderNumber", 0);
  73. E(this, "_setFPS", (sceneManager,t=25)=>{
  74. logger.info("Set fps to", t);
  75. const r = t > 60 ? 60 : t < 24 ? 24 : t;
  76. sceneManager.Engine.stopRenderLoop();
  77. const n = 1e3 / r;
  78. let o = Date.now()
  79. , a = Date.now()
  80. , s = n
  81. , l = 1;
  82. const u = ()=>{
  83. var T;
  84. const c = Date.now()
  85. , h = c - o
  86. , f = c - a;
  87. a = c,
  88. this.frameCircularArray.add(f),
  89. h - s > n && (this.systemStuckCnt += 1);
  90. const d = h / s;
  91. l = .9 * l + .1 * d;
  92. const _ = Date.now();
  93. let g = 0
  94. , m = 0;
  95. if (this.room.isUpdatedRawYUVData || this.room.isPano) {
  96. this.isRenderFirstFrame = !0
  97. if (this._checkSceneDurationFrameNum > 0)
  98. {
  99. this._checkSceneFrameCount++,
  100. this.room.sceneManager.isReadyToRender({}) && this._checkSceneDurationFrameNum--,
  101. this._checkSceneFrameCount > EngineProxy._CHECK_DURATION && (this._checkSceneDurationFrameNum = EngineProxy._CHECK_DURATION,
  102. this._checkSceneFrameCount = 0,
  103. this._checkSceneNotReadyCount++,
  104. (this._checkSceneNotReadyCount == 1 || this._checkSceneNotReadyCount % 100 == 0) && logger.error(`[SDK] Scene not ready, skip render. loop: ${this._checkSceneNotReadyCount}`),
  105. this._checkSceneNotReadyCount > 10 && (logger.error("[SDK] Scene not ready, reload later"),
  106. this.room.proxyEvents("renderError", {
  107. error: new Error("[SDK] Scene not ready, skip render and reload.")
  108. })),
  109. this.room.stats.assign({
  110. renderErrorCount: this._checkSceneNotReadyCount
  111. }),
  112. logger.infoAndReportMeasurement({
  113. value: 0,
  114. startTime: Date.now(),
  115. metric: "renderError",
  116. error: new Error("[SDK] Scene not ready, skip render and reload."),
  117. reportOptions: {
  118. sampleRate: .1
  119. }
  120. }));
  121. }
  122. else
  123. {
  124. try {
  125. sceneManager.render()
  126. }
  127. catch (C) {
  128. this.renderErrorCount++,
  129. this.renderErrorCount > 10 && this.room.proxyEvents("renderError", {
  130. error: C
  131. }),
  132. this.room.stats.assign({
  133. renderErrorCount: this.renderErrorCount
  134. }),
  135. logger.infoAndReportMeasurement({
  136. value: 0,
  137. startTime: Date.now(),
  138. metric: "renderError",
  139. error: C,
  140. reportOptions: {
  141. sampleRate: .1
  142. }
  143. })
  144. }
  145. }
  146. g = Date.now() - _,
  147. this.frameRenderNumber < 1e3 && this.frameRenderNumber++,
  148. this.room.networkController.rtcp.workers.UpdateYUV(),
  149. m = Date.now() - _ - g
  150. }
  151. this.isRenderFirstFrame || this.room.networkController.rtcp.workers.UpdateYUV();
  152. const y = Date.now() - _;
  153. o = c + y,
  154. s = Math.min(Math.max((n - y) / l, 5), 200),
  155. y > n && (s = 10,
  156. this.engineSloppyCnt += 1),
  157. this._idleTime = s;
  158. const b = s;
  159. if (s > 150 && console.log("lastGap is ", s, ", ratio is ", l, ", usedTimeMs is ", y, ", cpuRenderTime is ", g, ", cpuUpdateYUVTime is ", m),
  160. this.timeoutCircularArray.add(b),
  161. this.renderCnt % 25 == 0) {
  162. const C = this.frameCircularArray.getAvg()
  163. , A = this.timeoutCircularArray.getAvg()
  164. , S = this.frameCircularArray.getMax()
  165. , P = this.timeoutCircularArray.getMax();
  166. (T = this.room.stats) == null || T.assign({
  167. avgFrameTime: C,
  168. avgTimeoutTime: A,
  169. maxFrameTime: S,
  170. maxTimeoutTime: P,
  171. systemStuckCnt: this.systemStuckCnt
  172. })
  173. }
  174. this.renderTimer = window.setTimeout(u, s)
  175. }
  176. ;
  177. this.renderTimer = window.setTimeout(u, n / l)
  178. });
  179. E(this, "updateStats", ()=>{
  180. var e;
  181. (e = this.room.stats) == null || e.assign({
  182. renderFrameTime: this.renderTimeCircularArray.getAvg(),
  183. maxRenderFrameTime: this.renderTimeCircularArray.getMax(),
  184. interFrameTime: this.interFrameCircularArray.getAvg(),
  185. animationTime: this.animationCircularArray.getAvg(),
  186. meshSelectTime: this.meshSelectCircularArray.getAvg(),
  187. drawcallTime: this.drawCallTimeCircularArray.getAvg(),
  188. idleTime: this._idleTime,
  189. registerBeforeRenderTime: this.regBeforeRenderCircularArray.getAvg(),
  190. registerAfterRenderTime: this.regAfterRenderCircularArray.getAvg(),
  191. renderTargetRenderTime: this.renderTargetCircularArray.getAvg(),
  192. fps: (1e3 / (this.renderTimeCircularArray.getAvg() + this.interFrameCircularArray.getAvg())).toFixed(2),
  193. drawcall: this.drawCallCntCircularArray.getAvg(),
  194. engineSloppyCnt: this.engineSloppyCnt,
  195. maxInterFrameTime: this.interFrameCircularArray.getMax(),
  196. maxDrawcallTime: this.drawCallTimeCircularArray.getMax(),
  197. maxMeshSelectTime: this.meshSelectCircularArray.getMax(),
  198. maxAnimationTime: this.animationCircularArray.getMax(),
  199. maxRegisterBeforeRenderTime: this.regBeforeRenderCircularArray.getMax(),
  200. maxRegisterAfterRenderTime: this.regAfterRenderCircularArray.getMax(),
  201. maxRenderTargetRenderTime: this.renderTargetCircularArray.getMax(),
  202. avgFrameTime: this.frameCircularArray.getAvg(),
  203. avgTimeoutTime: this.timeoutCircularArray.getAvg(),
  204. maxFrameTime: this.frameCircularArray.getMax(),
  205. maxTimeoutTime: this.timeoutCircularArray.getMax()
  206. })
  207. }
  208. );
  209. this.room = xverseRoom
  210. }
  211. async initEngine(e) {
  212. await this.updateBillboard();
  213. logger.info("engine version:", VERSION$1);
  214. logger.setLevel(LoggerLevels.Warn);
  215. const videoPanoInfo = {
  216. videoResOriArray: [{
  217. width: 720,
  218. height: 1280
  219. }, {
  220. width: 1280,
  221. height: 720
  222. }, {
  223. width: 480,
  224. height: 654
  225. }, {
  226. width: 654,
  227. height: 480
  228. }, {
  229. width: 1920,
  230. height: 1080
  231. }, {
  232. width: 1080,
  233. height: 1920
  234. }, {
  235. width: 414,
  236. height: 896
  237. }],
  238. forceKeepVertical: this.room.options.objectFit !== "cover",
  239. panoInfo: {
  240. dynamicRange: 1,
  241. width: 4096,
  242. height: 2048
  243. },
  244. shaderMode: EShaderMode.videoAndPano,
  245. yuvInfo: {
  246. width: 1280,
  247. height: 720,
  248. fov: e.fov || DEFAULT_MAIN_CAMERA_FOV
  249. },
  250. cameraParam: {
  251. maxZ: 1e4
  252. },
  253. urlTransformer,
  254. logger: logger,
  255. disableWebGL2: this.room.options.disableWebGL2 || !1
  256. };
  257. const resolution = this.room.options.resolution;
  258. if(resolution){
  259. videoPanoInfo.videoResOriArray.some(l=>l.width === resolution.width && l.height === resolution.height) || videoPanoInfo.videoResOriArray.push(resolution)
  260. }
  261. const sceneManager = this.room.sceneManager = getSceneManager(this.room.canvas, videoPanoInfo);
  262. this.room.setPictureQualityLevel(this.room.options.pictureQualityLevel || "high");
  263. this.room.sceneManager.staticmeshComponent.setRegionLodRule([2, 2, -1, -1, -1]);
  264. this.room.scene = sceneManager.Scene;
  265. this.room.breathPointManager = sceneManager.breathPointComponent;
  266. this.lightManager = sceneManager.lightComponent;
  267. this.registerStats();
  268. this.setEnv(e);
  269. await this.room.avatarManager.init();
  270. const a = this._createAssetList(e);
  271. await this.loadAssets(a, "");
  272. this._setFPS(sceneManager);
  273. }
  274. pause() {
  275. clearTimeout(this.renderTimer),
  276. logger.info("Invoke room.pause to pause render");
  277. const e = {
  278. roomId: this.room.id,
  279. effects: [],
  280. lowPolyModels: [],
  281. breathPointsConfig: [],
  282. skinId: this.room.skinId
  283. };
  284. return this.loadAssets(e, this.room.skinId)
  285. }
  286. async resume() {
  287. this._setFPS(this.room.sceneManager),
  288. this.room.sceneManager.cameraComponent.cameraFovChange(this.room.sceneManager.yuvInfo),
  289. logger.info("Invoke room.resume to render");
  290. const e = this._createAssetList(this.room.skin);
  291. await this.loadAssets(e, "")
  292. }
  293. setEnv(e) {
  294. var r;
  295. this.lightManager || (this.lightManager = this.room.sceneManager.lightComponent),
  296. e = e || this.room.skin;
  297. const t = ModelManager.findModel(e.models, AssetTypeName.Config, AssetClassName.Env);
  298. return t ? (r = this.lightManager) == null ? void 0 : r.setIBL(t.modelUrl) : (logger.error("env file not found"),
  299. Promise.resolve())
  300. }
  301. async _parseModelsAndLoad(e, t, r) {
  302. logger.info("Invoke _parseModelsAndLoad start", t);
  303. const n = ["airship", "balloon", "default", "ground_feiting", "ground_reqiqiu"]
  304. , o = new Map;
  305. r == null && (r = "xxxx");
  306. let a = !0;
  307. for (let u = 0; u < e.length; ++u) {
  308. a = !0;
  309. for (let c = 0; c < n.length; ++c)
  310. if (e[u].modelUrl.toLowerCase().indexOf(n[c]) >= 0) {
  311. const h = o.get(n[c]);
  312. h ? (h.push(e[u]),
  313. o.set(n[c], h)) : o.set(n[c], [e[u]]),
  314. a = !1;
  315. break
  316. }
  317. if (a) {
  318. const c = o.get("default");
  319. c ? (c.push(e[u]),
  320. o.set("default", c)) : o.set("default", [e[u]])
  321. }
  322. }
  323. let s = o.get(t) || [];
  324. if (this.room.viewMode === "simple" && (s = s.filter(u=>!u.modelUrl.endsWith("zip"))),
  325. !s)
  326. return Promise.reject(`no invalid scene model with group name: ${t}`);
  327. const l = [];
  328. for (let u = 0; u < s.length; ++u) {
  329. const c = s[u];
  330. if (c.modelUrl.toLowerCase().endsWith("zip"))
  331. c.modelUrl.toLowerCase().endsWith("zip") && l.push(this.room.sceneManager.addNewLowPolyMesh({
  332. url: c.modelUrl,
  333. skinInfo: r
  334. }));
  335. else {
  336. const h = t;
  337. l.push(this.room.sceneManager.addNewLowPolyMesh({
  338. url: c.modelUrl,
  339. group: h,
  340. pick: !0,
  341. skinInfo: r
  342. }))
  343. }
  344. }
  345. return Promise.all(l)
  346. }
  347. async _deleteAssetsLowpolyModel(e) {
  348. this.room.sceneManager.staticmeshComponent.deleteMeshesBySkinInfo(e),
  349. this.room.sceneManager.breathPointComponent.clearBreathPointsBySkinInfo(e),
  350. this.room.sceneManager.decalComponent.deleteDecalBySkinInfo(e);
  351. const t = [];
  352. this.room.sceneManager.Scene.meshes.forEach(r=>{
  353. r.xskinInfo == e && t.push(r)
  354. }
  355. ),
  356. t.forEach(r=>{
  357. r.dispose(!1, !1)
  358. }
  359. )
  360. }
  361. async loadLandAssets() {
  362. const e = this._createAssetList(this.room.skin);
  363. return this.loadAssets(e, this.room.skinId).catch(()=>this.loadAssets(e, this.room.skinId))
  364. }
  365. async loadAssets(e, t="", r=8e3) {
  366. const startTime = Date.now();
  367. return this._loadAssets(e, t)._timeout(r, new InitEngineTimeoutError(`loadAssets timeout(${r}ms)`)).then(o=>(logger.infoAndReportMeasurement({
  368. tag: "loadAssets",
  369. startTime: startTime,
  370. metric: "loadAssets"
  371. }),o)).catch(err=>(logger.infoAndReportMeasurement({
  372. tag: "loadAssets",
  373. startTime: startTime,
  374. metric: "loadAssets",
  375. error: err
  376. }),
  377. Promise.reject(err)))
  378. }
  379. async _loadAssets(e, t="") {
  380. try {
  381. const r = [];
  382. r.push(this._loadAssetsLowpolyModel(e, t));
  383. await Promise.all(r);
  384. await this.setEnv();
  385. this._checkSceneDurationFrameNum = EngineProxy._CHECK_DURATION;
  386. this._checkSceneNotReadyCount = 0;
  387. this._checkSceneFrameCount = 0;
  388. this.updateAnimationList();
  389. this.room.loadAssetsHook();
  390. } catch (r) {
  391. return Promise.reject(r)
  392. }
  393. }
  394. updateAnimationList() {
  395. if (this.room.avatarManager && this.room.avatarManager.xAvatarManager) {
  396. const animationList = this.room.skin.animationList;
  397. if (!animationList)
  398. {
  399. return;
  400. }
  401. animationList.forEach(t=>{
  402. this.room.avatarManager.xAvatarManager.updateAnimationLists(t.animations, t.avatarId)
  403. })
  404. }
  405. }
  406. async _loadAssetsLowpolyModel(e, t="") {
  407. const r = []
  408. , n = []
  409. , o = [];
  410. e.lowPolyModels.forEach(f=>{
  411. f.group === "TV" ? n.push({
  412. id: "",
  413. name: "",
  414. thumbnailUrl: "",
  415. typeName: AssetTypeName.Model,
  416. className: AssetClassName.Tv,
  417. modelUrl: f.url
  418. }) : f.group === "\u544A\u767D\u5899" ? o.push({
  419. id: "",
  420. name: "",
  421. thumbnailUrl: "",
  422. typeName: AssetTypeName.Model,
  423. className: AssetClassName.Lpm,
  424. modelUrl: f.url
  425. }) : r.push({
  426. id: "",
  427. name: "",
  428. thumbnailUrl: "",
  429. typeName: AssetTypeName.Model,
  430. className: AssetClassName.Lpm,
  431. modelUrl: f.url
  432. })
  433. });
  434. t != "" && t != null && this._deleteAssetsLowpolyModel(t);
  435. const skinId = e.skinId;
  436. logger.info("====> from ", t, " to ", skinId),
  437. this._tvs.forEach(f=>f.clean()),
  438. this._tvs = [];
  439. let s = EFitMode.cover;
  440. skinId == "10048" && (s = EFitMode.contain)
  441. Array.isArray(n) && n.forEach((f,d)=>{
  442. this._tvs.push(new TV("squareTv" + d,f.modelUrl,this.room,{
  443. fitMode: s
  444. }))
  445. }
  446. ),
  447. e.breathPointsConfig.forEach(async breathPoint=>{
  448. let d;
  449. try {
  450. d = await urlTransformer(breathPoint.imageUrl)
  451. } catch (_) {
  452. d = breathPoint.imageUrl,
  453. logger.error("urlTransformer error", _)
  454. }
  455. this.room.breathPointManager.addBreathPoint({
  456. id: breathPoint.id,
  457. position: breathPoint.position,
  458. spriteSheet: d,
  459. rotation: breathPoint.rotation || {
  460. pitch: 0,
  461. yaw: 270,
  462. roll: 0
  463. },
  464. billboardMode: !0,
  465. type: breathPoint.type || "no_type",
  466. spriteWidthNumber: breathPoint.spriteWidthNum || 1,
  467. spriteHeightNumber: breathPoint.spriteHeightNum || 1,
  468. maxVisibleRegion: breathPoint.maxVisibleRegion || 150,
  469. width: breathPoint.width,
  470. height: breathPoint.height,
  471. skinInfo: breathPoint.skinId
  472. })
  473. }
  474. ),
  475. o.forEach(f=>{
  476. this.room.sceneManager.decalComponent.addDecal({
  477. id: f.id || "gbq",
  478. meshPath: f.modelUrl,
  479. skinInfo: skinId
  480. })
  481. }
  482. );
  483. const u = this.room.sceneManager.staticmeshComponent.lowModel_group
  484. , c = Array.from(u.keys()).filter(f=>!f.startsWith("region_"))
  485. , h = ["airship", "balloon", "ground_feiting", "ground_reqiqiu", "default"];
  486. return new Promise((f,d)=>{
  487. Promise.all(h.map(_=>this._parseModelsAndLoad(r, _, skinId))).then(()=>{
  488. let _ = !1;
  489. r.forEach(v=>{
  490. v.modelUrl.endsWith("zip") && (_ = !0)
  491. }
  492. ),
  493. _ == !1 && this.room.sceneManager.staticmeshComponent.deleteLastRegionMesh(),
  494. this.room.sceneManager.staticmeshComponent.lowModel_group;
  495. const g = Array.from(u.keys()).filter(v=>!v.startsWith("region_"))
  496. , m = c.filter(v=>g.indexOf(v) < 0);
  497. m.length > 0 && m.forEach(v=>{
  498. this.room.sceneManager.staticmeshComponent.deleteMeshesByGroup(v)
  499. }
  500. ),
  501. f(!0)
  502. }
  503. ).catch(_=>{
  504. d(_)
  505. }
  506. )
  507. }
  508. )
  509. }
  510. async _updateSkinAssets(e) {
  511. const t = this.room.lastSkinId
  512. , r = await this.room.getSkin(e)
  513. , n = this._createAssetList(r);
  514. try {
  515. await this.loadAssets(n, t),
  516. this.room.updateCurrentState({
  517. versionId: r.versionId,
  518. skinId: r.id,
  519. skin: r
  520. })
  521. } catch {
  522. await this.loadAssets(n, t),
  523. this.room.updateCurrentState({
  524. versionId: r.versionId,
  525. skinId: r.id,
  526. skin: r
  527. })
  528. }
  529. this.setEnv(r)
  530. }
  531. _createAssetList(e) {
  532. const t = []
  533. , r = []
  534. , n = [];
  535. let o = e.models;
  536. const a = this.room.modelManager.config.preload;
  537. return this.room.viewMode === "simple" ? a && (o = a.baseUrls.map(l=>(l.modelUrl = l.url,
  538. l))) : this.room.viewMode,
  539. ModelManager.findModels(o, AssetTypeName.Effects, AssetClassName.Effects).forEach(l=>{
  540. t.push({
  541. url: l.modelUrl,
  542. group: l.className,
  543. name: l.name
  544. })
  545. }
  546. ),
  547. ModelManager.findModels(o, AssetTypeName.Model, AssetClassName.Lpm).forEach(l=>{
  548. r.push({
  549. url: l.modelUrl,
  550. group: l.className
  551. })
  552. }
  553. ),
  554. ModelManager.findModels(o, AssetTypeName.Model, AssetClassName.Gbq).forEach(l=>{
  555. r.push({
  556. url: l.modelUrl,
  557. group: l.className
  558. })
  559. }
  560. ),
  561. ModelManager.findModels(o, AssetTypeName.Model, AssetClassName.Tv).forEach(l=>{
  562. r.push({
  563. url: l.modelUrl,
  564. group: l.className
  565. })
  566. }
  567. ),
  568. [].forEach(l=>{
  569. l.skinId == e.id && n.push(l)
  570. }
  571. ),
  572. {
  573. roomId: this.room.id,
  574. effects: t,
  575. lowPolyModels: r,
  576. breathPointsConfig: n,
  577. skinId: e.id
  578. }
  579. }
  580. //sceneManager.statisticComponent是XStats对象
  581. registerStats() {
  582. const sceneManager = this.room.sceneManager;
  583. this.room.scene.registerAfterRender(()=>{
  584. const interFrameTimeCounterCurrent = sceneManager.statisticComponent.getInterFrameTimeCounter()
  585. const drawCallsCounterCurrent = sceneManager.statisticComponent.getDrawCall()
  586. const activeTriangle = sceneManager.statisticComponent.getActiveFaces()
  587. const frameTimeCounterCurrent = sceneManager.statisticComponent.getFrameTimeCounter()
  588. const renderTimeCounterCurrent = sceneManager.statisticComponent.getDrawCallTime()
  589. const animationsTimeCounterCurrent = sceneManager.statisticComponent.getAnimationTime()
  590. const activeMeshesEvaluationTimeCounterCurrent = sceneManager.statisticComponent.getActiveMeshEvaluationTime()
  591. const renderTargetRenderTime = sceneManager.statisticComponent.getRenderTargetRenderTime()
  592. const registerBeforeTimeCounterCurrent = sceneManager.statisticComponent.getRegisterBeforeRenderTime()
  593. const registerAfterTimeCounterCurrent = sceneManager.statisticComponent.getRegisterAfterRenderTime()
  594. const _activeParticlesCurrent = sceneManager.statisticComponent.getActiveParticles()
  595. const _activeBonesCurrent = sceneManager.statisticComponent.getActiveBones()
  596. const activeAnimatablesLength = sceneManager.Scene._activeAnimatables.length
  597. const rootNodesLength = sceneManager.statisticComponent.getTotalRootNodes()
  598. const geometriesLength = sceneManager.Scene.geometries.length
  599. const beforeRenderObservableLength = sceneManager.Scene.onBeforeRenderObservable.observers.length
  600. const afterRenderObservableLength = sceneManager.Scene.onAfterRenderObservable.observers.length
  601. const meshesLength = sceneManager.statisticComponent.getTotalMeshes()
  602. const texturesLength = sceneManager.statisticComponent.getTotalTextures()
  603. const materialsLength = sceneManager.statisticComponent.getTotalMaterials()
  604. const systemInfo = sceneManager.statisticComponent.getSystemInfo()
  605. const resolution = systemInfo.resolution
  606. const driver = systemInfo.driver;
  607. systemInfo.vender;
  608. const version = systemInfo.version
  609. const hardwareScalingLevel = systemInfo.hardwareScalingLevel
  610. const hardwareInfo = resolution + "_" + driver + "_" + version + "_" + hardwareScalingLevel;
  611. this.interFrameCircularArray.add(interFrameTimeCounterCurrent);
  612. this.renderTimeCircularArray.add(frameTimeCounterCurrent);
  613. this.animationCircularArray.add(animationsTimeCounterCurrent);
  614. this.meshSelectCircularArray.add(activeMeshesEvaluationTimeCounterCurrent);
  615. this.drawCallTimeCircularArray.add(renderTimeCounterCurrent);
  616. this.regAfterRenderCircularArray.add(registerAfterTimeCounterCurrent);
  617. this.regBeforeRenderCircularArray.add(registerBeforeTimeCounterCurrent);
  618. this.renderTargetCircularArray.add(renderTargetRenderTime);
  619. this.drawCallCntCircularArray.add(drawCallsCounterCurrent);
  620. this.renderCnt += 1;
  621. if(this.renderCnt % 25 == 0){
  622. let stats = this.room.stats
  623. if(stats != null){
  624. stats.assign({
  625. renderFrameTime: this.renderTimeCircularArray.getAvg(),
  626. maxRenderFrameTime: this.renderTimeCircularArray.getMax(),
  627. interFrameTime: this.interFrameCircularArray.getAvg(),
  628. animationTime: this.animationCircularArray.getAvg(),
  629. meshSelectTime: this.meshSelectCircularArray.getAvg(),
  630. drawcallTime: this.drawCallTimeCircularArray.getAvg(),
  631. idleTime: this._idleTime,
  632. registerBeforeRenderTime: this.regBeforeRenderCircularArray.getAvg(),
  633. registerAfterRenderTime: this.regAfterRenderCircularArray.getAvg(),
  634. renderTargetRenderTime: this.renderTargetCircularArray.getAvg(),
  635. fps: (1e3 / (this.renderTimeCircularArray.getAvg() + this.interFrameCircularArray.getAvg())).toFixed(2),
  636. drawcall: this.drawCallCntCircularArray.getAvg(),
  637. triangle: activeTriangle.toString(),
  638. engineSloppyCnt: this.engineSloppyCnt,
  639. maxInterFrameTime: this.interFrameCircularArray.getMax(),
  640. maxDrawcallTime: this.drawCallTimeCircularArray.getMax(),
  641. maxMeshSelectTime: this.meshSelectCircularArray.getMax(),
  642. maxAnimationTime: this.animationCircularArray.getMax(),
  643. maxRegisterBeforeRenderTime: this.regBeforeRenderCircularArray.getMax(),
  644. maxRegisterAfterRenderTime: this.regAfterRenderCircularArray.getMax(),
  645. maxRenderTargetRenderTime: this.renderTargetCircularArray.getMax(),
  646. activeParticles: _activeParticlesCurrent,
  647. activeBones: _activeBonesCurrent,
  648. activeAnimation: activeAnimatablesLength,
  649. totalMeshes: meshesLength,
  650. totalRootNodes: rootNodesLength,
  651. totalGeometries: geometriesLength,
  652. totalTextures: texturesLength,
  653. totalMaterials: materialsLength,
  654. registerBeforeCount: beforeRenderObservableLength,
  655. registerAfterCount: afterRenderObservableLength,
  656. hardwareInfo: hardwareInfo
  657. })
  658. }
  659. }
  660. }
  661. )
  662. }
  663. async updateBillboard() {
  664. const {options: {skinId: skinId}} = this.room
  665. , r = (await this.room.modelManager.findAssetList(skinId)).filter(a=>a.typeName === AssetTypeName.Textures && a.className === AssetClassName.SayBubble)
  666. , n = ["bubble01", "bubble02", "bubble03"]
  667. , o = ["bubble01_npc", "bubble02_npc", "bubble03_npc"];
  668. if (r.length) {
  669. const a = r.filter(l=>n.includes(l.name)).map(l=>l.url)
  670. , s = r.filter(l=>o.includes(l.name)).map(l=>l.url);
  671. a.length && (XBillboardManager.userBubbleUrls = a),
  672. s.length && (XBillboardManager.npcBubbleUrls = s)
  673. }
  674. }
  675. }
  676. ;