0

我正在尝试使用来自相机位置的光线投射来检测与 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;

4

0 回答 0