Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
11
Help us understand the problem. What is going on with this article?
@nabehide

three.jsをスマホアプリで動かして暖をとる(react-native-webglの導入手順)

追記

react-native-webgl は deprecated となりました...

RNの新しいバージョンではreact-native-webglは動かないと思うので、お勧めされているexpo-glを使いましょう!

はじめに

この記事では、react-native-webglというライブラリの導入手順について書きます。

react-native-webglは、React NativeWebGLを使うためのライブラリです。
これを使えばネイティブアプリでthree.jsが使えるようになるので、試しに作ってみました!

とりあえずスマホカイロにしてみましたが、誰かかっこいいアプリ作ってくれないかな・・・

iOS: https://itunes.apple.com/us/app/three-js-native/id1447928256
Android: https://play.google.com/store/apps/details?id=com.three

Simulator Screen Shot - iPhone 8 Plus - 2019-02-06 at 20.52.51.png Simulator Screen Shot - iPhone 8 Plus - 2019-02-06 at 21.02.12.png

  • アプリ内の4種類のシーンのうち、Octahedronをたくさん表示するものが一番あったまれます。
  • segments(ポリゴンの分割数)などのパラメータは、最大にするとメモリが足らずアプリが落ちることがありますので、徐々に上げてみてください。

React Nativeの準備

公式のgetting-started通りに準備しましょう。
今回はexpoを使わないので、”Quick Start”ではなく、”Building Projects with Native Code”のタブに従ってください。

react-native-webglのインストール

React Nativeの最新はこの記事の執筆時点で0.58ですが、このバージョンではビルドが通らないため、0.57にします。

# init
react-native init threejsNative --version 0.57
cd threejsNative

その後、react-native-webglのパッケージをインストールしてリンクします。

yarn add react-native-webgl
react-native link react-native-webgl

iOS

New Build SystemではGPUImageというプロジェクト周りでエラーが出てしまうため、Legacy Build Systemに変更します。

File -> Workspace Settings... -> Build System -> Legacy Build System

Screen Shot 2019-02-08 at 1.35.54.png
Screen Shot 2019-02-08 at 1.36.12.png

Android

issueを読みつつ諸々を書き換えます。

android/build.gradle
  buildscript {

    ext {

-     minSdkVersion = 16
+     minSdkVersion = 17

    }

    dependencies {

+     classpath 'de.undercouch:gradle-download-task:3.1.2'

    }
node_modules/react-native-webgl/android/src/main/jni/Application.mk
- APP_PLATFORM := android-9
+ APP_PLATFORM := android-16

- APP_STL := gnustl_shared
+ APP_STL := c++_shared

- NDK_TOOLCHAIN_VERSION := 4.9
node_modules/react-native-webgl/android/build.gradle
  task packageRNWebGLLibs(dependsOn: buildRNWebGLLib, type: Copy) {

-   exclude '**/gnustl_shared.so'
+   exclude '**/libc++_shared.so'

  }

  android {

-   buildToolsVersion '25.0.0'
+   buildToolsVersion '27.0.3'

  }

  dependencies {
-   compile "com.facebook.react:react-native:+"  // From node_modules
+   implementation "com.facebook.react:react-native:+"  // From node_modules
  }

exclude '**/libc++_shared.so'でビルドが通らない時はinclude '**/libc++_shared.so'でうまくいく場合があります。

three.jsを読み込む

あとは公式のexampleの通りです。

yarn add three
three.js
const THREE = require("three");
global.THREE = THREE;
if (!window.addEventListener)
    window.addEventListener = () => { };
require("three/examples/js/renderers/Projector");
export default THREE;
App.js
import React from "react";
import { View } from "react-native";
import { WebGLView } from "react-native-webgl";
import THREE from "./three";

export default class App extends React.Component {
  requestId: *;
  componentWillUnmount() {
    cancelAnimationFrame(this.requestId);
  }
  onContextCreate = (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(0x000000, 1);

    let camera, scene;
    let cube;

    function init() {
      // ここにcameraやsceneのコードを書く
      camera = new THREE.PerspectiveCamera(75, width / height, 1, 1100);
      camera.position.y = 150;
      camera.position.z = 500;
      scene = new THREE.Scene();

      let geometry = new THREE.BoxGeometry(200, 200, 200);
      for (let i = 0; i < geometry.faces.length; i += 2) {
        let hex = Math.random() * 0xffffff;
        geometry.faces[i].color.setHex(hex);
        geometry.faces[i + 1].color.setHex(hex);
      }

      let material = new THREE.MeshBasicMaterial({
        vertexColors: THREE.FaceColors,
        overdraw: 0.5
      });

      cube = new THREE.Mesh(geometry, material);
      cube.position.y = 150;
      scene.add(cube);
    }
    const animate = () => {
      this.requestId = requestAnimationFrame(animate);
      renderer.render(scene, camera);

      // ここにアニメーションのコードを書く
      cube.rotation.y += 0.05;

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

    init();
    animate();
  };
  render() {
    return (
      <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
        <WebGLView
          style={{ width: 300, height: 300 }}
          onContextCreate={this.onContextCreate}
        />
      </View>
    );
  }
}

three.jsの部分は通常とほとんど同じように書けます!

実行

iOS/Androidそれぞれでオブジェクトが表示されれば成功です。

react-native run-ios
react-native run-android

まとめ

react-native-webglを使って、スマホアプリでthree.jsを動かす方法について書きました。
three.jsを使ったかっこいいアプリがさらに増えていくと嬉しいですね!

11
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
nabehide
Music, Programming, Web, Native app, Generative art Nuxt.js, React.js, React Native, Unity

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
11
Help us understand the problem. What is going on with this article?