lythreeframe 1.2.48 → 1.2.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,7 @@
3
3
  var webgpu = require('three/webgpu');
4
4
  var Addons_js = require('three/examples/jsm/Addons.js');
5
5
  var tsl = require('three/tsl');
6
+ var three = require('three');
6
7
  var DepthOfFieldNode_js = require('three/addons/tsl/display/DepthOfFieldNode.js');
7
8
  var BloomNode_js = require('three/examples/jsm/tsl/display/BloomNode.js');
8
9
  var DenoiseNode_js = require('three/examples/jsm/tsl/display/DenoiseNode.js');
@@ -11,7 +12,6 @@ var GTAONode_js = require('three/examples/jsm/tsl/display/GTAONode.js');
11
12
  var OutlineNode_js = require('three/examples/jsm/tsl/display/OutlineNode.js');
12
13
  var SMAANode_js = require('three/examples/jsm/tsl/display/SMAANode.js');
13
14
  var gsap = require('gsap');
14
- var three = require('three');
15
15
  var SkyMesh_js = require('three/examples/jsm/objects/SkyMesh.js');
16
16
  var CSS2DRenderer_js = require('three/examples/jsm/renderers/CSS2DRenderer.js');
17
17
  var PointerLockControls_js = require('three/examples/jsm/controls/PointerLockControls.js');
@@ -1521,7 +1521,12 @@ class Viewport {
1521
1521
  }
1522
1522
  get renderer() {
1523
1523
  if (!this._renderer) {
1524
- throw Error("Renderer is not initialized");
1524
+ if (this._webGLRenderer) {
1525
+ return this._webGLRenderer;
1526
+ }
1527
+ else {
1528
+ throw Error("Renderer is not initialized");
1529
+ }
1525
1530
  }
1526
1531
  return this._renderer;
1527
1532
  }
