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.
@@ -1,6 +1,7 @@
1
- import { MathUtils, Object3D, Vector3, Box3, Quaternion, Euler, Matrix4, Mesh, LoadingManager, BufferGeometry, Texture, FileLoader, Material, NearestFilter, WebGPURenderer, PostProcessing, Color, Vector2, Raycaster, OrthographicCamera, PerspectiveCamera, Clock, DirectionalLight, AmbientLight, MeshStandardMaterial, BoxGeometry, MeshBasicMaterial, PlaneGeometry, SphereGeometry } from 'three/webgpu';
1
+ import { MathUtils, Object3D, Vector3, Box3, Quaternion, Euler, Matrix4, Mesh, LoadingManager, BufferGeometry, Texture, FileLoader, Material, NearestFilter, WebGPURenderer, Vector2, Raycaster, OrthographicCamera, PerspectiveCamera, Clock, DirectionalLight, MeshStandardMaterial, BoxGeometry, MeshBasicMaterial, PlaneGeometry, SphereGeometry } from 'three/webgpu';
2
2
  import { GLTFLoader, DRACOLoader, CSS2DRenderer, OrbitControls } from 'three/examples/jsm/Addons.js';
3
- import { pass, mrt, output, uniform, metalness, transformedNormalView, time, oscSine } from 'three/tsl';
3
+ import { pass, mrt, output, uniform, metalness, transformedNormalView } from 'three/tsl';
4
+ import { WebGLRenderer, PCFSoftShadowMap, Scene, AmbientLight, CatmullRomCurve3, Color, LineBasicMaterial, BufferGeometry as BufferGeometry$1, Line, Float32BufferAttribute } from 'three';
4
5
  import { dof } from 'three/addons/tsl/display/DepthOfFieldNode.js';
5
6
  import { bloom } from 'three/examples/jsm/tsl/display/BloomNode.js';
6
7
  import { denoise } from 'three/examples/jsm/tsl/display/DenoiseNode.js';
@@ -9,7 +10,6 @@ import { ao } from 'three/examples/jsm/tsl/display/GTAONode.js';
9
10
  import { outline } from 'three/examples/jsm/tsl/display/OutlineNode.js';
10
11
  import { smaa } from 'three/examples/jsm/tsl/display/SMAANode.js';
11
12
  import { gsap } from 'gsap';
12
- import { Scene } from 'three';
13
13
  import { SkyMesh } from 'three/examples/jsm/objects/SkyMesh.js';
14
14
  import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer.js';
15
15
  import { PointerLockControls } from 'three/examples/jsm/controls/PointerLockControls.js';
@@ -1519,7 +1519,12 @@ class Viewport {
1519
1519
  }
1520
1520
  get renderer() {
1521
1521
  if (!this._renderer) {
1522
- throw Error("Renderer is not initialized");
1522
+ if (this._webGLRenderer) {
1523
+ return this._webGLRenderer;
1524
+ }
1525
+ else {
1526
+ throw Error("Renderer is not initialized");
1527
+ }
1523
1528
  }
1524
1529
  return this._renderer;
1525
1530
  }
