expo-three
Version:
Utilities for using THREE.js on Expo
140 lines (122 loc) • 3.48 kB
text/typescript
import { Platform } from '@unimodules/core';
import AssetUtils from 'expo-asset-utils';
import THREE from '../Three';
import readAsStringAsync from './readAsStringAsync';
async function loadFileAsync({ asset, funcName }): Promise<string | null> {
if (!asset) {
throw new Error(`ExpoTHREE.${funcName}: Cannot parse a null asset`);
}
return await AssetUtils.uriAsync(asset);
}
export async function loadMtlAsync({ asset, onAssetRequested }): Promise<any> {
const uri = await loadFileAsync({
asset,
funcName: 'loadMtlAsync',
});
if (!uri) return;
// @ts-ignore
if (THREE.MTLLoader == null) {
require('./MTLLoader');
}
// @ts-ignore
const loader = new THREE.MTLLoader();
loader.setPath(onAssetRequested);
if (Platform.OS === 'web') {
return await new Promise((resolve, reject) =>
loader.load(uri, resolve, () => {}, reject),
);
}
return loadFileContentsAsync(loader, uri, 'loadMtlAsync');
}
export async function loadObjAsync(options: {
asset: any;
onAssetRequested?: (...args: any[]) => any;
onMtlAssetRequested?: (...args: any[]) => any;
mtlAsset?: any;
materials?: any;
}): Promise<any> {
const {
asset,
onAssetRequested,
onMtlAssetRequested,
mtlAsset,
materials,
} = options;
let nextMaterials = materials;
if (nextMaterials == null && mtlAsset != null) {
nextMaterials = await loadMtlAsync({
asset: mtlAsset,
onAssetRequested: onMtlAssetRequested || onAssetRequested,
});
nextMaterials.preload();
}
const uri = await loadFileAsync({
asset,
funcName: 'loadObjAsync',
});
if (!uri) return;
// @ts-ignore
if (THREE.OBJLoader == null) {
require('three/examples/js/loaders/OBJLoader');
}
// @ts-ignore
const loader = new THREE.OBJLoader();
if (onAssetRequested) {
loader.setPath(onAssetRequested as any);
}
if (nextMaterials != null) {
loader.setMaterials(nextMaterials);
}
if (Platform.OS === 'web') {
return await new Promise((resolve, reject) =>
loader.load(uri, resolve, () => {}, reject),
);
}
return loadFileContentsAsync(loader, uri, 'loadObjAsync');
}
export async function loadDaeAsync({
asset,
onAssetRequested,
onProgress,
}): Promise<any> {
const uri = await loadFileAsync({
asset,
funcName: 'loadDaeAsync',
});
if (typeof uri !== 'string' || uri == null) {
return;
}
// @ts-ignore
if (THREE.ColladaLoader == null) {
require('three/examples/js/loaders/ColladaLoader');
}
return new Promise((res, rej) =>
new THREE.FileLoader().load(
uri!,
text => {
// @ts-ignore
const loader = new THREE.ColladaLoader();
const parsedResult = (loader.parse as any)(text, onAssetRequested);
res(parsedResult);
},
onProgress,
rej,
),
);
}
async function loadFileContentsAsync(loader, uri, funcName): Promise<any> {
try {
const fileContents = await readAsStringAsync(uri);
return loader.parse(fileContents);
} catch ({ message }) {
// Or model loader THREE.OBJLoader failed to parse fileContents
throw new Error(
`ExpoTHREE.${funcName}: Expo.FileSystem Failed to read uri: ${uri}. ${message}`,
);
}
}
export async function loadArrayBufferAsync({ uri, onProgress }): Promise<any> {
const loader = new THREE.FileLoader();
loader.setResponseType('arraybuffer');
return new Promise((res, rej) => loader.load(uri, res, onProgress, rej));
}