首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从useFBX渲染多个模型?@react-three/drei

如何从useFBX渲染多个模型?@react-three/drei
EN

Stack Overflow用户
提问于 2021-05-30 22:34:38
回答 2查看 349关注 0票数 0

我正在尝试在@react-three/drei中使用useFBX显示多个组件。尽管我调用了该函数两次,但在场景中只得到了一个组件。

我有以下代码来在场景中渲染一棵树

代码语言:javascript
复制
import { useBox } from "@react-three/cannon";
import { useFBX } from "@react-three/drei";
import React, { Suspense } from "react";

const Trees = (props) => {
  const [ref] = useBox(() => ({
    mass: 1,
    type: "Static",
    ...props,
  }));
  let fbx = useFBX(props.fbx);
  return (
    <Suspense fallback={null}>
      <mesh ref={ref} scale={props.scale} position={props.position}>
        <primitive object={fbx} dispose={null} />
      </mesh>
    </Suspense>
  );
};

export default Trees;

并且我正在调用另一个文件中的函数

代码语言:javascript
复制
    import React from "react";
    import Trees from "./Trees";
    
    const TreeDisplay = () => {
      return (
        <>
          <Trees
            fbx="/FBX/Tree1.fbx"
            position={[10, 0, 20]}
            scale={[0.01, 0.01, 0.01]}
          />
          <Trees
            fbx="/FBX/Tree1.fbx"
            position={[20, 0, 0]}
            scale={[0.01, 0.01, 0.01]}
          />
        </>
      );
    };
   export default TreeDisplay;

上面的函数必须在场景中定义的位置添加两棵树,但我只得到了一棵树。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-06-06 11:23:42

问题出在fbx上,克隆fbx模型就可以完成任务。

代码语言:javascript
复制
import { useBox } from "@react-three/cannon";
import { Loader, useFBX } from "@react-three/drei";
import React, { Suspense } from "react";

const Trees = (props) => {
  const [ref] = useBox(() => ({
    mass: 1,
    type: "Static",
    ...props,
  }));
  let fbx = useFBX(props.fbx);
  //Add this line
  let fbxClone = fbx.clone();
  return (
    <Suspense fallback={<Loader />}>
      <mesh ref={ref} scale={props.scale} material-reflectivity={1}>
        //pass the cloned object
        <primitive object={fbxClone} dispose={null} />
      </mesh>
    </Suspense>
  );
};

export default Trees;
票数 0
EN

Stack Overflow用户

发布于 2021-06-05 05:18:06

在javascript中,当你使用一个对象时,你使用的是它的直接引用,所以你需要复制该对象:

代码语言:javascript
复制
let fbx = useFBX(props.fbx);
let fbxClone = {...fbx};

在这种情况下,还有一个可能有用的object3D.clone()函数:

代码语言:javascript
复制
let fbxClone = fbx.clone();

除此之外,您可能想要使用javascript .map函数,如果您获得一个对象数组,则该函数允许您将其组成一个组件数组。

代码语言:javascript
复制
let mytrees  = [];
for(let i = 0;i<1000; i++)
   mytrees.push(fbx.clone());

return (<>{mytrees.map((tree)=>{return <instancedMesh material={tree.material} 
                                        geometry={tree.geometry} />})}</>)

这是一个完整的代码(使用gltfloader,但它应该与fbx的工作方式相同):

代码语言:javascript
复制
import React, { useRef, useState, useMemo, Suspense, useEffect, memo } from 'react'
import { Canvas, useFrame, useLoader, extend, useThree } from '@react-three/fiber'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader"
import * as THREE from 'three'

const Trees = memo((props) => {
    let listOfRefs = [];
    const tempObject = new THREE.Object3D();
    let treeTypes = ["three_1"];
    let loadedTrees = [];
    let trees = [];

    for(let cur of treeTypes)
    {
        loadedTrees.push(Object.values(useLoader(GLTFLoader, cur+'.glb',(loader) => {
          const dracoLoader = new DRACOLoader();
          dracoLoader.setDecoderPath("/draco-gltf/");
          loader.setDRACOLoader(dracoLoader);
        }).nodes).filter(m=>{return (m instanceof THREE.Mesh)})
        .map(m=>{return (<instancedMesh material={m.material} 
                                        geometry={m.geometry} 
                                        key={cur+""+Math.floor(Math.random()*10000)} 
                                        count={props.amount}
                                        ref={(()=>{
                                                listOfRefs.push(useRef()); 
                                                return listOfRefs[listOfRefs.length-1];
                                                })()}
                                        args={[null,null,props.amount]} />)}));
                                        
    }
    
    useEffect(()=>{
        if (listOfRefs.length < 1) return;
        let i = 0;
        for(let c = 0;c<props.amount;c++)
        {
            let currentPosition = [ Math.round(Math.random())?(Math.random()*props.halfSize):-(Math.random()*props.halfSize),
                                    13.75 , 
                                    Math.round(Math.random())?(Math.random()*props.halfSize):-(Math.random()*props.halfSize)];
            let currentRotation = [0,(Math.round(Math.random())*Math.PI/2),0]
            for(let curRef of listOfRefs) {
                const id = i++;
                tempObject.position.set(currentPosition[0],currentPosition[1],currentPosition[2])
                tempObject.rotation.set(currentRotation[0],currentRotation[1],currentRotation[2]);
                tempObject.updateMatrix();
                curRef.current.setMatrixAt(id, tempObject.matrix);
            }
        }
        for(let curRef of listOfRefs)
            curRef.current.instanceMatrix.needsUpdate = true;
        
    })
   return (
        <group>
            {loadedTrees[Math.floor(Math.random()*loadedTrees.length)]}
        </group>
   );
})
export default Trees;

另一个建议是使用这里提出的instancedMesh:https://threejs.org/docs/index.html?q=instanced#api/en/objects/InstancedMesh它以àreact-three-fiber组件的形式存在

<instancedMesh />

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67762366

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档