@almadar/ui 5.143.0 → 5.145.0
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/avl/index.cjs +89 -9
- package/dist/avl/index.js +91 -11
- package/dist/{avl-schema-parser-0hkiHOq3.d.ts → avl-schema-parser-BRJ77Yze.d.ts} +12 -2
- package/dist/{avl-schema-parser-BZ8pICOS.d.cts → avl-schema-parser-DVmrgdwc.d.cts} +12 -2
- package/dist/{cn-CvImTgKH.d.cts → cn-BdGFhYe3.d.cts} +1 -1
- package/dist/{cn-DryTiahe.d.ts → cn-DNkqAWZK.d.ts} +1 -1
- package/dist/components/index.cjs +186 -135
- package/dist/components/index.d.cts +7 -5
- package/dist/components/index.d.ts +7 -5
- package/dist/components/index.js +187 -136
- package/dist/lib/drawable/three/index.cjs +187 -134
- package/dist/lib/drawable/three/index.d.cts +3 -3
- package/dist/lib/drawable/three/index.d.ts +3 -3
- package/dist/lib/drawable/three/index.js +162 -109
- package/dist/lib/index.d.cts +2 -2
- package/dist/lib/index.d.ts +2 -2
- package/dist/marketing/index.cjs +6 -1
- package/dist/marketing/index.js +6 -1
- package/dist/{paintDispatch-D3-5_cOb.d.cts → paintDispatch-Cb_hQj4Y.d.cts} +7 -1
- package/dist/{paintDispatch-D3-5_cOb.d.ts → paintDispatch-Cb_hQj4Y.d.ts} +7 -1
- package/dist/providers/index.cjs +82 -7
- package/dist/providers/index.js +83 -8
- package/dist/runtime/index.cjs +89 -9
- package/dist/runtime/index.js +91 -11
- package/package.json +5 -4
|
@@ -2,7 +2,7 @@ import React3, { createContext, forwardRef, useRef, useState, useMemo, useEffect
|
|
|
2
2
|
import { EventBusContext, useTraitScopeChain } from '@almadar/ui/providers';
|
|
3
3
|
import { createLogger } from '@almadar/logger';
|
|
4
4
|
import { Canvas, useThree, useFrame } from '@react-three/fiber';
|
|
5
|
-
import * as
|
|
5
|
+
import * as THREE5 from 'three';
|
|
6
6
|
import { Vector3, QuadraticBezierCurve3, MathUtils, Quaternion } from 'three';
|
|
7
7
|
import { RoomEnvironment } from 'three/examples/jsm/environments/RoomEnvironment.js';
|
|
8
8
|
import { Grid, OrbitControls, Billboard, Text, Stars, Sparkles, Html, RoundedBox } from '@react-three/drei';
|
|
@@ -507,7 +507,7 @@ function Lighting3D({
|
|
|
507
507
|
"directionalLightHelper",
|
|
508
508
|
{
|
|
509
509
|
args: [
|
|
510
|
-
new
|
|
510
|
+
new THREE5.DirectionalLight(directionalColor, directionalIntensity),
|
|
511
511
|
5
|
|
512
512
|
]
|
|
513
513
|
}
|
|
@@ -564,8 +564,8 @@ function FollowCamera3D({
|
|
|
564
564
|
offset
|
|
565
565
|
}) {
|
|
566
566
|
const { camera } = useThree();
|
|
567
|
-
const look = useRef(new
|
|
568
|
-
const goal = useRef(new
|
|
567
|
+
const look = useRef(new THREE5.Vector3(target[0], target[1], target[2]));
|
|
568
|
+
const goal = useRef(new THREE5.Vector3());
|
|
569
569
|
useFrame((_, delta) => {
|
|
570
570
|
const t = Math.min(1, delta * 5);
|
|
571
571
|
goal.current.set(target[0] + offset[0], target[1] + offset[1], target[2] + offset[2]);
|
|
@@ -765,6 +765,10 @@ var atlasCache = /* @__PURE__ */ new Map();
|
|
|
765
765
|
function isTilesheet(a) {
|
|
766
766
|
return typeof a.tileWidth === "number";
|
|
767
767
|
}
|
|
768
|
+
function isSpriteSheetAtlas(a) {
|
|
769
|
+
const s = a;
|
|
770
|
+
return typeof s.frameWidth === "number" && typeof s.frameHeight === "number" && typeof s.animations === "object";
|
|
771
|
+
}
|
|
768
772
|
function getAtlas(url, onReady) {
|
|
769
773
|
if (atlasCache.has(url)) return atlasCache.get(url) ?? void 0;
|
|
770
774
|
atlasCache.set(url, void 0);
|
|
@@ -801,6 +805,7 @@ function subRectFor(atlas, sprite) {
|
|
|
801
805
|
sh: atlas.tileHeight
|
|
802
806
|
};
|
|
803
807
|
}
|
|
808
|
+
if (isSpriteSheetAtlas(atlas)) return null;
|
|
804
809
|
const st = atlas.subTextures[sprite];
|
|
805
810
|
if (!st) return null;
|
|
806
811
|
return { sx: st.x, sy: st.y, sw: st.width, sh: st.height };
|
|
@@ -894,12 +899,12 @@ function ModelLoader({
|
|
|
894
899
|
if (!loadedModel) return null;
|
|
895
900
|
const cloned = clone(loadedModel);
|
|
896
901
|
cloned.updateMatrixWorld(true);
|
|
897
|
-
const tintColor = tint ? new
|
|
902
|
+
const tintColor = tint ? new THREE5.Color(tint) : null;
|
|
898
903
|
cloned.traverse((child) => {
|
|
899
|
-
if (child instanceof
|
|
904
|
+
if (child instanceof THREE5.Mesh) {
|
|
900
905
|
child.castShadow = castShadow;
|
|
901
906
|
child.receiveShadow = receiveShadow;
|
|
902
|
-
if (tintColor && child.material instanceof
|
|
907
|
+
if (tintColor && child.material instanceof THREE5.MeshStandardMaterial) {
|
|
903
908
|
const mat = child.material.clone();
|
|
904
909
|
mat.color.multiply(tintColor);
|
|
905
910
|
child.material = mat;
|
|
@@ -908,7 +913,7 @@ function ModelLoader({
|
|
|
908
913
|
});
|
|
909
914
|
return cloned;
|
|
910
915
|
}, [loadedModel, castShadow, receiveShadow, tint]);
|
|
911
|
-
const mixer = useMemo(() => model ? new
|
|
916
|
+
const mixer = useMemo(() => model ? new THREE5.AnimationMixer(model) : null, [model]);
|
|
912
917
|
useEffect(() => {
|
|
913
918
|
if (!mixer || !animation || clips.length === 0) return;
|
|
914
919
|
const wanted = animation.toLowerCase();
|
|
@@ -925,8 +930,8 @@ function ModelLoader({
|
|
|
925
930
|
});
|
|
926
931
|
const normFactor = useMemo(() => {
|
|
927
932
|
if (!model) return 1;
|
|
928
|
-
const box = new
|
|
929
|
-
const size = new
|
|
933
|
+
const box = new THREE5.Box3().setFromObject(model);
|
|
934
|
+
const size = new THREE5.Vector3();
|
|
930
935
|
box.getSize(size);
|
|
931
936
|
const maxDim = Math.max(size.x, size.y, size.z);
|
|
932
937
|
if (!Number.isFinite(maxDim) || maxDim < 0.05) return 1;
|
|
@@ -1016,7 +1021,7 @@ var warnUnsupported3d = (kind) => {
|
|
|
1016
1021
|
warnedUnsupported.add(kind);
|
|
1017
1022
|
mesh3dLog.warn("unsupported drawable kind on the 3D backend \u2014 skipped", { kind });
|
|
1018
1023
|
};
|
|
1019
|
-
var CrossOriginTextureLoader = class extends
|
|
1024
|
+
var CrossOriginTextureLoader = class extends THREE5.TextureLoader {
|
|
1020
1025
|
constructor() {
|
|
1021
1026
|
super();
|
|
1022
1027
|
this.crossOrigin = "anonymous";
|
|
@@ -1034,7 +1039,7 @@ function useBillboardTexture(url) {
|
|
|
1034
1039
|
url,
|
|
1035
1040
|
(texture) => {
|
|
1036
1041
|
if (!active) return;
|
|
1037
|
-
texture.colorSpace =
|
|
1042
|
+
texture.colorSpace = THREE5.SRGBColorSpace;
|
|
1038
1043
|
setState({ texture, error: false });
|
|
1039
1044
|
},
|
|
1040
1045
|
void 0,
|
|
@@ -1087,7 +1092,7 @@ function SpriteBillboard({ node, world, cellSize = 1, groupOpacity = 1 }) {
|
|
|
1087
1092
|
}, [texture, frame, node.height, node.width, anchor, cellSize]);
|
|
1088
1093
|
const groundGeometry = React3.useMemo(() => {
|
|
1089
1094
|
if (anchor !== "top-left" || !texture || !atlasReady) return null;
|
|
1090
|
-
const g = new
|
|
1095
|
+
const g = new THREE5.PlaneGeometry(size.width, size.height);
|
|
1091
1096
|
g.rotateX(-Math.PI / 2);
|
|
1092
1097
|
return g;
|
|
1093
1098
|
}, [anchor, texture, atlasReady, size.width, size.height]);
|
|
@@ -1095,15 +1100,15 @@ function SpriteBillboard({ node, world, cellSize = 1, groupOpacity = 1 }) {
|
|
|
1095
1100
|
if (anchor === "top-left") {
|
|
1096
1101
|
return /* @__PURE__ */ jsx("group", { position: [world[0] + size.width / 2, 0.02, world[2] + size.height / 2], children: /* @__PURE__ */ jsxs("mesh", { rotation: [-Math.PI / 2, 0, 0], children: [
|
|
1097
1102
|
/* @__PURE__ */ jsx("planeGeometry", { args: [size.width, size.height] }),
|
|
1098
|
-
/* @__PURE__ */ jsx("meshBasicMaterial", { color: textureError ? 16729156 : 8947848, transparent: true, opacity: 0.6, side:
|
|
1103
|
+
/* @__PURE__ */ jsx("meshBasicMaterial", { color: textureError ? 16729156 : 8947848, transparent: true, opacity: 0.6, side: THREE5.DoubleSide })
|
|
1099
1104
|
] }) });
|
|
1100
1105
|
}
|
|
1101
1106
|
return /* @__PURE__ */ jsx("group", { position: [world[0], world[1] + size.height / 2, world[2]], children: /* @__PURE__ */ jsxs("mesh", { children: [
|
|
1102
1107
|
/* @__PURE__ */ jsx("planeGeometry", { args: [size.width, size.height] }),
|
|
1103
|
-
/* @__PURE__ */ jsx("meshBasicMaterial", { color: textureError ? 16729156 : 8947848, transparent: true, opacity: 0.6, side:
|
|
1108
|
+
/* @__PURE__ */ jsx("meshBasicMaterial", { color: textureError ? 16729156 : 8947848, transparent: true, opacity: 0.6, side: THREE5.DoubleSide })
|
|
1104
1109
|
] }) });
|
|
1105
1110
|
}
|
|
1106
|
-
texture.magFilter = texture.minFilter =
|
|
1111
|
+
texture.magFilter = texture.minFilter = THREE5.NearestFilter;
|
|
1107
1112
|
texture.needsUpdate = true;
|
|
1108
1113
|
if (frame) {
|
|
1109
1114
|
texture.repeat.set(frame.w / size.imgW, frame.h / size.imgH);
|
|
@@ -1116,7 +1121,7 @@ function SpriteBillboard({ node, world, cellSize = 1, groupOpacity = 1 }) {
|
|
|
1116
1121
|
map: texture,
|
|
1117
1122
|
transparent: true,
|
|
1118
1123
|
alphaTest: 0.1,
|
|
1119
|
-
side:
|
|
1124
|
+
side: THREE5.DoubleSide,
|
|
1120
1125
|
opacity: (node.opacity ?? 1) * groupOpacity
|
|
1121
1126
|
}
|
|
1122
1127
|
) }) });
|
|
@@ -1129,7 +1134,7 @@ function SpriteBillboard({ node, world, cellSize = 1, groupOpacity = 1 }) {
|
|
|
1129
1134
|
map: texture,
|
|
1130
1135
|
transparent: true,
|
|
1131
1136
|
alphaTest: 0.1,
|
|
1132
|
-
side:
|
|
1137
|
+
side: THREE5.DoubleSide,
|
|
1133
1138
|
opacity: node.opacity ?? 1
|
|
1134
1139
|
}
|
|
1135
1140
|
)
|
|
@@ -1198,7 +1203,7 @@ function Shape3D({ node, projector, groupOpacity = 1 }) {
|
|
|
1198
1203
|
}
|
|
1199
1204
|
case "poly": {
|
|
1200
1205
|
if (!node.points || node.points.length === 0) return null;
|
|
1201
|
-
const s = new
|
|
1206
|
+
const s = new THREE5.Shape();
|
|
1202
1207
|
node.points.forEach((p, i) => {
|
|
1203
1208
|
if (i === 0) s.moveTo(p.x, p.y);
|
|
1204
1209
|
else s.lineTo(p.x, p.y);
|
|
@@ -1216,7 +1221,7 @@ function Shape3D({ node, projector, groupOpacity = 1 }) {
|
|
|
1216
1221
|
}
|
|
1217
1222
|
return /* @__PURE__ */ jsx("group", { ref: groupRef, position: [world[0], world[1] + 0.02, world[2]], children: /* @__PURE__ */ jsxs("mesh", { rotation: [-Math.PI / 2, 0, 0], children: [
|
|
1218
1223
|
geometry,
|
|
1219
|
-
/* @__PURE__ */ jsx("meshBasicMaterial", { ref: materialRef, color, transparent: true, opacity: (node.opacity ?? 1) * groupOpacity, side:
|
|
1224
|
+
/* @__PURE__ */ jsx("meshBasicMaterial", { ref: materialRef, color, transparent: true, opacity: (node.opacity ?? 1) * groupOpacity, side: THREE5.DoubleSide })
|
|
1220
1225
|
] }) });
|
|
1221
1226
|
}
|
|
1222
1227
|
function Text3D({ node, projector, groupOpacity = 1 }) {
|
|
@@ -1238,6 +1243,18 @@ function Text3D({ node, projector, groupOpacity = 1 }) {
|
|
|
1238
1243
|
) });
|
|
1239
1244
|
}
|
|
1240
1245
|
var GROUND_ROTATION = [-Math.PI / 2, 0, 0];
|
|
1246
|
+
var textureCache = /* @__PURE__ */ new Map();
|
|
1247
|
+
function getMeshTexture(url) {
|
|
1248
|
+
const cached = textureCache.get(url);
|
|
1249
|
+
if (cached) return cached;
|
|
1250
|
+
const texture = new THREE5.TextureLoader().load(url);
|
|
1251
|
+
texture.flipY = false;
|
|
1252
|
+
texture.colorSpace = THREE5.SRGBColorSpace;
|
|
1253
|
+
texture.wrapS = THREE5.RepeatWrapping;
|
|
1254
|
+
texture.wrapT = THREE5.RepeatWrapping;
|
|
1255
|
+
textureCache.set(url, texture);
|
|
1256
|
+
return texture;
|
|
1257
|
+
}
|
|
1241
1258
|
function polyhedronGeometry(node, cellSize) {
|
|
1242
1259
|
const verts = node.vertices;
|
|
1243
1260
|
const faces = node.faces;
|
|
@@ -1258,8 +1275,16 @@ function polyhedronGeometry(node, cellSize) {
|
|
|
1258
1275
|
index.push(a, c, b);
|
|
1259
1276
|
}
|
|
1260
1277
|
if (index.length === 0) return null;
|
|
1261
|
-
const geometry = new
|
|
1262
|
-
geometry.setAttribute("position", new
|
|
1278
|
+
const geometry = new THREE5.BufferGeometry();
|
|
1279
|
+
geometry.setAttribute("position", new THREE5.BufferAttribute(positions, 3));
|
|
1280
|
+
if (node.uvs && node.uvs.length === verts.length) {
|
|
1281
|
+
const uv = new Float32Array(verts.length * 2);
|
|
1282
|
+
for (let i = 0; i < verts.length; i++) {
|
|
1283
|
+
uv[i * 2] = node.uvs[i][0];
|
|
1284
|
+
uv[i * 2 + 1] = node.uvs[i][1];
|
|
1285
|
+
}
|
|
1286
|
+
geometry.setAttribute("uv", new THREE5.BufferAttribute(uv, 2));
|
|
1287
|
+
}
|
|
1263
1288
|
geometry.setIndex(index);
|
|
1264
1289
|
geometry.computeVertexNormals();
|
|
1265
1290
|
const skin = node.skin;
|
|
@@ -1272,8 +1297,8 @@ function polyhedronGeometry(node, cellSize) {
|
|
|
1272
1297
|
skinWeight[i * 4 + k] = skin.weights[i][k] ?? 0;
|
|
1273
1298
|
}
|
|
1274
1299
|
}
|
|
1275
|
-
geometry.setAttribute("skinIndex", new
|
|
1276
|
-
geometry.setAttribute("skinWeight", new
|
|
1300
|
+
geometry.setAttribute("skinIndex", new THREE5.BufferAttribute(skinIndex, 4));
|
|
1301
|
+
geometry.setAttribute("skinWeight", new THREE5.BufferAttribute(skinWeight, 4));
|
|
1277
1302
|
}
|
|
1278
1303
|
const size = Math.max(bounds.max[0] - bounds.min[0], bounds.max[1] - bounds.min[1], bounds.max[2] - bounds.min[2]) * cellSize;
|
|
1279
1304
|
return { geometry, lift: -bounds.min[2] * cellSize, size };
|
|
@@ -1315,9 +1340,9 @@ function meshGeometry(node, cellSize) {
|
|
|
1315
1340
|
}
|
|
1316
1341
|
var warnedPolyhedronOutline = false;
|
|
1317
1342
|
var SIDE_MAP = {
|
|
1318
|
-
front:
|
|
1319
|
-
back:
|
|
1320
|
-
double:
|
|
1343
|
+
front: THREE5.FrontSide,
|
|
1344
|
+
back: THREE5.BackSide,
|
|
1345
|
+
double: THREE5.DoubleSide
|
|
1321
1346
|
};
|
|
1322
1347
|
function meshMaterial(mat, opacity, ref) {
|
|
1323
1348
|
const m = mat ?? {};
|
|
@@ -1326,7 +1351,8 @@ function meshMaterial(mat, opacity, ref) {
|
|
|
1326
1351
|
color: m.color ?? "#ffffff",
|
|
1327
1352
|
transparent: opacity < 1,
|
|
1328
1353
|
opacity,
|
|
1329
|
-
side: SIDE_MAP[m.side ?? "front"]
|
|
1354
|
+
side: SIDE_MAP[m.side ?? "front"],
|
|
1355
|
+
...m.map ? { map: getMeshTexture(m.map) } : {}
|
|
1330
1356
|
};
|
|
1331
1357
|
const emissive = m.emissive ? { emissive: m.emissive, emissiveIntensity: m.emissiveIntensity ?? 1 } : {};
|
|
1332
1358
|
switch (m.kind ?? "standard") {
|
|
@@ -1384,13 +1410,13 @@ function SkinnedPolyhedron3D({
|
|
|
1384
1410
|
if (mesh.skeleton && mesh.skeleton.bones.length === bones.length && mesh.skeleton.bones.every((b, i) => b === bones[i])) return;
|
|
1385
1411
|
if (skin.inverseBindMatrices.length !== bones.length) return;
|
|
1386
1412
|
const inverses = skin.inverseBindMatrices.map((m) => {
|
|
1387
|
-
const mat = new
|
|
1413
|
+
const mat = new THREE5.Matrix4().fromArray(m);
|
|
1388
1414
|
mat.elements[12] *= cellSize;
|
|
1389
1415
|
mat.elements[13] *= cellSize;
|
|
1390
1416
|
mat.elements[14] *= cellSize;
|
|
1391
1417
|
return mat;
|
|
1392
1418
|
});
|
|
1393
|
-
mesh.bind(new
|
|
1419
|
+
mesh.bind(new THREE5.Skeleton(bones, inverses), new THREE5.Matrix4());
|
|
1394
1420
|
}, [registryTick, skin, boneStore, geometry, cellSize]);
|
|
1395
1421
|
useEffect(() => {
|
|
1396
1422
|
const mesh = meshRef.current;
|
|
@@ -1497,7 +1523,7 @@ function Mesh3D({
|
|
|
1497
1523
|
"meshBasicMaterial",
|
|
1498
1524
|
{
|
|
1499
1525
|
color: node.outline.color ?? "#101014",
|
|
1500
|
-
side:
|
|
1526
|
+
side: THREE5.BackSide,
|
|
1501
1527
|
transparent: opacity < 1,
|
|
1502
1528
|
opacity
|
|
1503
1529
|
}
|
|
@@ -1543,7 +1569,7 @@ function Group3D({
|
|
|
1543
1569
|
const parentStore = useContext(BoneRegistryContext);
|
|
1544
1570
|
const scopedStore = useMemo(() => node.skeleton ? new BoneStore() : null, [node.skeleton]);
|
|
1545
1571
|
const boneStore = scopedStore ?? parentStore;
|
|
1546
|
-
const boneObject = useMemo(() => node.bone ? new
|
|
1572
|
+
const boneObject = useMemo(() => node.bone ? new THREE5.Bone() : null, [node.bone]);
|
|
1547
1573
|
useEffect(() => {
|
|
1548
1574
|
if (!node.bone || !boneStore || !boneObject) return;
|
|
1549
1575
|
return boneStore.register(node.bone, boneObject);
|
|
@@ -1583,10 +1609,26 @@ function cn(...inputs) {
|
|
|
1583
1609
|
}
|
|
1584
1610
|
var DEFAULT_GRID_CONFIG = {
|
|
1585
1611
|
cellSize: 1};
|
|
1612
|
+
function CameraPose({
|
|
1613
|
+
position,
|
|
1614
|
+
fov,
|
|
1615
|
+
controls
|
|
1616
|
+
}) {
|
|
1617
|
+
const camera = useThree((s) => s.camera);
|
|
1618
|
+
useEffect(() => {
|
|
1619
|
+
camera.position.set(position[0], position[1], position[2]);
|
|
1620
|
+
if (camera.isPerspectiveCamera) {
|
|
1621
|
+
camera.fov = fov;
|
|
1622
|
+
camera.updateProjectionMatrix();
|
|
1623
|
+
}
|
|
1624
|
+
controls.current?.update();
|
|
1625
|
+
}, [camera, position, fov, controls]);
|
|
1626
|
+
return null;
|
|
1627
|
+
}
|
|
1586
1628
|
function RoomEnvironment3D() {
|
|
1587
1629
|
const { gl, scene } = useThree(({ gl: gl2, scene: scene2 }) => ({ gl: gl2, scene: scene2 }));
|
|
1588
1630
|
useEffect(() => {
|
|
1589
|
-
const pmremGenerator = new
|
|
1631
|
+
const pmremGenerator = new THREE5.PMREMGenerator(gl);
|
|
1590
1632
|
const envTexture = pmremGenerator.fromScene(new RoomEnvironment(), 0.04).texture;
|
|
1591
1633
|
scene.environment = envTexture;
|
|
1592
1634
|
return () => {
|
|
@@ -1622,6 +1664,7 @@ var Canvas3DHost = forwardRef(
|
|
|
1622
1664
|
keyUpMap,
|
|
1623
1665
|
pixelsPerUnit,
|
|
1624
1666
|
fov,
|
|
1667
|
+
azimuth,
|
|
1625
1668
|
lighting,
|
|
1626
1669
|
post,
|
|
1627
1670
|
children,
|
|
@@ -1715,7 +1758,7 @@ var Canvas3DHost = forwardRef(
|
|
|
1715
1758
|
getCameraPosition: () => {
|
|
1716
1759
|
if (controlsRef.current) {
|
|
1717
1760
|
const pos = controlsRef.current.object.position;
|
|
1718
|
-
return new
|
|
1761
|
+
return new THREE5.Vector3(pos.x, pos.y, pos.z);
|
|
1719
1762
|
}
|
|
1720
1763
|
return null;
|
|
1721
1764
|
},
|
|
@@ -1755,20 +1798,28 @@ var Canvas3DHost = forwardRef(
|
|
|
1755
1798
|
const cz = cameraTarget[2];
|
|
1756
1799
|
const d = size * 1;
|
|
1757
1800
|
const fovDeg = fov ?? 45;
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1801
|
+
const base = (() => {
|
|
1802
|
+
switch (cameraMode) {
|
|
1803
|
+
case "isometric":
|
|
1804
|
+
return { position: [cx + d, d * 0.8, cz + d], fov: fovDeg };
|
|
1805
|
+
case "top-down":
|
|
1806
|
+
return { position: [cx, d * 2, cz + d * 0.35], fov: fovDeg };
|
|
1807
|
+
case "front":
|
|
1808
|
+
return { position: [cx, d * 0.32, cz + d * 1.15], fov: fovDeg };
|
|
1809
|
+
case "follow":
|
|
1810
|
+
return { position: [cx, d * 0.5, cz + d], fov: fovDeg };
|
|
1811
|
+
case "perspective":
|
|
1812
|
+
default:
|
|
1813
|
+
return { position: [cx + d, d, cz + d], fov: fovDeg };
|
|
1814
|
+
}
|
|
1815
|
+
})();
|
|
1816
|
+
if (!azimuth) return base;
|
|
1817
|
+
const ox = base.position[0] - cx;
|
|
1818
|
+
const oz = base.position[2] - cz;
|
|
1819
|
+
const c = Math.cos(azimuth);
|
|
1820
|
+
const s = Math.sin(azimuth);
|
|
1821
|
+
return { position: [cx + ox * c - oz * s, base.position[1], cz + ox * s + oz * c], fov: base.fov };
|
|
1822
|
+
}, [cameraMode, gridBounds, cellSize, cameraTarget, fov, azimuth]);
|
|
1772
1823
|
const followWorld = useMemo(() => {
|
|
1773
1824
|
if (followTarget) return drawableProjector.toWorld(followTarget);
|
|
1774
1825
|
return cameraTarget;
|
|
@@ -1829,6 +1880,7 @@ var Canvas3DHost = forwardRef(
|
|
|
1829
1880
|
{
|
|
1830
1881
|
shadows,
|
|
1831
1882
|
flat: lighting?.toneMapping === "none",
|
|
1883
|
+
gl: { preserveDrawingBuffer: true },
|
|
1832
1884
|
camera: {
|
|
1833
1885
|
position: cameraConfig.position,
|
|
1834
1886
|
fov: cameraConfig.fov,
|
|
@@ -1843,6 +1895,7 @@ var Canvas3DHost = forwardRef(
|
|
|
1843
1895
|
},
|
|
1844
1896
|
children: [
|
|
1845
1897
|
/* @__PURE__ */ jsx(CameraController3D, { onCameraChange: eventHandlers.handleCameraChange }),
|
|
1898
|
+
/* @__PURE__ */ jsx(CameraPose, { position: cameraConfig.position, fov: cameraConfig.fov, controls: controlsRef }),
|
|
1846
1899
|
(cameraMode === "follow" || cameraMode === "chase") && /* @__PURE__ */ jsx(FollowCamera3D, { target: followWorld, offset: followOffset }),
|
|
1847
1900
|
/* @__PURE__ */ jsx(
|
|
1848
1901
|
Lighting3D,
|
|
@@ -1923,7 +1976,7 @@ var Canvas3DHost = forwardRef(
|
|
|
1923
1976
|
dampingFactor: 0.05,
|
|
1924
1977
|
enableZoom: true,
|
|
1925
1978
|
enablePan: true,
|
|
1926
|
-
touches: { ONE:
|
|
1979
|
+
touches: { ONE: THREE5.TOUCH.ROTATE, TWO: THREE5.TOUCH.DOLLY_PAN },
|
|
1927
1980
|
minDistance: 2,
|
|
1928
1981
|
maxDistance: 100,
|
|
1929
1982
|
maxPolarAngle: Math.PI / 2 - 0.1
|
|
@@ -1946,15 +1999,15 @@ function Scene3D({ background = "#1a1a2e", fog, children }) {
|
|
|
1946
1999
|
if (initializedRef.current) return;
|
|
1947
2000
|
initializedRef.current = true;
|
|
1948
2001
|
if (background.startsWith("#") || background.startsWith("rgb")) {
|
|
1949
|
-
scene.background = new
|
|
2002
|
+
scene.background = new THREE5.Color(background);
|
|
1950
2003
|
} else {
|
|
1951
|
-
const loader = new
|
|
2004
|
+
const loader = new THREE5.TextureLoader();
|
|
1952
2005
|
loader.load(background, (texture) => {
|
|
1953
2006
|
scene.background = texture;
|
|
1954
2007
|
});
|
|
1955
2008
|
}
|
|
1956
2009
|
if (fog) {
|
|
1957
|
-
scene.fog = new
|
|
2010
|
+
scene.fog = new THREE5.Fog(fog.color, fog.near, fog.far);
|
|
1958
2011
|
}
|
|
1959
2012
|
return () => {
|
|
1960
2013
|
scene.background = null;
|
|
@@ -1977,14 +2030,14 @@ var Camera3D = forwardRef(
|
|
|
1977
2030
|
}, ref) => {
|
|
1978
2031
|
const { camera, set, viewport } = useThree();
|
|
1979
2032
|
const controlsRef = useRef(null);
|
|
1980
|
-
const initialPosition = useRef(new
|
|
1981
|
-
const initialTarget = useRef(new
|
|
2033
|
+
const initialPosition = useRef(new THREE5.Vector3(...position));
|
|
2034
|
+
const initialTarget = useRef(new THREE5.Vector3(...target));
|
|
1982
2035
|
useEffect(() => {
|
|
1983
2036
|
let newCamera;
|
|
1984
2037
|
if (mode === "isometric") {
|
|
1985
2038
|
const aspect = viewport.aspect;
|
|
1986
2039
|
const size = 10 / zoom;
|
|
1987
|
-
newCamera = new
|
|
2040
|
+
newCamera = new THREE5.OrthographicCamera(
|
|
1988
2041
|
-size * aspect,
|
|
1989
2042
|
size * aspect,
|
|
1990
2043
|
size,
|
|
@@ -1993,7 +2046,7 @@ var Camera3D = forwardRef(
|
|
|
1993
2046
|
1e3
|
|
1994
2047
|
);
|
|
1995
2048
|
} else {
|
|
1996
|
-
newCamera = new
|
|
2049
|
+
newCamera = new THREE5.PerspectiveCamera(fov, viewport.aspect, 0.1, 1e3);
|
|
1997
2050
|
}
|
|
1998
2051
|
newCamera.position.copy(initialPosition.current);
|
|
1999
2052
|
newCamera.lookAt(initialTarget.current.x, initialTarget.current.y, initialTarget.current.z);
|
|
@@ -2034,8 +2087,8 @@ var Camera3D = forwardRef(
|
|
|
2034
2087
|
}
|
|
2035
2088
|
},
|
|
2036
2089
|
getViewBounds: () => {
|
|
2037
|
-
const min = new
|
|
2038
|
-
const max = new
|
|
2090
|
+
const min = new THREE5.Vector3(-10, -10, -10);
|
|
2091
|
+
const max = new THREE5.Vector3(10, 10, 10);
|
|
2039
2092
|
return { min, max };
|
|
2040
2093
|
}
|
|
2041
2094
|
}));
|
|
@@ -2077,7 +2130,7 @@ var AssetLoader = class {
|
|
|
2077
2130
|
__publicField(this, "textureCache");
|
|
2078
2131
|
__publicField(this, "loadingPromises");
|
|
2079
2132
|
this.objLoader = new OBJLoader();
|
|
2080
|
-
this.textureLoader = new
|
|
2133
|
+
this.textureLoader = new THREE5.TextureLoader();
|
|
2081
2134
|
this.modelCache = /* @__PURE__ */ new Map();
|
|
2082
2135
|
this.textureCache = /* @__PURE__ */ new Map();
|
|
2083
2136
|
this.loadingPromises = /* @__PURE__ */ new Map();
|
|
@@ -2151,7 +2204,7 @@ var AssetLoader = class {
|
|
|
2151
2204
|
return this.loadingPromises.get(`texture:${url}`);
|
|
2152
2205
|
}
|
|
2153
2206
|
const loadPromise = this.textureLoader.loadAsync(url).then((texture) => {
|
|
2154
|
-
texture.colorSpace =
|
|
2207
|
+
texture.colorSpace = THREE5.SRGBColorSpace;
|
|
2155
2208
|
this.textureCache.set(url, texture);
|
|
2156
2209
|
this.loadingPromises.delete(`texture:${url}`);
|
|
2157
2210
|
return texture;
|
|
@@ -2225,7 +2278,7 @@ var AssetLoader = class {
|
|
|
2225
2278
|
});
|
|
2226
2279
|
this.modelCache.forEach((model) => {
|
|
2227
2280
|
model.scene.traverse((child) => {
|
|
2228
|
-
if (child instanceof
|
|
2281
|
+
if (child instanceof THREE5.Mesh) {
|
|
2229
2282
|
child.geometry.dispose();
|
|
2230
2283
|
if (Array.isArray(child.material)) {
|
|
2231
2284
|
child.material.forEach((m) => m.dispose());
|
|
@@ -2275,21 +2328,21 @@ function useThree5(options = {}) {
|
|
|
2275
2328
|
const [isReady, setIsReady] = useState(false);
|
|
2276
2329
|
const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
|
|
2277
2330
|
const initialCameraPosition = useMemo(
|
|
2278
|
-
() => new
|
|
2331
|
+
() => new THREE5.Vector3(...opts.cameraPosition),
|
|
2279
2332
|
[]
|
|
2280
2333
|
);
|
|
2281
2334
|
useEffect(() => {
|
|
2282
2335
|
if (!containerRef.current) return;
|
|
2283
2336
|
const container = containerRef.current;
|
|
2284
2337
|
const { clientWidth, clientHeight } = container;
|
|
2285
|
-
const scene = new
|
|
2286
|
-
scene.background = new
|
|
2338
|
+
const scene = new THREE5.Scene();
|
|
2339
|
+
scene.background = new THREE5.Color(opts.backgroundColor);
|
|
2287
2340
|
sceneRef.current = scene;
|
|
2288
2341
|
let camera;
|
|
2289
2342
|
const aspect = clientWidth / clientHeight;
|
|
2290
2343
|
if (opts.cameraMode === "isometric") {
|
|
2291
2344
|
const size = 10;
|
|
2292
|
-
camera = new
|
|
2345
|
+
camera = new THREE5.OrthographicCamera(
|
|
2293
2346
|
-size * aspect,
|
|
2294
2347
|
size * aspect,
|
|
2295
2348
|
size,
|
|
@@ -2298,11 +2351,11 @@ function useThree5(options = {}) {
|
|
|
2298
2351
|
1e3
|
|
2299
2352
|
);
|
|
2300
2353
|
} else {
|
|
2301
|
-
camera = new
|
|
2354
|
+
camera = new THREE5.PerspectiveCamera(45, aspect, 0.1, 1e3);
|
|
2302
2355
|
}
|
|
2303
2356
|
camera.position.copy(initialCameraPosition);
|
|
2304
2357
|
cameraRef.current = camera;
|
|
2305
|
-
const renderer = new
|
|
2358
|
+
const renderer = new THREE5.WebGLRenderer({
|
|
2306
2359
|
antialias: true,
|
|
2307
2360
|
alpha: true,
|
|
2308
2361
|
canvas: canvasRef.current || void 0
|
|
@@ -2310,7 +2363,7 @@ function useThree5(options = {}) {
|
|
|
2310
2363
|
renderer.setSize(clientWidth, clientHeight);
|
|
2311
2364
|
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
|
|
2312
2365
|
renderer.shadowMap.enabled = opts.shadows;
|
|
2313
|
-
renderer.shadowMap.type =
|
|
2366
|
+
renderer.shadowMap.type = THREE5.PCFSoftShadowMap;
|
|
2314
2367
|
rendererRef.current = renderer;
|
|
2315
2368
|
const controls = new OrbitControls$1(camera, renderer.domElement);
|
|
2316
2369
|
controls.enableDamping = true;
|
|
@@ -2319,16 +2372,16 @@ function useThree5(options = {}) {
|
|
|
2319
2372
|
controls.maxDistance = 100;
|
|
2320
2373
|
controls.maxPolarAngle = Math.PI / 2 - 0.1;
|
|
2321
2374
|
controlsRef.current = controls;
|
|
2322
|
-
const ambientLight = new
|
|
2375
|
+
const ambientLight = new THREE5.AmbientLight(16777215, 0.6);
|
|
2323
2376
|
scene.add(ambientLight);
|
|
2324
|
-
const directionalLight = new
|
|
2377
|
+
const directionalLight = new THREE5.DirectionalLight(16777215, 0.8);
|
|
2325
2378
|
directionalLight.position.set(10, 20, 10);
|
|
2326
2379
|
directionalLight.castShadow = opts.shadows;
|
|
2327
2380
|
directionalLight.shadow.mapSize.width = 2048;
|
|
2328
2381
|
directionalLight.shadow.mapSize.height = 2048;
|
|
2329
2382
|
scene.add(directionalLight);
|
|
2330
2383
|
if (opts.showGrid) {
|
|
2331
|
-
const gridHelper = new
|
|
2384
|
+
const gridHelper = new THREE5.GridHelper(
|
|
2332
2385
|
opts.gridSize,
|
|
2333
2386
|
opts.gridSize,
|
|
2334
2387
|
4473924,
|
|
@@ -2346,10 +2399,10 @@ function useThree5(options = {}) {
|
|
|
2346
2399
|
const handleResize = () => {
|
|
2347
2400
|
const { clientWidth: width, clientHeight: height } = container;
|
|
2348
2401
|
setDimensions({ width, height });
|
|
2349
|
-
if (camera instanceof
|
|
2402
|
+
if (camera instanceof THREE5.PerspectiveCamera) {
|
|
2350
2403
|
camera.aspect = width / height;
|
|
2351
2404
|
camera.updateProjectionMatrix();
|
|
2352
|
-
} else if (camera instanceof
|
|
2405
|
+
} else if (camera instanceof THREE5.OrthographicCamera) {
|
|
2353
2406
|
const aspect2 = width / height;
|
|
2354
2407
|
const size = 10;
|
|
2355
2408
|
camera.left = -size * aspect2;
|
|
@@ -2380,7 +2433,7 @@ function useThree5(options = {}) {
|
|
|
2380
2433
|
let newCamera;
|
|
2381
2434
|
if (opts.cameraMode === "isometric") {
|
|
2382
2435
|
const size = 10;
|
|
2383
|
-
newCamera = new
|
|
2436
|
+
newCamera = new THREE5.OrthographicCamera(
|
|
2384
2437
|
-size * aspect,
|
|
2385
2438
|
size * aspect,
|
|
2386
2439
|
size,
|
|
@@ -2389,7 +2442,7 @@ function useThree5(options = {}) {
|
|
|
2389
2442
|
1e3
|
|
2390
2443
|
);
|
|
2391
2444
|
} else {
|
|
2392
|
-
newCamera = new
|
|
2445
|
+
newCamera = new THREE5.PerspectiveCamera(45, aspect, 0.1, 1e3);
|
|
2393
2446
|
}
|
|
2394
2447
|
newCamera.position.copy(currentPos);
|
|
2395
2448
|
cameraRef.current = newCamera;
|
|
@@ -2719,8 +2772,8 @@ function useSceneGraph() {
|
|
|
2719
2772
|
}
|
|
2720
2773
|
function useRaycaster(options) {
|
|
2721
2774
|
const { camera, canvas, cellSize = 1, offsetX = 0, offsetZ = 0 } = options;
|
|
2722
|
-
const raycaster = useRef(new
|
|
2723
|
-
const mouse = useRef(new
|
|
2775
|
+
const raycaster = useRef(new THREE5.Raycaster());
|
|
2776
|
+
const mouse = useRef(new THREE5.Vector2());
|
|
2724
2777
|
const clientToNDC = useCallback(
|
|
2725
2778
|
(clientX, clientY) => {
|
|
2726
2779
|
if (!canvas) {
|
|
@@ -2790,8 +2843,8 @@ function useRaycaster(options) {
|
|
|
2790
2843
|
const ndc = clientToNDC(clientX, clientY);
|
|
2791
2844
|
mouse.current.set(ndc.x, ndc.y);
|
|
2792
2845
|
raycaster.current.setFromCamera(mouse.current, camera);
|
|
2793
|
-
const plane = new
|
|
2794
|
-
const target = new
|
|
2846
|
+
const plane = new THREE5.Plane(new THREE5.Vector3(0, 1, 0), 0);
|
|
2847
|
+
const target = new THREE5.Vector3();
|
|
2795
2848
|
const intersection = raycaster.current.ray.intersectPlane(plane, target);
|
|
2796
2849
|
if (intersection) {
|
|
2797
2850
|
const gridX = Math.round((target.x - offsetX) / cellSize);
|
|
@@ -2829,7 +2882,7 @@ function useRaycaster(options) {
|
|
|
2829
2882
|
return {
|
|
2830
2883
|
gridX: gridCoords.x,
|
|
2831
2884
|
gridZ: gridCoords.z,
|
|
2832
|
-
worldPosition: new
|
|
2885
|
+
worldPosition: new THREE5.Vector3(
|
|
2833
2886
|
gridCoords.x * cellSize + offsetX,
|
|
2834
2887
|
0,
|
|
2835
2888
|
gridCoords.z * cellSize + offsetZ
|
|
@@ -2859,7 +2912,7 @@ var DEFAULT_CONFIG = {
|
|
|
2859
2912
|
};
|
|
2860
2913
|
function gridToWorld(gridX, gridZ, config = DEFAULT_CONFIG) {
|
|
2861
2914
|
const opts = { ...DEFAULT_CONFIG, ...config };
|
|
2862
|
-
return new
|
|
2915
|
+
return new THREE5.Vector3(
|
|
2863
2916
|
gridX * opts.cellSize + opts.offsetX,
|
|
2864
2917
|
opts.elevation,
|
|
2865
2918
|
gridZ * opts.cellSize + opts.offsetZ
|
|
@@ -2873,17 +2926,17 @@ function worldToGrid(worldX, worldZ, config = DEFAULT_CONFIG) {
|
|
|
2873
2926
|
};
|
|
2874
2927
|
}
|
|
2875
2928
|
function raycastToPlane(camera, mouseX, mouseY, planeY = 0) {
|
|
2876
|
-
const raycaster = new
|
|
2877
|
-
const mouse = new
|
|
2929
|
+
const raycaster = new THREE5.Raycaster();
|
|
2930
|
+
const mouse = new THREE5.Vector2(mouseX, mouseY);
|
|
2878
2931
|
raycaster.setFromCamera(mouse, camera);
|
|
2879
|
-
const plane = new
|
|
2880
|
-
const target = new
|
|
2932
|
+
const plane = new THREE5.Plane(new THREE5.Vector3(0, 1, 0), -planeY);
|
|
2933
|
+
const target = new THREE5.Vector3();
|
|
2881
2934
|
const intersection = raycaster.ray.intersectPlane(plane, target);
|
|
2882
2935
|
return intersection ? target : null;
|
|
2883
2936
|
}
|
|
2884
2937
|
function raycastToObjects(camera, mouseX, mouseY, objects) {
|
|
2885
|
-
const raycaster = new
|
|
2886
|
-
const mouse = new
|
|
2938
|
+
const raycaster = new THREE5.Raycaster();
|
|
2939
|
+
const mouse = new THREE5.Vector2(mouseX, mouseY);
|
|
2887
2940
|
raycaster.setFromCamera(mouse, camera);
|
|
2888
2941
|
const intersects = raycaster.intersectObjects(objects, true);
|
|
2889
2942
|
return intersects.length > 0 ? intersects[0] : null;
|
|
@@ -2935,14 +2988,14 @@ function getCellsInRadius(centerX, centerZ, radius) {
|
|
|
2935
2988
|
return cells;
|
|
2936
2989
|
}
|
|
2937
2990
|
function createGridHighlight(color = 16776960, opacity = 0.3) {
|
|
2938
|
-
const geometry = new
|
|
2939
|
-
const material = new
|
|
2991
|
+
const geometry = new THREE5.PlaneGeometry(0.95, 0.95);
|
|
2992
|
+
const material = new THREE5.MeshBasicMaterial({
|
|
2940
2993
|
color,
|
|
2941
2994
|
transparent: true,
|
|
2942
2995
|
opacity,
|
|
2943
|
-
side:
|
|
2996
|
+
side: THREE5.DoubleSide
|
|
2944
2997
|
});
|
|
2945
|
-
const mesh = new
|
|
2998
|
+
const mesh = new THREE5.Mesh(geometry, material);
|
|
2946
2999
|
mesh.rotation.x = -Math.PI / 2;
|
|
2947
3000
|
mesh.position.y = 0.01;
|
|
2948
3001
|
return mesh;
|
|
@@ -2955,31 +3008,31 @@ function normalizeMouseCoordinates(clientX, clientY, element) {
|
|
|
2955
3008
|
};
|
|
2956
3009
|
}
|
|
2957
3010
|
function isInFrustum(position, camera, padding = 0) {
|
|
2958
|
-
const frustum = new
|
|
2959
|
-
const projScreenMatrix = new
|
|
3011
|
+
const frustum = new THREE5.Frustum();
|
|
3012
|
+
const projScreenMatrix = new THREE5.Matrix4();
|
|
2960
3013
|
projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
|
|
2961
3014
|
frustum.setFromProjectionMatrix(projScreenMatrix);
|
|
2962
|
-
const sphere = new
|
|
3015
|
+
const sphere = new THREE5.Sphere(position, padding);
|
|
2963
3016
|
return frustum.intersectsSphere(sphere);
|
|
2964
3017
|
}
|
|
2965
3018
|
function filterByFrustum(positions, camera, padding = 0) {
|
|
2966
|
-
const frustum = new
|
|
2967
|
-
const projScreenMatrix = new
|
|
3019
|
+
const frustum = new THREE5.Frustum();
|
|
3020
|
+
const projScreenMatrix = new THREE5.Matrix4();
|
|
2968
3021
|
projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
|
|
2969
3022
|
frustum.setFromProjectionMatrix(projScreenMatrix);
|
|
2970
3023
|
return positions.filter((position) => {
|
|
2971
|
-
const sphere = new
|
|
3024
|
+
const sphere = new THREE5.Sphere(position, padding);
|
|
2972
3025
|
return frustum.intersectsSphere(sphere);
|
|
2973
3026
|
});
|
|
2974
3027
|
}
|
|
2975
3028
|
function getVisibleIndices(positions, camera, padding = 0) {
|
|
2976
|
-
const frustum = new
|
|
2977
|
-
const projScreenMatrix = new
|
|
3029
|
+
const frustum = new THREE5.Frustum();
|
|
3030
|
+
const projScreenMatrix = new THREE5.Matrix4();
|
|
2978
3031
|
const visible = /* @__PURE__ */ new Set();
|
|
2979
3032
|
projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
|
|
2980
3033
|
frustum.setFromProjectionMatrix(projScreenMatrix);
|
|
2981
3034
|
positions.forEach((position, index) => {
|
|
2982
|
-
const sphere = new
|
|
3035
|
+
const sphere = new THREE5.Sphere(position, padding);
|
|
2983
3036
|
if (frustum.intersectsSphere(sphere)) {
|
|
2984
3037
|
visible.add(index);
|
|
2985
3038
|
}
|
|
@@ -3003,7 +3056,7 @@ function updateInstanceLOD(instancedMesh, positions, camera, lodDistances) {
|
|
|
3003
3056
|
return lodIndices;
|
|
3004
3057
|
}
|
|
3005
3058
|
function cullInstancedMesh(instancedMesh, positions, visibleIndices) {
|
|
3006
|
-
const dummy = new
|
|
3059
|
+
const dummy = new THREE5.Object3D();
|
|
3007
3060
|
let visibleCount = 0;
|
|
3008
3061
|
positions.forEach((position, index) => {
|
|
3009
3062
|
if (visibleIndices.has(index)) {
|
|
@@ -5786,12 +5839,12 @@ function useAvl3DConfig() {
|
|
|
5786
5839
|
}
|
|
5787
5840
|
function CameraController({ targetPosition, targetLookAt, animated }) {
|
|
5788
5841
|
const { camera } = useThree();
|
|
5789
|
-
const targetPosVec = useRef(new
|
|
5790
|
-
const targetLookVec = useRef(new
|
|
5842
|
+
const targetPosVec = useRef(new THREE5.Vector3(...targetPosition));
|
|
5843
|
+
const targetLookVec = useRef(new THREE5.Vector3(...targetLookAt));
|
|
5791
5844
|
const isAnimating = useRef(false);
|
|
5792
5845
|
useEffect(() => {
|
|
5793
|
-
const newTarget = new
|
|
5794
|
-
const newLookAt = new
|
|
5846
|
+
const newTarget = new THREE5.Vector3(...targetPosition);
|
|
5847
|
+
const newLookAt = new THREE5.Vector3(...targetLookAt);
|
|
5795
5848
|
if (!newTarget.equals(targetPosVec.current) || !newLookAt.equals(targetLookVec.current)) {
|
|
5796
5849
|
targetPosVec.current.copy(newTarget);
|
|
5797
5850
|
targetLookVec.current.copy(newLookAt);
|
|
@@ -5806,9 +5859,9 @@ function CameraController({ targetPosition, targetLookAt, animated }) {
|
|
|
5806
5859
|
useFrame((_, delta) => {
|
|
5807
5860
|
if (!isAnimating.current) return;
|
|
5808
5861
|
const speed = 3;
|
|
5809
|
-
camera.position.x =
|
|
5810
|
-
camera.position.y =
|
|
5811
|
-
camera.position.z =
|
|
5862
|
+
camera.position.x = THREE5.MathUtils.damp(camera.position.x, targetPosVec.current.x, speed, delta);
|
|
5863
|
+
camera.position.y = THREE5.MathUtils.damp(camera.position.y, targetPosVec.current.y, speed, delta);
|
|
5864
|
+
camera.position.z = THREE5.MathUtils.damp(camera.position.z, targetPosVec.current.z, speed, delta);
|
|
5812
5865
|
camera.lookAt(targetLookVec.current);
|
|
5813
5866
|
const dist = camera.position.distanceTo(targetPosVec.current);
|
|
5814
5867
|
if (dist < 0.05) {
|
|
@@ -5823,7 +5876,7 @@ function SceneFade({ animating, children }) {
|
|
|
5823
5876
|
useFrame((_, delta) => {
|
|
5824
5877
|
if (!groupRef.current) return;
|
|
5825
5878
|
const target = animating ? 0 : 1;
|
|
5826
|
-
opacityRef.current =
|
|
5879
|
+
opacityRef.current = THREE5.MathUtils.damp(opacityRef.current, target, 5, delta);
|
|
5827
5880
|
groupRef.current.visible = opacityRef.current > 0.05;
|
|
5828
5881
|
const s = 0.9 + opacityRef.current * 0.1;
|
|
5829
5882
|
groupRef.current.scale.setScalar(s);
|