我正在尝试使用来自相机位置的光线投射来检测与 3d 模型的碰撞。但我不确定如何在 Canvas 中投射光线,或者如何检测与组件 3d 模型的碰撞。
这是我的代码:代码
当文本位于球体的另一侧时,我试图隐藏文本。
任何提示或信息将不胜感激!
地球模型(“.gltf”组网格):
export default function Earth(props) {
const group = useRef();
const { nodes, materials } = useGLTF("/earthPinsGlowingCentered.gltf");
const pStyle = {
fontSize: "200%",
color: "red"
};
return (
<group scale={[0.01, 0.01, 0.01]} ref={group} {...props} dispose={null}>
<group userData={{ name: "Pins" }}>
<mesh
material={materials.glowMat}
geometry={nodes.australia_1.geometry}
position={[95.98, -78.51, 64.8]}
rotation={[1.91, -0.5, 2.23]}
userData={{ name: "australia 1" }}
>
<Html>
<p style={pStyle}></p>
</Html>
</mesh>
<mesh
material={materials.glowMat}
geometry={nodes.australia_2.geometry}
position={[62.18, -70.29, 103.77]}
rotation={[1.85, -0.55, 2.58]}
userData={{ name: "australia 2" }}
>
<Html>
<p style={pStyle}>test</p>
</Html>
</mesh>
<mesh
material={materials.glowMat}
geometry={nodes.phillipenes.geometry}
position={[43.84, -5.37, 132.76]}
rotation={[1.48, -0.37, 2.79]}
userData={{ name: "phillipenes" }}
>
<Html>
<p style={pStyle}>test</p>
</Html>
</mesh>
<mesh
material={materials.glowMat}
geometry={nodes.asia_1.geometry}
position={[43.61, 31.01, 129.27]}
rotation={[1.26, -0.24, 2.8]}
userData={{ name: "asia 1" }}
>
<Html>
<p style={pStyle}>test</p>
</Html>
</mesh>
<mesh
material={materials.glowMat}
geometry={nodes.japan.geometry}
position={[88.31, 77.59, 75.88]}
rotation={[1.02, 0.29, 2.41]}
userData={{ name: "japan" }}
>
<Html>
<p style={pStyle}>test</p>
</Html>
</mesh>
<mesh
material={materials.glowMat}
geometry={nodes.russia.geometry}
position={[-28.99, 118.4, 68.66]}
rotation={[0.39, 0.57, -2.9]}
userData={{ name: "russia" }}
>
<Html>
<p style={pStyle}>test</p>
</Html>
</mesh>
<mesh
material={materials.glowMat}
geometry={nodes.india.geometry}
position={[-19.16, 30.82, 135.12]}
rotation={[1.28, 0.47, -3]}
userData={{ name: "india" }}
>
<Html>
<p style={pStyle}>test</p>
</Html>
</mesh>
<mesh
material={materials.glowMat}
geometry={nodes.egypt.geometry}
position={[-102.43, 64.02, 70.6]}
rotation={[0.65, 0.17, -2.31]}
userData={{ name: "egypt" }}
>
<Html>
<p style={pStyle}>test</p>
</Html>
</mesh>
<mesh
material={materials.glowMat}
geometry={nodes.germany.geometry}
position={[-76.96, 110.83, 37]}
rotation={[0.19, 0.2, -2.56]}
userData={{ name: "germany" }}
>
<Html>
<p style={pStyle}>test</p>
</Html>
</mesh>
<mesh
material={materials.glowMat}
geometry={nodes.canada.geometry}
position={[28.65, 117.52, -70.31]}
rotation={[-0.59, -0.26, 2.92]}
userData={{ name: "canada" }}
>
<Html>
<p style={pStyle}>test</p>
</Html>
</mesh>
<mesh
material={materials.glowMat}
geometry={nodes.UK.geometry}
position={[-46.89, 129.14, 26.43]}
rotation={[0.01, 0.5, -2.76]}
userData={{ name: "UK" }}
>
<Html>
<p style={pStyle}>test</p>
</Html>
</mesh>
<mesh
material={materials.glowMat}
geometry={nodes.spain.geometry}
position={[-102.49, 95.08, -5.69]}
rotation={[-0.25, 0.17, -2.31]}
userData={{ name: "spain" }}
>
<Html>
<p style={pStyle}>test</p>
</Html>
</mesh>
<mesh
material={materials.glowMat}
geometry={nodes.africa_1.geometry}
position={[-136.93, 19.5, -21.09]}
rotation={[-0.12, -0.14, -1.74]}
userData={{ name: "africa 1" }}
>
<Html>
<p style={pStyle}>test</p>
</Html>
</mesh>
<mesh
material={materials.glowMat}
geometry={nodes.africa_2.geometry}
position={[-113.39, -68.7, 44.69]}
rotation={[0.2, 0.47, -1.15]}
userData={{ name: "africa 2" }}
>
<Html>
<p style={pStyle}>test</p>
</Html>
</mesh>
<mesh
material={materials.glowMat}
geometry={nodes.SA_1.geometry}
position={[-32.87, -69.25, -117.04]}
rotation={[0.6, -1.06, -0.51]}
userData={{ name: "SA 1" }}
>
<Html>
<p style={pStyle}>test</p>
</Html>
</mesh>
<mesh
material={materials.glowMat}
geometry={nodes.SA_2.geometry}
position={[-67.8, -24.99, -119.81]}
rotation={[0.36, -0.99, -1.09]}
userData={{ name: "SA 2" }}
>
<Html>
<p style={pStyle}>test</p>
</Html>
</mesh>
<mesh
material={materials.glowMat}
geometry={nodes.SA_3.geometry}
position={[-18.66, -20.77, -137.1]}
rotation={[1.14, -1.12, -0.32]}
userData={{ name: "SA 3" }}
>
<Html>
<p style={pStyle}>test</p>
</Html>
</mesh>
<mesh
material={materials.glowMat}
geometry={nodes.NA_1.geometry}
position={[-9.27, 100.21, -97.19]}
rotation={[2.25, -1.08, -0.15]}
userData={{ name: "NA 1" }}
>
<Html>
<p style={pStyle}>test</p>
</Html>
</mesh>
<mesh
material={materials.glowMat}
geometry={nodes.NA_2.geometry}
position={[68.82, 118.36, -28.81]}
rotation={[-3.06, -0.51, 0.59]}
userData={{ name: "NA 2" }}
>
<Html>
<p style={pStyle}>test</p>
</Html>
</mesh>
<mesh
material={materials.glowMat}
geometry={nodes.NA_3.geometry}
position={[57.08, 80.37, -99.29]}
rotation={[2.95, -0.97, 0.79]}
userData={{ name: "NA 3" }}
>
<Html>
<p style={pStyle}>test</p>
</Html>
</mesh>
</group>
<mesh
material={materials.Mat}
geometry={nodes.globe.geometry}
userData={{ name: "globe" }}
/>
</group>
);
}
场景:
import React, { Suspense, useRef, useEffect } from "react";
import * as THREE from "three";
import { extend, useFrame, useThree } from "react-three-fiber";
import { Controls, useControl } from "react-three-gui";
import { a, config } from "react-spring/three";
import { OrbitControls, useHelper, softShadows } from "drei";
import { CameraHelper, SpotLightHelper } from "three";
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer";
import { ShaderPass } from "three/examples/jsm/postprocessing/ShaderPass";
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass";
import { SSAOPass } from "three/examples/jsm/postprocessing/SSAOPass";
import { UnrealBloomPass } from "three/examples/jsm/postprocessing/UnrealBloomPass";
import { FXAAShader } from "three/examples/jsm/shaders/FXAAShader";
import Earth from "./Earth";
softShadows();
extend({ EffectComposer, ShaderPass, RenderPass, UnrealBloomPass, SSAOPass });
function Effects() {
const composer = useRef();
const { scene, gl, size, camera } = useThree();
useEffect(() => void composer.current.setSize(size.width, size.height), [
size
]);
useFrame(() => composer.current.render(), 1);
return (
<effectComposer ref={composer} args={[gl]}>
<renderPass attachArray="passes" scene={scene} camera={camera} />
<sSAOPass
attachArray="passes"
args={[scene, camera, 1024, 1024]}
kernelRadius={0.8}
maxDistance={0.4}
/>
<unrealBloomPass attachArray="passes" args={[undefined, 1.6, 1, 0.5]} />
<shaderPass
attachArray="passes"
args={[FXAAShader]}
material-uniforms-resolution-value={[1 / size.width, 1 / size.height]}
/>
</effectComposer>
);
}
const Light = ({ color, xValue }) => {
const refLight = useRef();
useHelper(refLight, SpotLightHelper, 5);
const posZ = useControl("Pos Z", {
value: 0,
type: "number",
spring: config.wobbly,
distance: 100,
min: -100,
max: 100
});
const posX = useControl("Pos X", {
value: xValue,
type: "number",
spring: config.wobbly,
distance: 100,
min: -100,
max: 100
});
const posY = useControl("Pos Y", {
value: 0,
type: "number",
spring: config.wobbly,
distance: 100,
min: -100,
max: 100
});
const intensity = useControl("Intensity", {
value: 0.22,
min: 0.01,
max: 1,
type: "number",
distance: 1
});
return (
<a.spotLight
lookAt={[0, 0, 0]}
width={100}
height={100}
castShadow
color={color}
ref={refLight}
position-x={posX}
position-y={posY}
position-z={posZ}
intensity={intensity}
/>
);
};
const Lights = () => {
return (
<>
<Light color={"#C1ECFF"} xValue={-10} />
<Light color={"#E4F7FF"} xValue={10} />
<ambientLight intensity={0.2} />
</>
);
};
const Model = () => {
const modelContainerStyle = {
height: "100%",
width: "100%"
};
const labelsContainerStyle = {
position: "relative",
width: "100%",
height: "100%",
overflow: "hidden"
};
return (
<div style={modelContainerStyle}>
<Controls.Provider>
<Controls.Canvas
raycaster
camera={{ position: [0, 0, 5], fov: 60 }}
shadowMap
colorManagement
onCreated={({ gl }) => {
gl.setClearColor(new THREE.Color("#040708"));
}}
>
<OrbitControls
enablePan={Boolean("Pan", true)}
enableZoom={Boolean("Zoom", true)}
enableRotate={Boolean("Rotate", true)}
/>
<Suspense fallback={null}>
<Earth />
</Suspense>
<Lights />
<Effects />
</Controls.Canvas>
<Controls />
</Controls.Provider>
<div style={labelsContainerStyle}></div>
</div>
);
};
export default Model;