如何从useFBX渲染多个模型@反应三/drei



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

我有以下代码来渲染场景内的树

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;

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

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;

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

在javascript中,当您使用对象时,您使用它的直接引用,因此您需要复制该对象:

let fbx = useFBX(props.fbx);
let fbxClone = {...fbx};

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

let fbxClone = fbx.clone();

除此之外,你可能想使用javascript.map函数,如果你得到一个对象数组,你可以用它来制作一个组件数组

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相同的方式工作(:

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它以反应三纤维组分的形式存在

<instancedMesh />

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

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;

最新更新