• Stars
    star
    619
  • Rank 72,496 (Top 2 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created over 7 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Utilities for using THREE.js on Expo

Welcome to Expo & Three.JS 👋

Tools for using three.js to create universal 3D experiences | Try it in the browser!

GitHub Actions status

Twitter: expo Medium: exposition

This package bridges Three.js to Expo GL - a package which provides a WebGL interface for native OpenGL-ES in React. Largely this helps with abstracting the DOM parts away from Three.js.

AR was moved to expo-three-ar in [email protected]

Quick Start

Create a universal React project with expo-three setup:

npx create-react-native-app -t with-three

For a more declarative interface, you can use this package with react-three-fiber. You can bootstrap that with:

npx create-react-native-app -t with-react-three-fiber

Installation

In [email protected] and higher, Three.js is a peer dependency

yarn add three expo-three expo-gl

Usage

Import the library into your project file:

import { Renderer } from 'expo-three';

Get a global instance of three.js from expo-three:

import { THREE } from 'expo-three';

🚨 You'll need to use a physical device as the iOS Simulators and Android emulators do not work well with Three.js + EXGL.

Due to some issues with the Metro bundler you may need to manually define the global instance of Three.js. This is important because three.js doesn't fully use ECMAScript but rather mutates a single global instance of THREE with side-effects.

global.THREE = global.THREE || THREE;

Creating a Renderer

Given a gl from a GLView, return a THREE.WebGLRenderer that draws to it.

import * as React from 'react';
import { ExpoWebGLRenderingContext, GLView } from 'expo-gl';
import { Renderer } from 'expo-three';

export default function App() {
  return (
    <GLView
      style={{ flex: 1 }}
      onContextCreate={(gl: ExpoWebGLRenderingContext) => {
        // Create a WebGLRenderer without a DOM element
        const renderer = new Renderer({ gl });
        renderer.setSize(gl.drawingBufferWidth, gl.drawingBufferHeight);
      }}
    />
  );
}

Loading assets

The Metro bundler cannot load arbitrary file types like (.obj, .mtl, .dae, etc..). In order to support them you must create a ./metro.config.js in your project root, and add the file extensions you want to support.

metro.config.js

module.exports = {
  resolver: {
    assetExts: ['db', 'mp3', 'ttf', 'obj', 'png', 'jpg'],
  },
};

All assets require a local URI to be loaded. You can resolve a local URI with expo-asset.

import { Asset } from 'expo-asset';

// Create an Asset from a resource
const asset = Asset.fromModule(require('./image.png'));

await asset.downloadAsync();

// This is the local URI
const uri = asset.localUri;

Loading a texture

After you have an asset loaded, you can use it to create a Three.js Texture. expo-three provides a helper utility that can resolve the asset internally and make other modifications to support a wider variety of images:

import { TextureLoader } from 'expo-three';

// This texture will be immediately ready but it'll load asynchronously
const texture = new TextureLoader().load(require('./img.png'));

Optionally, you can create a texture from the local URI manually (this may not work for most image types):

import { TextureLoader } from 'three';
import { Asset } from 'expo-asset';

// Create an Asset from a resource
const asset = Asset.fromModule(require('./img.png'));

await asset.downloadAsync();
// This texture will be immediately ready but it'll load asynchronously
const texture = new TextureLoader().load(asset.localUri);

Loading an obj model

Be sure to add support for whatever model extension you wish to load to your metro.config.js, then you can load a model using the local URI:

// Import from jsm for smaller bundles and faster apps
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
import { Asset } from 'expo-asset';

const asset = Asset.fromModule(require('./model.obj'));
await asset.downloadAsync();

const loader = new OBJLoader();
loader.load(asset.localUri, group => {
  // Model loaded...
});

ExpoTHREE.loadAsync()

A function that will asynchronously load files based on their extension.

Notice: Remember to update your metro.config.js to bundle obscure file types!

metro.config.js

module.exports = {
  resolver: {
    assetExts: ['db', 'mp3', 'ttf', 'obj', 'png', 'jpg'],
  },
};

Props

Property Type Description
resource PossibleAsset The asset that will be parsed asynchornously
onProgress (xhr) => void A function that is called with an xhr event
assetProvider () => Promise<Expo.Asset> A function that is called whenever an unknown asset is requested
PossibleAsset Format

export type PossibleAsset = Expo.Asset | number | string | AssetFormat;

type PossibleAsset = number | string | Expo.Asset;
  • number: Static file reference require('./model.*')
  • Expo.Asset: Expo.Asset
  • string: A uri path to an asset

Returns

This returns many different things, based on the input file. For a more predictable return value you should use one of the more specific model loaders.

Example

const texture = await ExpoTHREE.loadAsync(
  'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png'
);

Loaders

loadAsync(assetReference, onProgress, onAssetRequested)

A universal loader that can be used to load images, models, scenes, and animations. Optionally more specific loaders are provided with less complexity.

// A THREE.Texture from a static resource.
const texture = await ExpoTHREE.loadAsync(require('./icon.png'));
const obj = await ExpoTHREE.loadAsync(
  [require('./cartman.obj'), require('./cartman.mtl')],
  null,
  imageName => resources[imageName]
);
const { scene } = await ExpoTHREE.loadAsync(
  resources['./kenny.dae'],
  onProgress,
  resources
);

loadObjAsync({ asset, mtlAsset, materials, onAssetRequested, onMtlAssetRequested })

🚨 Deprecated: Load OBJ files manually with the JS module three/examples/jsm/loaders/OBJLoader

Props

  • asset: a obj model reference that will be evaluated using AssetUtils.resolveAsync
  • mtlAsset: an optional prop that will be loaded using loadMtlAsync()
  • onAssetRequested: A callback that is used to evaluate urls found within the asset and optionally the mtlAsset. You can also just pass in a dictionary of key values if you know the assets required ahead of time.
  • materials: Optionally you can provide an array of materials returned from loadMtlAsync()
  • onMtlAssetRequested: If provided this will be used to request assets in loadMtlAsync()

This function is used as a more direct method to loading a .obj model. You should use this function to debug when your model has a corrupted format.

const mesh = await loadObjAsync({ asset: 'https://www.members.com/chef.obj' });

loadTextureAsync({ asset })

🚨 Deprecated: Load textures manually with the JS module from three

Props

  • asset: an Expo.Asset that could be evaluated using AssetUtils.resolveAsync if localUri is missing or the asset hasn't been downloaded yet.

This function is used as a more direct method to loading an image into a texture. You should use this function to debug when your image is using an odd extension like .bmp.

const texture = await loadTextureAsync({ asset: require('./image.png') });

loadMtlAsync({ asset, onAssetRequested })

🚨 Deprecated: Load MTL files manually with the JS module three/examples/jsm/loaders/MTLLoader

Props

  • asset: a mtl material reference that will be evaluated using AssetUtils.resolveAsync
  • onAssetRequested: A callback that is used to evaluate urls found within the asset, optionally you can just pass in a dictionary of key values if you know the assets required ahead of time.
const materials = await loadMtlAsync({
  asset: require('chef.mtl'),
  onAssetRequested: modelAssets,
});

loadDaeAsync({ asset, onAssetRequested, onProgress })

🚨 Deprecated: Load DAE files manually with the JS module three/examples/jsm/loaders/ColladaLoader

Props

  • asset: a reference to a dae scene that will be evaluated using AssetUtils.resolveAsync
  • onAssetRequested: A callback that is used to evaluate urls found within the asset, optionally you can just pass in a dictionary of key values if you know the assets required ahead of time.
  • onProgress: An experimental callback used to track loading progress.
const { scene } = await loadDaeAsync({
  asset: require('chef.dae'),
  onAssetRequested: modelAssets,
  onProgress: () => {},
});

ExpoTHREE.utils

These are Three.js utilities that aren't required for using Three.js with Expo.

ExpoTHREE.utils.alignMesh()

Props

type Axis = {
  x?: number,
  y?: number,
  z?: number,
};
Property Type Description
mesh &THREE.Mesh The mesh that will be manipulated
axis ?Axis Set the relative center axis

Example

ExpoTHREE.utils.alignMesh(mesh, { x: 0.0, y: 0.5 });

ExpoTHREE.utils.scaleLongestSideToSize()

Props

Property Type Description
mesh &THREE.Mesh The mesh that will be manipulated
size number The size that the longest side of the mesh will be scaled to

Example

ExpoTHREE.utils.scaleLongestSideToSize(mesh, 3.2);

ExpoTHREE.utils.computeMeshNormals()

Used for smoothing imported geometry, specifically when imported from .obj models.

Props

Property Type Description
mesh &THREE.Mesh The mutable (inout) mesh that will be manipulated

Example

ExpoTHREE.utils.computeMeshNormals(mesh);

THREE Extensions

suppressMetroWarnings

A function that suppresses EXGL compatibility warnings and logs them instead. By default this is enabled on native because it can cause the Metro development server to slow down significantly. You will need to import the ExpoTHREE.THREE global instance to use this. By default this function will be activated on import.

  • shouldSuppress: boolean
import { THREE } from 'expo-three';
THREE.suppressMetroWarnings();

Links

Somewhat out of date

🤝 Contributing

Contributions, issues and feature requests are welcome!
Feel free to check issues page.

Show your support

Give a ⭐️ if this project helped you!

📝 License

Copyright © 2019-2022 650 Industries.
This project is MIT licensed.

More Repositories

1

expo

An open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.
TypeScript
33,454
star
2

create-react-native-app

Create React Native apps that run on iOS, Android, and web
TypeScript
13,151
star
3

expo-cli

Tools for creating, running, and deploying universal Expo and React Native apps
TypeScript
2,608
star
4

examples

Example projects that demonstrate how to use Expo APIs and integrate Expo with other popular tools
JavaScript
1,567
star
5

react-native-action-sheet

A cross-platform ActionSheet for React Native
TypeScript
1,384
star
6

router

[ARCHIVE]: Expo Router has moved to expo/expo -- The File-based router for universal React Native apps
TypeScript
1,367
star
7

xde

The Expo Development Environment
JavaScript
1,168
star
8

ex-navigation

Route-centric navigation for React Native
JavaScript
1,003
star
9

eas-cli

Fastest way to build, submit, and update iOS and Android apps
TypeScript
800
star
10

react-conf-app

TypeScript
791
star
11

google-fonts

Use any of the 1000+ fonts (and their variants) from fonts.google.com in your Expo app.
JavaScript
788
star
12

expo-github-action

Expo GitHub Action makes it easy to automate EAS builds or updates
TypeScript
782
star
13

fyi

Little bits of information that you may find useful when interacting with Expo tools and service. Append the markdown filename to https://expo.fyi/ to get a quick link to it.
759
star
14

expo-server-sdk-node

Server-side library for working with Expo using Node.js
TypeScript
674
star
15

vector-icons

JavaScript
646
star
16

react-native-read-more-text

JavaScript
572
star
17

ex-navigator

Route-centric navigation built on top of React Native's Navigator
JavaScript
522
star
18

react-native-infinite-scroll-view

An infinitely scrolling view that notifies you as the scroll offset approaches the bottom
JavaScript
520
star
19

awesome-expo

Useful resources for creating apps with Exponent
468
star
20

exp

JavaScript
465
star
21

react-native-invertible-scroll-view

An invertible ScrollView for React Native
JavaScript
460
star
22

config-plugins

Out-of-tree Expo config plugins for packages that haven't adopted the config plugin system yet.
TypeScript
457
star
23

orbit

Accelerate your development workflow with one-click build launches and simulator management from your macOS menu bar
TypeScript
436
star
24

vscode-expo

Expo Tools keep you productive with debugging, IntelliSense, and prebuild previews
TypeScript
425
star
25

turtle

Standalone app builder service
TypeScript
384
star
26

snack

Expo Snack lets you run Expo in the browser.
TypeScript
366
star
27

react-native-appearance

Access operating system appearance information (currently only light/dark mode) on iOS, Android, and web
Java
337
star
28

expo-pixi

Tools for using pixi.js in Expo
JavaScript
300
star
29

custom-expo-updates-server

A simplified demonstration of expo-updates protocol use.
TypeScript
295
star
30

use-unmount-signal

A React Hook to cancel promises when a component is unmounted
TypeScript
292
star
31

web-examples

Examples of using Expo in the browser.
JavaScript
272
star
32

image-upload-example

Demonstration of how to upload images from the ImagePicker, using a node backend to upload to S3
JavaScript
228
star
33

snack-web

TypeScript
215
star
34

expo-phaser

Use Phaser.js on mobile with Expo GL
JavaScript
212
star
35

sentry-expo

TypeScript
201
star
36

fluxpybird

some ideas involving games and Redux
JavaScript
179
star
37

stripe-expo

Use the Stripe HTTP API in Expo without the DOM, node, or native deps
JavaScript
160
star
38

react-native-responsive-image

A responsive Image component that chooses the best-resolution image for the current screen
JavaScript
160
star
39

react-native-loading-container

A container component that takes care of loading/catching timeouts/retrying
JavaScript
156
star
40

camerja

JavaScript
156
star
41

dev-plugins

Out-of-tree Expo devtools plugins for packages that haven't adopted the Expo devtools plugin system yet.
TypeScript
152
star
42

playlist-example

JavaScript
151
star
43

entity

Entity is a privacy-aware data layer for defining, caching, and authorizing access to application data models.
TypeScript
140
star
44

match-media

Universal polyfill for match media API using Expo APIs on mobile
TypeScript
136
star
45

react-native-fade-in-image

JavaScript
118
star
46

atlas

Visualize React Native bundles to understand and optimize your app.
TypeScript
114
star
47

eslint-config-universe

Moved to https://github.com/expo/expo/tree/master/packages/eslint-config-universe
JavaScript
110
star
48

expo-2d-context

A pure-js implementation of the W3C's Canvas-2D Context API that can be run on either Expo Graphics or WebGL
HTML
110
star
49

audio-recording-example

Audio Recording Example
TypeScript
109
star
50

redux-effex

Spin off async functions to perform side effects
JavaScript
108
star
51

auth0-example

This example has moved
JavaScript
108
star
52

results

An efficient, standards-compliant library for representing results of successful or failed operations
TypeScript
102
star
53

firebase-storage-upload-example

This example has moved
JavaScript
98
star
54

sqlite-example

This example has moved
JavaScript
97
star
55

react-native-scrollable-mixin

A standard interface for your scrollable React Native components, making it easier to compose components.
JavaScript
94
star
56

expo-processing

Utilities for using Processing.js on Expo
JavaScript
93
star
57

videoplayer

Customizable controls for Expo video
JavaScript
83
star
58

snack-sdk

Snack SDK
JavaScript
83
star
59

react-apple-easing

Apple's default Core Animation easing functions for React
JavaScript
83
star
60

turtle-cli-example

Turtle CLI usage example (CircleCI & Travis CI)
Shell
81
star
61

eas-build

TypeScript
77
star
62

dire-dire-ducks

Flood your room with water and rubber duckies!
JavaScript
77
star
63

expo-preview-action

With this preview action, you can test changes made in pull requests via Expo Go or custom development client (created with expo-dev-client) just by scanning QR code.
JavaScript
75
star
64

status-bar-height

Listen to status bar changes during incoming calls and other multi-tasking events
JavaScript
73
star
65

expo-three-ar

Utilities for using Expo AR with THREE.js
TypeScript
72
star
66

react-native-image-gallery

JavaScript
71
star
67

pomodoroexp

https://expo.io/@community/pomodoro
JavaScript
70
star
68

react-native-refreshable-scroll-view

A ScrollView that supports pull-to-refresh. You can customize it with the RefreshIndicator and type of ScrollView (ex: ListView) of your choice.
JavaScript
61
star
69

spawn-async

A Promise-based interface into processes created by child_process.spawn
TypeScript
59
star
70

react-native-for-curious-people

Available through the Exponent iPhone or Android app:
JavaScript
59
star
71

UpdatesAPIDemo

Demo app showing the useUpdates() API
TypeScript
55
star
72

browser-polyfill

Browser polyfill for making React Native compatible with web libs like pixi.js, three.js, phaser.js
JavaScript
52
star
73

xdl

The Expo Development Library
TypeScript
47
star
74

harvard-cs50-app

Harvard's mobile application for CS50.
JavaScript
46
star
75

styleguide

Foundational styles for Expo interfaces.
TypeScript
45
star
76

hello-graphql

JavaScript
44
star
77

expo-graphics

Tools to help simplify working with three, pixi, phaser, ect...
JavaScript
44
star
78

detox-expo-helpers

JavaScript
43
star
79

expo-asset-utils

Utilities for parsing files references, and Expo Assets.
TypeScript
42
star
80

hackathon-examples

40
star
81

with-detox-tests

This template is no longer maintained! See https://github.com/yaron1m/expo-detox-typescript-example instead
JavaScript
39
star
82

react-native-scrollable-decorator

A standard interface for your scrollable React Native components, making it easier to compose components.
JavaScript
38
star
83

react-native-url-handler

Navigate to external URLs, handle in-app URLs, and access system URLs
Objective-C
36
star
84

rnplay

THIS REPOSITORY IS QUITE OLD AND NOT MAINTAINED! React Native Playground has been replaced by https://snack.expo.io. Look at this repository like you might look at tools in a museum, and don't touch it or actually use it
JavaScript
36
star
85

expo-twitter-login-example

This example has moved
JavaScript
34
star
86

react-native-image-picker-android

A camera and gallery image picker native module for Android, giving a subset of the API of https://github.com/marcshilling/react-native-image-picker
Java
34
star
87

eas-tests-example

Demo of running E2E tests on EAS Build
Java
33
star
88

react-loading-indicator

A loading indicator written purely in React that uses SVG and no images.
JavaScript
32
star
89

socket-io-example

This example has moved
29
star
90

expo-electron-adapter

This package wraps `electron-webpack` and adds support for Expo web and other universal React packages.
TypeScript
28
star
91

koa-graphiql

Koa middleware to display GraphiQL, the interactive GraphQL UI
JavaScript
27
star
92

video-background-example

This example has moved
JavaScript
27
star
93

gl-test

Examples and tests for OpenGL rendering in Expo.
JavaScript
26
star
94

three-ar-test

Using Expo's AR functionality with THREE.js
JavaScript
25
star
95

BrightSky

Learn how to use Expo with this simple weather app!
TypeScript
24
star
96

expo-postpublish-slack-notify

JavaScript
24
star
97

breakout

why not?
JavaScript
24
star
98

hyperinstall

Runs "yarn" and "npm install" in several directories with extreme speed when possible
JavaScript
23
star
99

electron-cookies

Provides document.cookie support for Electron
JavaScript
22
star
100

pound-random

Expo Blue - a discussion app for small groups
JavaScript
22
star