@@ -1534,6 +1539,7 @@ class Viewport {
1534
1539
  constructor(app, viewportParam, rendererParam, postProcessParam) {
1535
1540
  this._uiDom = null;
1536
1541
  this._renderer = null;
1542
+ this._webGLRenderer = null;
1537
1543
  this.labelRenderer = null;
1538
1544
  this._app = null;
1539
1545
  this.resizeObserver = null;
@@ -1547,6 +1553,7 @@ class Viewport {
1547
1553
  if (viewportParam.elementId) {
1548
1554
  this._outerContainer = document.getElementById(viewportParam.elementId);
1549
1555
  }
1556
+ this.viewportParam = Object.assign({}, viewportParam);
1550
1557
  this.createRenderer(rendererParam);
1551
1558
  if (viewportParam.isLabelRendererNeeded) {
1552
1559
  this.createLabelRenderer();
@@ -1568,7 +1575,7 @@ class Viewport {
1568
1575
  this.setupPostProcess();
1569
1576
  });
1570
1577
  }
1571
- createRenderer(rendererParam) {
1578
+ async createRenderer(rendererParam) {
1572
1579
  if (this._outerContainer) {
1573
1580
  this._canvasContainer = document.createElement("div");
1574
1581
  this._canvasContainer.style.left = "0px";
@@ -1595,15 +1602,31 @@ class Viewport {
1595
1602
  renderP.logarithmicDepthBuffer = rendererParam.logarithmicDepthBuffer;
1596
1603
  renderP.samples = rendererParam.samples;
1597
1604
  renderP.colorBufferType = rendererParam.colorBufferType;
1598
- this._renderer = new webgpu.WebGPURenderer(renderP);
1599
- this._renderer.setPixelRatio(window.devicePixelRatio);
1600
- this._renderer.setSize(width, height);
1601
- this._renderer.shadowMap.enabled = rendererParam.shadowMapEnabled;
1602
- this._renderer.shadowMap.type = rendererParam.shadowMapType;
1603
- this._renderer.toneMapping = rendererParam.toneMapping;
1604
- this._renderer.toneMappingExposure = rendererParam.toneMappingExposure;
1605
- if (element) {
1606
- element.appendChild(this._renderer.domElement);
1605
+ if (this.viewportParam.usingWebGLRenderer) {
1606
+ this._webGLRenderer = new three.WebGLRenderer();
1607
+ this._webGLRenderer.setPixelRatio(window.devicePixelRatio);
1608
+ this._webGLRenderer.setSize(width, height);
1609
+ this._webGLRenderer.shadowMap.enabled = rendererParam.shadowMapEnabled;
1610
+ this._webGLRenderer.shadowMap.type = rendererParam.shadowMapType ? rendererParam.shadowMapType : three.PCFSoftShadowMap;
1611
+ this._webGLRenderer.toneMapping = rendererParam.toneMapping;
1612
+ this._webGLRenderer.toneMappingExposure = rendererParam.toneMappingExposure;
1613
+ if (element) {
1614
+ element.appendChild(this._webGLRenderer.domElement);
1615
+ }
1616
+ }
1617
+ else {
1618
+ this._renderer = new webgpu.WebGPURenderer(renderP);
1619
+ // WebGPU 需要异步初始化
1620
+ await this._renderer.init();
1621
+ this._renderer.setPixelRatio(window.devicePixelRatio);
1622
+ this._renderer.setSize(width, height);
1623
+ this._renderer.shadowMap.enabled = rendererParam.shadowMapEnabled;
1624
+ this._renderer.shadowMap.type = rendererParam.shadowMapType;
1625
+ this._renderer.toneMapping = rendererParam.toneMapping;
1626
+ this._renderer.toneMappingExposure = rendererParam.toneMappingExposure;
1627
+ if (element) {
1628
+ element.appendChild(this._renderer.domElement);
1629
+ }
1607
1630
  }
1608
1631
  }
1609
1632
  createLabelRenderer() {
@@ -1650,97 +1673,7 @@ class Viewport {
1650
1673
  this.setupPostProcess();
1651
1674
  }
1652
1675
  setupPostProcess() {
1653
- if (this.postProcessParam.steps.length === 0) {
1654
- this.destroyPostProcess();
1655
- this.markRenderStateDirty();
1656
- return;
1657
- }
1658
- if (!this.postProcessing) {
1659
- this.postProcessing = new webgpu.PostProcessing(this.renderer);
1660
- }
1661
- const scenePass = WebGPUPostProcessFactory.constructScenePass(this.app.world.scene, this.app.camera);
1662
- let finalNode = scenePass.getTextureNode('output');
1663
- this.postProcessParam.steps.forEach((step) => {
1664
- switch (step.type) {
1665
- case exports.PostProcessStepType.Bloom:
1666
- {
1667
- const bloomPass = WebGPUPostProcessFactory.constructBloomPass(scenePass, step);
1668
- //console.log("[PostProcess] BloomPass 构建完成");
1669
- finalNode = finalNode.add(bloomPass);
1670
- break;
1671
- }
1672
- case exports.PostProcessStepType.DepthOfField:
1673
- {
1674
- const dofPass = WebGPUPostProcessFactory.constructDOFPass(scenePass, step);
1675
- //console.log("[PostProcess] DOFPass 构建完成");
1676
- finalNode = finalNode.add(dofPass);
1677
- break;
1678
- }
1679
- case exports.PostProcessStepType.ScreenSpaceReflection:
1680
- {
1681
- console.warn("[PostProcess] SSR 目前存在技术问题,暂不支持。");
1682
- // const ssrPass = WebGPUPostProcessFactory.constructSSRPass(scenePass, step as SSRParam);
1683
- // console.log("[PostProcess] SSRPass 构建完成");
1684
- //finalNode = blendColor(finalNode, ssrPass);
1685
- break;
1686
- }
1687
- case exports.PostProcessStepType.GroundTruthAmbientOcclusion:
1688
- {
1689
- console.warn("[PostProcess] AO 目前存在技术问题,暂不支持。");
1690
- // const stepParam = step as GTAOParam
1691
- // const GTAOPass = WebGPUPostProcessFactory.constructGTAOPass(scenePass, stepParam);
1692
- // console.log("[PostProcess] GTAOPass 构建完成");
1693
- // if (stepParam.denoised)
1694
- // {
1695
- // const denoiseGTAOPass = WebGPUPostProcessFactory.constructGTAODenoisePass(scenePass, GTAOPass, stepParam);
1696
- // console.log("[PostProcess] GTAODenoisePass 构建完成");
1697
- // finalNode = denoiseGTAOPass.mul(finalNode);
1698
- // }
1699
- // else
1700
- // {
1701
- // finalNode = GTAOPass.getTextureNode().mul(finalNode);
1702
- // }
1703
- break;
1704
- }
1705
- case exports.PostProcessStepType.Outline:
1706
- {
1707
- const outlineParam = step;
1708
- const outlinePass = WebGPUPostProcessFactory.constructOutlinePass(this.app.world.scene, scenePass.camera, this.outlineObjects, outlineParam);
1709
- const { visibleEdge, hiddenEdge } = outlinePass;
1710
- const pulsePeriod = tsl.uniform(outlineParam.pulsePeriod);
1711
- const period = tsl.time.div(pulsePeriod).mul(2);
1712
- const osc = tsl.oscSine(period).mul(.5).add(.5);
1713
- const outlineColor = visibleEdge.mul(tsl.uniform(new webgpu.Color(outlineParam.visibleEdgeColor))).add(hiddenEdge.mul(tsl.uniform(new webgpu.Color(outlineParam.hiddenEdgeColor)))).mul(outlineParam.edgeStrength);
1714
- const outlinePulse = pulsePeriod.greaterThan(0).select(outlineColor.mul(osc), outlineColor);
1715
- // if(!this.denoiseOutlinePass)
1716
- // {
1717
- // this.denoiseOutlinePass = WebGPUPostProcessFactory.constructDenoisePass(this.scenePass, outlinePulse, DefaultDenoiseParam);
1718
- // }
1719
- // outlinePulse = this.denoiseOutlinePass.mul(outlinePulse)
1720
- // finalNode = this.denoiseOutlinePass.mul(outlinePulse).add(finalNode);
1721
- finalNode = outlinePulse.add(finalNode);
1722
- //console.log("[PostProcess] OutlinePass 构建完成");
1723
- break;
1724
- }
1725
- case exports.PostProcessStepType.Antialiasing:
1726
- {
1727
- const aaParam = step;
1728
- if (aaParam.method === "fxaa") {
1729
- finalNode = WebGPUPostProcessFactory.constructFXAAPass(finalNode);
1730
- //console.log("[PostProcess] FXAAPass 构建完成");
1731
- }
1732
- if (aaParam.method === "smaa") {
1733
- finalNode = WebGPUPostProcessFactory.constructSMAAPass(finalNode);
1734
- //console.log("[PostProcess] SMAAPass 构建完成");
1735
- }
1736
- break;
1737
- }
1738
- }
1739
- });
1740
- this.postProcessing.outputNode = finalNode;
1741
- this.postProcessing.needsUpdate = true;
1742
- //console.log("[PostProcess] setup complete", this.postProcessParam.steps);
1743
- this.markRenderStateDirty();
1676
+ return;
1744
1677
  }
1745
1678
  updatePostProcess(steps) {
1746
1679
  this.postProcessParam.steps = steps;
@@ -1825,7 +1758,7 @@ class Viewport {
1825
1758
  return;
1826
1759
  }
1827
1760
  if (this.postProcessing) {
1828
- this.postProcessing.render();
1761
+ this.postProcessing.renderAsync();
1829
1762
  }
1830
1763
  else {
1831
1764
  this.renderer.render(this.app.world.scene, this.app.camera);
@@ -1842,7 +1775,13 @@ class Viewport {
1842
1775
  await this.postProcessing.renderAsync();
1843
1776
  }
1844
1777
  else {
1845
- await this.renderer.renderAsync(this.app.world.scene, this.app.camera);
1778
+ if (this._renderer) {
1779
+ await this._renderer.renderAsync(this.app.world.scene, this.app.camera);
1780
+ }
1781
+ else if (this._webGLRenderer) {
1782
+ console.log("render with gl");
1783
+ this._webGLRenderer.render(this.app.world.scene, this.app.camera);
1784
+ }
1846
1785
  }
1847
1786
  // 检查 renderer.domElement 的尺寸
1848
1787
  const sourceWidth = this.renderer.domElement.width;
@@ -2151,13 +2090,7 @@ class Controller {
2151
2090
  this.pawn.enabled = isPawnEnabled;
2152
2091
  }
2153
2092
  init() {
2154
- if (this.viewPort.canvas) {
2155
- this.viewPort.canvas.addEventListener("pointermove", this.onPointerMove);
2156
- this.viewPort.canvas.addEventListener("pointerenter", this.onPointerEnter);
2157
- this.viewPort.canvas.addEventListener("pointerleave", this.onPointerLeave);
2158
- this.viewPort.canvas.addEventListener("pointerup", this.onPointerUp);
2159
- this.viewPort.canvas.addEventListener("pointerdown", this.onPointerDown);
2160
- }
2093
+ if (this.viewPort.canvas) ;
2161
2094
  }
2162
2095
  tick(deltaTime) {
2163
2096
  this.pawn.tick(deltaTime);
@@ -2167,13 +2100,7 @@ class Controller {
2167
2100
  clearTimeout(this.leftClickTimer);
2168
2101
  this.leftClickTimer = null;
2169
2102
  }
2170
- if (this.viewPort.canvas) {
2171
- this.viewPort.canvas.removeEventListener("pointermove", this.onPointerMove);
2172
- this.viewPort.canvas.removeEventListener("pointerenter", this.onPointerEnter);
2173
- this.viewPort.canvas.removeEventListener("pointerleave", this.onPointerLeave);
2174
- this.viewPort.canvas.removeEventListener("pointerup", this.onPointerUp);
2175
- this.viewPort.canvas.removeEventListener("pointerdown", this.onPointerDown);
2176
- }
2103
+ if (this.viewPort.canvas) ;
2177
2104
  this.pawn.unpossess();
2178
2105
  this.pawn.destroy();
2179
2106
  this._pawn = null;
@@ -2295,6 +2222,14 @@ class Controller {
2295
2222
  focusTo(targetPos, targetQuat, distance, time, onGoing = null, onFinished = null) {
2296
2223
  this.pawn.focusTo(targetPos, targetQuat, distance, time, onGoing, onFinished);
2297
2224
  }
2225
+ setPawn(pawn) {
2226
+ if (this._pawn) {
2227
+ this._pawn.unpossess();
2228
+ this._pawn.destroy();
2229
+ }
2230
+ this._pawn = pawn;
2231
+ this._pawn.possess();
2232
+ }
2298
2233
  }
2299
2234
 
2300
2235
  class CameraFactory {
@@ -2320,7 +2255,7 @@ class CameraFactory {
2320
2255
  catch (error) {
2321
2256
  console.warn("[CameraFactory]Error occurred while creating camera: ", error);
2322
2257
  console.warn("[CameraFactory]Create default perspective camera instead");
2323
- return new webgpu.PerspectiveCamera(50, 1, 0.1, 1000);
2258
+ return new webgpu.PerspectiveCamera(50, 1, 0.1, 100000);
2324
2259
  }
2325
2260
  }
2326
2261
  static updataCamera(param, camera) {
@@ -2334,6 +2269,7 @@ class CameraFactory {
2334
2269
  camera.far = data.far;
2335
2270
  camera.fov = data.fov;
2336
2271
  camera.aspect = data.aspect;
2272
+ camera.updateProjectionMatrix();
2337
2273
  return camera;
2338
2274
  }
2339
2275
  return new webgpu.PerspectiveCamera(data.fov, data.aspect, data.near, data.far);
@@ -2348,6 +2284,7 @@ class CameraFactory {
2348
2284
  camera.right = data.right;
2349
2285
  camera.top = data.top;
2350
2286
  camera.bottom = data.bottom;
2287
+ camera.updateProjectionMatrix();
2351
2288
  return camera;
2352
2289
  }
2353
2290
  return new webgpu.OrthographicCamera(data.left, data.right, data.top, data.bottom, data.near, data.far);
@@ -2368,7 +2305,7 @@ class CameraFactory {
2368
2305
 
2369
2306
  const DefaultPerspectiveCameraParam = {
2370
2307
  near: 0.1,
2371
- far: 1000,
2308
+ far: 10000,
2372
2309
  type: "Perspective",
2373
2310
  fov: 50,
2374
2311
  aspect: 1,
@@ -2900,7 +2837,14 @@ const DefaultWorldParam = {
2900
2837
  levelActorClass: LevelActor,
2901
2838
  };
2902
2839
 
2840
+ /** 动画循环启动延迟时间(毫秒) */
2841
+ const ANIMATION_START_DELAY = 100;
2842
+ /**
2843
+ * Three.js应用程序主类
2844
+ * 负责管理场景、视口、控制器和资源
2845
+ */
2903
2846
  class ThreeJsApp {
2847
+ // ========== 公共访问器 ==========
2904
2848
  get camera() {
2905
2849
  return this._camera;
2906
2850
  }
@@ -2925,67 +2869,132 @@ class ThreeJsApp {
2925
2869
  get onCameraChangedDelegate() {
2926
2870
  return this._onCameraChangedDelegate;
2927
2871
  }
2872
+ /**
2873
+ * 构造ThreeJs应用程序实例
2874
+ * @param appParam 应用程序参数配置
2875
+ */
2928
2876
  constructor(appParam = DefaultAppParam) {
2877
+ var _a, _b, _c, _d, _e, _f;
2878
+ // ========== 私有字段 ==========
2879
+ this.animationFrameHandle = 0;
2929
2880
  this._tickingFunctions = [];
2930
2881
  this._appParam = { viewportParam: DefaultViewportParam };
2931
2882
  this._onCameraChangedDelegate = new Delegate();
2932
- this._appParam.cameraParam = appParam.cameraParam ? appParam.cameraParam : DefaultCameraParam;
2933
- this._appParam.renderParam = appParam.renderParam ? appParam.renderParam : DefaultRendererParameters;
2934
- this._appParam.postProcessParam = appParam.postProcessParam ? appParam.postProcessParam : DefaultPostProcessParam;
2935
- this._appParam.viewportParam = appParam.viewportParam ? appParam.viewportParam : DefaultViewportParam;
2936
- this._appParam.classes = appParam.classes ? appParam.classes : {
2883
+ // 初始化应用参数(使用空值合并运算符简化默认值处理)
2884
+ this._appParam.cameraParam = (_a = appParam.cameraParam) !== null && _a !== void 0 ? _a : DefaultCameraParam;
2885
+ this._appParam.renderParam = (_b = appParam.renderParam) !== null && _b !== void 0 ? _b : DefaultRendererParameters;
2886
+ this._appParam.postProcessParam = (_c = appParam.postProcessParam) !== null && _c !== void 0 ? _c : DefaultPostProcessParam;
2887
+ this._appParam.viewportParam = (_d = appParam.viewportParam) !== null && _d !== void 0 ? _d : DefaultViewportParam;
2888
+ this._appParam.worldParam = (_e = appParam.worldParam) !== null && _e !== void 0 ? _e : DefaultWorldParam;
2889
+ this._appParam.isRenderEveryFrame = appParam.isRenderEveryFrame;
2890
+ this._appParam.classes = (_f = appParam.classes) !== null && _f !== void 0 ? _f : {
2937
2891
  assetManagerClass: AssetManager,
2938
2892
  controllerClass: Controller,
2939
2893
  worldClass: World,
2940
2894
  viewportClass: Viewport,
2941
2895
  };
2942
- this._appParam.isRenderEveryFrame = appParam.isRenderEveryFrame;
2896
+ // 初始化核心组件
2943
2897
  this._clock = new webgpu.Clock();
2944
2898
  this._camera = CameraFactory.createCamera(this._appParam.cameraParam);
2945
- this._world = new this._appParam.classes.worldClass(this, this._appParam.worldParam ? this._appParam.worldParam : DefaultWorldParam);
2899
+ this._world = new this._appParam.classes.worldClass(this, this._appParam.worldParam);
2946
2900
  this._viewport = new this._appParam.classes.viewportClass(this, this._appParam.viewportParam, this._appParam.renderParam, this._appParam.postProcessParam);
2947
2901
  this._controller = new this._appParam.classes.controllerClass(this);
2948
2902
  this._assetManager = new this._appParam.classes.assetManagerClass(this);
2949
- this.viewport.renderer.setAnimationLoop(() => {
2950
- const delta = this._clock.getDelta();
2951
- this.tick(delta);
2952
- });
2953
2903
  this.postConstruct();
2904
+ this.startAnimationLoop();
2954
2905
  }
2906
+ /**
2907
+ * 构造后初始化钩子
2908
+ * 按顺序初始化控制器、世界和视口
2909
+ */
2955
2910
  postConstruct() {
2956
2911
  this.controller.init();
2957
2912
  this.world.init();
2958
2913
  this.viewport.init();
2959
2914
  }
2915
+ /**
2916
+ * 公共初始化方法
2917
+ * 可由子类重写以添加自定义初始化逻辑
2918
+ */
2960
2919
  init() {
2961
- }
2920
+ // 预留给子类实现
2921
+ }
2922
+ /**
2923
+ * 启动动画循环
2924
+ * 使用延迟启动以确保所有组件完全初始化
2925
+ */
2926
+ startAnimationLoop() {
2927
+ const tick = () => {
2928
+ this.animationFrameHandle = requestAnimationFrame(tick);
2929
+ try {
2930
+ const delta = this._clock.getDelta();
2931
+ this.tick(delta);
2932
+ }
2933
+ catch (error) {
2934
+ console.error('动画循环错误:', error);
2935
+ }
2936
+ };
2937
+ setTimeout(() => {
2938
+ tick();
2939
+ }, ANIMATION_START_DELAY);
2940
+ }
2941
+ /**
2942
+ * 每帧更新方法
2943
+ * @param deltaTime 距离上一帧的时间增量(秒)
2944
+ */
2962
2945
  tick(deltaTime) {
2963
2946
  this._controller.tick(deltaTime);
2964
2947
  this.world.tick(deltaTime);
2948
+ // 执行所有注册的tick函数
2965
2949
  this._tickingFunctions.forEach(func => {
2966
2950
  func(deltaTime);
2967
2951
  });
2952
+ // 根据配置决定是否每帧都渲染
2968
2953
  if (this._appParam.isRenderEveryFrame) {
2969
2954
  this.viewport.markRenderStateDirty();
2970
2955
  }
2971
2956
  this.viewport.render();
2972
2957
  }
2958
+ /**
2959
+ * 添加每帧执行的函数
2960
+ * @param func 接收deltaTime参数的回调函数
2961
+ */
2973
2962
  addTickingFunction(func) {
2974
2963
  this._tickingFunctions.push(func);
2975
2964
  }
2965
+ /**
2966
+ * 移除已注册的tick函数
2967
+ * @param func 要移除的函数引用
2968
+ */
2976
2969
  removeTickingFunction(func) {
2977
2970
  const index = this._tickingFunctions.indexOf(func);
2978
2971
  if (index >= 0) {
2979
2972
  this._tickingFunctions.splice(index, 1);
2980
2973
  }
2981
2974
  }
2975
+ /**
2976
+ * 销毁应用程序并清理所有资源
2977
+ */
2982
2978
  destroy() {
2979
+ // 停止动画循环
2980
+ if (this.animationFrameHandle) {
2981
+ cancelAnimationFrame(this.animationFrameHandle);
2982
+ this.animationFrameHandle = 0;
2983
+ }
2984
+ // 清理委托
2983
2985
  this.onCameraChangedDelegate.clear();
2986
+ // 销毁各个组件
2984
2987
  this.controller.destroy();
2985
2988
  this.world.destroy();
2986
2989
  this.viewport.destroy();
2987
2990
  this._assetManager.clearAssets();
2991
+ // 清空tick函数列表
2992
+ this._tickingFunctions = [];
2988
2993
  }
2994
+ /**
2995
+ * 更新相机参数
2996
+ * @param param 新的相机参数
2997
+ */
2989
2998
  updateCamera(param) {
2990
2999
  const previousCam = this.camera;
2991
3000
  this._camera = CameraFactory.updataCamera(param, this.camera);
@@ -2996,16 +3005,31 @@ class ThreeJsApp {
2996
3005
  this._camera.updateProjectionMatrix();
2997
3006
  this.viewport.markRenderStateDirty();
2998
3007
  }
3008
+ /**
3009
+ * 窗口大小改变时的处理
3010
+ * @param width 新的宽度
3011
+ * @param height 新的高度
3012
+ */
2999
3013
  onWindowResize(width, height) {
3000
3014
  if (this.camera instanceof webgpu.PerspectiveCamera) {
3001
3015
  this.camera.aspect = width / height;
3002
3016
  }
3003
- // if(this.camera instanceof OrthographicCamera)
3004
- // {
3005
- // // to do
3017
+ // TODO: 实现正交相机的窗口缩放处理
3018
+ // if (this.camera instanceof OrthographicCamera) {
3019
+ // const aspect = width / height;
3020
+ // this.camera.left = -width / 2;
3021
+ // this.camera.right = width / 2;
3022
+ // this.camera.top = height / 2;
3023
+ // this.camera.bottom = -height / 2;
3006
3024
  // }
3007
3025
  this.camera.updateProjectionMatrix();
3008
3026
  }
3027
+ /**
3028
+ * 将当前场景渲染为图片
3029
+ * @param width 图片宽度,默认1024
3030
+ * @param height 图片高度,默认1024
3031
+ * @returns 图片的DataURL
3032
+ */
3009
3033
  async renderAsImage(width = 1024, height = 1024) {
3010
3034
  return await this.viewport.renderAsImage(width, height);
3011
3035
  }
@@ -3137,7 +3161,7 @@ class AmbientLightComponent extends LightComponent {
3137
3161
  this.threeObject.intensity = intensity;
3138
3162
  }
3139
3163
  createDefaultObject() {
3140
- return new webgpu.AmbientLight(0xffffff, 10);
3164
+ return new three.AmbientLight(0xffffff, 10);
3141
3165
  }
3142
3166
  setPosition(...args) {
3143
3167
  if (args.length === 1) {
@@ -3181,7 +3205,7 @@ class AmbientLightActor extends Actor {
3181
3205
  }
3182
3206
 
3183
3207
  class BoxComponent extends MeshComponent {
3184
- constructor(app, width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1, material = new webgpu.MeshStandardMaterial(), uuid) {
3208
+ constructor(app, width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1, material = new webgpu.MeshStandardMaterial({ color: 0x00ff00 }), uuid) {
3185
3209
  super(app, new webgpu.BoxGeometry(width, height, depth, widthSegments, heightSegments, depthSegments), material, uuid);
3186
3210
  }
3187
3211
  }
@@ -3328,6 +3352,120 @@ class LabelComponent extends SceneComponent {
3328
3352
  // labelStyle.style.fontSize = "10px";
3329
3353
  // labelStyle.style.pointerEvents = 'auto';
3330
3354
 
3355
+ class CurveComponent extends SceneComponent {
3356
+ get threeObject() {
3357
+ if (!this.obj) {
3358
+ throw new Error("threeObject is null");
3359
+ }
3360
+ return this.obj;
3361
+ }
3362
+ set threeObject(newThreeObject) {
3363
+ this.obj = newThreeObject;
3364
+ if (this.obj) {
3365
+ this.obj.userData["LYObject"] = this;
3366
+ }
3367
+ }
3368
+ get material() {
3369
+ return this.threeObject.material;
3370
+ }
3371
+ constructor(app, points, setup = { color: 0xffffff }, bCreateLine = true, uuid) {
3372
+ var _a, _b, _c;
3373
+ super(app, uuid);
3374
+ this.closed = (_a = setup.closed) !== null && _a !== void 0 ? _a : false;
3375
+ this.curveType = (_b = setup.type) !== null && _b !== void 0 ? _b : 'centripetal';
3376
+ this.tension = (_c = setup.tension) !== null && _c !== void 0 ? _c : 0;
3377
+ this.sourcePoints = points;
3378
+ this.curve = new three.CatmullRomCurve3(points, this.closed, this.curveType, this.tension);
3379
+ this.points = this.curve.getPoints(points.length * (this.tension === 0 ? 1 : 10) - 1);
3380
+ this.material.color = new three.Color(setup.color);
3381
+ this.bCreateLine = bCreateLine;
3382
+ this.name = "CurveComponent";
3383
+ if (this.bCreateLine) {
3384
+ this.createLine();
3385
+ }
3386
+ }
3387
+ isValid() {
3388
+ return this.threeObject != null;
3389
+ }
3390
+ createDefaultObject() {
3391
+ // 创建默认材质
3392
+ const material = new three.LineBasicMaterial({
3393
+ color: 0xffffff,
3394
+ transparent: true,
3395
+ opacity: 1
3396
+ });
3397
+ // 创建空的几何体和线对象
3398
+ const geometry = new three.BufferGeometry();
3399
+ const line = new three.Line(geometry, material);
3400
+ return line;
3401
+ }
3402
+ resetPoints(points) {
3403
+ this.sourcePoints = points;
3404
+ this.curve = new three.CatmullRomCurve3(points, this.closed, this.curveType, this.tension);
3405
+ this.points = this.curve.getPoints(points.length * (this.tension === 0 ? 1 : 10) - 1);
3406
+ if (this.bCreateLine) {
3407
+ this.createLine();
3408
+ }
3409
+ }
3410
+ createLine() {
3411
+ const positions = [];
3412
+ for (let i = 0; i < this.points.length; ++i) {
3413
+ positions.push(this.points[i].x);
3414
+ positions.push(this.points[i].y);
3415
+ positions.push(this.points[i].z);
3416
+ }
3417
+ const geometry = this.threeObject.geometry;
3418
+ geometry.setAttribute('position', new three.Float32BufferAttribute(positions, 3));
3419
+ }
3420
+ destroy() {
3421
+ if (this.isValid() && this.threeObject) {
3422
+ if (this.threeObject.geometry) {
3423
+ this.threeObject.geometry.dispose();
3424
+ }
3425
+ if (this.material) {
3426
+ this.material.dispose();
3427
+ }
3428
+ }
3429
+ super.destroy();
3430
+ }
3431
+ get SourcePoints() {
3432
+ return this.sourcePoints;
3433
+ }
3434
+ get Curve() {
3435
+ return this.curve;
3436
+ }
3437
+ get Points() {
3438
+ return this.points;
3439
+ }
3440
+ getPointAt(u) {
3441
+ return this.curve.getPointAt(u);
3442
+ }
3443
+ getTangentAt(u) {
3444
+ return this.curve.getTangentAt(u);
3445
+ }
3446
+ // 返回曲线在参数 u 处的世界坐标点
3447
+ getWorldPointAt(u) {
3448
+ const p = this.curve.getPointAt(u).clone();
3449
+ if (this.obj) {
3450
+ this.obj.updateMatrixWorld(true);
3451
+ return this.localToWorld(p);
3452
+ }
3453
+ return p;
3454
+ }
3455
+ // 返回曲线在参数 u 处的世界坐标系下的单位切线方向
3456
+ getWorldTangentAt(u) {
3457
+ const t = this.curve.getTangentAt(u).clone();
3458
+ if (this.obj) {
3459
+ this.obj.updateMatrixWorld(true);
3460
+ t.transformDirection(this.obj.matrixWorld);
3461
+ }
3462
+ return t;
3463
+ }
3464
+ getLength() {
3465
+ return this.curve.getLength();
3466
+ }
3467
+ }
3468
+
3331
3469
  const DefaultBloomParam = {
3332
3470
  type: exports.PostProcessStepType.Bloom,
3333
3471
  threshold: 0,
@@ -3609,6 +3747,7 @@ exports.AssetManager = AssetManager;
3609
3747
  exports.BoxActor = BoxActor;
3610
3748
  exports.BoxComponent = BoxComponent;
3611
3749
  exports.Controller = Controller;
3750
+ exports.CurveComponent = CurveComponent;
3612
3751
  exports.DefaultAAParams = DefaultAAParams;
3613
3752
  exports.DefaultAppParam = DefaultAppParam;
3614
3753
  exports.DefaultBloomParam = DefaultBloomParam;
@@ -3636,6 +3775,7 @@ exports.LevelComponent = LevelComponent;
3636
3775
  exports.MaterialAssetPointer = MaterialAssetPointer;
3637
3776
  exports.MeshComponent = MeshComponent;
3638
3777
  exports.Orbital = Orbital;
3778
+ exports.Pawn = Pawn;
3639
3779
  exports.PlaneActor = PlaneActor;
3640
3780
  exports.PlaneComponent = PlaneComponent;
3641
3781
  exports.SceneComponent = SceneComponent;