rnc-archive / react-native-webgl

DEPRECATED: use expo-gl – Implements WebGL for react-native
295 stars 73 forks source link

Any way to use OrbitControls from THREE.JS? #64

Closed vpsantos closed 4 years ago

vpsantos commented 6 years ago

Hi guys, I am testing the THREE.JS here and it is working, but I was wondering if would be possible to use the OrbitControls (rotate, zoom, etc) from THREE.JS at the camera with react-native-webgl. Is there any way to make it work instead of handling the touches by React Native?

shokimble commented 6 years ago

I'm still trying to get three.js to actually render something but I have done some digging in anticipation.

You shouldn't need to reimplement orbitcontrols, just wrap your context component in this and it should pass the events in properly and three.js can respond to them.

https://github.com/EvanBacon/expo-three-template/blob/master/window/Touches.js

robertjuh commented 6 years ago

Awesome, please let us know if you can actually render something in THREEjs (without expo), that would be of so much help!

shokimble commented 6 years ago

I got it working. NFI how I did. I copied someone else's code that didn't seem to do anything different.

Working on orbitcontrols shortly. Firstly I'm working out how to load models. It seems they've done a lot of work on the expo project to get three working that I don't particularly want to have to redo but it seems they've wound in expo so tightly for no particular reason that I don't have much choice.

Not opposed to expo as such but I don't want to have to double the size of my app store binary just to use webgl.

robertjuh commented 6 years ago

Could you please share some code or maybe the entire project? If that's no problem for you.

shokimble commented 6 years ago

This page has enough info to get the spinning cube example. Make sure you follow instructions for react-native-webgl installation in this repo's readme as well.

http://mkumaran.net/blog/2018/03/create-3d-model-in-react-native-using-webgl-and-three-js/

I'll post a writeup on the whole install, loading models, touch controls etc etc when I'm there.

robertjuh commented 6 years ago

Awesome! thanks a ton!

shokimble commented 6 years ago

I'm starting to tear my hair out here. This gist should in theory load an obj in and it's mtl and even load textures using the loader in react-native-webgl but I always end up with a black model.

If I look at the logs it's all happening in the background but what is rendered is wrong

https://gist.github.com/shokimble/c75d559e79e1a564097ba95e2dc31ce6

The example in the gist doesn't even load in textures and still doesn't work! It's not a problem with the scene or camera or lighting as you can uncomment the cube setup and it will spin a cube from the demo no problems.

Can I pay someone in beer to resolve this for me? I'm getting to the point of cash but beer seems more friendly :)

shokimble commented 6 years ago

I gave up BTW and have been using this instead:

https://github.com/rastapasta/react-native-gl-model-view/

It lets you load in a basic model and texture and the example show how to add pan controls to it. There's some problems on Android but I fixed them and submitting a PR.

Unfortunately it was just impossible to debug what was going on. Everything appeared to be working as expected but the textures were never being applied to the models. Neither in iOS nor Android.

robertjuh commented 6 years ago

yea it seems impossible to debug because of the webglrenderingcontext. So when the WebGLView is disabled, debugging is possible, but have no webglrenderingcontext.

When it wants to apply a texture in THREEjs it uses 'TextureLoader' which in turn uses an 'imageloader'. The imageloader makes an IMG dom element by using the 'document' object, and because react native doesnt have a 'document' object because it doesnt use a browser, it will fail there.

shokimble commented 6 years ago

When it wants to apply a texture in THREEjs it uses 'TextureLoader' which in turn uses an 'imageloader'. The imageloader makes an IMG dom element by using the 'document' object, and because react native doesnt have a 'document' object because it doesnt use a browser, it will fail there.

Yeah I got that same issue and tried using a shim/polyfill and loading the textures using rngl.loadTexture you can see it in the gist posted earlier (https://gist.github.com/shokimble/c75d559e79e1a564097ba95e2dc31ce6) but it still refuses to display the textures. Just a blank model even though by all indications the texture has loaded.

whatisor commented 6 years ago

You need to override load textutre function: function loadTexture(src, onLoad) { var textureThreeJS = new THREE.Texture(); var properties = renderer.properties.get(textureThreeJS); gl .getExtension('RN') .loadTexture({ yflip: true, image: src }) .then(({ texture }) => { properties.webglTexture = texture; properties.webglInit = true; texture.needsUpdate = true; if(onLoad)onLoad(textureThreeJS); }); }; THREE.TextureLoader.prototype.load = loadTexture;

And remember to require material to update, for example: //var material=....;//your material; var loader = new THREE.TextureLoader(); loader.load(imageSrc,function(tex){ material.map = tex; material.needsUpdate = true; })

shokimble commented 6 years ago

That's what I had in my gist. It doesn't work.

Have you managed to get it working ?

whatisor commented 6 years ago

Ofcourse, that is the reason I posted here :) I think I modified some small details

