├── .gitignore ├── README.md ├── apk ├── app-debug.apk ├── app-malivr-debug.apk ├── app-rajawali-debug.apk └── app-vrwidget-debug.apk ├── app-malivr ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ ├── cube.fs │ ├── cube.vs │ ├── distort.fs │ └── distort.vs │ ├── java │ └── org │ │ └── babysource │ │ └── vrdroid │ │ ├── VRDroid.java │ │ └── VRDroidView.java │ ├── jni │ ├── armvr.cpp │ ├── armvr.h │ ├── loader.cpp │ ├── main.cpp │ └── matrix.h │ └── res │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── app-rajawali ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── org │ │ └── babysource │ │ └── vrdroid │ │ ├── VRDroidLister.java │ │ ├── VRDroidPlayer.java │ │ └── render │ │ └── VRDroidRender.java │ └── res │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── app-vrwidget ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── org │ │ └── babysource │ │ └── vrdroid │ │ ├── VRDroidLister.java │ │ └── VRDroidPlayer.java │ └── res │ ├── layout │ ├── droid_item.xml │ ├── droid_lister.xml │ └── droid_player.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── org │ │ └── babysource │ │ └── vrdroid │ │ ├── VRDroidBuilder.java │ │ ├── VRDroidCamera.java │ │ └── VRDroidCamera2.java │ └── res │ ├── layout │ └── droid_lister.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── libraries ├── audio │ ├── audio.aar │ └── build.gradle ├── base │ ├── base.aar │ └── build.gradle ├── common │ ├── build.gradle │ └── common.aar ├── commonwidget │ ├── build.gradle │ └── commonwidget.aar ├── controller │ ├── build.gradle │ └── controller.aar ├── panowidget │ ├── build.gradle │ └── panowidget.aar └── videowidget │ ├── build.gradle │ └── videowidget.aar └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | Thumbs.db 3 | /.idea 4 | /bin 5 | /build 6 | /captures 7 | /local.properties 8 | .gradle 9 | *.iml 10 | *.ipr 11 | *.iws -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VRDroid 2 | VR Player for android 3 | 4 | # 项目简介 5 | 6 | VR相关探索研究项目,长期关注VR前沿动态,及时跟进最新VR开发技术; 7 | 8 | # 模块简介 9 | 10 | [app] 11 | 12 | VR摄像头偷窥APP;(实现通过Camera api v1 and v2) 13 | 14 | [app-malivr]: 15 | 16 | Malivr Demo;(适用于:An ARM based development board with a Mali series GPU running Android.) 17 | 18 | [app-rajawali]: 19 | 20 | Rajawali3D引擎实现VR 360°全景视频播放; 21 | 22 | [app-vrwidget]: 23 | 24 | GvrView v1.0.3实现VR 360°全景视频播放; -------------------------------------------------------------------------------- /apk/app-debug.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/apk/app-debug.apk -------------------------------------------------------------------------------- /apk/app-malivr-debug.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/apk/app-malivr-debug.apk -------------------------------------------------------------------------------- /apk/app-rajawali-debug.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/apk/app-rajawali-debug.apk -------------------------------------------------------------------------------- /apk/app-vrwidget-debug.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/apk/app-vrwidget-debug.apk -------------------------------------------------------------------------------- /app-malivr/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app-malivr/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.model.application' 2 | 3 | model { 4 | android { 5 | compileSdkVersion = 23 6 | buildToolsVersion = '23.0.3' 7 | 8 | defaultConfig.with { 9 | applicationId = 'com.babysource.vrdroid.malivr' 10 | minSdkVersion.apiLevel = 16 11 | targetSdkVersion.apiLevel = 23 12 | } 13 | } 14 | 15 | android.ndk { 16 | platformVersion = '19' 17 | moduleName = 'Native' 18 | stl = 'stlport_static' 19 | abiFilters.add('armeabi-v7a') 20 | CFlags.add('-Werror') 21 | ldLibs.addAll(['log', 'GLESv3', 'EGL', 'm']) 22 | } 23 | 24 | android.sources { 25 | main { 26 | jni { 27 | source { 28 | exclude 'armvr.cpp' 29 | exclude 'loader.cpp' 30 | } 31 | } 32 | } 33 | } 34 | 35 | android.buildTypes { 36 | debug { 37 | debuggable = true 38 | minifyEnabled = false 39 | multiDexEnabled = false 40 | shrinkResources = false 41 | zipAlignEnabled = true 42 | } 43 | release { 44 | debuggable = false 45 | minifyEnabled = false 46 | multiDexEnabled = false 47 | shrinkResources = true 48 | zipAlignEnabled = true 49 | proguardFiles.add(file('proguard-rules.pro')) 50 | } 51 | } 52 | 53 | android.packagingOptions { 54 | exclude 'META-INF/DEPENDENCIES' 55 | exclude 'META-INF/LICENSE.txt' 56 | exclude 'META-INF/LICENSE' 57 | exclude 'META-INF/NOTICE.txt' 58 | exclude 'META-INF/NOTICE' 59 | } 60 | 61 | android.lintOptions { 62 | abortOnError = false 63 | } 64 | } 65 | 66 | dependencies { 67 | compile 'com.android.support:appcompat-v7:23.2.1' 68 | } 69 | -------------------------------------------------------------------------------- /app-malivr/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\adt-bundle-windows-x86_64-20131030\Android_Studio_sdk\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app-malivr/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 20 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /app-malivr/src/main/assets/cube.fs: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | // This proprietary software may be used only as 3 | // authorised by a licensing agreement from ARM Limited 4 | // (C) COPYRIGHT 2015 ARM Limited 5 | // ALL RIGHTS RESERVED 6 | // The entire notice above must be reproduced on all authorised 7 | // copies and copies may only be made to the extent permitted 8 | // by a licensing agreement from ARM Limited. 9 | precision highp float; 10 | 11 | in vec3 v_position; 12 | in vec3 v_normal; 13 | in float v_depth; 14 | out vec4 f_color; 15 | 16 | vec3 light(vec3 n, vec3 l, vec3 c) 17 | { 18 | float ndotl = max(dot(n, l), 0.0); 19 | return ndotl * c; 20 | } 21 | 22 | void main() 23 | { 24 | vec3 albedo = vec3(0.95, 0.84, 0.62); 25 | vec3 n = normalize(v_normal); 26 | f_color.rgb = vec3(0.0); 27 | f_color.rgb += light(n, normalize(vec3(1.0)), vec3(1.0)); 28 | f_color.rgb += light(n, normalize(vec3(-1.0, -1.0, 0.0)), vec3(0.2, 0.23, 0.35)); 29 | 30 | // Fog 31 | f_color.rgb *= 1.0 - smoothstep(0.9, 10.0, v_depth); 32 | 33 | // Gamma 34 | f_color.rgb = sqrt(f_color.rgb); 35 | 36 | f_color.a = 1.0; 37 | } 38 | -------------------------------------------------------------------------------- /app-malivr/src/main/assets/cube.vs: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | #extension GL_OVR_multiview2 : enable 3 | // This proprietary software may be used only as 4 | // authorised by a licensing agreement from ARM Limited 5 | // (C) COPYRIGHT 2015 ARM Limited 6 | // ALL RIGHTS RESERVED 7 | // The entire notice above must be reproduced on all authorised 8 | // copies and copies may only be made to the extent permitted 9 | // by a licensing agreement from ARM Limited. 10 | 11 | layout(num_views = 4) in; 12 | 13 | in vec3 position; 14 | in vec3 normal; 15 | uniform mat4 projection[4]; 16 | uniform mat4 view[4]; 17 | uniform mat4 model; 18 | out float v_depth; 19 | out vec3 v_position; 20 | out vec3 v_normal; 21 | 22 | void main() 23 | { 24 | vec4 view_pos = view[gl_ViewID_OVR] * model * vec4(position, 1.0); 25 | gl_Position = projection[gl_ViewID_OVR] * view_pos; 26 | v_normal = (view[gl_ViewID_OVR] * model * vec4(normal, 0.0)).xyz; 27 | v_depth = -view_pos.z; 28 | v_position = position; 29 | } 30 | -------------------------------------------------------------------------------- /app-malivr/src/main/assets/distort.fs: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | // This proprietary software may be used only as 3 | // authorised by a licensing agreement from ARM Limited 4 | // (C) COPYRIGHT 2015 ARM Limited 5 | // ALL RIGHTS RESERVED 6 | // The entire notice above must be reproduced on all authorised 7 | // copies and copies may only be made to the extent permitted 8 | // by a licensing agreement from ARM Limited. 9 | precision highp float; 10 | precision mediump int; 11 | precision mediump sampler2DArray; 12 | 13 | in vec2 texel_r_low_res; 14 | in vec2 texel_g_low_res; 15 | in vec2 texel_b_low_res; 16 | in vec2 texel_r_high_res; 17 | in vec2 texel_g_high_res; 18 | in vec2 texel_b_high_res; 19 | uniform sampler2DArray framebuffer; 20 | uniform int layer_index; 21 | out vec4 f_color; 22 | 23 | vec3 sample_per_channel(vec2 tex_coord_r, vec2 tex_coord_g, vec2 tex_coord_b, int layer) 24 | { 25 | vec3 sampled_color; 26 | sampled_color.r = texture(framebuffer, vec3(tex_coord_r, layer)).r; 27 | sampled_color.g = texture(framebuffer, vec3(tex_coord_g, layer)).g; 28 | sampled_color.b = texture(framebuffer, vec3(tex_coord_b, layer)).b; 29 | 30 | return sampled_color; 31 | } 32 | 33 | float interpolate_color(vec2 tex_coord, float low_res_color_val, float high_res_color_val) 34 | { 35 | // Using squared distance to middle of screen for interpolating. 36 | vec2 dist_vec = vec2(0.5) - tex_coord; 37 | float squared_dist = dot(dist_vec, dist_vec); 38 | // Using the high res texture when distance from center is less than 0.5 in texture coordinates (0.25 is 0.5 squared). 39 | // When the distance is less than 0.2 (0.04 is 0.2 squared), only the high res texture will be used. 40 | float lerp_val = smoothstep(-0.25, -0.4, -squared_dist); 41 | return mix(low_res_color_val, high_res_color_val, lerp_val); 42 | } 43 | 44 | void main() 45 | { 46 | vec3 low_res_color = sample_per_channel(texel_r_low_res, texel_g_low_res, texel_b_low_res, layer_index); 47 | vec3 high_res_color = sample_per_channel(texel_r_high_res, texel_g_high_res, texel_b_high_res, layer_index + 2); 48 | 49 | f_color.r = interpolate_color(texel_r_high_res, low_res_color.r, high_res_color.r); 50 | f_color.g = interpolate_color(texel_g_high_res, low_res_color.g, high_res_color.g); 51 | f_color.b = interpolate_color(texel_b_high_res, low_res_color.b, high_res_color.b); 52 | f_color.a = 1.0; 53 | } 54 | -------------------------------------------------------------------------------- /app-malivr/src/main/assets/distort.vs: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | // This proprietary software may be used only as 3 | // authorised by a licensing agreement from ARM Limited 4 | // (C) COPYRIGHT 2015 ARM Limited 5 | // ALL RIGHTS RESERVED 6 | // The entire notice above must be reproduced on all authorised 7 | // copies and copies may only be made to the extent permitted 8 | // by a licensing agreement from ARM Limited. 9 | 10 | in vec2 position; 11 | in vec2 uv_red_low_res; 12 | in vec2 uv_green_low_res; 13 | in vec2 uv_blue_low_res; 14 | in vec2 uv_red_high_res; 15 | in vec2 uv_green_high_res; 16 | in vec2 uv_blue_high_res; 17 | out vec2 texel_r_low_res; 18 | out vec2 texel_g_low_res; 19 | out vec2 texel_b_low_res; 20 | out vec2 texel_r_high_res; 21 | out vec2 texel_g_high_res; 22 | out vec2 texel_b_high_res; 23 | 24 | void main() 25 | { 26 | gl_Position = vec4(position, 0.0, 1.0); 27 | texel_r_low_res = uv_red_low_res; 28 | texel_g_low_res = uv_green_low_res; 29 | texel_b_low_res = uv_blue_low_res; 30 | texel_r_high_res = uv_red_high_res; 31 | texel_g_high_res = uv_green_high_res; 32 | texel_b_high_res = uv_blue_high_res; 33 | } 34 | -------------------------------------------------------------------------------- /app-malivr/src/main/java/org/babysource/vrdroid/VRDroid.java: -------------------------------------------------------------------------------- 1 | // This proprietary software may be used only as 2 | // authorised by a licensing agreement from ARM Limited 3 | // (C) COPYRIGHT 2015 ARM Limited 4 | // ALL RIGHTS RESERVED 5 | // The entire notice above must be reproduced on all authorised 6 | // copies and copies may only be made to the extent permitted 7 | // by a licensing agreement from ARM Limited. 8 | package org.babysource.vrdroid; 9 | 10 | import android.content.res.AssetManager; 11 | import android.app.Activity; 12 | import android.os.Bundle; 13 | import android.util.Log; 14 | 15 | import java.io.File; 16 | import java.io.InputStream; 17 | import java.io.RandomAccessFile; 18 | 19 | public class VRDroid extends Activity { 20 | 21 | VRDroidView mView; 22 | private static android.content.Context applicationContext = null; 23 | private static String assetsDirectory = null; 24 | private static String LOGTAG = "VRDroid"; 25 | 26 | @Override 27 | protected void onCreate(Bundle savedInstanceState) { 28 | super.onCreate(savedInstanceState); 29 | mView = new VRDroidView(getApplication()); 30 | setContentView(mView); 31 | 32 | applicationContext = getApplicationContext(); 33 | assetsDirectory = applicationContext.getFilesDir().getPath() + "/"; 34 | 35 | extractAsset("distort.vs"); 36 | extractAsset("distort.fs"); 37 | 38 | extractAsset("cube.vs"); 39 | extractAsset("cube.fs"); 40 | } 41 | 42 | @Override 43 | protected void onPause() { 44 | super.onPause(); 45 | mView.onPause(); 46 | } 47 | 48 | @Override 49 | protected void onResume() { 50 | super.onResume(); 51 | mView.onResume(); 52 | } 53 | 54 | private void extractAsset(String assetName) { 55 | File file = new File(assetsDirectory + assetName); 56 | 57 | if (file.exists()) { 58 | Log.d(LOGTAG, assetName + " already exists. No extraction needed.\n"); 59 | } else { 60 | Log.d(LOGTAG, assetName + " doesn't exist. Extraction needed. \n"); 61 | 62 | try { 63 | RandomAccessFile randomAccessFile = new RandomAccessFile(assetsDirectory + assetName, "rw"); 64 | AssetManager assetManager = applicationContext.getResources().getAssets(); 65 | InputStream inputStream = assetManager.open(assetName); 66 | 67 | byte buffer[] = new byte[1024]; 68 | int count = inputStream.read(buffer, 0, 1024); 69 | 70 | while (count > 0) { 71 | randomAccessFile.write(buffer, 0, count); 72 | 73 | count = inputStream.read(buffer, 0, 1024); 74 | } 75 | 76 | randomAccessFile.close(); 77 | inputStream.close(); 78 | } catch (Exception e) { 79 | Log.e(LOGTAG, "Failure in extractAssets(): " + e.toString() + " " + assetsDirectory + assetName); 80 | } 81 | 82 | if (file.exists()) { 83 | Log.d(LOGTAG, "File extracted successfully"); 84 | } 85 | } 86 | } 87 | 88 | public static native void init(); 89 | 90 | public static native void resize(int width, int height); 91 | 92 | public static native void step(); 93 | 94 | static { 95 | System.loadLibrary("Native"); 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /app-malivr/src/main/java/org/babysource/vrdroid/VRDroidView.java: -------------------------------------------------------------------------------- 1 | // This proprietary software may be used only as 2 | // authorised by a licensing agreement from ARM Limited 3 | // (C) COPYRIGHT 2015 ARM Limited 4 | // ALL RIGHTS RESERVED 5 | // The entire notice above must be reproduced on all authorised 6 | // copies and copies may only be made to the extent permitted 7 | // by a licensing agreement from ARM Limited. 8 | package org.babysource.vrdroid; 9 | 10 | import android.content.Context; 11 | import android.opengl.GLSurfaceView; 12 | 13 | import javax.microedition.khronos.egl.EGLConfig; 14 | import javax.microedition.khronos.opengles.GL10; 15 | 16 | class VRDroidView extends GLSurfaceView { 17 | 18 | public VRDroidView(Context context) { 19 | super(context); 20 | setEGLConfigChooser(8, 8, 8, 0, 16, 0); 21 | setEGLContextClientVersion(2); 22 | setRenderer(new Renderer()); 23 | } 24 | 25 | private static class Renderer implements GLSurfaceView.Renderer { 26 | public void onDrawFrame(GL10 gl) { 27 | VRDroid.step(); 28 | } 29 | 30 | public void onSurfaceChanged(GL10 gl, int width, int height) { 31 | VRDroid.resize(width, height); 32 | } 33 | 34 | public void onSurfaceCreated(GL10 gl, EGLConfig config) { 35 | VRDroid.init(); 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /app-malivr/src/main/jni/armvr.cpp: -------------------------------------------------------------------------------- 1 | // This proprietary software may be used only as 2 | // authorised by a licensing agreement from ARM Limited 3 | // (C) COPYRIGHT 2015 ARM Limited 4 | // ALL RIGHTS RESERVED 5 | // The entire notice above must be reproduced on all authorised 6 | // copies and copies may only be made to the extent permitted 7 | // by a licensing agreement from ARM Limited. 8 | #include "armvr.h" 9 | 10 | // These are the dimensions of the viewports (in pixels) used 11 | // when rendering each eye's framebuffer. 12 | #define View_Resolution_X (Screen_Resolution_X / 2) 13 | #define View_Resolution_Y Screen_Resolution_Y 14 | 15 | // These are used to ensure that the distortion appears 16 | // circular, even when the quad is stretched across a 17 | // non-square region of the device. Furthermore, we use 18 | // them to fit the resulting distorted image such that 19 | // the rendered scene fully fits into the viewport. 20 | #define View_Aspect_Ratio ((float)View_Resolution_X / (float)View_Resolution_Y) 21 | #define Eye_Fb_Aspect_Ratio ((float)Eye_Fb_Resolution_X / (float)Eye_Fb_Resolution_Y) 22 | 23 | // The near-clipping plane does not need to be equal to the 24 | // projection plane (the hmd). It can be set larger as long 25 | // as you can ensure that no geometry gets clipped (since 26 | // that is really jarring for users). 27 | #define Z_Near (Eye_Display_Distance) 28 | #define Z_Far Meter(12.0f) 29 | 30 | // Instead of recomputing the distortion per frame, we store 31 | // the distorted texel lookup coordinates in the attributes of 32 | // a tessellated quad. The coordinates are linearly interpolated 33 | // between each vertex. This gives acceptable results given a 34 | // high enough resolution of the mesh, even though the distortion 35 | // equations are nonlinear. 36 | #define Warp_Mesh_Resolution_X 64 37 | #define Warp_Mesh_Resolution_Y 64 38 | 39 | #include 40 | #include 41 | 42 | typedef void (GL_APIENTRY* PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVR)(GLenum, GLenum, GLuint, GLint, GLint, GLsizei); 43 | typedef void (GL_APIENTRY* PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVR) (GLenum, GLenum, GLuint, GLint, GLsizei, GLint, GLsizei); 44 | 45 | Framebuffer make_eye_framebuffer(int width, int height, int num_views) 46 | { 47 | Framebuffer result = {}; 48 | result.width = width; 49 | result.height = height; 50 | 51 | PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVR glFramebufferTextureMultiviewOVR = 52 | (PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVR)eglGetProcAddress ("glFramebufferTextureMultiviewOVR"); 53 | PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVR glFramebufferTextureMultisampleMultiviewOVR = 54 | (PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVR)eglGetProcAddress ("glFramebufferTextureMultisampleMultiviewOVR"); 55 | 56 | if (!glFramebufferTextureMultiviewOVR) 57 | { 58 | LOGE("Did not have glFramebufferTextureMultiviewOVR\n"); 59 | exit(EXIT_FAILURE); 60 | } 61 | if (!glFramebufferTextureMultisampleMultiviewOVR) 62 | { 63 | LOGE("Did not have glFramebufferTextureMultisampleMultiviewOVR\n"); 64 | } 65 | 66 | bool have_multisampled_ext = glFramebufferTextureMultisampleMultiviewOVR != 0; 67 | 68 | GL_CHECK(glGenFramebuffers(1, &result.framebuffer)); 69 | GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, result.framebuffer)); 70 | 71 | GL_CHECK(glGenTextures(1, &result.depthbuffer)); 72 | GL_CHECK(glBindTexture(GL_TEXTURE_2D_ARRAY, result.depthbuffer)); 73 | GL_CHECK(glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_DEPTH_COMPONENT16, width, height, num_views)); 74 | 75 | if (have_multisampled_ext) 76 | { 77 | GL_CHECK(glFramebufferTextureMultisampleMultiviewOVR(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, result.depthbuffer, 0, Multisample_Samples, 0, num_views)); 78 | } 79 | else 80 | { 81 | GL_CHECK(glFramebufferTextureMultiviewOVR(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, result.depthbuffer, 0, 0, num_views)); 82 | } 83 | 84 | GL_CHECK(glGenTextures(1, &result.colorbuffer)); 85 | GL_CHECK(glBindTexture(GL_TEXTURE_2D_ARRAY, result.colorbuffer)); 86 | GL_CHECK(glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, width, height, num_views)); 87 | GL_CHECK(glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); 88 | GL_CHECK(glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); 89 | GL_CHECK(glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER_EXT)); 90 | GL_CHECK(glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER_EXT)); 91 | GLint border_color[4] = {0, 0, 0, 0}; 92 | GL_CHECK(glTexParameteriv(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BORDER_COLOR_EXT, border_color)); 93 | GL_CHECK(glBindTexture(GL_TEXTURE_2D_ARRAY, 0)); 94 | 95 | if (have_multisampled_ext) 96 | { 97 | GL_CHECK(glFramebufferTextureMultisampleMultiviewOVR(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, result.colorbuffer, 0, Multisample_Samples, 0, num_views)); 98 | } 99 | else 100 | { 101 | GL_CHECK(glFramebufferTextureMultiviewOVR(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, result.colorbuffer, 0, 0, num_views)); 102 | } 103 | 104 | GLenum status = GL_CHECK(glCheckFramebufferStatus(GL_FRAMEBUFFER)); 105 | if (status != GL_FRAMEBUFFER_COMPLETE) 106 | LOGE("Framebuffer not complete\n"); 107 | GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0)); 108 | 109 | return result; 110 | } 111 | 112 | GLuint make_cube() 113 | { 114 | float v[] = { 115 | // front 116 | -1.0f, -1.0f, +1.0f, 0.0f, 0.0f, +1.0f, 117 | +1.0f, -1.0f, +1.0f, 0.0f, 0.0f, +1.0f, 118 | +1.0f, +1.0f, +1.0f, 0.0f, 0.0f, +1.0f, 119 | +1.0f, +1.0f, +1.0f, 0.0f, 0.0f, +1.0f, 120 | -1.0f, +1.0f, +1.0f, 0.0f, 0.0f, +1.0f, 121 | -1.0f, -1.0f, +1.0f, 0.0f, 0.0f, +1.0f, 122 | 123 | // back 124 | -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 125 | -1.0f, +1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 126 | +1.0f, +1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 127 | +1.0f, +1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 128 | +1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 129 | -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 130 | 131 | // left 132 | -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 133 | -1.0f, -1.0f, +1.0f, -1.0f, 0.0f, 0.0f, 134 | -1.0f, +1.0f, +1.0f, -1.0f, 0.0f, 0.0f, 135 | -1.0f, +1.0f, +1.0f, -1.0f, 0.0f, 0.0f, 136 | -1.0f, +1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 137 | -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 138 | 139 | // right 140 | +1.0f, -1.0f, -1.0f, +1.0f, 0.0f, 0.0f, 141 | +1.0f, +1.0f, -1.0f, +1.0f, 0.0f, 0.0f, 142 | +1.0f, +1.0f, +1.0f, +1.0f, 0.0f, 0.0f, 143 | +1.0f, +1.0f, +1.0f, +1.0f, 0.0f, 0.0f, 144 | +1.0f, -1.0f, +1.0f, +1.0f, 0.0f, 0.0f, 145 | +1.0f, -1.0f, -1.0f, +1.0f, 0.0f, 0.0f, 146 | 147 | // up 148 | -1.0f, +1.0f, -1.0f, 0.0f, +1.0f, 0.0f, 149 | -1.0f, +1.0f, +1.0f, 0.0f, +1.0f, 0.0f, 150 | +1.0f, +1.0f, +1.0f, 0.0f, +1.0f, 0.0f, 151 | +1.0f, +1.0f, +1.0f, 0.0f, +1.0f, 0.0f, 152 | +1.0f, +1.0f, -1.0f, 0.0f, +1.0f, 0.0f, 153 | -1.0f, +1.0f, -1.0f, 0.0f, +1.0f, 0.0f, 154 | 155 | // down 156 | -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 157 | +1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 158 | +1.0f, -1.0f, +1.0f, 0.0f, -1.0f, 0.0f, 159 | +1.0f, -1.0f, +1.0f, 0.0f, -1.0f, 0.0f, 160 | -1.0f, -1.0f, +1.0f, 0.0f, -1.0f, 0.0f, 161 | -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f 162 | }; 163 | 164 | GLuint result = 0; 165 | GL_CHECK(glGenBuffers(1, &result)); 166 | GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, result)); 167 | GL_CHECK(glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW)); 168 | return result; 169 | } 170 | 171 | // Computes the distorted texel coordinate given the 172 | // position on the image plane. 173 | vec2 compute_distortion(float x, float y, 174 | vec2 distort_centre, 175 | DistortionCoefficients coefficients, 176 | float tex_coord_factor) 177 | { 178 | float k1 = coefficients.k1; 179 | float k2 = coefficients.k2; 180 | float k3 = coefficients.k3; 181 | float p1 = coefficients.p1; 182 | float p2 = coefficients.p2; 183 | 184 | // We need to correct for aspect ratio to ensure that 185 | // the distortion appears circular on the device. 186 | y /= View_Aspect_Ratio; 187 | 188 | float dx = x - distort_centre.x; 189 | float dy = y - distort_centre.y; 190 | float r2 = dx * dx + dy * dy; 191 | float r4 = r2 * r2; 192 | float r6 = r4 * r2; 193 | 194 | float radial_x = x * (k1 * r2 + k2 * r4 + k3 * r6); 195 | float radial_y = y * (k1 * r2 + k2 * r4 + k3 * r6); 196 | 197 | float tangential_x = p1 * (r2 + 2.0f*x*x) + 2.0f*p2*x*y; 198 | float tangential_y = p2 * (r2 + 2.0f*y*y) + 2.0f*p1*x*y; 199 | 200 | float distorted_x = x + radial_x + tangential_x; 201 | float distorted_y = y + radial_y + tangential_y; 202 | 203 | float result_x = 0.5f + tex_coord_factor * distorted_x; 204 | float result_y = 0.5f + tex_coord_factor * distorted_y * View_Aspect_Ratio; 205 | 206 | return vec2(result_x, result_y); 207 | } 208 | 209 | GLuint make_warp_mesh(LensConfig config) 210 | { 211 | struct Vertex 212 | { 213 | vec2 position; 214 | vec2 uv_red_low_res; 215 | vec2 uv_green_low_res; 216 | vec2 uv_blue_low_res; 217 | vec2 uv_red_high_res; 218 | vec2 uv_green_high_res; 219 | vec2 uv_blue_high_res; 220 | }; 221 | static Vertex v[(Warp_Mesh_Resolution_X + 1) * (Warp_Mesh_Resolution_Y + 1)]; 222 | 223 | // Compute vertices 224 | int vi = 0; 225 | for (int yi = 0; yi <= Warp_Mesh_Resolution_Y; yi++) 226 | for (int xi = 0; xi <= Warp_Mesh_Resolution_X; xi++) 227 | { 228 | float x = -1.0f + 2.0f * xi / Warp_Mesh_Resolution_X; 229 | float y = -1.0f + 2.0f * yi / Warp_Mesh_Resolution_Y; 230 | v[vi].position = vec2(x, y) * config.fill_scale + config.image_centre; 231 | v[vi].uv_red_low_res = compute_distortion(x, y, config.distort_centre, config.coefficients_red, 0.5f); 232 | v[vi].uv_green_low_res = compute_distortion(x, y, config.distort_centre, config.coefficients_green, 0.5f); 233 | v[vi].uv_blue_low_res = compute_distortion(x, y, config.distort_centre, config.coefficients_blue, 0.5f); 234 | // The texture coordinates for the higher resolution texture go from -0.5 to 1.5 so 235 | // that only the center of the screen samples the high resolution texture. 236 | v[vi].uv_red_high_res = compute_distortion(x, y, config.distort_centre, config.coefficients_red, 1.0f); 237 | v[vi].uv_green_high_res = compute_distortion(x, y, config.distort_centre, config.coefficients_green, 1.0f); 238 | v[vi].uv_blue_high_res = compute_distortion(x, y, config.distort_centre, config.coefficients_blue, 1.0f); 239 | vi++; 240 | } 241 | 242 | // Generate faces from vertices 243 | static Vertex f[Warp_Mesh_Resolution_X * Warp_Mesh_Resolution_Y * 6]; 244 | int fi = 0; 245 | for (int yi = 0; yi < Warp_Mesh_Resolution_Y; yi++) 246 | for (int xi = 0; xi < Warp_Mesh_Resolution_X; xi++) 247 | { 248 | Vertex v0 = v[(yi ) * (Warp_Mesh_Resolution_X + 1) + xi ]; 249 | Vertex v1 = v[(yi ) * (Warp_Mesh_Resolution_X + 1) + xi + 1]; 250 | Vertex v2 = v[(yi + 1) * (Warp_Mesh_Resolution_X + 1) + xi + 1]; 251 | Vertex v3 = v[(yi + 1) * (Warp_Mesh_Resolution_X + 1) + xi ]; 252 | f[fi++] = v0; 253 | f[fi++] = v1; 254 | f[fi++] = v2; 255 | f[fi++] = v2; 256 | f[fi++] = v3; 257 | f[fi++] = v0; 258 | } 259 | 260 | GLuint result = 0; 261 | GL_CHECK(glGenBuffers(1, &result)); 262 | GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, result)); 263 | GL_CHECK(glBufferData(GL_ARRAY_BUFFER, sizeof(f), f, GL_STATIC_DRAW)); 264 | return result; 265 | } 266 | 267 | // This computes a general frustum given four field-of-view (FOV) 268 | // angles and the near and far clipping planes. The FOV angle is 269 | // defined as the angle between the optical axis (i.e. the eye's 270 | // forward direction) and the line from the eye to the respective 271 | // edge of the screen. 272 | mat4 make_frustum(float left_fov, 273 | float right_fov, 274 | float bottom_fov, 275 | float top_fov, 276 | float z_near, 277 | float z_far) 278 | { 279 | mat4 result(0.0f); 280 | float tt = tan(top_fov); 281 | float tb = tan(bottom_fov); 282 | float tl = tan(left_fov); 283 | float tr = tan(right_fov); 284 | result.x.x = 2.0f / (tl + tr); 285 | result.y.y = 2.0f / (tt + tb); 286 | result.z.x = (tl - tr) / (tl + tr); 287 | result.z.y = (tt - tb) / (tt + tb); 288 | result.z.z = (z_near + z_far) / (z_near - z_far); 289 | result.w.w = -1.0f; 290 | result.w.z = 2.0f * z_near * z_far / (z_near - z_far); 291 | return result; 292 | } 293 | 294 | // This computes a general frustum given the distance 295 | // from the viewer's eye to the display, and the corners 296 | // of that eye's screen half relative to the eye. 297 | // z_near and z_far decide the near and far clipping planes. 298 | mat4 make_frustum_screen_viewer(float eye_display_distance, 299 | float left, 300 | float right, 301 | float bottom, 302 | float top, 303 | float z_near, 304 | float z_far) 305 | { 306 | mat4 result(0.0f); 307 | result.x.x = 2.0f * eye_display_distance / (right - left); 308 | result.y.y = 2.0f * eye_display_distance / (top - bottom); 309 | result.z.x = (right + left) / (right - left); 310 | result.z.y = (top + bottom) / (top - bottom); 311 | result.z.z = (z_near + z_far) / (z_near - z_far); 312 | result.z.w = -1.0f; 313 | result.w.z = 2.0f * z_near * z_far / (z_near - z_far); 314 | return result; 315 | } 316 | 317 | void app_initialize(App *app) 318 | { 319 | // Make sure the required extensions are present. 320 | const GLubyte* extensions = glGetString(GL_EXTENSIONS); 321 | char * found_multiview2_extension = strstr ((const char*)extensions, "GL_OVR_multiview2"); 322 | char * found_multisample_multiview_extension = strstr ((const char*)extensions, "GL_OVR_multiview_multisampled_render_to_texture"); 323 | char * found_border_clamp_extension = strstr ((const char*)extensions, "GL_EXT_texture_border_clamp"); 324 | 325 | if (found_multiview2_extension == NULL) 326 | { 327 | LOGI("OpenGL ES 3.0 implementation does not support GL_OVR_multiview2 extension.\n"); 328 | exit(EXIT_FAILURE); 329 | } 330 | 331 | if (found_multisample_multiview_extension == NULL) 332 | { 333 | // If multisampled multiview is not supported, multisampling will not be used, so no need to exit here. 334 | LOGI("OpenGL ES 3.0 implementation does not support GL_OVR_multiview_multisampled_render_to_texture extension.\n"); 335 | } 336 | 337 | if (found_border_clamp_extension == NULL) 338 | { 339 | LOGI("OpenGL ES 3.0 implementation does not support GL_EXT_texture_border_clamp extension.\n"); 340 | exit(EXIT_FAILURE); 341 | } 342 | 343 | GL_CHECK(glGenVertexArrays(1, &app->vao)); 344 | GL_CHECK(glBindVertexArray(app->vao)); 345 | GL_CHECK(glViewport(0, 0, app->window_width, app->window_height)); 346 | 347 | app->vbo_cube = make_cube(); 348 | 349 | app->fb = make_eye_framebuffer(Eye_Fb_Resolution_X, Eye_Fb_Resolution_Y, Num_Views); 350 | 351 | // The coefficients below may be calibrated by photographing an 352 | // image containing straight lines, both vertical and horizontal, 353 | // through the lenses of the HMD, at the position where the viewer 354 | // would be looking through them. 355 | 356 | // Ideally, the user would be allowed to calibrate them for their 357 | // own eyes, through some calibration utility. The application should 358 | // then load a stored user-profile on runtime. For now, we hardcode 359 | // some values based on our calibration of the SM-R320 Gear VR 360 | // lenses. 361 | 362 | // Left lens 363 | app->hmd.left.coefficients_red.k1 = 0.19f; 364 | app->hmd.left.coefficients_red.k2 = 0.21f; 365 | app->hmd.left.coefficients_red.k3 = 0.0f; 366 | app->hmd.left.coefficients_red.p1 = 0.0f; 367 | app->hmd.left.coefficients_red.p2 = 0.0f; 368 | app->hmd.left.coefficients_green.k1 = 0.22f; 369 | app->hmd.left.coefficients_green.k2 = 0.24f; 370 | app->hmd.left.coefficients_green.k3 = 0.0f; 371 | app->hmd.left.coefficients_green.p1 = 0.0f; 372 | app->hmd.left.coefficients_green.p2 = 0.0f; 373 | app->hmd.left.coefficients_blue.k1 = 0.24f; 374 | app->hmd.left.coefficients_blue.k2 = 0.26f; 375 | app->hmd.left.coefficients_blue.k3 = 0.0f; 376 | app->hmd.left.coefficients_blue.p1 = 0.0f; 377 | app->hmd.left.coefficients_blue.p2 = 0.0f; 378 | 379 | // Right lens 380 | app->hmd.right.coefficients_red.k1 = 0.19f; 381 | app->hmd.right.coefficients_red.k2 = 0.21f; 382 | app->hmd.right.coefficients_red.k3 = 0.0f; 383 | app->hmd.right.coefficients_red.p1 = 0.0f; 384 | app->hmd.right.coefficients_red.p2 = 0.0f; 385 | app->hmd.right.coefficients_green.k1 = 0.22f; 386 | app->hmd.right.coefficients_green.k2 = 0.24f; 387 | app->hmd.right.coefficients_green.k3 = 0.0f; 388 | app->hmd.right.coefficients_green.p1 = 0.0f; 389 | app->hmd.right.coefficients_green.p2 = 0.0f; 390 | app->hmd.right.coefficients_blue.k1 = 0.24f; 391 | app->hmd.right.coefficients_blue.k2 = 0.26f; 392 | app->hmd.right.coefficients_blue.k3 = 0.0f; 393 | app->hmd.right.coefficients_blue.p1 = 0.0f; 394 | app->hmd.right.coefficients_blue.p2 = 0.0f; 395 | 396 | // These may be computed by measuring the distance between the top 397 | // of the unscaled distorted image and the top of the screen. Denote 398 | // this distance by Delta. The normalized view coordinate of the 399 | // distorted image top is 400 | // Y = 1 - 2 Delta / Screen_Size_Y 401 | // We want to scale this coordinate such that it maps to the top of 402 | // the view. That is, 403 | // Y * fill_scale = 1 404 | // Solving for fill_scale gives the equations below. 405 | float delta = Centimeter(0.7f); 406 | app->hmd.left.fill_scale = 1.0f / (1.0f - 2.0f * delta / Screen_Size_Y); 407 | app->hmd.right.fill_scale = 1.0f / (1.0f - 2.0f * delta / Screen_Size_Y); 408 | 409 | // These are computed such that the centers of the displayed framebuffers 410 | // on the device are seperated by the viewer's IPD. 411 | app->hmd.left.image_centre = vec2(+1.0f - Eye_IPD / (Screen_Size_X / 2.0f), 0.0f); 412 | app->hmd.right.image_centre = vec2(-1.0f + Eye_IPD / (Screen_Size_X / 2.0f), 0.0f); 413 | 414 | // These are computed such that the distortion takes place around 415 | // an offset determined by the difference between lens seperation 416 | // and the viewer's eye IPD. If the difference is zero, the distortion 417 | // takes place around the image centre. 418 | app->hmd.left.distort_centre = vec2((Lens_IPD - Eye_IPD) / (Screen_Size_X / 2.0f), 0.0f); 419 | app->hmd.right.distort_centre = vec2((Eye_IPD - Lens_IPD) / (Screen_Size_X / 2.0f), 0.0f); 420 | 421 | app->warp_mesh[0] = make_warp_mesh(app->hmd.left); 422 | app->warp_mesh[1] = make_warp_mesh(app->hmd.right); 423 | 424 | get_attrib_location( distort, position); 425 | get_attrib_location( distort, uv_red_low_res); 426 | get_attrib_location( distort, uv_green_low_res); 427 | get_attrib_location( distort, uv_blue_low_res); 428 | get_attrib_location( distort, uv_red_high_res); 429 | get_attrib_location( distort, uv_green_high_res); 430 | get_attrib_location( distort, uv_blue_high_res); 431 | get_uniform_location(distort, layer_index); 432 | get_uniform_location(distort, framebuffer); 433 | 434 | get_attrib_location (cube, position); 435 | get_attrib_location (cube, normal); 436 | get_uniform_location(cube, projection); 437 | get_uniform_location(cube, view); 438 | get_uniform_location(cube, model); 439 | } 440 | 441 | void draw_scene(App *app) 442 | { 443 | int n = 5; 444 | for (int zi = 0; zi <= n; zi++) 445 | for (int xi = 0; xi <= n; xi++) 446 | { 447 | float x = Centimeter(-100.0f) + 2.0f * Centimeter(100.0f * xi / n); 448 | float z = Centimeter(-100.0f * zi); 449 | int i = zi * n + xi; 450 | mat4 mat_model = translate(x, 0.0f, z) * 451 | scale(Centimeter(5.0f)) * 452 | rotateY(0.3f * app->elapsed_time + i * 1.57f) * 453 | rotateX(0.2f * app->elapsed_time + i * 3.2f); 454 | uniformm4(cube, model, mat_model); 455 | GL_CHECK(glDrawArrays(GL_TRIANGLES, 0, 36)); 456 | } 457 | 458 | mat4 mat_model = translate(0.0f, Centimeter(70.0f), Centimeter(400.0f)) * 459 | scale(Centimeter(5.0f)) * 460 | rotateY(0.3f * app->elapsed_time) * 461 | rotateX(0.05f * app->elapsed_time); 462 | uniformm4(cube, model, mat_model); 463 | GL_CHECK(glDrawArrays(GL_TRIANGLES, 0, 36)); 464 | } 465 | 466 | void app_update_and_render(App *app) 467 | { 468 | GL_CHECK(glEnable(GL_DEPTH_TEST)); 469 | GL_CHECK(glDepthFunc(GL_LEQUAL)); 470 | GL_CHECK(glDepthMask(GL_TRUE)); 471 | GL_CHECK(glDepthRangef(0.0, 1.0)); 472 | 473 | GL_CHECK(glClearDepthf(1.0f)); 474 | GL_CHECK(glClearColor(0.15f, 0.17f, 0.2f, 1.0f)); 475 | 476 | //////////////////////////// 477 | // Cube shader 478 | 479 | GL_CHECK(glUseProgram(app->program_cube)); 480 | GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, app->vbo_cube)); 481 | attribfv(cube, position, 3, 6, 0); 482 | attribfv(cube, normal, 3, 6, 3); 483 | 484 | float camera_z = Centimeter(500.0f); 485 | float camera_y = Centimeter(70.0f); 486 | 487 | mat4 mat_view[Num_Views]; 488 | mat_view[0] = translate(+Eye_IPD / 2.0f, -camera_y, -camera_z); 489 | mat_view[1] = translate(-Eye_IPD / 2.0f, -camera_y, -camera_z); 490 | mat_view[2] = translate(+Eye_IPD / 2.0f, -camera_y, -camera_z); 491 | mat_view[3] = translate(-Eye_IPD / 2.0f, -camera_y, -camera_z); 492 | 493 | // The scene is rendered twice for each eye position, once with a wide field of view, and 494 | // once with a narrower field of view in order to render the midpoint of the screen with 495 | // a higher resolution than the rest. 496 | mat4 mat_projection[Num_Views]; 497 | mat_projection[0] = make_frustum_screen_viewer( 498 | Eye_Display_Distance, 499 | -(Screen_Size_X - Eye_IPD) / 2.0f, 500 | +(Eye_IPD / 2.0f), 501 | -Screen_Size_Y / 2.0f, 502 | +Screen_Size_Y / 2.0f, 503 | Z_Near, Z_Far); 504 | mat_projection[1] = make_frustum_screen_viewer( 505 | Eye_Display_Distance, 506 | -(Eye_IPD / 2.0f), 507 | +(Screen_Size_X - Eye_IPD) / 2.0f, 508 | -Screen_Size_Y / 2.0f, 509 | +Screen_Size_Y / 2.0f, 510 | Z_Near, Z_Far); 511 | 512 | float right_midpoint = -((Screen_Size_X/4.0f) - (Eye_IPD / 2.0f)); 513 | float left_midpoint = (Screen_Size_X/4.0f) - (Eye_IPD / 2.0f); 514 | mat_projection[2] = make_frustum_screen_viewer( 515 | Eye_Display_Distance, 516 | right_midpoint - (Screen_Size_X/8.0f), 517 | right_midpoint + (Screen_Size_X/8.0f), 518 | -Screen_Size_Y / 4.0f, 519 | +Screen_Size_Y / 4.0f, 520 | Z_Near, Z_Far); 521 | mat_projection[3] = make_frustum_screen_viewer( 522 | Eye_Display_Distance, 523 | left_midpoint - (Screen_Size_X/8.0f), 524 | left_midpoint + (Screen_Size_X/8.0f), 525 | -Screen_Size_Y / 4.0f, 526 | +Screen_Size_Y / 4.0f, 527 | Z_Near, Z_Far); 528 | 529 | GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, app->fb.framebuffer)); 530 | GL_CHECK(glViewport(0, 0, app->fb.width, app->fb.height)); 531 | GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); 532 | uniformm4array(cube, projection, mat_projection[0], Num_Views); 533 | uniformm4array(cube, view, mat_view[0], Num_Views); 534 | draw_scene(app); 535 | 536 | //////////////////////////// 537 | // Distortion shader 538 | 539 | GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0)); 540 | 541 | GL_CHECK(glDisable(GL_DEPTH_TEST)); 542 | GL_CHECK(glDepthMask(GL_FALSE)); 543 | GL_CHECK(glClearColor(0.0f, 0.0f, 0.0f, 1.0f)); 544 | GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); 545 | 546 | GL_CHECK(glUseProgram(app->program_distort)); 547 | GL_CHECK(glActiveTexture(GL_TEXTURE0)); 548 | uniform1i(distort, framebuffer, 0); 549 | 550 | // Left eye 551 | GL_CHECK(glViewport(0, 0, View_Resolution_X, View_Resolution_Y)); 552 | GL_CHECK(glBindTexture(GL_TEXTURE_2D_ARRAY, app->fb.colorbuffer)); 553 | uniform1i(distort, layer_index, 0); 554 | GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, app->warp_mesh[0])); 555 | attribfv(distort, position, 2, 14, 0); 556 | attribfv(distort, uv_red_low_res, 2, 14, 2); 557 | attribfv(distort, uv_green_low_res, 2, 14, 4); 558 | attribfv(distort, uv_blue_low_res, 2, 14, 6); 559 | attribfv(distort, uv_red_high_res, 2, 14, 8); 560 | attribfv(distort, uv_green_high_res, 2, 14, 10); 561 | attribfv(distort, uv_blue_high_res, 2, 14, 12); 562 | GL_CHECK(glDrawArrays(GL_TRIANGLES, 0, Warp_Mesh_Resolution_X * Warp_Mesh_Resolution_Y * 6)); 563 | 564 | // Right eye 565 | GL_CHECK(glViewport(View_Resolution_X, 0, View_Resolution_X, View_Resolution_Y)); 566 | uniform1i(distort, layer_index, 1); 567 | GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, app->warp_mesh[1])); 568 | attribfv(distort, position, 2, 14, 0); 569 | attribfv(distort, uv_red_low_res, 2, 14, 2); 570 | attribfv(distort, uv_green_low_res, 2, 14, 4); 571 | attribfv(distort, uv_blue_low_res, 2, 14, 6); 572 | attribfv(distort, uv_red_high_res, 2, 14, 8); 573 | attribfv(distort, uv_green_high_res, 2, 14, 10); 574 | attribfv(distort, uv_blue_high_res, 2, 14, 12); 575 | GL_CHECK(glDrawArrays(GL_TRIANGLES, 0, Warp_Mesh_Resolution_X * Warp_Mesh_Resolution_Y * 6)); 576 | } 577 | -------------------------------------------------------------------------------- /app-malivr/src/main/jni/armvr.h: -------------------------------------------------------------------------------- 1 | // This proprietary software may be used only as 2 | // authorised by a licensing agreement from ARM Limited 3 | // (C) COPYRIGHT 2015 ARM Limited 4 | // ALL RIGHTS RESERVED 5 | // The entire notice above must be reproduced on all authorised 6 | // copies and copies may only be made to the extent permitted 7 | // by a licensing agreement from ARM Limited. 8 | #ifndef _armvr_h_ 9 | #define _armvr_h_ 10 | #include 11 | #include "matrix.h" 12 | #define Meter(x) (x) 13 | #define Centimeter(x) (Meter(x) / 100.0f) 14 | #define Millimeter(x) (Meter(x) / 1000.0f) 15 | 16 | // The following compile-time constants are used to calibrate the 17 | // VR experience for each device and each user. For the optimal 18 | // experience, you will need to perform measurements on your own 19 | // device, head-mounted-display and eyes. The default values are 20 | // calibrated for a Samsung Note 4 for a Gear VR SM-R320 HMD. 21 | 22 | #define Num_Eyes 2 23 | #define Num_Views Num_Eyes * 2 24 | 25 | // The dimensions of the device screen in pixels and meters. 26 | #define Screen_Resolution_X 2560 27 | #define Screen_Resolution_Y 1440 28 | #define Screen_Size_X Meter(0.125f) 29 | #define Screen_Size_Y Meter(0.072f) 30 | 31 | // The dimensions of the framebuffers used for both eyes when 32 | // rendering the scene. The values for these will balance visual 33 | // quality and performance. The framebuffers will be scaled down 34 | // or up to fit inside the viewports. 35 | #define Eye_Fb_Resolution_X 1280 36 | #define Eye_Fb_Resolution_Y 1440 37 | 38 | // If multisampling is available on the device the framebuffers 39 | // will be rendered to using multisampling. 40 | #define Multisample_Samples 4 41 | 42 | // The interpupillary distance (IPD) is the distance between 43 | // your pupils when looking straight ahead. The human average 44 | // is about 64mm, which is the same as the distance between the 45 | // lenses of the Gear VR headset. The user should set these to 46 | // their own measured IPD for the most comfortable experience. 47 | #define Eye_IPD Millimeter(61.0f) 48 | 49 | // This should be set equal to the distance between the lens 50 | // centres in the head-mounted display. 51 | #define Lens_IPD Millimeter(64.0f) 52 | 53 | // This should be set equal to the distance between the display 54 | // and the center point of the viewer's eye. 55 | #define Eye_Display_Distance Centimeter(8.0f) 56 | 57 | // Defining border color enums in case the headers are not up to date for using the android extension pack. 58 | #ifndef GL_TEXTURE_BORDER_COLOR_EXT 59 | #define GL_TEXTURE_BORDER_COLOR_EXT 0x1004 60 | #endif 61 | 62 | #ifndef GL_CLAMP_TO_BORDER_EXT 63 | #define GL_CLAMP_TO_BORDER_EXT 0x812D 64 | #endif 65 | 66 | struct Framebuffer 67 | { 68 | int width; 69 | int height; 70 | GLuint framebuffer; 71 | GLuint depthbuffer; 72 | GLuint colorbuffer; 73 | }; 74 | 75 | // These coefficients control the degree of distortion that 76 | // is applied on the rendertargets, per channel. The notation 77 | // is the same as in the original Brown-Conray distortion 78 | // correction model. 79 | struct DistortionCoefficients 80 | { 81 | // Radial distortion coefficients 82 | float k1; // Central 83 | float k2; // Edge 84 | float k3; // Fine 85 | 86 | // Tangential distortion coefficients 87 | float p1; // Horizontal 88 | float p2; // Vertical 89 | }; 90 | 91 | struct LensConfig 92 | { 93 | // One set for each channel, to handle chromatic aberration. 94 | DistortionCoefficients coefficients_red; 95 | DistortionCoefficients coefficients_green; 96 | DistortionCoefficients coefficients_blue; 97 | 98 | // The viewer may not look through the lens centre. This means 99 | // that we need to perform an asymmetrical barrel distortion, 100 | // centered at an offset given by the difference between the 101 | // viewer's eye seperation and the HMD lens seperation. 102 | vec2 distort_centre; 103 | 104 | // Each eye should be looking at the centre of each produced 105 | // framebuffer image. To do this we must shift the result of 106 | // each framebuffer by an appropriate amount, such that when 107 | // the viewer looks straight ahead, the left pupil is in the 108 | // centre of the left image and the right pupil vice versa. 109 | vec2 image_centre; 110 | 111 | // The distorted image will appear smaller on the screen, 112 | // depending on the values of the distortion coefficients. 113 | // We apply a shape-preserving upscale to make the distorted 114 | // image fit into the edges of the screen. The value of this 115 | // scale is somewhat arbitrarily chosen. 116 | float fill_scale; 117 | }; 118 | 119 | struct HMDConfig 120 | { 121 | LensConfig left; 122 | LensConfig right; 123 | }; 124 | 125 | struct WarpMesh 126 | { 127 | GLuint vbo; 128 | GLuint ibo; 129 | int index_count; 130 | }; 131 | 132 | struct App 133 | { 134 | int window_width; 135 | int window_height; 136 | float frame_time; 137 | float elapsed_time; 138 | 139 | // Distortion shader 140 | GLuint program_distort; 141 | GLuint a_distort_position; 142 | GLuint a_distort_uv_red_low_res; 143 | GLuint a_distort_uv_green_low_res; 144 | GLuint a_distort_uv_blue_low_res; 145 | GLuint a_distort_uv_red_high_res; 146 | GLuint a_distort_uv_green_high_res; 147 | GLuint a_distort_uv_blue_high_res; 148 | GLuint u_distort_layer_index; 149 | GLuint u_distort_framebuffer; 150 | 151 | // Cube shader 152 | GLuint program_cube; 153 | GLuint a_cube_position; 154 | GLuint a_cube_normal; 155 | GLuint u_cube_projection; 156 | GLuint u_cube_view; 157 | GLuint u_cube_model; 158 | 159 | // Geometry 160 | GLuint vao; 161 | GLuint vbo_cube; 162 | GLuint warp_mesh[Num_Eyes]; 163 | 164 | HMDConfig hmd; 165 | Framebuffer fb; 166 | }; 167 | 168 | void gl_check(const char *msg); 169 | void app_initialize(App *app); 170 | void app_update_and_render(App *app); 171 | 172 | ///////////////////////////////////// 173 | // Convenience macros 174 | 175 | #define GL_CHECK(x) \ 176 | x; \ 177 | { \ 178 | GLenum glError = glGetError(); \ 179 | if(glError != GL_NO_ERROR) { \ 180 | LOGE("glGetError() = %i (0x%.8x) at %s:%i\n", glError, glError, __FILE__, __LINE__); \ 181 | exit(1); \ 182 | } \ 183 | } 184 | 185 | #define get_attrib_location(prog, name) \ 186 | app->a_##prog##_##name = GL_CHECK(glGetAttribLocation(app->program_##prog, #name)); \ 187 | if (app->a_##prog##_##name < 0) { \ 188 | LOGE("Invalid or unused attribute %s\n", #name); \ 189 | } 190 | 191 | #define get_uniform_location(prog, name) \ 192 | app->u_##prog##_##name = GL_CHECK(glGetUniformLocation(app->program_##prog, #name)); \ 193 | if (app->u_##prog##_##name < 0) { \ 194 | LOGE("Invalid or unused uniform %s\n", #name); \ 195 | } 196 | 197 | #define attribfv(prog, name, n, stride, offset) \ 198 | GL_CHECK(glEnableVertexAttribArray(app->a_##prog##_##name)); \ 199 | GL_CHECK(glVertexAttribPointer(app->a_##prog##_##name, n, GL_FLOAT, GL_FALSE, \ 200 | stride * sizeof(GLfloat), (void*)(offset * sizeof(GLfloat)))); 201 | 202 | #define attribiv(prog, name, n, stride, offset) \ 203 | GL_CHECK(glEnableVertexAttribArray(app->a_##prog##_##name)); \ 204 | GL_CHECK(glVertexAttribPointer(app->a_##prog##_##name, n, GL_INT, GL_FALSE, \ 205 | stride * sizeof(GLint), (void*)(offset * sizeof(GLint)) )); 206 | 207 | #define uniform1f(prog, name, value) GL_CHECK(glUniform1f(app->u_##prog##_##name, value)); 208 | #define uniform2f(prog, name, x, y) GL_CHECK(glUniform2f(app->u_##prog##_##name, x, y)); 209 | #define uniform2fv(prog, name, value) GL_CHECK(glUniform2fv(app->u_##prog##_##name, 1, &value[0])); 210 | #define uniform3fv(prog, name, value) GL_CHECK(glUniform3fv(app->u_##prog##_##name, 1, &value[0])); 211 | #define uniform1i(prog, name, value) GL_CHECK(glUniform1i(app->u_##prog##_##name, value)); 212 | #define uniformm4(prog, name, value) GL_CHECK(glUniformMatrix4fv(app->u_##prog##_##name, 1, GL_FALSE, value.value_ptr())); 213 | #define uniformm4array(prog, name, value, arraySize) GL_CHECK(glUniformMatrix4fv(app->u_##prog##_##name, arraySize, GL_FALSE, value.value_ptr())); 214 | 215 | #endif 216 | -------------------------------------------------------------------------------- /app-malivr/src/main/jni/loader.cpp: -------------------------------------------------------------------------------- 1 | // This proprietary software may be used only as 2 | // authorised by a licensing agreement from ARM Limited 3 | // (C) COPYRIGHT 2015 ARM Limited 4 | // ALL RIGHTS RESERVED 5 | // The entire notice above must be reproduced on all authorised 6 | // copies and copies may only be made to the extent permitted 7 | // by a licensing agreement from ARM Limited. 8 | 9 | char *read_file(const char *filename) 10 | { 11 | FILE *file = fopen(filename, "rb"); 12 | if (!file) 13 | { 14 | LOGE("Failed to open file %s\n", filename); 15 | exit (1); 16 | } 17 | fseek(file, 0, SEEK_END); 18 | long length = ftell(file); 19 | fseek(file, 0, SEEK_SET); 20 | char *data = (char *)calloc(length + 1, sizeof(char)); 21 | if (!data) 22 | { 23 | LOGE("Failed to allocate memory for file data %s\n", filename); 24 | exit(1); 25 | } 26 | size_t read = fread(data, sizeof(char), length, file); 27 | if (read != length) 28 | { 29 | LOGE("Failed to read whole file %s\n", filename); 30 | exit(1); 31 | } 32 | data[length] = '\0'; 33 | fclose(file); 34 | return data; 35 | } 36 | 37 | GLuint compile_shader(const char *source, GLenum type) 38 | { 39 | GLuint result = glCreateShader(type); 40 | glShaderSource(result, 1, (const GLchar**)&source, NULL); 41 | glCompileShader(result); 42 | GLint status; 43 | glGetShaderiv(result, GL_COMPILE_STATUS, &status); 44 | if (status == GL_FALSE) { 45 | GLint length; 46 | glGetShaderiv(result, GL_INFO_LOG_LENGTH, &length); 47 | GLchar *info = new GLchar[length]; 48 | glGetShaderInfoLog(result, length, NULL, info); 49 | LOGE("[COMPILE] %s\n", info); 50 | delete[] info; 51 | exit(1); 52 | } 53 | return result; 54 | } 55 | 56 | GLuint link_program(GLuint *shaders, int count) 57 | { 58 | GLuint program = glCreateProgram(); 59 | for (int i = 0; i < count; ++i) 60 | glAttachShader(program, shaders[i]); 61 | 62 | glLinkProgram(program); 63 | 64 | for (int i = 0; i < count; ++i) 65 | glDetachShader(program, shaders[i]); 66 | 67 | GLint status; 68 | glGetProgramiv(program, GL_LINK_STATUS, &status); 69 | if (status == GL_FALSE) { 70 | GLint length; 71 | glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length); 72 | GLchar *info = new GLchar[length]; 73 | glGetProgramInfoLog(program, length, NULL, info); 74 | LOGE("[LINK] %s\n", info); 75 | delete[] info; 76 | exit(1); 77 | } 78 | return program; 79 | } 80 | 81 | void load_cube_shader(App *app) 82 | { 83 | char *vs_src = read_file(SHADER_PATH("cube.vs")); 84 | char *fs_src = read_file(SHADER_PATH("cube.fs")); 85 | 86 | GLuint shaders[2]; 87 | shaders[0] = compile_shader(vs_src, GL_VERTEX_SHADER); 88 | shaders[1] = compile_shader(fs_src, GL_FRAGMENT_SHADER); 89 | app->program_cube = link_program(shaders, 2); 90 | 91 | free(vs_src); 92 | free(fs_src); 93 | } 94 | 95 | void load_distort_shader(App *app) 96 | { 97 | char *vs_src = read_file(SHADER_PATH("distort.vs")); 98 | char *fs_src = read_file(SHADER_PATH("distort.fs")); 99 | 100 | GLuint shaders[2]; 101 | shaders[0] = compile_shader(vs_src, GL_VERTEX_SHADER); 102 | shaders[1] = compile_shader(fs_src, GL_FRAGMENT_SHADER); 103 | app->program_distort = link_program(shaders, 2); 104 | 105 | free(vs_src); 106 | free(fs_src); 107 | } 108 | 109 | void load_assets(App *app) 110 | { 111 | load_distort_shader(app); 112 | load_cube_shader(app); 113 | } 114 | -------------------------------------------------------------------------------- /app-malivr/src/main/jni/main.cpp: -------------------------------------------------------------------------------- 1 | // This proprietary software may be used only as 2 | // authorised by a licensing agreement from ARM Limited 3 | // (C) COPYRIGHT 2015 ARM Limited 4 | // ALL RIGHTS RESERVED 5 | // The entire notice above must be reproduced on all authorised 6 | // copies and copies may only be made to the extent permitted 7 | // by a licensing agreement from ARM Limited. 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #define LOG_TAG "ARMVR" 14 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) 15 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) 16 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) 17 | 18 | #include 19 | #include "armvr.cpp" 20 | 21 | #define BASE_ASSET_PATH "/data/data/com.arm.malideveloper.vrsdk.armvr/files/" 22 | #define SHADER_PATH(name) BASE_ASSET_PATH name 23 | #include "loader.cpp" 24 | 25 | #include 26 | static timeval start_time; 27 | static App app; 28 | 29 | const char *get_gl_error_msg(GLenum code) 30 | { 31 | switch (code) 32 | { 33 | case 0: return "NO_ERROR"; 34 | case 0x0500: return "INVALID_ENUM"; 35 | case 0x0501: return "INVALID_VALUE"; 36 | case 0x0502: return "INVALID_OPERATION"; 37 | case 0x0503: return "STACK_OVERFLOW"; 38 | case 0x0504: return "STACK_UNDERFLOW"; 39 | case 0x0505: return "OUT_OF_MEMORY"; 40 | case 0x0506: return "INVALID_FRAMEBUFFER_OPERATION"; 41 | default: return "UNKNOWN"; 42 | } 43 | } 44 | 45 | void gl_check() 46 | { 47 | GLenum error = glGetError(); 48 | if (error != GL_NO_ERROR) 49 | { 50 | LOGD("An OpenGL error occurred %s", get_gl_error_msg(error)); 51 | exit(1); 52 | } 53 | } 54 | 55 | extern "C" 56 | { 57 | JNIEXPORT void JNICALL Java_org_babysource_vrdroid_VRDroid_init(JNIEnv* env, jobject obj) 58 | { 59 | LOGD("Init\n"); 60 | start_time.tv_sec = 0; 61 | start_time.tv_usec = 0; 62 | gettimeofday(&start_time, NULL); 63 | 64 | LOGD("Load assets\n"); 65 | load_assets(&app); 66 | app_initialize(&app); 67 | } 68 | 69 | JNIEXPORT void JNICALL Java_org_babysource_vrdroid_VRDroid_resize(JNIEnv* env, jobject obj, jint width, jint height) 70 | { 71 | app.window_width = width; 72 | app.window_height = height; 73 | app.elapsed_time = 0.0f; 74 | glViewport(0, 0, width, height); 75 | LOGD("Resizing %d %d\n", width, height); 76 | } 77 | 78 | JNIEXPORT void JNICALL Java_org_babysource_vrdroid_VRDroid_step(JNIEnv* env, jobject obj) 79 | { 80 | timeval now; 81 | gettimeofday(&now, NULL); 82 | float seconds = (now.tv_sec - start_time.tv_sec); 83 | float milliseconds = (float(now.tv_usec - start_time.tv_usec)) / 1000000.0f; 84 | float elapsed_time = seconds + milliseconds; 85 | app.frame_time = elapsed_time - app.elapsed_time; 86 | app.elapsed_time = elapsed_time; 87 | 88 | app_update_and_render(&app); 89 | gl_check(); 90 | } 91 | }; 92 | -------------------------------------------------------------------------------- /app-malivr/src/main/jni/matrix.h: -------------------------------------------------------------------------------- 1 | // This proprietary software may be used only as 2 | // authorised by a licensing agreement from ARM Limited 3 | // (C) COPYRIGHT 2015 ARM Limited 4 | // ALL RIGHTS RESERVED 5 | // The entire notice above must be reproduced on all authorised 6 | // copies and copies may only be made to the extent permitted 7 | // by a licensing agreement from ARM Limited. 8 | #ifndef MATRIX_H 9 | #define MATRIX_H 10 | #ifndef PI 11 | #define PI 3.141592653f 12 | #endif 13 | #include 14 | 15 | struct vec2 16 | { 17 | float x; 18 | float y; 19 | 20 | vec2() : x(0.0f), y(0.0f) { } 21 | vec2(float X, float Y) : x(X), y(Y){ } 22 | explicit vec2(float S) : x(S), y(S) { } 23 | vec2 operator + (const vec2 &rhs) const { return vec2(x + rhs.x, y + rhs.y); } 24 | vec2 operator * (const vec2 &rhs) const { return vec2(x * rhs.x, y * rhs.y); } 25 | vec2 operator - (const vec2 &rhs) const { return vec2(x - rhs.x, y - rhs.y); } 26 | vec2 operator * (const float s) const { return vec2(x * s, y * s); } 27 | vec2 operator / (const float s) const { return vec2(x / s, y / s); } 28 | 29 | vec2 &operator *= (const float s) { *this = *this * s; return *this; } 30 | vec2 &operator += (const vec2 &rhs) { *this = *this + rhs; return *this; } 31 | vec2 &operator *= (const vec2 &rhs) { *this = *this * rhs; return *this; } 32 | vec2 &operator -= (const vec2 &rhs) { *this = *this - rhs; return *this; } 33 | 34 | float &operator [] (unsigned int i) { return (&x)[i]; } 35 | const float &operator [] (unsigned int i) const { return (&x)[i]; } 36 | }; 37 | 38 | struct vec3 39 | { 40 | float x; 41 | float y; 42 | float z; 43 | 44 | vec3() : x(0.0f), y(0.0f), z(0.0f) { } 45 | vec3(float X, float Y, float Z) : x(X), y(Y), z(Z) { } 46 | explicit vec3(float S) : x(S), y(S), z(S) { } 47 | vec3 operator - () const { return vec3(-x, -y, -z); } 48 | vec3 operator + (const vec3 &rhs) const { return vec3(x + rhs.x, y + rhs.y, z + rhs.z); } 49 | vec3 operator * (const vec3 &rhs) const { return vec3(x * rhs.x, y * rhs.y, z * rhs.z); } 50 | vec3 operator - (const vec3 &rhs) const { return vec3(x - rhs.x, y - rhs.y, z - rhs.z); } 51 | vec3 operator * (const float s) const { return vec3(x * s, y * s, z * s); } 52 | vec3 operator / (const float s) const { return vec3(x / s, y / s, z / s); } 53 | 54 | vec3 &operator += (const vec3 &rhs) { *this = *this + rhs; return *this; } 55 | vec3 &operator *= (const vec3 &rhs) { *this = *this * rhs; return *this; } 56 | vec3 &operator -= (const vec3 &rhs) { *this = *this - rhs; return *this; } 57 | 58 | float &operator [] (unsigned int i) { return (&x)[i]; } 59 | const float &operator [] (unsigned int i) const { return (&x)[i]; } 60 | }; 61 | 62 | struct vec4 63 | { 64 | float x; 65 | float y; 66 | float z; 67 | float w; 68 | 69 | vec4() : x(0.0f), y(0.0f), z(0.0f), w(0.0f) { } 70 | vec4(vec3 V, float W) : x(V.x), y(V.y), z(V.z), w(W) { } 71 | vec4(float X, float Y, float Z, float W) : x(X), y(Y), z(Z), w(W) { } 72 | explicit vec4(float S) : x(S), y(S), z(S), w(S) { } 73 | vec4 operator - () const { return vec4(-x, -y, -z, -w); } 74 | vec4 operator + (const vec4 &rhs) const { return vec4(x + rhs.x, y + rhs.y, z + rhs.z, w + rhs.w); } 75 | vec4 operator * (const vec4 &rhs) const { return vec4(x * rhs.x, y * rhs.y, z * rhs.z, w * rhs.w); } 76 | vec4 operator - (const vec4 &rhs) const { return vec4(x - rhs.x, y - rhs.y, z - rhs.z, w - rhs.w); } 77 | vec4 operator * (const float s) const { return vec4(x * s, y * s, z * s, w * s); } 78 | vec4 operator / (const float s) const { return vec4(x / s, y / s, z / s, w / s); } 79 | 80 | vec4 &operator *= (const float s) { *this = *this * s; return *this; } 81 | vec4 &operator += (const vec4 &rhs) { *this = *this + rhs; return *this; } 82 | vec4 &operator *= (const vec4 &rhs) { *this = *this * rhs; return *this; } 83 | vec4 &operator -= (const vec4 &rhs) { *this = *this - rhs; return *this; } 84 | 85 | float &operator [] (unsigned int i) { return (&x)[i]; } 86 | const float &operator [] (unsigned int i) const { return (&x)[i]; } 87 | 88 | vec3 xyz() const { return vec3(x, y, z); } 89 | }; 90 | 91 | struct mat4 92 | { 93 | vec4 x, y, z, w; // columns 94 | 95 | mat4() { } 96 | explicit mat4(float s) : x(0.0f), y(0.0f), z(0.0f), w(0.0f) 97 | { 98 | x.x = s; 99 | y.y = s; 100 | z.z = s; 101 | w.w = s; 102 | } 103 | 104 | mat4 operator * (const mat4 &rhs) 105 | { 106 | mat4 m; 107 | for (int lrow = 0; lrow < 4; ++lrow) 108 | { 109 | for (int rcol = 0; rcol < 4; ++rcol) 110 | { 111 | m[rcol][lrow] = 0.0f; 112 | for (int k = 0; k < 4; ++k) 113 | { 114 | m[rcol][lrow] += (*this)[k][lrow] * rhs[rcol][k]; 115 | } 116 | } 117 | } 118 | return m; 119 | } 120 | 121 | mat4 operator * (const float s) 122 | { 123 | mat4 m = *this; 124 | m.x *= s; 125 | m.y *= s; 126 | m.z *= s; 127 | m.w *= s; 128 | return m; 129 | } 130 | 131 | vec4 operator * (const vec4 &rhs) 132 | { 133 | return x * rhs.x + y * rhs.y + z * rhs.z + w * rhs.w; 134 | } 135 | 136 | vec4 &operator [] (unsigned int i) { return (&x)[i]; } 137 | const vec4 &operator [] (unsigned int i) const { return (&x)[i]; } 138 | const float *value_ptr() const { return &(x[0]); } 139 | float *value_ptr() { return &(x[0]); } 140 | }; 141 | 142 | static vec3 normalize(const vec3 &v) 143 | { 144 | return v / sqrt(v.x * v.x + v.y * v.y + v.z * v.z); 145 | } 146 | 147 | static mat4 transpose(const mat4 &m) 148 | { 149 | vec4 a = m.x; 150 | vec4 b = m.y; 151 | vec4 c = m.z; 152 | vec4 d = m.w; 153 | mat4 result; 154 | result.x = vec4(a.x, b.x, c.x, d.x); 155 | result.y = vec4(a.y, b.y, c.y, d.y); 156 | result.z = vec4(a.z, b.z, c.z, d.z); 157 | result.w = vec4(a.w, b.w, c.w, d.w); 158 | return result; 159 | } 160 | 161 | static mat4 perspective(float fovy, float aspect, float z_near, float z_far) 162 | { 163 | mat4 m(1.0f); 164 | float invtf = 1.0f / tan(fovy * 0.5f); 165 | m[0].x = invtf / aspect; 166 | m[1].y = invtf; 167 | m[2].z = -(z_far + z_near) / (z_far - z_near); 168 | m[2].w = -1.0f; 169 | m[3].z = (-2.0f * z_far * z_near) / (z_far - z_near); 170 | m[3].w = 0.0f; 171 | return m; 172 | } 173 | 174 | static mat4 orthographic(float left, float right, float bottom, float top, float z_near, float z_far) 175 | { 176 | mat4 m(1.0f); 177 | m[0].x = 2.0f / (right - left); 178 | m[3].x = -(right + left) / (right - left); 179 | m[1].y = 2.0f / (top - bottom); 180 | m[3].y = -(top + bottom) / (top - bottom); 181 | m[2].z = -2.0f / (z_far - z_near); 182 | m[3].z = -(z_far + z_near) / (z_far - z_near); 183 | return m; 184 | } 185 | 186 | static mat4 rotateX(float rad) 187 | { 188 | float co = cosf(rad); float si = sinf(rad); 189 | mat4 m(1.0f); 190 | m[1][1] = co; m[1][2] = -si; m[2][1] = si; m[2][2] = co; 191 | return m; 192 | } 193 | 194 | static mat4 rotateY(float rad) 195 | { 196 | float co = cosf(rad); float si = sinf(rad); 197 | mat4 m(1.0f); 198 | m[0][0] = co; m[0][2] = si; m[2][0] = -si; m[2][2] = co; 199 | return m; 200 | } 201 | 202 | static mat4 rotateZ(float rad) 203 | { 204 | float co = cosf(rad); float si = sinf(rad); 205 | mat4 m(1.0f); 206 | m[0][0] = co; m[1][0] = -si; m[0][1] = si; m[1][1] = co; 207 | return m; 208 | } 209 | 210 | static mat4 translate(float x, float y, float z) 211 | { 212 | mat4 m(1.0f); 213 | m[3][0] = x; m[3][1] = y; m[3][2] = z; m[3][3] = 1.0f; 214 | return m; 215 | } 216 | 217 | static mat4 translate(const vec3 &v) 218 | { 219 | mat4 m(1.0f); 220 | m[3][0] = v.x; m[3][1] = v.y; m[3][2] = v.z; 221 | return m; 222 | } 223 | 224 | static mat4 scale(float x, float y, float z) 225 | { 226 | mat4 m(1.0f); 227 | m[0][0] = x; m[1][1] = y; m[2][2] = z; 228 | return m; 229 | } 230 | 231 | static mat4 scale(float s) 232 | { 233 | return scale(s, s, s); 234 | } 235 | 236 | #endif 237 | -------------------------------------------------------------------------------- /app-malivr/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/app-malivr/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app-malivr/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/app-malivr/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app-malivr/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/app-malivr/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app-malivr/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/app-malivr/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app-malivr/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/app-malivr/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app-malivr/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | #DDDDDD 7 | #FFFFFF 8 | 9 | -------------------------------------------------------------------------------- /app-malivr/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /app-malivr/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | VRDroid-Malivr 3 | 4 | -------------------------------------------------------------------------------- /app-malivr/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app-rajawali/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app-rajawali/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.model.application' 2 | 3 | model { 4 | android { 5 | compileSdkVersion = 23 6 | buildToolsVersion = '23.0.3' 7 | 8 | defaultConfig { 9 | applicationId = 'com.babysource.vrdroid.rajawali' 10 | minSdkVersion.apiLevel = 16 11 | targetSdkVersion.apiLevel = 23 12 | } 13 | } 14 | 15 | android.buildTypes { 16 | debug { 17 | debuggable = true 18 | minifyEnabled = false 19 | multiDexEnabled = false 20 | shrinkResources = false 21 | zipAlignEnabled = true 22 | } 23 | release { 24 | debuggable = false 25 | minifyEnabled = false 26 | multiDexEnabled = false 27 | shrinkResources = true 28 | zipAlignEnabled = true 29 | proguardFiles.add(file('proguard-rules.pro')) 30 | } 31 | } 32 | 33 | android.packagingOptions { 34 | exclude 'META-INF/DEPENDENCIES' 35 | exclude 'META-INF/LICENSE.txt' 36 | exclude 'META-INF/LICENSE' 37 | exclude 'META-INF/NOTICE.txt' 38 | exclude 'META-INF/NOTICE' 39 | } 40 | 41 | android.lintOptions { 42 | abortOnError = false 43 | } 44 | } 45 | 46 | repositories { 47 | maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } 48 | } 49 | 50 | dependencies { 51 | compile 'com.android.support:appcompat-v7:23.2.1' 52 | compile 'org.rajawali3d:rajawali:1.1.777' 53 | compile 'org.rajawali3d:vr:1.1.777' 54 | } 55 | -------------------------------------------------------------------------------- /app-rajawali/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\adt-bundle-windows-x86_64-20131030\Android_Studio_sdk\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app-rajawali/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /app-rajawali/src/main/java/org/babysource/vrdroid/VRDroidLister.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Created on 2016/3/31 3 | */ 4 | package org.babysource.vrdroid; 5 | 6 | import android.os.Bundle; 7 | import android.support.v4.app.FragmentActivity; 8 | 9 | /** 10 | * VR资源列表 11 | *

12 | * 13 | * @author Wythe 14 | */ 15 | public class VRDroidLister extends FragmentActivity { 16 | 17 | @Override 18 | protected void onCreate(final Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /app-rajawali/src/main/java/org/babysource/vrdroid/VRDroidPlayer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Created on 2016/3/31 3 | */ 4 | package org.babysource.vrdroid; 5 | 6 | import android.os.Bundle; 7 | 8 | import org.babysource.vrdroid.render.VRDroidRender; 9 | import org.rajawali3d.vr.VRActivity; 10 | 11 | /** 12 | * VR资源播放 13 | *

14 | * 15 | * @author Wythe 16 | */ 17 | public class VRDroidPlayer extends VRActivity { 18 | 19 | private VRDroidRender mMediaRender; 20 | 21 | @Override 22 | public void onCreate(final Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | this.getSurfaceView().setSettingsButtonEnabled(false); 25 | this.getSurfaceView().setAlignmentMarkerEnabled(false); 26 | this.getSurfaceView().setRenderer(this.mMediaRender = new VRDroidRender(this)); 27 | } 28 | 29 | @Override 30 | public void onPause() { 31 | super.onPause(); 32 | if (this.mMediaRender != null) { 33 | this.mMediaRender.onPause(); 34 | } 35 | } 36 | 37 | @Override 38 | public void onResume() { 39 | super.onResume(); 40 | if (this.mMediaRender != null) { 41 | this.mMediaRender.onResume(); 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /app-rajawali/src/main/java/org/babysource/vrdroid/render/VRDroidRender.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Created on 2016/3/31 3 | */ 4 | package org.babysource.vrdroid.render; 5 | 6 | import android.content.Context; 7 | import android.graphics.SurfaceTexture; 8 | import android.media.MediaPlayer; 9 | import android.net.Uri; 10 | import android.os.Environment; 11 | import android.view.MotionEvent; 12 | 13 | import org.rajawali3d.materials.Material; 14 | import org.rajawali3d.materials.textures.ATexture; 15 | import org.rajawali3d.materials.textures.StreamingTexture; 16 | import org.rajawali3d.primitives.Sphere; 17 | import org.rajawali3d.vr.renderer.VRRenderer; 18 | 19 | import java.io.File; 20 | 21 | /** 22 | * VR资源渲染 23 | *

24 | * 25 | * @author Wythe 26 | */ 27 | public class VRDroidRender extends VRRenderer { 28 | 29 | private MediaPlayer mMediaPlayer; 30 | 31 | private StreamingTexture mMediaTexture; 32 | 33 | public VRDroidRender(Context context) { 34 | super(context); 35 | this.setFrameRate(60.0D); 36 | } 37 | 38 | @Override 39 | protected void initScene() { 40 | if (this.mMediaPlayer == null) { 41 | this.mMediaPlayer = MediaPlayer.create(getContext(), Uri.fromFile( 42 | new File(Environment.getExternalStorageDirectory() + File.separator + "360Videos/360.mp4") 43 | )); 44 | } 45 | if (this.mMediaTexture == null) { 46 | this.mMediaTexture = new StreamingTexture("video", this.mMediaPlayer); 47 | } 48 | final Material material = new Material(); 49 | try { 50 | material.addTexture(this.mMediaTexture); 51 | } catch (ATexture.TextureException e) { 52 | e.printStackTrace(); 53 | return; 54 | } 55 | final Sphere sphere = new Sphere(1, 24, 24); 56 | sphere.setMaterial(material); 57 | sphere.setPosition(0, 0, 0); 58 | sphere.setScaleX(100); 59 | sphere.setScaleY(100); 60 | sphere.setScaleZ(-100); 61 | material.setColorInfluence(0F); 62 | getCurrentScene().addChild(sphere); 63 | this.mMediaPlayer.setLooping(true); 64 | this.mMediaPlayer.start(); 65 | } 66 | 67 | @Override 68 | public void onRenderSurfaceDestroyed(final SurfaceTexture surface) { 69 | super.onRenderSurfaceDestroyed(surface); 70 | if (this.mMediaTexture != null) { 71 | this.mMediaTexture = null; 72 | } 73 | if (this.mMediaPlayer != null) { 74 | try { 75 | this.mMediaPlayer.stop(); 76 | } catch (Exception e) { 77 | e.printStackTrace(); 78 | } finally { 79 | this.mMediaPlayer.release(); 80 | } 81 | this.mMediaPlayer = null; 82 | } 83 | } 84 | 85 | @Override 86 | public void onPause() { 87 | super.onPause(); 88 | if (this.mMediaPlayer != null) { 89 | this.mMediaPlayer.pause(); 90 | } 91 | } 92 | 93 | @Override 94 | public void onResume() { 95 | super.onResume(); 96 | if (this.mMediaPlayer != null) { 97 | this.mMediaPlayer.start(); 98 | } 99 | } 100 | 101 | @Override 102 | protected void onRender(final long ellapsedRealtime, final double deltaTime) { 103 | super.onRender(ellapsedRealtime, deltaTime); 104 | if (this.mMediaTexture != null) { 105 | this.mMediaTexture.update(); 106 | } 107 | } 108 | 109 | @Override 110 | public void onTouchEvent(final MotionEvent event) { 111 | 112 | } 113 | 114 | @Override 115 | public void onOffsetsChanged(final float xOffset, final float yOffset, final float xOffsetStep, final float yOffsetStep, final int xPixelOffset, final int yPixelOffset) { 116 | 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /app-rajawali/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/app-rajawali/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app-rajawali/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/app-rajawali/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app-rajawali/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/app-rajawali/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app-rajawali/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/app-rajawali/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app-rajawali/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/app-rajawali/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app-rajawali/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app-rajawali/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /app-rajawali/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | VRDroid-Rajawali 3 | 4 | -------------------------------------------------------------------------------- /app-rajawali/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app-vrwidget/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app-vrwidget/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.model.application' 2 | 3 | model { 4 | android { 5 | compileSdkVersion = 23 6 | buildToolsVersion = '23.0.3' 7 | 8 | defaultConfig { 9 | applicationId = 'com.babysource.vrdroid.vrview' 10 | minSdkVersion.apiLevel = 19 11 | targetSdkVersion.apiLevel = 23 12 | } 13 | } 14 | 15 | android.buildTypes { 16 | debug { 17 | debuggable = true 18 | minifyEnabled = false 19 | multiDexEnabled = false 20 | shrinkResources = false 21 | zipAlignEnabled = true 22 | } 23 | release { 24 | debuggable = false 25 | minifyEnabled = false 26 | multiDexEnabled = false 27 | shrinkResources = true 28 | zipAlignEnabled = true 29 | proguardFiles.add(file('proguard-rules.pro')) 30 | } 31 | } 32 | 33 | android.packagingOptions { 34 | exclude 'META-INF/DEPENDENCIES' 35 | exclude 'META-INF/LICENSE.txt' 36 | exclude 'META-INF/LICENSE' 37 | exclude 'META-INF/NOTICE.txt' 38 | exclude 'META-INF/NOTICE' 39 | } 40 | 41 | android.lintOptions { 42 | abortOnError = false 43 | } 44 | } 45 | 46 | dependencies { 47 | compile project(':libraries:common') 48 | compile project(':libraries:videowidget') 49 | compile project(':libraries:commonwidget') 50 | compile 'com.android.support:appcompat-v7:23.2.1' 51 | compile 'com.google.android.exoplayer:exoplayer:r1.5.12' 52 | compile 'com.google.protobuf.nano:protobuf-javanano:3.1.0' 53 | } 54 | -------------------------------------------------------------------------------- /app-vrwidget/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\adt-bundle-windows-x86_64-20131030\Android_Studio_sdk\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app-vrwidget/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 20 | 21 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /app-vrwidget/src/main/java/org/babysource/vrdroid/VRDroidLister.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Created on 2016/3/31 3 | */ 4 | package org.babysource.vrdroid; 5 | 6 | import android.content.Intent; 7 | import android.graphics.Bitmap; 8 | import android.media.ThumbnailUtils; 9 | import android.os.AsyncTask; 10 | import android.os.Bundle; 11 | import android.os.Environment; 12 | import android.provider.MediaStore; 13 | import android.support.v4.app.FragmentActivity; 14 | import android.text.TextUtils; 15 | import android.view.LayoutInflater; 16 | import android.view.View; 17 | import android.view.ViewGroup; 18 | import android.widget.BaseAdapter; 19 | import android.widget.ImageView; 20 | import android.widget.ListView; 21 | import android.widget.TextView; 22 | import android.widget.Toast; 23 | 24 | import java.io.File; 25 | import java.util.ArrayList; 26 | import java.util.List; 27 | 28 | /** 29 | * VR资源列表 30 | *

31 | * 32 | * @author Wythe 33 | */ 34 | public class VRDroidLister extends FragmentActivity { 35 | 36 | private final static String VR_FOLDER = "360Videos"; 37 | 38 | private List mVrVideoIcon = new ArrayList<>(); 39 | 40 | private long mBackPressedTime; 41 | 42 | private ListView mVrVideoList; 43 | 44 | private VRDroidAdapter mVrAdapter; 45 | 46 | @Override 47 | protected void onCreate(final Bundle savedInstanceState) { 48 | super.onCreate(savedInstanceState); 49 | this.setContentView(R.layout.droid_lister); 50 | this.mVrVideoList = (ListView) this.findViewById(R.id.vr_video_list); 51 | if (this.mVrVideoList != null) { 52 | this.mVrVideoList.setAdapter( 53 | this.mVrAdapter = new VRDroidAdapter() 54 | ); 55 | } 56 | if (this.mVrAdapter != null) { 57 | final File folder = new File(Environment.getExternalStorageDirectory() + File.separator + VR_FOLDER); 58 | if (!folder.exists()) { 59 | folder.mkdirs(); 60 | } 61 | final File[] files = folder.listFiles(); 62 | if (files.length > 0) { 63 | final String[] paths = new String[files.length]; 64 | for (int i = 0, l = files.length; i < l; i++) { 65 | paths[i] = files[i].getAbsolutePath(); 66 | } 67 | new VRIconTask().execute(paths); 68 | this.mVrAdapter.setFiles(files); 69 | } 70 | } 71 | } 72 | 73 | @Override 74 | public void onBackPressed() { 75 | final long mCurrentTime = System.currentTimeMillis(); 76 | if (mCurrentTime - this.mBackPressedTime > 1000) { 77 | Toast.makeText(this, R.string.app_logout, Toast.LENGTH_SHORT).show(); 78 | this.mBackPressedTime = mCurrentTime; 79 | return; 80 | } 81 | super.onBackPressed(); 82 | System.exit(0); 83 | } 84 | 85 | private final class VRDroidAdapter extends BaseAdapter { 86 | 87 | private File[] files; 88 | 89 | public void setFiles(final File[] files) { 90 | this.files = files; 91 | } 92 | 93 | @Override 94 | public int getCount() { 95 | return files != null ? files.length : 0; 96 | } 97 | 98 | @Override 99 | public Object getItem(int position) { 100 | return null; 101 | } 102 | 103 | @Override 104 | public long getItemId(int position) { 105 | return 0; 106 | } 107 | 108 | @Override 109 | public View getView(int position, View convertView, ViewGroup parent) { 110 | VRViewHolder holder = null; 111 | if (convertView != null) { 112 | holder = (VRViewHolder) convertView.getTag(); 113 | } else { 114 | convertView = LayoutInflater.from(VRDroidLister.this).inflate(R.layout.droid_item, null); 115 | if (convertView != null) { 116 | convertView.setTag( 117 | holder = new VRViewHolder(convertView) 118 | ); 119 | } 120 | } 121 | if (holder != null) { 122 | final File file = this.files[position]; 123 | if (file != null) { 124 | final String path = file.getAbsolutePath(); 125 | if (!TextUtils.isEmpty(path)) { 126 | final String name = this.getFileName(file); 127 | if (!TextUtils.isEmpty(name)) { 128 | holder.name.setText(name); 129 | } 130 | if (mVrVideoIcon.size() > position) { 131 | holder.icon.setImageBitmap(mVrVideoIcon.get(position)); 132 | } 133 | convertView.setOnClickListener(new View.OnClickListener() { 134 | @Override 135 | public void onClick(final View v) { 136 | final Intent intent = new Intent(); 137 | intent.putExtra(VRDroidPlayer.KEY_NAME, name); 138 | intent.putExtra(VRDroidPlayer.KEY_PATH, path); 139 | intent.setClass(VRDroidLister.this, VRDroidPlayer.class); 140 | startActivity(intent); 141 | } 142 | }); 143 | } 144 | } 145 | } 146 | return convertView; 147 | } 148 | 149 | private String getFileName(final File file) { 150 | final String name = file.getName(); 151 | if (!TextUtils.isEmpty(name)) { 152 | final int ext = name.lastIndexOf("."); 153 | if (ext > 0) { 154 | return name.substring(0, ext); 155 | } 156 | } 157 | return name; 158 | } 159 | 160 | } 161 | 162 | private final class VRViewHolder { 163 | final TextView name; 164 | final ImageView icon; 165 | 166 | public VRViewHolder(final View view) { 167 | this.name = (TextView) view.findViewById(R.id.vr_video_name); 168 | this.icon = (ImageView) view.findViewById(R.id.vr_video_icon); 169 | } 170 | } 171 | 172 | private final class VRIconTask extends AsyncTask { 173 | 174 | @Override 175 | protected Void doInBackground(final String... paths) { 176 | for (final String path : paths) { 177 | mVrVideoIcon.add(ThumbnailUtils.createVideoThumbnail(path, MediaStore.Video.Thumbnails.MICRO_KIND)); 178 | } 179 | return null; 180 | } 181 | 182 | @Override 183 | protected void onPostExecute(final Void aVoid) { 184 | if (mVrAdapter != null) { 185 | mVrAdapter.notifyDataSetChanged(); 186 | } 187 | } 188 | } 189 | 190 | } 191 | -------------------------------------------------------------------------------- /app-vrwidget/src/main/java/org/babysource/vrdroid/VRDroidPlayer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Created on 2016/3/31 3 | */ 4 | package org.babysource.vrdroid; 5 | 6 | import android.net.Uri; 7 | import android.os.Bundle; 8 | import android.support.v4.app.FragmentActivity; 9 | import android.text.TextUtils; 10 | import android.widget.TextView; 11 | 12 | import com.google.vr.sdk.widgets.common.VrWidgetView; 13 | import com.google.vr.sdk.widgets.video.VrVideoView; 14 | 15 | import java.io.File; 16 | import java.io.IOException; 17 | 18 | /** 19 | * VR资源播放 20 | *

21 | * 22 | * @author Wythe 23 | */ 24 | public class VRDroidPlayer extends FragmentActivity { 25 | 26 | final static String KEY_NAME = "_$KEY_NAME"; 27 | final static String KEY_PATH = "_$KEY_PATH"; 28 | 29 | private TextView mVrVideoName; 30 | 31 | private VrVideoView mVrVideoView; 32 | 33 | @Override 34 | public void onBackPressed() { 35 | super.onBackPressed(); 36 | this.finish(); 37 | } 38 | 39 | @Override 40 | protected void onDestroy() { 41 | if (this.mVrVideoView != null) { 42 | this.mVrVideoView.pauseRendering(); 43 | this.mVrVideoView.shutdown(); 44 | } 45 | super.onDestroy(); 46 | } 47 | 48 | @Override 49 | protected void onPause() { 50 | super.onPause(); 51 | if (this.mVrVideoView != null) { 52 | this.mVrVideoView.pauseVideo(); 53 | } 54 | } 55 | 56 | @Override 57 | protected void onResume() { 58 | super.onResume(); 59 | if (this.mVrVideoView != null) { 60 | this.mVrVideoView.playVideo(); 61 | } 62 | } 63 | 64 | @Override 65 | protected void onCreate(final Bundle savedInstanceState) { 66 | super.onCreate(savedInstanceState); 67 | this.setContentView(R.layout.droid_player); 68 | this.mVrVideoName = (TextView) this.findViewById(R.id.tv_video_name); 69 | if (this.mVrVideoName != null) { 70 | final String name = this.getIntent().getStringExtra(KEY_NAME); 71 | if (!TextUtils.isEmpty(name)) { 72 | this.mVrVideoName.setText(name); 73 | } 74 | } 75 | this.mVrVideoView = (VrVideoView) this.findViewById(R.id.vr_video_view); 76 | if (this.mVrVideoView != null) { 77 | final String path = this.getIntent().getStringExtra(KEY_PATH); 78 | if (!TextUtils.isEmpty(path)) { 79 | this.mVrVideoView.setDisplayMode( 80 | VrWidgetView.DisplayMode.FULLSCREEN_STEREO 81 | ); 82 | this.mVrVideoView.setInfoButtonEnabled(false); 83 | try { 84 | this.mVrVideoView.loadVideo( 85 | Uri.fromFile(new File(path)), new VrVideoView.Options() 86 | ); 87 | } catch (IOException e) { 88 | e.printStackTrace(); 89 | } 90 | } 91 | } 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /app-vrwidget/src/main/res/layout/droid_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | 18 | 19 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app-vrwidget/src/main/res/layout/droid_lister.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 19 | 20 | 21 | 22 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app-vrwidget/src/main/res/layout/droid_player.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app-vrwidget/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/app-vrwidget/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app-vrwidget/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/app-vrwidget/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app-vrwidget/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/app-vrwidget/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app-vrwidget/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/app-vrwidget/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app-vrwidget/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/app-vrwidget/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app-vrwidget/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | #DDDDDD 7 | #FFFFFF 8 | 9 | -------------------------------------------------------------------------------- /app-vrwidget/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /app-vrwidget/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | VRDroid-Vrview 3 | 本地资源 4 | 继续按返回键退出 5 | 6 | -------------------------------------------------------------------------------- /app-vrwidget/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.model.application' 2 | 3 | model { 4 | android { 5 | compileSdkVersion = 23 6 | buildToolsVersion = '23.0.3' 7 | 8 | defaultConfig { 9 | applicationId = 'com.babysource.vrdroid.camera' 10 | minSdkVersion.apiLevel = 21 11 | targetSdkVersion.apiLevel = 23 12 | } 13 | } 14 | 15 | android.buildTypes { 16 | debug { 17 | debuggable = true 18 | minifyEnabled = false 19 | multiDexEnabled = false 20 | shrinkResources = false 21 | zipAlignEnabled = true 22 | } 23 | release { 24 | debuggable = false 25 | minifyEnabled = false 26 | multiDexEnabled = false 27 | shrinkResources = true 28 | zipAlignEnabled = true 29 | proguardFiles.add(file('proguard-rules.pro')) 30 | } 31 | } 32 | 33 | android.packagingOptions { 34 | exclude 'META-INF/DEPENDENCIES' 35 | exclude 'META-INF/LICENSE.txt' 36 | exclude 'META-INF/LICENSE' 37 | exclude 'META-INF/NOTICE.txt' 38 | exclude 'META-INF/NOTICE' 39 | } 40 | 41 | android.lintOptions { 42 | abortOnError = false 43 | } 44 | } 45 | 46 | dependencies { 47 | compile project(':libraries:base') 48 | compile project(':libraries:common') 49 | compile 'com.android.support:appcompat-v7:23.2.1' 50 | compile 'com.google.protobuf.nano:protobuf-javanano:3.1.0' 51 | } 52 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\adt-bundle-windows-x86_64-20131030\Android_Studio_sdk\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 18 | 19 | 22 | 23 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /app/src/main/java/org/babysource/vrdroid/VRDroidBuilder.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Created on 2016/4/21 3 | */ 4 | package org.babysource.vrdroid; 5 | 6 | import android.opengl.GLES20; 7 | 8 | import javax.microedition.khronos.opengles.GL10; 9 | 10 | /** 11 | *

12 | * 13 | * @author Wythe 14 | */ 15 | public final class VRDroidBuilder { 16 | 17 | final static int GL_CAMERA_OES = 0x8D65; 18 | 19 | final static int MAX_PREVIEW_WIDE = 1920; 20 | 21 | final static int MAX_PREVIEW_HIGH = 1080; 22 | 23 | final static String ATTR_POSITION = "a_Position"; 24 | 25 | final static String ATTR_TEXCOORD = "a_Texcoord"; 26 | 27 | // 顶点坐标个数 28 | final static int COORDS_PER_VERTEX = 2; 29 | 30 | // 顶点绘制顺序 31 | final static short ORDER_VERTICES[] = { 32 | 0, 3, 2, 0, 2, 1 33 | }; 34 | 35 | // 定义平面顶点 36 | final static float PLANE_VERTICES[] = { 37 | -1.0F, 1.0F, // 0:左上角 38 | 1.0F, 1.0F, // 1:右上角 39 | 1.0F, -1.0F, // 2:右下角 40 | -1.0F, -1.0F, // 3:左下角 41 | }; 42 | 43 | // 定义纹理顶点 44 | final static float FRAME_VERTICES[] = { 45 | 0.0f, 0.0f, // 0:左上角 46 | 1.0f, 0.0f, // 1:右上角 47 | 1.0f, 1.0f, // 2:右下角 48 | 0.0f, 1.0f // 3:左下角 49 | }; 50 | 51 | // 顶点绘制程序 52 | final static String VERTEX_SHADER_CODE = 53 | "attribute vec4 " + ATTR_POSITION + ";" + 54 | "attribute vec2 " + ATTR_TEXCOORD + ";" + 55 | "varying vec2 v_Texcoord;" + 56 | "void main() {" + 57 | " v_Texcoord = " + ATTR_TEXCOORD + ";" + 58 | " gl_Position = " + ATTR_POSITION + ";" + 59 | "}"; 60 | 61 | // 外观绘制程序 62 | final static String FACADE_SHADER_CODE = 63 | "#extension GL_OES_EGL_image_external : require\n" + 64 | "precision mediump float;" + 65 | "varying vec2 v_Texcoord;" + 66 | "uniform samplerExternalOES s_Texture;" + 67 | "void main() {" + 68 | " gl_FragColor = texture2D(s_Texture, v_Texcoord);" + 69 | "}"; 70 | 71 | final static int createTexture() { 72 | final int[] textures = new int[1]; 73 | GLES20.glGenTextures(1, textures, 0); 74 | GLES20.glBindTexture(VRDroidBuilder.GL_CAMERA_OES, textures[0]); 75 | GLES20.glTexParameterf(VRDroidBuilder.GL_CAMERA_OES, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); 76 | GLES20.glTexParameterf(VRDroidBuilder.GL_CAMERA_OES, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); 77 | GLES20.glTexParameteri(VRDroidBuilder.GL_CAMERA_OES, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE); 78 | GLES20.glTexParameteri(VRDroidBuilder.GL_CAMERA_OES, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE); 79 | return textures[0]; 80 | } 81 | 82 | final static int fitPreviewWide(final int wide) { 83 | if (wide < 0) { 84 | return 0; 85 | } 86 | return wide > MAX_PREVIEW_WIDE ? MAX_PREVIEW_WIDE : wide; 87 | } 88 | 89 | final static int fitPreviewHigh(final int high) { 90 | if (high < 0) { 91 | return 0; 92 | } 93 | return high > MAX_PREVIEW_HIGH ? MAX_PREVIEW_HIGH : high; 94 | } 95 | 96 | final static int loadGLShader(final int type, final String code) { 97 | int shader = GLES20.glCreateShader(type); 98 | GLES20.glShaderSource(shader, code); 99 | GLES20.glCompileShader(shader); 100 | // 校验编译状态 101 | final int[] compileStatus = new int[1]; 102 | GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compileStatus, 0); 103 | if (compileStatus[0] == 0) { 104 | GLES20.glDeleteShader(shader); 105 | shader = 0; 106 | } 107 | if (shader == 0) { 108 | throw new RuntimeException("Creating shader error."); 109 | } 110 | return shader; 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /app/src/main/java/org/babysource/vrdroid/VRDroidCamera.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Created on 2016/3/31 3 | */ 4 | package org.babysource.vrdroid; 5 | 6 | import android.Manifest; 7 | import android.content.pm.PackageManager; 8 | import android.graphics.SurfaceTexture; 9 | import android.hardware.Camera; 10 | import android.opengl.GLES20; 11 | import android.os.Bundle; 12 | import android.support.v4.app.ActivityCompat; 13 | import android.widget.Toast; 14 | 15 | import com.google.vr.sdk.base.Eye; 16 | import com.google.vr.sdk.base.GvrActivity; 17 | import com.google.vr.sdk.base.GvrView; 18 | import com.google.vr.sdk.base.HeadTransform; 19 | import com.google.vr.sdk.base.Viewport; 20 | 21 | import java.io.IOException; 22 | import java.nio.ByteBuffer; 23 | import java.nio.ByteOrder; 24 | import java.nio.FloatBuffer; 25 | import java.nio.ShortBuffer; 26 | 27 | import javax.microedition.khronos.egl.EGLConfig; 28 | 29 | /** 30 | * VR资源列表 31 | *

32 | * 33 | * @author Wythe 34 | */ 35 | public class VRDroidCamera extends GvrActivity implements GvrView.StereoRenderer { 36 | 37 | private final float[] mRes = new float[16]; 38 | 39 | private final float[] mRhs = new float[16]; 40 | 41 | private long mBackPressedTime; 42 | 43 | private int mTarget; 44 | 45 | private int mProgram; 46 | 47 | private Camera mCamera; 48 | 49 | private ShortBuffer mOrderBuffer; 50 | 51 | private FloatBuffer mPlaneBuffer; 52 | 53 | private FloatBuffer mFrameBuffer; 54 | 55 | private GvrView mGvrView; 56 | 57 | private SurfaceTexture mCameraTexture; 58 | 59 | @Override 60 | protected void onCreate(final Bundle savedInstanceState) { 61 | super.onCreate(savedInstanceState); 62 | this.setContentView(R.layout.droid_lister); 63 | this.mGvrView = (GvrView) this.findViewById(R.id.gvr_view); 64 | if (this.mGvrView != null) { 65 | this.setGvrView(this.mGvrView); 66 | // 设置视图 67 | this.mGvrView.setRenderer(this); 68 | this.mGvrView.setStereoModeEnabled(true); 69 | this.mGvrView.setTransitionViewEnabled(true); 70 | } 71 | } 72 | 73 | @Override 74 | protected void onPause() { 75 | super.onPause(); 76 | if (this.mGvrView != null) { 77 | this.mGvrView.onPause(); 78 | } 79 | } 80 | 81 | @Override 82 | protected void onResume() { 83 | super.onResume(); 84 | if (this.mGvrView != null) { 85 | this.mGvrView.onResume(); 86 | } 87 | } 88 | 89 | @Override 90 | protected void onDestroy() { 91 | this.shutCamera(); 92 | super.onDestroy(); 93 | } 94 | 95 | @Override 96 | public void onBackPressed() { 97 | final long mCurrentTime = System.currentTimeMillis(); 98 | if (mCurrentTime - this.mBackPressedTime > 1000) { 99 | Toast.makeText(this, R.string.app_logout, Toast.LENGTH_SHORT).show(); 100 | this.mBackPressedTime = mCurrentTime; 101 | return; 102 | } 103 | super.onBackPressed(); 104 | System.exit(0); 105 | } 106 | 107 | @Override 108 | public void onRendererShutdown() { 109 | this.shutCamera(); 110 | } 111 | 112 | @Override 113 | public void onDrawEye(final Eye eye) { 114 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); 115 | // 初始绘制 116 | GLES20.glUseProgram(this.mProgram); 117 | GLES20.glActiveTexture(VRDroidBuilder.GL_CAMERA_OES); 118 | GLES20.glBindTexture(VRDroidBuilder.GL_CAMERA_OES, this.mTarget); 119 | // 绘制平面 120 | final int mPositionHandle = GLES20.glGetAttribLocation(this.mProgram, VRDroidBuilder.ATTR_POSITION); 121 | GLES20.glEnableVertexAttribArray(mPositionHandle); 122 | GLES20.glVertexAttribPointer(mPositionHandle, VRDroidBuilder.COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, VRDroidBuilder.COORDS_PER_VERTEX * 4, this.mPlaneBuffer); 123 | // 绘制纹理 124 | final int mTexCoordHandle = GLES20.glGetAttribLocation(this.mProgram, VRDroidBuilder.ATTR_TEXCOORD); 125 | GLES20.glEnableVertexAttribArray(mTexCoordHandle); 126 | GLES20.glVertexAttribPointer(mTexCoordHandle, VRDroidBuilder.COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, VRDroidBuilder.COORDS_PER_VERTEX * 4, this.mFrameBuffer); 127 | // 顺序绘制 128 | GLES20.glDrawElements(GLES20.GL_TRIANGLES, VRDroidBuilder.ORDER_VERTICES.length, GLES20.GL_UNSIGNED_SHORT, this.mOrderBuffer); 129 | GLES20.glDisableVertexAttribArray(mPositionHandle); 130 | GLES20.glDisableVertexAttribArray(mTexCoordHandle); 131 | android.opengl.Matrix.multiplyMM(this.mRes, 0, eye.getEyeView(), 0, this.mRhs, 0); 132 | } 133 | 134 | @Override 135 | public void onNewFrame(final HeadTransform headTransform) { 136 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); 137 | if (this.mCameraTexture != null) { 138 | this.mCameraTexture.updateTexImage(); 139 | } 140 | } 141 | 142 | @Override 143 | public void onFinishFrame(final Viewport viewport) { 144 | } 145 | 146 | @Override 147 | public void onSurfaceCreated(final EGLConfig eglConfig) { 148 | GLES20.glClearColor(0.1F, 0.1F, 0.1F, 0.5F); 149 | // 初始绘制顺序缓冲 150 | final ByteBuffer orderBuffer = ByteBuffer.allocateDirect(VRDroidBuilder.ORDER_VERTICES.length * 2).order(ByteOrder.nativeOrder()); 151 | this.mOrderBuffer = orderBuffer.asShortBuffer(); 152 | this.mOrderBuffer.put(VRDroidBuilder.ORDER_VERTICES); 153 | this.mOrderBuffer.position(0); 154 | // 初始平面顶点缓冲 155 | final ByteBuffer planeBuffer = ByteBuffer.allocateDirect(VRDroidBuilder.PLANE_VERTICES.length * 4).order(ByteOrder.nativeOrder()); 156 | this.mPlaneBuffer = planeBuffer.asFloatBuffer(); 157 | this.mPlaneBuffer.put(VRDroidBuilder.PLANE_VERTICES); 158 | this.mPlaneBuffer.position(0); 159 | // 初始纹理顶点缓冲 160 | final ByteBuffer frameBuffer = ByteBuffer.allocateDirect(VRDroidBuilder.FRAME_VERTICES.length * 4).order(ByteOrder.nativeOrder()); 161 | this.mFrameBuffer = frameBuffer.asFloatBuffer(); 162 | this.mFrameBuffer.put(VRDroidBuilder.FRAME_VERTICES); 163 | this.mFrameBuffer.position(0); 164 | // 创建绘制应用程序 165 | this.mProgram = GLES20.glCreateProgram(); 166 | GLES20.glAttachShader(this.mProgram, VRDroidBuilder.loadGLShader(GLES20.GL_VERTEX_SHADER, VRDroidBuilder.VERTEX_SHADER_CODE)); 167 | GLES20.glAttachShader(this.mProgram, VRDroidBuilder.loadGLShader(GLES20.GL_FRAGMENT_SHADER, VRDroidBuilder.FACADE_SHADER_CODE)); 168 | GLES20.glLinkProgram(this.mProgram); 169 | // 打开摄像头 170 | this.openCamera(); 171 | } 172 | 173 | @Override 174 | public void onSurfaceChanged(final int i0, final int i1) { 175 | } 176 | 177 | private void openCamera() { 178 | if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { 179 | this.mCamera = Camera.open(); 180 | if (this.mCamera != null) { 181 | (this.mCameraTexture = new SurfaceTexture( 182 | this.mTarget = VRDroidBuilder.createTexture() 183 | )).setDefaultBufferSize(VRDroidBuilder.fitPreviewWide(mGvrView.getWidth()), VRDroidBuilder.fitPreviewHigh(mGvrView.getHeight())); 184 | try { 185 | this.mCamera.setPreviewTexture(this.mCameraTexture); 186 | } catch (IOException e) { 187 | e.printStackTrace(); 188 | this.mCamera.release(); 189 | return; 190 | } 191 | // 开始偷窥 192 | this.mCamera.startPreview(); 193 | } 194 | } 195 | } 196 | 197 | private void shutCamera() { 198 | if (this.mCamera != null) { 199 | this.mCamera.release(); 200 | this.mCamera = null; 201 | } 202 | } 203 | 204 | } 205 | -------------------------------------------------------------------------------- /app/src/main/java/org/babysource/vrdroid/VRDroidCamera2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Created on 2016/3/31 3 | */ 4 | package org.babysource.vrdroid; 5 | 6 | import android.Manifest; 7 | import android.content.Context; 8 | import android.content.pm.PackageManager; 9 | import android.graphics.SurfaceTexture; 10 | import android.hardware.camera2.CameraAccessException; 11 | import android.hardware.camera2.CameraCaptureSession; 12 | import android.hardware.camera2.CameraCharacteristics; 13 | import android.hardware.camera2.CameraDevice; 14 | import android.hardware.camera2.CameraManager; 15 | import android.hardware.camera2.CaptureRequest; 16 | import android.opengl.GLES20; 17 | import android.os.Bundle; 18 | import android.os.Handler; 19 | import android.os.HandlerThread; 20 | import android.support.v4.app.ActivityCompat; 21 | import android.view.Surface; 22 | import android.widget.Toast; 23 | 24 | import com.google.vr.sdk.base.Eye; 25 | import com.google.vr.sdk.base.GvrActivity; 26 | import com.google.vr.sdk.base.GvrView; 27 | import com.google.vr.sdk.base.HeadTransform; 28 | import com.google.vr.sdk.base.Viewport; 29 | 30 | import java.nio.ByteBuffer; 31 | import java.nio.ByteOrder; 32 | import java.nio.FloatBuffer; 33 | import java.nio.ShortBuffer; 34 | import java.util.Arrays; 35 | import java.util.concurrent.Semaphore; 36 | 37 | import javax.microedition.khronos.egl.EGLConfig; 38 | 39 | /** 40 | * VR资源列表 41 | *

42 | * 43 | * @author Wythe 44 | */ 45 | public class VRDroidCamera2 extends GvrActivity implements GvrView.StereoRenderer { 46 | 47 | private final Semaphore mCameraLocker = new Semaphore(1); 48 | 49 | private final float[] mRes = new float[16]; 50 | 51 | private final float[] mRhs = new float[16]; 52 | 53 | private long mBackPressedTime; 54 | 55 | private int mTarget; 56 | 57 | private int mProgram; 58 | 59 | private GvrView mGvrView; 60 | 61 | private Handler mCameraHandle; 62 | 63 | private ShortBuffer mOrderBuffer; 64 | 65 | private FloatBuffer mPlaneBuffer; 66 | 67 | private FloatBuffer mFrameBuffer; 68 | 69 | private CameraDevice mCameraDevice; 70 | 71 | private HandlerThread mCameraThread; 72 | 73 | private CameraManager mCameraManager; 74 | 75 | private SurfaceTexture mCameraTexture; 76 | 77 | private CaptureRequest.Builder mCameraBuilder; 78 | 79 | @Override 80 | protected void onCreate(final Bundle savedInstanceState) { 81 | super.onCreate(savedInstanceState); 82 | this.setContentView(R.layout.droid_lister); 83 | this.mGvrView = (GvrView) this.findViewById(R.id.gvr_view); 84 | if (this.mGvrView != null) { 85 | this.setGvrView(this.mGvrView); 86 | // 设置视图 87 | this.mGvrView.setRenderer(this); 88 | this.mGvrView.setStereoModeEnabled(true); 89 | this.mGvrView.setTransitionViewEnabled(true); 90 | } 91 | } 92 | 93 | @Override 94 | protected void onPause() { 95 | super.onPause(); 96 | if (this.mGvrView != null) { 97 | this.mGvrView.onPause(); 98 | } 99 | } 100 | 101 | @Override 102 | protected void onResume() { 103 | super.onResume(); 104 | if (this.mGvrView != null) { 105 | this.mGvrView.onResume(); 106 | } 107 | } 108 | 109 | @Override 110 | protected void onDestroy() { 111 | this.shutCamera(); 112 | super.onDestroy(); 113 | } 114 | 115 | @Override 116 | public void onBackPressed() { 117 | final long mCurrentTime = System.currentTimeMillis(); 118 | if (mCurrentTime - this.mBackPressedTime > 1000) { 119 | Toast.makeText(this, R.string.app_logout, Toast.LENGTH_SHORT).show(); 120 | this.mBackPressedTime = mCurrentTime; 121 | return; 122 | } 123 | super.onBackPressed(); 124 | System.exit(0); 125 | } 126 | 127 | @Override 128 | public void onRendererShutdown() { 129 | this.shutCamera(); 130 | } 131 | 132 | @Override 133 | public void onDrawEye(final Eye eye) { 134 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); 135 | // 初始绘制 136 | GLES20.glUseProgram(this.mProgram); 137 | GLES20.glActiveTexture(VRDroidBuilder.GL_CAMERA_OES); 138 | GLES20.glBindTexture(VRDroidBuilder.GL_CAMERA_OES, this.mTarget); 139 | // 绘制平面 140 | final int mPositionHandle = GLES20.glGetAttribLocation(this.mProgram, VRDroidBuilder.ATTR_POSITION); 141 | GLES20.glEnableVertexAttribArray(mPositionHandle); 142 | GLES20.glVertexAttribPointer(mPositionHandle, VRDroidBuilder.COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, VRDroidBuilder.COORDS_PER_VERTEX * 4, this.mPlaneBuffer); 143 | // 绘制纹理 144 | final int mTexCoordHandle = GLES20.glGetAttribLocation(this.mProgram, VRDroidBuilder.ATTR_TEXCOORD); 145 | GLES20.glEnableVertexAttribArray(mTexCoordHandle); 146 | GLES20.glVertexAttribPointer(mTexCoordHandle, VRDroidBuilder.COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, VRDroidBuilder.COORDS_PER_VERTEX * 4, this.mFrameBuffer); 147 | // 顺序绘制 148 | GLES20.glDrawElements(GLES20.GL_TRIANGLES, VRDroidBuilder.ORDER_VERTICES.length, GLES20.GL_UNSIGNED_SHORT, this.mOrderBuffer); 149 | GLES20.glDisableVertexAttribArray(mPositionHandle); 150 | GLES20.glDisableVertexAttribArray(mTexCoordHandle); 151 | android.opengl.Matrix.multiplyMM(this.mRes, 0, eye.getEyeView(), 0, this.mRhs, 0); 152 | } 153 | 154 | @Override 155 | public void onNewFrame(final HeadTransform headTransform) { 156 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); 157 | if (this.mCameraTexture != null) { 158 | this.mCameraTexture.updateTexImage(); 159 | } 160 | } 161 | 162 | @Override 163 | public void onFinishFrame(final Viewport viewport) { 164 | } 165 | 166 | @Override 167 | public void onSurfaceCreated(final EGLConfig eglConfig) { 168 | GLES20.glClearColor(0.1F, 0.1F, 0.1F, 0.5F); 169 | // 初始绘制顺序缓冲 170 | final ByteBuffer orderBuffer = ByteBuffer.allocateDirect(VRDroidBuilder.ORDER_VERTICES.length * 2).order(ByteOrder.nativeOrder()); 171 | this.mOrderBuffer = orderBuffer.asShortBuffer(); 172 | this.mOrderBuffer.put(VRDroidBuilder.ORDER_VERTICES); 173 | this.mOrderBuffer.position(0); 174 | // 初始平面顶点缓冲 175 | final ByteBuffer planeBuffer = ByteBuffer.allocateDirect(VRDroidBuilder.PLANE_VERTICES.length * 4).order(ByteOrder.nativeOrder()); 176 | this.mPlaneBuffer = planeBuffer.asFloatBuffer(); 177 | this.mPlaneBuffer.put(VRDroidBuilder.PLANE_VERTICES); 178 | this.mPlaneBuffer.position(0); 179 | // 初始纹理顶点缓冲 180 | final ByteBuffer frameBuffer = ByteBuffer.allocateDirect(VRDroidBuilder.FRAME_VERTICES.length * 4).order(ByteOrder.nativeOrder()); 181 | this.mFrameBuffer = frameBuffer.asFloatBuffer(); 182 | this.mFrameBuffer.put(VRDroidBuilder.FRAME_VERTICES); 183 | this.mFrameBuffer.position(0); 184 | // 创建绘制应用程序 185 | this.mProgram = GLES20.glCreateProgram(); 186 | GLES20.glAttachShader(this.mProgram, VRDroidBuilder.loadGLShader(GLES20.GL_VERTEX_SHADER, VRDroidBuilder.VERTEX_SHADER_CODE)); 187 | GLES20.glAttachShader(this.mProgram, VRDroidBuilder.loadGLShader(GLES20.GL_FRAGMENT_SHADER, VRDroidBuilder.FACADE_SHADER_CODE)); 188 | GLES20.glLinkProgram(this.mProgram); 189 | // 打开摄像头 190 | this.openCamera(); 191 | } 192 | 193 | @Override 194 | public void onSurfaceChanged(final int i0, final int i1) { 195 | } 196 | 197 | private void openCamera() { 198 | if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { 199 | this.mCameraManager = (CameraManager) this.getSystemService(Context.CAMERA_SERVICE); 200 | if (this.mCameraManager != null) { 201 | this.openCameraThread(); 202 | try { 203 | for (final String cameraId : this.mCameraManager.getCameraIdList()) { 204 | CameraCharacteristics characteristics = this.mCameraManager.getCameraCharacteristics(cameraId); 205 | if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_BACK) { 206 | this.mCameraManager.openCamera(cameraId, this.mCameraStateCallback, this.mCameraHandle); 207 | return; 208 | } 209 | } 210 | } catch (CameraAccessException e) { 211 | e.printStackTrace(); 212 | } 213 | } 214 | } 215 | } 216 | 217 | private void shutCamera() { 218 | try { 219 | this.mCameraLocker.acquire(); 220 | if (this.mCameraDevice != null) { 221 | this.mCameraDevice.close(); 222 | this.mCameraDevice = null; 223 | } 224 | } catch (InterruptedException e) { 225 | e.printStackTrace(); 226 | } finally { 227 | this.mCameraLocker.release(); 228 | } 229 | this.stopCameraThread(); 230 | } 231 | 232 | private void openCameraThread() { 233 | this.mCameraThread = new HandlerThread("VRCamera"); 234 | this.mCameraThread.start(); 235 | this.mCameraHandle = new Handler( 236 | this.mCameraThread.getLooper() 237 | ); 238 | } 239 | 240 | private void stopCameraThread() { 241 | this.mCameraThread.quitSafely(); 242 | try { 243 | this.mCameraThread.join(); 244 | this.mCameraThread = null; 245 | this.mCameraHandle = null; 246 | } catch (InterruptedException e) { 247 | e.printStackTrace(); 248 | } 249 | } 250 | 251 | private final CameraDevice.StateCallback mCameraStateCallback = new CameraDevice.StateCallback() { 252 | @Override 253 | public void onError(final CameraDevice cameraDevice, final int error) { 254 | mCameraLocker.release(); 255 | cameraDevice.close(); 256 | mCameraDevice = null; 257 | } 258 | 259 | @Override 260 | public void onOpened(final CameraDevice cameraDevice) { 261 | mCameraLocker.release(); 262 | mCameraDevice = cameraDevice; 263 | mCameraTexture = new SurfaceTexture( 264 | mTarget = VRDroidBuilder.createTexture() 265 | ); 266 | try { 267 | mCameraBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 268 | } catch (CameraAccessException e) { 269 | e.printStackTrace(); 270 | mCameraBuilder = null; 271 | } 272 | if (mCameraBuilder != null) { 273 | final Surface surface = new Surface(mCameraTexture); 274 | if (surface != null) { 275 | mCameraBuilder.addTarget(surface); 276 | mCameraTexture.setDefaultBufferSize( 277 | VRDroidBuilder.fitPreviewWide(mGvrView.getWidth()), VRDroidBuilder.fitPreviewHigh(mGvrView.getHeight()) 278 | ); 279 | try { 280 | mCameraDevice.createCaptureSession(Arrays.asList(surface), mCameraCaptureSessionCallback, mCameraHandle); 281 | } catch (CameraAccessException e) { 282 | e.printStackTrace(); 283 | } 284 | } 285 | } 286 | } 287 | 288 | @Override 289 | public void onDisconnected(final CameraDevice cameraDevice) { 290 | mCameraLocker.release(); 291 | cameraDevice.close(); 292 | mCameraDevice = null; 293 | } 294 | }; 295 | 296 | private final CameraCaptureSession.StateCallback mCameraCaptureSessionCallback = new CameraCaptureSession.StateCallback() { 297 | @Override 298 | public void onConfigured(final CameraCaptureSession session) { 299 | mCameraBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); 300 | try { 301 | session.setRepeatingRequest(mCameraBuilder.build(), null, mCameraHandle); 302 | } catch (CameraAccessException e) { 303 | e.printStackTrace(); 304 | } 305 | } 306 | 307 | @Override 308 | public void onConfigureFailed(final CameraCaptureSession session) { 309 | 310 | } 311 | }; 312 | 313 | } 314 | -------------------------------------------------------------------------------- /app/src/main/res/layout/droid_lister.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | #DDDDDD 7 | #FFFFFF 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | VRDroid-Camera 3 | 继续按返回键退出 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 4 | mavenCentral() 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle-experimental:0.7.3' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 15 | mavenCentral() 16 | jcenter() 17 | } 18 | } 19 | 20 | task clean(type: Delete) { 21 | delete rootProject.buildDir 22 | } 23 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | org.gradle.jvmargs=-Xmx2048M -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Sep 23 10:48:47 CST 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /libraries/audio/audio.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/libraries/audio/audio.aar -------------------------------------------------------------------------------- /libraries/audio/build.gradle: -------------------------------------------------------------------------------- 1 | configurations.create("default") 2 | artifacts.add("default", file('audio.aar')) -------------------------------------------------------------------------------- /libraries/base/base.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/libraries/base/base.aar -------------------------------------------------------------------------------- /libraries/base/build.gradle: -------------------------------------------------------------------------------- 1 | configurations.create("default") 2 | artifacts.add("default", file('base.aar')) -------------------------------------------------------------------------------- /libraries/common/build.gradle: -------------------------------------------------------------------------------- 1 | configurations.create("default") 2 | artifacts.add("default", file('common.aar')) -------------------------------------------------------------------------------- /libraries/common/common.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/libraries/common/common.aar -------------------------------------------------------------------------------- /libraries/commonwidget/build.gradle: -------------------------------------------------------------------------------- 1 | configurations.create("default") 2 | artifacts.add("default", file('commonwidget.aar')) -------------------------------------------------------------------------------- /libraries/commonwidget/commonwidget.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/libraries/commonwidget/commonwidget.aar -------------------------------------------------------------------------------- /libraries/controller/build.gradle: -------------------------------------------------------------------------------- 1 | configurations.create("default") 2 | artifacts.add("default", file('controller.aar')) -------------------------------------------------------------------------------- /libraries/controller/controller.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/libraries/controller/controller.aar -------------------------------------------------------------------------------- /libraries/panowidget/build.gradle: -------------------------------------------------------------------------------- 1 | configurations.create("default") 2 | artifacts.add("default", file('panowidget.aar')) -------------------------------------------------------------------------------- /libraries/panowidget/panowidget.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/libraries/panowidget/panowidget.aar -------------------------------------------------------------------------------- /libraries/videowidget/build.gradle: -------------------------------------------------------------------------------- 1 | configurations.create("default") 2 | artifacts.add("default", file('videowidget.aar')) 3 | -------------------------------------------------------------------------------- /libraries/videowidget/videowidget.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babysource/VRDroid/93bd16e55cba36c08e93044fa97aed2916623af2/libraries/videowidget/videowidget.aar -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | include ':app-malivr' 3 | include ':app-rajawali' 4 | include ':app-vrwidget' 5 | include ':libraries:base' 6 | include ':libraries:audio' 7 | include ':libraries:common' 8 | include ':libraries:controller' 9 | include ':libraries:panowidget' 10 | include ':libraries:videowidget' 11 | include ':libraries:commonwidget' 12 | --------------------------------------------------------------------------------