[英]How to use .obj files in expo three.js without AR module? [React Native Expo]
我的問題是關於如何在expo three.js中使用.mtl和.obj文件,但是我不想使用AR,我只想使用旋轉對象的簡單畫布/視圖。 這段代碼是我想要的,但是要使用我的obj文件,而不是創建多維數據集。
import { View as GraphicsView } from 'expo-graphics';
import ExpoTHREE, { THREE } from 'expo-three';
import React from 'react';
import Assets from './Assets.js';
import ThreeStage from './ThreeStage.js';
export default class App extends React.Component {
componentWillMount() {
THREE.suppressExpoWarnings();
}
render() {
return (
<GraphicsView
onContextCreate={this.onContextCreate}
onRender={this.onRender}
/>
);
}
async setupModels() {
await super.setupModels();
const model = Assets.models.obj.ninja;
const SCALE = 2.436143; // from original model
const BIAS = -0.428408; // from original model
const object = await ExpoTHREE.loadObjAsync({
asset: require('ninja.obj'),
});
const materialStandard = new THREE.MeshStandardMaterial({
color: 0xffffff,
metalness: 0.5,
roughness: 0.6,
displacementScale: SCALE,
displacementBias: BIAS,
normalScale: new THREE.Vector2(1, -1),
//flatShading: true,
side: THREE.DoubleSide,
});
const geometry = object.children[0].geometry;
geometry.attributes.uv2 = geometry.attributes.uv;
geometry.center();
const mesh = new THREE.Mesh(geometry, materialStandard);
mesh.scale.multiplyScalar(0.25);
ExpoTHREE.utils.scaleLongestSideToSize(mesh, 1);
ExpoTHREE.utils.alignMesh(mesh, { y: 1 });
this.scene.add(mesh);
this.mesh = mesh;
}
onRender(delta) {
super.onRender(delta);
this.mesh.rotation.y += 0.5 * delta;
}
}
我的assets.js文件,其中包含.obj中我的3D模態的路徑
export default {
obj: {
"museu.obj": require('../Conteudos_AV/museu1.obj'),
}
};
還有我的threeStage.js文件,其中包含3DModal.js的導入
import ExpoTHREE, { THREE } from 'expo-three';
class ThreeStage {
constructor() {
this.onRender = this.onRender.bind(this);
this.setupControls = this.setupControls.bind(this);
this.onResize = this.onResize.bind(this);
this.setupCamera = this.setupCamera.bind(this);
this.setupScene = this.setupScene.bind(this);
}
onContextCreate = async ({
gl,
canvas,
width,
height,
scale: pixelRatio,
}) => {
this.gl = gl;
this.canvas = canvas;
this.width = width;
this.height = height;
this.pixelRatio = pixelRatio;
await this.setupAsync();
};
setupAsync = async () => {
const { gl, canvas, width, height, pixelRatio } = this;
await this.setupRenderer({ gl, canvas, width, height, pixelRatio });
await this.setupScene();
await this.setupCamera({ width, height });
await this.setupLights();
await this.setupModels();
await this.setupControls();
};
setupControls() {
new THREE.OrbitControls(this.camera);
}
setupRenderer = props => {
this.renderer = new ExpoTHREE.Renderer(props);
this.renderer.capabilities.maxVertexUniforms = 52502;
};
setupCamera({ width, height }) {
this.camera = new THREE.PerspectiveCamera(50, width / height, 0.1, 10000);
this.camera.position.set(0, 6, 12);
this.camera.lookAt(0, 0, 0);
}
setupScene() {
this.scene = new THREE.Scene();
this.scene.background = new THREE.Color(0x999999);
this.scene.fog = new THREE.FogExp2(0xcccccc, 0.002);
this.scene.add(new THREE.GridHelper(50, 50, 0xffffff, 0x555555));
}
setupLights = () => {
const directionalLightA = new THREE.DirectionalLight(0xffffff);
directionalLightA.position.set(1, 1, 1);
this.scene.add(directionalLightA);
const directionalLightB = new THREE.DirectionalLight(0xffeedd);
directionalLightB.position.set(-1, -1, -1);
this.scene.add(directionalLightB);
const ambientLight = new THREE.AmbientLight(0x222222);
this.scene.add(ambientLight);
};
async setupModels() {}
onResize({ width, height, scale }) {
this.camera.aspect = width / height;
this.camera.updateProjectionMatrix();
this.renderer.setPixelRatio(scale);
this.renderer.setSize(width, height);
this.width = width;
this.height = height;
this.pixelRatio = scale;
}
onRender(delta) {
this.renderer.render(this.scene, this.camera);
}
}
export default ThreeStage;
看起來提供的代碼創建了一個ThreeStage類,該類已導入,但從未被包含Expo GraphicsView的類使用。
在倉庫3中,為世博會提供的示例使用了一些深奧的結構,因為它們分別是通過具有集中式資產庫和抽象組件的react-navigation應用程序提供的。 對於僅嘗試在屏幕上顯示模型的簡單應用程序來說,這是很多額外的。
import React from 'react';
import ExpoTHREE, { THREE } from 'expo-three';
import { GraphicsView } from 'expo-graphics';
export default class App extends React.Component {
componentDidMount() {
THREE.suppressExpoWarnings();
}
render() {
return (
<GraphicsView
onContextCreate={this.onContextCreate}
onRender={this.onRender}
onResize={this.onResize}
/>
);
}
// When our context is built we can start coding 3D things.
onContextCreate = async ({ gl, pixelRatio, width, height }) => {
// Create a 3D renderer
this.renderer = new ExpoTHREE.Renderer({
gl,
pixelRatio,
width,
height,
});
// We will add all of our meshes to this scene.
this.scene = new THREE.Scene();
this.scene.background = new THREE.Color(0xbebebe)
this.camera = new THREE.PerspectiveCamera(45, width/height, 1, 1000)
this.camera.position.set(3, 3, 3);
this.camera.lookAt(0, 0, 0);
this.scene.add(new THREE.AmbientLight(0xffffff));
await this.loadModel();
};
loadModel = async () => {
const obj = {
"museu.obj": require('../Conteudos_AV/museu1.obj')
}
const model = await ExpoTHREE.loadAsync(
obj['museu.obj'],
null,
obj
);
// this ensures the model will be small enough to be viewed properly
ExpoTHREE.utils.scaleLongestSideToSize(model, 1);
this.scene.add(model)
};
// When the phone rotates, or the view changes size, this method will be called.
onResize = ({ x, y, scale, width, height }) => {
// Let's stop the function if we haven't setup our scene yet
if (!this.renderer) {
return;
}
this.camera.aspect = width / height;
this.camera.updateProjectionMatrix();
this.renderer.setPixelRatio(scale);
this.renderer.setSize(width, height);
};
// Called every frame.
onRender = delta => {
// Finally render the scene with the Camera
this.renderer.render(this.scene, this.camera);
};
}
我從Evan的博覽會零食示例中改編了此代碼,由於它們在整個示例應用程序中沒有太多開銷,因此易於遵循。 您可以在他的博覽會零食頁面上找到更多信息: https : //expo.io/snacks/@bacon 。
該代碼應呈現您的目標文件,但是如果您的.obj依賴於其他材質或紋理文件,則可能會遇到問題。 如果是這種情況,則需要將它們添加到loadModel函數中,如下所示:
const obj = {
"museu.obj": require('../Conteudos_AV/museu1.obj'),
"museu.mtl": require('../Conteudos_AV/museu1.mtl'),
"museu.png": require('../Conteudos_AV/museu1.png'),
}
const model = await ExpoTHREE.loadAsync(
[obj['museu.obj'], obj['museu.mtl']],
null,
obj
);
我建議您在開始時先看看使用expo-3而不是示例應用程序的expo快餐,因為處理示例中的所有復雜內容可能有點兒困惑。
我目前沒有方便使用的設備進行測試,但是請告訴我上述代碼是否有問題,當我回到手機和筆記本電腦旁邊時,我可以進行故障排除。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.