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.
- package/dist/bundle.cjs.js +278 -138
- package/dist/bundle.esm.js +278 -140
- package/dist/index.d.ts +3 -0
- package/dist/lythreeframe/Frame/Controller.d.ts +1 -0
- package/dist/lythreeframe/Frame/Parameters/AppParameter.d.ts +2 -0
- package/dist/lythreeframe/Frame/Parameters/ControllerParameters.d.ts +2 -0
- package/dist/lythreeframe/Frame/Parameters/ViewportParameters.d.ts +1 -0
- package/dist/lythreeframe/Frame/Viewport.d.ts +7 -3
- package/dist/lythreeframe/Object/Components/Curve/CurveComponent.d.ts +35 -0
- package/dist/lythreeframe/Object/Components/Light/AmbientLight/AmbientLightComponent.d.ts +1 -1
- package/dist/lythreeframe/PostProcess/Param/AAParam.d.ts +1 -1
- package/dist/lythreeframe/PostProcess/Param/Bloom.d.ts +1 -1
- package/dist/lythreeframe/PostProcess/Param/DOF.d.ts +1 -1
- package/dist/lythreeframe/PostProcess/Param/GTAO.d.ts +1 -1
- package/dist/lythreeframe/PostProcess/Param/Outline.d.ts +2 -2
- package/dist/lythreeframe/PostProcess/Param/SSR.d.ts +1 -1
- package/dist/lythreeframe/PostProcess/WebGPUPostProcessFactory.d.ts +6 -6
- package/dist/lythreeframe/ThreeJsApp.d.ts +60 -8
- package/package.json +1 -1
package/dist/bundle.cjs.js
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
element
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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,
|
|
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:
|
|
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
|
-
|
|
2933
|
-
this._appParam.
|
|
2934
|
-
this._appParam.
|
|
2935
|
-
this._appParam.
|
|
2936
|
-
this._appParam.
|
|
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
|
-
|
|
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
|
|
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
|
-
//
|
|
3004
|
-
// {
|
|
3005
|
-
//
|
|
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
|
|
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;
|