@layoutit/polycss-react 0.2.6 → 0.2.7
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/README.md +1 -2
- package/dist/index.cjs +102 -43
- package/dist/index.d.cts +37 -2
- package/dist/index.d.ts +37 -2
- package/dist/index.js +108 -47
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -69,7 +69,7 @@ export default function App() {
|
|
|
69
69
|
### PolyScene
|
|
70
70
|
|
|
71
71
|
- `polygons` renders a static `Polygon[]` directly.
|
|
72
|
-
- `directionalLight` and `ambientLight` control scene lighting.
|
|
72
|
+
- `directionalLight`, `pointLights` (direction-only, baked mode; optional per-light `castShadow`), and `ambientLight` control scene lighting.
|
|
73
73
|
- `textureLighting` chooses `"baked"` or `"dynamic"`.
|
|
74
74
|
- `textureQuality` controls atlas raster budget.
|
|
75
75
|
- `strategies` can disable selected render strategies for diagnostics.
|
|
@@ -84,7 +84,6 @@ export default function App() {
|
|
|
84
84
|
- `autoCenter` shifts the mesh bbox center to local origin.
|
|
85
85
|
- `meshResolution` chooses `"lossy"` (default) or `"lossless"` optimization. STL imports use the conservative lossless path in both modes.
|
|
86
86
|
- `castShadow` emits CSS-projected shadows in dynamic lighting mode.
|
|
87
|
-
- Tooling can reuse `buildPolyMeshTransform`, `buildPolySceneTransform`, `worldPositionToPolyCss`, `worldDirectionToPolyCss`, `worldDirectionalLightToPolyCss`, `worldDistanceToPolyCss`, `polyCssDistanceToWorld`, and `polyCssPositionToWorld` for renderer-compatible transforms and world/CSS conversions.
|
|
88
87
|
|
|
89
88
|
### Controls
|
|
90
89
|
|
package/dist/index.cjs
CHANGED
|
@@ -2748,6 +2748,7 @@ function PolySceneInner({
|
|
|
2748
2748
|
rotY: _rotY,
|
|
2749
2749
|
zoom: _zoom,
|
|
2750
2750
|
directionalLight,
|
|
2751
|
+
pointLights,
|
|
2751
2752
|
ambientLight,
|
|
2752
2753
|
textureLighting = "baked",
|
|
2753
2754
|
textureQuality,
|
|
@@ -2805,17 +2806,19 @@ function PolySceneInner({
|
|
|
2805
2806
|
const sceneBbox = centerInputPolygons ? centerSceneBbox : renderSceneBbox;
|
|
2806
2807
|
const directionalForAtlas = textureLighting === "dynamic" ? void 0 : directionalLight;
|
|
2807
2808
|
const ambientForAtlas = textureLighting === "dynamic" ? void 0 : ambientLight;
|
|
2809
|
+
const pointLightsForAtlas = textureLighting === "dynamic" ? void 0 : pointLights;
|
|
2808
2810
|
const polyContext = (0, import_react14.useMemo)(() => {
|
|
2809
2811
|
const tileSize = 50;
|
|
2810
2812
|
return {
|
|
2811
2813
|
tileSize,
|
|
2812
2814
|
layerElevation: tileSize,
|
|
2813
2815
|
directionalLight: directionalForAtlas,
|
|
2816
|
+
pointLights: pointLightsForAtlas,
|
|
2814
2817
|
ambientLight: ambientForAtlas,
|
|
2815
2818
|
textureLighting,
|
|
2816
2819
|
seamBleed
|
|
2817
2820
|
};
|
|
2818
|
-
}, [directionalForAtlas, ambientForAtlas, textureLighting, seamBleed]);
|
|
2821
|
+
}, [directionalForAtlas, pointLightsForAtlas, ambientForAtlas, textureLighting, seamBleed]);
|
|
2819
2822
|
const autoCenterOffset = (0, import_react14.useMemo)(() => {
|
|
2820
2823
|
if (!autoCenter) return [0, 0, 0];
|
|
2821
2824
|
return [
|
|
@@ -3001,6 +3004,7 @@ function PolySceneInner({
|
|
|
3001
3004
|
() => ({
|
|
3002
3005
|
textureLighting,
|
|
3003
3006
|
directionalLight,
|
|
3007
|
+
pointLights,
|
|
3004
3008
|
ambientLight,
|
|
3005
3009
|
strategies,
|
|
3006
3010
|
seamBleed,
|
|
@@ -3017,7 +3021,7 @@ function PolySceneInner({
|
|
|
3017
3021
|
groundCssZ,
|
|
3018
3022
|
sceneEl
|
|
3019
3023
|
}),
|
|
3020
|
-
[textureLighting, directionalLight, ambientLight, strategies, seamBleed, textureLeafSizing, textureImageRendering, textureBackend, textureProjection, shadow, registerShadowCaster, registerShadowReceiver, shadowCastersVersion, hasShadowReceiver, groundCssZ, sceneEl]
|
|
3024
|
+
[textureLighting, directionalLight, pointLights, ambientLight, strategies, seamBleed, textureLeafSizing, textureImageRendering, textureBackend, textureProjection, shadow, registerShadowCaster, registerShadowReceiver, shadowCastersVersion, hasShadowReceiver, groundCssZ, sceneEl]
|
|
3021
3025
|
);
|
|
3022
3026
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PolySceneContext.Provider, { value: sceneCtxValue, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
3023
3027
|
"div",
|
|
@@ -3907,6 +3911,7 @@ var PolyMesh = (0, import_react16.forwardRef)(function PolyMesh2({
|
|
|
3907
3911
|
onFrameReady,
|
|
3908
3912
|
castShadow,
|
|
3909
3913
|
receiveShadow,
|
|
3914
|
+
shadowDefinition,
|
|
3910
3915
|
merge = true,
|
|
3911
3916
|
children,
|
|
3912
3917
|
fallback,
|
|
@@ -4175,6 +4180,18 @@ var PolyMesh = (0, import_react16.forwardRef)(function PolyMesh2({
|
|
|
4175
4180
|
direction: (0, import_polycss_core16.inverseRotateVec3)(cssLight.direction, rot)
|
|
4176
4181
|
};
|
|
4177
4182
|
}, [effectiveDirectional, bakedRotation]);
|
|
4183
|
+
const bakedPointLights = (0, import_react16.useMemo)(() => {
|
|
4184
|
+
const pls = sceneCtx?.pointLights;
|
|
4185
|
+
if (!pls || pls.length === 0) return void 0;
|
|
4186
|
+
const pos = position ?? [0, 0, 0];
|
|
4187
|
+
const rot = bakedRotation ?? [0, 0, 0];
|
|
4188
|
+
const hasRot = rot[0] !== 0 || rot[1] !== 0 || rot[2] !== 0;
|
|
4189
|
+
return pls.map((pl) => {
|
|
4190
|
+
const rel = [pl.position[0] - pos[0], pl.position[1] - pos[1], pl.position[2] - pos[2]];
|
|
4191
|
+
const local = hasRot ? (0, import_polycss_core16.inverseRotateVec3)(rel, rot) : rel;
|
|
4192
|
+
return { ...pl, position: local };
|
|
4193
|
+
});
|
|
4194
|
+
}, [sceneCtx?.pointLights, position, bakedRotation]);
|
|
4178
4195
|
const lightOccludedPolyIndices = void 0;
|
|
4179
4196
|
const atlasPlans = (0, import_react16.useMemo)(
|
|
4180
4197
|
() => {
|
|
@@ -4193,6 +4210,7 @@ var PolyMesh = (0, import_react16.forwardRef)(function PolyMesh2({
|
|
|
4193
4210
|
i,
|
|
4194
4211
|
{
|
|
4195
4212
|
directionalLight: bakedDirectional,
|
|
4213
|
+
pointLights: bakedPointLights,
|
|
4196
4214
|
ambientLight: effectiveAmbient,
|
|
4197
4215
|
seamBleed: seamBleedEdges?.has(i) ? effectiveSeamBleed : void 0,
|
|
4198
4216
|
seamEdges: seamBleedEdges?.get(i),
|
|
@@ -4202,7 +4220,7 @@ var PolyMesh = (0, import_react16.forwardRef)(function PolyMesh2({
|
|
|
4202
4220
|
basisHints[i]
|
|
4203
4221
|
));
|
|
4204
4222
|
},
|
|
4205
|
-
[renderPolygon, directVoxelEnabled, polygons, bakedDirectional, effectiveAmbient, effectiveSeamBleed, lightOccludedPolyIndices]
|
|
4223
|
+
[renderPolygon, directVoxelEnabled, polygons, bakedDirectional, bakedPointLights, effectiveAmbient, effectiveSeamBleed, lightOccludedPolyIndices]
|
|
4206
4224
|
);
|
|
4207
4225
|
const textureAtlas = useTextureAtlas(
|
|
4208
4226
|
atlasPlans,
|
|
@@ -4248,23 +4266,32 @@ var PolyMesh = (0, import_react16.forwardRef)(function PolyMesh2({
|
|
|
4248
4266
|
}
|
|
4249
4267
|
return s;
|
|
4250
4268
|
}, [atlasPlans, polygons]);
|
|
4269
|
+
const shadowCasterRegisteredRef = (0, import_react16.useRef)(false);
|
|
4270
|
+
const lastShadowPolyCountRef = (0, import_react16.useRef)(-1);
|
|
4251
4271
|
(0, import_react16.useEffect)(() => {
|
|
4252
|
-
if (!sceneRegisterShadowCaster) return;
|
|
4253
|
-
if (castShadow) {
|
|
4254
|
-
sceneRegisterShadowCaster(meshIdRef.current, {
|
|
4255
|
-
polygons,
|
|
4256
|
-
position: position ?? [0, 0, 0],
|
|
4257
|
-
scale,
|
|
4258
|
-
rotation,
|
|
4259
|
-
renderedPolygonIndices
|
|
4260
|
-
});
|
|
4261
|
-
} else {
|
|
4262
|
-
sceneRegisterShadowCaster(meshIdRef.current, null);
|
|
4263
|
-
}
|
|
4272
|
+
if (!sceneRegisterShadowCaster || !castShadow) return;
|
|
4264
4273
|
return () => {
|
|
4265
4274
|
sceneRegisterShadowCaster(meshIdRef.current, null);
|
|
4275
|
+
shadowCasterRegisteredRef.current = false;
|
|
4276
|
+
lastShadowPolyCountRef.current = -1;
|
|
4266
4277
|
};
|
|
4267
|
-
}, [sceneRegisterShadowCaster, castShadow
|
|
4278
|
+
}, [sceneRegisterShadowCaster, castShadow]);
|
|
4279
|
+
(0, import_react16.useEffect)(() => {
|
|
4280
|
+
if (!sceneRegisterShadowCaster || !castShadow) return;
|
|
4281
|
+
const followAnimation = sceneCtx?.shadow?.followAnimation ?? false;
|
|
4282
|
+
const topologyChanged = polygons.length !== lastShadowPolyCountRef.current;
|
|
4283
|
+
if (shadowCasterRegisteredRef.current && !followAnimation && !topologyChanged) return;
|
|
4284
|
+
lastShadowPolyCountRef.current = polygons.length;
|
|
4285
|
+
shadowCasterRegisteredRef.current = true;
|
|
4286
|
+
sceneRegisterShadowCaster(meshIdRef.current, {
|
|
4287
|
+
polygons,
|
|
4288
|
+
position: position ?? [0, 0, 0],
|
|
4289
|
+
scale,
|
|
4290
|
+
rotation,
|
|
4291
|
+
renderedPolygonIndices,
|
|
4292
|
+
shadowDefinition
|
|
4293
|
+
});
|
|
4294
|
+
}, [sceneRegisterShadowCaster, castShadow, polygons, position, scale, rotation, renderedPolygonIndices, shadowDefinition, sceneCtx?.shadow]);
|
|
4268
4295
|
const sceneRegisterShadowReceiver = sceneCtx?.registerShadowReceiver;
|
|
4269
4296
|
(0, import_react16.useEffect)(() => {
|
|
4270
4297
|
if (!sceneRegisterShadowReceiver) return;
|
|
@@ -4390,6 +4417,16 @@ var PolyMesh = (0, import_react16.forwardRef)(function PolyMesh2({
|
|
|
4390
4417
|
if (!shadowCasters || shadowCasters.size === 0) return null;
|
|
4391
4418
|
const userLightDir = sceneDirectionalLight?.direction ?? [0.4, -0.7, 0.59];
|
|
4392
4419
|
const lightDir = (0, import_polycss_core16.worldDirectionToCss)(userLightDir);
|
|
4420
|
+
const dynamicShading = effectiveTextureLighting === "dynamic";
|
|
4421
|
+
const scenePoints = dynamicShading ? [] : sceneCtx?.pointLights ?? [];
|
|
4422
|
+
const allPointLightsCss = scenePoints.map((pl) => ({
|
|
4423
|
+
position: (0, import_polycss_core16.worldPositionToCss)(pl.position),
|
|
4424
|
+
color: pl.color,
|
|
4425
|
+
intensity: pl.intensity
|
|
4426
|
+
}));
|
|
4427
|
+
const shadowPointIndices = scenePoints.map((pl, i) => pl.castShadow ? i : -1).filter((i) => i >= 0);
|
|
4428
|
+
const runDirectionalShadow = !!sceneDirectionalLight?.direction && (sceneDirectionalLight.intensity ?? 1) > 0;
|
|
4429
|
+
const hasShadowPoints = shadowPointIndices.length > 0;
|
|
4393
4430
|
const shadowLift = sceneShadow?.lift ?? 1e-3;
|
|
4394
4431
|
const planes = (0, import_polycss_core16.prepareReceiverFacePlanes)(
|
|
4395
4432
|
polygons,
|
|
@@ -4402,18 +4439,17 @@ var PolyMesh = (0, import_react16.forwardRef)(function PolyMesh2({
|
|
|
4402
4439
|
if (planes.length === 0) return null;
|
|
4403
4440
|
const casterInputs = [];
|
|
4404
4441
|
for (const [casterId, data] of shadowCasters) {
|
|
4405
|
-
const rendered = data.renderedPolygonIndices;
|
|
4406
4442
|
const items = (0, import_polycss_core16.prepareCasterPolyItems)(
|
|
4407
4443
|
data.polygons,
|
|
4408
4444
|
data.position,
|
|
4409
4445
|
data.scale,
|
|
4410
|
-
|
|
4446
|
+
() => true,
|
|
4411
4447
|
data.rotation ?? null
|
|
4412
4448
|
);
|
|
4413
4449
|
const isSelf = data.polygons === polygons;
|
|
4414
4450
|
const selfMap = isSelf ? selfShadowEdgeMap : void 0;
|
|
4415
4451
|
let edgeOwners;
|
|
4416
|
-
if (!isSelf && data.polygons.length >= 40) {
|
|
4452
|
+
if (!isSelf && (data.polygons.length >= 40 || hasShadowPoints)) {
|
|
4417
4453
|
const dposArr = data.position;
|
|
4418
4454
|
const drot = data.rotation ?? null;
|
|
4419
4455
|
const dsKey = JSON.stringify(data.scale ?? null);
|
|
@@ -4426,12 +4462,29 @@ var PolyMesh = (0, import_react16.forwardRef)(function PolyMesh2({
|
|
|
4426
4462
|
}
|
|
4427
4463
|
edgeOwners = cachedOwners;
|
|
4428
4464
|
}
|
|
4465
|
+
let overrideSilhouette;
|
|
4466
|
+
let overridePointSilhouettes;
|
|
4467
|
+
if (sceneShadow?.parametric) {
|
|
4468
|
+
const def = data.shadowDefinition ?? sceneShadow.definition ?? 16;
|
|
4469
|
+
const result = (0, import_polycss_core16.buildParametricCasterOverride)({
|
|
4470
|
+
polysWorldVerts: items.map((it) => it.wv),
|
|
4471
|
+
lightDir,
|
|
4472
|
+
definition: def,
|
|
4473
|
+
isSelf,
|
|
4474
|
+
style: sceneShadow.style,
|
|
4475
|
+
pointLights: shadowPointIndices.map((i) => ({ position: allPointLightsCss[i].position, index: i }))
|
|
4476
|
+
});
|
|
4477
|
+
overrideSilhouette = result.overrideSilhouette;
|
|
4478
|
+
overridePointSilhouettes = result.overridePointSilhouettes;
|
|
4479
|
+
}
|
|
4429
4480
|
casterInputs.push({
|
|
4430
4481
|
id: casterId,
|
|
4431
4482
|
items,
|
|
4432
4483
|
selfShadowEdgeMap: selfMap,
|
|
4433
4484
|
edgeOwners,
|
|
4434
|
-
casterPolygonCount: data.polygons.length
|
|
4485
|
+
casterPolygonCount: data.polygons.length,
|
|
4486
|
+
overrideSilhouette,
|
|
4487
|
+
overridePointSilhouettes
|
|
4435
4488
|
});
|
|
4436
4489
|
}
|
|
4437
4490
|
const cameraState = cameraCtx?.store.getState().cameraState;
|
|
@@ -4440,27 +4493,31 @@ var PolyMesh = (0, import_react16.forwardRef)(function PolyMesh2({
|
|
|
4440
4493
|
rotY: cameraState?.rotY ?? 45,
|
|
4441
4494
|
meshRotation: rotation
|
|
4442
4495
|
};
|
|
4443
|
-
const
|
|
4496
|
+
const faces = (0, import_polycss_core16.computeMergedReceiverShadows)({
|
|
4444
4497
|
receiverPlanes: planes,
|
|
4445
4498
|
receiverPolygons: polygons,
|
|
4446
4499
|
receiverHasTexture: polygons.some((p) => p.texture !== void 0),
|
|
4447
4500
|
casters: casterInputs,
|
|
4448
4501
|
lightDir,
|
|
4502
|
+
runDirectional: runDirectionalShadow,
|
|
4503
|
+
pointPasses: shadowPointIndices.map((i) => ({ lightPos: allPointLightsCss[i].position, index: i })),
|
|
4504
|
+
allPointLights: allPointLightsCss,
|
|
4449
4505
|
cameraRot,
|
|
4450
4506
|
ambientLight: sceneCtx?.ambientLight,
|
|
4451
4507
|
directionalLight: sceneDirectionalLight,
|
|
4452
4508
|
shadow: { color: sceneShadow?.color, opacity: sceneShadow?.opacity ?? 0.25, maxExtend: sceneShadow?.maxExtend }
|
|
4453
4509
|
});
|
|
4454
|
-
|
|
4510
|
+
if (faces.length === 0) return null;
|
|
4511
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: faces.map((fc) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
4455
4512
|
"svg",
|
|
4456
4513
|
{
|
|
4457
4514
|
className: "polycss-shadow polycss-shadow-svg polycss-shadow-receiver",
|
|
4458
4515
|
"data-poly-shadow-type": "receiver",
|
|
4459
|
-
"data-poly-shadow-receiver-face":
|
|
4460
|
-
"data-poly-shadow-receiver-polys": JSON.stringify(
|
|
4461
|
-
width:
|
|
4462
|
-
height:
|
|
4463
|
-
viewBox: `0 0 ${
|
|
4516
|
+
"data-poly-shadow-receiver-face": fc.faceIndex,
|
|
4517
|
+
"data-poly-shadow-receiver-polys": JSON.stringify(fc.memberPolyIndices),
|
|
4518
|
+
width: fc.width,
|
|
4519
|
+
height: fc.height,
|
|
4520
|
+
viewBox: `0 0 ${fc.width} ${fc.height}`,
|
|
4464
4521
|
style: {
|
|
4465
4522
|
position: "absolute",
|
|
4466
4523
|
top: 0,
|
|
@@ -4470,25 +4527,27 @@ var PolyMesh = (0, import_react16.forwardRef)(function PolyMesh2({
|
|
|
4470
4527
|
transformOrigin: "0 0",
|
|
4471
4528
|
pointerEvents: "none",
|
|
4472
4529
|
willChange: "transform",
|
|
4473
|
-
|
|
4530
|
+
opacity: fc.svgOpacity,
|
|
4531
|
+
transform: fc.matrixCss
|
|
4474
4532
|
},
|
|
4475
|
-
children:
|
|
4476
|
-
"path",
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4533
|
+
children: [
|
|
4534
|
+
fc.baseFill && fc.baseD ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: fc.baseD, fill: fc.baseFill, fillRule: "nonzero" }) : null,
|
|
4535
|
+
fc.layers.map((layer, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4536
|
+
"path",
|
|
4537
|
+
{
|
|
4538
|
+
d: layer.d,
|
|
4539
|
+
fill: layer.fill,
|
|
4540
|
+
fillRule: "nonzero",
|
|
4541
|
+
opacity: layer.opacity !== 1 ? layer.opacity.toFixed(4) : void 0,
|
|
4542
|
+
style: layer.multiply ? { mixBlendMode: "multiply" } : void 0
|
|
4543
|
+
},
|
|
4544
|
+
i
|
|
4545
|
+
))
|
|
4546
|
+
]
|
|
4488
4547
|
},
|
|
4489
|
-
`receiver-${
|
|
4548
|
+
`receiver-${fc.faceIndex}`
|
|
4490
4549
|
)) });
|
|
4491
|
-
}, [receiveShadow, shadowCasters, shadowCastersVersion, polygons, position, scale, rotation, sceneDirectionalLight, sceneShadow, sceneCtx?.ambientLight, cameraCtx?.store, cameraTick, selfShadowEdgeMap]);
|
|
4550
|
+
}, [receiveShadow, shadowCasters, shadowCastersVersion, polygons, position, scale, rotation, sceneDirectionalLight, sceneCtx?.pointLights, effectiveTextureLighting, sceneShadow, sceneCtx?.ambientLight, cameraCtx?.store, cameraTick, selfShadowEdgeMap]);
|
|
4492
4551
|
const portalSceneEl = sceneCtx?.sceneEl ?? null;
|
|
4493
4552
|
const portaledReceiverShadowSvgs = portalSceneEl && receiverShadowSvgs ? (0, import_react_dom.createPortal)(receiverShadowSvgs, portalSceneEl) : null;
|
|
4494
4553
|
setPolygonsImplRef.current = (nextPolygons) => {
|
package/dist/index.d.cts
CHANGED
|
@@ -2,7 +2,7 @@ import * as React$1 from 'react';
|
|
|
2
2
|
import React__default, { ReactNode, CSSProperties, MouseEventHandler, PointerEventHandler, FocusEventHandler, KeyboardEventHandler, IframeHTMLAttributes, RefObject, MouseEvent as MouseEvent$1 } from 'react';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
import * as _layoutit_polycss_core from '@layoutit/polycss-core';
|
|
5
|
-
import { Vec3, CameraState, CameraHandle, PolyCameraProjection, PolyTextureImageSource, PolyTexturePresentation, Vec2, PolyMaterial, PolyDirectionalLight, PolyTextureLightingMode, TextureQuality, PolyTextureLeafSizing, PolyTextureImageRendering, PolyTextureBackend, PolyTextureProjection, Polygon, PolyAmbientLight, PolySeamBleed, PolyRenderStrategiesOption, LoadMeshOptions, ParseResult, MeshResolution, BoxPolygonsOptions, ConePolygonsOptions, CylinderPolygonsOptions, DodecahedronPolygonsOptions, IcosahedronPolygonsOptions, OctahedronPolygonsOptions, PlanePolygonsOptions, RingPolygonsOptions, SpherePolygonsOptions, TetrahedronPolygonsOptions, TorusPolygonsOptions, PolyAnimationTarget, PolyAnimationMixer, PolyAnimationClip, PolyAnimationAction, ParseAnimationController } from '@layoutit/polycss-core';
|
|
5
|
+
import { Vec3, CameraState, CameraHandle, PolyCameraProjection, PolyTextureImageSource, PolyTexturePresentation, Vec2, PolyMaterial, PolyDirectionalLight, PolyTextureLightingMode, TextureQuality, PolyTextureLeafSizing, PolyTextureImageRendering, PolyTextureBackend, PolyTextureProjection, Polygon, PolyPointLight, PolyAmbientLight, PolySeamBleed, PolyRenderStrategiesOption, LoadMeshOptions, ParseResult, MeshResolution, BoxPolygonsOptions, ConePolygonsOptions, CylinderPolygonsOptions, DodecahedronPolygonsOptions, IcosahedronPolygonsOptions, OctahedronPolygonsOptions, PlanePolygonsOptions, RingPolygonsOptions, SpherePolygonsOptions, TetrahedronPolygonsOptions, TorusPolygonsOptions, PolyAnimationTarget, PolyAnimationMixer, PolyAnimationClip, PolyAnimationAction, ParseAnimationController } from '@layoutit/polycss-core';
|
|
6
6
|
export { ArrowPolygonsOptions, AutoRotateConfig, AutoRotateOption, AxesHelperOptions, BASE_TILE, BoxFace, BoxFaceOptions, BoxPolygonsOptions, CAMERA_BACKFACE_CULL_EPS, CameraCullNormalGroup, CameraCullRotation, CameraHandle, CameraState, CameraStyleInput, ConePolygonsOptions, CoverPlanarPolygonsOptions, CullInteriorOptions, CylinderPolygonsOptions, DEFAULT_CAMERA_STATE, DEFAULT_PROJECTION, DEFAULT_SEAM_FACET_SPLIT_OPTIONS, DEFAULT_SEAM_OVERLAP_OPTIONS, DodecahedronPolygonsOptions, GltfParseOptions, IcosahedronPolygonsOptions, LoadMeshOptions, LoopMode, LoopOnce, LoopPingPong, LoopRepeat, MeshResolution, MtlParseResult, NormalizeResult, ObjParseOptions, OctahedronPolygonsOptions, OptimizeAnimatedMeshPolygonsOptions, OptimizeMeshParseResultOptions, OptimizeMeshPolygonsOptions, ParseAnimationClip, ParseAnimationController, ParseResult, ParseStlColor, ParseStlSolid, ParseStlTopology, ParsedColor, PlanePolygonsOptions, PolyAmbientLight, PolyAnimationAction, PolyAnimationClip, PolyAnimationMixer, PolyAnimationTarget, PolyCameraProjection, PolyCameraSnapshot, PolyCameraSnapshotOptions, PolyCameraSnapshotSource, PolyDirectionalLight, PolyMaterial, PolyMeshTransformInput, PolyRenderStrategiesOption, PolyRenderStrategy, PolySceneTransformInput, PolyTextureBackend, PolyTextureImageLighting, PolyTextureImageRendering, PolyTextureImageSource, PolyTextureLeafSizing, PolyTextureLightingMode, PolyTexturePresentation, PolyTextureProjection, Polygon, PolygonFace, RingPolygonsOptions, SceneBbox, SceneContext, SceneContextBuildArgs, SceneContextBuildResult, SeamFacetSplitCandidate, SeamFacetSplitCandidateReason, SeamFacetSplitOptions, SeamFacetSplitReport, SeamOverlapCandidate, SeamOverlapCandidateKind, SeamOverlapDiagnostics, SeamOverlapOptions, SimplifyTriangleMeshPolygonsOptions, SolidTextureSampleOptions, StlParseOptions, TetrahedronPolygonsOptions, TexturePaintMetrics, TexturePaintMetricsOptions, TextureTriangle, TorusPolygonsOptions, VOXEL_CAMERA_CULL_AXIS_EPS, VOXEL_CAMERA_CULL_NORMAL_LIMIT, Vec2, Vec3, VoxParseOptions, arrowPolygons, axesHelperPolygons, bakeSolidTextureSampledPolygons, bakeSolidTextureSamples, boxPolygons, buildPolyCameraSceneTransform, buildPolyMeshTransform, buildPolySceneTransform, buildSceneContext, cameraCullNormalGroups, cameraCullNormalGroupsFromPolygons, cameraCullNormalKey, cameraCullVisibleSignature, cameraFacingDepth, capturePolyCameraSnapshot, clampChannel, computeSceneBbox, computeShapeLighting, computeTexturePaintMetrics, conePolygons, coverPlanarPolygons, createIsometricCamera, createPolyAnimationMixer, cssDistanceToWorld, cssPositionToWorld, cullInteriorPolygons, cylinderPolygons, dodecahedronPolygons, formatColor, icosahedronPolygons, inverseRotateVec3, isAxisAlignedSurfaceNormal, isVoxelCameraCullableNormalGroups, loadMesh, mergePolygons, normalFacesCamera, normalizeInvertMultiplier, normalizePolygons, octahedronPolygons, optimizeAnimatedMeshPolygons, optimizeMeshParseResult, optimizeMeshPolygons, parseColor, parseGltf, parseHexColor, parseMtl, parseObj, parsePureColor, parseRgbColor, parseStl, parseVox, planePolygons, polyCameraTargetToCss, polyCssDistanceToWorld, polyCssPositionToWorld, polygonCssSurfaceNormal, polygonFaces, polygonFacesCamera, repairMeshSeams, resolvePolyCameraAppliedPerspectiveStyle, ringPolygons, rotateVec3, seamFacetSplitPolygons, seamFacetSplitReport, seamOverlapDiagnostics, seamOverlapPolygons, seamOverlapReport, shadeColor, simplifyTriangleMeshPolygons, tetrahedronPolygons, torusPolygons, worldDirectionToCss, worldDirectionToPolyCss, worldDirectionalLightToCss, worldDirectionalLightToPolyCss, worldDistanceToCss, worldDistanceToPolyCss, worldPositionToCss, worldPositionToPolyCss } from '@layoutit/polycss-core';
|
|
7
7
|
|
|
8
8
|
interface PolyPerspectiveCameraProps {
|
|
@@ -118,6 +118,32 @@ interface ShadowOptions {
|
|
|
118
118
|
* disable the cap entirely.
|
|
119
119
|
*/
|
|
120
120
|
maxExtend?: number;
|
|
121
|
+
/**
|
|
122
|
+
* Cast a low-resolution parametric silhouette per caster instead of its full
|
|
123
|
+
* geometry — lighter DOM + cheaper projection at the cost of an approximate
|
|
124
|
+
* outline. Casts onto every receiver through the normal pipeline. Default:
|
|
125
|
+
* `false`. (Directional + point lights; the exact path stays the default.)
|
|
126
|
+
*/
|
|
127
|
+
parametric?: boolean;
|
|
128
|
+
/**
|
|
129
|
+
* Parametric-shadow detail (max silhouette points / pixel-grid resolution).
|
|
130
|
+
* Only used when `parametric` is true. Default: `16`. Override per mesh via
|
|
131
|
+
* `<PolyMesh shadowDefinition>`.
|
|
132
|
+
*/
|
|
133
|
+
definition?: number;
|
|
134
|
+
/**
|
|
135
|
+
* Parametric render style: `"vector"` (smooth contour, default) or `"pixel"`
|
|
136
|
+
* (greedy-meshed voxel blocks; `definition` becomes the grid resolution).
|
|
137
|
+
*/
|
|
138
|
+
style?: "vector" | "pixel";
|
|
139
|
+
/**
|
|
140
|
+
* Re-emit a caster's shadow while it animates (deforms) so the shadow follows
|
|
141
|
+
* the pose instead of freezing. Default `false`: a same-topology deform keeps
|
|
142
|
+
* the last shadow pose (re-emitting every frame is expensive). Best with
|
|
143
|
+
* `parametric` — a low-res silhouette is cheap to reproject. Topology changes
|
|
144
|
+
* (different polygon count) always re-emit regardless.
|
|
145
|
+
*/
|
|
146
|
+
followAnimation?: boolean;
|
|
121
147
|
}
|
|
122
148
|
|
|
123
149
|
/** Three.js-style transform props accepted by every PolyCSS component. */
|
|
@@ -227,6 +253,9 @@ interface PolySceneProps extends TransformProps {
|
|
|
227
253
|
rotY?: number;
|
|
228
254
|
zoom?: number;
|
|
229
255
|
directionalLight?: PolyDirectionalLight;
|
|
256
|
+
/** Point lights (world-space positions). Direction-only per-face Lambert,
|
|
257
|
+
* baked-mode only. */
|
|
258
|
+
pointLights?: PolyPointLight[];
|
|
230
259
|
ambientLight?: PolyAmbientLight;
|
|
231
260
|
/** Textured polygon lighting mode. Defaults to "baked". */
|
|
232
261
|
textureLighting?: PolyTextureLightingMode;
|
|
@@ -275,7 +304,7 @@ interface PolySceneProps extends TransformProps {
|
|
|
275
304
|
debugShowLabels?: boolean;
|
|
276
305
|
debugShowBackfaces?: boolean;
|
|
277
306
|
}
|
|
278
|
-
declare function PolySceneInner({ polygons: polygonsProp, centerPolygons: centerPolygonsProp, perspective: _perspective, rotX: _rotX, rotY: _rotY, zoom: _zoom, directionalLight, ambientLight, textureLighting, textureQuality, textureLeafSizing, textureImageRendering, textureBackend, textureProjection, seamBleed, strategies, autoCenter, shadow, className, style, children, position: _position, scale: _scale, rotation: _rotation, debugShowLabels: _debugShowLabels, debugShowBackfaces, }: PolySceneProps): react_jsx_runtime.JSX.Element;
|
|
307
|
+
declare function PolySceneInner({ polygons: polygonsProp, centerPolygons: centerPolygonsProp, perspective: _perspective, rotX: _rotX, rotY: _rotY, zoom: _zoom, directionalLight, pointLights, ambientLight, textureLighting, textureQuality, textureLeafSizing, textureImageRendering, textureBackend, textureProjection, seamBleed, strategies, autoCenter, shadow, className, style, children, position: _position, scale: _scale, rotation: _rotation, debugShowLabels: _debugShowLabels, debugShowBackfaces, }: PolySceneProps): react_jsx_runtime.JSX.Element;
|
|
279
308
|
declare const PolyScene: React$1.MemoExoticComponent<typeof PolySceneInner>;
|
|
280
309
|
|
|
281
310
|
type UseMeshOptions = LoadMeshOptions;
|
|
@@ -511,6 +540,12 @@ interface PolyMeshProps extends TransformProps, InteractionProps {
|
|
|
511
540
|
* for caster meshes — receivers handle shadow display. Defaults to `false`.
|
|
512
541
|
*/
|
|
513
542
|
receiveShadow?: boolean;
|
|
543
|
+
/**
|
|
544
|
+
* Per-mesh parametric-shadow detail, overriding the scene's
|
|
545
|
+
* `shadow.definition` for this mesh's cast/self shadow. Only used when the
|
|
546
|
+
* scene's `shadow.parametric` is true. Unset → inherit the scene definition.
|
|
547
|
+
*/
|
|
548
|
+
shadowDefinition?: number;
|
|
514
549
|
/**
|
|
515
550
|
* Apply mesh optimization (coplanar merge + interior cull) before
|
|
516
551
|
* rendering. Defaults to `true` — matches vanilla `scene.add`'s default.
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as React$1 from 'react';
|
|
|
2
2
|
import React__default, { ReactNode, CSSProperties, MouseEventHandler, PointerEventHandler, FocusEventHandler, KeyboardEventHandler, IframeHTMLAttributes, RefObject, MouseEvent as MouseEvent$1 } from 'react';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
import * as _layoutit_polycss_core from '@layoutit/polycss-core';
|
|
5
|
-
import { Vec3, CameraState, CameraHandle, PolyCameraProjection, PolyTextureImageSource, PolyTexturePresentation, Vec2, PolyMaterial, PolyDirectionalLight, PolyTextureLightingMode, TextureQuality, PolyTextureLeafSizing, PolyTextureImageRendering, PolyTextureBackend, PolyTextureProjection, Polygon, PolyAmbientLight, PolySeamBleed, PolyRenderStrategiesOption, LoadMeshOptions, ParseResult, MeshResolution, BoxPolygonsOptions, ConePolygonsOptions, CylinderPolygonsOptions, DodecahedronPolygonsOptions, IcosahedronPolygonsOptions, OctahedronPolygonsOptions, PlanePolygonsOptions, RingPolygonsOptions, SpherePolygonsOptions, TetrahedronPolygonsOptions, TorusPolygonsOptions, PolyAnimationTarget, PolyAnimationMixer, PolyAnimationClip, PolyAnimationAction, ParseAnimationController } from '@layoutit/polycss-core';
|
|
5
|
+
import { Vec3, CameraState, CameraHandle, PolyCameraProjection, PolyTextureImageSource, PolyTexturePresentation, Vec2, PolyMaterial, PolyDirectionalLight, PolyTextureLightingMode, TextureQuality, PolyTextureLeafSizing, PolyTextureImageRendering, PolyTextureBackend, PolyTextureProjection, Polygon, PolyPointLight, PolyAmbientLight, PolySeamBleed, PolyRenderStrategiesOption, LoadMeshOptions, ParseResult, MeshResolution, BoxPolygonsOptions, ConePolygonsOptions, CylinderPolygonsOptions, DodecahedronPolygonsOptions, IcosahedronPolygonsOptions, OctahedronPolygonsOptions, PlanePolygonsOptions, RingPolygonsOptions, SpherePolygonsOptions, TetrahedronPolygonsOptions, TorusPolygonsOptions, PolyAnimationTarget, PolyAnimationMixer, PolyAnimationClip, PolyAnimationAction, ParseAnimationController } from '@layoutit/polycss-core';
|
|
6
6
|
export { ArrowPolygonsOptions, AutoRotateConfig, AutoRotateOption, AxesHelperOptions, BASE_TILE, BoxFace, BoxFaceOptions, BoxPolygonsOptions, CAMERA_BACKFACE_CULL_EPS, CameraCullNormalGroup, CameraCullRotation, CameraHandle, CameraState, CameraStyleInput, ConePolygonsOptions, CoverPlanarPolygonsOptions, CullInteriorOptions, CylinderPolygonsOptions, DEFAULT_CAMERA_STATE, DEFAULT_PROJECTION, DEFAULT_SEAM_FACET_SPLIT_OPTIONS, DEFAULT_SEAM_OVERLAP_OPTIONS, DodecahedronPolygonsOptions, GltfParseOptions, IcosahedronPolygonsOptions, LoadMeshOptions, LoopMode, LoopOnce, LoopPingPong, LoopRepeat, MeshResolution, MtlParseResult, NormalizeResult, ObjParseOptions, OctahedronPolygonsOptions, OptimizeAnimatedMeshPolygonsOptions, OptimizeMeshParseResultOptions, OptimizeMeshPolygonsOptions, ParseAnimationClip, ParseAnimationController, ParseResult, ParseStlColor, ParseStlSolid, ParseStlTopology, ParsedColor, PlanePolygonsOptions, PolyAmbientLight, PolyAnimationAction, PolyAnimationClip, PolyAnimationMixer, PolyAnimationTarget, PolyCameraProjection, PolyCameraSnapshot, PolyCameraSnapshotOptions, PolyCameraSnapshotSource, PolyDirectionalLight, PolyMaterial, PolyMeshTransformInput, PolyRenderStrategiesOption, PolyRenderStrategy, PolySceneTransformInput, PolyTextureBackend, PolyTextureImageLighting, PolyTextureImageRendering, PolyTextureImageSource, PolyTextureLeafSizing, PolyTextureLightingMode, PolyTexturePresentation, PolyTextureProjection, Polygon, PolygonFace, RingPolygonsOptions, SceneBbox, SceneContext, SceneContextBuildArgs, SceneContextBuildResult, SeamFacetSplitCandidate, SeamFacetSplitCandidateReason, SeamFacetSplitOptions, SeamFacetSplitReport, SeamOverlapCandidate, SeamOverlapCandidateKind, SeamOverlapDiagnostics, SeamOverlapOptions, SimplifyTriangleMeshPolygonsOptions, SolidTextureSampleOptions, StlParseOptions, TetrahedronPolygonsOptions, TexturePaintMetrics, TexturePaintMetricsOptions, TextureTriangle, TorusPolygonsOptions, VOXEL_CAMERA_CULL_AXIS_EPS, VOXEL_CAMERA_CULL_NORMAL_LIMIT, Vec2, Vec3, VoxParseOptions, arrowPolygons, axesHelperPolygons, bakeSolidTextureSampledPolygons, bakeSolidTextureSamples, boxPolygons, buildPolyCameraSceneTransform, buildPolyMeshTransform, buildPolySceneTransform, buildSceneContext, cameraCullNormalGroups, cameraCullNormalGroupsFromPolygons, cameraCullNormalKey, cameraCullVisibleSignature, cameraFacingDepth, capturePolyCameraSnapshot, clampChannel, computeSceneBbox, computeShapeLighting, computeTexturePaintMetrics, conePolygons, coverPlanarPolygons, createIsometricCamera, createPolyAnimationMixer, cssDistanceToWorld, cssPositionToWorld, cullInteriorPolygons, cylinderPolygons, dodecahedronPolygons, formatColor, icosahedronPolygons, inverseRotateVec3, isAxisAlignedSurfaceNormal, isVoxelCameraCullableNormalGroups, loadMesh, mergePolygons, normalFacesCamera, normalizeInvertMultiplier, normalizePolygons, octahedronPolygons, optimizeAnimatedMeshPolygons, optimizeMeshParseResult, optimizeMeshPolygons, parseColor, parseGltf, parseHexColor, parseMtl, parseObj, parsePureColor, parseRgbColor, parseStl, parseVox, planePolygons, polyCameraTargetToCss, polyCssDistanceToWorld, polyCssPositionToWorld, polygonCssSurfaceNormal, polygonFaces, polygonFacesCamera, repairMeshSeams, resolvePolyCameraAppliedPerspectiveStyle, ringPolygons, rotateVec3, seamFacetSplitPolygons, seamFacetSplitReport, seamOverlapDiagnostics, seamOverlapPolygons, seamOverlapReport, shadeColor, simplifyTriangleMeshPolygons, tetrahedronPolygons, torusPolygons, worldDirectionToCss, worldDirectionToPolyCss, worldDirectionalLightToCss, worldDirectionalLightToPolyCss, worldDistanceToCss, worldDistanceToPolyCss, worldPositionToCss, worldPositionToPolyCss } from '@layoutit/polycss-core';
|
|
7
7
|
|
|
8
8
|
interface PolyPerspectiveCameraProps {
|
|
@@ -118,6 +118,32 @@ interface ShadowOptions {
|
|
|
118
118
|
* disable the cap entirely.
|
|
119
119
|
*/
|
|
120
120
|
maxExtend?: number;
|
|
121
|
+
/**
|
|
122
|
+
* Cast a low-resolution parametric silhouette per caster instead of its full
|
|
123
|
+
* geometry — lighter DOM + cheaper projection at the cost of an approximate
|
|
124
|
+
* outline. Casts onto every receiver through the normal pipeline. Default:
|
|
125
|
+
* `false`. (Directional + point lights; the exact path stays the default.)
|
|
126
|
+
*/
|
|
127
|
+
parametric?: boolean;
|
|
128
|
+
/**
|
|
129
|
+
* Parametric-shadow detail (max silhouette points / pixel-grid resolution).
|
|
130
|
+
* Only used when `parametric` is true. Default: `16`. Override per mesh via
|
|
131
|
+
* `<PolyMesh shadowDefinition>`.
|
|
132
|
+
*/
|
|
133
|
+
definition?: number;
|
|
134
|
+
/**
|
|
135
|
+
* Parametric render style: `"vector"` (smooth contour, default) or `"pixel"`
|
|
136
|
+
* (greedy-meshed voxel blocks; `definition` becomes the grid resolution).
|
|
137
|
+
*/
|
|
138
|
+
style?: "vector" | "pixel";
|
|
139
|
+
/**
|
|
140
|
+
* Re-emit a caster's shadow while it animates (deforms) so the shadow follows
|
|
141
|
+
* the pose instead of freezing. Default `false`: a same-topology deform keeps
|
|
142
|
+
* the last shadow pose (re-emitting every frame is expensive). Best with
|
|
143
|
+
* `parametric` — a low-res silhouette is cheap to reproject. Topology changes
|
|
144
|
+
* (different polygon count) always re-emit regardless.
|
|
145
|
+
*/
|
|
146
|
+
followAnimation?: boolean;
|
|
121
147
|
}
|
|
122
148
|
|
|
123
149
|
/** Three.js-style transform props accepted by every PolyCSS component. */
|
|
@@ -227,6 +253,9 @@ interface PolySceneProps extends TransformProps {
|
|
|
227
253
|
rotY?: number;
|
|
228
254
|
zoom?: number;
|
|
229
255
|
directionalLight?: PolyDirectionalLight;
|
|
256
|
+
/** Point lights (world-space positions). Direction-only per-face Lambert,
|
|
257
|
+
* baked-mode only. */
|
|
258
|
+
pointLights?: PolyPointLight[];
|
|
230
259
|
ambientLight?: PolyAmbientLight;
|
|
231
260
|
/** Textured polygon lighting mode. Defaults to "baked". */
|
|
232
261
|
textureLighting?: PolyTextureLightingMode;
|
|
@@ -275,7 +304,7 @@ interface PolySceneProps extends TransformProps {
|
|
|
275
304
|
debugShowLabels?: boolean;
|
|
276
305
|
debugShowBackfaces?: boolean;
|
|
277
306
|
}
|
|
278
|
-
declare function PolySceneInner({ polygons: polygonsProp, centerPolygons: centerPolygonsProp, perspective: _perspective, rotX: _rotX, rotY: _rotY, zoom: _zoom, directionalLight, ambientLight, textureLighting, textureQuality, textureLeafSizing, textureImageRendering, textureBackend, textureProjection, seamBleed, strategies, autoCenter, shadow, className, style, children, position: _position, scale: _scale, rotation: _rotation, debugShowLabels: _debugShowLabels, debugShowBackfaces, }: PolySceneProps): react_jsx_runtime.JSX.Element;
|
|
307
|
+
declare function PolySceneInner({ polygons: polygonsProp, centerPolygons: centerPolygonsProp, perspective: _perspective, rotX: _rotX, rotY: _rotY, zoom: _zoom, directionalLight, pointLights, ambientLight, textureLighting, textureQuality, textureLeafSizing, textureImageRendering, textureBackend, textureProjection, seamBleed, strategies, autoCenter, shadow, className, style, children, position: _position, scale: _scale, rotation: _rotation, debugShowLabels: _debugShowLabels, debugShowBackfaces, }: PolySceneProps): react_jsx_runtime.JSX.Element;
|
|
279
308
|
declare const PolyScene: React$1.MemoExoticComponent<typeof PolySceneInner>;
|
|
280
309
|
|
|
281
310
|
type UseMeshOptions = LoadMeshOptions;
|
|
@@ -511,6 +540,12 @@ interface PolyMeshProps extends TransformProps, InteractionProps {
|
|
|
511
540
|
* for caster meshes — receivers handle shadow display. Defaults to `false`.
|
|
512
541
|
*/
|
|
513
542
|
receiveShadow?: boolean;
|
|
543
|
+
/**
|
|
544
|
+
* Per-mesh parametric-shadow detail, overriding the scene's
|
|
545
|
+
* `shadow.definition` for this mesh's cast/self shadow. Only used when the
|
|
546
|
+
* scene's `shadow.parametric` is true. Unset → inherit the scene definition.
|
|
547
|
+
*/
|
|
548
|
+
shadowDefinition?: number;
|
|
514
549
|
/**
|
|
515
550
|
* Apply mesh optimization (coplanar merge + interior cull) before
|
|
516
551
|
* rendering. Defaults to `true` — matches vanilla `scene.add`'s default.
|
package/dist/index.js
CHANGED
|
@@ -2638,6 +2638,7 @@ function PolySceneInner({
|
|
|
2638
2638
|
rotY: _rotY,
|
|
2639
2639
|
zoom: _zoom,
|
|
2640
2640
|
directionalLight,
|
|
2641
|
+
pointLights,
|
|
2641
2642
|
ambientLight,
|
|
2642
2643
|
textureLighting = "baked",
|
|
2643
2644
|
textureQuality,
|
|
@@ -2695,17 +2696,19 @@ function PolySceneInner({
|
|
|
2695
2696
|
const sceneBbox = centerInputPolygons ? centerSceneBbox : renderSceneBbox;
|
|
2696
2697
|
const directionalForAtlas = textureLighting === "dynamic" ? void 0 : directionalLight;
|
|
2697
2698
|
const ambientForAtlas = textureLighting === "dynamic" ? void 0 : ambientLight;
|
|
2699
|
+
const pointLightsForAtlas = textureLighting === "dynamic" ? void 0 : pointLights;
|
|
2698
2700
|
const polyContext = useMemo6(() => {
|
|
2699
2701
|
const tileSize = 50;
|
|
2700
2702
|
return {
|
|
2701
2703
|
tileSize,
|
|
2702
2704
|
layerElevation: tileSize,
|
|
2703
2705
|
directionalLight: directionalForAtlas,
|
|
2706
|
+
pointLights: pointLightsForAtlas,
|
|
2704
2707
|
ambientLight: ambientForAtlas,
|
|
2705
2708
|
textureLighting,
|
|
2706
2709
|
seamBleed
|
|
2707
2710
|
};
|
|
2708
|
-
}, [directionalForAtlas, ambientForAtlas, textureLighting, seamBleed]);
|
|
2711
|
+
}, [directionalForAtlas, pointLightsForAtlas, ambientForAtlas, textureLighting, seamBleed]);
|
|
2709
2712
|
const autoCenterOffset = useMemo6(() => {
|
|
2710
2713
|
if (!autoCenter) return [0, 0, 0];
|
|
2711
2714
|
return [
|
|
@@ -2891,6 +2894,7 @@ function PolySceneInner({
|
|
|
2891
2894
|
() => ({
|
|
2892
2895
|
textureLighting,
|
|
2893
2896
|
directionalLight,
|
|
2897
|
+
pointLights,
|
|
2894
2898
|
ambientLight,
|
|
2895
2899
|
strategies,
|
|
2896
2900
|
seamBleed,
|
|
@@ -2907,7 +2911,7 @@ function PolySceneInner({
|
|
|
2907
2911
|
groundCssZ,
|
|
2908
2912
|
sceneEl
|
|
2909
2913
|
}),
|
|
2910
|
-
[textureLighting, directionalLight, ambientLight, strategies, seamBleed, textureLeafSizing, textureImageRendering, textureBackend, textureProjection, shadow, registerShadowCaster, registerShadowReceiver, shadowCastersVersion, hasShadowReceiver, groundCssZ, sceneEl]
|
|
2914
|
+
[textureLighting, directionalLight, pointLights, ambientLight, strategies, seamBleed, textureLeafSizing, textureImageRendering, textureBackend, textureProjection, shadow, registerShadowCaster, registerShadowReceiver, shadowCastersVersion, hasShadowReceiver, groundCssZ, sceneEl]
|
|
2911
2915
|
);
|
|
2912
2916
|
return /* @__PURE__ */ jsx8(PolySceneContext.Provider, { value: sceneCtxValue, children: /* @__PURE__ */ jsxs(
|
|
2913
2917
|
"div",
|
|
@@ -2943,9 +2947,10 @@ import {
|
|
|
2943
2947
|
} from "react";
|
|
2944
2948
|
import {
|
|
2945
2949
|
BASE_TILE as BASE_TILE3,
|
|
2950
|
+
buildParametricCasterOverride,
|
|
2946
2951
|
buildPolyMeshTransform,
|
|
2947
2952
|
buildSharedEdgeMap,
|
|
2948
|
-
|
|
2953
|
+
computeMergedReceiverShadows,
|
|
2949
2954
|
computeSceneBbox,
|
|
2950
2955
|
DEFAULT_SEAM_BLEED as DEFAULT_SEAM_BLEED2,
|
|
2951
2956
|
ensureCcw2D,
|
|
@@ -2958,7 +2963,8 @@ import {
|
|
|
2958
2963
|
prepareReceiverFacePlanes,
|
|
2959
2964
|
projectCssVertexToGround,
|
|
2960
2965
|
resolvePolyTextureLeafGeometry as resolvePolyTextureLeafGeometry2,
|
|
2961
|
-
worldDirectionToCss as worldDirectionToCss2
|
|
2966
|
+
worldDirectionToCss as worldDirectionToCss2,
|
|
2967
|
+
worldPositionToCss
|
|
2962
2968
|
} from "@layoutit/polycss-core";
|
|
2963
2969
|
|
|
2964
2970
|
// src/scene/useMesh.ts
|
|
@@ -3835,6 +3841,7 @@ var PolyMesh = forwardRef(function PolyMesh2({
|
|
|
3835
3841
|
onFrameReady,
|
|
3836
3842
|
castShadow,
|
|
3837
3843
|
receiveShadow,
|
|
3844
|
+
shadowDefinition,
|
|
3838
3845
|
merge = true,
|
|
3839
3846
|
children,
|
|
3840
3847
|
fallback,
|
|
@@ -4103,6 +4110,18 @@ var PolyMesh = forwardRef(function PolyMesh2({
|
|
|
4103
4110
|
direction: inverseRotateVec3(cssLight.direction, rot)
|
|
4104
4111
|
};
|
|
4105
4112
|
}, [effectiveDirectional, bakedRotation]);
|
|
4113
|
+
const bakedPointLights = useMemo7(() => {
|
|
4114
|
+
const pls = sceneCtx?.pointLights;
|
|
4115
|
+
if (!pls || pls.length === 0) return void 0;
|
|
4116
|
+
const pos = position ?? [0, 0, 0];
|
|
4117
|
+
const rot = bakedRotation ?? [0, 0, 0];
|
|
4118
|
+
const hasRot = rot[0] !== 0 || rot[1] !== 0 || rot[2] !== 0;
|
|
4119
|
+
return pls.map((pl) => {
|
|
4120
|
+
const rel = [pl.position[0] - pos[0], pl.position[1] - pos[1], pl.position[2] - pos[2]];
|
|
4121
|
+
const local = hasRot ? inverseRotateVec3(rel, rot) : rel;
|
|
4122
|
+
return { ...pl, position: local };
|
|
4123
|
+
});
|
|
4124
|
+
}, [sceneCtx?.pointLights, position, bakedRotation]);
|
|
4106
4125
|
const lightOccludedPolyIndices = void 0;
|
|
4107
4126
|
const atlasPlans = useMemo7(
|
|
4108
4127
|
() => {
|
|
@@ -4121,6 +4140,7 @@ var PolyMesh = forwardRef(function PolyMesh2({
|
|
|
4121
4140
|
i,
|
|
4122
4141
|
{
|
|
4123
4142
|
directionalLight: bakedDirectional,
|
|
4143
|
+
pointLights: bakedPointLights,
|
|
4124
4144
|
ambientLight: effectiveAmbient,
|
|
4125
4145
|
seamBleed: seamBleedEdges?.has(i) ? effectiveSeamBleed : void 0,
|
|
4126
4146
|
seamEdges: seamBleedEdges?.get(i),
|
|
@@ -4130,7 +4150,7 @@ var PolyMesh = forwardRef(function PolyMesh2({
|
|
|
4130
4150
|
basisHints[i]
|
|
4131
4151
|
));
|
|
4132
4152
|
},
|
|
4133
|
-
[renderPolygon, directVoxelEnabled, polygons, bakedDirectional, effectiveAmbient, effectiveSeamBleed, lightOccludedPolyIndices]
|
|
4153
|
+
[renderPolygon, directVoxelEnabled, polygons, bakedDirectional, bakedPointLights, effectiveAmbient, effectiveSeamBleed, lightOccludedPolyIndices]
|
|
4134
4154
|
);
|
|
4135
4155
|
const textureAtlas = useTextureAtlas(
|
|
4136
4156
|
atlasPlans,
|
|
@@ -4176,23 +4196,32 @@ var PolyMesh = forwardRef(function PolyMesh2({
|
|
|
4176
4196
|
}
|
|
4177
4197
|
return s;
|
|
4178
4198
|
}, [atlasPlans, polygons]);
|
|
4199
|
+
const shadowCasterRegisteredRef = useRef6(false);
|
|
4200
|
+
const lastShadowPolyCountRef = useRef6(-1);
|
|
4179
4201
|
useEffect5(() => {
|
|
4180
|
-
if (!sceneRegisterShadowCaster) return;
|
|
4181
|
-
if (castShadow) {
|
|
4182
|
-
sceneRegisterShadowCaster(meshIdRef.current, {
|
|
4183
|
-
polygons,
|
|
4184
|
-
position: position ?? [0, 0, 0],
|
|
4185
|
-
scale,
|
|
4186
|
-
rotation,
|
|
4187
|
-
renderedPolygonIndices
|
|
4188
|
-
});
|
|
4189
|
-
} else {
|
|
4190
|
-
sceneRegisterShadowCaster(meshIdRef.current, null);
|
|
4191
|
-
}
|
|
4202
|
+
if (!sceneRegisterShadowCaster || !castShadow) return;
|
|
4192
4203
|
return () => {
|
|
4193
4204
|
sceneRegisterShadowCaster(meshIdRef.current, null);
|
|
4205
|
+
shadowCasterRegisteredRef.current = false;
|
|
4206
|
+
lastShadowPolyCountRef.current = -1;
|
|
4194
4207
|
};
|
|
4195
|
-
}, [sceneRegisterShadowCaster, castShadow
|
|
4208
|
+
}, [sceneRegisterShadowCaster, castShadow]);
|
|
4209
|
+
useEffect5(() => {
|
|
4210
|
+
if (!sceneRegisterShadowCaster || !castShadow) return;
|
|
4211
|
+
const followAnimation = sceneCtx?.shadow?.followAnimation ?? false;
|
|
4212
|
+
const topologyChanged = polygons.length !== lastShadowPolyCountRef.current;
|
|
4213
|
+
if (shadowCasterRegisteredRef.current && !followAnimation && !topologyChanged) return;
|
|
4214
|
+
lastShadowPolyCountRef.current = polygons.length;
|
|
4215
|
+
shadowCasterRegisteredRef.current = true;
|
|
4216
|
+
sceneRegisterShadowCaster(meshIdRef.current, {
|
|
4217
|
+
polygons,
|
|
4218
|
+
position: position ?? [0, 0, 0],
|
|
4219
|
+
scale,
|
|
4220
|
+
rotation,
|
|
4221
|
+
renderedPolygonIndices,
|
|
4222
|
+
shadowDefinition
|
|
4223
|
+
});
|
|
4224
|
+
}, [sceneRegisterShadowCaster, castShadow, polygons, position, scale, rotation, renderedPolygonIndices, shadowDefinition, sceneCtx?.shadow]);
|
|
4196
4225
|
const sceneRegisterShadowReceiver = sceneCtx?.registerShadowReceiver;
|
|
4197
4226
|
useEffect5(() => {
|
|
4198
4227
|
if (!sceneRegisterShadowReceiver) return;
|
|
@@ -4318,6 +4347,16 @@ var PolyMesh = forwardRef(function PolyMesh2({
|
|
|
4318
4347
|
if (!shadowCasters || shadowCasters.size === 0) return null;
|
|
4319
4348
|
const userLightDir = sceneDirectionalLight?.direction ?? [0.4, -0.7, 0.59];
|
|
4320
4349
|
const lightDir = worldDirectionToCss2(userLightDir);
|
|
4350
|
+
const dynamicShading = effectiveTextureLighting === "dynamic";
|
|
4351
|
+
const scenePoints = dynamicShading ? [] : sceneCtx?.pointLights ?? [];
|
|
4352
|
+
const allPointLightsCss = scenePoints.map((pl) => ({
|
|
4353
|
+
position: worldPositionToCss(pl.position),
|
|
4354
|
+
color: pl.color,
|
|
4355
|
+
intensity: pl.intensity
|
|
4356
|
+
}));
|
|
4357
|
+
const shadowPointIndices = scenePoints.map((pl, i) => pl.castShadow ? i : -1).filter((i) => i >= 0);
|
|
4358
|
+
const runDirectionalShadow = !!sceneDirectionalLight?.direction && (sceneDirectionalLight.intensity ?? 1) > 0;
|
|
4359
|
+
const hasShadowPoints = shadowPointIndices.length > 0;
|
|
4321
4360
|
const shadowLift = sceneShadow?.lift ?? 1e-3;
|
|
4322
4361
|
const planes = prepareReceiverFacePlanes(
|
|
4323
4362
|
polygons,
|
|
@@ -4330,18 +4369,17 @@ var PolyMesh = forwardRef(function PolyMesh2({
|
|
|
4330
4369
|
if (planes.length === 0) return null;
|
|
4331
4370
|
const casterInputs = [];
|
|
4332
4371
|
for (const [casterId, data] of shadowCasters) {
|
|
4333
|
-
const rendered = data.renderedPolygonIndices;
|
|
4334
4372
|
const items = prepareCasterPolyItems(
|
|
4335
4373
|
data.polygons,
|
|
4336
4374
|
data.position,
|
|
4337
4375
|
data.scale,
|
|
4338
|
-
|
|
4376
|
+
() => true,
|
|
4339
4377
|
data.rotation ?? null
|
|
4340
4378
|
);
|
|
4341
4379
|
const isSelf = data.polygons === polygons;
|
|
4342
4380
|
const selfMap = isSelf ? selfShadowEdgeMap : void 0;
|
|
4343
4381
|
let edgeOwners;
|
|
4344
|
-
if (!isSelf && data.polygons.length >= 40) {
|
|
4382
|
+
if (!isSelf && (data.polygons.length >= 40 || hasShadowPoints)) {
|
|
4345
4383
|
const dposArr = data.position;
|
|
4346
4384
|
const drot = data.rotation ?? null;
|
|
4347
4385
|
const dsKey = JSON.stringify(data.scale ?? null);
|
|
@@ -4354,12 +4392,29 @@ var PolyMesh = forwardRef(function PolyMesh2({
|
|
|
4354
4392
|
}
|
|
4355
4393
|
edgeOwners = cachedOwners;
|
|
4356
4394
|
}
|
|
4395
|
+
let overrideSilhouette;
|
|
4396
|
+
let overridePointSilhouettes;
|
|
4397
|
+
if (sceneShadow?.parametric) {
|
|
4398
|
+
const def = data.shadowDefinition ?? sceneShadow.definition ?? 16;
|
|
4399
|
+
const result = buildParametricCasterOverride({
|
|
4400
|
+
polysWorldVerts: items.map((it) => it.wv),
|
|
4401
|
+
lightDir,
|
|
4402
|
+
definition: def,
|
|
4403
|
+
isSelf,
|
|
4404
|
+
style: sceneShadow.style,
|
|
4405
|
+
pointLights: shadowPointIndices.map((i) => ({ position: allPointLightsCss[i].position, index: i }))
|
|
4406
|
+
});
|
|
4407
|
+
overrideSilhouette = result.overrideSilhouette;
|
|
4408
|
+
overridePointSilhouettes = result.overridePointSilhouettes;
|
|
4409
|
+
}
|
|
4357
4410
|
casterInputs.push({
|
|
4358
4411
|
id: casterId,
|
|
4359
4412
|
items,
|
|
4360
4413
|
selfShadowEdgeMap: selfMap,
|
|
4361
4414
|
edgeOwners,
|
|
4362
|
-
casterPolygonCount: data.polygons.length
|
|
4415
|
+
casterPolygonCount: data.polygons.length,
|
|
4416
|
+
overrideSilhouette,
|
|
4417
|
+
overridePointSilhouettes
|
|
4363
4418
|
});
|
|
4364
4419
|
}
|
|
4365
4420
|
const cameraState = cameraCtx?.store.getState().cameraState;
|
|
@@ -4368,27 +4423,31 @@ var PolyMesh = forwardRef(function PolyMesh2({
|
|
|
4368
4423
|
rotY: cameraState?.rotY ?? 45,
|
|
4369
4424
|
meshRotation: rotation
|
|
4370
4425
|
};
|
|
4371
|
-
const
|
|
4426
|
+
const faces = computeMergedReceiverShadows({
|
|
4372
4427
|
receiverPlanes: planes,
|
|
4373
4428
|
receiverPolygons: polygons,
|
|
4374
4429
|
receiverHasTexture: polygons.some((p) => p.texture !== void 0),
|
|
4375
4430
|
casters: casterInputs,
|
|
4376
4431
|
lightDir,
|
|
4432
|
+
runDirectional: runDirectionalShadow,
|
|
4433
|
+
pointPasses: shadowPointIndices.map((i) => ({ lightPos: allPointLightsCss[i].position, index: i })),
|
|
4434
|
+
allPointLights: allPointLightsCss,
|
|
4377
4435
|
cameraRot,
|
|
4378
4436
|
ambientLight: sceneCtx?.ambientLight,
|
|
4379
4437
|
directionalLight: sceneDirectionalLight,
|
|
4380
4438
|
shadow: { color: sceneShadow?.color, opacity: sceneShadow?.opacity ?? 0.25, maxExtend: sceneShadow?.maxExtend }
|
|
4381
4439
|
});
|
|
4382
|
-
|
|
4440
|
+
if (faces.length === 0) return null;
|
|
4441
|
+
return /* @__PURE__ */ jsx9(Fragment, { children: faces.map((fc) => /* @__PURE__ */ jsxs2(
|
|
4383
4442
|
"svg",
|
|
4384
4443
|
{
|
|
4385
4444
|
className: "polycss-shadow polycss-shadow-svg polycss-shadow-receiver",
|
|
4386
4445
|
"data-poly-shadow-type": "receiver",
|
|
4387
|
-
"data-poly-shadow-receiver-face":
|
|
4388
|
-
"data-poly-shadow-receiver-polys": JSON.stringify(
|
|
4389
|
-
width:
|
|
4390
|
-
height:
|
|
4391
|
-
viewBox: `0 0 ${
|
|
4446
|
+
"data-poly-shadow-receiver-face": fc.faceIndex,
|
|
4447
|
+
"data-poly-shadow-receiver-polys": JSON.stringify(fc.memberPolyIndices),
|
|
4448
|
+
width: fc.width,
|
|
4449
|
+
height: fc.height,
|
|
4450
|
+
viewBox: `0 0 ${fc.width} ${fc.height}`,
|
|
4392
4451
|
style: {
|
|
4393
4452
|
position: "absolute",
|
|
4394
4453
|
top: 0,
|
|
@@ -4398,25 +4457,27 @@ var PolyMesh = forwardRef(function PolyMesh2({
|
|
|
4398
4457
|
transformOrigin: "0 0",
|
|
4399
4458
|
pointerEvents: "none",
|
|
4400
4459
|
willChange: "transform",
|
|
4401
|
-
|
|
4460
|
+
opacity: fc.svgOpacity,
|
|
4461
|
+
transform: fc.matrixCss
|
|
4402
4462
|
},
|
|
4403
|
-
children:
|
|
4404
|
-
"path",
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4463
|
+
children: [
|
|
4464
|
+
fc.baseFill && fc.baseD ? /* @__PURE__ */ jsx9("path", { d: fc.baseD, fill: fc.baseFill, fillRule: "nonzero" }) : null,
|
|
4465
|
+
fc.layers.map((layer, i) => /* @__PURE__ */ jsx9(
|
|
4466
|
+
"path",
|
|
4467
|
+
{
|
|
4468
|
+
d: layer.d,
|
|
4469
|
+
fill: layer.fill,
|
|
4470
|
+
fillRule: "nonzero",
|
|
4471
|
+
opacity: layer.opacity !== 1 ? layer.opacity.toFixed(4) : void 0,
|
|
4472
|
+
style: layer.multiply ? { mixBlendMode: "multiply" } : void 0
|
|
4473
|
+
},
|
|
4474
|
+
i
|
|
4475
|
+
))
|
|
4476
|
+
]
|
|
4416
4477
|
},
|
|
4417
|
-
`receiver-${
|
|
4478
|
+
`receiver-${fc.faceIndex}`
|
|
4418
4479
|
)) });
|
|
4419
|
-
}, [receiveShadow, shadowCasters, shadowCastersVersion, polygons, position, scale, rotation, sceneDirectionalLight, sceneShadow, sceneCtx?.ambientLight, cameraCtx?.store, cameraTick, selfShadowEdgeMap]);
|
|
4480
|
+
}, [receiveShadow, shadowCasters, shadowCastersVersion, polygons, position, scale, rotation, sceneDirectionalLight, sceneCtx?.pointLights, effectiveTextureLighting, sceneShadow, sceneCtx?.ambientLight, cameraCtx?.store, cameraTick, selfShadowEdgeMap]);
|
|
4420
4481
|
const portalSceneEl = sceneCtx?.sceneEl ?? null;
|
|
4421
4482
|
const portaledReceiverShadowSvgs = portalSceneEl && receiverShadowSvgs ? createPortal(receiverShadowSvgs, portalSceneEl) : null;
|
|
4422
4483
|
setPolygonsImplRef.current = (nextPolygons) => {
|
|
@@ -7819,7 +7880,7 @@ import {
|
|
|
7819
7880
|
worldDirectionalLightToPolyCss,
|
|
7820
7881
|
worldDistanceToCss,
|
|
7821
7882
|
worldDistanceToPolyCss,
|
|
7822
|
-
worldPositionToCss,
|
|
7883
|
+
worldPositionToCss as worldPositionToCss2,
|
|
7823
7884
|
worldPositionToPolyCss,
|
|
7824
7885
|
BASE_TILE as BASE_TILE7,
|
|
7825
7886
|
DEFAULT_CAMERA_STATE as DEFAULT_CAMERA_STATE2,
|
|
@@ -7968,6 +8029,6 @@ export {
|
|
|
7968
8029
|
worldDirectionalLightToPolyCss,
|
|
7969
8030
|
worldDistanceToCss,
|
|
7970
8031
|
worldDistanceToPolyCss,
|
|
7971
|
-
worldPositionToCss,
|
|
8032
|
+
worldPositionToCss2 as worldPositionToCss,
|
|
7972
8033
|
worldPositionToPolyCss
|
|
7973
8034
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@layoutit/polycss-react",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"description": "React components for the CSS-based polygon mesh rendering engine",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"access": "public"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@layoutit/polycss-core": "^0.2.
|
|
44
|
+
"@layoutit/polycss-core": "^0.2.7"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"react": "^18.0.0 || ^19.0.0",
|