react-native-filament
Version:
A real-time physically based 3D rendering engine for React Native
114 lines (105 loc) • 3.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useModel = useModel;
var _useBuffer = require("./useBuffer");
var _useFilamentContext = require("./useFilamentContext");
var _useDisposableResource = require("./useDisposableResource");
var _usePrevious = _interopRequireDefault(require("./usePrevious"));
var _useWorkletEffect = require("./useWorkletEffect");
var _react = require("react");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* The resulting filament model, or `'loading'` if not yet available.
*/
/**
* Loads a model from the given source.
*
*
* If you are passing in a `.glb` model or similar from your app's bundle using `require(..)`, make sure to add `glb` as an asset extension to `metro.config.js`!
* If you are passing in a `{ url: ... }`, make sure the URL points directly to a `.glb` model. This can either be a web URL (`http://..`/`https://..`), a local file (`file://..`), or an native asset path (`path/to/asset.glb`)
*
* @worklet
* @example
* ```ts
* const model = useModel(require('model.glb'))
* ```
*/
function useModel(source, props) {
const {
shouldReleaseSourceData = true,
addToScene = true,
instanceCount
} = props ?? {};
const {
engine,
scene,
workletContext
} = (0, _useFilamentContext.useFilamentContext)();
const assetBuffer = (0, _useBuffer.useBuffer)({
source: source,
releaseOnUnmount: false
});
// Note: the native cleanup of the asset will remove it automatically from the scene
const asset = (0, _useDisposableResource.useDisposableResource)(() => {
if (assetBuffer == null) return;
if (instanceCount === 0) {
throw new Error('instanceCount must be greater than 0');
}
return workletContext.runAsync(() => {
'worklet';
let loadedAsset;
if (instanceCount == null || instanceCount === 1) {
loadedAsset = engine.loadAsset(assetBuffer);
} else {
loadedAsset = engine.loadInstancedAsset(assetBuffer, instanceCount);
}
// After loading the asset we can release the buffer
assetBuffer.release();
return loadedAsset;
});
}, [assetBuffer, workletContext, engine, instanceCount]);
(0, _useWorkletEffect.useWorkletEffect)(() => {
'worklet';
if (asset == null || !shouldReleaseSourceData) {
return;
}
// releases CPU memory for bindings
asset.releaseSourceData();
});
// Add or remove from the scene:
const previousAddToScene = (0, _usePrevious.default)(addToScene);
(0, _useWorkletEffect.useWorkletEffect)(() => {
'worklet';
if (asset == null) return;
if (addToScene) {
scene.addAssetEntities(asset);
} else if (!addToScene && previousAddToScene) {
// Only remove when it was previously added (ie. the user set addToScene: false)
scene.removeAssetEntities(asset);
}
});
const boundingBox = (0, _react.useMemo)(() => {
if (asset == null) return undefined;
return asset.getBoundingBox();
}, [asset]);
const rootEntity = (0, _react.useMemo)(() => {
if (asset == null) {
return null;
}
return asset.getRoot();
}, [asset]);
if (assetBuffer == null || asset == null || boundingBox == null || rootEntity == null) {
return {
state: 'loading'
};
}
return {
state: 'loaded',
asset: asset,
rootEntity: rootEntity,
boundingBox: boundingBox
};
}
//# sourceMappingURL=useModel.js.map