-
Notifications
You must be signed in to change notification settings - Fork 35
Description
I am experiencing a bug when rendering multiple 3D models using react-three-map and react-three-fiber. Despite having different URLs for the models, the same model is rendered across all canvases. This issue occurs when trying to load multiple models that are close to each other on the map.
Use the provided MapPolygons component.
Ensure there are at least three models with distinct URLs that are close to each other geographically.
Observe that the same model is rendered in all canvases, even though their URLs are different.
Expected Behavior:
Each canvas should render the 3D model specified by its unique URL.
Actual Behavior:
All canvases render the same model, ignoring the distinct URLs.
Relevant Code:
import { Layer, Source, useMap, Marker } from "react-map-gl";
import { useLoader } from "@react-three/fiber";
import { Canvas } from "react-three-map/maplibre";
import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader";
import { HemisphereLight } from "three";
import { BORDER_COLORS } from "../../Services/Constants/BorderColors";
import { POLYGON_COLORS } from "../../Services/Constants/PolygonColors";
import useRequest from "../../Services/Hooks/useRequest";
import { ClipLoader } from "react-spinners";
const FBXModel = memo(({ url, rotation, setLoading, uniqueKey }) => {
const fbx = useLoader(FBXLoader, url, (loader) => {
loader.manager.onStart = () => setLoading(true);
loader.manager.onLoad = () => setLoading(false);
loader.manager.onError = () => setLoading(false);
});
const fbxRef = useRef();
return (
<group ref={fbxRef} rotation={rotation} scale={0.0097} key={uniqueKey}>
<hemisphereLight
args={["#ffffff", "#60666C"]}
intensity={12}
key={`${uniqueKey}-light`}
/>
<primitive object={fbx} key={`${uniqueKey}-primitive`} />
</group>
);
});
const MapPolygons = () => {
const map = useMap();
const bounds = map.current.getBounds();
const [features, setFeatures] = useState([]);
const [buildingModels, setBuildingModels] = useState([]);
const [zoom, setZoom] = useState(map.current.getZoom());
const [isLoading, setIsLoading] = useState(false);
const { Request } = useRequest();
useEffect(() => {
const handleViewportChange = () => {
setZoom(map.current.getZoom());
};
map.current.on("zoomend", handleViewportChange);
return () => {
map.current.off("zoomend", handleViewportChange);
};
}, [map]);
useEffect(() => {
window.Echo.channel("feature-status").listen(
".feature-status-changed",
(e) => {
const data = [];
for (const feature of features) {
if (parseInt(feature.id) === parseInt(e.data.id)) {
feature.rgb = e.data.rgb;
}
data.push(feature);
}
setFeatures(data);
}
);
}, [features]);
useEffect(() => {
if (bounds.getSouthWest().lng && zoom >= 14) {
const loadBuildings = zoom >= 15 ? "&load_buildings=1" : "";
Request(
`features?points[]=${bounds.getSouthWest().lng},${
bounds.getSouthWest().lat
}&points[]=${bounds.getSouthEast().lng},${
bounds.getSouthEast().lat
}&points[]=${bounds.getNorthWest().lng},${
bounds.getNorthWest().lat
}&points[]=${bounds.getNorthEast().lng},${
bounds.getNorthEast().lat
}${loadBuildings}`
).then((response) => {
const newFeatures = [];
const newBuildingModels = [];
for (const feature of response?.data?.data) {
newFeatures.push({
id: feature?.geometry?.feature_id,
rgb: feature?.properties?.rgb,
coordinates: feature?.geometry?.coordinates.map((coordinate) => [
parseFloat(coordinate.x),
parseFloat(coordinate.y),
]),
});
if (feature.building_models) {
for (const model of feature.building_models) {
newBuildingModels.push(model);
}
}
}
setFeatures((prevFeatures) => [...prevFeatures, ...newFeatures]);
setBuildingModels((prevModels) => [
...prevModels,
...newBuildingModels,
]);
});
}
}, [bounds.getSouthWest().lng, zoom]);
return (
<>
{zoom >= 14 && (
<Source
id="polygons"
type="geojson"
data={{
type: "FeatureCollection",
features: features.map((polygon) => ({
type: "Feature",
properties: {
id: polygon.id,
fill: POLYGON_COLORS[polygon.rgb],
border: BORDER_COLORS[polygon.rgb],
},
geometry: {
type: "Polygon",
coordinates: [polygon.coordinates],
},
})),
}}
>
<Layer
id="polygon-fill-layer"
type="fill"
paint={{
"fill-color": ["get", "fill"],
}}
/>
<Layer
id="polygon-outline-layer"
type="line"
paint={{
"line-color": ["get", "border"],
"line-width": 3,
}}
/>
</Source>
)}
{zoom >= 15 &&
buildingModels.length > 0 &&
buildingModels.map((model) => {
return (
<>
{isLoading && <ClipLoader color="#36d7b7" />}
<Canvas
latitude={parseFloat(model.building.position.split(", ")[0])}
longitude={parseFloat(model.building.position.split(", ")[1])}
key={`${model.id}-canvas`}
>
<FBXModel
url={model.file.url}
rotation={[0, 0, 0]}
setLoading={setIsLoading}
uniqueKey={`${model.id}-model`}
/>
</Canvas>
</>
);
})}
</>
);
};
export default MapPolygons;
The models have different URLs and unique keys.
This issue is impacting the accurate visualization of 3D models on the map.
Environment:
