I am working on implementing a texture from an image using createTHREEViewClass. I want to map this texture to a materaial to be used on the inside of a sphere mesh to make a panorama.
I am using Node v7.10.0
Here are my project dependencies:
"@expo/vector-icons": "^5.0.0",
"directory": "^0.1.0",
"expo": "^16.0.0",
"lodash": "^4.17.4",
"prop-types": "^15.5.9",
"react": "16.0.0-alpha.6",
"react-native": "^0.43.4",
"react-navigation": "^1.0.0-beta.9",
"react-redux": "^5.0.4",
"redux-logger": "^3.0.1",
"redux-multi": "^0.1.12",
"redux-thunk": "^2.2.0",
"three": "^0.85.2"
Here is the project path for the image I am trying to load:
src/components/TestView/equirectangle.jpg
Here is the appâs folder structure:
|- src
|- components
|- TestView
|- equirectange.jpg
|- TestThreeJS.js
|- App.js
Here is my class:
import React, {Component} from 'react'
import {Dimensions} from 'react-native'
import Expo from 'expo'
import * as THREE from 'three'
const {
Matrix4,
MeshBasicMaterial,
PerspectiveCamera,
Scene,
SphereGeometry,
Vector3
} = THREE
export default class TestThreeJS extends Component {
ThreeView = Expo.createTHREEViewClass(THREE)
componentWillMount () {
const {width, height} = Dimensions.get('window')
this.scene = new Scene()
this.scene.name = 'scene'
this.camera = new PerspectiveCamera(75, width / height, 1, 1000)
this.camera.name = 'perspective-camera'
this.camera.target = new Vector3(0, 0, 0)
this.scene.add(this.camera)
const panoGeometry = new SphereGeometry(500, 60, 40)
panoGeometry.applyMatrix(new Matrix4().makeScale(-1, 1, 1))
const panoMaterial = loadImageMaterial('pano', this.ThreeView)
const panoMesh = new THREE.Mesh(panoGeometry, panoMaterial)
panoMesh.material.side = THREE.DoubleSide
panoMesh.name = 'pano'
this.scene.add(panoMesh)
}
update = (dt) => {
}
render () {
const {ThreeView, update, scene, camera} = this
return (
<ThreeView
style={{flex: 1}}
backgroundColor={'#FFFFFF'}
scene={scene}
camera={camera}
tick={update}
/>
)
}
}
// The code below was suggested by Jim
const modules = {
'pano': require('./equirectangle.jpg')
}
const Assets = Object.assign({},
...Object.keys(modules).map(name => ({
[name]: Expo.Asset.fromModule(modules[name])
}))
)
const loadImageMaterial = (assetName, threeView) => {
const asset = Assets[assetName]
asset.localUri = asset.uri
const texture = threeView.textureFromAsset(asset)
texture.minFilter = texture.magFilter = THREE.NearestFilter
texture.needsUpdate = true
const material = new MeshBasicMaterial({
map: texture,
transparent: true // Use the image's alpha channel for alpha.
})
return material
}
I got an error when running the aboce code: Asset ./equirectangle.jpg needs to be downloaded before being used as an OpenGL texture.
It is thrown from createTHREEViewClass ln 39. The asset I am passing does not have a localUri property, just a uri.
I updated the asset object to set the localUri property from the uri and here is my asset object logged out in textureFromAsset
:
// asset object
{
"name": "equirectangle",
"type": "jpg",
"hash": "27bb232b523c0038ce850bd343e9366e",
"uri": "http://localhost:19001/assets/src/components/TestView/equirectangle.jpg?platform=ios&hash=27bb232b523c0038ce850bd343e9366e",
"width": 5376,
"height": 2688,
"downloading": false,
"downloaded": false,
"downloadCallbacks": [],
"localUri": "http://localhost:19001/assets/src/components/TestView/equirectangle.jpg?platform=ios&hash=27bb232b523c0038ce850bd343e9366e"
}
I now get an error Cant find variable: document
I checked the meta object that Assets.fromModule
is returning and here is what I get:
// meta obj
{
"__packager_asset": true,
"httpServerLocation": "/assets/src/components/TestView",
"width": 5376,
"height": 2688,
"scales": [
1
],
"hash": "27bb232b523c0038ce850bd343e9366e",
"name": "equirectangle",
"type": "jpg",
"fileHashes": [
"27bb232b523c0038ce850bd343e9366e"
]
}
Which is turned into the asset I listed above.
This is where I am stuck. A couple of things of interest:
-
Expo.Asset.fromModule()
does not set a localUri property even though it is expected inthreeView.textureFromAsset()
- The uri and now localUri path seem to be looking in an assets directory that does not exist. I looked into
Asset.fromModule
and its using the react-native AssetRegistry which must be making asset locations in an asset directory