Skip to content

Duplicate Model Rendering for Different Models #121

@m6hdix

Description

@m6hdix

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:

image

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions