diff --git a/.travis.yml b/.travis.yml index ddd64795fb..176c4ea852 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,7 +54,7 @@ matrix: - docker pull debian:latest install: - docker build -f android.Dockerfile -t exokit . - - docker run exokit cat exokit.apk >exokit.apk + - docker run exokit cat exokit.apk >exokit-oculusmobile.apk script: - echo "skipping 'npm run test' outside of docker" deploy: diff --git a/android/app/build.gradle b/android/app/googlevr-build.gradle similarity index 84% rename from android/app/build.gradle rename to android/app/googlevr-build.gradle index 3d08f5e86f..1562a9d44d 100644 --- a/android/app/build.gradle +++ b/android/app/googlevr-build.gradle @@ -36,7 +36,7 @@ android { externalNativeBuild { cmake { // version '3.10.2' - path '../CMakeLists.txt' + path '../googlevr-CMakeLists.txt' } } lintOptions { @@ -45,13 +45,14 @@ android { } -/* dependencies { - implementation 'com.google.vr:sdk-base:1.190.0' +dependencies { + // Adds Google VR spatial audio support + compile 'com.google.vr:sdk-audio:1.160.0' + + // Required for all Google VR apps + compile 'com.google.vr:sdk-base:1.160.0' +} - // Obj - a simple Wavefront OBJ file loader - // https://github.com/javagl/Obj - implementation 'de.javagl:obj:0.2.1' -} */ android { sourceSets { diff --git a/android/app/oculusmobile-build.gradle b/android/app/oculusmobile-build.gradle new file mode 100644 index 0000000000..ef0c01f744 --- /dev/null +++ b/android/app/oculusmobile-build.gradle @@ -0,0 +1,54 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 21 + // Sceneform libraries use language constructs from Java 8. + // Add these compile options if targeting minSdkVersion < 26. + compileOptions { + sourceCompatibility 1.8 + targetCompatibility 1.8 + } + + + defaultConfig { + applicationId = 'com.webmr.exokit' + minSdkVersion 21 + targetSdkVersion 21 + externalNativeBuild { + cmake { + arguments '-DANDROID_STL=c++_static' + cppFlags "-std=c++11" + } + } + ndk { + // Specifies the ABI configurations of your native + // libraries Gradle should build and package with your APK. + abiFilters 'arm64-v8a' + } + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), + 'proguard-rules.pro' + } + } + externalNativeBuild { + cmake { + // version '3.10.2' + path '../oculusmobile-CMakeLists.txt' + } + } + lintOptions { + abortOnError false + } +} + +android { + sourceSets { + main { + assets.srcDirs = ['assets'] + jniLibs.srcDirs = ['assets/node_modules/native-oculus-mobile-deps/lib/android'] + } + } +} diff --git a/android/app/src/main/googlevr-AndroidManifest.xml b/android/app/src/main/googlevr-AndroidManifest.xml new file mode 100644 index 0000000000..29a85cc85b --- /dev/null +++ b/android/app/src/main/googlevr-AndroidManifest.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/oculusmobile-AndroidManifest.xml similarity index 100% rename from android/app/src/main/AndroidManifest.xml rename to android/app/src/main/oculusmobile-AndroidManifest.xml diff --git a/android/googlevr-CMakeLists.txt b/android/googlevr-CMakeLists.txt new file mode 100644 index 0000000000..ab7d62d67f --- /dev/null +++ b/android/googlevr-CMakeLists.txt @@ -0,0 +1,67 @@ +cmake_minimum_required(VERSION 3.6.0) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -Wall -Werror") +add_library(native-main SHARED ${CMAKE_SOURCE_DIR}/../main.cpp ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) + +include_directories( SYSTEM ${CMAKE_SOURCE_DIR}/../node_modules/nan ) +include_directories( SYSTEM ${CMAKE_SOURCE_DIR}/../deps/exokit-bindings/util/include ) +include_directories( SYSTEM ${CMAKE_SOURCE_DIR}/../.node-gyp/11.6.0/include/node ) +include_directories( SYSTEM ${CMAKE_SOURCE_DIR}/../build/libexokit ) +include_directories( SYSTEM ${ANDROID_NDK}/sources/android/native_app_glue ) + +add_library( exokit STATIC IMPORTED ) +set_target_properties( exokit PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../build/libexokit/libexokit.a ) + +add_library( node STATIC IMPORTED ) +set_target_properties( node PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../node_modules/libnode.a-android/libnode.a ) + +add_library( skia STATIC IMPORTED ) +set_target_properties( skia PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../node_modules/native-canvas-deps/lib2/magicleap/libskia.a ) + +add_library( labsound STATIC IMPORTED ) +set_target_properties( labsound PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../node_modules/native-audio-deps/lib2/magicleap/libLabSound.a ) + +add_library( avformat STATIC IMPORTED ) +set_target_properties( avformat PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../node_modules/native-video-deps/lib2/magicleap/libavformat.a ) +add_library( avcodec STATIC IMPORTED ) +set_target_properties( avcodec PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../node_modules/native-video-deps/lib2/magicleap/libavcodec.a ) +add_library( avutil STATIC IMPORTED ) +set_target_properties( avutil PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../node_modules/native-video-deps/lib2/magicleap/libavutil.a ) +add_library( avdevice STATIC IMPORTED ) +set_target_properties( avdevice PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../node_modules/native-video-deps/lib2/magicleap/libavdevice.a ) +add_library( swscale STATIC IMPORTED ) +set_target_properties( swscale PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../node_modules/native-video-deps/lib2/magicleap/libswscale.a ) +add_library( swresample STATIC IMPORTED ) +set_target_properties( swresample PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../node_modules/native-video-deps/lib2/magicleap/libswresample.a ) +add_library( opus STATIC IMPORTED ) +set_target_properties( opus PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../node_modules/native-video-deps/lib2/magicleap/libopus.a ) + +add_library( webrtc STATIC IMPORTED ) +set_target_properties( webrtc PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../node_modules/native-webrtc-deps/lib2/magicleap/libwebrtc.a ) + +add_library( gvr-lib SHARED IMPORTED ) +set_target_properties( gvr-lib PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../node_modules/native-googlevr-deps/lib/android/arm64-v8a/libgvr.so ) +add_library( gvraudio-lib SHARED IMPORTED ) +set_target_properties( gvraudio-lib PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../node_modules/native-googlevr-deps/lib/android/arm64-v8a/libgvr_audio.so ) + +target_link_libraries(native-main + android + log + EGL + GLESv2 + exokit + node + skia + labsound + avformat + avcodec + avutil + avdevice + swscale + swresample + opus + webrtc + OpenSLES + gvr-lib + gvraudio-lib +) diff --git a/android/googlevr-build.gradle b/android/googlevr-build.gradle new file mode 100644 index 0000000000..c2123bc5ee --- /dev/null +++ b/android/googlevr-build.gradle @@ -0,0 +1,31 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + repositories { + google() + jcenter() + maven { + url "https://maven.google.com" + } + } +} + +allprojects { + repositories { + google() + jcenter() + maven { + // For Android support library components. + url "https://maven.google.com" + } + // You can also use a local Maven repository if desired. + mavenLocal() + } + dependencies { + // The Google VR SDK requires version 2.3.3 or higher. + classpath 'com.android.tools.build:gradle:3.3.2' + + // The Google VR NDK requires experimental version 0.9.3 or higher. + // classpath 'com.android.tools.build:gradle-experimental:0.9.3' + } + +} diff --git a/android/CMakeLists.txt b/android/oculusmobile-CMakeLists.txt similarity index 100% rename from android/CMakeLists.txt rename to android/oculusmobile-CMakeLists.txt diff --git a/android/build.gradle b/android/oculusmobile-build.gradle similarity index 99% rename from android/build.gradle rename to android/oculusmobile-build.gradle index 91caed3adb..118f523255 100644 --- a/android/build.gradle +++ b/android/oculusmobile-build.gradle @@ -24,4 +24,3 @@ allprojects { mavenLocal() } } - diff --git a/binding.gyp b/binding.gyp index 5020e7c9c5..553db629cf 100644 --- a/binding.gyp +++ b/binding.gyp @@ -566,7 +566,7 @@ 'WEBRTC_POSIX', ], }], - ['" +#include +#include +#include + +namespace googlevr { + +extern ovrJava java; + +class GoogleVrContext : public ObjectWrap { +public: + static Local Initialize(); + + void RequestPresent(); + static void handleAppCmd(struct android_app *app, int32_t cmd); + void CreateSwapChain(WebGLRenderingContext *gl, int width, int height); + void PollEvents(bool wait); + + static NAN_METHOD(New); + void Destroy(); + + static NAN_METHOD(WaitGetPoses); + static NAN_METHOD(Submit); + static NAN_METHOD(GetRecommendedRenderTargetSize); + + GoogleVrContext(NATIVEwindow *windowHandle); + ~GoogleVrContext(); + +// protected: + NATIVEwindow *windowHandle; + // ovrMobile *ovrState; + bool running; + ANativeWindow *androidNativeWindow; + // ovrTextureSwapChain *swapChains[2]; + int swapChainMetrics[2]; + int swapChainLength; + int swapChainIndex; + bool hasSwapChain; + GLuint fboId; + ovrTracking2 tracking; + long long frameIndex; + double displayTime; + int swapInterval; +}; + +} + +#endif diff --git a/deps/googlevr/include/googlevr-math.h b/deps/googlevr/include/googlevr-math.h new file mode 100644 index 0000000000..0b3961da20 --- /dev/null +++ b/deps/googlevr/include/googlevr-math.h @@ -0,0 +1,11 @@ +#ifndef _GOOGLEVR_MATH_H_ +#define _GOOGLEVR_MATH_H_ + +#include + +namespace googlevr { + + +} + +#endif diff --git a/deps/googlevr/include/googlevr.h b/deps/googlevr/include/googlevr.h new file mode 100644 index 0000000000..66f3be7f3a --- /dev/null +++ b/deps/googlevr/include/googlevr.h @@ -0,0 +1,39 @@ +#ifndef _GOOGLEVR_H_ +#define _GOOGLEVR_H_ + +#include +#include + +#include + +#include +#include +#include + +#include "gvr.h" +#include "gvr_audio.h" +#include "gvr_audio_surround.h" +#include "gvr_beta.h" +#include "gvr_controller.h" +#include "gvr_gesture.h" +#include "gvr_types.h" +#include "gvr_version.h" + +using namespace v8; + +extern struct android_app *androidApp; +extern JNIEnv *androidJniEnv; + +namespace googlevr { + +extern Nan::Persistent googleVrContextConstructor; +extern Nan::Persistent googleVrContext; + +NAN_METHOD(GoogleVr_Init); +NAN_METHOD(GoogleVr_IsHmdPresent); + +} + +Local makeGoogleVr(); + +#endif diff --git a/deps/googlevr/src/googlevr-math.cpp b/deps/googlevr/src/googlevr-math.cpp new file mode 100644 index 0000000000..cd9a73aaa6 --- /dev/null +++ b/deps/googlevr/src/googlevr-math.cpp @@ -0,0 +1,10 @@ +#if defined(ANDROID) + +#include + +namespace googlevr { + + +} + +#endif diff --git a/deps/googlevr/src/googlevr.cpp b/deps/googlevr/src/googlevr.cpp new file mode 100644 index 0000000000..f1f9c86d4f --- /dev/null +++ b/deps/googlevr/src/googlevr.cpp @@ -0,0 +1,72 @@ +#ifdef ANDROID + +#include +#include +#include + +#include +#include + +#include +#include + +namespace googlevr { + +Nan::Persistent googleVrContextConstructor; +Nan::Persistent googleVrContext; + +NAN_METHOD(GoogleVr_Init) { + std::cout << "GoogleVr_Init 1" << std::endl; + + Local windowHandleArray = Local::Cast(info[0]); + + if (googleVrContextConstructor.IsEmpty()) { + googleVrContextConstructor.Reset(GoogleVrContext::Initialize()); + } + + Local localGoogleVrContextConstructor = Nan::New(googleVrContextConstructor); + Local argv[] = { + windowHandleArray, + }; + Local googleVrContextObj = localGoogleVrContextConstructor->NewInstance(Isolate::GetCurrent()->GetCurrentContext(), sizeof(argv)/sizeof(argv[0]), argv).ToLocalChecked(); + // Local googleVrContextObj = localGoogleVrContextConstructor->NewInstance(Isolate::GetCurrent()->GetCurrentContext(), 0, nullptr).ToLocalChecked(); + googleVrContext.Reset(googleVrContextObj); + + GoogleVrContext *omc = ObjectWrap::Unwrap(googleVrContextObj); + omc->RequestPresent(); + + info.GetReturnValue().Set(googleVrContextObj); +} + +NAN_METHOD(GoogleVr_Shutdown) { + std::cout << "GoogleVr_Shutdown" << std::endl; + + Local googleVrContextObj = Nan::New(googleVrContext); + GoogleVrContext *omc = ObjectWrap::Unwrap(googleVrContextObj); + omc->Destroy(); + googleVrContext.Reset(); + + // gvr_Shutdown(); +} + +NAN_METHOD(GoogleVr_IsHmdPresent) { + std::cout << "GoogleVr_IsHmdPresent" << std::endl; + + info.GetReturnValue().Set(Nan::New(true)); +} + +} + +Local makeGoogleVrVr() { + v8::EscapableHandleScope scope(Isolate::GetCurrent()); + + Local exports = Object::New(Isolate::GetCurrent()); + + exports->Set(Nan::New("GoogleVr_Init").ToLocalChecked(), Nan::New(googlevr::GoogleVr_Init)->GetFunction()); + exports->Set(Nan::New("GoogleVr_Shutdown").ToLocalChecked(), Nan::New(googlevr::GoogleVr_Shutdown)->GetFunction()); + exports->Set(Nan::New("GoogleVr_IsHmdPresent").ToLocalChecked(), Nan::New(googlevr::GoogleVr_IsHmdPresent)->GetFunction()); + + return scope.Escape(exports); +} + +#endif diff --git a/exokit.cpp b/exokit.cpp index d3455e573c..ce45b02870 100644 --- a/exokit.cpp +++ b/exokit.cpp @@ -12,7 +12,7 @@ #ifdef OPENVR #include #endif -#ifdef ANDROID +#if defined(ANDROID) && defined(OCULUSMOBILE) #include #endif @@ -211,7 +211,7 @@ void InitExports(Local exports) { exports->Set(v8::String::NewFromUtf8(Isolate::GetCurrent(), "nativeLm"), lm); #endif -#ifdef ANDROID +#if defined(ANDROID) && defined(OCULUSMOBILE) Local oculusMobileVr = makeOculusMobileVr(); exports->Set(v8::String::NewFromUtf8(Isolate::GetCurrent(), "nativeOculusMobileVr"), oculusMobileVr); #endif diff --git a/package.json b/package.json index fae24e2919..5707bca3e1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "exokit", - "version": "0.0.520", + "version": "0.0.521", "description": "Native VR and AR engine for JavaScript", "engines": { "node": ">=10.0.0" @@ -72,6 +72,7 @@ "native-graphics-deps": "0.0.20", "native-oculus-deps": "0.0.2", "native-oculus-mobile-deps": "0.0.2", + "native-googlevr-deps": "0.0.1", "native-openvr-deps": "0.0.18", "native-video-deps": "0.0.35", "native-webrtc-deps": "0.0.45", diff --git a/scripts/build-android.sh b/scripts/build-googlevr-android.sh old mode 100755 new mode 100644 similarity index 96% rename from scripts/build-android.sh rename to scripts/build-googlevr-android.sh index 9d94eb1983..4a1a82ada3 --- a/scripts/build-android.sh +++ b/scripts/build-googlevr-android.sh @@ -28,6 +28,7 @@ export LD="$TOOLCHAIN/bin/aarch64-linux-android-ld" export OS="android" export ANDROID=1 +export GOOGLEVR=1 EXTRA_FLAGS="-I$TOOLCHAIN_INCLUDE_LIB -I$TOOLCHAIN_INCLUDE_SYSROOT" export CFLAGS="$CFLAGS $EXTRA_FLAGS" @@ -60,7 +61,7 @@ rsync -a --relative --copy-links build/Release/exokit.node ./android/app/assets/ # build apk pushd android -./gradlew build && ./gradlew assembleDebug +./gradlew build -b googlevr-build.gradle && ./gradlew assembleDebug popd # for debugging symbols lookup diff --git a/scripts/build-oculusmobile-android.sh b/scripts/build-oculusmobile-android.sh new file mode 100644 index 0000000000..28d4b1cec7 --- /dev/null +++ b/scripts/build-oculusmobile-android.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +# Initialization. + +set -e + +# Preface. + +TOOLCHAIN="$ANDROID_HOME/ndk-bundle/toolchain" +cd "$(dirname "$0")" + +export TOOLCHAIN_USR="$TOOLCHAIN/sysroot/usr" +export TOOLCHAIN_LIB=$TOOLCHAIN/sysroot/usr/lib +export TOOLCHAIN_LIB_CXX=$TOOLCHAIN/aarch64-linux-android/lib +export TOOLCHAIN_LIB_64=$TOOLCHAIN/aarch64-linux-android/lib64 +#export TOOLCHAIN_INCLUDE_LIB=$TOOLCHAIN/include/c++/4.9.x +export TOOLCHAIN_INCLUDE_SYSROOT=$TOOLCHAIN/sysroot/usr/include +export LD_LIBRARY_PATH="./Release:.:$LD_LIBRARY_PATH" + +export CC_target="aarch64" +export GYP_CROSSCOMPILE=1 +export CLANG_CXX_LIBRARY="libstdc++" +export CC="$TOOLCHAIN/bin/aarch64-linux-android-clang" +export CXX="$TOOLCHAIN/bin/aarch64-linux-android-clang++" +export LINK="$TOOLCHAIN/bin/aarch64-linux-android-clang++" +export AR="$TOOLCHAIN/bin/aarch64-linux-android-ar" +export LD="$TOOLCHAIN/bin/aarch64-linux-android-ld" + +export OS="android" +export ANDROID=1 +export OCULUSMOBILE=1 + +EXTRA_FLAGS="-I$TOOLCHAIN_INCLUDE_LIB -I$TOOLCHAIN_INCLUDE_SYSROOT" +export CFLAGS="$CFLAGS $EXTRA_FLAGS" +export CXXFLAGS="$CXXFLAGS $EXTRA_FLAGS" +export LDFLAGS="" + +export npm_config_arch=aarch64 +export OS="android" +export TARGET_ARCH="aarch64" # For webrtc install prebuilt. + +pushd .. + +# build native modules +npm install --verbose --devdir="$(pwd)/.node-gyp" --arch=aarch64 --target_arch=aarch64 --no-optional + +# archive native module dlibs +mkdir -p build/libexokit +find build/Release/obj.target node_modules -name '*.o' | xargs "$AR" crs build/libexokit/libexokit.a +./scripts/gen-dlibs-h.js "$(pwd)" >build/libexokit/dlibs.h + +# copy assets for packaging +mkdir -p ./android/app/assets +rsync -a --copy-links package.json ./android/app/assets/package.json +rsync -a --copy-links src/ ./android/app/assets/src +rsync -a --copy-links lib/ ./android/app/assets/lib +rsync -a --copy-links examples/ ./android/app/assets/examples +rsync -a --copy-links node_modules/* ./android/app/assets/node_modules/ +rsync -a --relative --copy-links build/Release/exokit.node ./android/app/assets/ +./scripts/gen-assets-h.js >android/app/assets/index.bin + +# build apk +pushd android +./gradlew build -b oculusmobile-build.gradle && ./gradlew assembleDebug +popd + +# for debugging symbols lookup +mkdir -p android/app/src/main/arm64-v8a +rsync -a --copy-links android/app/build/intermediates/cmake/debug/obj/arm64-v8a/libnative-main.so android/app/src/main/arm64-v8a/libnative-main.so + +popd