Three.js:使用图像作为表面纹理绘制地球时出现缩放问题
Three.js: Scaling issue when drawing earth with an image as surface texture
我试图用一堆卫星和地球上的用户以及从卫星指向用户的线来绘制地球,但我完全失败了。
缩放问题:
当我缩小一点时:
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>
</>
);
}
您的地球半径似乎是 4000 个单位。默认情况下,透视相机的近距和远距范围为 0.1 到 2000,因此大部分球体可能位于相机的截锥体之外。您必须调整这些值。对于初学者,我会尝试 camera.near = 100
到 10000。
https://threejs.org/docs/?q=camer#api/en/cameras/PerspectiveCamera.far
我试图用一堆卫星和地球上的用户以及从卫星指向用户的线来绘制地球,但我完全失败了。
缩放问题:
当我缩小一点时:
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>
</>
);
}
您的地球半径似乎是 4000 个单位。默认情况下,透视相机的近距和远距范围为 0.1 到 2000,因此大部分球体可能位于相机的截锥体之外。您必须调整这些值。对于初学者,我会尝试 camera.near = 100
到 10000。
https://threejs.org/docs/?q=camer#api/en/cameras/PerspectiveCamera.far