nathanfrad commented 6 years ago

Did you succeed in controlling three.js camera? I tried the three-orbit-controls library ( npm) ,and the controls in three.js such as DeviceOrientationControls.js and OrbitControls.js ... Nothing works and displays no error..

The scene contains a camera, a rotating SphereGeometry (earth) and a SphereBufferGeometry (sky). And the textures work.


import React, {Component} from "react";
import {Platform, StyleSheet, Text, View, ImageBackground, Animated} from "react-native";
import {WebGLView} from "react-native-webgl";
import THREE from "../../three";
import OrbitControls from "/Users/nathan/IdeaProjects/Open-Stars-Application2/src/Planetarium3D/js/libs/controls/OrbitControls.js"
import OrientationControls from "/Users/nathan/IdeaProjects/Open-Stars-Application2/src/Planetarium3D/js/libs/controls/DeviceOrientationControls.js"

//var THREE = require('three')
var ThreeOrbitControls = require('three-orbit-controls')(THREE)

type Props = {};
export default class MenuOrbit extends Component<Props> {
    constructor(props) {
        super(props);
    }

    render() {
        return (
            <View>
                <WebGLView style={{width: 400, height: 500}} onContextCreate={this.onContextCreate}/>
            </View>

        );
    }

    onContextCreate = async (gl: WebGLRenderingContext) => {
        const rngl = gl.getExtension("RN");
        const {drawingBufferWidth: width, drawingBufferHeight: height} = gl;
        const renderer = new THREE.WebGLRenderer({
            canvas:  {
                width,
                height,
                style: {},
                addEventListener: () => {
                },
                removeEventListener: () => {
                },
                clientHeight: height
            },
            context: gl
        });

        renderer.setSize(width, height);
        renderer.setClearColor(0xffffff, 1);

        let camera, scene , controls, sphere;

        function init() {
            scene = new THREE.Scene();

            camera = new THREE.PerspectiveCamera(75, width / height, 1, 1100);
            camera.position.y = 0;
            camera.position.z = 200;
            camera.lookAt(new THREE.Vector3(0,0,0));

            //  Earth
            let geometry = new THREE.SphereGeometry(32, 32, 32);
            //texture
            let file =  require( '../images/earthmap.jpg' );
            let tileImage = file;
            let material = loadTexture(tileImage);
            sphere = new THREE.Mesh(geometry, material);
            sphere.position.y = 0;
            scene.add(sphere);

            //  sky
            let geometrysky = new THREE.SphereBufferGeometry(500, 60, 40);
            geometrysky.scale(-1, 1, 1);
           // texture
            let filesky =  require( '/Users/nathan/IdeaProjects/Open-Stars-Application2/src/Planetarium3D/textures/stars_bg.png' );
            let tileImagesky = filesky;
            let materialsky = loadTexture(tileImagesky);
            sky = new THREE.Mesh(geometrysky, materialsky);
            sky.position.y = 0;
            scene.add(sky);

            scene.add(new THREE.AxesHelper(8000));

            // control de base avec la lib three
            // controls = new THREEOrbitControls(camera);

            //control en utilisant la lib three-orbit-controls
            controls = new ThreeOrbitControls( camera , renderer.domElement);
            this.controls = controls;
            //Orientcontrols = new OrientationControls( camera );
            controls.update();
        }

        init();

        const render = () => {
            requestAnimationFrame(render);

            sphere.rotation.y += 0.006;
            sphere.rotation.x += 0.004;
            sphere.rotation.z += 0.003;
            controls.update();
            renderer.render(scene, camera);

            gl.flush();
            rngl.endFrame();
        };
        render();

        function loadTexture(src) {
            let texture = new THREE.Texture();
            let material = new THREE.MeshBasicMaterial({map: texture, overdraw: 0.5});
            var properties = renderer.properties.get(texture);
            rngl.loadTexture({yflip: false, image: src})
                .then(({texture}) => {
                    properties.__webglTexture = texture;
                    properties.__webglInit = true;
                    texture.needsUpdate = true;
                });
            console.warn()
            return material;
        }

    };

}
ashp07 commented 5 years ago

This page has enough info to get the spinning cube example. Make sure you follow instructions for react-native-webgl installation in this repo's readme as well.

http://mkumaran.net/blog/2018/03/create-3d-model-in-react-native-using-webgl-and-three-js/

I'll post a writeup on the whole install, loading models, touch controls etc etc when I'm there.

That URL got changed, below is the updated URL http://mkumaran.net/first/07-3dmodel-reactnative-threejs/