@@ -1532,6 +1537,7 @@ class Viewport {
1532
1537
  constructor(app, viewportParam, rendererParam, postProcessParam) {
1533
1538
  this._uiDom = null;
1534
1539
  this._renderer = null;
1540
+ this._webGLRenderer = null;
1535
1541
  this.labelRenderer = null;
1536
1542
  this._app = null;
1537
1543
  this.resizeObserver = null;
@@ -1545,6 +1551,7 @@ class Viewport {
1545
1551
  if (viewportParam.elementId) {
1546
1552
  this._outerContainer = document.getElementById(viewportParam.elementId);
1547
1553
  }
1554
+ this.viewportParam = Object.assign({}, viewportParam);
1548
1555
  this.createRenderer(rendererParam);
1549
1556
  if (viewportParam.isLabelRendererNeeded) {
1550
1557
  this.createLabelRenderer();
@@ -1566,7 +1573,7 @@ class Viewport {
1566
1573
  this.setupPostProcess();
1567
1574
  });
1568
1575
  }
1569
- createRenderer(rendererParam) {
1576
+ async createRenderer(rendererParam) {
1570
1577
  if (this._outerContainer) {
1571
1578
  this._canvasContainer = document.createElement("div");
1572
1579
  this._canvasContainer.style.left = "0px";
@@ -1593,15 +1600,31 @@ class Viewport {
1593
1600
  renderP.logarithmicDepthBuffer = rendererParam.logarithmicDepthBuffer;
1594
1601
  renderP.samples = rendererParam.samples;
1595
1602
  renderP.colorBufferType = rendererParam.colorBufferType;
1596
- this._renderer = new WebGPURenderer(renderP);
1597
- this._renderer.setPixelRatio(window.devicePixelRatio);
1598
- this._renderer.setSize(width, height);
1599
- this._renderer.shadowMap.enabled = rendererParam.shadowMapEnabled;
1600
- this._renderer.shadowMap.type = rendererParam.shadowMapType;
1601
- this._renderer.toneMapping = rendererParam.toneMapping;
1602
- this._renderer.toneMappingExposure = rendererParam.toneMappingExposure;
1603
- if (element) {
1604
- element.appendChild(this._renderer.domElement);
1603
+ if (this.viewportParam.usingWebGLRenderer) {
1604
+ this._webGLRenderer = new WebGLRenderer();
1605
+ this._webGLRenderer.setPixelRatio(window.devicePixelRatio);
1606
+ this._webGLRenderer.setSize(width, height);
1607
+ this._webGLRenderer.shadowMap.enabled = rendererParam.shadowMapEnabled;
1608
+ this._webGLRenderer.shadowMap.type = rendererParam.shadowMapType ? rendererParam.shadowMapType : PCFSoftShadowMap;
1609
+ this._webGLRenderer.toneMapping = rendererParam.toneMapping;
1610
+ this._webGLRenderer.toneMappingExposure = rendererParam.toneMappingExposure;
1611
+ if (element) {
1612
+ element.appendChild(this._webGLRenderer.domElement);
1613
+ }
1614
+ }
1615
+ else {
1616
+ this._renderer = new WebGPURenderer(renderP);
1617
+ // WebGPU 需要异步初始化
1618
+ await this._renderer.init();
1619
+ this._renderer.setPixelRatio(window.devicePixelRatio);
1620
+ this._renderer.setSize(width, height);
1621
+ this._renderer.shadowMap.enabled = rendererParam.shadowMapEnabled;
1622
+ this._renderer.shadowMap.type = rendererParam.shadowMapType;
1623
+ this._renderer.toneMapping = rendererParam.toneMapping;
1624
+ this._renderer.toneMappingExposure = rendererParam.toneMappingExposure;
1625
+ if (element) {
1626
+ element.appendChild(this._renderer.domElement);
1627
+ }
1605
1628
  }
1606
1629
  }
1607
1630
  createLabelRenderer() {
@@ -1648,97 +1671,7 @@ class Viewport {
1648
1671
  this.setupPostProcess();
1649
1672
  }
1650
1673
  setupPostProcess() {
1651
- if (this.postProcessParam.steps.length === 0) {
1652
- this.destroyPostProcess();
1653
- this.markRenderStateDirty();
1654
- return;
1655
- }
1656
- if (!this.postProcessing) {
1657
- this.postProcessing = new PostProcessing(this.renderer);
1658
- }
1659
- const scenePass = WebGPUPostProcessFactory.constructScenePass(this.app.world.scene, this.app.camera);
1660
- let finalNode = scenePass.getTextureNode('output');
1661
- this.postProcessParam.steps.forEach((step) => {
1662
- switch (step.type) {
1663
- case PostProcessStepType.Bloom:
1664
- {
1665
- const bloomPass = WebGPUPostProcessFactory.constructBloomPass(scenePass, step);
1666
- //console.log("[PostProcess] BloomPass 构建完成");
1667
- finalNode = finalNode.add(bloomPass);
1668
- break;
1669
- }
1670
- case PostProcessStepType.DepthOfField:
1671
- {
1672
- const dofPass = WebGPUPostProcessFactory.constructDOFPass(scenePass, step);
1673
- //console.log("[PostProcess] DOFPass 构建完成");
1674
- finalNode = finalNode.add(dofPass);
1675
- break;
1676
- }
1677
- case PostProcessStepType.ScreenSpaceReflection:
1678
- {
1679
- console.warn("[PostProcess] SSR 目前存在技术问题,暂不支持。");
1680
- // const ssrPass = WebGPUPostProcessFactory.constructSSRPass(scenePass, step as SSRParam);
1681
- // console.log("[PostProcess] SSRPass 构建完成");
1682
- //finalNode = blendColor(finalNode, ssrPass);
1683
- break;
1684
- }
1685
- case PostProcessStepType.GroundTruthAmbientOcclusion:
1686
- {
1687
- console.warn("[PostProcess] AO 目前存在技术问题,暂不支持。");
1688
- // const stepParam = step as GTAOParam
1689
- // const GTAOPass = WebGPUPostProcessFactory.constructGTAOPass(scenePass, stepParam);
1690
- // console.log("[PostProcess] GTAOPass 构建完成");
1691
- // if (stepParam.denoised)
1692
- // {
1693
- // const denoiseGTAOPass = WebGPUPostProcessFactory.constructGTAODenoisePass(scenePass, GTAOPass, stepParam);
1694
- // console.log("[PostProcess] GTAODenoisePass 构建完成");
1695
- // finalNode = denoiseGTAOPass.mul(finalNode);
1696
- // }
1697
- // else
1698
- // {
1699
- // finalNode = GTAOPass.getTextureNode().mul(finalNode);
1700
- // }
1701
- break;
1702
- }
1703
- case PostProcessStepType.Outline:
1704
- {
1705
- const outlineParam = step;
1706
- const outlinePass = WebGPUPostProcessFactory.constructOutlinePass(this.app.world.scene, scenePass.camera, this.outlineObjects, outlineParam);
1707
- const { visibleEdge, hiddenEdge } = outlinePass;
1708
- const pulsePeriod = uniform(outlineParam.pulsePeriod);
1709
- const period = time.div(pulsePeriod).mul(2);
1710
- const osc = oscSine(period).mul(.5).add(.5);
1711
- const outlineColor = visibleEdge.mul(uniform(new Color(outlineParam.visibleEdgeColor))).add(hiddenEdge.mul(uniform(new Color(outlineParam.hiddenEdgeColor)))).mul(outlineParam.edgeStrength);
1712
- const outlinePulse = pulsePeriod.greaterThan(0).select(outlineColor.mul(osc), outlineColor);
1713
- // if(!this.denoiseOutlinePass)
1714
- // {
1715
- // this.denoiseOutlinePass = WebGPUPostProcessFactory.constructDenoisePass(this.scenePass, outlinePulse, DefaultDenoiseParam);
1716
- // }
1717
- // outlinePulse = this.denoiseOutlinePass.mul(outlinePulse)
1718
- // finalNode = this.denoiseOutlinePass.mul(outlinePulse).add(finalNode);
1719
- finalNode = outlinePulse.add(finalNode);
1720
- //console.log("[PostProcess] OutlinePass 构建完成");
1721
- break;
1722
- }
1723
- case PostProcessStepType.Antialiasing:
1724
- {
1725
- const aaParam = step;
1726
- if (aaParam.method === "fxaa") {
1727
- finalNode = WebGPUPostProcessFactory.constructFXAAPass(finalNode);
1728
- //console.log("[PostProcess] FXAAPass 构建完成");
1729
- }
1730
- if (aaParam.method === "smaa") {
1731
- finalNode = WebGPUPostProcessFactory.constructSMAAPass(finalNode);
1732
- //console.log("[PostProcess] SMAAPass 构建完成");
1733
- }
1734
- break;
1735
- }
1736
- }
1737
- });
1738
- this.postProcessing.outputNode = finalNode;
1739
- this.postProcessing.needsUpdate = true;
1740
- //console.log("[PostProcess] setup complete", this.postProcessParam.steps);
1741
- this.markRenderStateDirty();
1674
+ return;
1742
1675
  }
1743
1676
  updatePostProcess(steps) {
1744
1677
  this.postProcessParam.steps = steps;
@@ -1823,7 +1756,7 @@ class Viewport {
1823
1756
  return;
1824
1757
  }
1825
1758
  if (this.postProcessing) {
1826
- this.postProcessing.render();
1759
+ this.postProcessing.renderAsync();
1827
1760
  }
1828
1761
  else {
1829
1762
  this.renderer.render(this.app.world.scene, this.app.camera);
@@ -1840,7 +1773,13 @@ class Viewport {
1840
1773
  await this.postProcessing.renderAsync();
1841
1774
  }
1842
1775
  else {
1843
- await this.renderer.renderAsync(this.app.world.scene, this.app.camera);
1776
+ if (this._renderer) {
1777
+ await this._renderer.renderAsync(this.app.world.scene, this.app.camera);
1778
+ }
1779
+ else if (this._webGLRenderer) {
1780
+ console.log("render with gl");
1781
+ this._webGLRenderer.render(this.app.world.scene, this.app.camera);
1782
+ }
1844
1783
  }
1845
1784
  // 检查 renderer.domElement 的尺寸
1846
1785
  const sourceWidth = this.renderer.domElement.width;
@@ -2149,13 +2088,7 @@ class Controller {
2149
2088
  this.pawn.enabled = isPawnEnabled;
2150
2089
  }
2151
2090
  init() {
2152
- if (this.viewPort.canvas) {
2153
- this.viewPort.canvas.addEventListener("pointermove", this.onPointerMove);
2154
- this.viewPort.canvas.addEventListener("pointerenter", this.onPointerEnter);
2155
- this.viewPort.canvas.addEventListener("pointerleave", this.onPointerLeave);
2156
- this.viewPort.canvas.addEventListener("pointerup", this.onPointerUp);
2157
- this.viewPort.canvas.addEventListener("pointerdown", this.onPointerDown);
2158
- }
2091
+ if (this.viewPort.canvas) ;
2159
2092
  }
2160
2093
  tick(deltaTime) {
2161
2094
  this.pawn.tick(deltaTime);
@@ -2165,13 +2098,7 @@ class Controller {
2165
2098
  clearTimeout(this.leftClickTimer);
2166
2099
  this.leftClickTimer = null;
2167
2100
  }
2168
- if (this.viewPort.canvas) {
2169
- this.viewPort.canvas.removeEventListener("pointermove", this.onPointerMove);
2170
- this.viewPort.canvas.removeEventListener("pointerenter", this.onPointerEnter);
2171
- this.viewPort.canvas.removeEventListener("pointerleave", this.onPointerLeave);
2172
- this.viewPort.canvas.removeEventListener("pointerup", this.onPointerUp);
2173
- this.viewPort.canvas.removeEventListener("pointerdown", this.onPointerDown);
2174
- }
2101
+ if (this.viewPort.canvas) ;
2175
2102
  this.pawn.unpossess();
2176
2103
  this.pawn.destroy();
2177
2104
  this._pawn = null;
@@ -2293,6 +2220,14 @@ class Controller {
2293
2220
  focusTo(targetPos, targetQuat, distance, time, onGoing = null, onFinished = null) {
2294
2221
  this.pawn.focusTo(targetPos, targetQuat, distance, time, onGoing, onFinished);
2295
2222
  }
2223
+ setPawn(pawn) {
2224
+ if (this._pawn) {
2225
+ this._pawn.unpossess();
2226
+ this._pawn.destroy();
2227
+ }
2228
+ this._pawn = pawn;
2229
+ this._pawn.possess();
2230
+ }
2296
2231
  }
2297
2232
 
2298
2233
  class CameraFactory {
@@ -2318,7 +2253,7 @@ class CameraFactory {
2318
2253
  catch (error) {
2319
2254
  console.warn("[CameraFactory]Error occurred while creating camera: ", error);
2320
2255
  console.warn("[CameraFactory]Create default perspective camera instead");
2321
- return new PerspectiveCamera(50, 1, 0.1, 1000);
2256
+ return new PerspectiveCamera(50, 1, 0.1, 100000);
2322
2257
  }
2323
2258
  }
2324
2259
  static updataCamera(param, camera) {
@@ -2332,6 +2267,7 @@ class CameraFactory {
2332
2267
  camera.far = data.far;
2333
2268
  camera.fov = data.fov;
2334
2269
  camera.aspect = data.aspect;
2270
+ camera.updateProjectionMatrix();
2335
2271
  return camera;
2336
2272
  }
2337
2273
  return new PerspectiveCamera(data.fov, data.aspect, data.near, data.far);
@@ -2346,6 +2282,7 @@ class CameraFactory {
2346
2282
  camera.right = data.right;
2347
2283
  camera.top = data.top;
2348
2284
  camera.bottom = data.bottom;
2285
+ camera.updateProjectionMatrix();
2349
2286
  return camera;
2350
2287
  }
2351
2288
  return new OrthographicCamera(data.left, data.right, data.top, data.bottom, data.near, data.far);
@@ -2366,7 +2303,7 @@ class CameraFactory {
2366
2303
 
2367
2304
  const DefaultPerspectiveCameraParam = {
2368
2305
  near: 0.1,
2369
- far: 1000,
2306
+ far: 10000,
2370
2307
  type: "Perspective",
2371
2308
  fov: 50,
2372
2309
  aspect: 1,
@@ -2898,7 +2835,14 @@ const DefaultWorldParam = {
2898
2835
  levelActorClass: LevelActor,
2899
2836
  };
2900
2837
 
2838
+ /** 动画循环启动延迟时间(毫秒) */
2839
+ const ANIMATION_START_DELAY = 100;
2840
+ /**
2841
+ * Three.js应用程序主类
2842
+ * 负责管理场景、视口、控制器和资源
2843
+ */
2901
2844
  class ThreeJsApp {
2845
+ // ========== 公共访问器 ==========
2902
2846
  get camera() {
2903
2847
  return this._camera;
2904
2848
  }
@@ -2923,67 +2867,132 @@ class ThreeJsApp {
2923
2867
  get onCameraChangedDelegate() {
2924
2868
  return this._onCameraChangedDelegate;
2925
2869
  }
2870
+ /**
2871
+ * 构造ThreeJs应用程序实例
2872
+ * @param appParam 应用程序参数配置
2873
+ */
2926
2874
  constructor(appParam = DefaultAppParam) {
2875
+ var _a, _b, _c, _d, _e, _f;
2876
+ // ========== 私有字段 ==========
2877
+ this.animationFrameHandle = 0;
2927
2878
  this._tickingFunctions = [];
2928
2879
  this._appParam = { viewportParam: DefaultViewportParam };
2929
2880
  this._onCameraChangedDelegate = new Delegate();
2930
- this._appParam.cameraParam = appParam.cameraParam ? appParam.cameraParam : DefaultCameraParam;
2931
- this._appParam.renderParam = appParam.renderParam ? appParam.renderParam : DefaultRendererParameters;
2932
- this._appParam.postProcessParam = appParam.postProcessParam ? appParam.postProcessParam : DefaultPostProcessParam;
2933
- this._appParam.viewportParam = appParam.viewportParam ? appParam.viewportParam : DefaultViewportParam;
2934
- this._appParam.classes = appParam.classes ? appParam.classes : {
2881
+ // 初始化应用参数(使用空值合并运算符简化默认值处理)
2882
+ this._appParam.cameraParam = (_a = appParam.cameraParam) !== null && _a !== void 0 ? _a : DefaultCameraParam;
2883
+ this._appParam.renderParam = (_b = appParam.renderParam) !== null && _b !== void 0 ? _b : DefaultRendererParameters;
2884
+ this._appParam.postProcessParam = (_c = appParam.postProcessParam) !== null && _c !== void 0 ? _c : DefaultPostProcessParam;
2885
+ this._appParam.viewportParam = (_d = appParam.viewportParam) !== null && _d !== void 0 ? _d : DefaultViewportParam;
2886
+ this._appParam.worldParam = (_e = appParam.worldParam) !== null && _e !== void 0 ? _e : DefaultWorldParam;
2887
+ this._appParam.isRenderEveryFrame = appParam.isRenderEveryFrame;
2888
+ this._appParam.classes = (_f = appParam.classes) !== null && _f !== void 0 ? _f : {
2935
2889
  assetManagerClass: AssetManager,
2936
2890
  controllerClass: Controller,
2937
2891
  worldClass: World,
2938
2892
  viewportClass: Viewport,
2939
2893
  };
2940
- this._appParam.isRenderEveryFrame = appParam.isRenderEveryFrame;
2894
+ // 初始化核心组件
2941
2895
  this._clock = new Clock();
2942
2896
  this._camera = CameraFactory.createCamera(this._appParam.cameraParam);
2943
- this._world = new this._appParam.classes.worldClass(this, this._appParam.worldParam ? this._appParam.worldParam : DefaultWorldParam);
2897
+ this._world = new this._appParam.classes.worldClass(this, this._appParam.worldParam);
2944
2898
  this._viewport = new this._appParam.classes.viewportClass(this, this._appParam.viewportParam, this._appParam.renderParam, this._appParam.postProcessParam);
2945
2899
  this._controller = new this._appParam.classes.controllerClass(this);
2946
2900
  this._assetManager = new this._appParam.classes.assetManagerClass(this);
2947
- this.viewport.renderer.setAnimationLoop(() => {
2948
- const delta = this._clock.getDelta();
2949
- this.tick(delta);
2950
- });
2951
2901
  this.postConstruct();
2902
+ this.startAnimationLoop();
2952
2903
  }
2904
+ /**
2905
+ * 构造后初始化钩子
2906
+ * 按顺序初始化控制器、世界和视口
2907
+ */
2953
2908
  postConstruct() {
2954
2909
  this.controller.init();
2955
2910
  this.world.init();
2956
2911
  this.viewport.init();
2957
2912
  }
2913
+ /**
2914
+ * 公共初始化方法
2915
+ * 可由子类重写以添加自定义初始化逻辑
2916
+ */
2958
2917
  init() {
2959
- }
2918
+ // 预留给子类实现
2919
+ }
2920
+ /**
2921
+ * 启动动画循环
2922
+ * 使用延迟启动以确保所有组件完全初始化
2923
+ */
2924
+ startAnimationLoop() {
2925
+ const tick = () => {
2926
+ this.animationFrameHandle = requestAnimationFrame(tick);
2927
+ try {
2928
+ const delta = this._clock.getDelta();
2929
+ this.tick(delta);
2930
+ }
2931
+ catch (error) {
2932
+ console.error('动画循环错误:', error);
2933
+ }
2934
+ };
2935
+ setTimeout(() => {
2936
+ tick();
2937
+ }, ANIMATION_START_DELAY);
2938
+ }
2939
+ /**
2940
+ * 每帧更新方法
2941
+ * @param deltaTime 距离上一帧的时间增量(秒)
2942
+ */
2960
2943
  tick(deltaTime) {
2961
2944
  this._controller.tick(deltaTime);
2962
2945
  this.world.tick(deltaTime);
2946
+ // 执行所有注册的tick函数
2963
2947
  this._tickingFunctions.forEach(func => {
2964
2948
  func(deltaTime);
2965
2949
  });
2950
+ // 根据配置决定是否每帧都渲染
2966
2951
  if (this._appParam.isRenderEveryFrame) {
2967
2952
  this.viewport.markRenderStateDirty();
2968
2953
  }
2969
2954
  this.viewport.render();
2970
2955
  }
2956
+ /**
2957
+ * 添加每帧执行的函数
2958
+ * @param func 接收deltaTime参数的回调函数
2959
+ */
2971
2960
  addTickingFunction(func) {
2972
2961
  this._tickingFunctions.push(func);
2973
2962
  }
2963
+ /**
2964
+ * 移除已注册的tick函数
2965
+ * @param func 要移除的函数引用
2966
+ */
2974
2967
  removeTickingFunction(func) {
2975
2968
  const index = this._tickingFunctions.indexOf(func);
2976
2969
  if (index >= 0) {
2977
2970
  this._tickingFunctions.splice(index, 1);
2978
2971
  }
2979
2972
  }
2973
+ /**
2974
+ * 销毁应用程序并清理所有资源
2975
+ */
2980
2976
  destroy() {
2977
+ // 停止动画循环
2978
+ if (this.animationFrameHandle) {
2979
+ cancelAnimationFrame(this.animationFrameHandle);
2980
+ this.animationFrameHandle = 0;
2981
+ }
2982
+ // 清理委托
2981
2983
  this.onCameraChangedDelegate.clear();
2984
+ // 销毁各个组件
2982
2985
  this.controller.destroy();
2983
2986
  this.world.destroy();
2984
2987
  this.viewport.destroy();
2985
2988
  this._assetManager.clearAssets();
2989
+ // 清空tick函数列表
2990
+ this._tickingFunctions = [];
2986
2991
  }
2992
+ /**
2993
+ * 更新相机参数
2994
+ * @param param 新的相机参数
2995
+ */
2987
2996
  updateCamera(param) {
2988
2997
  const previousCam = this.camera;
2989
2998
  this._camera = CameraFactory.updataCamera(param, this.camera);
@@ -2994,16 +3003,31 @@ class ThreeJsApp {
2994
3003
  this._camera.updateProjectionMatrix();
2995
3004
  this.viewport.markRenderStateDirty();
2996
3005
  }
3006
+ /**
3007
+ * 窗口大小改变时的处理
3008
+ * @param width 新的宽度
3009
+ * @param height 新的高度
3010
+ */
2997
3011
  onWindowResize(width, height) {
2998
3012
  if (this.camera instanceof PerspectiveCamera) {
2999
3013
  this.camera.aspect = width / height;
3000
3014
  }
3001
- // if(this.camera instanceof OrthographicCamera)
3002
- // {
3003
- // // to do
3015
+ // TODO: 实现正交相机的窗口缩放处理
3016
+ // if (this.camera instanceof OrthographicCamera) {
3017
+ // const aspect = width / height;
3018
+ // this.camera.left = -width / 2;
3019
+ // this.camera.right = width / 2;
3020
+ // this.camera.top = height / 2;
3021
+ // this.camera.bottom = -height / 2;
3004
3022
  // }
3005
3023
  this.camera.updateProjectionMatrix();
3006
3024
  }
3025
+ /**
3026
+ * 将当前场景渲染为图片
3027
+ * @param width 图片宽度,默认1024
3028
+ * @param height 图片高度,默认1024
3029
+ * @returns 图片的DataURL
3030
+ */
3007
3031
  async renderAsImage(width = 1024, height = 1024) {
3008
3032
  return await this.viewport.renderAsImage(width, height);
3009
3033
  }
@@ -3179,7 +3203,7 @@ class AmbientLightActor extends Actor {
3179
3203
  }
3180
3204
 
3181
3205
  class BoxComponent extends MeshComponent {
3182
- constructor(app, width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1, material = new MeshStandardMaterial(), uuid) {
3206
+ constructor(app, width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1, material = new MeshStandardMaterial({ color: 0x00ff00 }), uuid) {
3183
3207
  super(app, new BoxGeometry(width, height, depth, widthSegments, heightSegments, depthSegments), material, uuid);
3184
3208
  }
3185
3209
  }
@@ -3326,6 +3350,120 @@ class LabelComponent extends SceneComponent {
3326
3350
  // labelStyle.style.fontSize = "10px";
3327
3351
  // labelStyle.style.pointerEvents = 'auto';
3328
3352
 
3353
+ class CurveComponent extends SceneComponent {
3354
+ get threeObject() {
3355
+ if (!this.obj) {
3356
+ throw new Error("threeObject is null");
3357
+ }
3358
+ return this.obj;
3359
+ }
3360
+ set threeObject(newThreeObject) {
3361
+ this.obj = newThreeObject;
3362
+ if (this.obj) {
3363
+ this.obj.userData["LYObject"] = this;
3364
+ }
3365
+ }
3366
+ get material() {
3367
+ return this.threeObject.material;
3368
+ }
3369
+ constructor(app, points, setup = { color: 0xffffff }, bCreateLine = true, uuid) {
3370
+ var _a, _b, _c;
3371
+ super(app, uuid);
3372
+ this.closed = (_a = setup.closed) !== null && _a !== void 0 ? _a : false;
3373
+ this.curveType = (_b = setup.type) !== null && _b !== void 0 ? _b : 'centripetal';
3374
+ this.tension = (_c = setup.tension) !== null && _c !== void 0 ? _c : 0;
3375
+ this.sourcePoints = points;
3376
+ this.curve = new CatmullRomCurve3(points, this.closed, this.curveType, this.tension);
3377
+ this.points = this.curve.getPoints(points.length * (this.tension === 0 ? 1 : 10) - 1);
3378
+ this.material.color = new Color(setup.color);
3379
+ this.bCreateLine = bCreateLine;
3380
+ this.name = "CurveComponent";
3381
+ if (this.bCreateLine) {
3382
+ this.createLine();
3383
+ }
3384
+ }
3385
+ isValid() {
3386
+ return this.threeObject != null;
3387
+ }
3388
+ createDefaultObject() {
3389
+ // 创建默认材质
3390
+ const material = new LineBasicMaterial({
3391
+ color: 0xffffff,
3392
+ transparent: true,
3393
+ opacity: 1
3394
+ });
3395
+ // 创建空的几何体和线对象
3396
+ const geometry = new BufferGeometry$1();
3397
+ const line = new Line(geometry, material);
3398
+ return line;
3399
+ }
3400
+ resetPoints(points) {
3401
+ this.sourcePoints = points;
3402
+ this.curve = new CatmullRomCurve3(points, this.closed, this.curveType, this.tension);
3403
+ this.points = this.curve.getPoints(points.length * (this.tension === 0 ? 1 : 10) - 1);
3404
+ if (this.bCreateLine) {
3405
+ this.createLine();
3406
+ }
3407
+ }
3408
+ createLine() {
3409
+ const positions = [];
3410
+ for (let i = 0; i < this.points.length; ++i) {
3411
+ positions.push(this.points[i].x);
3412
+ positions.push(this.points[i].y);
3413
+ positions.push(this.points[i].z);
3414
+ }
3415
+ const geometry = this.threeObject.geometry;
3416
+ geometry.setAttribute('position', new Float32BufferAttribute(positions, 3));
3417
+ }
3418
+ destroy() {
3419
+ if (this.isValid() && this.threeObject) {
3420
+ if (this.threeObject.geometry) {
3421
+ this.threeObject.geometry.dispose();
3422
+ }
3423
+ if (this.material) {
3424
+ this.material.dispose();
3425
+ }
3426
+ }
3427
+ super.destroy();
3428
+ }
3429
+ get SourcePoints() {
3430
+ return this.sourcePoints;
3431
+ }
3432
+ get Curve() {
3433
+ return this.curve;
3434
+ }
3435
+ get Points() {
3436
+ return this.points;
3437
+ }
3438
+ getPointAt(u) {
3439
+ return this.curve.getPointAt(u);
3440
+ }
3441
+ getTangentAt(u) {
3442
+ return this.curve.getTangentAt(u);
3443
+ }
3444
+ // 返回曲线在参数 u 处的世界坐标点
3445
+ getWorldPointAt(u) {
3446
+ const p = this.curve.getPointAt(u).clone();
3447
+ if (this.obj) {
3448
+ this.obj.updateMatrixWorld(true);
3449
+ return this.localToWorld(p);
3450
+ }
3451
+ return p;
3452
+ }
3453
+ // 返回曲线在参数 u 处的世界坐标系下的单位切线方向
3454
+ getWorldTangentAt(u) {
3455
+ const t = this.curve.getTangentAt(u).clone();
3456
+ if (this.obj) {
3457
+ this.obj.updateMatrixWorld(true);
3458
+ t.transformDirection(this.obj.matrixWorld);
3459
+ }
3460
+ return t;
3461
+ }
3462
+ getLength() {
3463
+ return this.curve.getLength();
3464
+ }
3465
+ }
3466
+
3329
3467
  const DefaultBloomParam = {
3330
3468
  type: PostProcessStepType.Bloom,
3331
3469
  threshold: 0,
@@ -3600,4 +3738,4 @@ class TransformGizmo extends Pawn {
3600
3738
  }
3601
3739
  }
3602
3740
 
3603
- export { Actor, AmbientLightActor, AmbientLightComponent, AssetManager, AttachmentRules, BoxActor, BoxComponent, Controller, DefaultAAParams, DefaultAppParam, DefaultBloomParam, DefaultCameraParam, DefaultDOFParam, DefaultDenoiseParam, DefaultGTAOParam, DefaultOrthographicCameraParam, DefaultOutlineParams, DefaultPerspectiveCameraParam, DefaultPostProcessParam, DefaultRendererParameters, DefaultSSRParam, DefaultSkyParam, DefaultViewportParam, DefaultWorldParam, Delegate, DirectionalLightActor, DirectionalLightComponent, FirstPerson, GeometryAssetPointer, LabelComponent, LevelActor, LevelComponent, MaterialAssetPointer, MeshComponent, Orbital, PlaneActor, PlaneComponent, PostProcessStepType, SceneComponent, SkyActor, SkyComponent, SphereComponent, TAssetPointer, TSmartPointer, TextureAssetPointer, ThreeJsApp, ThreeObjectLibrary, TransformGizmo, Viewport, WebGPUPostProcessFactory, World };
3741
+ export { Actor, AmbientLightActor, AmbientLightComponent, AssetManager, AttachmentRules, BoxActor, BoxComponent, Controller, CurveComponent, DefaultAAParams, DefaultAppParam, DefaultBloomParam, DefaultCameraParam, DefaultDOFParam, DefaultDenoiseParam, DefaultGTAOParam, DefaultOrthographicCameraParam, DefaultOutlineParams, DefaultPerspectiveCameraParam, DefaultPostProcessParam, DefaultRendererParameters, DefaultSSRParam, DefaultSkyParam, DefaultViewportParam, DefaultWorldParam, Delegate, DirectionalLightActor, DirectionalLightComponent, FirstPerson, GeometryAssetPointer, LabelComponent, LevelActor, LevelComponent, MaterialAssetPointer, MeshComponent, Orbital, Pawn, PlaneActor, PlaneComponent, PostProcessStepType, SceneComponent, SkyActor, SkyComponent, SphereComponent, TAssetPointer, TSmartPointer, TextureAssetPointer, ThreeJsApp, ThreeObjectLibrary, TransformGizmo, Viewport, WebGPUPostProcessFactory, World };
package/dist/index.d.ts CHANGED
@@ -37,6 +37,8 @@ export { DirectionalLightComponent } from "./lythreeframe/Object/Components/Ligh
37
37
  export { AmbientLightComponent } from './lythreeframe/Object/Components/Light/AmbientLight/AmbientLightComponent';
38
38
  export { LabelComponent } from "./lythreeframe/Object/Components/2D/2DComponent";
39
39
  export { SkyComponent } from "./lythreeframe/Object/Components/Sky/SkyComponent";
40
+ export { CurveComponent } from './lythreeframe/Object/Components/Curve/CurveComponent';
41
+ export type { CurveComponetSetup } from './lythreeframe/Object/Components/Curve/CurveComponent';
40
42
  export type { SkyComponentParam } from "./lythreeframe/Object/Components/Sky/SkyComponent";
41
43
  export { DefaultSkyParam } from "./lythreeframe/Object/Components/Sky/SkyComponent";
42
44
  export { WebGPUPostProcessFactory } from "./lythreeframe/PostProcess/WebGPUPostProcessFactory";
@@ -58,6 +60,7 @@ export { DefaultSSRParam } from "./lythreeframe/PostProcess/Param/SSR";
58
60
  export type { SSRParam } from "./lythreeframe/PostProcess/Param/SSR";
59
61
  export { DefaultAAParams } from "./lythreeframe/PostProcess/Param/AAParam";
60
62
  export type { AAParams } from "./lythreeframe/PostProcess/Param/AAParam";
63
+ export { Pawn } from "./lythreeframe/Object/PawnV2/Pawn";
61
64
  export { Orbital } from "./lythreeframe/Object/PawnV2/Oribital";
62
65
  export { FirstPerson } from "./lythreeframe/Object/PawnV2/FirstPerson";
63
66
  export type { ITransforming } from "./lythreeframe/Object/PawnV2/TransformControl";
@@ -40,4 +40,5 @@ export declare class Controller {
40
40
  getHitResultUnderCursor(): Intersection | null;
41
41
  getHitResultFromScreenPoint(x: number, y: number): Intersection | null;
42
42
  focusTo(targetPos: Vector3, targetQuat: Quaternion | Euler, distance: number, time: number, onGoing?: (() => void) | null, onFinished?: (() => void) | null): void;
43
+ setPawn(pawn: Pawn): void;
43
44
  }
@@ -7,6 +7,7 @@ import { ViewportParam } from "./ViewportParameters";
7
7
  import { AssetManager } from "../../AssetManagement/AssetManager";
8
8
  import { PostProcessParam } from "../../PostProcess/PostProcessParam";
9
9
  import { RendererParameters } from "./RendererParameters";
10
+ import { ControllerParameters } from "./ControllerParameters";
10
11
  export interface AppClass {
11
12
  assetManagerClass: typeof AssetManager;
12
13
  controllerClass: typeof Controller;
@@ -19,6 +20,7 @@ export interface AppParam {
19
20
  postProcessParam?: PostProcessParam;
20
21
  worldParam?: WorldParam;
21
22
  viewportParam: ViewportParam;
23
+ controllerParam?: ControllerParameters;
22
24
  classes?: AppClass;
23
25
  isRenderEveryFrame?: boolean;
24
26
  }
@@ -0,0 +1,2 @@
1
+ export interface ControllerParameters {
2
+ }