framefields 2.8.0 → 2.8.1
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/audio/index.d.mts +4 -4
- package/dist/audio/index.mjs +10 -10
- package/dist/{audio-CxAUxVyA.d.mts → audio-Ccpl9mjV.d.mts} +3 -3
- package/dist/{audio-CxAUxVyA.d.mts.map → audio-Ccpl9mjV.d.mts.map} +1 -1
- package/dist/{audio-CGVJlZb9.mjs → audio-vatRe308.mjs} +3 -3
- package/dist/{audio-CGVJlZb9.mjs.map → audio-vatRe308.mjs.map} +1 -1
- package/dist/cli/check-worker.mjs +43 -43
- package/dist/components/index.d.mts +10 -10
- package/dist/components/index.mjs +42 -42
- package/dist/{dist-C5eZw8ms.mjs → dist-BbwtlSZO.mjs} +2 -2
- package/dist/{dist-C5eZw8ms.mjs.map → dist-BbwtlSZO.mjs.map} +1 -1
- package/dist/{dist-CnFcSau0.mjs → dist-CFe1fC9l.mjs} +2289 -212
- package/dist/dist-CFe1fC9l.mjs.map +1 -0
- package/dist/effects/index.d.mts +4 -4
- package/dist/effects/index.mjs +34 -34
- package/dist/{effects-DdvkiI3u.mjs → effects-CCyfjbhZ.mjs} +2 -2
- package/dist/{effects-DdvkiI3u.mjs.map → effects-CCyfjbhZ.mjs.map} +1 -1
- package/dist/fonts/index.mjs +2 -2
- package/dist/{fonts-k_89s1HO.mjs → fonts-C1mgtkCa.mjs} +2 -2
- package/dist/{fonts-k_89s1HO.mjs.map → fonts-C1mgtkCa.mjs.map} +1 -1
- package/dist/{gpu-BoyykRdD.mjs → gpu-CU2tEKJJ.mjs} +2 -2
- package/dist/{gpu-BoyykRdD.mjs.map → gpu-CU2tEKJJ.mjs.map} +1 -1
- package/dist/{index-CPFKis94.d.mts → index-7Z9_a_iB.d.mts} +3 -3
- package/dist/{index-CPFKis94.d.mts.map → index-7Z9_a_iB.d.mts.map} +1 -1
- package/dist/{index-CFKMZDv1.d.mts → index-BIjMAW1h.d.mts} +2 -2
- package/dist/{index-CFKMZDv1.d.mts.map → index-BIjMAW1h.d.mts.map} +1 -1
- package/dist/{index-Ds9_v60R.d.mts → index-BwRrsP_V.d.mts} +181 -13
- package/dist/index-BwRrsP_V.d.mts.map +1 -0
- package/dist/{index-BukqOGDa.d.mts → index-CFoAmh7q.d.mts} +3 -3
- package/dist/{index-BukqOGDa.d.mts.map → index-CFoAmh7q.d.mts.map} +1 -1
- package/dist/{index-CPeaSZoz.d.mts → index-CJL0JAU8.d.mts} +2 -2
- package/dist/{index-CPeaSZoz.d.mts.map → index-CJL0JAU8.d.mts.map} +1 -1
- package/dist/{index-Ced1Ry4S.d.mts → index-D5UDyVMb.d.mts} +211 -9
- package/dist/index-D5UDyVMb.d.mts.map +1 -0
- package/dist/{index-B_nooAhS.d.mts → index-UDDAfHAF.d.mts} +4 -4
- package/dist/{index-B_nooAhS.d.mts.map → index-UDDAfHAF.d.mts.map} +1 -1
- package/dist/index.d.mts +11 -11
- package/dist/index.mjs +49 -49
- package/dist/preview/index.d.mts +3 -3
- package/dist/preview/index.mjs +10 -10
- package/dist/{preview-DHqCrFhG.mjs → preview-WXbsf6Dv.mjs} +2 -2
- package/dist/{preview-DHqCrFhG.mjs.map → preview-WXbsf6Dv.mjs.map} +1 -1
- package/dist/preview-engine/{chunk-K5F4ZW6T.mjs → chunk-7U34VKNO.mjs} +1 -1
- package/dist/preview-engine/chunk-FKG27DVO.mjs +4 -0
- package/dist/preview-engine/chunk-KFNVUGNN.mjs +1974 -0
- package/dist/preview-engine/chunk-NKAVHU7H.mjs +480 -0
- package/dist/preview-engine/chunk-PYX6Q2EJ.mjs +2403 -0
- package/dist/preview-engine/components.mjs +1 -1
- package/dist/preview-engine/framefields.mjs +1 -1
- package/dist/preview-engine/player.mjs +1 -1
- package/dist/preview-engine/renderers-KPCQGBIY.mjs +228 -0
- package/dist/{program-CqQDWfSV.mjs → program-Cq4gP9Dd.mjs} +5 -6
- package/dist/program-Cq4gP9Dd.mjs.map +1 -0
- package/dist/renderer/index.d.mts +2 -2
- package/dist/renderer/index.mjs +2 -2
- package/dist/renderer-01zxT4CK.mjs +5 -0
- package/dist/renderer-35LHkj36.mjs +5 -0
- package/dist/{renderer-Cx2Sw9Ib.mjs → renderer-AMBVtZ_G.mjs} +3 -3
- package/dist/{renderer-Cx2Sw9Ib.mjs.map → renderer-AMBVtZ_G.mjs.map} +1 -1
- package/dist/renderer-B0OIdCGj.mjs +5 -0
- package/dist/renderer-B3IPtkK9.mjs +5 -0
- package/dist/{renderer-DCyp-jzQ.mjs → renderer-B4iCFvJh.mjs} +3 -3
- package/dist/{renderer-DCyp-jzQ.mjs.map → renderer-B4iCFvJh.mjs.map} +1 -1
- package/dist/{renderer-DsGE9qtz.mjs → renderer-BD00i68i.mjs} +3 -3
- package/dist/{renderer-DsGE9qtz.mjs.map → renderer-BD00i68i.mjs.map} +1 -1
- package/dist/{renderer-CuK1lPnA.mjs → renderer-BEuU7qlG.mjs} +2 -2
- package/dist/{renderer-CuK1lPnA.mjs.map → renderer-BEuU7qlG.mjs.map} +1 -1
- package/dist/{renderer-BuYRrBRf.mjs → renderer-BGPnCRFI.mjs} +3 -3
- package/dist/{renderer-BuYRrBRf.mjs.map → renderer-BGPnCRFI.mjs.map} +1 -1
- package/dist/{renderer-D7FuHXiz.mjs → renderer-BIGILDEA.mjs} +2 -2
- package/dist/{renderer-D7FuHXiz.mjs.map → renderer-BIGILDEA.mjs.map} +1 -1
- package/dist/{renderer-4GwADfB0.mjs → renderer-BLU0PQTB.mjs} +3 -3
- package/dist/{renderer-4GwADfB0.mjs.map → renderer-BLU0PQTB.mjs.map} +1 -1
- package/dist/renderer-BMC39abo.mjs +5 -0
- package/dist/{renderer-DS-Gv-3w.mjs → renderer-BNzT34UV.mjs} +2 -2
- package/dist/renderer-BQj3nlAI.mjs +5 -0
- package/dist/{renderer-DqMZiy5N.mjs → renderer-BWlMAacF.mjs} +2 -2
- package/dist/{renderer-DqMZiy5N.mjs.map → renderer-BWlMAacF.mjs.map} +1 -1
- package/dist/{renderer-DXu0nrzo.d.mts → renderer-BX7jS14r.d.mts} +2 -2
- package/dist/{renderer-DXu0nrzo.d.mts.map → renderer-BX7jS14r.d.mts.map} +1 -1
- package/dist/{renderer-DPUULdjh.mjs → renderer-BXAgUuAq.mjs} +2 -2
- package/dist/{renderer-DPUULdjh.mjs.map → renderer-BXAgUuAq.mjs.map} +1 -1
- package/dist/{renderer-Cn34qZC4.mjs → renderer-BZKkT-6Q.mjs} +2 -2
- package/dist/{renderer-Cn34qZC4.mjs.map → renderer-BZKkT-6Q.mjs.map} +1 -1
- package/dist/{renderer-BcHpcLq3.mjs → renderer-BdbGTz7z.mjs} +3 -3
- package/dist/{renderer-BcHpcLq3.mjs.map → renderer-BdbGTz7z.mjs.map} +1 -1
- package/dist/{renderer-Dhi0Q1cI.mjs → renderer-BeFiQfzV.mjs} +69 -69
- package/dist/{renderer-Dhi0Q1cI.mjs.map → renderer-BeFiQfzV.mjs.map} +1 -1
- package/dist/{renderer-kg8-ngnB.mjs → renderer-BeQrWrOa.mjs} +2 -2
- package/dist/{renderer-kg8-ngnB.mjs.map → renderer-BeQrWrOa.mjs.map} +1 -1
- package/dist/{renderer-Ca-LoeJh.mjs → renderer-BioUC9zE.mjs} +2 -2
- package/dist/{renderer-Ca-LoeJh.mjs.map → renderer-BioUC9zE.mjs.map} +1 -1
- package/dist/{renderer-wH_l-jMH.mjs → renderer-Bkqg-U2F.mjs} +3 -3
- package/dist/{renderer-wH_l-jMH.mjs.map → renderer-Bkqg-U2F.mjs.map} +1 -1
- package/dist/{renderer-Sj11W1xq.mjs → renderer-BlVmbzPs.mjs} +2 -2
- package/dist/renderer-BnBvSmp_.mjs +5 -0
- package/dist/{renderer-Qd-HCwKj.mjs → renderer-Br4UZvfL.mjs} +3 -3
- package/dist/{renderer-Qd-HCwKj.mjs.map → renderer-Br4UZvfL.mjs.map} +1 -1
- package/dist/{renderer-DX5ZpEBB.mjs → renderer-BrWOcJ9Q.mjs} +3 -3
- package/dist/{renderer-DX5ZpEBB.mjs.map → renderer-BrWOcJ9Q.mjs.map} +1 -1
- package/dist/renderer-BsDSpTpL.mjs +5 -0
- package/dist/renderer-BtW6_gvE.mjs +5 -0
- package/dist/renderer-By8U44Rt.mjs +5 -0
- package/dist/{renderer-XnWe1hSL.mjs → renderer-C-5RNIeX.mjs} +2 -2
- package/dist/{renderer-XnWe1hSL.mjs.map → renderer-C-5RNIeX.mjs.map} +1 -1
- package/dist/renderer-C3lDmxuX.mjs +5 -0
- package/dist/renderer-C6SZAE_x.mjs +5 -0
- package/dist/{renderer-DSM5c7UA.mjs → renderer-C8rxyjaE.mjs} +2 -2
- package/dist/{renderer-DSM5c7UA.mjs.map → renderer-C8rxyjaE.mjs.map} +1 -1
- package/dist/renderer-CA3IVeZj.mjs +5 -0
- package/dist/{renderer-DYT4iPi-.mjs → renderer-CAagaRag.mjs} +2 -2
- package/dist/{renderer-DYT4iPi-.mjs.map → renderer-CAagaRag.mjs.map} +1 -1
- package/dist/{renderer-CaE0rp9j.mjs → renderer-CCSzKnvs.mjs} +2 -2
- package/dist/{renderer-CaE0rp9j.mjs.map → renderer-CCSzKnvs.mjs.map} +1 -1
- package/dist/renderer-CFoCH_mO.mjs +5 -0
- package/dist/renderer-CLhZqJF8.mjs +6 -0
- package/dist/{renderer-Bw5jGUo5.mjs → renderer-COQc1jn6.mjs} +2 -2
- package/dist/{renderer-Bw5jGUo5.mjs.map → renderer-COQc1jn6.mjs.map} +1 -1
- package/dist/{renderer-DB7PM7nZ.mjs → renderer-CP2FOWyJ.mjs} +3 -3
- package/dist/{renderer-DB7PM7nZ.mjs.map → renderer-CP2FOWyJ.mjs.map} +1 -1
- package/dist/{renderer-DXsV3mZD.mjs → renderer-CUq2qgyc.mjs} +3 -3
- package/dist/{renderer-DXsV3mZD.mjs.map → renderer-CUq2qgyc.mjs.map} +1 -1
- package/dist/{renderer-DYfNgEhK.mjs → renderer-CXWAdRqn.mjs} +2 -2
- package/dist/{renderer-DYfNgEhK.mjs.map → renderer-CXWAdRqn.mjs.map} +1 -1
- package/dist/renderer-CYJXQS8E.mjs +5 -0
- package/dist/{renderer-JDLYPnRh.mjs → renderer-CZyJ72JZ.mjs} +2 -2
- package/dist/{renderer-JDLYPnRh.mjs.map → renderer-CZyJ72JZ.mjs.map} +1 -1
- package/dist/renderer-C_vj6_WJ.mjs +5 -0
- package/dist/{renderer-4F4FypvN.mjs → renderer-Ce8VPaog.mjs} +2 -2
- package/dist/{renderer-4F4FypvN.mjs.map → renderer-Ce8VPaog.mjs.map} +1 -1
- package/dist/{renderer-4a4koLCl.mjs → renderer-CeX7uUXB.mjs} +2 -2
- package/dist/{renderer-4a4koLCl.mjs.map → renderer-CeX7uUXB.mjs.map} +1 -1
- package/dist/renderer-CeqfC6OR.mjs +5 -0
- package/dist/{renderer-NvGahExL.mjs → renderer-Ci9x2WUd.mjs} +3 -3
- package/dist/{renderer-NvGahExL.mjs.map → renderer-Ci9x2WUd.mjs.map} +1 -1
- package/dist/{renderer-iA7rxZmR.mjs → renderer-CiMIftlS.mjs} +3 -3
- package/dist/{renderer-iA7rxZmR.mjs.map → renderer-CiMIftlS.mjs.map} +1 -1
- package/dist/{renderer-CpEU-TRR.mjs → renderer-CjklM-KD.mjs} +2 -2
- package/dist/{renderer-CpEU-TRR.mjs.map → renderer-CjklM-KD.mjs.map} +1 -1
- package/dist/{renderer-CNVzJIBz.mjs → renderer-Cjx3x7xM.mjs} +3 -3
- package/dist/{renderer-CNVzJIBz.mjs.map → renderer-Cjx3x7xM.mjs.map} +1 -1
- package/dist/renderer-CkZCGMAc.mjs +5 -0
- package/dist/renderer-Clxju1r9.mjs +5 -0
- package/dist/{renderer-l-K6iZLC.mjs → renderer-CrgfMDbh.mjs} +3 -3
- package/dist/{renderer-l-K6iZLC.mjs.map → renderer-CrgfMDbh.mjs.map} +1 -1
- package/dist/{renderer-fv9WvK0d.mjs → renderer-CsilJwL-.mjs} +3 -3
- package/dist/{renderer-fv9WvK0d.mjs.map → renderer-CsilJwL-.mjs.map} +1 -1
- package/dist/{renderer-DBN6SV8L.mjs → renderer-CxEBV-w0.mjs} +2 -2
- package/dist/{renderer-DBN6SV8L.mjs.map → renderer-CxEBV-w0.mjs.map} +1 -1
- package/dist/{renderer-Bw3tlr9I.mjs → renderer-CyWRvKUI.mjs} +2 -2
- package/dist/{renderer-Bw3tlr9I.mjs.map → renderer-CyWRvKUI.mjs.map} +1 -1
- package/dist/renderer-CyWtKBF7.mjs +5 -0
- package/dist/{renderer-BlUfAZyK.mjs → renderer-D-17HVPb.mjs} +3 -3
- package/dist/{renderer-BlUfAZyK.mjs.map → renderer-D-17HVPb.mjs.map} +1 -1
- package/dist/renderer-D27STGoB.mjs +5 -0
- package/dist/{renderer-BUV6IH0o.mjs → renderer-D2JOseb1.mjs} +2 -2
- package/dist/{renderer-BUV6IH0o.mjs.map → renderer-D2JOseb1.mjs.map} +1 -1
- package/dist/{renderer-BYIa_hnS.mjs → renderer-D3K9FEQk.mjs} +3 -3
- package/dist/{renderer-BYIa_hnS.mjs.map → renderer-D3K9FEQk.mjs.map} +1 -1
- package/dist/{renderer-bE6yZ_Ef.mjs → renderer-D41gHat4.mjs} +3 -3
- package/dist/{renderer-bE6yZ_Ef.mjs.map → renderer-D41gHat4.mjs.map} +1 -1
- package/dist/{renderer-C7SYbHgB.mjs → renderer-D6X9vWkN.mjs} +2 -2
- package/dist/{renderer-C7SYbHgB.mjs.map → renderer-D6X9vWkN.mjs.map} +1 -1
- package/dist/renderer-D78Aq9YK.mjs +5 -0
- package/dist/{renderer-ClxmV_id.mjs → renderer-D7Cu9OZx.mjs} +2 -2
- package/dist/{renderer-ClxmV_id.mjs.map → renderer-D7Cu9OZx.mjs.map} +1 -1
- package/dist/{renderer-DO15Nj-w.mjs → renderer-D7Kk7VxM.mjs} +3 -3
- package/dist/{renderer-DO15Nj-w.mjs.map → renderer-D7Kk7VxM.mjs.map} +1 -1
- package/dist/{renderer-DZKZup7n.mjs → renderer-D8CMakyz.mjs} +3 -3
- package/dist/{renderer-DZKZup7n.mjs.map → renderer-D8CMakyz.mjs.map} +1 -1
- package/dist/{renderer-DbO4xZBb.mjs → renderer-DEcbSNQd.mjs} +3 -3
- package/dist/{renderer-DbO4xZBb.mjs.map → renderer-DEcbSNQd.mjs.map} +1 -1
- package/dist/{renderer-DjWBBISJ.mjs → renderer-DGPaKIFf.mjs} +2 -2
- package/dist/renderer-DHEffABL.mjs +5 -0
- package/dist/{renderer-CTr_Zi08.mjs → renderer-DIPyUVX2.mjs} +3 -3
- package/dist/{renderer-CTr_Zi08.mjs.map → renderer-DIPyUVX2.mjs.map} +1 -1
- package/dist/{renderer-D_Mf-Zft.d.mts → renderer-DKgPVOLL.d.mts} +2 -2
- package/dist/{renderer-D_Mf-Zft.d.mts.map → renderer-DKgPVOLL.d.mts.map} +1 -1
- package/dist/{renderer-BrXkb-9N.mjs → renderer-DPn2DhMU.mjs} +2 -2
- package/dist/{renderer-BrXkb-9N.mjs.map → renderer-DPn2DhMU.mjs.map} +1 -1
- package/dist/{renderer-CyELq6P6.mjs → renderer-DRGa6tlX.mjs} +2 -2
- package/dist/{renderer-CyELq6P6.mjs.map → renderer-DRGa6tlX.mjs.map} +1 -1
- package/dist/{renderer-Crl8q_vD.mjs → renderer-DSpTGqUU.mjs} +3 -3
- package/dist/{renderer-Crl8q_vD.mjs.map → renderer-DSpTGqUU.mjs.map} +1 -1
- package/dist/{renderer-vVKNp3ri.mjs → renderer-DTgO5LPf.mjs} +3 -3
- package/dist/{renderer-vVKNp3ri.mjs.map → renderer-DTgO5LPf.mjs.map} +1 -1
- package/dist/renderer-DUuNCgzW.mjs +5 -0
- package/dist/renderer-DVD5pzRq.mjs +5 -0
- package/dist/{renderer-C55eLbl1.mjs → renderer-DgLt0TPo.mjs} +2 -2
- package/dist/{renderer-C55eLbl1.mjs.map → renderer-DgLt0TPo.mjs.map} +1 -1
- package/dist/{renderer-BHwbnT6S.mjs → renderer-Dk45W8Zd.mjs} +3 -3
- package/dist/{renderer-BHwbnT6S.mjs.map → renderer-Dk45W8Zd.mjs.map} +1 -1
- package/dist/{renderer-Dv5yE4LE.mjs → renderer-DlZwbO-A.mjs} +2 -2
- package/dist/{renderer-Dv5yE4LE.mjs.map → renderer-DlZwbO-A.mjs.map} +1 -1
- package/dist/{renderer-CaRPsrbX.mjs → renderer-DnPzvIHK.mjs} +2 -2
- package/dist/{renderer-CCnrG0Pd.mjs → renderer-DoRazdp_.mjs} +2 -2
- package/dist/{renderer-CCnrG0Pd.mjs.map → renderer-DoRazdp_.mjs.map} +1 -1
- package/dist/{renderer-CeIXVu9F.mjs → renderer-DsAoxQ8O.mjs} +2 -2
- package/dist/{renderer-CeIXVu9F.mjs.map → renderer-DsAoxQ8O.mjs.map} +1 -1
- package/dist/renderer-Dsp6xDw5.mjs +5 -0
- package/dist/renderer-DuC-BFXR.mjs +5 -0
- package/dist/renderer-DuWs_Wsv.mjs +5 -0
- package/dist/{renderer-8pS82_mX.mjs → renderer-DveQQCi8.mjs} +3 -3
- package/dist/{renderer-8pS82_mX.mjs.map → renderer-DveQQCi8.mjs.map} +1 -1
- package/dist/{renderer-Dypn26aP.mjs → renderer-DxHICEk3.mjs} +3 -3
- package/dist/{renderer-Dypn26aP.mjs.map → renderer-DxHICEk3.mjs.map} +1 -1
- package/dist/{renderer-DfTnsfy9.mjs → renderer-DxbFjINv.mjs} +3 -3
- package/dist/{renderer-DfTnsfy9.mjs.map → renderer-DxbFjINv.mjs.map} +1 -1
- package/dist/{renderer-jvgqy4Td.mjs → renderer-Gw1ICOJ3.mjs} +3 -3
- package/dist/{renderer-jvgqy4Td.mjs.map → renderer-Gw1ICOJ3.mjs.map} +1 -1
- package/dist/{renderer-j-3XB8YI.mjs → renderer-LY2MiIj0.mjs} +3 -3
- package/dist/{renderer-j-3XB8YI.mjs.map → renderer-LY2MiIj0.mjs.map} +1 -1
- package/dist/{renderer-BLrhcSex.mjs → renderer-LwrcnEtI.mjs} +3 -3
- package/dist/{renderer-BLrhcSex.mjs.map → renderer-LwrcnEtI.mjs.map} +1 -1
- package/dist/renderer-OSgsiIrW.mjs +5 -0
- package/dist/renderer-OZaMFYtZ.mjs +5 -0
- package/dist/renderer-T79TmHET.mjs +5 -0
- package/dist/{renderer-7Tx-L9Vf.mjs → renderer-U-12BOhe.mjs} +2 -2
- package/dist/{renderer-7Tx-L9Vf.mjs.map → renderer-U-12BOhe.mjs.map} +1 -1
- package/dist/renderer-UhsC9oTU.mjs +5 -0
- package/dist/renderer-WYZV1jWf.mjs +5 -0
- package/dist/renderer-Y7evDjHH.mjs +5 -0
- package/dist/{renderer-CQkZUsvc.mjs → renderer-cg06hb82.mjs} +3 -3
- package/dist/{renderer-CQkZUsvc.mjs.map → renderer-cg06hb82.mjs.map} +1 -1
- package/dist/{renderer-DRLtfxdW.mjs → renderer-eAVNsuX8.mjs} +95 -16
- package/dist/renderer-eAVNsuX8.mjs.map +1 -0
- package/dist/renderer-mcePkmUe.mjs +5 -0
- package/dist/{renderer-CT_aJBk2.mjs → renderer-uorPCWdC.mjs} +3 -3
- package/dist/{renderer-CT_aJBk2.mjs.map → renderer-uorPCWdC.mjs.map} +1 -1
- package/dist/{renderer-BMnX_-PZ.mjs → renderer-xLQ_nkmy.mjs} +3 -3
- package/dist/{renderer-BMnX_-PZ.mjs.map → renderer-xLQ_nkmy.mjs.map} +1 -1
- package/dist/{renderers-CP8CFWDs-fYqxoIKK.mjs → renderers-CP8CFWDs-ywy4xljX.mjs} +2 -2
- package/dist/{renderers-CP8CFWDs-fYqxoIKK.mjs.map → renderers-CP8CFWDs-ywy4xljX.mjs.map} +1 -1
- package/dist/signals/index.d.mts +5 -5
- package/dist/signals/index.mjs +4 -4
- package/dist/{src-DggYlKaX.mjs → src-B0KFNjj4.mjs} +289 -59
- package/dist/src-B0KFNjj4.mjs.map +1 -0
- package/package.json +58 -58
- package/dist/dist-CnFcSau0.mjs.map +0 -1
- package/dist/index-Ced1Ry4S.d.mts.map +0 -1
- package/dist/index-Ds9_v60R.d.mts.map +0 -1
- package/dist/preview-engine/chunk-3OXRGTQ2.mjs +0 -2390
- package/dist/preview-engine/chunk-7EYVBRN3.mjs +0 -480
- package/dist/preview-engine/chunk-7WBDEZ2A.mjs +0 -1974
- package/dist/preview-engine/chunk-HPP52AQI.mjs +0 -4
- package/dist/preview-engine/renderers-CCOEGTZJ.mjs +0 -228
- package/dist/program-CqQDWfSV.mjs.map +0 -1
- package/dist/renderer-68XHoE2b.mjs +0 -5
- package/dist/renderer-AqUForA-.mjs +0 -5
- package/dist/renderer-B0J-uGBG.mjs +0 -5
- package/dist/renderer-BF2R0rwb.mjs +0 -5
- package/dist/renderer-BLrO9lqK.mjs +0 -5
- package/dist/renderer-BMy8jXhL.mjs +0 -5
- package/dist/renderer-BUxENp9L.mjs +0 -5
- package/dist/renderer-C-ebryrM.mjs +0 -5
- package/dist/renderer-C8Gbs3kr.mjs +0 -5
- package/dist/renderer-CFZvMv2-.mjs +0 -5
- package/dist/renderer-CGXW7mOs.mjs +0 -5
- package/dist/renderer-CNq6OGbb.mjs +0 -5
- package/dist/renderer-CO-Ddz6-.mjs +0 -5
- package/dist/renderer-CRdxAsP7.mjs +0 -5
- package/dist/renderer-CZLo0ALi.mjs +0 -5
- package/dist/renderer-CdvVUkhR.mjs +0 -5
- package/dist/renderer-Cjg7kmTq.mjs +0 -5
- package/dist/renderer-CxKymhVa.mjs +0 -5
- package/dist/renderer-Cxlpu3pN.mjs +0 -5
- package/dist/renderer-Cz6qZ2Ii.mjs +0 -5
- package/dist/renderer-DDGvF2YA.mjs +0 -5
- package/dist/renderer-DFxtOKpi.mjs +0 -5
- package/dist/renderer-DGBNjTsB.mjs +0 -6
- package/dist/renderer-DRLtfxdW.mjs.map +0 -1
- package/dist/renderer-DUFcdZmw.mjs +0 -5
- package/dist/renderer-DUMu6EOH.mjs +0 -5
- package/dist/renderer-DdULrvJo.mjs +0 -5
- package/dist/renderer-DoaOOP6_.mjs +0 -5
- package/dist/renderer-DqmZqV-a.mjs +0 -5
- package/dist/renderer-LxTQ2E-G.mjs +0 -5
- package/dist/renderer-SpU-RddZ.mjs +0 -5
- package/dist/renderer-W6ahCM9z.mjs +0 -5
- package/dist/renderer-gGqtzw-S.mjs +0 -5
- package/dist/renderer-l0Wn1AoV.mjs +0 -5
- package/dist/renderer-rpXHvMZG.mjs +0 -5
- package/dist/renderer-twdsKOiz.mjs +0 -5
- package/dist/renderer-uJz-eIqO.mjs +0 -5
- package/dist/src-DggYlKaX.mjs.map +0 -1
|
@@ -10052,6 +10052,7 @@ function resolveEnvironment(opts) {
|
|
|
10052
10052
|
* normal matrix computation for non-uniform surface scaling,
|
|
10053
10053
|
* and binary uniform buffer packing for WGSL shaders.
|
|
10054
10054
|
*/
|
|
10055
|
+
/** Slots retained in the legacy uniform prefix; actual direct lights use storage. */
|
|
10055
10056
|
const MAX_LIGHTS = 8;
|
|
10056
10057
|
/**
|
|
10057
10058
|
* 16 (ambient) + 16 (params) + 8 * 64 (lights), then the physical-shading
|
|
@@ -10255,7 +10256,7 @@ const Light3D = {
|
|
|
10255
10256
|
ambientR += col[0] * int$1;
|
|
10256
10257
|
ambientG += col[1] * int$1;
|
|
10257
10258
|
ambientB += col[2] * int$1;
|
|
10258
|
-
} else
|
|
10259
|
+
} else directLights.push(Light3D.processLight(l));
|
|
10259
10260
|
buffer[0] = ambientR;
|
|
10260
10261
|
buffer[1] = ambientG;
|
|
10261
10262
|
buffer[2] = ambientB;
|
|
@@ -10287,12 +10288,42 @@ const Light3D = {
|
|
|
10287
10288
|
}
|
|
10288
10289
|
return buffer;
|
|
10289
10290
|
},
|
|
10291
|
+
packDirectLights(lights, shadows = []) {
|
|
10292
|
+
const direct = lights.filter((light) => (light.lightType ?? light.type) !== "ambient");
|
|
10293
|
+
const data = new Float32Array(Math.max(1, direct.length) * 40);
|
|
10294
|
+
const shadowLayers = new Map(shadows.map((shadow, layer) => [shadow.lightIndex, layer]));
|
|
10295
|
+
for (const [i, light] of direct.entries()) {
|
|
10296
|
+
const packed = Light3D.processLight(light);
|
|
10297
|
+
const offset = i * 40;
|
|
10298
|
+
data.set(packed.posType, offset);
|
|
10299
|
+
data.set(packed.dirRadius, offset + 4);
|
|
10300
|
+
data.set(packed.colorIntensity, offset + 8);
|
|
10301
|
+
data.set(packed.spotParams, offset + 12);
|
|
10302
|
+
const layer = shadowLayers.get(i);
|
|
10303
|
+
const shadow = layer === void 0 ? void 0 : shadows[layer];
|
|
10304
|
+
if (shadow && layer !== void 0) {
|
|
10305
|
+
for (let j = 0; j < 16; j++) data[offset + 16 + j] = shadow.matrix[j] ?? 0;
|
|
10306
|
+
data.set([
|
|
10307
|
+
shadow.softness,
|
|
10308
|
+
shadow.mapSize,
|
|
10309
|
+
layer,
|
|
10310
|
+
1
|
|
10311
|
+
], offset + 32);
|
|
10312
|
+
data.set([
|
|
10313
|
+
shadow.bias,
|
|
10314
|
+
shadow.normalOffset,
|
|
10315
|
+
shadow.darkness,
|
|
10316
|
+
0
|
|
10317
|
+
], offset + 36);
|
|
10318
|
+
}
|
|
10319
|
+
}
|
|
10320
|
+
return data;
|
|
10321
|
+
},
|
|
10290
10322
|
shadowCasterIndex(lights) {
|
|
10291
10323
|
let index = 0;
|
|
10292
10324
|
for (const l of lights) {
|
|
10293
10325
|
const kind = l.lightType ?? l.type;
|
|
10294
10326
|
if (kind === "ambient") continue;
|
|
10295
|
-
if (index >= MAX_LIGHTS) break;
|
|
10296
10327
|
if (l.castShadow && (kind === "directional" || kind === "spot")) return index;
|
|
10297
10328
|
index++;
|
|
10298
10329
|
}
|
|
@@ -10400,7 +10431,7 @@ var Path3D = class Path3D$1 {
|
|
|
10400
10431
|
0,
|
|
10401
10432
|
0
|
|
10402
10433
|
];
|
|
10403
|
-
|
|
10434
|
+
const b0 = Vector3Math.normalize(Vector3Math.cross(t0, n0));
|
|
10404
10435
|
this.frames[0] = {
|
|
10405
10436
|
normal: n0,
|
|
10406
10437
|
binormal: b0,
|
|
@@ -10443,6 +10474,21 @@ var Path3D = class Path3D$1 {
|
|
|
10443
10474
|
];
|
|
10444
10475
|
}
|
|
10445
10476
|
/**
|
|
10477
|
+
* Returns a copy of the discrete samples `[position, tangent, distance]` along this path.
|
|
10478
|
+
*/
|
|
10479
|
+
getSamples() {
|
|
10480
|
+
return this.samples;
|
|
10481
|
+
}
|
|
10482
|
+
/**
|
|
10483
|
+
* Evaluates `count` evenly arc-length-spaced 3D positions along the path.
|
|
10484
|
+
*/
|
|
10485
|
+
getPoints(count = 64) {
|
|
10486
|
+
const n = Math.max(2, Math.round(count));
|
|
10487
|
+
const pts = [];
|
|
10488
|
+
for (let i = 0; i < n; i++) pts.push(this.getPointAt(i / (n - 1)).position);
|
|
10489
|
+
return pts;
|
|
10490
|
+
}
|
|
10491
|
+
/**
|
|
10446
10492
|
* Evaluates point, tangent, normal, binormal, and rotation at normalized progress u in [0, 1].
|
|
10447
10493
|
* Progression moves with constant velocity along the arc length of the path.
|
|
10448
10494
|
*/
|
|
@@ -17784,8 +17830,6 @@ function transformModelBounds(bounds, { offset, scale }) {
|
|
|
17784
17830
|
* hierarchy into model-space matrices, and turns a skin's joints into the
|
|
17785
17831
|
* joint matrices the mesh shader blends (joint world × inverse bind).
|
|
17786
17832
|
*/
|
|
17787
|
-
/** Joints per skin the mesh shader holds (mesh3d.wgsl jointMatrices). */
|
|
17788
|
-
const MAX_JOINTS = 128;
|
|
17789
17833
|
/** Column-major translate · rotate(quaternion) · scale. */
|
|
17790
17834
|
function trsMatrix(t, q, s) {
|
|
17791
17835
|
const [x, y, z, w] = q;
|
|
@@ -17927,12 +17971,12 @@ function poseNodes(model, clip, time$2) {
|
|
|
17927
17971
|
};
|
|
17928
17972
|
return nodes.map((_, i) => resolve$1$1(i));
|
|
17929
17973
|
}
|
|
17930
|
-
/** The joint matrices of one skin for a posed scene graph
|
|
17974
|
+
/** The joint matrices of one skin for a posed scene graph. */
|
|
17931
17975
|
function jointMatrices(model, skinIndex, world) {
|
|
17932
17976
|
const skin = model.skins?.[skinIndex];
|
|
17933
17977
|
if (!skin) throw new Error(`model has no skin ${skinIndex}`);
|
|
17934
|
-
const out = new Float32Array(
|
|
17935
|
-
for (let j = 0; j <
|
|
17978
|
+
const out = new Float32Array(Math.max(1, skin.joints.length) * 16);
|
|
17979
|
+
for (let j = 0; j < Math.max(1, skin.joints.length); j++) {
|
|
17936
17980
|
const node = skin.joints[j];
|
|
17937
17981
|
if (node === void 0) {
|
|
17938
17982
|
out.set(Matrix4Math.identity(), j * 16);
|
|
@@ -18354,7 +18398,6 @@ var FbxLoader = class FbxLoader$1 {
|
|
|
18354
18398
|
influences.set(cp, list);
|
|
18355
18399
|
}
|
|
18356
18400
|
}
|
|
18357
|
-
if (joints.length > MAX_JOINTS) throw new Error(`FBX skin has ${joints.length} bones; the mesh shader holds ${MAX_JOINTS}`);
|
|
18358
18401
|
if (joints.length > 0) {
|
|
18359
18402
|
skinIndex = skins.length;
|
|
18360
18403
|
skins.push({
|
|
@@ -20054,7 +20097,6 @@ var GltfLoader = class GltfLoader$1 {
|
|
|
20054
20097
|
});
|
|
20055
20098
|
});
|
|
20056
20099
|
}
|
|
20057
|
-
for (const skin of skins) if (skin.joints.length > MAX_JOINTS) throw new Error(`glTF skin has ${skin.joints.length} joints; the mesh shader holds ${MAX_JOINTS}`);
|
|
20058
20100
|
if (!Number.isFinite(minX)) {
|
|
20059
20101
|
minX = minY = minZ = 0;
|
|
20060
20102
|
maxX = maxY = maxZ = 0;
|
|
@@ -30950,6 +30992,16 @@ struct GPULight {
|
|
|
30950
30992
|
spotParams : vec4<f32>, // x = cos(outer), y = cos(inner), z = decay, w = unused
|
|
30951
30993
|
};
|
|
30952
30994
|
|
|
30995
|
+
struct DirectLight {
|
|
30996
|
+
posType : vec4<f32>,
|
|
30997
|
+
dirRadius : vec4<f32>,
|
|
30998
|
+
colorIntensity : vec4<f32>,
|
|
30999
|
+
spotParams : vec4<f32>,
|
|
31000
|
+
shadowMatrix : mat4x4<f32>,
|
|
31001
|
+
shadowParams : vec4<f32>,
|
|
31002
|
+
shadowBias : vec4<f32>,
|
|
31003
|
+
};
|
|
31004
|
+
|
|
30953
31005
|
struct LightsUniforms {
|
|
30954
31006
|
ambientColor : vec4<f32>, // rgb = ambient color * intensity (sRGB), w = unused
|
|
30955
31007
|
params : vec4<f32>, // x = numLights, y = hasLights, z = physical (1), w = tone mapping (0 none, 1 ACES, 2 AgX, 3 PBR Neutral)
|
|
@@ -31132,25 +31184,26 @@ var<private> POISSON : array<vec2<f32>, 12> = array<vec2<f32>, 12>(
|
|
|
31132
31184
|
|
|
31133
31185
|
/// 1 = fully lit, 0 = fully shadowed, for light index i.
|
|
31134
31186
|
fn shadowFactor(worldPos: vec3<f32>, N: vec3<f32>, i: i32) -> f32 {
|
|
31135
|
-
|
|
31187
|
+
let shadow = directLights[i];
|
|
31188
|
+
if (shadow.shadowParams.w < 0.5) {
|
|
31136
31189
|
return 1.0;
|
|
31137
31190
|
}
|
|
31138
|
-
let p = worldPos + N *
|
|
31139
|
-
let lp =
|
|
31191
|
+
let p = worldPos + N * shadow.shadowBias.y;
|
|
31192
|
+
let lp = shadow.shadowMatrix * vec4<f32>(p, 1.0);
|
|
31140
31193
|
let ndc = lp.xyz / lp.w;
|
|
31141
31194
|
let uv = vec2<f32>(ndc.x * 0.5 + 0.5, 0.5 - ndc.y * 0.5);
|
|
31142
31195
|
if (lp.w <= 0.0 || uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0 || ndc.z > 1.0) {
|
|
31143
31196
|
return 1.0;
|
|
31144
31197
|
}
|
|
31145
|
-
let texel = 1.0 / max(
|
|
31146
|
-
let radius =
|
|
31147
|
-
let depthRef = ndc.z -
|
|
31198
|
+
let texel = 1.0 / max(shadow.shadowParams.y, 1.0);
|
|
31199
|
+
let radius = shadow.shadowParams.x * texel;
|
|
31200
|
+
let depthRef = ndc.z - shadow.shadowBias.x;
|
|
31148
31201
|
var lit = 0.0;
|
|
31149
31202
|
for (var k = 0; k < 12; k++) {
|
|
31150
|
-
lit += textureSampleCompareLevel(shadowMap, shadowSampler, uv + POISSON[k] * radius, depthRef);
|
|
31203
|
+
lit += textureSampleCompareLevel(shadowMap, shadowSampler, uv + POISSON[k] * radius, i32(shadow.shadowParams.z), depthRef);
|
|
31151
31204
|
}
|
|
31152
31205
|
lit = lit / 12.0;
|
|
31153
|
-
return mix(1.0, lit,
|
|
31206
|
+
return mix(1.0, lit, shadow.shadowBias.z);
|
|
31154
31207
|
}
|
|
31155
31208
|
|
|
31156
31209
|
// ── Lights ────────────────────────────────────────────────────────────
|
|
@@ -31163,7 +31216,7 @@ struct LightSample {
|
|
|
31163
31216
|
|
|
31164
31217
|
fn sampleLight(i: i32, worldPos: vec3<f32>) -> LightSample {
|
|
31165
31218
|
var out = LightSample(vec3<f32>(0.0, 0.0, 1.0), 1.0, false);
|
|
31166
|
-
let light =
|
|
31219
|
+
let light = directLights[i];
|
|
31167
31220
|
let lightType = light.posType.w;
|
|
31168
31221
|
if (lightType > 0.5 && lightType < 1.5) {
|
|
31169
31222
|
out.L = normalize(-light.dirRadius.xyz);
|
|
@@ -31212,15 +31265,12 @@ fn applyLighting3D(worldPos: vec3<f32>, worldNormal: vec3<f32>, baseColor: vec3<
|
|
|
31212
31265
|
|
|
31213
31266
|
var totalIllumination = baseColor * (lights.ambientColor.rgb * ambientInt);
|
|
31214
31267
|
let numLights = i32(lights.params.x);
|
|
31215
|
-
for (var i = 0; i <
|
|
31216
|
-
if (i >= numLights) {
|
|
31217
|
-
break;
|
|
31218
|
-
}
|
|
31268
|
+
for (var i = 0; i < numLights; i++) {
|
|
31219
31269
|
let ls = sampleLight(i, worldPos);
|
|
31220
31270
|
if (!ls.valid) {
|
|
31221
31271
|
continue;
|
|
31222
31272
|
}
|
|
31223
|
-
let light =
|
|
31273
|
+
let light = directLights[i];
|
|
31224
31274
|
let lightColor = light.colorIntensity.rgb;
|
|
31225
31275
|
let intensity = light.colorIntensity.w;
|
|
31226
31276
|
let NdotL = max(dot(N, ls.L), 0.0);
|
|
@@ -31253,15 +31303,12 @@ fn shadePhysical(worldPos: vec3<f32>, worldNormal: vec3<f32>, albedo: vec3<f32>,
|
|
|
31253
31303
|
|
|
31254
31304
|
var lo = vec3<f32>(0.0);
|
|
31255
31305
|
let numLights = i32(lights.params.x);
|
|
31256
|
-
for (var i = 0; i <
|
|
31257
|
-
if (i >= numLights) {
|
|
31258
|
-
break;
|
|
31259
|
-
}
|
|
31306
|
+
for (var i = 0; i < numLights; i++) {
|
|
31260
31307
|
let ls = sampleLight(i, worldPos);
|
|
31261
31308
|
if (!ls.valid) {
|
|
31262
31309
|
continue;
|
|
31263
31310
|
}
|
|
31264
|
-
let light =
|
|
31311
|
+
let light = directLights[i];
|
|
31265
31312
|
let nDotL = max(dot(N, ls.L), 0.0);
|
|
31266
31313
|
if (nDotL <= 0.0) {
|
|
31267
31314
|
continue;
|
|
@@ -31358,8 +31405,9 @@ fn shadeSurface(worldPos: vec3<f32>, worldNormal: vec3<f32>, baseColor: vec3<f32
|
|
|
31358
31405
|
/** Group-3 bindings every lit 3D shader declares. */
|
|
31359
31406
|
const lightsBindingsWgsl = `
|
|
31360
31407
|
@group(3) @binding(0) var<uniform> lights : LightsUniforms;
|
|
31361
|
-
@group(3) @binding(1) var shadowMap :
|
|
31408
|
+
@group(3) @binding(1) var shadowMap : texture_depth_2d_array;
|
|
31362
31409
|
@group(3) @binding(2) var shadowSampler : sampler_comparison;
|
|
31410
|
+
@group(3) @binding(3) var<storage, read> directLights : array<DirectLight>;
|
|
31363
31411
|
`;
|
|
31364
31412
|
/**
|
|
31365
31413
|
* The 3D pipelines draw into one of four target sets: color; color + linear
|
|
@@ -32385,7 +32433,7 @@ fn matteCoverage(fragPos : vec2<f32>) -> f32 {
|
|
|
32385
32433
|
}
|
|
32386
32434
|
/**
|
|
32387
32435
|
* WebGPU WGSL shaders for 3D static and skinned meshes.
|
|
32388
|
-
* Supports GPU Linear Blend Skinning
|
|
32436
|
+
* Supports GPU Linear Blend Skinning,
|
|
32389
32437
|
* the shared 3D surface shading (Blinn-Phong, or physical GGX + image-based light
|
|
32390
32438
|
* in scenes with an environment) or toon shading, shadow maps, emissive,
|
|
32391
32439
|
* alpha-cutoff (glTF MASK) materials,
|
|
@@ -32398,7 +32446,7 @@ struct ModelUniforms {
|
|
|
32398
32446
|
modelMatrix : mat4x4<f32>,
|
|
32399
32447
|
normalMatrix : mat4x4<f32>,
|
|
32400
32448
|
colorTint : vec4<f32>,
|
|
32401
|
-
params : vec4<f32>, // x = opacity, y = twoSided, z = isSkinned, w = flags (bit 0 instanced, bit 1 map UVs)
|
|
32449
|
+
params : vec4<f32>, // x = opacity, y = twoSided, z = isSkinned, w = flags (bit 0 instanced, bit 1 map UVs, bit 2 matrix instances)
|
|
32402
32450
|
materialParams : vec4<f32>, // x = shininess, y = specularIntensity, z = ambientIntensity, w = materialMode (0=unlit, 1=lit, 2=toon)
|
|
32403
32451
|
shade : vec4<f32>, // rgb = toon shadow-side color multiplier, a = alpha cutoff (0 = none)
|
|
32404
32452
|
pbr : vec4<f32>, // x = roughness (<0 = default), y = metallic
|
|
@@ -32407,7 +32455,7 @@ struct ModelUniforms {
|
|
|
32407
32455
|
};
|
|
32408
32456
|
|
|
32409
32457
|
struct SkinningUniforms {
|
|
32410
|
-
jointMatrices : array<mat4x4<f32
|
|
32458
|
+
jointMatrices : array<mat4x4<f32>>,
|
|
32411
32459
|
};
|
|
32412
32460
|
|
|
32413
32461
|
struct InstanceData {
|
|
@@ -32419,7 +32467,7 @@ struct InstanceData {
|
|
|
32419
32467
|
|
|
32420
32468
|
@group(0) @binding(0) var<uniform> cam : CameraUniforms;
|
|
32421
32469
|
@group(1) @binding(0) var<uniform> model : ModelUniforms;
|
|
32422
|
-
@group(1) @binding(1) var<
|
|
32470
|
+
@group(1) @binding(1) var<storage, read> skinning : SkinningUniforms;
|
|
32423
32471
|
${matte3dWgsl(1, 2)}@group(1) @binding(3) var backdropTex : texture_2d<f32>;
|
|
32424
32472
|
@group(1) @binding(4) var<storage, read> instances : array<InstanceData>;
|
|
32425
32473
|
@group(2) @binding(0) var texSampler : sampler;
|
|
@@ -32505,7 +32553,14 @@ fn vs_main(
|
|
|
32505
32553
|
var instColor = vec4<f32>(1.0);
|
|
32506
32554
|
var instEmissive = vec4<f32>(0.0);
|
|
32507
32555
|
|
|
32508
|
-
if ((u32(model.params.w) &
|
|
32556
|
+
if ((u32(model.params.w) & 4u) != 0u) {
|
|
32557
|
+
let a = instances[instanceIndex * 2u];
|
|
32558
|
+
let b = instances[instanceIndex * 2u + 1u];
|
|
32559
|
+
let instanceModel = mat4x4<f32>(a.posScale, a.quat, a.color, a.emissive);
|
|
32560
|
+
let instanceNormal = mat4x4<f32>(b.posScale, b.quat, b.color, b.emissive);
|
|
32561
|
+
localPos = (instanceModel * vec4<f32>(localPos, 1.0)).xyz;
|
|
32562
|
+
localNorm = (instanceNormal * vec4<f32>(localNorm, 0.0)).xyz;
|
|
32563
|
+
} else if ((u32(model.params.w) & 1u) != 0u) {
|
|
32509
32564
|
let inst = instances[instanceIndex];
|
|
32510
32565
|
let scaledPos = localPos * inst.posScale.w;
|
|
32511
32566
|
localPos = rotateVecByQuat(scaledPos, inst.quat) + inst.posScale.xyz;
|
|
@@ -33057,12 +33112,20 @@ function createLightsLayout(device, label = "Lights3DLayout") {
|
|
|
33057
33112
|
{
|
|
33058
33113
|
binding: 1,
|
|
33059
33114
|
visibility: GPUShaderStage.FRAGMENT,
|
|
33060
|
-
texture: {
|
|
33115
|
+
texture: {
|
|
33116
|
+
sampleType: "depth",
|
|
33117
|
+
viewDimension: "2d-array"
|
|
33118
|
+
}
|
|
33061
33119
|
},
|
|
33062
33120
|
{
|
|
33063
33121
|
binding: 2,
|
|
33064
33122
|
visibility: GPUShaderStage.FRAGMENT,
|
|
33065
33123
|
sampler: { type: "comparison" }
|
|
33124
|
+
},
|
|
33125
|
+
{
|
|
33126
|
+
binding: 3,
|
|
33127
|
+
visibility: GPUShaderStage.FRAGMENT,
|
|
33128
|
+
buffer: { type: "read-only-storage" }
|
|
33066
33129
|
}
|
|
33067
33130
|
]
|
|
33068
33131
|
});
|
|
@@ -33367,7 +33430,7 @@ var Mesh3DPipeline = class {
|
|
|
33367
33430
|
constructor(device, format, depthFormat = "depth24plus", cameraLayout, lightsLayout, sampleCount = 1) {
|
|
33368
33431
|
this.device = device;
|
|
33369
33432
|
this.modelPool = new BufferPool((52 + SURFACE_PARAMS_FLOATS) * 4, GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST);
|
|
33370
|
-
this.skinningPool = new BufferPool(
|
|
33433
|
+
this.skinningPool = new BufferPool(64, GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST);
|
|
33371
33434
|
const module$1 = device.createShaderModule({
|
|
33372
33435
|
label: "mesh3d.wgsl",
|
|
33373
33436
|
code: mesh3dWgsl
|
|
@@ -33391,7 +33454,7 @@ var Mesh3DPipeline = class {
|
|
|
33391
33454
|
{
|
|
33392
33455
|
binding: 1,
|
|
33393
33456
|
visibility: GPUShaderStage.VERTEX,
|
|
33394
|
-
buffer: { type: "
|
|
33457
|
+
buffer: { type: "read-only-storage" }
|
|
33395
33458
|
},
|
|
33396
33459
|
matteLayoutEntry(2),
|
|
33397
33460
|
matteLayoutEntry(3),
|
|
@@ -33642,16 +33705,11 @@ var Mesh3DPipeline = class {
|
|
|
33642
33705
|
width: 1,
|
|
33643
33706
|
height: 1
|
|
33644
33707
|
});
|
|
33645
|
-
const idMatrices = new Float32Array(
|
|
33646
|
-
|
|
33647
|
-
idMatrices[b * 16] = 1;
|
|
33648
|
-
idMatrices[b * 16 + 5] = 1;
|
|
33649
|
-
idMatrices[b * 16 + 10] = 1;
|
|
33650
|
-
idMatrices[b * 16 + 15] = 1;
|
|
33651
|
-
}
|
|
33708
|
+
const idMatrices = new Float32Array(16);
|
|
33709
|
+
idMatrices[0] = idMatrices[5] = idMatrices[10] = idMatrices[15] = 1;
|
|
33652
33710
|
this.defaultSkinningBuffer = device.createBuffer({
|
|
33653
|
-
size:
|
|
33654
|
-
usage: GPUBufferUsage.
|
|
33711
|
+
size: 64,
|
|
33712
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
|
|
33655
33713
|
mappedAtCreation: true
|
|
33656
33714
|
});
|
|
33657
33715
|
new Float32Array(this.defaultSkinningBuffer.getMappedRange()).set(idMatrices);
|
|
@@ -33690,7 +33748,7 @@ var Mesh3DPipeline = class {
|
|
|
33690
33748
|
this.modelData[36] = data.opacity ?? 1;
|
|
33691
33749
|
this.modelData[37] = data.twoSided ? 1 : 0;
|
|
33692
33750
|
this.modelData[38] = data.isSkinned ? 1 : 0;
|
|
33693
|
-
this.modelData[39] = (data.isInstanced || data.instanceBuffer ? 1 : 0) + (data.hasMapUvs ? 2 : 0);
|
|
33751
|
+
this.modelData[39] = (data.isInstanced || data.instanceBuffer ? 1 : 0) + (data.hasMapUvs ? 2 : 0) + (data.matrixInstances ? 4 : 0);
|
|
33694
33752
|
const shininess = data.roughness !== void 0 ? Math.max(1, (1 - data.roughness) * 128) : data.shininess ?? 32;
|
|
33695
33753
|
const specInt = data.metallic !== void 0 ? data.metallic : data.specularIntensity ?? .5;
|
|
33696
33754
|
const ambientInt = data.ambientIntensity ?? 1;
|
|
@@ -33723,6 +33781,7 @@ var Mesh3DPipeline = class {
|
|
|
33723
33781
|
this.modelData[51] = glass.ior;
|
|
33724
33782
|
}
|
|
33725
33783
|
const modelBuffer = this.modelPool.getBuffer(this.device, this.modelData);
|
|
33784
|
+
if (data.skinningMatrices && data.skinningMatrices.byteLength > this.device.limits.maxStorageBufferBindingSize) throw new Error(`Skinning data requires ${data.skinningMatrices.byteLength} bytes, exceeding the device storage binding limit of ${this.device.limits.maxStorageBufferBindingSize} bytes`);
|
|
33726
33785
|
const skinningBuffer = data.isSkinned && data.skinningMatrices ? this.skinningPool.getBuffer(this.device, data.skinningMatrices) : this.defaultSkinningBuffer;
|
|
33727
33786
|
return this.device.createBindGroup({
|
|
33728
33787
|
layout: this.modelLayout,
|
|
@@ -34119,37 +34178,13 @@ var MotionBlurPipeline = class {
|
|
|
34119
34178
|
}
|
|
34120
34179
|
};
|
|
34121
34180
|
function parseHexOrRgbColor(colorStr) {
|
|
34122
|
-
const c = colorStr
|
|
34123
|
-
if (c.
|
|
34124
|
-
|
|
34125
|
-
|
|
34126
|
-
|
|
34127
|
-
|
|
34128
|
-
|
|
34129
|
-
1
|
|
34130
|
-
];
|
|
34131
|
-
if (hex.length === 6) return [
|
|
34132
|
-
Number.parseInt(hex.slice(0, 2), 16) / 255,
|
|
34133
|
-
Number.parseInt(hex.slice(2, 4), 16) / 255,
|
|
34134
|
-
Number.parseInt(hex.slice(4, 6), 16) / 255,
|
|
34135
|
-
1
|
|
34136
|
-
];
|
|
34137
|
-
if (hex.length === 8) return [
|
|
34138
|
-
Number.parseInt(hex.slice(0, 2), 16) / 255,
|
|
34139
|
-
Number.parseInt(hex.slice(2, 4), 16) / 255,
|
|
34140
|
-
Number.parseInt(hex.slice(4, 6), 16) / 255,
|
|
34141
|
-
Number.parseInt(hex.slice(6, 8), 16) / 255
|
|
34142
|
-
];
|
|
34143
|
-
}
|
|
34144
|
-
if (c.startsWith("rgb")) {
|
|
34145
|
-
const parts = c.replace(/rgba?\(/, "").replace(/\)/, "").split(",").map((p) => Number.parseFloat(p.trim()));
|
|
34146
|
-
return [
|
|
34147
|
-
(parts[0] ?? 0) / 255,
|
|
34148
|
-
(parts[1] ?? 0) / 255,
|
|
34149
|
-
(parts[2] ?? 0) / 255,
|
|
34150
|
-
parts[3] !== void 0 ? parts[3] : 1
|
|
34151
|
-
];
|
|
34152
|
-
}
|
|
34181
|
+
const c = parseColor(colorStr);
|
|
34182
|
+
if (c.a > 0 || colorStr.trim().toLowerCase() === "transparent") return [
|
|
34183
|
+
c.r,
|
|
34184
|
+
c.g,
|
|
34185
|
+
c.b,
|
|
34186
|
+
c.a
|
|
34187
|
+
];
|
|
34153
34188
|
return [
|
|
34154
34189
|
1,
|
|
34155
34190
|
1,
|
|
@@ -34298,7 +34333,7 @@ function extractGlyphContours(glyph, glyphX, glyphY, scale, flattening) {
|
|
|
34298
34333
|
};
|
|
34299
34334
|
}
|
|
34300
34335
|
/** Side-wall segments meeting at more than this angle (30°) keep a hard edge. */
|
|
34301
|
-
const SIDE_CREASE_COS = Math.cos(30 * Math.PI / 180);
|
|
34336
|
+
const SIDE_CREASE_COS$1 = Math.cos(30 * Math.PI / 180);
|
|
34302
34337
|
/**
|
|
34303
34338
|
* Group a glyph's contours into filled outlines and their holes by nesting
|
|
34304
34339
|
* depth: a contour inside an even number of others is an outline (the ring
|
|
@@ -34597,7 +34632,7 @@ function generateExtrudedTextGeometry(options) {
|
|
|
34597
34632
|
const u = along / perimeter;
|
|
34598
34633
|
const sx = incoming.x + outgoing.x;
|
|
34599
34634
|
const sy = incoming.y + outgoing.y;
|
|
34600
|
-
const averaged = incoming.x * outgoing.x + incoming.y * outgoing.y >= SIDE_CREASE_COS ? {
|
|
34635
|
+
const averaged = incoming.x * outgoing.x + incoming.y * outgoing.y >= SIDE_CREASE_COS$1 ? {
|
|
34601
34636
|
x: sx / Math.hypot(sx, sy),
|
|
34602
34637
|
y: sy / Math.hypot(sx, sy)
|
|
34603
34638
|
} : null;
|
|
@@ -34736,11 +34771,14 @@ var MeshBuilder = class {
|
|
|
34736
34771
|
positions = [];
|
|
34737
34772
|
normals = [];
|
|
34738
34773
|
uvs = [];
|
|
34774
|
+
colors = [];
|
|
34739
34775
|
indices = [];
|
|
34740
|
-
|
|
34776
|
+
topology;
|
|
34777
|
+
vertex(p, n, uv, color) {
|
|
34741
34778
|
this.positions.push(p[0], p[1], p[2]);
|
|
34742
34779
|
this.normals.push(n[0], n[1], n[2]);
|
|
34743
34780
|
this.uvs.push(uv[0], uv[1]);
|
|
34781
|
+
if (color) this.colors.push(color[0], color[1], color[2], color[3]);
|
|
34744
34782
|
return this.positions.length / 3 - 1;
|
|
34745
34783
|
}
|
|
34746
34784
|
/**
|
|
@@ -34760,7 +34798,7 @@ var MeshBuilder = class {
|
|
|
34760
34798
|
}
|
|
34761
34799
|
build(name) {
|
|
34762
34800
|
const count = this.positions.length / 3;
|
|
34763
|
-
|
|
34801
|
+
const mesh = {
|
|
34764
34802
|
id: `${name}-mesh`,
|
|
34765
34803
|
name,
|
|
34766
34804
|
positions: new Float32Array(this.positions),
|
|
@@ -34769,6 +34807,9 @@ var MeshBuilder = class {
|
|
|
34769
34807
|
indices: count > 65535 ? new Uint32Array(this.indices) : new Uint16Array(this.indices),
|
|
34770
34808
|
materialName: `${name}-material`
|
|
34771
34809
|
};
|
|
34810
|
+
if (this.topology) mesh.topology = this.topology;
|
|
34811
|
+
if (this.colors.length === count * 4 && this.colors.length > 0) mesh.colors = new Float32Array(this.colors);
|
|
34812
|
+
return mesh;
|
|
34772
34813
|
}
|
|
34773
34814
|
};
|
|
34774
34815
|
function normalize(v) {
|
|
@@ -34783,6 +34824,23 @@ function normalize(v) {
|
|
|
34783
34824
|
0
|
|
34784
34825
|
];
|
|
34785
34826
|
}
|
|
34827
|
+
function sub3(a, b) {
|
|
34828
|
+
return [
|
|
34829
|
+
a[0] - b[0],
|
|
34830
|
+
a[1] - b[1],
|
|
34831
|
+
a[2] - b[2]
|
|
34832
|
+
];
|
|
34833
|
+
}
|
|
34834
|
+
function dot3(a, b) {
|
|
34835
|
+
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
|
34836
|
+
}
|
|
34837
|
+
function cross3(a, b) {
|
|
34838
|
+
return [
|
|
34839
|
+
a[1] * b[2] - a[2] * b[1],
|
|
34840
|
+
a[2] * b[0] - a[0] * b[2],
|
|
34841
|
+
a[0] * b[1] - a[1] * b[0]
|
|
34842
|
+
];
|
|
34843
|
+
}
|
|
34786
34844
|
/**
|
|
34787
34845
|
* 1D samples across a side of half-extent `e` whose ends round off with
|
|
34788
34846
|
* radius `r`: arc-spaced through each rounded zone, nothing in between, so
|
|
@@ -34943,29 +35001,87 @@ function sphere(o, mb) {
|
|
|
34943
35001
|
}
|
|
34944
35002
|
function cylinder(o, mb) {
|
|
34945
35003
|
const seg = Math.max(3, Math.round(o.segments ?? 32));
|
|
34946
|
-
const rTop = o.radiusTop ?? o.radius ?? 50;
|
|
34947
|
-
const rBottom = o.radiusBottom ?? o.radius ?? 50;
|
|
35004
|
+
const rTop = Math.max(0, o.radiusTop ?? o.radius ?? 50);
|
|
35005
|
+
const rBottom = Math.max(0, o.radiusBottom ?? o.radius ?? 50);
|
|
34948
35006
|
const hy = o.height / 2;
|
|
34949
|
-
|
|
34950
|
-
|
|
34951
|
-
const
|
|
34952
|
-
const
|
|
34953
|
-
|
|
34954
|
-
|
|
34955
|
-
|
|
34956
|
-
|
|
34957
|
-
|
|
34958
|
-
|
|
34959
|
-
|
|
34960
|
-
|
|
34961
|
-
|
|
34962
|
-
|
|
34963
|
-
|
|
34964
|
-
|
|
34965
|
-
|
|
35007
|
+
if (o.flatShaded) for (let i = 0; i < seg; i++) {
|
|
35008
|
+
const theta0 = i / seg * Math.PI * 2;
|
|
35009
|
+
const theta1 = (i + 1) / seg * Math.PI * 2;
|
|
35010
|
+
const c0 = Math.cos(theta0);
|
|
35011
|
+
const s0 = Math.sin(theta0);
|
|
35012
|
+
const c1 = Math.cos(theta1);
|
|
35013
|
+
const s1 = Math.sin(theta1);
|
|
35014
|
+
const t0 = [
|
|
35015
|
+
c0 * rTop,
|
|
35016
|
+
-hy,
|
|
35017
|
+
s0 * rTop
|
|
35018
|
+
];
|
|
35019
|
+
const t1 = [
|
|
35020
|
+
c1 * rTop,
|
|
35021
|
+
-hy,
|
|
35022
|
+
s1 * rTop
|
|
35023
|
+
];
|
|
35024
|
+
const b0 = [
|
|
35025
|
+
c0 * rBottom,
|
|
35026
|
+
hy,
|
|
35027
|
+
s0 * rBottom
|
|
35028
|
+
];
|
|
35029
|
+
const b1 = [
|
|
35030
|
+
c1 * rBottom,
|
|
35031
|
+
hy,
|
|
35032
|
+
s1 * rBottom
|
|
35033
|
+
];
|
|
35034
|
+
const fn = normalize(cross3(sub3(b0, t0), rBottom >= rTop ? sub3(b1, b0) : sub3(t1, t0)));
|
|
35035
|
+
const u0 = i / seg;
|
|
35036
|
+
const u1 = (i + 1) / seg;
|
|
35037
|
+
if (rTop <= 1e-6) {
|
|
35038
|
+
const apex = mb.vertex([
|
|
35039
|
+
0,
|
|
35040
|
+
-hy,
|
|
35041
|
+
0
|
|
35042
|
+
], fn, [(u0 + u1) / 2, 0]);
|
|
35043
|
+
const vB0 = mb.vertex(b0, fn, [u0, 1]);
|
|
35044
|
+
const vB1 = mb.vertex(b1, fn, [u1, 1]);
|
|
35045
|
+
mb.indices.push(apex, vB0, vB1);
|
|
35046
|
+
} else if (rBottom <= 1e-6) {
|
|
35047
|
+
const vT0 = mb.vertex(t0, fn, [u0, 0]);
|
|
35048
|
+
const vT1 = mb.vertex(t1, fn, [u1, 0]);
|
|
35049
|
+
const apex = mb.vertex([
|
|
35050
|
+
0,
|
|
35051
|
+
hy,
|
|
35052
|
+
0
|
|
35053
|
+
], fn, [(u0 + u1) / 2, 1]);
|
|
35054
|
+
mb.indices.push(vT0, apex, vT1);
|
|
35055
|
+
} else {
|
|
35056
|
+
const base = mb.vertex(t0, fn, [u0, 0]);
|
|
35057
|
+
mb.vertex(t1, fn, [u1, 0]);
|
|
35058
|
+
mb.vertex(b0, fn, [u0, 1]);
|
|
35059
|
+
mb.vertex(b1, fn, [u1, 1]);
|
|
35060
|
+
mb.indices.push(base, base + 2, base + 1, base + 1, base + 2, base + 3);
|
|
35061
|
+
}
|
|
35062
|
+
}
|
|
35063
|
+
else {
|
|
35064
|
+
const lean = o.height > 0 ? (rBottom - rTop) / o.height : 0;
|
|
35065
|
+
for (let j = 0; j <= 1; j++) {
|
|
35066
|
+
const rr = j === 0 ? rTop : rBottom;
|
|
35067
|
+
const y = j === 0 ? -hy : hy;
|
|
35068
|
+
for (let i = 0; i <= seg; i++) {
|
|
35069
|
+
const theta = i / seg * Math.PI * 2;
|
|
35070
|
+
const c = Math.cos(theta);
|
|
35071
|
+
const s = Math.sin(theta);
|
|
35072
|
+
mb.vertex([
|
|
35073
|
+
c * rr,
|
|
35074
|
+
y,
|
|
35075
|
+
s * rr
|
|
35076
|
+
], normalize([
|
|
35077
|
+
c,
|
|
35078
|
+
-lean,
|
|
35079
|
+
s
|
|
35080
|
+
]), [i / seg, j]);
|
|
35081
|
+
}
|
|
34966
35082
|
}
|
|
35083
|
+
mb.grid(0, seg, 1);
|
|
34967
35084
|
}
|
|
34968
|
-
mb.grid(0, seg, 1);
|
|
34969
35085
|
if (o.openEnded) return;
|
|
34970
35086
|
for (const [y, rr, ny] of [[
|
|
34971
35087
|
-hy,
|
|
@@ -34976,7 +35092,7 @@ function cylinder(o, mb) {
|
|
|
34976
35092
|
rBottom,
|
|
34977
35093
|
1
|
|
34978
35094
|
]]) {
|
|
34979
|
-
if (rr <=
|
|
35095
|
+
if (rr <= 1e-6) continue;
|
|
34980
35096
|
const center = mb.vertex([
|
|
34981
35097
|
0,
|
|
34982
35098
|
y,
|
|
@@ -34986,7 +35102,7 @@ function cylinder(o, mb) {
|
|
|
34986
35102
|
ny,
|
|
34987
35103
|
0
|
|
34988
35104
|
], [.5, .5]);
|
|
34989
|
-
const ring = mb.positions.length / 3;
|
|
35105
|
+
const ring$1 = mb.positions.length / 3;
|
|
34990
35106
|
for (let i = 0; i <= seg; i++) {
|
|
34991
35107
|
const theta = i / seg * Math.PI * 2;
|
|
34992
35108
|
const c = Math.cos(theta);
|
|
@@ -35001,97 +35117,2014 @@ function cylinder(o, mb) {
|
|
|
35001
35117
|
0
|
|
35002
35118
|
], [(c + 1) / 2, (s + 1) / 2]);
|
|
35003
35119
|
}
|
|
35004
|
-
for (let i = 0; i < seg; i++) if (ny < 0) mb.indices.push(center, ring + i, ring + i + 1);
|
|
35005
|
-
else mb.indices.push(center, ring + i + 1, ring + i);
|
|
35120
|
+
for (let i = 0; i < seg; i++) if (ny < 0) mb.indices.push(center, ring$1 + i, ring$1 + i + 1);
|
|
35121
|
+
else mb.indices.push(center, ring$1 + i + 1, ring$1 + i);
|
|
35006
35122
|
}
|
|
35007
35123
|
}
|
|
35008
|
-
|
|
35009
|
-
|
|
35010
|
-
|
|
35011
|
-
|
|
35012
|
-
|
|
35013
|
-
const
|
|
35014
|
-
const
|
|
35015
|
-
const
|
|
35016
|
-
const
|
|
35017
|
-
|
|
35018
|
-
const
|
|
35019
|
-
|
|
35020
|
-
const
|
|
35021
|
-
const
|
|
35022
|
-
|
|
35023
|
-
|
|
35024
|
-
|
|
35025
|
-
|
|
35026
|
-
|
|
35027
|
-
|
|
35028
|
-
|
|
35029
|
-
|
|
35030
|
-
|
|
35031
|
-
|
|
35032
|
-
|
|
35033
|
-
|
|
35034
|
-
|
|
35035
|
-
|
|
35036
|
-
|
|
35037
|
-
[
|
|
35038
|
-
|
|
35039
|
-
|
|
35124
|
+
/**
|
|
35125
|
+
* Torus centered at origin lying in the XY plane (so its hole faces a default
|
|
35126
|
+
* camera looking along +Z), with major radius `radius` and tube radius `tube`.
|
|
35127
|
+
*/
|
|
35128
|
+
function torus(o, mb) {
|
|
35129
|
+
const R = Math.max(.001, o.radius ?? 60);
|
|
35130
|
+
const r = Math.max(.001, o.tube ?? 20);
|
|
35131
|
+
const radialSegments = Math.max(3, Math.round(o.radialSegments ?? 24));
|
|
35132
|
+
const tubularSegments = Math.max(3, Math.round(o.tubularSegments ?? 48));
|
|
35133
|
+
const arcRad = (o.arc ?? 360) * Math.PI / 180;
|
|
35134
|
+
const base = mb.positions.length / 3;
|
|
35135
|
+
for (let j = 0; j <= radialSegments; j++) {
|
|
35136
|
+
const v = j / radialSegments * Math.PI * 2;
|
|
35137
|
+
const cv = Math.cos(v);
|
|
35138
|
+
const sv = Math.sin(v);
|
|
35139
|
+
for (let i = 0; i <= tubularSegments; i++) {
|
|
35140
|
+
const u = i / tubularSegments * arcRad;
|
|
35141
|
+
const cu = Math.cos(u);
|
|
35142
|
+
const su = Math.sin(u);
|
|
35143
|
+
const x = (R + r * cv) * cu;
|
|
35144
|
+
const y = (R + r * cv) * su;
|
|
35145
|
+
const z = r * sv;
|
|
35146
|
+
const nx = cv * cu;
|
|
35147
|
+
const ny = cv * su;
|
|
35148
|
+
const nz = sv;
|
|
35149
|
+
mb.vertex([
|
|
35150
|
+
x,
|
|
35151
|
+
y,
|
|
35152
|
+
z
|
|
35153
|
+
], normalize([
|
|
35154
|
+
nx,
|
|
35155
|
+
ny,
|
|
35156
|
+
nz
|
|
35157
|
+
]), [i / tubularSegments, j / radialSegments]);
|
|
35158
|
+
}
|
|
35159
|
+
}
|
|
35160
|
+
mb.grid(base, tubularSegments, radialSegments, true);
|
|
35161
|
+
if (Math.abs(arcRad) < Math.PI * 2 - 1e-4) for (const [u, sign] of [[0, -1], [arcRad, 1]]) {
|
|
35162
|
+
const cu = Math.cos(u);
|
|
35163
|
+
const su = Math.sin(u);
|
|
35164
|
+
const capN = [
|
|
35165
|
+
-su * sign,
|
|
35166
|
+
cu * sign,
|
|
35167
|
+
0
|
|
35168
|
+
];
|
|
35169
|
+
const center = mb.vertex([
|
|
35170
|
+
R * cu,
|
|
35171
|
+
R * su,
|
|
35172
|
+
0
|
|
35173
|
+
], capN, [.5, .5]);
|
|
35174
|
+
const ring$1 = mb.positions.length / 3;
|
|
35175
|
+
for (let j = 0; j <= radialSegments; j++) {
|
|
35176
|
+
const v = j / radialSegments * Math.PI * 2;
|
|
35177
|
+
const cv = Math.cos(v);
|
|
35178
|
+
const sv = Math.sin(v);
|
|
35179
|
+
mb.vertex([
|
|
35180
|
+
(R + r * cv) * cu,
|
|
35181
|
+
(R + r * cv) * su,
|
|
35182
|
+
r * sv
|
|
35183
|
+
], capN, [(cv + 1) / 2, (sv + 1) / 2]);
|
|
35184
|
+
}
|
|
35185
|
+
for (let j = 0; j < radialSegments; j++) if (sign < 0) mb.indices.push(center, ring$1 + j, ring$1 + j + 1);
|
|
35186
|
+
else mb.indices.push(center, ring$1 + j + 1, ring$1 + j);
|
|
35187
|
+
}
|
|
35188
|
+
}
|
|
35189
|
+
/**
|
|
35190
|
+
* Capsule aligned along the Y axis: a cylinder of height `length` and radius `radius`
|
|
35191
|
+
* capped by top (-y) and bottom (+y) hemispheres of radius `radius`.
|
|
35192
|
+
*/
|
|
35193
|
+
function capsule(o, mb) {
|
|
35194
|
+
const r = Math.max(.001, o.radius ?? 30);
|
|
35195
|
+
const length = Math.max(0, o.length ?? 60);
|
|
35196
|
+
const hy = length / 2;
|
|
35197
|
+
const capSeg = Math.max(2, Math.round(o.capSegments ?? 12));
|
|
35198
|
+
const radSeg = Math.max(3, Math.round(o.radialSegments ?? 32));
|
|
35199
|
+
const rings = [];
|
|
35200
|
+
const totalArc = Math.PI * r + length;
|
|
35201
|
+
for (let j = 0; j <= capSeg; j++) {
|
|
35202
|
+
const phi = j / capSeg * Math.PI / 2;
|
|
35203
|
+
const s = Math.sin(phi);
|
|
35204
|
+
const c = Math.cos(phi);
|
|
35205
|
+
rings.push({
|
|
35206
|
+
y: -hy - r * c,
|
|
35207
|
+
rRing: r * s,
|
|
35208
|
+
ny: -c,
|
|
35209
|
+
nr: s,
|
|
35210
|
+
v: phi * r / (totalArc || 1)
|
|
35211
|
+
});
|
|
35212
|
+
}
|
|
35213
|
+
for (let j = 0; j <= capSeg; j++) {
|
|
35214
|
+
if (j === 0 && length <= 1e-6) continue;
|
|
35215
|
+
const phi = Math.PI / 2 + j / capSeg * Math.PI / 2;
|
|
35216
|
+
const s = Math.sin(phi);
|
|
35217
|
+
const c = Math.cos(phi);
|
|
35218
|
+
rings.push({
|
|
35219
|
+
y: hy - r * c,
|
|
35220
|
+
rRing: r * s,
|
|
35221
|
+
ny: -c,
|
|
35222
|
+
nr: s,
|
|
35223
|
+
v: (Math.PI / 2 * r + length + (phi - Math.PI / 2) * r) / (totalArc || 1)
|
|
35224
|
+
});
|
|
35225
|
+
}
|
|
35226
|
+
const base = mb.positions.length / 3;
|
|
35227
|
+
for (const ring$1 of rings) for (let i = 0; i <= radSeg; i++) {
|
|
35228
|
+
const theta = i / radSeg * Math.PI * 2;
|
|
35229
|
+
const ct = Math.cos(theta);
|
|
35230
|
+
const st = Math.sin(theta);
|
|
35231
|
+
const n = normalize([
|
|
35232
|
+
ring$1.nr * ct,
|
|
35233
|
+
ring$1.ny,
|
|
35234
|
+
ring$1.nr * st
|
|
35235
|
+
]);
|
|
35236
|
+
mb.vertex([
|
|
35237
|
+
ring$1.rRing * ct,
|
|
35238
|
+
ring$1.y,
|
|
35239
|
+
ring$1.rRing * st
|
|
35240
|
+
], n, [i / radSeg, ring$1.v]);
|
|
35241
|
+
}
|
|
35242
|
+
mb.grid(base, radSeg, rings.length - 1, false);
|
|
35243
|
+
}
|
|
35244
|
+
/**
|
|
35245
|
+
* Flat or thick-walled annulus (ring) in the XY plane facing -Z (front) and +Z (back).
|
|
35246
|
+
* Always builds a closed two-sided or solid manifold so it works with single-sided culling.
|
|
35247
|
+
*/
|
|
35248
|
+
function ring(o, mb) {
|
|
35249
|
+
const rInner = Math.max(0, o.innerRadius ?? 30);
|
|
35250
|
+
const rOuter = Math.max(rInner + .001, o.outerRadius ?? 60);
|
|
35251
|
+
const hz = Math.max(0, o.depth ?? 0) / 2;
|
|
35252
|
+
const thetaSeg = Math.max(3, Math.round(o.thetaSegments ?? 48));
|
|
35253
|
+
const phiSeg = Math.max(1, Math.round(o.phiSegments ?? 1));
|
|
35254
|
+
const thetaStart = (o.thetaStart ?? 0) * Math.PI / 180;
|
|
35255
|
+
const thetaLength = (o.thetaLength ?? 360) * Math.PI / 180;
|
|
35256
|
+
for (const [z, nz, flip] of [[
|
|
35257
|
+
-hz,
|
|
35258
|
+
-1,
|
|
35259
|
+
false
|
|
35260
|
+
], [
|
|
35261
|
+
hz,
|
|
35262
|
+
1,
|
|
35263
|
+
true
|
|
35264
|
+
]]) {
|
|
35265
|
+
const base = mb.positions.length / 3;
|
|
35266
|
+
for (let j = 0; j <= phiSeg; j++) {
|
|
35267
|
+
const radius = rInner + (rOuter - rInner) * j / phiSeg;
|
|
35268
|
+
for (let i = 0; i <= thetaSeg; i++) {
|
|
35269
|
+
const theta = thetaStart + i / thetaSeg * thetaLength;
|
|
35270
|
+
const c = Math.cos(theta);
|
|
35271
|
+
const s = Math.sin(theta);
|
|
35272
|
+
const x = radius * c;
|
|
35273
|
+
const y = radius * s;
|
|
35274
|
+
mb.vertex([
|
|
35275
|
+
x,
|
|
35276
|
+
y,
|
|
35277
|
+
z
|
|
35278
|
+
], [
|
|
35279
|
+
0,
|
|
35280
|
+
0,
|
|
35281
|
+
nz
|
|
35282
|
+
], [(x / rOuter + 1) / 2, (y / rOuter + 1) / 2]);
|
|
35283
|
+
}
|
|
35284
|
+
}
|
|
35285
|
+
mb.grid(base, thetaSeg, phiSeg, !flip);
|
|
35286
|
+
}
|
|
35287
|
+
if (hz > 0) {
|
|
35288
|
+
const outerBase = mb.positions.length / 3;
|
|
35289
|
+
for (const [z, v] of [[-hz, 0], [hz, 1]]) for (let i = 0; i <= thetaSeg; i++) {
|
|
35290
|
+
const theta = thetaStart + i / thetaSeg * thetaLength;
|
|
35291
|
+
const c = Math.cos(theta);
|
|
35292
|
+
const s = Math.sin(theta);
|
|
35293
|
+
mb.vertex([
|
|
35294
|
+
rOuter * c,
|
|
35295
|
+
rOuter * s,
|
|
35296
|
+
z
|
|
35297
|
+
], [
|
|
35298
|
+
c,
|
|
35299
|
+
s,
|
|
35300
|
+
0
|
|
35301
|
+
], [i / thetaSeg, v]);
|
|
35302
|
+
}
|
|
35303
|
+
mb.grid(outerBase, thetaSeg, 1, true);
|
|
35304
|
+
if (rInner > 1e-6) {
|
|
35305
|
+
const innerBase = mb.positions.length / 3;
|
|
35306
|
+
for (const [z, v] of [[-hz, 0], [hz, 1]]) for (let i = 0; i <= thetaSeg; i++) {
|
|
35307
|
+
const theta = thetaStart + i / thetaSeg * thetaLength;
|
|
35308
|
+
const c = Math.cos(theta);
|
|
35309
|
+
const s = Math.sin(theta);
|
|
35310
|
+
mb.vertex([
|
|
35311
|
+
rInner * c,
|
|
35312
|
+
rInner * s,
|
|
35313
|
+
z
|
|
35314
|
+
], [
|
|
35315
|
+
-c,
|
|
35316
|
+
-s,
|
|
35317
|
+
0
|
|
35318
|
+
], [i / thetaSeg, v]);
|
|
35319
|
+
}
|
|
35320
|
+
mb.grid(innerBase, thetaSeg, 1, false);
|
|
35321
|
+
}
|
|
35322
|
+
if (Math.abs(thetaLength) < Math.PI * 2 - 1e-4) for (const [theta, sign] of [[thetaStart, -1], [thetaStart + thetaLength, 1]]) {
|
|
35323
|
+
const c = Math.cos(theta);
|
|
35324
|
+
const s = Math.sin(theta);
|
|
35325
|
+
const capN = [
|
|
35326
|
+
-s * sign,
|
|
35327
|
+
c * sign,
|
|
35328
|
+
0
|
|
35329
|
+
];
|
|
35330
|
+
const p0 = mb.vertex([
|
|
35331
|
+
rInner * c,
|
|
35332
|
+
rInner * s,
|
|
35333
|
+
-hz
|
|
35334
|
+
], capN, [0, 0]);
|
|
35335
|
+
const p1 = mb.vertex([
|
|
35336
|
+
rOuter * c,
|
|
35337
|
+
rOuter * s,
|
|
35040
35338
|
-hz
|
|
35339
|
+
], capN, [1, 0]);
|
|
35340
|
+
const p2 = mb.vertex([
|
|
35341
|
+
rInner * c,
|
|
35342
|
+
rInner * s,
|
|
35343
|
+
hz
|
|
35344
|
+
], capN, [0, 1]);
|
|
35345
|
+
const p3 = mb.vertex([
|
|
35346
|
+
rOuter * c,
|
|
35347
|
+
rOuter * s,
|
|
35348
|
+
hz
|
|
35349
|
+
], capN, [1, 1]);
|
|
35350
|
+
if (sign > 0) mb.indices.push(p0, p2, p1, p1, p2, p3);
|
|
35351
|
+
else mb.indices.push(p0, p1, p2, p1, p3, p2);
|
|
35352
|
+
}
|
|
35353
|
+
}
|
|
35354
|
+
}
|
|
35355
|
+
/**
|
|
35356
|
+
* Platonic solids (tetrahedron, octahedron, dodecahedron, icosahedron) and
|
|
35357
|
+
* geodesic icosphere with configurable subdivision `detail`.
|
|
35358
|
+
*/
|
|
35359
|
+
function polyhedron(o, mb) {
|
|
35360
|
+
const shape = o.shape ?? "icosahedron";
|
|
35361
|
+
const radius = Math.max(.001, o.radius ?? 50);
|
|
35362
|
+
const detail = Math.max(0, Math.min(5, Math.round(o.detail ?? (shape === "icosphere" ? 2 : 0))));
|
|
35363
|
+
const flatShaded = o.flatShaded ?? shape !== "icosphere";
|
|
35364
|
+
let baseVerts = [];
|
|
35365
|
+
let baseFaces = [];
|
|
35366
|
+
if (shape === "tetrahedron") {
|
|
35367
|
+
baseVerts = [
|
|
35368
|
+
[
|
|
35369
|
+
1,
|
|
35370
|
+
1,
|
|
35371
|
+
1
|
|
35041
35372
|
],
|
|
35042
35373
|
[
|
|
35043
|
-
|
|
35044
|
-
-
|
|
35045
|
-
|
|
35374
|
+
-1,
|
|
35375
|
+
-1,
|
|
35376
|
+
1
|
|
35046
35377
|
],
|
|
35047
35378
|
[
|
|
35048
|
-
|
|
35049
|
-
|
|
35050
|
-
-
|
|
35379
|
+
-1,
|
|
35380
|
+
1,
|
|
35381
|
+
-1
|
|
35051
35382
|
],
|
|
35052
35383
|
[
|
|
35053
|
-
|
|
35054
|
-
|
|
35055
|
-
-
|
|
35384
|
+
1,
|
|
35385
|
+
-1,
|
|
35386
|
+
-1
|
|
35056
35387
|
]
|
|
35057
|
-
]
|
|
35058
|
-
[
|
|
35388
|
+
];
|
|
35389
|
+
baseFaces = [
|
|
35059
35390
|
[
|
|
35060
|
-
|
|
35061
|
-
|
|
35062
|
-
|
|
35391
|
+
2,
|
|
35392
|
+
1,
|
|
35393
|
+
0
|
|
35063
35394
|
],
|
|
35064
35395
|
[
|
|
35065
|
-
|
|
35066
|
-
|
|
35067
|
-
|
|
35396
|
+
0,
|
|
35397
|
+
3,
|
|
35398
|
+
2
|
|
35068
35399
|
],
|
|
35069
35400
|
[
|
|
35070
|
-
|
|
35071
|
-
|
|
35072
|
-
|
|
35401
|
+
1,
|
|
35402
|
+
3,
|
|
35403
|
+
0
|
|
35073
35404
|
],
|
|
35074
35405
|
[
|
|
35075
|
-
|
|
35076
|
-
|
|
35077
|
-
|
|
35406
|
+
2,
|
|
35407
|
+
3,
|
|
35408
|
+
1
|
|
35078
35409
|
]
|
|
35079
|
-
]
|
|
35080
|
-
|
|
35410
|
+
];
|
|
35411
|
+
} else if (shape === "octahedron") {
|
|
35412
|
+
baseVerts = [
|
|
35081
35413
|
[
|
|
35082
|
-
|
|
35083
|
-
|
|
35084
|
-
|
|
35414
|
+
1,
|
|
35415
|
+
0,
|
|
35416
|
+
0
|
|
35085
35417
|
],
|
|
35086
35418
|
[
|
|
35087
|
-
-
|
|
35088
|
-
|
|
35089
|
-
|
|
35419
|
+
-1,
|
|
35420
|
+
0,
|
|
35421
|
+
0
|
|
35090
35422
|
],
|
|
35091
35423
|
[
|
|
35092
|
-
|
|
35093
|
-
|
|
35094
|
-
|
|
35424
|
+
0,
|
|
35425
|
+
1,
|
|
35426
|
+
0
|
|
35427
|
+
],
|
|
35428
|
+
[
|
|
35429
|
+
0,
|
|
35430
|
+
-1,
|
|
35431
|
+
0
|
|
35432
|
+
],
|
|
35433
|
+
[
|
|
35434
|
+
0,
|
|
35435
|
+
0,
|
|
35436
|
+
1
|
|
35437
|
+
],
|
|
35438
|
+
[
|
|
35439
|
+
0,
|
|
35440
|
+
0,
|
|
35441
|
+
-1
|
|
35442
|
+
]
|
|
35443
|
+
];
|
|
35444
|
+
baseFaces = [
|
|
35445
|
+
[
|
|
35446
|
+
0,
|
|
35447
|
+
2,
|
|
35448
|
+
4
|
|
35449
|
+
],
|
|
35450
|
+
[
|
|
35451
|
+
0,
|
|
35452
|
+
4,
|
|
35453
|
+
3
|
|
35454
|
+
],
|
|
35455
|
+
[
|
|
35456
|
+
0,
|
|
35457
|
+
3,
|
|
35458
|
+
5
|
|
35459
|
+
],
|
|
35460
|
+
[
|
|
35461
|
+
0,
|
|
35462
|
+
5,
|
|
35463
|
+
2
|
|
35464
|
+
],
|
|
35465
|
+
[
|
|
35466
|
+
1,
|
|
35467
|
+
2,
|
|
35468
|
+
5
|
|
35469
|
+
],
|
|
35470
|
+
[
|
|
35471
|
+
1,
|
|
35472
|
+
5,
|
|
35473
|
+
3
|
|
35474
|
+
],
|
|
35475
|
+
[
|
|
35476
|
+
1,
|
|
35477
|
+
3,
|
|
35478
|
+
4
|
|
35479
|
+
],
|
|
35480
|
+
[
|
|
35481
|
+
1,
|
|
35482
|
+
4,
|
|
35483
|
+
2
|
|
35484
|
+
]
|
|
35485
|
+
];
|
|
35486
|
+
} else if (shape === "dodecahedron") {
|
|
35487
|
+
const t = (1 + Math.sqrt(5)) / 2;
|
|
35488
|
+
const r = 1 / t;
|
|
35489
|
+
baseVerts = [
|
|
35490
|
+
[
|
|
35491
|
+
-1,
|
|
35492
|
+
-1,
|
|
35493
|
+
-1
|
|
35494
|
+
],
|
|
35495
|
+
[
|
|
35496
|
+
-1,
|
|
35497
|
+
-1,
|
|
35498
|
+
1
|
|
35499
|
+
],
|
|
35500
|
+
[
|
|
35501
|
+
-1,
|
|
35502
|
+
1,
|
|
35503
|
+
-1
|
|
35504
|
+
],
|
|
35505
|
+
[
|
|
35506
|
+
-1,
|
|
35507
|
+
1,
|
|
35508
|
+
1
|
|
35509
|
+
],
|
|
35510
|
+
[
|
|
35511
|
+
1,
|
|
35512
|
+
-1,
|
|
35513
|
+
-1
|
|
35514
|
+
],
|
|
35515
|
+
[
|
|
35516
|
+
1,
|
|
35517
|
+
-1,
|
|
35518
|
+
1
|
|
35519
|
+
],
|
|
35520
|
+
[
|
|
35521
|
+
1,
|
|
35522
|
+
1,
|
|
35523
|
+
-1
|
|
35524
|
+
],
|
|
35525
|
+
[
|
|
35526
|
+
1,
|
|
35527
|
+
1,
|
|
35528
|
+
1
|
|
35529
|
+
],
|
|
35530
|
+
[
|
|
35531
|
+
0,
|
|
35532
|
+
-r,
|
|
35533
|
+
-t
|
|
35534
|
+
],
|
|
35535
|
+
[
|
|
35536
|
+
0,
|
|
35537
|
+
-r,
|
|
35538
|
+
t
|
|
35539
|
+
],
|
|
35540
|
+
[
|
|
35541
|
+
0,
|
|
35542
|
+
r,
|
|
35543
|
+
-t
|
|
35544
|
+
],
|
|
35545
|
+
[
|
|
35546
|
+
0,
|
|
35547
|
+
r,
|
|
35548
|
+
t
|
|
35549
|
+
],
|
|
35550
|
+
[
|
|
35551
|
+
-r,
|
|
35552
|
+
-t,
|
|
35553
|
+
0
|
|
35554
|
+
],
|
|
35555
|
+
[
|
|
35556
|
+
-r,
|
|
35557
|
+
t,
|
|
35558
|
+
0
|
|
35559
|
+
],
|
|
35560
|
+
[
|
|
35561
|
+
r,
|
|
35562
|
+
-t,
|
|
35563
|
+
0
|
|
35564
|
+
],
|
|
35565
|
+
[
|
|
35566
|
+
r,
|
|
35567
|
+
t,
|
|
35568
|
+
0
|
|
35569
|
+
],
|
|
35570
|
+
[
|
|
35571
|
+
-t,
|
|
35572
|
+
0,
|
|
35573
|
+
-r
|
|
35574
|
+
],
|
|
35575
|
+
[
|
|
35576
|
+
t,
|
|
35577
|
+
0,
|
|
35578
|
+
-r
|
|
35579
|
+
],
|
|
35580
|
+
[
|
|
35581
|
+
-t,
|
|
35582
|
+
0,
|
|
35583
|
+
r
|
|
35584
|
+
],
|
|
35585
|
+
[
|
|
35586
|
+
t,
|
|
35587
|
+
0,
|
|
35588
|
+
r
|
|
35589
|
+
]
|
|
35590
|
+
];
|
|
35591
|
+
const pentagons = [
|
|
35592
|
+
[
|
|
35593
|
+
3,
|
|
35594
|
+
11,
|
|
35595
|
+
7,
|
|
35596
|
+
15,
|
|
35597
|
+
13
|
|
35598
|
+
],
|
|
35599
|
+
[
|
|
35600
|
+
7,
|
|
35601
|
+
19,
|
|
35602
|
+
17,
|
|
35603
|
+
6,
|
|
35604
|
+
15
|
|
35605
|
+
],
|
|
35606
|
+
[
|
|
35607
|
+
17,
|
|
35608
|
+
4,
|
|
35609
|
+
8,
|
|
35610
|
+
10,
|
|
35611
|
+
6
|
|
35612
|
+
],
|
|
35613
|
+
[
|
|
35614
|
+
8,
|
|
35615
|
+
0,
|
|
35616
|
+
16,
|
|
35617
|
+
2,
|
|
35618
|
+
10
|
|
35619
|
+
],
|
|
35620
|
+
[
|
|
35621
|
+
0,
|
|
35622
|
+
12,
|
|
35623
|
+
1,
|
|
35624
|
+
18,
|
|
35625
|
+
16
|
|
35626
|
+
],
|
|
35627
|
+
[
|
|
35628
|
+
6,
|
|
35629
|
+
10,
|
|
35630
|
+
2,
|
|
35631
|
+
13,
|
|
35632
|
+
15
|
|
35633
|
+
],
|
|
35634
|
+
[
|
|
35635
|
+
2,
|
|
35636
|
+
16,
|
|
35637
|
+
18,
|
|
35638
|
+
3,
|
|
35639
|
+
13
|
|
35640
|
+
],
|
|
35641
|
+
[
|
|
35642
|
+
18,
|
|
35643
|
+
1,
|
|
35644
|
+
9,
|
|
35645
|
+
11,
|
|
35646
|
+
3
|
|
35647
|
+
],
|
|
35648
|
+
[
|
|
35649
|
+
4,
|
|
35650
|
+
14,
|
|
35651
|
+
12,
|
|
35652
|
+
0,
|
|
35653
|
+
8
|
|
35654
|
+
],
|
|
35655
|
+
[
|
|
35656
|
+
11,
|
|
35657
|
+
9,
|
|
35658
|
+
5,
|
|
35659
|
+
19,
|
|
35660
|
+
7
|
|
35661
|
+
],
|
|
35662
|
+
[
|
|
35663
|
+
19,
|
|
35664
|
+
5,
|
|
35665
|
+
14,
|
|
35666
|
+
4,
|
|
35667
|
+
17
|
|
35668
|
+
],
|
|
35669
|
+
[
|
|
35670
|
+
1,
|
|
35671
|
+
12,
|
|
35672
|
+
14,
|
|
35673
|
+
5,
|
|
35674
|
+
9
|
|
35675
|
+
]
|
|
35676
|
+
];
|
|
35677
|
+
if (detail === 0 && flatShaded) {
|
|
35678
|
+
const unitVerts = baseVerts.map((v) => normalize(v));
|
|
35679
|
+
for (const pent of pentagons) {
|
|
35680
|
+
const pts = pent.map((idx) => unitVerts[idx]);
|
|
35681
|
+
const center = [
|
|
35682
|
+
pts.reduce((s, p) => s + p[0], 0) / 5,
|
|
35683
|
+
pts.reduce((s, p) => s + p[1], 0) / 5,
|
|
35684
|
+
pts.reduce((s, p) => s + p[2], 0) / 5
|
|
35685
|
+
];
|
|
35686
|
+
let fn = normalize(cross3(sub3(pts[1], pts[0]), sub3(pts[2], pts[0])));
|
|
35687
|
+
if (dot3(fn, center) < 0) {
|
|
35688
|
+
pts.reverse();
|
|
35689
|
+
fn = [
|
|
35690
|
+
-fn[0],
|
|
35691
|
+
-fn[1],
|
|
35692
|
+
-fn[2]
|
|
35693
|
+
];
|
|
35694
|
+
}
|
|
35695
|
+
const base = mb.positions.length / 3;
|
|
35696
|
+
for (const p of pts) {
|
|
35697
|
+
const u = .5 + Math.atan2(p[2], p[0]) / (2 * Math.PI);
|
|
35698
|
+
const v = Math.acos(Math.max(-1, Math.min(1, -p[1]))) / Math.PI;
|
|
35699
|
+
mb.vertex([
|
|
35700
|
+
p[0] * radius,
|
|
35701
|
+
p[1] * radius,
|
|
35702
|
+
p[2] * radius
|
|
35703
|
+
], fn, [u, v]);
|
|
35704
|
+
}
|
|
35705
|
+
for (let k = 1; k < pts.length - 1; k++) mb.indices.push(base, base + k, base + k + 1);
|
|
35706
|
+
}
|
|
35707
|
+
return;
|
|
35708
|
+
}
|
|
35709
|
+
for (const p of pentagons) baseFaces.push([
|
|
35710
|
+
p[0],
|
|
35711
|
+
p[1],
|
|
35712
|
+
p[2]
|
|
35713
|
+
], [
|
|
35714
|
+
p[0],
|
|
35715
|
+
p[2],
|
|
35716
|
+
p[3]
|
|
35717
|
+
], [
|
|
35718
|
+
p[0],
|
|
35719
|
+
p[3],
|
|
35720
|
+
p[4]
|
|
35721
|
+
]);
|
|
35722
|
+
} else {
|
|
35723
|
+
const t = (1 + Math.sqrt(5)) / 2;
|
|
35724
|
+
baseVerts = [
|
|
35725
|
+
[
|
|
35726
|
+
-1,
|
|
35727
|
+
t,
|
|
35728
|
+
0
|
|
35729
|
+
],
|
|
35730
|
+
[
|
|
35731
|
+
1,
|
|
35732
|
+
t,
|
|
35733
|
+
0
|
|
35734
|
+
],
|
|
35735
|
+
[
|
|
35736
|
+
-1,
|
|
35737
|
+
-t,
|
|
35738
|
+
0
|
|
35739
|
+
],
|
|
35740
|
+
[
|
|
35741
|
+
1,
|
|
35742
|
+
-t,
|
|
35743
|
+
0
|
|
35744
|
+
],
|
|
35745
|
+
[
|
|
35746
|
+
0,
|
|
35747
|
+
-1,
|
|
35748
|
+
t
|
|
35749
|
+
],
|
|
35750
|
+
[
|
|
35751
|
+
0,
|
|
35752
|
+
1,
|
|
35753
|
+
t
|
|
35754
|
+
],
|
|
35755
|
+
[
|
|
35756
|
+
0,
|
|
35757
|
+
-1,
|
|
35758
|
+
-t
|
|
35759
|
+
],
|
|
35760
|
+
[
|
|
35761
|
+
0,
|
|
35762
|
+
1,
|
|
35763
|
+
-t
|
|
35764
|
+
],
|
|
35765
|
+
[
|
|
35766
|
+
t,
|
|
35767
|
+
0,
|
|
35768
|
+
-1
|
|
35769
|
+
],
|
|
35770
|
+
[
|
|
35771
|
+
t,
|
|
35772
|
+
0,
|
|
35773
|
+
1
|
|
35774
|
+
],
|
|
35775
|
+
[
|
|
35776
|
+
-t,
|
|
35777
|
+
0,
|
|
35778
|
+
-1
|
|
35779
|
+
],
|
|
35780
|
+
[
|
|
35781
|
+
-t,
|
|
35782
|
+
0,
|
|
35783
|
+
1
|
|
35784
|
+
]
|
|
35785
|
+
];
|
|
35786
|
+
baseFaces = [
|
|
35787
|
+
[
|
|
35788
|
+
0,
|
|
35789
|
+
11,
|
|
35790
|
+
5
|
|
35791
|
+
],
|
|
35792
|
+
[
|
|
35793
|
+
0,
|
|
35794
|
+
5,
|
|
35795
|
+
1
|
|
35796
|
+
],
|
|
35797
|
+
[
|
|
35798
|
+
0,
|
|
35799
|
+
1,
|
|
35800
|
+
7
|
|
35801
|
+
],
|
|
35802
|
+
[
|
|
35803
|
+
0,
|
|
35804
|
+
7,
|
|
35805
|
+
10
|
|
35806
|
+
],
|
|
35807
|
+
[
|
|
35808
|
+
0,
|
|
35809
|
+
10,
|
|
35810
|
+
11
|
|
35811
|
+
],
|
|
35812
|
+
[
|
|
35813
|
+
1,
|
|
35814
|
+
5,
|
|
35815
|
+
9
|
|
35816
|
+
],
|
|
35817
|
+
[
|
|
35818
|
+
5,
|
|
35819
|
+
11,
|
|
35820
|
+
4
|
|
35821
|
+
],
|
|
35822
|
+
[
|
|
35823
|
+
11,
|
|
35824
|
+
10,
|
|
35825
|
+
2
|
|
35826
|
+
],
|
|
35827
|
+
[
|
|
35828
|
+
10,
|
|
35829
|
+
7,
|
|
35830
|
+
6
|
|
35831
|
+
],
|
|
35832
|
+
[
|
|
35833
|
+
7,
|
|
35834
|
+
1,
|
|
35835
|
+
8
|
|
35836
|
+
],
|
|
35837
|
+
[
|
|
35838
|
+
3,
|
|
35839
|
+
9,
|
|
35840
|
+
4
|
|
35841
|
+
],
|
|
35842
|
+
[
|
|
35843
|
+
3,
|
|
35844
|
+
4,
|
|
35845
|
+
2
|
|
35846
|
+
],
|
|
35847
|
+
[
|
|
35848
|
+
3,
|
|
35849
|
+
2,
|
|
35850
|
+
6
|
|
35851
|
+
],
|
|
35852
|
+
[
|
|
35853
|
+
3,
|
|
35854
|
+
6,
|
|
35855
|
+
8
|
|
35856
|
+
],
|
|
35857
|
+
[
|
|
35858
|
+
3,
|
|
35859
|
+
8,
|
|
35860
|
+
9
|
|
35861
|
+
],
|
|
35862
|
+
[
|
|
35863
|
+
4,
|
|
35864
|
+
9,
|
|
35865
|
+
5
|
|
35866
|
+
],
|
|
35867
|
+
[
|
|
35868
|
+
2,
|
|
35869
|
+
4,
|
|
35870
|
+
11
|
|
35871
|
+
],
|
|
35872
|
+
[
|
|
35873
|
+
6,
|
|
35874
|
+
2,
|
|
35875
|
+
10
|
|
35876
|
+
],
|
|
35877
|
+
[
|
|
35878
|
+
8,
|
|
35879
|
+
6,
|
|
35880
|
+
7
|
|
35881
|
+
],
|
|
35882
|
+
[
|
|
35883
|
+
9,
|
|
35884
|
+
8,
|
|
35885
|
+
1
|
|
35886
|
+
]
|
|
35887
|
+
];
|
|
35888
|
+
}
|
|
35889
|
+
const verts = baseVerts.map((v) => normalize(v));
|
|
35890
|
+
let tris = baseFaces.map((f) => [
|
|
35891
|
+
f[0],
|
|
35892
|
+
f[1],
|
|
35893
|
+
f[2]
|
|
35894
|
+
]);
|
|
35895
|
+
for (let d = 0; d < detail; d++) {
|
|
35896
|
+
const midCache = /* @__PURE__ */ new Map();
|
|
35897
|
+
const midpoint = (a, b) => {
|
|
35898
|
+
const key = a < b ? `${a}_${b}` : `${b}_${a}`;
|
|
35899
|
+
const existing = midCache.get(key);
|
|
35900
|
+
if (existing !== void 0) return existing;
|
|
35901
|
+
const va = verts[a];
|
|
35902
|
+
const vb = verts[b];
|
|
35903
|
+
const idx = verts.length;
|
|
35904
|
+
verts.push(normalize([
|
|
35905
|
+
va[0] + vb[0],
|
|
35906
|
+
va[1] + vb[1],
|
|
35907
|
+
va[2] + vb[2]
|
|
35908
|
+
]));
|
|
35909
|
+
midCache.set(key, idx);
|
|
35910
|
+
return idx;
|
|
35911
|
+
};
|
|
35912
|
+
const nextTris = [];
|
|
35913
|
+
for (const [i0, i1, i2] of tris) {
|
|
35914
|
+
const m01 = midpoint(i0, i1);
|
|
35915
|
+
const m12 = midpoint(i1, i2);
|
|
35916
|
+
const m20 = midpoint(i2, i0);
|
|
35917
|
+
nextTris.push([
|
|
35918
|
+
i0,
|
|
35919
|
+
m01,
|
|
35920
|
+
m20
|
|
35921
|
+
], [
|
|
35922
|
+
i1,
|
|
35923
|
+
m12,
|
|
35924
|
+
m01
|
|
35925
|
+
], [
|
|
35926
|
+
i2,
|
|
35927
|
+
m20,
|
|
35928
|
+
m12
|
|
35929
|
+
], [
|
|
35930
|
+
m01,
|
|
35931
|
+
m12,
|
|
35932
|
+
m20
|
|
35933
|
+
]);
|
|
35934
|
+
}
|
|
35935
|
+
tris = nextTris;
|
|
35936
|
+
}
|
|
35937
|
+
const uvOf = (n) => [.5 + Math.atan2(n[2], n[0]) / (2 * Math.PI), Math.acos(Math.max(-1, Math.min(1, -n[1]))) / Math.PI];
|
|
35938
|
+
if (flatShaded) for (const [i0, i1, i2] of tris) {
|
|
35939
|
+
const a = verts[i0];
|
|
35940
|
+
let b = verts[i1];
|
|
35941
|
+
let c = verts[i2];
|
|
35942
|
+
const centroid = [
|
|
35943
|
+
(a[0] + b[0] + c[0]) / 3,
|
|
35944
|
+
(a[1] + b[1] + c[1]) / 3,
|
|
35945
|
+
(a[2] + b[2] + c[2]) / 3
|
|
35946
|
+
];
|
|
35947
|
+
let fn = normalize(cross3(sub3(b, a), sub3(c, a)));
|
|
35948
|
+
if (dot3(fn, centroid) < 0) {
|
|
35949
|
+
const tmp = b;
|
|
35950
|
+
b = c;
|
|
35951
|
+
c = tmp;
|
|
35952
|
+
fn = [
|
|
35953
|
+
-fn[0],
|
|
35954
|
+
-fn[1],
|
|
35955
|
+
-fn[2]
|
|
35956
|
+
];
|
|
35957
|
+
}
|
|
35958
|
+
const base = mb.positions.length / 3;
|
|
35959
|
+
mb.vertex([
|
|
35960
|
+
a[0] * radius,
|
|
35961
|
+
a[1] * radius,
|
|
35962
|
+
a[2] * radius
|
|
35963
|
+
], fn, uvOf(a));
|
|
35964
|
+
mb.vertex([
|
|
35965
|
+
b[0] * radius,
|
|
35966
|
+
b[1] * radius,
|
|
35967
|
+
b[2] * radius
|
|
35968
|
+
], fn, uvOf(b));
|
|
35969
|
+
mb.vertex([
|
|
35970
|
+
c[0] * radius,
|
|
35971
|
+
c[1] * radius,
|
|
35972
|
+
c[2] * radius
|
|
35973
|
+
], fn, uvOf(c));
|
|
35974
|
+
mb.indices.push(base, base + 1, base + 2);
|
|
35975
|
+
}
|
|
35976
|
+
else {
|
|
35977
|
+
const base = mb.positions.length / 3;
|
|
35978
|
+
for (const n of verts) mb.vertex([
|
|
35979
|
+
n[0] * radius,
|
|
35980
|
+
n[1] * radius,
|
|
35981
|
+
n[2] * radius
|
|
35982
|
+
], n, uvOf(n));
|
|
35983
|
+
for (const [i0, i1, i2] of tris) {
|
|
35984
|
+
const a = verts[i0];
|
|
35985
|
+
const b = verts[i1];
|
|
35986
|
+
const c = verts[i2];
|
|
35987
|
+
const centroid = [
|
|
35988
|
+
(a[0] + b[0] + c[0]) / 3,
|
|
35989
|
+
(a[1] + b[1] + c[1]) / 3,
|
|
35990
|
+
(a[2] + b[2] + c[2]) / 3
|
|
35991
|
+
];
|
|
35992
|
+
if (dot3(cross3(sub3(b, a), sub3(c, a)), centroid) < 0) mb.indices.push(base + i0, base + i2, base + i1);
|
|
35993
|
+
else mb.indices.push(base + i0, base + i1, base + i2);
|
|
35994
|
+
}
|
|
35995
|
+
}
|
|
35996
|
+
}
|
|
35997
|
+
/**
|
|
35998
|
+
* Parses an SVG path string (supporting M, L, H, V, C, S, Q, T, A, Z and multiple subpaths)
|
|
35999
|
+
* into closed 2D contours with adaptive or fixed curve flattening.
|
|
36000
|
+
*/
|
|
36001
|
+
function parseSvgPathToContours(d, flattening) {
|
|
36002
|
+
const contours = [];
|
|
36003
|
+
if (!d || typeof d !== "string") return contours;
|
|
36004
|
+
const tokens = [];
|
|
36005
|
+
const regex = /([a-df-z])|([-+]?(?:\d*\.\d+|\d+)(?:[eE][-+]?\d+)?)/gi;
|
|
36006
|
+
let match = regex.exec(d);
|
|
36007
|
+
while (match !== null) {
|
|
36008
|
+
if (match[1]) tokens.push(match[1]);
|
|
36009
|
+
else if (match[2]) tokens.push(Number.parseFloat(match[2]));
|
|
36010
|
+
match = regex.exec(d);
|
|
36011
|
+
}
|
|
36012
|
+
let cursor = 0;
|
|
36013
|
+
let current = {
|
|
36014
|
+
x: 0,
|
|
36015
|
+
y: 0
|
|
36016
|
+
};
|
|
36017
|
+
let subpathStart = {
|
|
36018
|
+
x: 0,
|
|
36019
|
+
y: 0
|
|
36020
|
+
};
|
|
36021
|
+
let lastCubicControl = null;
|
|
36022
|
+
let lastQuadControl = null;
|
|
36023
|
+
let contour = [];
|
|
36024
|
+
const finishContour = () => {
|
|
36025
|
+
if (contour.length >= 2) {
|
|
36026
|
+
const first = contour[0];
|
|
36027
|
+
const last = contour[contour.length - 1];
|
|
36028
|
+
if (Math.hypot(last.x - first.x, last.y - first.y) < 1e-4) contour.pop();
|
|
36029
|
+
if (contour.length >= 2) contours.push(contour);
|
|
36030
|
+
}
|
|
36031
|
+
contour = [];
|
|
36032
|
+
};
|
|
36033
|
+
const segCount = (maxSecondDeriv) => {
|
|
36034
|
+
if (flattening.segments !== void 0) return Math.max(1, flattening.segments);
|
|
36035
|
+
const n = Math.ceil(Math.sqrt(maxSecondDeriv / (8 * Math.max(.001, flattening.tolerance))));
|
|
36036
|
+
return Math.min(64, Math.max(1, n));
|
|
36037
|
+
};
|
|
36038
|
+
const addQuad = (p0, cp, end) => {
|
|
36039
|
+
const n = segCount(2 * Math.hypot(p0.x - 2 * cp.x + end.x, p0.y - 2 * cp.y + end.y));
|
|
36040
|
+
for (let s = 1; s <= n; s++) {
|
|
36041
|
+
const t = s / n;
|
|
36042
|
+
const mt = 1 - t;
|
|
36043
|
+
contour.push({
|
|
36044
|
+
x: mt * mt * p0.x + 2 * mt * t * cp.x + t * t * end.x,
|
|
36045
|
+
y: mt * mt * p0.y + 2 * mt * t * cp.y + t * t * end.y
|
|
36046
|
+
});
|
|
36047
|
+
}
|
|
36048
|
+
};
|
|
36049
|
+
const addCubic = (p0, cp1, cp2, end) => {
|
|
36050
|
+
const n = segCount(6 * Math.max(Math.hypot(p0.x - 2 * cp1.x + cp2.x, p0.y - 2 * cp1.y + cp2.y), Math.hypot(cp1.x - 2 * cp2.x + end.x, cp1.y - 2 * cp2.y + end.y)));
|
|
36051
|
+
for (let s = 1; s <= n; s++) {
|
|
36052
|
+
const t = s / n;
|
|
36053
|
+
const mt = 1 - t;
|
|
36054
|
+
contour.push({
|
|
36055
|
+
x: mt * mt * mt * p0.x + 3 * mt * mt * t * cp1.x + 3 * mt * t * t * cp2.x + t * t * t * end.x,
|
|
36056
|
+
y: mt * mt * mt * p0.y + 3 * mt * mt * t * cp1.y + 3 * mt * t * t * cp2.y + t * t * t * end.y
|
|
36057
|
+
});
|
|
36058
|
+
}
|
|
36059
|
+
};
|
|
36060
|
+
const getNum = () => cursor < tokens.length && typeof tokens[cursor] === "number" ? tokens[cursor++] : 0;
|
|
36061
|
+
while (cursor < tokens.length) {
|
|
36062
|
+
const cmdToken = tokens[cursor++];
|
|
36063
|
+
if (typeof cmdToken !== "string") continue;
|
|
36064
|
+
const isRel = cmdToken === cmdToken.toLowerCase();
|
|
36065
|
+
switch (cmdToken.toUpperCase()) {
|
|
36066
|
+
case "M": {
|
|
36067
|
+
finishContour();
|
|
36068
|
+
let first = true;
|
|
36069
|
+
while (cursor < tokens.length && typeof tokens[cursor] === "number") {
|
|
36070
|
+
let x = getNum();
|
|
36071
|
+
let y = getNum();
|
|
36072
|
+
if (isRel) {
|
|
36073
|
+
x += current.x;
|
|
36074
|
+
y += current.y;
|
|
36075
|
+
}
|
|
36076
|
+
current = {
|
|
36077
|
+
x,
|
|
36078
|
+
y
|
|
36079
|
+
};
|
|
36080
|
+
if (first) {
|
|
36081
|
+
subpathStart = current;
|
|
36082
|
+
contour = [current];
|
|
36083
|
+
first = false;
|
|
36084
|
+
} else contour.push(current);
|
|
36085
|
+
}
|
|
36086
|
+
lastCubicControl = null;
|
|
36087
|
+
lastQuadControl = null;
|
|
36088
|
+
break;
|
|
36089
|
+
}
|
|
36090
|
+
case "L":
|
|
36091
|
+
while (cursor < tokens.length && typeof tokens[cursor] === "number") {
|
|
36092
|
+
let x = getNum();
|
|
36093
|
+
let y = getNum();
|
|
36094
|
+
if (isRel) {
|
|
36095
|
+
x += current.x;
|
|
36096
|
+
y += current.y;
|
|
36097
|
+
}
|
|
36098
|
+
current = {
|
|
36099
|
+
x,
|
|
36100
|
+
y
|
|
36101
|
+
};
|
|
36102
|
+
contour.push(current);
|
|
36103
|
+
}
|
|
36104
|
+
lastCubicControl = null;
|
|
36105
|
+
lastQuadControl = null;
|
|
36106
|
+
break;
|
|
36107
|
+
case "H":
|
|
36108
|
+
while (cursor < tokens.length && typeof tokens[cursor] === "number") {
|
|
36109
|
+
let x = getNum();
|
|
36110
|
+
if (isRel) x += current.x;
|
|
36111
|
+
current = {
|
|
36112
|
+
x,
|
|
36113
|
+
y: current.y
|
|
36114
|
+
};
|
|
36115
|
+
contour.push(current);
|
|
36116
|
+
}
|
|
36117
|
+
lastCubicControl = null;
|
|
36118
|
+
lastQuadControl = null;
|
|
36119
|
+
break;
|
|
36120
|
+
case "V":
|
|
36121
|
+
while (cursor < tokens.length && typeof tokens[cursor] === "number") {
|
|
36122
|
+
let y = getNum();
|
|
36123
|
+
if (isRel) y += current.y;
|
|
36124
|
+
current = {
|
|
36125
|
+
x: current.x,
|
|
36126
|
+
y
|
|
36127
|
+
};
|
|
36128
|
+
contour.push(current);
|
|
36129
|
+
}
|
|
36130
|
+
lastCubicControl = null;
|
|
36131
|
+
lastQuadControl = null;
|
|
36132
|
+
break;
|
|
36133
|
+
case "C":
|
|
36134
|
+
while (cursor < tokens.length && typeof tokens[cursor] === "number") {
|
|
36135
|
+
let x1 = getNum();
|
|
36136
|
+
let y1 = getNum();
|
|
36137
|
+
let x2 = getNum();
|
|
36138
|
+
let y2 = getNum();
|
|
36139
|
+
let x = getNum();
|
|
36140
|
+
let y = getNum();
|
|
36141
|
+
if (isRel) {
|
|
36142
|
+
x1 += current.x;
|
|
36143
|
+
y1 += current.y;
|
|
36144
|
+
x2 += current.x;
|
|
36145
|
+
y2 += current.y;
|
|
36146
|
+
x += current.x;
|
|
36147
|
+
y += current.y;
|
|
36148
|
+
}
|
|
36149
|
+
const cp1 = {
|
|
36150
|
+
x: x1,
|
|
36151
|
+
y: y1
|
|
36152
|
+
};
|
|
36153
|
+
const cp2 = {
|
|
36154
|
+
x: x2,
|
|
36155
|
+
y: y2
|
|
36156
|
+
};
|
|
36157
|
+
const end = {
|
|
36158
|
+
x,
|
|
36159
|
+
y
|
|
36160
|
+
};
|
|
36161
|
+
addCubic(current, cp1, cp2, end);
|
|
36162
|
+
current = end;
|
|
36163
|
+
lastCubicControl = cp2;
|
|
36164
|
+
}
|
|
36165
|
+
lastQuadControl = null;
|
|
36166
|
+
break;
|
|
36167
|
+
case "S":
|
|
36168
|
+
while (cursor < tokens.length && typeof tokens[cursor] === "number") {
|
|
36169
|
+
let x2 = getNum();
|
|
36170
|
+
let y2 = getNum();
|
|
36171
|
+
let x = getNum();
|
|
36172
|
+
let y = getNum();
|
|
36173
|
+
if (isRel) {
|
|
36174
|
+
x2 += current.x;
|
|
36175
|
+
y2 += current.y;
|
|
36176
|
+
x += current.x;
|
|
36177
|
+
y += current.y;
|
|
36178
|
+
}
|
|
36179
|
+
const cp1 = lastCubicControl ? {
|
|
36180
|
+
x: 2 * current.x - lastCubicControl.x,
|
|
36181
|
+
y: 2 * current.y - lastCubicControl.y
|
|
36182
|
+
} : current;
|
|
36183
|
+
const cp2 = {
|
|
36184
|
+
x: x2,
|
|
36185
|
+
y: y2
|
|
36186
|
+
};
|
|
36187
|
+
const end = {
|
|
36188
|
+
x,
|
|
36189
|
+
y
|
|
36190
|
+
};
|
|
36191
|
+
addCubic(current, cp1, cp2, end);
|
|
36192
|
+
current = end;
|
|
36193
|
+
lastCubicControl = cp2;
|
|
36194
|
+
}
|
|
36195
|
+
lastQuadControl = null;
|
|
36196
|
+
break;
|
|
36197
|
+
case "Q":
|
|
36198
|
+
while (cursor < tokens.length && typeof tokens[cursor] === "number") {
|
|
36199
|
+
let x1 = getNum();
|
|
36200
|
+
let y1 = getNum();
|
|
36201
|
+
let x = getNum();
|
|
36202
|
+
let y = getNum();
|
|
36203
|
+
if (isRel) {
|
|
36204
|
+
x1 += current.x;
|
|
36205
|
+
y1 += current.y;
|
|
36206
|
+
x += current.x;
|
|
36207
|
+
y += current.y;
|
|
36208
|
+
}
|
|
36209
|
+
const cp = {
|
|
36210
|
+
x: x1,
|
|
36211
|
+
y: y1
|
|
36212
|
+
};
|
|
36213
|
+
const end = {
|
|
36214
|
+
x,
|
|
36215
|
+
y
|
|
36216
|
+
};
|
|
36217
|
+
addQuad(current, cp, end);
|
|
36218
|
+
current = end;
|
|
36219
|
+
lastQuadControl = cp;
|
|
36220
|
+
}
|
|
36221
|
+
lastCubicControl = null;
|
|
36222
|
+
break;
|
|
36223
|
+
case "T":
|
|
36224
|
+
while (cursor < tokens.length && typeof tokens[cursor] === "number") {
|
|
36225
|
+
let x = getNum();
|
|
36226
|
+
let y = getNum();
|
|
36227
|
+
if (isRel) {
|
|
36228
|
+
x += current.x;
|
|
36229
|
+
y += current.y;
|
|
36230
|
+
}
|
|
36231
|
+
const cp = lastQuadControl ? {
|
|
36232
|
+
x: 2 * current.x - lastQuadControl.x,
|
|
36233
|
+
y: 2 * current.y - lastQuadControl.y
|
|
36234
|
+
} : current;
|
|
36235
|
+
const end = {
|
|
36236
|
+
x,
|
|
36237
|
+
y
|
|
36238
|
+
};
|
|
36239
|
+
addQuad(current, cp, end);
|
|
36240
|
+
current = end;
|
|
36241
|
+
lastQuadControl = cp;
|
|
36242
|
+
}
|
|
36243
|
+
lastCubicControl = null;
|
|
36244
|
+
break;
|
|
36245
|
+
case "A":
|
|
36246
|
+
while (cursor < tokens.length && typeof tokens[cursor] === "number") {
|
|
36247
|
+
const rx = getNum();
|
|
36248
|
+
const ry = getNum();
|
|
36249
|
+
const rot = getNum();
|
|
36250
|
+
const largeArc = getNum() !== 0;
|
|
36251
|
+
const sweep = getNum() !== 0;
|
|
36252
|
+
let x = getNum();
|
|
36253
|
+
let y = getNum();
|
|
36254
|
+
if (isRel) {
|
|
36255
|
+
x += current.x;
|
|
36256
|
+
y += current.y;
|
|
36257
|
+
}
|
|
36258
|
+
const end = {
|
|
36259
|
+
x,
|
|
36260
|
+
y
|
|
36261
|
+
};
|
|
36262
|
+
const segs = sampleSvgArc(current, rx, ry, rot, largeArc, sweep, end);
|
|
36263
|
+
for (const s of segs) contour.push(s.p1);
|
|
36264
|
+
current = end;
|
|
36265
|
+
}
|
|
36266
|
+
lastCubicControl = null;
|
|
36267
|
+
lastQuadControl = null;
|
|
36268
|
+
break;
|
|
36269
|
+
case "Z":
|
|
36270
|
+
finishContour();
|
|
36271
|
+
current = subpathStart;
|
|
36272
|
+
lastCubicControl = null;
|
|
36273
|
+
lastQuadControl = null;
|
|
36274
|
+
break;
|
|
36275
|
+
}
|
|
36276
|
+
}
|
|
36277
|
+
finishContour();
|
|
36278
|
+
return contours;
|
|
36279
|
+
}
|
|
36280
|
+
function toPoint2D(p) {
|
|
36281
|
+
return Array.isArray(p) ? {
|
|
36282
|
+
x: p[0],
|
|
36283
|
+
y: p[1]
|
|
36284
|
+
} : {
|
|
36285
|
+
x: p.x,
|
|
36286
|
+
y: p.y
|
|
36287
|
+
};
|
|
36288
|
+
}
|
|
36289
|
+
function normalizeContoursInput(o, flattening) {
|
|
36290
|
+
const raw = o.shape ?? o.d ?? o.contour;
|
|
36291
|
+
let contours = [];
|
|
36292
|
+
if (typeof raw === "string") contours = parseSvgPathToContours(raw, flattening).filter((c) => c.length >= 3);
|
|
36293
|
+
else if (Array.isArray(raw) && raw.length > 0) {
|
|
36294
|
+
const first = raw[0];
|
|
36295
|
+
if (Array.isArray(first) && first.length > 0 && (Array.isArray(first[0]) || typeof first[0] === "object" && first[0] !== null && "x" in first[0])) contours = raw.map((c) => c.map(toPoint2D)).filter((c) => c.length >= 3);
|
|
36296
|
+
else {
|
|
36297
|
+
const single = raw.map(toPoint2D);
|
|
36298
|
+
if (single.length >= 3) contours = [single];
|
|
36299
|
+
}
|
|
36300
|
+
}
|
|
36301
|
+
if (Array.isArray(o.holes)) for (const hole of o.holes) {
|
|
36302
|
+
const mapped = hole.map(toPoint2D);
|
|
36303
|
+
if (mapped.length >= 3) contours.push(mapped);
|
|
36304
|
+
}
|
|
36305
|
+
return contours;
|
|
36306
|
+
}
|
|
36307
|
+
/** Side-wall segments meeting at more than 30° keep a crisp hard edge. */
|
|
36308
|
+
const SIDE_CREASE_COS = Math.cos(30 * Math.PI / 180);
|
|
36309
|
+
/**
|
|
36310
|
+
* Extrudes any 2D outline (SVG path string with subpaths/holes, or polygon contour arrays)
|
|
36311
|
+
* into a 3D solid mesh with optional front/back bevels and crease-aware smooth/hard side normals.
|
|
36312
|
+
*/
|
|
36313
|
+
function buildExtrudedShapeModel(o) {
|
|
36314
|
+
const halfDepth = Math.max(.001, o.depth ?? 20) / 2;
|
|
36315
|
+
const bevelThickness = Math.max(0, Math.min(halfDepth * .49, o.bevelThickness ?? 0));
|
|
36316
|
+
const bevelSize = Math.max(0, o.bevelSize ?? bevelThickness);
|
|
36317
|
+
const bevelSegments = bevelThickness > 0 || bevelSize > 0 ? Math.max(1, Math.round(o.bevelSegments ?? 2)) : 0;
|
|
36318
|
+
const polygons = organizeGlyphPolygons({
|
|
36319
|
+
contours: normalizeContoursInput(o, {
|
|
36320
|
+
segments: o.curveSegments,
|
|
36321
|
+
tolerance: Math.max(.001, o.curveTolerance ?? .25)
|
|
36322
|
+
}),
|
|
36323
|
+
simplified: false
|
|
36324
|
+
});
|
|
36325
|
+
let minX = Number.POSITIVE_INFINITY;
|
|
36326
|
+
let maxX = Number.NEGATIVE_INFINITY;
|
|
36327
|
+
let minY = Number.POSITIVE_INFINITY;
|
|
36328
|
+
let maxY = Number.NEGATIVE_INFINITY;
|
|
36329
|
+
for (const poly of polygons) {
|
|
36330
|
+
for (const p of poly.outer) {
|
|
36331
|
+
if (p.x < minX) minX = p.x;
|
|
36332
|
+
if (p.x > maxX) maxX = p.x;
|
|
36333
|
+
if (p.y < minY) minY = p.y;
|
|
36334
|
+
if (p.y > maxY) maxY = p.y;
|
|
36335
|
+
}
|
|
36336
|
+
for (const hole of poly.holes) for (const p of hole) {
|
|
36337
|
+
if (p.x < minX) minX = p.x;
|
|
36338
|
+
if (p.x > maxX) maxX = p.x;
|
|
36339
|
+
if (p.y < minY) minY = p.y;
|
|
36340
|
+
if (p.y > maxY) maxY = p.y;
|
|
36341
|
+
}
|
|
36342
|
+
}
|
|
36343
|
+
if (!Number.isFinite(minX)) minX = maxX = minY = maxY = 0;
|
|
36344
|
+
if (o.center ?? true) {
|
|
36345
|
+
const cx = (minX + maxX) / 2;
|
|
36346
|
+
const cy = (minY + maxY) / 2;
|
|
36347
|
+
for (const poly of polygons) {
|
|
36348
|
+
for (const p of poly.outer) {
|
|
36349
|
+
p.x -= cx;
|
|
36350
|
+
p.y -= cy;
|
|
36351
|
+
}
|
|
36352
|
+
for (const hole of poly.holes) for (const p of hole) {
|
|
36353
|
+
p.x -= cx;
|
|
36354
|
+
p.y -= cy;
|
|
36355
|
+
}
|
|
36356
|
+
}
|
|
36357
|
+
minX -= cx;
|
|
36358
|
+
maxX -= cx;
|
|
36359
|
+
minY -= cy;
|
|
36360
|
+
maxY -= cy;
|
|
36361
|
+
}
|
|
36362
|
+
const w = maxX - minX;
|
|
36363
|
+
const h = maxY - minY;
|
|
36364
|
+
const frontMb = new MeshBuilder();
|
|
36365
|
+
const sideMb = new MeshBuilder();
|
|
36366
|
+
const useSeparateSideMaterial = o.bevelColor !== void 0 && o.bevelColor !== o.color;
|
|
36367
|
+
const wallMb = useSeparateSideMaterial ? sideMb : frontMb;
|
|
36368
|
+
const cleanContour = (contour) => {
|
|
36369
|
+
const pts = contour.filter((p, k) => {
|
|
36370
|
+
const next = contour[(k + 1) % contour.length];
|
|
36371
|
+
return Math.hypot(next.x - p.x, next.y - p.y) >= 1e-5;
|
|
36372
|
+
});
|
|
36373
|
+
const count = pts.length;
|
|
36374
|
+
if (count < 3) return null;
|
|
36375
|
+
const edgeLengths = [];
|
|
36376
|
+
const edgeNormals = pts.map((p, k) => {
|
|
36377
|
+
const next = pts[(k + 1) % count];
|
|
36378
|
+
const len = Math.hypot(next.x - p.x, next.y - p.y);
|
|
36379
|
+
edgeLengths.push(len);
|
|
36380
|
+
return {
|
|
36381
|
+
x: (next.y - p.y) / len,
|
|
36382
|
+
y: -(next.x - p.x) / len
|
|
36383
|
+
};
|
|
36384
|
+
});
|
|
36385
|
+
return {
|
|
36386
|
+
pts,
|
|
36387
|
+
edgeLengths,
|
|
36388
|
+
edgeNormals,
|
|
36389
|
+
miterNormals: pts.map((_, k) => {
|
|
36390
|
+
const nPrev = edgeNormals[(k - 1 + count) % count];
|
|
36391
|
+
const nNext = edgeNormals[k];
|
|
36392
|
+
const sx = nPrev.x + nNext.x;
|
|
36393
|
+
const sy = nPrev.y + nNext.y;
|
|
36394
|
+
const len = Math.hypot(sx, sy);
|
|
36395
|
+
if (len < 1e-6) return nNext;
|
|
36396
|
+
const dot = sx / len * nNext.x + sy / len * nNext.y;
|
|
36397
|
+
const scale = Math.min(2, 1 / Math.max(.35, dot));
|
|
36398
|
+
return {
|
|
36399
|
+
x: sx / len * scale,
|
|
36400
|
+
y: sy / len * scale
|
|
36401
|
+
};
|
|
36402
|
+
})
|
|
36403
|
+
};
|
|
36404
|
+
};
|
|
36405
|
+
const addSideWallWithProfile = (contour) => {
|
|
36406
|
+
const info = cleanContour(contour);
|
|
36407
|
+
if (!info) return;
|
|
36408
|
+
const { pts, edgeLengths, edgeNormals, miterNormals } = info;
|
|
36409
|
+
const count = pts.length;
|
|
36410
|
+
const perimeter = edgeLengths.reduce((a, b) => a + b, 0) || 1;
|
|
36411
|
+
const slices = [];
|
|
36412
|
+
if (bevelSegments <= 0) slices.push({
|
|
36413
|
+
z: -halfDepth,
|
|
36414
|
+
inset: 0,
|
|
36415
|
+
nr: 1,
|
|
36416
|
+
nz: 0,
|
|
36417
|
+
v: 0
|
|
36418
|
+
}, {
|
|
36419
|
+
z: halfDepth,
|
|
36420
|
+
inset: 0,
|
|
36421
|
+
nr: 1,
|
|
36422
|
+
nz: 0,
|
|
36423
|
+
v: 1
|
|
36424
|
+
});
|
|
36425
|
+
else {
|
|
36426
|
+
const totalRows = bevelSegments * 2 + 1;
|
|
36427
|
+
let row = 0;
|
|
36428
|
+
for (let b = 0; b <= bevelSegments; b++) {
|
|
36429
|
+
const a = b / bevelSegments * Math.PI / 2;
|
|
36430
|
+
slices.push({
|
|
36431
|
+
z: -halfDepth + bevelThickness * (1 - Math.cos(a)),
|
|
36432
|
+
inset: -bevelSize * (1 - Math.sin(a)),
|
|
36433
|
+
nr: Math.sin(a),
|
|
36434
|
+
nz: -Math.cos(a),
|
|
36435
|
+
v: row++ / totalRows
|
|
36436
|
+
});
|
|
36437
|
+
}
|
|
36438
|
+
for (let b = 0; b <= bevelSegments; b++) {
|
|
36439
|
+
const a = b / bevelSegments * Math.PI / 2;
|
|
36440
|
+
slices.push({
|
|
36441
|
+
z: halfDepth - bevelThickness * (1 - Math.sin(a)),
|
|
36442
|
+
inset: -bevelSize * (1 - Math.cos(a)),
|
|
36443
|
+
nr: Math.cos(a),
|
|
36444
|
+
nz: Math.sin(a),
|
|
36445
|
+
v: row++ / totalRows
|
|
36446
|
+
});
|
|
36447
|
+
}
|
|
36448
|
+
}
|
|
36449
|
+
const numSlices = slices.length;
|
|
36450
|
+
const addColumn = (p, miter, n2d, u) => {
|
|
36451
|
+
const base = wallMb.positions.length / 3;
|
|
36452
|
+
for (const s of slices) {
|
|
36453
|
+
const px = p.x + miter.x * s.inset;
|
|
36454
|
+
const py = p.y + miter.y * s.inset;
|
|
36455
|
+
const n3 = normalize([
|
|
36456
|
+
n2d.x * s.nr,
|
|
36457
|
+
n2d.y * s.nr,
|
|
36458
|
+
s.nz
|
|
36459
|
+
]);
|
|
36460
|
+
wallMb.vertex([
|
|
36461
|
+
px,
|
|
36462
|
+
py,
|
|
36463
|
+
s.z
|
|
36464
|
+
], n3, [u, s.v]);
|
|
36465
|
+
}
|
|
36466
|
+
return base;
|
|
36467
|
+
};
|
|
36468
|
+
const startColumn = [];
|
|
36469
|
+
const endColumn = [];
|
|
36470
|
+
let along = 0;
|
|
36471
|
+
for (let k = 0; k < count; k++) {
|
|
36472
|
+
const incoming = edgeNormals[(k - 1 + count) % count];
|
|
36473
|
+
const outgoing = edgeNormals[k];
|
|
36474
|
+
const miter = miterNormals[k];
|
|
36475
|
+
const u = along / perimeter;
|
|
36476
|
+
const sx = incoming.x + outgoing.x;
|
|
36477
|
+
const sy = incoming.y + outgoing.y;
|
|
36478
|
+
const averaged = incoming.x * outgoing.x + incoming.y * outgoing.y >= SIDE_CREASE_COS ? {
|
|
36479
|
+
x: sx / Math.hypot(sx, sy),
|
|
36480
|
+
y: sy / Math.hypot(sx, sy)
|
|
36481
|
+
} : null;
|
|
36482
|
+
if (averaged && k > 0) startColumn[k] = endColumn[k] = addColumn(pts[k], miter, averaged, u);
|
|
36483
|
+
else {
|
|
36484
|
+
endColumn[k] = addColumn(pts[k], miter, averaged ?? incoming, k === 0 ? 1 : u);
|
|
36485
|
+
startColumn[k] = addColumn(pts[k], miter, averaged ?? outgoing, u);
|
|
36486
|
+
}
|
|
36487
|
+
along += edgeLengths[k];
|
|
36488
|
+
}
|
|
36489
|
+
for (let k = 0; k < count; k++) {
|
|
36490
|
+
const colA = startColumn[k];
|
|
36491
|
+
const colB = endColumn[(k + 1) % count];
|
|
36492
|
+
for (let s = 0; s < numSlices - 1; s++) {
|
|
36493
|
+
const a0 = colA + s;
|
|
36494
|
+
const a1 = colA + s + 1;
|
|
36495
|
+
const b0 = colB + s;
|
|
36496
|
+
const b1 = colB + s + 1;
|
|
36497
|
+
wallMb.indices.push(a0, b0, a1, b0, b1, a1);
|
|
36498
|
+
}
|
|
36499
|
+
}
|
|
36500
|
+
};
|
|
36501
|
+
for (const poly of polygons) {
|
|
36502
|
+
const outer = poly.outer;
|
|
36503
|
+
if (computeContourSignedArea(outer) < 0) outer.reverse();
|
|
36504
|
+
for (const hole of poly.holes) if (computeContourSignedArea(hole) > 0) hole.reverse();
|
|
36505
|
+
const outerInfo = cleanContour(outer);
|
|
36506
|
+
if (!outerInfo) continue;
|
|
36507
|
+
const holeInfos = poly.holes.map(cleanContour).filter((x) => x !== null);
|
|
36508
|
+
const capInset = -bevelSize;
|
|
36509
|
+
const earcutCoords = [];
|
|
36510
|
+
const holeIndices = [];
|
|
36511
|
+
for (let k = 0; k < outerInfo.pts.length; k++) {
|
|
36512
|
+
const p = outerInfo.pts[k];
|
|
36513
|
+
const m = outerInfo.miterNormals[k];
|
|
36514
|
+
earcutCoords.push(p.x + m.x * capInset, p.y + m.y * capInset);
|
|
36515
|
+
}
|
|
36516
|
+
for (const hInfo of holeInfos) {
|
|
36517
|
+
holeIndices.push(earcutCoords.length / 2);
|
|
36518
|
+
for (let k = 0; k < hInfo.pts.length; k++) {
|
|
36519
|
+
const p = hInfo.pts[k];
|
|
36520
|
+
const m = hInfo.miterNormals[k];
|
|
36521
|
+
earcutCoords.push(p.x + m.x * capInset, p.y + m.y * capInset);
|
|
36522
|
+
}
|
|
36523
|
+
}
|
|
36524
|
+
const triangles = earcut(earcutCoords, holeIndices, 2);
|
|
36525
|
+
const vertCount = earcutCoords.length / 2;
|
|
36526
|
+
const frontBase = frontMb.positions.length / 3;
|
|
36527
|
+
for (let v = 0; v < vertCount; v++) {
|
|
36528
|
+
const vx = earcutCoords[v * 2];
|
|
36529
|
+
const vy = earcutCoords[v * 2 + 1];
|
|
36530
|
+
frontMb.vertex([
|
|
36531
|
+
vx,
|
|
36532
|
+
vy,
|
|
36533
|
+
-halfDepth
|
|
36534
|
+
], [
|
|
36535
|
+
0,
|
|
36536
|
+
0,
|
|
36537
|
+
-1
|
|
36538
|
+
], [(vx - minX) / (w || 1), (vy - minY) / (h || 1)]);
|
|
36539
|
+
}
|
|
36540
|
+
for (let t = 0; t < triangles.length; t += 3) frontMb.indices.push(frontBase + triangles[t], frontBase + triangles[t + 2], frontBase + triangles[t + 1]);
|
|
36541
|
+
const backBase = frontMb.positions.length / 3;
|
|
36542
|
+
for (let v = 0; v < vertCount; v++) {
|
|
36543
|
+
const vx = earcutCoords[v * 2];
|
|
36544
|
+
const vy = earcutCoords[v * 2 + 1];
|
|
36545
|
+
frontMb.vertex([
|
|
36546
|
+
vx,
|
|
36547
|
+
vy,
|
|
36548
|
+
halfDepth
|
|
36549
|
+
], [
|
|
36550
|
+
0,
|
|
36551
|
+
0,
|
|
36552
|
+
1
|
|
36553
|
+
], [(vx - minX) / (w || 1), (vy - minY) / (h || 1)]);
|
|
36554
|
+
}
|
|
36555
|
+
for (let t = 0; t < triangles.length; t += 3) frontMb.indices.push(backBase + triangles[t], backBase + triangles[t + 1], backBase + triangles[t + 2]);
|
|
36556
|
+
addSideWallWithProfile(outer);
|
|
36557
|
+
for (const hole of poly.holes) addSideWallWithProfile(hole);
|
|
36558
|
+
}
|
|
36559
|
+
const meshes = [];
|
|
36560
|
+
const materials = {};
|
|
36561
|
+
const frontMesh = frontMb.build("extrude-front");
|
|
36562
|
+
frontMesh.materialName = "extrude-front-material";
|
|
36563
|
+
meshes.push(frontMesh);
|
|
36564
|
+
materials["extrude-front-material"] = {
|
|
36565
|
+
name: "extrude-front-material",
|
|
36566
|
+
diffuseColor: parseHexOrRgbColor(o.color ?? "#ffffff"),
|
|
36567
|
+
shading: o.material ?? "lit",
|
|
36568
|
+
shininess: o.shininess ?? 32,
|
|
36569
|
+
roughness: o.roughness,
|
|
36570
|
+
metallic: o.metallic
|
|
36571
|
+
};
|
|
36572
|
+
if (useSeparateSideMaterial && sideMb.indices.length > 0) {
|
|
36573
|
+
const sideMesh = sideMb.build("extrude-side");
|
|
36574
|
+
sideMesh.materialName = "extrude-side-material";
|
|
36575
|
+
meshes.push(sideMesh);
|
|
36576
|
+
materials["extrude-side-material"] = {
|
|
36577
|
+
name: "extrude-side-material",
|
|
36578
|
+
diffuseColor: parseHexOrRgbColor(o.bevelColor ?? o.color ?? "#ffffff"),
|
|
36579
|
+
shading: o.material ?? "lit",
|
|
36580
|
+
shininess: o.shininess ?? 32,
|
|
36581
|
+
roughness: o.roughness,
|
|
36582
|
+
metallic: o.metallic
|
|
36583
|
+
};
|
|
36584
|
+
}
|
|
36585
|
+
return finalizeModel3DData("extrude", meshes, materials);
|
|
36586
|
+
}
|
|
36587
|
+
/**
|
|
36588
|
+
* Revolves a 2D profile `(r, y)` around the Y axis (`x = r cos φ, y = y, z = r sin φ`).
|
|
36589
|
+
*/
|
|
36590
|
+
function lathe(o, mb) {
|
|
36591
|
+
const rawPoints = typeof o.points === "string" ? parseSvgPathToContours(o.points, { tolerance: .25 })[0] ?? [] : o.points.map(toPoint2D);
|
|
36592
|
+
if (rawPoints.length < 2) return;
|
|
36593
|
+
const pts = rawPoints.map((p) => ({
|
|
36594
|
+
x: Math.max(0, p.x),
|
|
36595
|
+
y: p.y
|
|
36596
|
+
}));
|
|
36597
|
+
const isClosedLoop = pts.length >= 3 && Math.hypot(pts[pts.length - 1].x - pts[0].x, pts[pts.length - 1].y - pts[0].y) < 1e-4;
|
|
36598
|
+
if (isClosedLoop) {
|
|
36599
|
+
if (computeContourSignedArea(pts) < 0) pts.reverse();
|
|
36600
|
+
} else if (pts[0].y > pts[pts.length - 1].y) pts.reverse();
|
|
36601
|
+
const seg = Math.max(3, Math.round(o.segments ?? 32));
|
|
36602
|
+
const phiStart = (o.phiStart ?? 0) * Math.PI / 180;
|
|
36603
|
+
const phiLength = (o.phiLength ?? 360) * Math.PI / 180;
|
|
36604
|
+
const count = pts.length;
|
|
36605
|
+
const segLens = [];
|
|
36606
|
+
const segNormals = [];
|
|
36607
|
+
let totalLen = 0;
|
|
36608
|
+
for (let j = 0; j < count - 1; j++) {
|
|
36609
|
+
const a = pts[j];
|
|
36610
|
+
const b = pts[j + 1];
|
|
36611
|
+
const dr = b.x - a.x;
|
|
36612
|
+
const dy = b.y - a.y;
|
|
36613
|
+
const len = Math.hypot(dr, dy);
|
|
36614
|
+
segLens.push(len);
|
|
36615
|
+
totalLen += len;
|
|
36616
|
+
segNormals.push(len > 1e-8 ? {
|
|
36617
|
+
x: dy / len,
|
|
36618
|
+
y: -dr / len
|
|
36619
|
+
} : {
|
|
36620
|
+
x: 1,
|
|
36621
|
+
y: 0
|
|
36622
|
+
});
|
|
36623
|
+
}
|
|
36624
|
+
const vCoords = [0];
|
|
36625
|
+
let acc = 0;
|
|
36626
|
+
for (const len of segLens) {
|
|
36627
|
+
acc += len;
|
|
36628
|
+
vCoords.push(totalLen > 0 ? acc / totalLen : 0);
|
|
36629
|
+
}
|
|
36630
|
+
if (o.flatShaded) for (let j = 0; j < count - 1; j++) {
|
|
36631
|
+
const pA = pts[j];
|
|
36632
|
+
const pB = pts[j + 1];
|
|
36633
|
+
const n2 = segNormals[j];
|
|
36634
|
+
for (let i = 0; i < seg; i++) {
|
|
36635
|
+
const phi0 = phiStart + i / seg * phiLength;
|
|
36636
|
+
const phi1 = phiStart + (i + 1) / seg * phiLength;
|
|
36637
|
+
const phiMid = (phi0 + phi1) / 2;
|
|
36638
|
+
const fn = normalize([
|
|
36639
|
+
n2.x * Math.cos(phiMid),
|
|
36640
|
+
n2.y,
|
|
36641
|
+
n2.x * Math.sin(phiMid)
|
|
36642
|
+
]);
|
|
36643
|
+
const c0 = Math.cos(phi0);
|
|
36644
|
+
const s0 = Math.sin(phi0);
|
|
36645
|
+
const c1 = Math.cos(phi1);
|
|
36646
|
+
const s1 = Math.sin(phi1);
|
|
36647
|
+
const base = mb.positions.length / 3;
|
|
36648
|
+
mb.vertex([
|
|
36649
|
+
pA.x * c0,
|
|
36650
|
+
pA.y,
|
|
36651
|
+
pA.x * s0
|
|
36652
|
+
], fn, [i / seg, vCoords[j]]);
|
|
36653
|
+
mb.vertex([
|
|
36654
|
+
pA.x * c1,
|
|
36655
|
+
pA.y,
|
|
36656
|
+
pA.x * s1
|
|
36657
|
+
], fn, [(i + 1) / seg, vCoords[j]]);
|
|
36658
|
+
mb.vertex([
|
|
36659
|
+
pB.x * c0,
|
|
36660
|
+
pB.y,
|
|
36661
|
+
pB.x * s0
|
|
36662
|
+
], fn, [i / seg, vCoords[j + 1]]);
|
|
36663
|
+
mb.vertex([
|
|
36664
|
+
pB.x * c1,
|
|
36665
|
+
pB.y,
|
|
36666
|
+
pB.x * s1
|
|
36667
|
+
], fn, [(i + 1) / seg, vCoords[j + 1]]);
|
|
36668
|
+
mb.indices.push(base, base + 2, base + 1, base + 1, base + 2, base + 3);
|
|
36669
|
+
}
|
|
36670
|
+
}
|
|
36671
|
+
else {
|
|
36672
|
+
const smoothOrCrease = (nSeg, nAdj) => {
|
|
36673
|
+
if (nSeg.x * nAdj.x + nSeg.y * nAdj.y < SIDE_CREASE_COS) return nSeg;
|
|
36674
|
+
const nx = nSeg.x + nAdj.x;
|
|
36675
|
+
const ny = nSeg.y + nAdj.y;
|
|
36676
|
+
const nLen = Math.hypot(nx, ny);
|
|
36677
|
+
return nLen > 1e-8 ? {
|
|
36678
|
+
x: nx / nLen,
|
|
36679
|
+
y: ny / nLen
|
|
36680
|
+
} : nSeg;
|
|
36681
|
+
};
|
|
36682
|
+
const emitRing = (p, n2, v) => {
|
|
36683
|
+
for (let i = 0; i <= seg; i++) {
|
|
36684
|
+
const phi = phiStart + i / seg * phiLength;
|
|
36685
|
+
const c = Math.cos(phi);
|
|
36686
|
+
const s = Math.sin(phi);
|
|
36687
|
+
const vNorm = p.x <= 1e-5 && Math.abs(n2.y) > 1e-5 ? [
|
|
36688
|
+
0,
|
|
36689
|
+
n2.y < 0 ? -1 : 1,
|
|
36690
|
+
0
|
|
36691
|
+
] : normalize([
|
|
36692
|
+
n2.x * c,
|
|
36693
|
+
n2.y,
|
|
36694
|
+
n2.x * s
|
|
36695
|
+
]);
|
|
36696
|
+
mb.vertex([
|
|
36697
|
+
p.x * c,
|
|
36698
|
+
p.y,
|
|
36699
|
+
p.x * s
|
|
36700
|
+
], vNorm, [i / seg, v]);
|
|
36701
|
+
}
|
|
36702
|
+
};
|
|
36703
|
+
for (let j = 0; j < count - 1; j++) {
|
|
36704
|
+
const pA = pts[j];
|
|
36705
|
+
const pB = pts[j + 1];
|
|
36706
|
+
const nSeg = segNormals[j];
|
|
36707
|
+
const nPrevA = j > 0 ? segNormals[j - 1] : isClosedLoop ? segNormals[count - 2] : nSeg;
|
|
36708
|
+
const nNextB = j + 1 < count - 1 ? segNormals[j + 1] : isClosedLoop ? segNormals[0] : nSeg;
|
|
36709
|
+
const nA = smoothOrCrease(nSeg, nPrevA);
|
|
36710
|
+
const nB = smoothOrCrease(nSeg, nNextB);
|
|
36711
|
+
const base = mb.positions.length / 3;
|
|
36712
|
+
emitRing(pA, nA, vCoords[j]);
|
|
36713
|
+
emitRing(pB, nB, vCoords[j + 1]);
|
|
36714
|
+
mb.grid(base, seg, 1, false);
|
|
36715
|
+
}
|
|
36716
|
+
}
|
|
36717
|
+
if ((o.capped ?? o.closed) && !isClosedLoop) {
|
|
36718
|
+
const first = pts[0];
|
|
36719
|
+
const last = pts[count - 1];
|
|
36720
|
+
for (const [pt, ny] of [[first, -1], [last, 1]]) {
|
|
36721
|
+
if (pt.x <= 1e-5) continue;
|
|
36722
|
+
const center = mb.vertex([
|
|
36723
|
+
0,
|
|
36724
|
+
pt.y,
|
|
36725
|
+
0
|
|
36726
|
+
], [
|
|
36727
|
+
0,
|
|
36728
|
+
ny,
|
|
36729
|
+
0
|
|
36730
|
+
], [.5, .5]);
|
|
36731
|
+
const ring$1 = mb.positions.length / 3;
|
|
36732
|
+
for (let i = 0; i <= seg; i++) {
|
|
36733
|
+
const phi = phiStart + i / seg * phiLength;
|
|
36734
|
+
const c = Math.cos(phi);
|
|
36735
|
+
const s = Math.sin(phi);
|
|
36736
|
+
mb.vertex([
|
|
36737
|
+
pt.x * c,
|
|
36738
|
+
pt.y,
|
|
36739
|
+
pt.x * s
|
|
36740
|
+
], [
|
|
36741
|
+
0,
|
|
36742
|
+
ny,
|
|
36743
|
+
0
|
|
36744
|
+
], [(c + 1) / 2, (s + 1) / 2]);
|
|
36745
|
+
}
|
|
36746
|
+
for (let i = 0; i < seg; i++) if (ny < 0) mb.indices.push(center, ring$1 + i, ring$1 + i + 1);
|
|
36747
|
+
else mb.indices.push(center, ring$1 + i + 1, ring$1 + i);
|
|
36748
|
+
}
|
|
36749
|
+
}
|
|
36750
|
+
}
|
|
36751
|
+
function buildPath3DFromSpec(spec, closedDefault = false) {
|
|
36752
|
+
if (Array.isArray(spec)) {
|
|
36753
|
+
if (spec.length < 2) throw new Error("3D path requires at least 2 points");
|
|
36754
|
+
return Path3D.catmullRom(spec, { closed: closedDefault });
|
|
36755
|
+
}
|
|
36756
|
+
if (spec.kind === "catmullRom") return Path3D.catmullRom(spec.points, {
|
|
36757
|
+
tension: spec.tension,
|
|
36758
|
+
closed: spec.closed ?? closedDefault,
|
|
36759
|
+
samplesPerSegment: spec.samplesPerSegment
|
|
36760
|
+
});
|
|
36761
|
+
if (spec.kind === "bezier") return Path3D.bezier(spec.segments, spec.samplesPerSegment);
|
|
36762
|
+
if (spec.kind === "helix") return Path3D.helix({
|
|
36763
|
+
center: spec.center ?? [
|
|
36764
|
+
0,
|
|
36765
|
+
0,
|
|
36766
|
+
0
|
|
36767
|
+
],
|
|
36768
|
+
radius: spec.radius,
|
|
36769
|
+
pitch: spec.pitch,
|
|
36770
|
+
turns: spec.turns,
|
|
36771
|
+
axis: spec.axis,
|
|
36772
|
+
samplesPerTurn: spec.samplesPerTurn
|
|
36773
|
+
});
|
|
36774
|
+
return Path3D.circle({
|
|
36775
|
+
center: spec.center ?? [
|
|
36776
|
+
0,
|
|
36777
|
+
0,
|
|
36778
|
+
0
|
|
36779
|
+
],
|
|
36780
|
+
radius: spec.radius,
|
|
36781
|
+
startAngleDeg: spec.startAngleDeg,
|
|
36782
|
+
endAngleDeg: spec.endAngleDeg,
|
|
36783
|
+
samples: spec.samples
|
|
36784
|
+
});
|
|
36785
|
+
}
|
|
36786
|
+
/**
|
|
36787
|
+
* Sweeps a circular (or thick-walled hollow pipe) cross-section along a 3D path
|
|
36788
|
+
* using Rotation-Minimizing Frames (RMF) so the tube never kinks or gimbal-flips.
|
|
36789
|
+
*/
|
|
36790
|
+
function tube(o, mb) {
|
|
36791
|
+
const closed = o.closed ?? (!Array.isArray(o.path) && o.path.kind === "catmullRom" && Boolean(o.path.closed));
|
|
36792
|
+
const path$1 = buildPath3DFromSpec(o.path, closed);
|
|
36793
|
+
const tubSeg = Math.max(2, Math.round(o.tubularSegments ?? 64));
|
|
36794
|
+
const radSeg = Math.max(3, Math.round(o.radialSegments ?? 16));
|
|
36795
|
+
const rDefault = Math.max(.001, o.radius ?? 12);
|
|
36796
|
+
const rStart = o.radiusTaper ? Math.max(0, o.radiusTaper[0]) : rDefault;
|
|
36797
|
+
const rEnd = o.radiusTaper ? Math.max(0, o.radiusTaper[1]) : rDefault;
|
|
36798
|
+
const rInnerBase = Math.max(0, Math.min(rDefault - .001, o.innerRadius ?? 0));
|
|
36799
|
+
const capped = o.capped ?? true;
|
|
36800
|
+
const frames = [];
|
|
36801
|
+
for (let j = 0; j <= tubSeg; j++) frames.push(path$1.getPointAt(j / tubSeg));
|
|
36802
|
+
const outerBase = mb.positions.length / 3;
|
|
36803
|
+
for (let j = 0; j <= tubSeg; j++) {
|
|
36804
|
+
const u = j / tubSeg;
|
|
36805
|
+
const r = rStart + (rEnd - rStart) * u;
|
|
36806
|
+
const f = frames[j];
|
|
36807
|
+
const [px, py, pz] = f.position;
|
|
36808
|
+
const [nx, ny, nz] = f.normal;
|
|
36809
|
+
const [bx, by, bz] = f.binormal;
|
|
36810
|
+
for (let i = 0; i <= radSeg; i++) {
|
|
36811
|
+
const v = i / radSeg;
|
|
36812
|
+
const theta = v * Math.PI * 2;
|
|
36813
|
+
const c = Math.cos(theta);
|
|
36814
|
+
const s = Math.sin(theta);
|
|
36815
|
+
const dirX = c * nx + s * bx;
|
|
36816
|
+
const dirY = c * ny + s * by;
|
|
36817
|
+
const dirZ = c * nz + s * bz;
|
|
36818
|
+
mb.vertex([
|
|
36819
|
+
px + r * dirX,
|
|
36820
|
+
py + r * dirY,
|
|
36821
|
+
pz + r * dirZ
|
|
36822
|
+
], normalize([
|
|
36823
|
+
dirX,
|
|
36824
|
+
dirY,
|
|
36825
|
+
dirZ
|
|
36826
|
+
]), [u, v]);
|
|
36827
|
+
}
|
|
36828
|
+
}
|
|
36829
|
+
mb.grid(outerBase, radSeg, tubSeg, true);
|
|
36830
|
+
if (rInnerBase > 1e-6) {
|
|
36831
|
+
const innerRatio = rInnerBase / rDefault;
|
|
36832
|
+
const innerBase = mb.positions.length / 3;
|
|
36833
|
+
for (let j = 0; j <= tubSeg; j++) {
|
|
36834
|
+
const u = j / tubSeg;
|
|
36835
|
+
const r = (rStart + (rEnd - rStart) * u) * innerRatio;
|
|
36836
|
+
const f = frames[j];
|
|
36837
|
+
const [px, py, pz] = f.position;
|
|
36838
|
+
const [nx, ny, nz] = f.normal;
|
|
36839
|
+
const [bx, by, bz] = f.binormal;
|
|
36840
|
+
for (let i = 0; i <= radSeg; i++) {
|
|
36841
|
+
const v = i / radSeg;
|
|
36842
|
+
const theta = v * Math.PI * 2;
|
|
36843
|
+
const c = Math.cos(theta);
|
|
36844
|
+
const s = Math.sin(theta);
|
|
36845
|
+
const dirX = c * nx + s * bx;
|
|
36846
|
+
const dirY = c * ny + s * by;
|
|
36847
|
+
const dirZ = c * nz + s * bz;
|
|
36848
|
+
mb.vertex([
|
|
36849
|
+
px + r * dirX,
|
|
36850
|
+
py + r * dirY,
|
|
36851
|
+
pz + r * dirZ
|
|
36852
|
+
], normalize([
|
|
36853
|
+
-dirX,
|
|
36854
|
+
-dirY,
|
|
36855
|
+
-dirZ
|
|
36856
|
+
]), [u, v]);
|
|
36857
|
+
}
|
|
36858
|
+
}
|
|
36859
|
+
mb.grid(innerBase, radSeg, tubSeg, false);
|
|
36860
|
+
if (!closed && capped) for (const [j, sign] of [[0, -1], [tubSeg, 1]]) {
|
|
36861
|
+
const u = j / tubSeg;
|
|
36862
|
+
const rOut = rStart + (rEnd - rStart) * u;
|
|
36863
|
+
const rIn = rOut * innerRatio;
|
|
36864
|
+
const f = frames[j];
|
|
36865
|
+
const [px, py, pz] = f.position;
|
|
36866
|
+
const [nx, ny, nz] = f.normal;
|
|
36867
|
+
const [bx, by, bz] = f.binormal;
|
|
36868
|
+
const capN = normalize([
|
|
36869
|
+
f.tangent[0] * sign,
|
|
36870
|
+
f.tangent[1] * sign,
|
|
36871
|
+
f.tangent[2] * sign
|
|
36872
|
+
]);
|
|
36873
|
+
const base = mb.positions.length / 3;
|
|
36874
|
+
for (const rr of [rIn, rOut]) for (let i = 0; i <= radSeg; i++) {
|
|
36875
|
+
const theta = i / radSeg * Math.PI * 2;
|
|
36876
|
+
const c = Math.cos(theta);
|
|
36877
|
+
const s = Math.sin(theta);
|
|
36878
|
+
const dirX = c * nx + s * bx;
|
|
36879
|
+
const dirY = c * ny + s * by;
|
|
36880
|
+
const dirZ = c * nz + s * bz;
|
|
36881
|
+
mb.vertex([
|
|
36882
|
+
px + rr * dirX,
|
|
36883
|
+
py + rr * dirY,
|
|
36884
|
+
pz + rr * dirZ
|
|
36885
|
+
], capN, [(c * (rr / rOut) + 1) / 2, (s * (rr / rOut) + 1) / 2]);
|
|
36886
|
+
}
|
|
36887
|
+
mb.grid(base, radSeg, 1, sign < 0);
|
|
36888
|
+
}
|
|
36889
|
+
} else if (!closed && capped) for (const [j, sign] of [[0, -1], [tubSeg, 1]]) {
|
|
36890
|
+
const u = j / tubSeg;
|
|
36891
|
+
const r = rStart + (rEnd - rStart) * u;
|
|
36892
|
+
if (r <= 1e-6) continue;
|
|
36893
|
+
const f = frames[j];
|
|
36894
|
+
const [px, py, pz] = f.position;
|
|
36895
|
+
const [nx, ny, nz] = f.normal;
|
|
36896
|
+
const [bx, by, bz] = f.binormal;
|
|
36897
|
+
const capN = normalize([
|
|
36898
|
+
f.tangent[0] * sign,
|
|
36899
|
+
f.tangent[1] * sign,
|
|
36900
|
+
f.tangent[2] * sign
|
|
36901
|
+
]);
|
|
36902
|
+
const center = mb.vertex([
|
|
36903
|
+
px,
|
|
36904
|
+
py,
|
|
36905
|
+
pz
|
|
36906
|
+
], capN, [.5, .5]);
|
|
36907
|
+
const ring$1 = mb.positions.length / 3;
|
|
36908
|
+
for (let i = 0; i <= radSeg; i++) {
|
|
36909
|
+
const theta = i / radSeg * Math.PI * 2;
|
|
36910
|
+
const c = Math.cos(theta);
|
|
36911
|
+
const s = Math.sin(theta);
|
|
36912
|
+
const dirX = c * nx + s * bx;
|
|
36913
|
+
const dirY = c * ny + s * by;
|
|
36914
|
+
const dirZ = c * nz + s * bz;
|
|
36915
|
+
mb.vertex([
|
|
36916
|
+
px + r * dirX,
|
|
36917
|
+
py + r * dirY,
|
|
36918
|
+
pz + r * dirZ
|
|
36919
|
+
], capN, [(c + 1) / 2, (s + 1) / 2]);
|
|
36920
|
+
}
|
|
36921
|
+
for (let i = 0; i < radSeg; i++) if (sign > 0) mb.indices.push(center, ring$1 + i, ring$1 + i + 1);
|
|
36922
|
+
else mb.indices.push(center, ring$1 + i + 1, ring$1 + i);
|
|
36923
|
+
}
|
|
36924
|
+
}
|
|
36925
|
+
function resolvePointArray(spec) {
|
|
36926
|
+
if (Array.isArray(spec)) return spec;
|
|
36927
|
+
const path$1 = buildPath3DFromSpec(spec);
|
|
36928
|
+
const count = 96;
|
|
36929
|
+
const out = [];
|
|
36930
|
+
for (let i = 0; i <= count; i++) out.push(path$1.getPointAt(i / count).position);
|
|
36931
|
+
return out;
|
|
36932
|
+
}
|
|
36933
|
+
/**
|
|
36934
|
+
* Native 3D line geometry (`line-list` topology) with optional dashing and per-vertex colors.
|
|
36935
|
+
*/
|
|
36936
|
+
function line3d(o, mb) {
|
|
36937
|
+
mb.topology = "line-list";
|
|
36938
|
+
const pts = resolvePointArray(o.points);
|
|
36939
|
+
if (pts.length < 2) return;
|
|
36940
|
+
const parsedColors = o.colors?.map((c) => parseHexOrRgbColor(c));
|
|
36941
|
+
const mode = o.mode ?? "strip";
|
|
36942
|
+
if (o.dashSize && o.dashSize > 0 && mode === "strip") {
|
|
36943
|
+
const dash = o.dashSize;
|
|
36944
|
+
const cycle = dash + (o.gapSize ?? dash);
|
|
36945
|
+
const workPts = o.closed ? [...pts, pts[0]] : pts;
|
|
36946
|
+
let dist = 0;
|
|
36947
|
+
for (let i = 0; i < workPts.length - 1; i++) {
|
|
36948
|
+
const a = workPts[i];
|
|
36949
|
+
const b = workPts[i + 1];
|
|
36950
|
+
const segLen = Math.hypot(b[0] - a[0], b[1] - a[1], b[2] - a[2]);
|
|
36951
|
+
if (segLen < 1e-6) continue;
|
|
36952
|
+
const dir = [
|
|
36953
|
+
(b[0] - a[0]) / segLen,
|
|
36954
|
+
(b[1] - a[1]) / segLen,
|
|
36955
|
+
(b[2] - a[2]) / segLen
|
|
36956
|
+
];
|
|
36957
|
+
const colA = parsedColors?.[i % parsedColors.length];
|
|
36958
|
+
let local = 0;
|
|
36959
|
+
while (local < segLen) {
|
|
36960
|
+
const phase = (dist + local) % cycle;
|
|
36961
|
+
if (phase < dash) {
|
|
36962
|
+
const step = Math.min(dash - phase, segLen - local);
|
|
36963
|
+
const p0 = [
|
|
36964
|
+
a[0] + dir[0] * local,
|
|
36965
|
+
a[1] + dir[1] * local,
|
|
36966
|
+
a[2] + dir[2] * local
|
|
36967
|
+
];
|
|
36968
|
+
const p1 = [
|
|
36969
|
+
a[0] + dir[0] * (local + step),
|
|
36970
|
+
a[1] + dir[1] * (local + step),
|
|
36971
|
+
a[2] + dir[2] * (local + step)
|
|
36972
|
+
];
|
|
36973
|
+
const idx0 = mb.vertex(p0, [
|
|
36974
|
+
0,
|
|
36975
|
+
-1,
|
|
36976
|
+
0
|
|
36977
|
+
], [0, 0], colA);
|
|
36978
|
+
const idx1 = mb.vertex(p1, [
|
|
36979
|
+
0,
|
|
36980
|
+
-1,
|
|
36981
|
+
0
|
|
36982
|
+
], [1, 0], colA);
|
|
36983
|
+
mb.indices.push(idx0, idx1);
|
|
36984
|
+
local += step;
|
|
36985
|
+
} else local += cycle - phase;
|
|
36986
|
+
}
|
|
36987
|
+
dist += segLen;
|
|
36988
|
+
}
|
|
36989
|
+
return;
|
|
36990
|
+
}
|
|
36991
|
+
for (let i = 0; i < pts.length; i++) {
|
|
36992
|
+
const u = pts.length > 1 ? i / (pts.length - 1) : 0;
|
|
36993
|
+
mb.vertex(pts[i], [
|
|
36994
|
+
0,
|
|
36995
|
+
-1,
|
|
36996
|
+
0
|
|
36997
|
+
], [u, 0], parsedColors ? parsedColors[i % parsedColors.length] : void 0);
|
|
36998
|
+
}
|
|
36999
|
+
if (mode === "segments") for (let i = 0; i + 1 < pts.length; i += 2) mb.indices.push(i, i + 1);
|
|
37000
|
+
else {
|
|
37001
|
+
for (let i = 0; i < pts.length - 1; i++) mb.indices.push(i, i + 1);
|
|
37002
|
+
if (o.closed && pts.length >= 3) mb.indices.push(pts.length - 1, 0);
|
|
37003
|
+
}
|
|
37004
|
+
}
|
|
37005
|
+
/**
|
|
37006
|
+
* 3D point cloud geometry: either native GPU `point-list` topology (`pointSize <= 0` or omitted)
|
|
37007
|
+
* or icosahedral 3D dots of radius `pointSize` for diagram vertices that scale with perspective.
|
|
37008
|
+
*/
|
|
37009
|
+
function points3d(o, mb) {
|
|
37010
|
+
const pts = resolvePointArray(o.points);
|
|
37011
|
+
if (pts.length === 0) return;
|
|
37012
|
+
const parsedColors = o.colors?.map((c) => parseHexOrRgbColor(c));
|
|
37013
|
+
const pointSize = o.pointSize ?? 0;
|
|
37014
|
+
if (pointSize > 0) {
|
|
37015
|
+
const dotMb = new MeshBuilder();
|
|
37016
|
+
polyhedron({
|
|
37017
|
+
type: "polyhedron",
|
|
37018
|
+
shape: "icosphere",
|
|
37019
|
+
radius: pointSize,
|
|
37020
|
+
detail: 1,
|
|
37021
|
+
flatShaded: false
|
|
37022
|
+
}, dotMb);
|
|
37023
|
+
const dotVerts = dotMb.positions.length / 3;
|
|
37024
|
+
for (let pIdx = 0; pIdx < pts.length; pIdx++) {
|
|
37025
|
+
const [px, py, pz] = pts[pIdx];
|
|
37026
|
+
const col = parsedColors ? parsedColors[pIdx % parsedColors.length] : void 0;
|
|
37027
|
+
const base = mb.positions.length / 3;
|
|
37028
|
+
for (let v = 0; v < dotVerts; v++) mb.vertex([
|
|
37029
|
+
px + dotMb.positions[v * 3],
|
|
37030
|
+
py + dotMb.positions[v * 3 + 1],
|
|
37031
|
+
pz + dotMb.positions[v * 3 + 2]
|
|
37032
|
+
], [
|
|
37033
|
+
dotMb.normals[v * 3],
|
|
37034
|
+
dotMb.normals[v * 3 + 1],
|
|
37035
|
+
dotMb.normals[v * 3 + 2]
|
|
37036
|
+
], [dotMb.uvs[v * 2], dotMb.uvs[v * 2 + 1]], col);
|
|
37037
|
+
for (const idx of dotMb.indices) mb.indices.push(base + idx);
|
|
37038
|
+
}
|
|
37039
|
+
return;
|
|
37040
|
+
}
|
|
37041
|
+
mb.topology = "point-list";
|
|
37042
|
+
for (let i = 0; i < pts.length; i++) {
|
|
37043
|
+
const u = pts.length > 1 ? i / (pts.length - 1) : 0;
|
|
37044
|
+
const idx = mb.vertex(pts[i], [
|
|
37045
|
+
0,
|
|
37046
|
+
-1,
|
|
37047
|
+
0
|
|
37048
|
+
], [u, 0], parsedColors ? parsedColors[i % parsedColors.length] : void 0);
|
|
37049
|
+
mb.indices.push(idx);
|
|
37050
|
+
}
|
|
37051
|
+
}
|
|
37052
|
+
function shard(o, mb) {
|
|
37053
|
+
const r = o.radius ?? 50;
|
|
37054
|
+
const hx = (o.size ? o.size[0] : r) || 50;
|
|
37055
|
+
const hy = (o.size ? o.size[1] : r) || 50;
|
|
37056
|
+
const hz = (o.size ? o.size[2] : r) || 50;
|
|
37057
|
+
const maxR = Math.max(hx, hy, hz);
|
|
37058
|
+
const facets = Math.max(4, Math.min(64, Math.round(o.facets ?? 14)));
|
|
37059
|
+
const seed = Math.round(o.seed ?? 1) >>> 0;
|
|
37060
|
+
const irregularity = Math.max(0, Math.min(.85, o.irregularity ?? .35));
|
|
37061
|
+
let state = BigInt(seed) * 6364136223846793005n + 1442695040888963407n;
|
|
37062
|
+
const rnd = () => {
|
|
37063
|
+
state = state * 6364136223846793005n + 1442695040888963407n;
|
|
37064
|
+
const xorshifted = Number((state >> 18n ^ state) >> 27n) >>> 0;
|
|
37065
|
+
const rot = Number(state >> 59n) >>> 0;
|
|
37066
|
+
return ((xorshifted >>> rot | xorshifted << (32 - rot & 31)) >>> 0) / 4294967296;
|
|
37067
|
+
};
|
|
37068
|
+
let faces = [
|
|
37069
|
+
[
|
|
37070
|
+
[
|
|
37071
|
+
-hx,
|
|
37072
|
+
-hy,
|
|
37073
|
+
-hz
|
|
37074
|
+
],
|
|
37075
|
+
[
|
|
37076
|
+
hx,
|
|
37077
|
+
-hy,
|
|
37078
|
+
-hz
|
|
37079
|
+
],
|
|
37080
|
+
[
|
|
37081
|
+
hx,
|
|
37082
|
+
hy,
|
|
37083
|
+
-hz
|
|
37084
|
+
],
|
|
37085
|
+
[
|
|
37086
|
+
-hx,
|
|
37087
|
+
hy,
|
|
37088
|
+
-hz
|
|
37089
|
+
]
|
|
37090
|
+
],
|
|
37091
|
+
[
|
|
37092
|
+
[
|
|
37093
|
+
hx,
|
|
37094
|
+
-hy,
|
|
37095
|
+
hz
|
|
37096
|
+
],
|
|
37097
|
+
[
|
|
37098
|
+
-hx,
|
|
37099
|
+
-hy,
|
|
37100
|
+
hz
|
|
37101
|
+
],
|
|
37102
|
+
[
|
|
37103
|
+
-hx,
|
|
37104
|
+
hy,
|
|
37105
|
+
hz
|
|
37106
|
+
],
|
|
37107
|
+
[
|
|
37108
|
+
hx,
|
|
37109
|
+
hy,
|
|
37110
|
+
hz
|
|
37111
|
+
]
|
|
37112
|
+
],
|
|
37113
|
+
[
|
|
37114
|
+
[
|
|
37115
|
+
-hx,
|
|
37116
|
+
-hy,
|
|
37117
|
+
hz
|
|
37118
|
+
],
|
|
37119
|
+
[
|
|
37120
|
+
-hx,
|
|
37121
|
+
-hy,
|
|
37122
|
+
-hz
|
|
37123
|
+
],
|
|
37124
|
+
[
|
|
37125
|
+
-hx,
|
|
37126
|
+
hy,
|
|
37127
|
+
-hz
|
|
35095
37128
|
],
|
|
35096
37129
|
[
|
|
35097
37130
|
-hx,
|
|
@@ -35330,24 +37363,7 @@ function shard(o, mb) {
|
|
|
35330
37363
|
for (let j = 1; j < face.length - 1; j++) mb.indices.push(baseIdx, baseIdx + j, baseIdx + j + 1);
|
|
35331
37364
|
}
|
|
35332
37365
|
}
|
|
35333
|
-
|
|
35334
|
-
function generatePrimitiveGeometry(options) {
|
|
35335
|
-
const mb = new MeshBuilder();
|
|
35336
|
-
if (options.type === "roundedBox") roundedBox(options, mb);
|
|
35337
|
-
else if (options.type === "sphere") sphere(options, mb);
|
|
35338
|
-
else if (options.type === "cylinder") cylinder(options, mb);
|
|
35339
|
-
else if (options.type === "shard") shard(options, mb);
|
|
35340
|
-
else throw new Error(`Unknown 3D primitive: ${options.type}`);
|
|
35341
|
-
const name = options.type;
|
|
35342
|
-
const mesh = mb.build(name);
|
|
35343
|
-
const material = {
|
|
35344
|
-
name: `${name}-material`,
|
|
35345
|
-
diffuseColor: parseHexOrRgbColor(options.color ?? "#ffffff"),
|
|
35346
|
-
shading: options.material ?? "lit",
|
|
35347
|
-
shininess: options.shininess ?? 32,
|
|
35348
|
-
roughness: options.roughness,
|
|
35349
|
-
metallic: options.metallic
|
|
35350
|
-
};
|
|
37366
|
+
function finalizeModel3DData(name, meshes, materials) {
|
|
35351
37367
|
const min = [
|
|
35352
37368
|
Number.POSITIVE_INFINITY,
|
|
35353
37369
|
Number.POSITIVE_INFINITY,
|
|
@@ -35358,11 +37374,17 @@ function generatePrimitiveGeometry(options) {
|
|
|
35358
37374
|
Number.NEGATIVE_INFINITY,
|
|
35359
37375
|
Number.NEGATIVE_INFINITY
|
|
35360
37376
|
];
|
|
35361
|
-
const
|
|
35362
|
-
|
|
35363
|
-
|
|
35364
|
-
|
|
35365
|
-
|
|
37377
|
+
for (const mesh of meshes) {
|
|
37378
|
+
const pos = mesh.positions;
|
|
37379
|
+
for (let i = 0; i < pos.length; i += 3) for (let k = 0; k < 3; k++) {
|
|
37380
|
+
const v = pos[i + k];
|
|
37381
|
+
if (v < min[k]) min[k] = v;
|
|
37382
|
+
if (v > max[k]) max[k] = v;
|
|
37383
|
+
}
|
|
37384
|
+
}
|
|
37385
|
+
if (!Number.isFinite(min[0])) {
|
|
37386
|
+
min[0] = min[1] = min[2] = 0;
|
|
37387
|
+
max[0] = max[1] = max[2] = 0;
|
|
35366
37388
|
}
|
|
35367
37389
|
const size = [
|
|
35368
37390
|
max[0] - min[0],
|
|
@@ -35371,8 +37393,8 @@ function generatePrimitiveGeometry(options) {
|
|
|
35371
37393
|
];
|
|
35372
37394
|
return {
|
|
35373
37395
|
name: `primitive-${name}`,
|
|
35374
|
-
meshes
|
|
35375
|
-
materials
|
|
37396
|
+
meshes,
|
|
37397
|
+
materials,
|
|
35376
37398
|
animations: [],
|
|
35377
37399
|
bounds: {
|
|
35378
37400
|
min,
|
|
@@ -35387,6 +37409,36 @@ function generatePrimitiveGeometry(options) {
|
|
|
35387
37409
|
}
|
|
35388
37410
|
};
|
|
35389
37411
|
}
|
|
37412
|
+
/** Builds a procedural solid as a Model3DData. */
|
|
37413
|
+
function generatePrimitiveGeometry(options) {
|
|
37414
|
+
if (options.type === "extrude") return buildExtrudedShapeModel(options);
|
|
37415
|
+
const mb = new MeshBuilder();
|
|
37416
|
+
if (options.type === "roundedBox") roundedBox(options, mb);
|
|
37417
|
+
else if (options.type === "sphere") sphere(options, mb);
|
|
37418
|
+
else if (options.type === "cylinder") cylinder(options, mb);
|
|
37419
|
+
else if (options.type === "torus") torus(options, mb);
|
|
37420
|
+
else if (options.type === "capsule") capsule(options, mb);
|
|
37421
|
+
else if (options.type === "ring") ring(options, mb);
|
|
37422
|
+
else if (options.type === "polyhedron") polyhedron(options, mb);
|
|
37423
|
+
else if (options.type === "lathe") lathe(options, mb);
|
|
37424
|
+
else if (options.type === "tube") tube(options, mb);
|
|
37425
|
+
else if (options.type === "line3d") line3d(options, mb);
|
|
37426
|
+
else if (options.type === "points3d") points3d(options, mb);
|
|
37427
|
+
else if (options.type === "shard") shard(options, mb);
|
|
37428
|
+
else throw new Error(`Unknown 3D primitive: ${options.type}`);
|
|
37429
|
+
const name = options.type;
|
|
37430
|
+
const mesh = mb.build(name);
|
|
37431
|
+
const defaultShading = options.type === "line3d" || options.type === "points3d" && (options.pointSize ?? 0) <= 0 ? "unlit" : "lit";
|
|
37432
|
+
const material = {
|
|
37433
|
+
name: `${name}-material`,
|
|
37434
|
+
diffuseColor: parseHexOrRgbColor(options.color ?? "#ffffff"),
|
|
37435
|
+
shading: options.material ?? defaultShading,
|
|
37436
|
+
shininess: options.shininess ?? 32,
|
|
37437
|
+
roughness: options.roughness,
|
|
37438
|
+
metallic: options.metallic
|
|
37439
|
+
};
|
|
37440
|
+
return finalizeModel3DData(name, [mesh], { [material.name]: material });
|
|
37441
|
+
}
|
|
35390
37442
|
const primitiveCache = /* @__PURE__ */ new Map();
|
|
35391
37443
|
/**
|
|
35392
37444
|
* Like generatePrimitiveGeometry, but identical options return the same
|
|
@@ -37084,6 +39136,7 @@ var Renderer3D = class {
|
|
|
37084
39136
|
dofBindGroupLayout;
|
|
37085
39137
|
cameraPool;
|
|
37086
39138
|
lightsPool;
|
|
39139
|
+
directLightsPool;
|
|
37087
39140
|
instancePool;
|
|
37088
39141
|
cameraUniformBindGroupCache = new UniformBindGroupCache();
|
|
37089
39142
|
samplerCache = new SamplerCache();
|
|
@@ -37108,6 +39161,7 @@ var Renderer3D = class {
|
|
|
37108
39161
|
modelCache = /* @__PURE__ */ new Map();
|
|
37109
39162
|
lastCameraPose = null;
|
|
37110
39163
|
shadowTexture = null;
|
|
39164
|
+
shadowTextures = /* @__PURE__ */ new Map();
|
|
37111
39165
|
placeholderShadowTexture = null;
|
|
37112
39166
|
shadowSampler = null;
|
|
37113
39167
|
meshBounds = /* @__PURE__ */ new WeakMap();
|
|
@@ -37132,6 +39186,7 @@ var Renderer3D = class {
|
|
|
37132
39186
|
this.floorReflectionPipeline = new FloorReflectionPipeline(device, format, sampleCount, this.quad3dPipeline.cameraLayout, this.quad3dPipeline.lightsLayout, "depth24plus");
|
|
37133
39187
|
this.cameraPool = new BufferPool(320, GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST);
|
|
37134
39188
|
this.lightsPool = new BufferPool(LIGHT_UNIFORM_SIZE_BYTES, GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST);
|
|
39189
|
+
this.directLightsPool = new BufferPool(64, GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST);
|
|
37135
39190
|
this.instancePool = new BufferPool(65536, GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST);
|
|
37136
39191
|
const dofModule = device.createShaderModule({
|
|
37137
39192
|
label: "dof-bokeh.wgsl",
|
|
@@ -37183,6 +39238,7 @@ var Renderer3D = class {
|
|
|
37183
39238
|
this.lastCameraPose = null;
|
|
37184
39239
|
this.lastCameraBuffer = null;
|
|
37185
39240
|
this.lightsPool.reset();
|
|
39241
|
+
this.directLightsPool.reset();
|
|
37186
39242
|
this.instancePool.reset();
|
|
37187
39243
|
this.quad3dPipeline.resetPools();
|
|
37188
39244
|
this.slug3dPipeline.resetPools();
|
|
@@ -37367,11 +39423,14 @@ var Renderer3D = class {
|
|
|
37367
39423
|
return this.cameraUniformBindGroupCache.getBindGroup(this.device, this.quad3dPipeline.cameraLayout, cameraBuffer);
|
|
37368
39424
|
}
|
|
37369
39425
|
getOrCreateLightsBuffer(lights, world) {
|
|
37370
|
-
const lightsData = Light3D.packLightsUniforms(lights ?? [], world?.environment, world?.shadow);
|
|
39426
|
+
const lightsData = Light3D.packLightsUniforms(lights ?? [], world?.environment, Array.isArray(world?.shadow) ? world.shadow[0] : world?.shadow);
|
|
37371
39427
|
return this.lightsPool.getBuffer(this.device, lightsData);
|
|
37372
39428
|
}
|
|
37373
39429
|
/** Lights uniform + shadow map + comparison sampler (group 3 of every lit shader). */
|
|
37374
|
-
createLightsBindGroup(lightsBuffer, withShadow) {
|
|
39430
|
+
createLightsBindGroup(lightsBuffer, withShadow, lights, shadows) {
|
|
39431
|
+
const data = Light3D.packDirectLights(lights, shadows);
|
|
39432
|
+
if (data.byteLength > this.device.limits.maxStorageBufferBindingSize) throw new Error(`Direct lights require ${data.byteLength} bytes, exceeding the device storage binding limit of ${this.device.limits.maxStorageBufferBindingSize} bytes`);
|
|
39433
|
+
const directBuffer = this.directLightsPool.getBuffer(this.device, data);
|
|
37375
39434
|
this.shadowSampler ??= this.device.createSampler({
|
|
37376
39435
|
label: "ShadowComparisonSampler",
|
|
37377
39436
|
compare: "less-equal",
|
|
@@ -37400,11 +39459,15 @@ var Renderer3D = class {
|
|
|
37400
39459
|
},
|
|
37401
39460
|
{
|
|
37402
39461
|
binding: 1,
|
|
37403
|
-
resource: map.createView()
|
|
39462
|
+
resource: map.createView({ dimension: "2d-array" })
|
|
37404
39463
|
},
|
|
37405
39464
|
{
|
|
37406
39465
|
binding: 2,
|
|
37407
39466
|
resource: this.shadowSampler
|
|
39467
|
+
},
|
|
39468
|
+
{
|
|
39469
|
+
binding: 3,
|
|
39470
|
+
resource: { buffer: directBuffer }
|
|
37408
39471
|
}
|
|
37409
39472
|
]
|
|
37410
39473
|
});
|
|
@@ -37487,6 +39550,9 @@ var Renderer3D = class {
|
|
|
37487
39550
|
processed.dirRadius[2]
|
|
37488
39551
|
];
|
|
37489
39552
|
const mapSize = options.mapSize ?? 2048;
|
|
39553
|
+
const layer = options.layer ?? 0;
|
|
39554
|
+
const layerCount = options.layerCount ?? 1;
|
|
39555
|
+
if (layerCount > this.device.limits.maxTextureArrayLayers) throw new Error(`Shadow maps require ${layerCount} texture layers, exceeding the device limit of ${this.device.limits.maxTextureArrayLayers}`);
|
|
37490
39556
|
const casterBounds = casters.map((c) => this.worldBounds(c));
|
|
37491
39557
|
const frustum = fitShadowFrustum({
|
|
37492
39558
|
type: kind,
|
|
@@ -37495,18 +39561,22 @@ var Renderer3D = class {
|
|
|
37495
39561
|
angle: light.angle
|
|
37496
39562
|
}, casterBounds, receivers, mapSize);
|
|
37497
39563
|
if (!frustum) return null;
|
|
37498
|
-
|
|
37499
|
-
|
|
37500
|
-
|
|
39564
|
+
const key = `${mapSize}:${layerCount}`;
|
|
39565
|
+
let texture = this.shadowTextures.get(key);
|
|
39566
|
+
if (!texture) {
|
|
39567
|
+
texture = this.device.createTexture({
|
|
37501
39568
|
label: "ShadowMap",
|
|
37502
39569
|
size: {
|
|
37503
39570
|
width: mapSize,
|
|
37504
|
-
height: mapSize
|
|
39571
|
+
height: mapSize,
|
|
39572
|
+
depthOrArrayLayers: layerCount
|
|
37505
39573
|
},
|
|
37506
39574
|
format: SHADOW_DEPTH_FORMAT,
|
|
37507
39575
|
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING
|
|
37508
39576
|
});
|
|
39577
|
+
this.shadowTextures.set(key, texture);
|
|
37509
39578
|
}
|
|
39579
|
+
this.shadowTexture = texture;
|
|
37510
39580
|
const lightCam = new Float32Array(80);
|
|
37511
39581
|
lightCam.set(frustum.viewProj, 32);
|
|
37512
39582
|
lightCam.set(frustum.viewProj, 0);
|
|
@@ -37525,7 +39595,11 @@ var Renderer3D = class {
|
|
|
37525
39595
|
label: "ShadowMapPass",
|
|
37526
39596
|
colorAttachments: [],
|
|
37527
39597
|
depthStencilAttachment: {
|
|
37528
|
-
view: this.shadowTexture.createView(
|
|
39598
|
+
view: this.shadowTexture.createView({
|
|
39599
|
+
dimension: "2d",
|
|
39600
|
+
baseArrayLayer: layer,
|
|
39601
|
+
arrayLayerCount: 1
|
|
39602
|
+
}),
|
|
37529
39603
|
depthClearValue: 1,
|
|
37530
39604
|
depthLoadOp: "clear",
|
|
37531
39605
|
depthStoreOp: "store"
|
|
@@ -37576,7 +39650,7 @@ var Renderer3D = class {
|
|
|
37576
39650
|
const cameraBuffer = this.packCameraUniforms(camera, surfaceWidth, surfaceHeight);
|
|
37577
39651
|
const cameraBindGroup = this.createCameraBindGroup(cameraBuffer);
|
|
37578
39652
|
const lightsBuffer = this.getOrCreateLightsBuffer(lights, world);
|
|
37579
|
-
const lightsBindGroup = this.createLightsBindGroup(lightsBuffer, Boolean(world?.shadow));
|
|
39653
|
+
const lightsBindGroup = this.createLightsBindGroup(lightsBuffer, Boolean(world?.shadow), lights ?? [], world?.shadow ? Array.isArray(world.shadow) ? world.shadow : [world.shadow] : []);
|
|
37580
39654
|
const msaa = this.sampleCount > 1;
|
|
37581
39655
|
if (msaa && loadOp === "load") throw new Error("Renderer3D.beginPass: loadOp 'load' needs a Renderer3D built with sampleCount 1");
|
|
37582
39656
|
const attach = (view, msaaTex, clearValue, attachmentLoadOp) => msaaTex ? {
|
|
@@ -37636,9 +39710,9 @@ var Renderer3D = class {
|
|
|
37636
39710
|
const depthTex = this.getOrCreateReflectionDepthTexture(reflWidth, reflHeight);
|
|
37637
39711
|
const cameraBuffer = this.packCameraUniforms(camera, reflWidth, reflHeight);
|
|
37638
39712
|
const cameraBindGroup = this.createCameraBindGroup(cameraBuffer);
|
|
37639
|
-
const lightsData = Light3D.packLightsUniforms(lights ?? [], world?.environment, world?.shadow, true);
|
|
39713
|
+
const lightsData = Light3D.packLightsUniforms(lights ?? [], world?.environment, Array.isArray(world?.shadow) ? world.shadow[0] : world?.shadow, true);
|
|
37640
39714
|
const lightsBuffer = this.lightsPool.getBuffer(this.device, lightsData);
|
|
37641
|
-
const lightsBindGroup = this.createLightsBindGroup(lightsBuffer, Boolean(world?.shadow));
|
|
39715
|
+
const lightsBindGroup = this.createLightsBindGroup(lightsBuffer, Boolean(world?.shadow), lights ?? [], world?.shadow ? Array.isArray(world.shadow) ? world.shadow : [world.shadow] : []);
|
|
37642
39716
|
const msaa = this.sampleCount > 1;
|
|
37643
39717
|
const msaaTex = msaa ? this.getOrCreateReflectionMsaaTexture(reflWidth, reflHeight) : null;
|
|
37644
39718
|
const colorAttachments = [msaaTex ? {
|
|
@@ -38061,7 +40135,8 @@ var Renderer3D = class {
|
|
|
38061
40135
|
matte: opts.matte,
|
|
38062
40136
|
maps: opts.maps,
|
|
38063
40137
|
isInstanced: Boolean(opts.instanceBuffer || opts.instanceCount && opts.instanceCount > 1),
|
|
38064
|
-
instanceBuffer: opts.instanceBuffer
|
|
40138
|
+
instanceBuffer: opts.instanceBuffer,
|
|
40139
|
+
matrixInstances: opts.matrixInstances
|
|
38065
40140
|
}, useMrt, this.passWritesHdr, opts.instanceCount ?? 1, opts.firstInstance ?? 0);
|
|
38066
40141
|
}
|
|
38067
40142
|
loadModel(srcOrData, format = "auto", options = {}) {
|
|
@@ -38265,7 +40340,8 @@ var Renderer3D = class {
|
|
|
38265
40340
|
destroy() {
|
|
38266
40341
|
this.bloomPipeline?.destroy();
|
|
38267
40342
|
this.depthTexture?.destroy();
|
|
38268
|
-
this.
|
|
40343
|
+
for (const texture of this.shadowTextures.values()) texture.destroy();
|
|
40344
|
+
this.shadowTextures.clear();
|
|
38269
40345
|
this.placeholderShadowTexture?.destroy();
|
|
38270
40346
|
this.linearDepthTexture?.destroy();
|
|
38271
40347
|
this.msaaColorTexture?.destroy();
|
|
@@ -38284,6 +40360,7 @@ var Renderer3D = class {
|
|
|
38284
40360
|
this.reflectionBlurredTexture?.destroy();
|
|
38285
40361
|
this.cameraPool.destroy();
|
|
38286
40362
|
this.lightsPool.destroy();
|
|
40363
|
+
this.directLightsPool.destroy();
|
|
38287
40364
|
this.instancePool.destroy();
|
|
38288
40365
|
this.cameraUniformBindGroupCache.destroy();
|
|
38289
40366
|
}
|
|
@@ -38934,4 +41011,4 @@ if (typeof globalThis !== "undefined") globalThis.__GATEWAI_DELAYS__ = globalThi
|
|
|
38934
41011
|
|
|
38935
41012
|
//#endregion
|
|
38936
41013
|
export { probeVideoSize as $, TextPathBuilder as $t, emojiGraphemes as A, generateArcLengthLUT as An, CubicBezierSegmentSchema as At, jointMatrices as B, ParticleDissolveConfigSchema as Bt, drawGifNode as C, evaluateExpressionSelector as Cn, AdvancedTextAnimatorSchema as Ct, drawSignalNode as D, evaluateSpringProgress as Dn, AudioSignalComputePipeline as Dt, drawParagraphNode as E, evaluateSkewMatrix as En, AnimatableGlyphPropsSchema as Et, getPrimitiveGeometry as F, sampleAudioSpectrumScale as Fn, GlyphAnchorGroupingSchema as Ft, measureMaxCaptionHeight as G, SignalRegistry as Gt, loadModel3D as H, SelectorModeSchema as Ht, getRegisteredFontSource as I, sampleCurveGeometry as In, GlyphAnchorPointSchema as It, parseFBX as J, SpringPhysicsSchema as Jt, mediaDecoderCache as K, SkewPropertiesSchema as Kt, getRenderer2D as L, samplePathChainGeometry as Ln, KineticMarqueeConfigSchema as Lt, fitSpansToText as M, getScramblePool as Mn, EnhancedTextNodeSchema as Mt, generateExtrudedTextGeometry as N, getShuffledOrder as Nn, ExpressionSelectorSchema as Nt, drawSvgNode as O, evaluateTypewriterState as On, AudioSpectrumTypographySchema as Ot, getHeadlessFontPath as P, parseSvgPathToCubicBeziers as Pn, ExtendedGlyphPropertiesSchema as Pt, poseNodes as Q, TextCursorStyleSchema as Qt, initHeadlessWebGPU as R, signalRegistry as Rn, LineSpacingDynamicsSchema as Rt, drawCaptionNode as S, evaluateCubicBezierDerivative as Sn, AdvancedTextAnimatorBuilder as St, drawLottieNode as T, evaluateSelectorCombination as Tn, AnchorPresetSchema as Tt, loadOBJ as U, SelectorShapeSchema as Ut, loadFBX as V, SelectorBasedOnSchema as Vt, lutStore as W, SelectorUnitsSchema as Wt, parseOBJ as X, TextAnimatorBuilder as Xt, parseMTL as Y, TextAnchorConfigSchema as Yt, parseSvgPathToSegments as Z, TextCursorConfigSchema as Zt, buildShapeSvgPath as _, computeRangeSelectorWeight as _n, Vector3Math as _t, GlassPipeline as a, TextSignalSelectorSchema as an, spansText as at, colorMatrixWgsl as b, ellipseToCubicBeziers as bn, resolveEnvironment as bt, Renderer2D as c, TypingCadenceSchema as cn, GetFontAssetUrl as ct, ScreenSpaceRelightPipeline as d, VolumetricFormationConfigSchema as dn, ENVIRONMENT_PRESETS as dt, TextPathOptionsSchema as en, registerHeadlessFont as et, ShadowPipeline as f, VolumetricFormationModeSchema as fn, LIGHT_UNIFORM_SIZE_BYTES as ft, WebGPUAudioProcessor as g, computeLineLeadingDisplacement as gn, Path3D as gt, SlugPipeline as h, computeAnchorPivotOffset as hn, Matrix4Math as ht, EffectPipeline as i, TextSelectorSchema as in, shaderStore as it, ensureDevice as j, generatePathSegments as jn, DynamicStrokePropertiesSchema as jt, drawVideoNode as k, evaluateVolumetricFormation as kn, ChromaticGlitchConfigSchema as kt, Renderer3D as l, VariableFontAxesSchema as ln, resolveMediaSourceUrl as lt, SlugGeometry as m, buildWGSLSignalFn as mn, MAX_LIGHTS as mt, AudioLatentTrackCache as n, TextRangeSelectorSchema as nn, sampleMorphWeights as nt, MotionBlurPipeline as o, TextWigglySelectorSchema as on, srtLoader as ot, SlugFontCache as p, buildPathLUT as pn, Light3D as pt, parseColor as q, Spatial3DPropertiesSchema as qt, AudioMeshDeformPipeline as r, TextScrambleConfigSchema as rn, setRegisteredFontSource as rt, NodeSurfaceProvider as s, TypewriterAnimatorSchema as sn, textureCache as st, AudioLatentEngine as t, TextPathSourceSchema as tn, resolveTextSpans as tt, SSAOPipeline as u, Vec2Schema as un, Camera3D as ut, clearAllVideoCache as v, deterministicWigglyNoise as vn, linearRgb as vt, drawImageNode as w, evaluateMarqueeOffset as wn, AnchorGroupingSchema as wt, describeGpu as x, evaluateCubicBezier as xn, AETextAnimatorSchema as xt, clearHeadlessFonts as y, distanceToCurveParameter as yn, parseColorToRgb as yt, inputStore as z, waveToCubicBeziers as zn, LongShadowConfigSchema as zt };
|
|
38937
|
-
//# sourceMappingURL=dist-
|
|
41014
|
+
//# sourceMappingURL=dist-CFe1fC9l.mjs.map
|