Home > OS >  Three.js: Scaling issue when drawing earth with an image as surface texture
Three.js: Scaling issue when drawing earth with an image as surface texture

Time:04-25

I am trying to draw earth with a bunch of satellites and users on earth and lines pointing from satellite to users but I am completely failing.

Scaling issue:

enter image description here

And when I zoom out a little: enter image description here

import React, { useRef } from "react";
import { useLoader, useFrame } from "@react-three/fiber";
import { TextureLoader } from "three";
import { OrbitControls, Stars } from "@react-three/drei";
import * as THREE from "three";
import data from "../data.json";

import EarthDayMap from "../assets/img/earth_texture_map_1000px.jpg";

const COLORS = {
  0: 'white',
  1: 'lightgrey',
  2: 'orange',
  3: 'pink'
};

const EARTH_RADIUS = 4000;

export function Earth(props) {
  const [colorMap, normalMap, specularMap, cloudsMap] = useLoader(
    TextureLoader,
    [EarthDayMap]
  );

  const earthRef = useRef();
  const cloudsRef = useRef();
  const satellitesRef = useRef([]);
  const usersRef = useRef([]);

  useFrame(({ clock }) => {
    const elapsedTime = clock.getElapsedTime();

    earthRef.current.rotation.y = elapsedTime / 24;
    cloudsRef.current.rotation.y = elapsedTime / 24;
  });

  return (
    <>
      <ambientLight intensity={1} />
      <pointLight color="#f6f3ea" position={[5000, 0, 5]} intensity={1.2} />
      <Stars
        radius={30000}
        count={20000}
        factor={7}
        saturation={0}
        fade={true}
      />
      <mesh ref={cloudsRef} position={[0, 0, 0]}>
        <sphereGeometry args={[0, 32, 32]} />
        <meshPhongMaterial
          map={cloudsMap}
          opacity={0.1}
          transparent={true}
          side={THREE.DoubleSide}
        />
      </mesh>
      <group>
        {data.satellites.map(({ coordinate: { x, y, z }, id }, i) => <mesh
          key={id}
          ref={el => satellitesRef.current[i] = el}
          position={[x, y, z]}>
          <sphereGeometry args={[100, 32, 32]} />
          <meshPhongMaterial
            color='red'
            side={THREE.DoubleSide}
          />
        </mesh>)}
      </group>
      <group>
        {data.satellites.map(({ coordinate: { x, y, z }, id }, i) => <mesh
          key={id}
          ref={el => usersRef.current[i] = el}
          position={[x, y, z]}>
          <sphereGeometry args={[100, 32, 32]} />
          <meshPhongMaterial
            color='green'
            side={THREE.DoubleSide}
          />
        </mesh>)}
      </group>
      <group>
        {data.mappings.map(({ satellite: satelliteId, user: userId, color }, id) => {

          const satellite = data.satellites.find(s => s.id === satelliteId);
          const user = data.users.find(u => u.id === userId);

          return <line key={id}
            points={[
              [satellite.coordinate.x, satellite.coordinate.y, satellite.coordinate.z],
              [user.coordinate.x, user.coordinate.y, user.coordinate.z]
            ]}
            color={COLORS[color]}
          />
        })}
      </group>
      <mesh ref={earthRef} position={[0, 0, 0]}>
        <sphereGeometry args={[EARTH_RADIUS, 256, 256]} />
        <meshPhongMaterial specularMap={specularMap} />
        <meshStandardMaterial
          map={colorMap}
          normalMap={normalMap}
          metalness={0.4}
          roughness={0.7}
        />
        <OrbitControls
          enableZoom={true}
          enablePan={true}
          enableRotate={true}
          zoomSpeed={0.6}
          panSpeed={0.5}
          rotateSpeed={0.4}
        />
      </mesh>
    </>
  );
}

Repository

CodePudding user response:

Your Earth radius seems to be 4000 units. The Perspective camera by default has a near and far range of 0.1 to 2000, so most of the sphere is probably outside the camera’s frustum. You’ll have to adjust these values. I’d try camera.near = 100 and far at 10000, for starters.

https://threejs.org/docs/?q=camer#api/en/cameras/PerspectiveCamera.far

  • Related