【问题标题】:Is there a way to display 3d models in a react native project without expo?有没有办法在没有博览会的反应原生项目中显示 3d 模型?
【发布时间】:2022-09-23 15:52:15
【问题描述】:

我试图在不使用 expo 的情况下在 react native 项目中显示 3d 模型。 我能找到的只是使用 expo 进行 react native 的示例。

  • 请提供足够的代码,以便其他人更好地理解或重现问题。
  • 我在代码中遇到的问题不是问题

标签: javascript reactjs 3d react-native-cli


【解决方案1】:

您可以使用 Three.js 在 react-native 中实现 3D 模型(gltf、glb、obj...)

例子: https://github.com/pmndrs/react-three-fiber

import { createRoot } from 'react-dom/client'
import React, { useRef, useState } from 'react'
import { Canvas, useFrame } from '@react-three/fiber'

function Box(props) {
  // This reference gives us direct access to the THREE.Mesh object
  const ref = useRef()
  // Hold state for hovered and clicked events
  const [hovered, hover] = useState(false)
  const [clicked, click] = useState(false)
  // Subscribe this component to the render-loop, rotate the mesh every frame
  useFrame((state, delta) => (ref.current.rotation.x += 0.01))
  // Return the view, these are regular Threejs elements expressed in JSX
  return (
    <mesh
      {...props}
      ref={ref}
      scale={clicked ? 1.5 : 1}
      onClick={(event) => click(!clicked)}
      onPointerOver={(event) => hover(true)}
      onPointerOut={(event) => hover(false)}>
      <boxGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
    </mesh>
  )
}

createRoot(document.getElementById('root')).render(
  <Canvas>
    <ambientLight />
    <pointLight position={[10, 10, 10]} />
    <Box position={[-1.2, 0, 0]} />
    <Box position={[1.2, 0, 0]} />
  </Canvas>,
)

你可以在这里找到完整的文档:https://github.com/pmndrs/react-three-fiber

注意:这不是我的代码,我只是将其粘贴在这里以供参考。

【讨论】:

    【解决方案2】:

    简短的回答:是的,你可以。

    长答案:您需要很多库,其中一些库来自 EXPO。您可以在不使用 expo CLI 的情况下在纯 react native 中使用 expo 库。

    这是使用轨道控制加载 3D 模型类型 .obj 的工作代码示例。

    import React, { useState, useEffect } from 'react';
    import { View } from 'react-native';
    import { ExpoWebGLRenderingContext, GLView } from 'expo-gl';
    import { resolveAsync } from 'expo-asset-utils';
    import * as FileSystem from 'expo-file-system';
    import { decode } from 'base64-arraybuffer';
    import { Renderer, TextureLoader, loadObjAsync, loadTextureAsync } from 'expo-three';
    import OrbitControlsView from 'expo-three-orbit-controls';
    import { Asset } from 'expo-asset'
    import {
      AmbientLight,
      BoxGeometry,
      Fog,
      GridHelper,
      Mesh,
      MeshStandardMaterial,
      PerspectiveCamera,
      PointLight,
      Scene,
      SpotLight,
      Camera,
    } from 'three';
    
    const ThreeD = () => {
      const [camera, setCamera] = useState<Camera | null>(null);
    
      let timeout;
    
      useEffect(() => {
        return () => clearTimeout(timeout);
      }, []);
    
      const onContextCreate = async (gl: ExpoWebGLRenderingContext) => {
        const { drawingBufferWidth: width, drawingBufferHeight: height } = gl;
        const sceneColor = 0x6ad6f0;
    
        // Create a WebGLRenderer without a DOM element
        const renderer = new Renderer({ gl });
        renderer.setSize(width, height);
        renderer.setClearColor(sceneColor);
    
        const camera = new PerspectiveCamera(70, width / height, 0.01, 1000);
        camera.position.set(2, 5, 5);
        setCamera(camera);
    
        const scene = new Scene();
        scene.fog = new Fog(sceneColor, 1, 10000);
        scene.add(new GridHelper(10, 10));
    
        const ambientLight = new AmbientLight(0xB1B1B1, 1.5);
        scene.add(ambientLight);
    
        const spotLight = new SpotLight(0xffffff, 1.5);
        spotLight.position.set(0, 200, 200);
        spotLight.lookAt(scene.position);
        scene.add(spotLight);
    
        const texture = await loadTextureAsync({
          asset: require('../assets/3D/delonghi-kettle/source/house/textures/house.xpng'),
        });
    
        const obj = await loadObjAsync({
          asset: require('../assets/3D/delonghi-kettle/source/house/house.obj')
        });
        obj.traverse(function(object) {
          if (object instanceof THREE.Mesh) {
            object.material.map = texture;
          }
        });
    
        scene.add(obj);
    
        camera.lookAt(obj.position);
    
        function update() {
          obj.rotation.y = 0;
          obj.rotation.x = 0;
        }
    
        // Setup an animation loop
        const render = () => {
          timeout = requestAnimationFrame(render);
          update();
          renderer.render(scene, camera);
    
          gl.endFrameEXP();
        };
        render();
      };
    
      return (
        <View style={{flex: 1}}>
          <OrbitControlsView style={{ flex: 1 }} camera={camera}>
            <GLView style={{ flex: 1 }} onContextCreate={onContextCreate} key="d" />
          </OrbitControlsView>
        </View>
    
      );
    };
    
    export default ThreeD;

    这已经在 GitHub 上讨论过了。所以,我不会详细介绍。

    你可以去this comment阅读更多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多