├── .gitignore ├── RajawaliVR ├── .gitignore ├── build.gradle ├── gradle.properties ├── libs │ ├── armeabi-v7a │ │ ├── libvraudio_engine.so │ │ └── libvrtoolkit.so │ ├── audio.jar │ └── cardboard.jar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── vr │ │ └── rajawali3d │ │ └── org │ │ └── rajawalivr │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── org │ │ └── rajawali3d │ │ └── vr │ │ ├── RajawaliVRActivity.java │ │ ├── materials │ │ └── shaders │ │ │ ├── HotspotFragmentShader.java │ │ │ └── HotspotMaterial.java │ │ ├── renderer │ │ └── RajawaliVRRenderer.java │ │ ├── surface │ │ └── RajawaliVRSurfaceView.java │ │ └── ui │ │ ├── CardboardOverlayView.java │ │ └── GestureListener.java │ └── res │ └── values │ └── strings.xml ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── me │ │ └── substarry │ │ └── vrplayer │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── me │ │ └── substarry │ │ └── vrplayer │ │ ├── ListActivity.java │ │ ├── MainActivity.java │ │ ├── MyAdapter.java │ │ ├── MyRenderer.java │ │ ├── ScreenUtils.java │ │ ├── Splash.java │ │ └── VideoRenderer.java │ └── res │ ├── drawable │ ├── pan.jpg │ ├── splash.png │ └── ss.jpg │ ├── layout │ ├── activity_fullscreen.xml │ ├── activity_list.xml │ ├── activity_main.xml │ ├── activity_splash.xml │ └── rowlayout.xml │ ├── menu │ ├── menu_list.xml │ ├── menu_main.xml │ └── menu_splash.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── raw │ ├── demo.mp4 │ └── ss.jpg │ ├── values-v11 │ └── styles.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── attrs.xml │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── config.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Log Files 12 | *.log 13 | 14 | # Android generated 15 | bin 16 | gen 17 | obj 18 | lint.xml 19 | 20 | # IntelliJ IDEA 21 | .idea 22 | *.iml 23 | *.ipr 24 | *.iws 25 | classes 26 | gen-external-apklibs 27 | 28 | # Eclipse 29 | .project 30 | .classpath 31 | .settings 32 | .checkstyle 33 | .cproject 34 | 35 | # Gradle 36 | .gradle 37 | build 38 | out 39 | 40 | # Maven 41 | target 42 | release.properties 43 | pom.xml.* 44 | 45 | # Ant 46 | ant.properties 47 | local.properties 48 | proguard.cfg 49 | proguard-project.txt 50 | 51 | # Other 52 | .DS_Store 53 | dist 54 | tmp 55 | /captures 56 | -------------------------------------------------------------------------------- /RajawaliVR/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /RajawaliVR/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'signing' 3 | 4 | status = 'debug' 5 | 6 | android { 7 | compileSdkVersion rootProject.compileSdk 8 | buildToolsVersion rootProject.buildTools 9 | 10 | defaultConfig { 11 | minSdkVersion rootProject.minSdk 12 | targetSdkVersion rootProject.targetSdk 13 | versionCode rootProject.versionCode 14 | versionName rootProject.versionName 15 | } 16 | buildTypes { 17 | release { 18 | status = 'release' 19 | } 20 | } 21 | 22 | sourceSets { 23 | main { 24 | jniLibs.srcDirs = ['libs'] 25 | } 26 | } 27 | } 28 | 29 | dependencies { 30 | compile fileTree(dir: 'libs', include: ['*.jar']) 31 | compile rootProject.depRajawali 32 | compile rootProject.depAppCompat 33 | } 34 | -------------------------------------------------------------------------------- /RajawaliVR/gradle.properties: -------------------------------------------------------------------------------- 1 | VERSION_NAME = 1.0.0-SNAPSHOT 2 | VERSION_CODE = 1 3 | GROUP = org.rajawali3d.vr 4 | 5 | POM_NAME=RajawaliVR 6 | POM_ARTIFACT_ID=rajawalivr 7 | POM_PACKAGING=aar 8 | POM_DESCRIPTION=Android OpenGL ES 2.0 Engine, Cardboard Binding 9 | POM_URL=https://github.com/Rajawali/RajawaliVR 10 | POM_SCM_URL=https://github.com/Rajawali/RajawaliVR.git 11 | POM_SCM_CONNECTION=scm:git@github.com:MasDennis/RajawaliVR.git 12 | POM_SCM_DEV_CONNECTION=scm:git@github.com:MasDennis/RajawaliVR.git 13 | POM_LICENCE_NAME=The Apache Software License, Version 2.0 14 | POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt 15 | POM_LICENCE_DIST=repo 16 | POM_DEVELOPER_ID=MasDennis 17 | POM_DEVELOPER_NAME=Dennis Ippel 18 | POM_DEVELOPER_EMAIL=info@rozengain.com 19 | POM_DEVELOPER_ORGANIZATION=Rajawali 20 | POM_DEVELOPER_ORGANIZATION_URL=https://plus.google.com/u/0/communities/116529974266844528013 21 | -------------------------------------------------------------------------------- /RajawaliVR/libs/armeabi-v7a/libvraudio_engine.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/substarry/VRPlayer/8ad2c6dad39e6c2850da7ea7c2733d53bcde9059/RajawaliVR/libs/armeabi-v7a/libvraudio_engine.so -------------------------------------------------------------------------------- /RajawaliVR/libs/armeabi-v7a/libvrtoolkit.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/substarry/VRPlayer/8ad2c6dad39e6c2850da7ea7c2733d53bcde9059/RajawaliVR/libs/armeabi-v7a/libvrtoolkit.so -------------------------------------------------------------------------------- /RajawaliVR/libs/audio.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/substarry/VRPlayer/8ad2c6dad39e6c2850da7ea7c2733d53bcde9059/RajawaliVR/libs/audio.jar -------------------------------------------------------------------------------- /RajawaliVR/libs/cardboard.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/substarry/VRPlayer/8ad2c6dad39e6c2850da7ea7c2733d53bcde9059/RajawaliVR/libs/cardboard.jar -------------------------------------------------------------------------------- /RajawaliVR/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 /home/dennis/Android/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 | -------------------------------------------------------------------------------- /RajawaliVR/src/androidTest/java/vr/rajawali3d/org/rajawalivr/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package vr.rajawali3d.org.rajawalivr; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /RajawaliVR/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /RajawaliVR/src/main/java/org/rajawali3d/vr/RajawaliVRActivity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015 Dennis Ippel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | */ 13 | package org.rajawali3d.vr; 14 | 15 | import android.app.ActionBar; 16 | import android.hardware.SensorManager; 17 | import android.os.Bundle; 18 | import android.view.Display; 19 | import android.view.View; 20 | import android.view.ViewGroup; 21 | import android.view.WindowManager; 22 | 23 | import com.google.vrtoolkit.cardboard.CardboardActivity; 24 | import com.google.vrtoolkit.cardboard.CardboardView; 25 | 26 | import org.rajawali3d.vr.renderer.RajawaliVRRenderer; 27 | import org.rajawali3d.vr.surface.RajawaliVRSurfaceView; 28 | 29 | /** 30 | * @author dennis.ippel 31 | */ 32 | public class RajawaliVRActivity extends CardboardActivity { 33 | 34 | @Override 35 | public void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | 38 | CardboardView cardboardView = new CardboardView(this); 39 | 40 | addContentView(cardboardView, new ActionBar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT)); 41 | 42 | cardboardView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE 43 | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 44 | | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 45 | | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar 46 | | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar 47 | | View.SYSTEM_UI_FLAG_IMMERSIVE); 48 | 49 | setCardboardView(cardboardView); 50 | } 51 | 52 | protected void setRenderer(RajawaliVRRenderer renderer) { 53 | getCardboardView().setRenderer(renderer); 54 | } 55 | 56 | protected void setOnTouchListener(View.OnTouchListener listener){ 57 | getCardboardView().setOnTouchListener(listener); 58 | } 59 | 60 | protected void setVRModeEnabled(boolean enabled) { 61 | getCardboardView().setVRModeEnabled(enabled); 62 | } 63 | 64 | protected boolean getVRMode() { 65 | return getCardboardView().getVRMode(); 66 | } 67 | 68 | @Override 69 | public void onResume() { 70 | super.onResume(); 71 | } 72 | 73 | @Override 74 | public void onPause() { 75 | super.onPause(); 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /RajawaliVR/src/main/java/org/rajawali3d/vr/materials/shaders/HotspotFragmentShader.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015 Dennis Ippel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | */ 13 | 14 | package org.rajawali3d.vr.materials.shaders; 15 | 16 | import android.graphics.Color; 17 | import android.opengl.GLES20; 18 | 19 | import org.rajawali3d.materials.shaders.FragmentShader; 20 | import org.rajawali3d.math.vector.Vector2; 21 | 22 | /** 23 | * @author dennis.ippel 24 | */ 25 | public class HotspotFragmentShader extends FragmentShader { 26 | private RFloat mcPI; 27 | private RFloat mcTwoPI; 28 | 29 | private RVec2 muCircleCenter; 30 | private RVec2 mvTextureCoord; 31 | 32 | private RVec4 muTrackColor; 33 | private RVec4 muProgressColor; 34 | 35 | private RFloat muCircleRadius; 36 | private RFloat muBorderThickness; 37 | private RFloat muTextureRotationSpeed; 38 | private RFloat muProgress; 39 | private RFloat muTime; 40 | 41 | private RSampler2D muTexture; 42 | 43 | private float[] mCircleCenter = new float[] { 0.5f, 0.5f }; 44 | private float[] mTrackColor = new float[] { 0.7f, 0.7f, 0.7f, 1.0f }; 45 | private float[] mProgressColor = new float[] { 1.0f, 1.0f, 1.0f, 1.0f }; 46 | 47 | private float mCircleRadius = 0.4f; 48 | private float mBorderThickness = 0.05f; 49 | private float mTextureRotationSpeed = 2.0f; 50 | private float mProgress; 51 | 52 | private int muCircleCenterHandle; 53 | private int muTrackColorHandle; 54 | private int muProgressColorHandle; 55 | private int muCircleRadiusHandle; 56 | private int muBorderThicknessHandle; 57 | private int muTextureRotationSpeedHandle; 58 | private int muProgressHandle; 59 | private int muTextureHandle; 60 | 61 | private boolean mUseTexture; 62 | private boolean mDiscardAlpha; 63 | 64 | public HotspotFragmentShader(boolean useTexture) { 65 | this(useTexture, false); 66 | } 67 | 68 | public HotspotFragmentShader(boolean useTexture, boolean discardalpha) { 69 | super(); 70 | 71 | mUseTexture = useTexture; 72 | mDiscardAlpha = discardalpha; 73 | 74 | initialize(); 75 | } 76 | 77 | @Override 78 | public void initialize() { 79 | super.initialize(); 80 | 81 | addPrecisionQualifier(DataType.FLOAT, Precision.MEDIUMP); 82 | 83 | mcPI = (RFloat) addConst("PI", Math.PI); 84 | mcTwoPI = (RFloat) addConst("TWO_PI", Math.PI * 2.0); 85 | 86 | mvTextureCoord = (RVec2) addVarying(DefaultShaderVar.V_TEXTURE_COORD); 87 | 88 | muCircleCenter = (RVec2) addUniform("uCircleCenter", DataType.VEC2); 89 | 90 | muTrackColor = (RVec4) addUniform("uTrackColor", DataType.VEC4); 91 | muProgressColor = (RVec4) addUniform("uProgressColor", DataType.VEC4); 92 | 93 | muCircleRadius = (RFloat) addUniform("uCircleRadius", DataType.FLOAT); 94 | muBorderThickness = (RFloat) addUniform("uBorderThickness", DataType.FLOAT); 95 | muProgress = (RFloat) addUniform("uProgress", DataType.FLOAT); 96 | 97 | muTime = (RFloat) addUniform(DefaultShaderVar.U_TIME); 98 | 99 | muTexture = (RSampler2D) addUniform("uProgressTexture", DataType.SAMPLER2D); 100 | 101 | if(mUseTexture) 102 | muTextureRotationSpeed = (RFloat) addUniform("uTextureRotationSpeed", DataType.FLOAT); 103 | } 104 | 105 | @Override 106 | public void main() { 107 | // vec2 uv = fragCoord.xy / iResolution.xy; 108 | RVec2 uv = new RVec2("uv", mvTextureCoord); 109 | // float circleBorderHalf = circleBorder * 0.5; 110 | RFloat circleBorderHalf = new RFloat("circleBorderHalf"); 111 | circleBorderHalf.assign(muBorderThickness.multiply(0.5f)); 112 | 113 | // float dist = distance(uv, circleCenter); 114 | ShaderVar dist = distance(uv, muCircleCenter); 115 | 116 | RVec4 outColor = new RVec4("outColor", new RVec4("vec4(0.0)")); 117 | //outColor.a().assign(0.0f); 118 | 119 | if(mUseTexture) { 120 | // float yScale = sin(iGlobalTime * textureRotationSpeed) * 0.5 + 0.5; 121 | ShaderVar yScale = sin(muTime.multiply(muTextureRotationSpeed)).multiply(0.5f).add(0.5f); 122 | RFloat one = new RFloat("one", new RFloat(1.0f)); 123 | //one.assign(1.0f); 124 | // vec2 uvAnim = vec2(uv.x, uv.y - 0.5); 125 | RVec2 uvAnim = new RVec2("uvAnim", new RVec2("vec2(0.0)")); 126 | uvAnim.x().assign(uv.x()); 127 | uvAnim.y().assign(uv.y().subtract(0.5f)); 128 | // uvAnim.y *= 1.0 / yScale; 129 | uvAnim.y().assignMultiply(one.divide(yScale)); 130 | // uvAnim.y += 0.5; 131 | uvAnim.y().assignAdd(0.5f); 132 | // outColor = texture2D(iChannel0, uvAnim); 133 | RVec4 color = (RVec4)getGlobal(DefaultShaderVar.G_COLOR); 134 | outColor.assign(texture2D(muTexture, uvAnim)); 135 | } 136 | 137 | // if(dist < circleRadius + circleBorderHalf && dist > circleRadius - circleBorderHalf) { 138 | startif( 139 | new Condition(dist, Operator.LESS_THAN, muCircleRadius.add(circleBorderHalf)), 140 | new Condition(Operator.AND, dist, Operator.GREATER_THAN, muCircleRadius.subtract(circleBorderHalf)) 141 | ); 142 | { 143 | // outColor = trackColor; 144 | outColor.assign(muTrackColor); 145 | // float startAngle = 0.0; 146 | RFloat startAngle = new RFloat("startAngle", new RFloat(0)); 147 | // float endAngle = startAngle + mod(iGlobalTime * 2.0, PI_2); 148 | RFloat endAngle = new RFloat("endAngle", startAngle.add(muProgress.multiply(mcTwoPI))); 149 | // uv -= circleCenter; 150 | uv.assignSubtract(muCircleCenter); 151 | // float angle = -1.0 * atan(uv.y, uv.x) + PI; 152 | RFloat angle = new RFloat("angle", atan(uv.y(), uv.x()).multiply(-1)); 153 | angle.assignAdd(mcPI); 154 | 155 | // if(angle >= startAngle && angle <= endAngle) { 156 | startif(new Condition(angle, Operator.GREATER_THAN_EQUALS, startAngle), 157 | new Condition(Operator.AND, angle, Operator.LESS_THAN_EQUALS, endAngle)); 158 | { 159 | // outColor = progressColor; 160 | outColor.assign(muProgressColor); 161 | } 162 | endif(); 163 | } 164 | endif(); 165 | 166 | if(mDiscardAlpha) { 167 | startif(new Condition(outColor.a(), Operator.EQUALS, 0)); 168 | { 169 | discard(); 170 | } 171 | endif(); 172 | } 173 | 174 | // fragColor = outColor; 175 | GL_FRAG_COLOR.assign(outColor.getName()); 176 | } 177 | 178 | @Override 179 | public void setLocations(final int programHandle) { 180 | super.setLocations(programHandle); 181 | 182 | muCircleCenterHandle = getUniformLocation(programHandle, "uCircleCenter"); 183 | muTrackColorHandle = getUniformLocation(programHandle, "uTrackColor"); 184 | muProgressColorHandle = getUniformLocation(programHandle, "uProgressColor"); 185 | muCircleRadiusHandle = getUniformLocation(programHandle, "uCircleRadius"); 186 | muBorderThicknessHandle = getUniformLocation(programHandle, "uBorderThickness"); 187 | muTextureRotationSpeedHandle = getUniformLocation(programHandle, "uTextureRotationSpeed"); 188 | muProgressHandle = getUniformLocation(programHandle, "uProgress"); 189 | muTextureHandle = getUniformLocation(programHandle, "uProgressTexture"); 190 | } 191 | 192 | @Override 193 | public void applyParams() { 194 | super.applyParams(); 195 | 196 | GLES20.glUniform2fv(muCircleCenterHandle, 1, mCircleCenter, 0); 197 | GLES20.glUniform4fv(muTrackColorHandle, 1, mTrackColor, 0); 198 | GLES20.glUniform4fv(muProgressColorHandle, 1, mProgressColor, 0); 199 | GLES20.glUniform1f(muCircleRadiusHandle, mCircleRadius); 200 | GLES20.glUniform1f(muBorderThicknessHandle, mBorderThickness); 201 | GLES20.glUniform1f(muTextureRotationSpeedHandle, mTextureRotationSpeed); 202 | GLES20.glUniform1f(muProgressHandle, mProgress); 203 | } 204 | 205 | public void setCircleCenter(Vector2 center) { 206 | mCircleCenter[0] = (float)center.getX(); 207 | mCircleCenter[1] = (float)center.getY(); 208 | } 209 | 210 | public void setTrackColor(int color) { 211 | mTrackColor[0] = (float) Color.red(color) / 255.f; 212 | mTrackColor[1] = (float) Color.green(color) / 255.f; 213 | mTrackColor[2] = (float) Color.blue(color) / 255.f; 214 | mTrackColor[3] = (float) Color.alpha(color) / 255.f; 215 | } 216 | 217 | public void setProgressColor(int color) { 218 | mProgressColor[0] = (float) Color.red(color) / 255.f; 219 | mProgressColor[1] = (float) Color.green(color) / 255.f; 220 | mProgressColor[2] = (float) Color.blue(color) / 255.f; 221 | mProgressColor[3] = (float) Color.alpha(color) / 255.f; 222 | } 223 | 224 | public void setCircleRadius(float circleRadius) { 225 | mCircleRadius = circleRadius; 226 | } 227 | 228 | public void setBorderThickness(float borderThickness) { 229 | mBorderThickness = borderThickness; 230 | } 231 | 232 | public void setTextureRotationSpeed(float textureRotationSpeed) { 233 | mTextureRotationSpeed = textureRotationSpeed; 234 | } 235 | 236 | public void setProgress(float progress) { 237 | mProgress = progress; 238 | } 239 | 240 | public float getProgress() { 241 | return mProgress; 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /RajawaliVR/src/main/java/org/rajawali3d/vr/materials/shaders/HotspotMaterial.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015 Dennis Ippel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | */ 13 | 14 | package org.rajawali3d.vr.materials.shaders; 15 | 16 | import org.rajawali3d.materials.Material; 17 | import org.rajawali3d.materials.shaders.VertexShader; 18 | import org.rajawali3d.math.vector.Vector2; 19 | import org.rajawali3d.vr.R; 20 | 21 | /** 22 | * @author dennis.ippel 23 | */ 24 | public class HotspotMaterial extends Material { 25 | private HotspotFragmentShader mHotspotShader; 26 | 27 | public HotspotMaterial(boolean useTexture) { 28 | this(useTexture, false); 29 | } 30 | 31 | public HotspotMaterial(boolean useTexture, boolean discardAlpha) { 32 | super(new VertexShader(R.raw.minimal_vertex_shader), new HotspotFragmentShader(useTexture, discardAlpha)); 33 | mHotspotShader = (HotspotFragmentShader)mCustomFragmentShader; 34 | } 35 | 36 | public void setCircleCenter(Vector2 center) { 37 | mHotspotShader.setCircleCenter(center); 38 | } 39 | 40 | public void setTrackColor(int color) { 41 | mHotspotShader.setTrackColor(color); 42 | } 43 | 44 | public void setProgressColor(int color) { 45 | mHotspotShader.setProgressColor(color); 46 | } 47 | 48 | public void setCircleRadius(float circleRadius) { 49 | mHotspotShader.setCircleRadius(circleRadius); 50 | } 51 | 52 | public void setBorderThickness(float borderThickness) { 53 | mHotspotShader.setBorderThickness(borderThickness); 54 | } 55 | 56 | public void setTextureRotationSpeed(float textureRotationSpeed) { 57 | mHotspotShader.setTextureRotationSpeed(textureRotationSpeed); 58 | } 59 | 60 | public void setProgress(float progress) { 61 | mHotspotShader.setProgress(progress); 62 | } 63 | 64 | public float getProgress() { 65 | return mHotspotShader.getProgress(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /RajawaliVR/src/main/java/org/rajawali3d/vr/renderer/RajawaliVRRenderer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015 Dennis Ippel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | */ 13 | 14 | package org.rajawali3d.vr.renderer; 15 | 16 | import android.content.Context; 17 | import android.view.MotionEvent; 18 | 19 | import com.google.vrtoolkit.cardboard.CardboardView; 20 | import com.google.vrtoolkit.cardboard.Eye; 21 | import com.google.vrtoolkit.cardboard.HeadTransform; 22 | import com.google.vrtoolkit.cardboard.Viewport; 23 | 24 | import org.rajawali3d.Object3D; 25 | import org.rajawali3d.math.Matrix4; 26 | import org.rajawali3d.math.Quaternion; 27 | import org.rajawali3d.math.vector.Vector3; 28 | import org.rajawali3d.renderer.RajawaliRenderer; 29 | 30 | import javax.microedition.khronos.egl.EGLConfig; 31 | 32 | /** 33 | * @author dennis.ippel 34 | */ 35 | public class RajawaliVRRenderer extends RajawaliRenderer implements CardboardView.StereoRenderer { 36 | private static final float MAX_LOOKAT_ANGLE = 10; 37 | 38 | protected Matrix4 mCurrentEyeMatrix; 39 | protected Matrix4 mHeadViewMatrix; 40 | protected Quaternion mCurrentEyeOrientation; 41 | protected Quaternion mHeadViewQuaternion; 42 | protected Vector3 mCameraPosition; 43 | private Vector3 mForwardVec; 44 | private Vector3 mHeadTranslation; 45 | 46 | 47 | private Matrix4 mLookingAtMatrix; 48 | private float[] mHeadView; 49 | 50 | protected float mGestureXAngle = 0; 51 | protected float mGestureYAngle = 0; 52 | 53 | protected Matrix4 mTmpMatrix; 54 | protected Quaternion mTmpOrientation; 55 | 56 | 57 | public RajawaliVRRenderer(Context context) { 58 | super(context); 59 | mCurrentEyeMatrix = new Matrix4(); 60 | mHeadViewMatrix = new Matrix4(); 61 | mLookingAtMatrix = new Matrix4(); 62 | mCurrentEyeOrientation = new Quaternion(); 63 | mHeadViewQuaternion = new Quaternion(); 64 | mHeadView = new float[16]; 65 | mCameraPosition = new Vector3(); 66 | mForwardVec = new Vector3(); 67 | mHeadTranslation = new Vector3(); 68 | 69 | mTmpMatrix = new Matrix4(); 70 | mTmpOrientation = new Quaternion(); 71 | } 72 | 73 | @Override 74 | public void initScene() { 75 | 76 | } 77 | 78 | @Override 79 | public void onRender(long elapsedTime, double deltaTime) { 80 | super.onRender(elapsedTime, deltaTime); 81 | } 82 | 83 | @Override 84 | public void onOffsetsChanged(float v, float v2, float v3, float v4, int i, int i2) { 85 | 86 | } 87 | 88 | @Override 89 | public void onTouchEvent(MotionEvent motionEvent) { 90 | 91 | } 92 | 93 | @Override 94 | public void onNewFrame(HeadTransform headTransform) { 95 | headTransform.getHeadView(mHeadView, 0); 96 | mHeadViewMatrix.setAll(mHeadView); 97 | } 98 | 99 | @Override 100 | public void onDrawEye(Eye eye) { 101 | getCurrentCamera().updatePerspective( 102 | eye.getFov().getLeft(), 103 | eye.getFov().getRight(), 104 | eye.getFov().getBottom(), 105 | eye.getFov().getTop()); 106 | 107 | // 左右滑动时camera绕世界坐标的Y轴旋转, 上下滑动时camera绕自身的X轴旋转 108 | mCurrentEyeMatrix.identity(); 109 | mCurrentEyeMatrix.multiply(mTmpMatrix.setAll(mTmpOrientation.fromAngleAxis(Vector3.X, mGestureXAngle))); 110 | mCurrentEyeMatrix.multiply(mTmpMatrix.setAll(eye.getEyeView())); 111 | mCurrentEyeMatrix.multiply(mTmpMatrix.setAll(mTmpOrientation.fromAngleAxis(Vector3.Y, mGestureYAngle))); 112 | 113 | 114 | mCurrentEyeOrientation.fromMatrix(mCurrentEyeMatrix); 115 | getCurrentCamera().setOrientation(mCurrentEyeOrientation); 116 | getCurrentCamera().setPosition(mCameraPosition); 117 | getCurrentCamera().getPosition().add(mCurrentEyeMatrix.getTranslation().inverse()); 118 | super.onRenderFrame(null); 119 | } 120 | 121 | @Override 122 | public void onFinishFrame(Viewport viewport) { 123 | 124 | } 125 | 126 | @Override 127 | public void onSurfaceChanged(int width, int height) { 128 | super.onRenderSurfaceSizeChanged(null, width, height); 129 | } 130 | 131 | @Override 132 | public void onSurfaceCreated(EGLConfig eglConfig) { 133 | super.onRenderSurfaceCreated(eglConfig, null, -1, -1); 134 | } 135 | 136 | @Override 137 | public void onRendererShutdown() { 138 | super.onRenderSurfaceDestroyed(null); 139 | } 140 | 141 | public boolean isLookingAtObject(Object3D target) { 142 | return this.isLookingAtObject(target, MAX_LOOKAT_ANGLE); 143 | } 144 | 145 | public boolean isLookingAtObject(Object3D target, float maxAngle) { 146 | mHeadViewQuaternion.fromMatrix(mHeadViewMatrix); 147 | mHeadViewQuaternion.inverse(); 148 | mForwardVec.setAll(0, 0, 1); 149 | mForwardVec.transform(mHeadViewQuaternion); 150 | 151 | mHeadTranslation.setAll(mHeadViewMatrix.getTranslation()); 152 | mHeadTranslation.subtract(target.getPosition()); 153 | mHeadTranslation.normalize(); 154 | 155 | return mHeadTranslation.angle(mForwardVec) < maxAngle; 156 | } 157 | 158 | public void addGestureRotateAngle(float rotateXAngle, float rotateYAngle){ 159 | mGestureXAngle += rotateXAngle; 160 | mGestureYAngle += rotateYAngle; 161 | 162 | if(mGestureXAngle >= 360){ 163 | mGestureXAngle -= 360; 164 | } 165 | 166 | else if(mGestureXAngle <= -360){ 167 | mGestureXAngle += 360; 168 | } 169 | 170 | if(mGestureYAngle >= 360){ 171 | mGestureYAngle -= 360; 172 | } 173 | else if(mGestureYAngle <= -360){ 174 | mGestureYAngle += 360; 175 | } 176 | } 177 | 178 | public void resetGestureAngle(){ 179 | mGestureXAngle = 0; 180 | mGestureYAngle = 0; 181 | } 182 | 183 | public Matrix4 getHeadViewMatrix() { 184 | return mHeadViewMatrix; 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /RajawaliVR/src/main/java/org/rajawali3d/vr/surface/RajawaliVRSurfaceView.java: -------------------------------------------------------------------------------- 1 | package org.rajawali3d.vr.surface; 2 | 3 | /** 4 | * Copyright 2015 Dennis Ippel 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 12 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | * specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | import android.content.Context; 17 | import android.graphics.PixelFormat; 18 | import android.util.AttributeSet; 19 | import android.view.View; 20 | 21 | import com.google.vrtoolkit.cardboard.CardboardView; 22 | 23 | import org.rajawali3d.surface.IRajawaliSurface; 24 | import org.rajawali3d.surface.IRajawaliSurfaceRenderer; 25 | import org.rajawali3d.util.Capabilities; 26 | import org.rajawali3d.util.egl.RajawaliEGLConfigChooser; 27 | 28 | /** 29 | * 30 | */ 31 | public class RajawaliVRSurfaceView extends CardboardView implements IRajawaliSurface { 32 | 33 | public RajawaliVRSurfaceView(Context context) { 34 | super(context); 35 | } 36 | 37 | public RajawaliVRSurfaceView(Context context, AttributeSet attrs) 38 | { 39 | super(context, attrs); 40 | } 41 | 42 | @Override 43 | protected void onVisibilityChanged(View changedView, int visibility) { 44 | if (visibility == View.GONE || visibility == View.INVISIBLE) { 45 | onPause(); 46 | } else { 47 | onResume(); 48 | } 49 | super.onVisibilityChanged(changedView, visibility); 50 | } 51 | 52 | @Override 53 | protected void onAttachedToWindow() { 54 | super.onAttachedToWindow(); 55 | onResume(); 56 | } 57 | 58 | @Override 59 | public void setFrameRate(double v) { 60 | 61 | } 62 | 63 | @Override 64 | public void setAntiAliasingMode(ANTI_ALIASING_CONFIG anti_aliasing_config) { 65 | 66 | } 67 | 68 | @Override 69 | public void setSampleCount(int i) { 70 | 71 | } 72 | 73 | @Override 74 | public void setSurfaceRenderer(IRajawaliSurfaceRenderer iRajawaliSurfaceRenderer) throws IllegalStateException { 75 | 76 | } 77 | 78 | @Override 79 | public void requestRenderUpdate() { 80 | requestRender(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /RajawaliVR/src/main/java/org/rajawali3d/vr/ui/CardboardOverlayView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Google Inc. All Rights Reserved. 3 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.rajawali3d.vr.ui; 18 | 19 | import android.content.Context; 20 | import android.graphics.Color; 21 | import android.graphics.Typeface; 22 | import android.util.AttributeSet; 23 | import android.util.TypedValue; 24 | import android.view.Gravity; 25 | import android.view.View; 26 | import android.view.ViewGroup; 27 | import android.view.animation.AlphaAnimation; 28 | import android.view.animation.Animation; 29 | import android.widget.ImageView; 30 | import android.widget.LinearLayout; 31 | import android.widget.TextView; 32 | 33 | /** 34 | * Contains two sub-views to provide a simple stereo HUD. 35 | */ 36 | public class CardboardOverlayView extends LinearLayout { 37 | private final CardboardOverlayEyeView leftView; 38 | private final CardboardOverlayEyeView rightView; 39 | private AlphaAnimation textFadeAnimation; 40 | 41 | public CardboardOverlayView(Context context, AttributeSet attrs) { 42 | super(context, attrs); 43 | setOrientation(HORIZONTAL); 44 | 45 | LayoutParams params = new LayoutParams( 46 | LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1.0f); 47 | params.setMargins(0, 0, 0, 0); 48 | 49 | leftView = new CardboardOverlayEyeView(context, attrs); 50 | leftView.setLayoutParams(params); 51 | addView(leftView); 52 | 53 | rightView = new CardboardOverlayEyeView(context, attrs); 54 | rightView.setLayoutParams(params); 55 | addView(rightView); 56 | 57 | // Set some reasonable defaults. 58 | setDepthOffset(0.01f); 59 | setColor(Color.rgb(150, 255, 180)); 60 | setVisibility(View.VISIBLE); 61 | 62 | textFadeAnimation = new AlphaAnimation(1.0f, 0.0f); 63 | textFadeAnimation.setDuration(5000); 64 | } 65 | 66 | public void show3DToast(String message) { 67 | setText(message); 68 | setTextAlpha(1f); 69 | textFadeAnimation.setAnimationListener(new EndAnimationListener() { 70 | @Override 71 | public void onAnimationEnd(Animation animation) { 72 | setTextAlpha(0f); 73 | } 74 | }); 75 | startAnimation(textFadeAnimation); 76 | } 77 | 78 | private abstract class EndAnimationListener implements Animation.AnimationListener { 79 | @Override public void onAnimationRepeat(Animation animation) {} 80 | @Override public void onAnimationStart(Animation animation) {} 81 | } 82 | 83 | private void setDepthOffset(float offset) { 84 | leftView.setOffset(offset); 85 | rightView.setOffset(-offset); 86 | } 87 | 88 | private void setText(String text) { 89 | leftView.setText(text); 90 | rightView.setText(text); 91 | } 92 | 93 | private void setTextAlpha(float alpha) { 94 | leftView.setTextViewAlpha(alpha); 95 | rightView.setTextViewAlpha(alpha); 96 | } 97 | 98 | private void setColor(int color) { 99 | leftView.setColor(color); 100 | rightView.setColor(color); 101 | } 102 | 103 | /** 104 | * A simple view group containing some horizontally centered text underneath a horizontally 105 | * centered image. 106 | * 107 | *

This is a helper class for CardboardOverlayView. 108 | */ 109 | private class CardboardOverlayEyeView extends ViewGroup { 110 | private final ImageView imageView; 111 | private final TextView textView; 112 | private float offset; 113 | 114 | public CardboardOverlayEyeView(Context context, AttributeSet attrs) { 115 | super(context, attrs); 116 | imageView = new ImageView(context, attrs); 117 | imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); 118 | imageView.setAdjustViewBounds(true); // Preserve aspect ratio. 119 | addView(imageView); 120 | 121 | textView = new TextView(context, attrs); 122 | textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14.0f); 123 | textView.setTypeface(textView.getTypeface(), Typeface.BOLD); 124 | textView.setGravity(Gravity.CENTER); 125 | textView.setShadowLayer(3.0f, 0.0f, 0.0f, Color.DKGRAY); 126 | addView(textView); 127 | } 128 | 129 | public void setColor(int color) { 130 | imageView.setColorFilter(color); 131 | textView.setTextColor(color); 132 | } 133 | 134 | public void setText(String text) { 135 | textView.setText(text); 136 | } 137 | 138 | public void setTextViewAlpha(float alpha) { 139 | textView.setAlpha(alpha); 140 | } 141 | 142 | public void setOffset(float offset) { 143 | this.offset = offset; 144 | } 145 | 146 | @Override 147 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 148 | // Width and height of this ViewGroup. 149 | final int width = right - left; 150 | final int height = bottom - top; 151 | 152 | // The size of the image, given as a fraction of the dimension as a ViewGroup. 153 | // We multiply both width and heading with this number to compute the image's bounding 154 | // box. Inside the box, the image is the horizontally and vertically centered. 155 | final float imageSize = 0.1f; 156 | 157 | // The fraction of this ViewGroup's height by which we shift the image off the 158 | // ViewGroup's center. Positive values shift downwards, negative values shift upwards. 159 | final float verticalImageOffset = -0.07f; 160 | 161 | // Vertical position of the text, specified in fractions of this ViewGroup's height. 162 | final float verticalTextPos = 0.52f; 163 | 164 | // Layout ImageView 165 | float adjustedOffset = offset; 166 | // If the half screen width is bigger than 1000 pixels, that means it's a big screen 167 | // phone and we need to use a different offset value. 168 | if (width > 1000) { 169 | adjustedOffset = 3.8f * offset; 170 | } 171 | float imageMargin = (1.0f - imageSize) / 2.0f; 172 | float leftMargin = (int) (width * (imageMargin + adjustedOffset)); 173 | float topMargin = (int) (height * (imageMargin + verticalImageOffset)); 174 | imageView.layout( 175 | (int) leftMargin, (int) topMargin, 176 | (int) (leftMargin + width * imageSize), (int) (topMargin + height * imageSize)); 177 | 178 | // Layout TextView 179 | leftMargin = adjustedOffset * width; 180 | topMargin = height * verticalTextPos; 181 | textView.layout( 182 | (int) leftMargin, (int) topMargin, 183 | (int) (leftMargin + width), (int) (topMargin + height * (1.0f - verticalTextPos))); 184 | } 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /RajawaliVR/src/main/java/org/rajawali3d/vr/ui/GestureListener.java: -------------------------------------------------------------------------------- 1 | package org.rajawali3d.vr.ui; 2 | 3 | import android.view.MotionEvent; 4 | import android.view.View; 5 | import android.view.View.OnTouchListener; 6 | 7 | public class GestureListener implements OnTouchListener { 8 | private int mode = 0; 9 | private long touchStartTime; 10 | private float x, y; 11 | private float mTouchStartX; 12 | private float mTouchStartY; 13 | private float mClickTouchStartX, mClickTouchStartY; 14 | private float oldDist; 15 | private TOUCHEMODE mTouchMode = TOUCHEMODE.NOTHING; 16 | private TOUCHTYPE mTouchType; 17 | private OnEventGesture mOnEventGesture; 18 | 19 | public enum TOUCHEMODE { 20 | MODE_ZOOM_AND_MOVE, MODE_CTRL_SBP, NOTHING 21 | } 22 | 23 | public enum TOUCHTYPE { 24 | TYPE_GLIDE_LEFT_RIGHT, TYPE_GLIDE_UP_DOWN_IN_LEFT, TYPE_GLIDE_UP_DOWN_IN_RIGHT, 25 | } 26 | 27 | public enum GestureState { 28 | STATE_GESTURE_START, STATE_GESTURE_ING, STATE_GESTURE_END 29 | } 30 | 31 | public void setToucheMode(TOUCHEMODE mode) { 32 | mTouchMode = mode; 33 | } 34 | 35 | public void setOnEventGesture(OnEventGesture onEventGesture) { 36 | this.mOnEventGesture = onEventGesture; 37 | } 38 | 39 | @Override 40 | public boolean onTouch(View v, MotionEvent event) { 41 | int pointCount = event.getPointerCount(); 42 | switch (event.getAction() & MotionEvent.ACTION_MASK) { 43 | 44 | case MotionEvent.ACTION_DOWN: 45 | mode = 1; 46 | touchStartTime = System.currentTimeMillis(); 47 | mTouchStartX = event.getRawX(); 48 | mTouchStartY = event.getRawY(); 49 | mClickTouchStartX = mTouchStartX; 50 | mClickTouchStartY = mTouchStartY; 51 | x = event.getX(); 52 | y = event.getY(); 53 | break; 54 | case MotionEvent.ACTION_POINTER_UP: 55 | mode -= 1; 56 | break; 57 | case MotionEvent.ACTION_POINTER_DOWN: 58 | oldDist = spacing(event); 59 | mode += 1; 60 | break; 61 | case MotionEvent.ACTION_MOVE: 62 | if (mode >= 2) { 63 | 64 | float newDist = spacing(event); 65 | if (mTouchMode == TOUCHEMODE.MODE_ZOOM_AND_MOVE) 66 | mOnEventGesture.onZoomGesture(v, newDist, oldDist); 67 | oldDist = newDist; 68 | 69 | } else { 70 | singleMove(event, v); 71 | 72 | } 73 | break; 74 | 75 | case MotionEvent.ACTION_UP: 76 | mode = 0; 77 | if (pointCount >= 2) 78 | break; 79 | 80 | if (mTouchType != null) { 81 | switch (mTouchType) { 82 | case TYPE_GLIDE_LEFT_RIGHT: 83 | 84 | mOnEventGesture.onLeftRightGesture(v, event, x, y, 85 | GestureState.STATE_GESTURE_END); 86 | break; 87 | case TYPE_GLIDE_UP_DOWN_IN_LEFT: 88 | mOnEventGesture.onUpDownLeftGesture(v, event, x, y, 89 | GestureState.STATE_GESTURE_END); 90 | break; 91 | case TYPE_GLIDE_UP_DOWN_IN_RIGHT: 92 | mOnEventGesture.onUpDownRightGesture(v, event, x, y, 93 | GestureState.STATE_GESTURE_END); 94 | break; 95 | } 96 | mTouchType = null; 97 | 98 | } else { 99 | if (Math.abs(event.getRawX() - mClickTouchStartX) < 30 100 | && Math.abs(event.getRawY() - mClickTouchStartY) < 30 101 | && System.currentTimeMillis() - touchStartTime < 300) { 102 | mOnEventGesture.onClick(v, event); 103 | } 104 | } 105 | break; 106 | default: 107 | break; 108 | } 109 | return true; 110 | } 111 | 112 | private void singleMove(MotionEvent event, View v) { 113 | switch (mTouchMode) { 114 | case MODE_CTRL_SBP: 115 | if (mTouchType != null) { 116 | switch (mTouchType) { 117 | case TYPE_GLIDE_LEFT_RIGHT: 118 | 119 | mOnEventGesture.onLeftRightGesture(v, event, x, y, 120 | GestureState.STATE_GESTURE_ING); 121 | break; 122 | case TYPE_GLIDE_UP_DOWN_IN_LEFT: 123 | mOnEventGesture.onUpDownLeftGesture(v, event, x, y, 124 | GestureState.STATE_GESTURE_ING); 125 | break; 126 | case TYPE_GLIDE_UP_DOWN_IN_RIGHT: 127 | mOnEventGesture.onUpDownRightGesture(v, event, x, y, 128 | GestureState.STATE_GESTURE_ING); 129 | break; 130 | } 131 | } else { 132 | 133 | if (Math.abs(event.getY() - y) < 50 134 | && Math.abs(event.getX() - x) > 50) { 135 | mTouchType = TOUCHTYPE.TYPE_GLIDE_LEFT_RIGHT; 136 | mOnEventGesture.onLeftRightGesture(v, event, x, y, 137 | GestureState.STATE_GESTURE_START); 138 | x = event.getX(); 139 | y = event.getY(); 140 | } else if (Math.abs(event.getX() - x) < 50 141 | && Math.abs(event.getY() - y) > 50) { 142 | 143 | if (x < v.getWidth() / 2) { 144 | mTouchType = TOUCHTYPE.TYPE_GLIDE_UP_DOWN_IN_LEFT; 145 | mOnEventGesture.onUpDownLeftGesture(v, event, x, y, 146 | GestureState.STATE_GESTURE_START); 147 | } else { 148 | mTouchType = TOUCHTYPE.TYPE_GLIDE_UP_DOWN_IN_RIGHT; 149 | mOnEventGesture.onUpDownRightGesture(v, event, x, y, 150 | GestureState.STATE_GESTURE_START); 151 | } 152 | x = event.getX(); 153 | y = event.getY(); 154 | } 155 | 156 | } 157 | break; 158 | case MODE_ZOOM_AND_MOVE: 159 | mOnEventGesture.onMoveGesture(v, event, mTouchStartX, mTouchStartY); 160 | mTouchStartX = event.getRawX(); 161 | mTouchStartY = event.getRawY(); 162 | break; 163 | } 164 | } 165 | 166 | private float spacing(MotionEvent event) { 167 | float x = event.getX(0) - event.getX(1); 168 | float y = event.getY(0) - event.getY(1); 169 | return (float)Math.sqrt(x * x + y * y); 170 | } 171 | 172 | public interface OnEventGesture { 173 | public void onZoomGesture(View v, float newDist, float oldDist); 174 | 175 | public void onMoveGesture(View v, MotionEvent currentMoveEvent, 176 | float mTouchStartX, float mTouchStartY); 177 | 178 | public void onClick(View v, MotionEvent currentMoveEvent); 179 | 180 | public void onLeftRightGesture(View v, MotionEvent currentEventm, 181 | float startx, float starty, GestureState state); 182 | 183 | public void onUpDownLeftGesture(View v, MotionEvent currentEventm, 184 | float startx, float starty, GestureState state); 185 | 186 | public void onUpDownRightGesture(View v, MotionEvent currentEventm, 187 | float startx, float starty, GestureState state); 188 | } 189 | } -------------------------------------------------------------------------------- /RajawaliVR/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | RajawaliVR 3 | 4 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion rootProject.compileSdk 5 | buildToolsVersion rootProject.buildTools 6 | 7 | defaultConfig { 8 | applicationId rootProject.applicationId 9 | minSdkVersion rootProject.minSdk 10 | targetSdkVersion rootProject.targetSdk 11 | versionCode rootProject.versionCode 12 | versionName rootProject.versionName 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | compile project (':RajawaliVR') 25 | compile rootProject.depAndroidSupport 26 | compile rootProject.depRecycler 27 | compile rootProject.depAppCompat 28 | compile rootProject.depDesign 29 | compile rootProject.depCardview 30 | } 31 | -------------------------------------------------------------------------------- /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:\develop\Android\android-sdk\IDEintegration\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/androidTest/java/me/substarry/vrplayer/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package me.substarry.vrplayer; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 | 23 | 27 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /app/src/main/java/me/substarry/vrplayer/ListActivity.java: -------------------------------------------------------------------------------- 1 | package me.substarry.vrplayer; 2 | 3 | 4 | import android.app.ProgressDialog; 5 | import android.content.Intent; 6 | import android.graphics.Bitmap; 7 | import android.media.ThumbnailUtils; 8 | import android.os.AsyncTask; 9 | import android.os.Bundle; 10 | import android.os.Environment; 11 | import android.provider.MediaStore; 12 | import android.support.v7.app.ActionBar; 13 | import android.support.v7.app.AppCompatActivity; 14 | import android.support.v7.widget.LinearLayoutManager; 15 | import android.support.v7.widget.RecyclerView; 16 | import android.view.Menu; 17 | import android.view.MenuItem; 18 | import android.view.View; 19 | import android.widget.Toast; 20 | 21 | import com.samskrut.vrplayer.R; 22 | 23 | import java.io.File; 24 | import java.util.ArrayList; 25 | 26 | public class ListActivity extends AppCompatActivity { 27 | 28 | 29 | private RecyclerView mRecyclerView; 30 | private RecyclerView.Adapter mAdapter; 31 | private RecyclerView.LayoutManager mLayoutManager; 32 | 33 | ArrayList filenames; 34 | ArrayList filepaths; 35 | ArrayList bitmaps; 36 | 37 | static int files_count_old=0; 38 | 39 | @Override 40 | protected void onResume() { 41 | super.onResume(); 42 | 43 | File file = new File(Environment.getExternalStorageDirectory() + File.separator + "360Videos"); 44 | 45 | if(file.listFiles() != null && (files_count_old==0||files_count_old!=file.listFiles().length)){ 46 | 47 | files_count_old=file.listFiles().length; 48 | 49 | filenames = new ArrayList(); 50 | filepaths = new ArrayList(); 51 | 52 | try { 53 | file = new File(Environment.getExternalStorageDirectory() + File.separator + "360Videos"); 54 | for (File f : file.listFiles()) { 55 | filenames.add(stripExtension(f.getName())); 56 | filepaths.add(f.getAbsolutePath()); 57 | } 58 | 59 | new LongOperation().execute(filepaths); 60 | 61 | } catch (Exception e) { 62 | Toast.makeText(getApplicationContext(), "Video Files are not found in '360Videos' Folder", Toast.LENGTH_SHORT).show(); 63 | } 64 | 65 | }else { 66 | 67 | 68 | } 69 | 70 | 71 | } 72 | 73 | @Override 74 | protected void onCreate(Bundle savedInstanceState) { 75 | super.onCreate(savedInstanceState); 76 | setContentView(R.layout.activity_list); 77 | ActionBar ab = getSupportActionBar(); 78 | ab.setTitle(""); 79 | mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view); 80 | 81 | findViewById(R.id.tv_play_demo).setOnClickListener(new View.OnClickListener() { 82 | @Override 83 | public void onClick(View v) { 84 | Intent i = new Intent(ListActivity.this, MainActivity.class); 85 | i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 86 | ListActivity.this.startActivity(i); 87 | } 88 | }); 89 | 90 | } 91 | 92 | 93 | @Override 94 | public boolean onCreateOptionsMenu(Menu menu) { 95 | // Inflate the menu; this adds items to the action bar if it is present. 96 | getMenuInflater().inflate(R.menu.menu_list, menu); 97 | return true; 98 | } 99 | 100 | @Override 101 | public boolean onOptionsItemSelected(MenuItem item) { 102 | // Handle action bar item clicks here. The action bar will 103 | // automatically handle clicks on the Home/Up button, so long 104 | // as you specify a parent activity in AndroidManifest.xml. 105 | int id = item.getItemId(); 106 | 107 | //noinspection SimplifiableIfStatement 108 | if (id == R.id.action_settings) { 109 | return true; 110 | } 111 | 112 | return super.onOptionsItemSelected(item); 113 | } 114 | 115 | static String stripExtension(String str) { 116 | // Handle null case specially. 117 | 118 | if (str == null) return null; 119 | 120 | // Get position of last '.'. 121 | 122 | int pos = str.lastIndexOf("."); 123 | 124 | // If there wasn't any '.' just return the string as is. 125 | 126 | if (pos == -1) return str; 127 | 128 | // Otherwise return the string, up to the dot. 129 | 130 | return str.substring(0, pos); 131 | } 132 | 133 | private class LongOperation extends AsyncTask, Integer, ArrayList> { 134 | 135 | ProgressDialog dialog; 136 | 137 | 138 | @Override 139 | protected ArrayList doInBackground(ArrayList... params) { 140 | ArrayList passed = params[0]; 141 | bitmaps = new ArrayList<>(); 142 | int i = 0; 143 | for (String path : passed) { 144 | i++; 145 | bitmaps.add(ThumbnailUtils.createVideoThumbnail(path, MediaStore.Video.Thumbnails.MINI_KIND)); 146 | publishProgress(i); 147 | } 148 | return bitmaps; 149 | } 150 | 151 | @Override 152 | protected void onPostExecute(ArrayList al) { 153 | dialog.dismiss(); 154 | 155 | // use this setting to improve performance if you know that changes 156 | // in content do not change the layout size of the RecyclerView 157 | mRecyclerView.setHasFixedSize(true); 158 | // use a linear layout manager 159 | mLayoutManager = new LinearLayoutManager(ListActivity.this); 160 | mRecyclerView.setLayoutManager(mLayoutManager); 161 | mAdapter = new MyAdapter(getApplicationContext(), filenames, filepaths, al); 162 | mRecyclerView.setAdapter(mAdapter); 163 | 164 | } 165 | 166 | @Override 167 | protected void onPreExecute() { 168 | 169 | dialog = new ProgressDialog(ListActivity.this); 170 | dialog.setTitle("Updating UI..."); 171 | dialog.setMessage("Please Wait.."); 172 | dialog.setIndeterminate(true); 173 | dialog.setCancelable(false); 174 | dialog.show(); 175 | 176 | } 177 | 178 | @Override 179 | protected void onProgressUpdate(Integer... values) { 180 | 181 | dialog.setMessage(values[0] + " out of " + filepaths.size() + " files are loaded."); 182 | } 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /app/src/main/java/me/substarry/vrplayer/MainActivity.java: -------------------------------------------------------------------------------- 1 | package me.substarry.vrplayer; 2 | 3 | import android.content.pm.ActivityInfo; 4 | import android.os.Bundle; 5 | import android.view.MotionEvent; 6 | import android.view.View; 7 | import android.view.Window; 8 | import android.view.WindowManager; 9 | import android.widget.Toast; 10 | 11 | import org.rajawali3d.util.RajLog; 12 | import org.rajawali3d.vr.RajawaliVRActivity; 13 | import org.rajawali3d.vr.ui.GestureListener; 14 | 15 | import java.io.File; 16 | 17 | 18 | public class MainActivity extends RajawaliVRActivity { 19 | 20 | private VideoRenderer mRenderer; 21 | @Override 22 | public void onCreate(Bundle savedInstanceState) { 23 | 24 | requestWindowFeature(Window.FEATURE_NO_TITLE); 25 | getWindow().setFlags( 26 | WindowManager.LayoutParams.FLAG_FULLSCREEN 27 | | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, 28 | WindowManager.LayoutParams.FLAG_FULLSCREEN 29 | | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 30 | 31 | super.onCreate(savedInstanceState); 32 | 33 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 34 | 35 | GestureListener gestureListener = new GestureListener(); 36 | gestureListener.setOnEventGesture(mOnEventGesture); 37 | gestureListener.setToucheMode(GestureListener.TOUCHEMODE.MODE_ZOOM_AND_MOVE); 38 | setOnTouchListener(gestureListener); 39 | 40 | Bundle bundle = getIntent().getExtras(); 41 | if (bundle != null && bundle.get("fpath") != null) { 42 | String path = getIntent().getExtras().getString("fpath", null); 43 | File file = new File(path); 44 | mRenderer = new VideoRenderer(MainActivity.this, path); 45 | } else { 46 | mRenderer = new VideoRenderer(MainActivity.this, null); 47 | Toast.makeText(getApplicationContext(), "Play Demo!", Toast.LENGTH_SHORT).show(); 48 | } 49 | 50 | setRenderer(mRenderer); 51 | 52 | setConvertTapIntoTrigger(true); 53 | } 54 | 55 | /** 56 | * Called when the Cardboard trigger is pulled. 57 | */ 58 | @Override 59 | public void onCardboardTrigger() { 60 | RajLog.i("onCardboardTrigger"); 61 | } 62 | 63 | @Override 64 | public void onPause() { 65 | mRenderer.pauseVideo(); 66 | super.onPause(); 67 | } 68 | 69 | @Override 70 | public void onResume() { 71 | super.onResume(); 72 | mRenderer.resumeVideo(); 73 | } 74 | 75 | private GestureListener.OnEventGesture mOnEventGesture = new GestureListener.OnEventGesture() { 76 | @Override 77 | public void onZoomGesture(View v, float newDist, float oldDist) { 78 | 79 | } 80 | 81 | @Override 82 | public void onMoveGesture(View v, MotionEvent currentMoveEvent, float mTouchStartX, float mTouchStartY) { 83 | if(!getVRMode()){ 84 | mRenderer.addGestureRotateAngle( 85 | ScreenUtils.rawY2Angle(MainActivity.this, currentMoveEvent.getRawY() - mTouchStartY), 86 | ScreenUtils.rawX2Angle(MainActivity.this, currentMoveEvent.getRawX() - mTouchStartX) 87 | ); 88 | } 89 | } 90 | 91 | @Override 92 | public void onClick(View v, MotionEvent currentMoveEvent) { 93 | onCardboardTrigger(); 94 | } 95 | 96 | @Override 97 | public void onLeftRightGesture(View v, MotionEvent currentEventm, float startx, float starty, GestureListener.GestureState state) { 98 | 99 | } 100 | 101 | @Override 102 | public void onUpDownLeftGesture(View v, MotionEvent currentEventm, float startx, float starty, GestureListener.GestureState state) { 103 | 104 | } 105 | 106 | @Override 107 | public void onUpDownRightGesture(View v, MotionEvent currentEventm, float startx, float starty, GestureListener.GestureState state) { 108 | 109 | } 110 | }; 111 | 112 | 113 | } -------------------------------------------------------------------------------- /app/src/main/java/me/substarry/vrplayer/MyAdapter.java: -------------------------------------------------------------------------------- 1 | package me.substarry.vrplayer; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.graphics.Bitmap; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.text.TextUtils; 8 | import android.util.Log; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.widget.ImageView; 13 | import android.widget.LinearLayout; 14 | import android.widget.TextView; 15 | 16 | import com.samskrut.vrplayer.R; 17 | 18 | import java.util.ArrayList; 19 | 20 | /** 21 | * Created by bmp on 07-12-2015. 22 | */ 23 | 24 | 25 | public class MyAdapter extends RecyclerView.Adapter { 26 | Context context; 27 | private ArrayList filenames; 28 | private ArrayList filepaths; 29 | ArrayList bitmaps; 30 | 31 | // Provide a suitable constructor (depends on the kind of dataset) 32 | public MyAdapter(Context ctx, ArrayList _filenames, ArrayList _filepaths, ArrayList _bitmaps) { 33 | this.filenames = _filenames; 34 | this.filepaths = _filepaths; 35 | bitmaps=_bitmaps; 36 | context = ctx; 37 | } 38 | 39 | public void add(int position, String item) { 40 | filenames.add(position, item); 41 | notifyItemInserted(position); 42 | } 43 | 44 | public void remove(String item) { 45 | int position = filenames.indexOf(item); 46 | Log.d("bis", "onBindViewHolder2= " + position); 47 | filenames.remove(position); 48 | notifyItemRemoved(position); 49 | } 50 | 51 | // Create new views (invoked by the layout manager) 52 | @Override 53 | public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, 54 | int viewType) { 55 | // create a new view 56 | View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.rowlayout, parent, false); 57 | // set the view's size, margins, paddings and layout parameters 58 | ViewHolder vh = new ViewHolder(v); 59 | return vh; 60 | } 61 | 62 | // Replace the contents of a view (invoked by the layout manager) 63 | @Override 64 | public void onBindViewHolder(ViewHolder holder, final int position) { 65 | // - get element from your dataset at this position 66 | // - replace the contents of the view with that element 67 | final String name = filenames.get(position); 68 | // Bitmap bMap = ThumbnailUtils.createVideoThumbnail(filepaths.get(position), MediaStore.Video.Thumbnails.MINI_KIND); 69 | 70 | // Bitmap bMap = ThumbnailUtils.createVideoThumbnail(filepaths.get(position), MediaStore.Video.Thumbnails.FULL_SCREEN_KIND); 71 | 72 | //holder.rl.setBackgroundColor(context.getResources().getColor(android.R.color.darker_gray)); 73 | holder.ll.setOnClickListener(new View.OnClickListener() { 74 | @Override 75 | public void onClick(View v) { 76 | 77 | Log.d("bis", "onBindViewHolder= " + position); 78 | //remove(name); 79 | 80 | Intent i = new Intent(context, MainActivity.class); 81 | i.putExtra("fpath", filepaths.get(position)); 82 | i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 83 | context.startActivity(i); 84 | 85 | } 86 | }); 87 | holder.iv.setImageBitmap(bitmaps.get(position)); 88 | holder.video_infotv.setSelected(true); 89 | holder.video_infotv.setEllipsize(TextUtils.TruncateAt.MARQUEE); 90 | holder.video_infotv.setText(filenames.get(position)); 91 | 92 | } 93 | 94 | // Return the size of your dataset (invoked by the layout manager) 95 | @Override 96 | public int getItemCount() { 97 | return filenames.size(); 98 | } 99 | 100 | // Provide a reference to the views for each data item 101 | // Complex data items may need more than one view per item, and 102 | // you provide access to all the views for a data item in a view holder 103 | public class ViewHolder extends RecyclerView.ViewHolder { 104 | // each data item is just a string in this case 105 | public TextView video_infotv; 106 | 107 | public ImageView iv; 108 | public LinearLayout ll; 109 | 110 | public ViewHolder(View v) { 111 | super(v); 112 | video_infotv = (TextView) v.findViewById(R.id.video_infotv); 113 | iv = (ImageView) v.findViewById(R.id.icon); 114 | ll = (LinearLayout) v.findViewById(R.id.ll); 115 | } 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /app/src/main/java/me/substarry/vrplayer/MyRenderer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * All you need to know about this class is that, when you give it the projectPos, pos and the context, 3 | * it will render that particular jpg in 3D split view for viewing. 4 | *

5 | * This class is part of the Rajawali Library, with small additions to it as per our need. 6 | */ 7 | package me.substarry.vrplayer; 8 | 9 | import android.content.ContextWrapper; 10 | import android.graphics.Bitmap; 11 | import android.graphics.BitmapFactory; 12 | import android.os.Environment; 13 | import android.util.Log; 14 | 15 | import org.rajawali3d.materials.Material; 16 | import org.rajawali3d.materials.textures.ATexture; 17 | import org.rajawali3d.materials.textures.Texture; 18 | import org.rajawali3d.math.vector.Vector3; 19 | import org.rajawali3d.primitives.Sphere; 20 | import org.rajawali3d.vr.renderer.RajawaliVRRenderer; 21 | 22 | import java.io.BufferedInputStream; 23 | import java.io.File; 24 | import java.io.FileInputStream; 25 | import java.io.InputStream; 26 | 27 | public class MyRenderer extends RajawaliVRRenderer { 28 | 29 | 30 | public ContextWrapper contextWrapper; 31 | 32 | 33 | public MyRenderer(ContextWrapper c) { 34 | super(c); 35 | contextWrapper = c; 36 | 37 | } 38 | 39 | private static Sphere createPhotoSphereWithTexture(ATexture texture) { 40 | 41 | Material material = new Material(); 42 | material.setColor(0); 43 | 44 | try { 45 | material.addTexture(texture); 46 | } catch (ATexture.TextureException e) { 47 | throw new RuntimeException(e); 48 | } 49 | 50 | Sphere sphere = new Sphere(50, 64, 32); 51 | sphere.setScaleX(-1); 52 | sphere.setMaterial(material); 53 | 54 | return sphere; 55 | } 56 | 57 | @Override 58 | public void initScene() { 59 | InputStream fis = null; 60 | try { 61 | FileInputStream fiss = new FileInputStream(Environment.getExternalStorageDirectory() + File.separator + "ss.jpg"); 62 | 63 | fis = new BufferedInputStream(fiss); 64 | 65 | } catch (Exception e) { 66 | 67 | Log.d("bis", "my render image e=" + e.getLocalizedMessage()); 68 | } 69 | 70 | 71 | Bitmap bitmap = BitmapFactory.decodeStream(fis); 72 | // Bitmap bitmap = BitmapFactory.decodeResource(contextWrapper.getResources(), R.raw.ss); 73 | Log.d("bis", "my render image bitmap" + bitmap.toString()); 74 | 75 | Sphere sphere = createPhotoSphereWithTexture(new Texture("photo", bitmap)); 76 | 77 | /////////////////////////////////////////////////////////////////////////// 78 | 79 | getCurrentScene().addChild(sphere); 80 | getCurrentCamera().setPosition(Vector3.ZERO); 81 | getCurrentCamera().setFieldOfView(75); 82 | } 83 | } -------------------------------------------------------------------------------- /app/src/main/java/me/substarry/vrplayer/ScreenUtils.java: -------------------------------------------------------------------------------- 1 | package me.substarry.vrplayer; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Point; 5 | import android.util.Log; 6 | 7 | /** 8 | * Created by 何凌 on 2016/4/6. 9 | */ 10 | public class ScreenUtils { 11 | 12 | private static final String TAG = "ScreenUtils"; 13 | private static float mScreenWidth = 0, mScreenHeight = 0; 14 | 15 | /** 16 | * 手指横向滑动距离与旋转角度换算,一屏的距离对应180度 17 | * @param activity 18 | * @param rawX 横向滑动距离 19 | * @return 角度 20 | */ 21 | public static float rawX2Angle(Activity activity, float rawX){ 22 | if(getScreenWidth(activity) == 0){ 23 | return rawX * 0.1f; 24 | } 25 | return rawX * 180/mScreenWidth; 26 | } 27 | 28 | /** 29 | * 手指纵向滑动距离与旋转角度换算,一屏的距离对应180度 30 | * @param activity 31 | * @param rawY 纵向滑动距离 32 | * @return 角度 33 | */ 34 | public static float rawY2Angle(Activity activity, float rawY){ 35 | if(getScreenHeight(activity) == 0){ 36 | return rawY * 0.2f; 37 | } 38 | return rawY * 180/mScreenHeight; 39 | } 40 | 41 | public static float getScreenWidth(Activity activity){ 42 | if(mScreenWidth == 0){ 43 | Point size = new Point(); 44 | activity.getWindowManager().getDefaultDisplay().getSize(size); 45 | mScreenWidth = size.x; 46 | Log.d(TAG, "screen size is " + size); 47 | } 48 | return mScreenWidth; 49 | } 50 | 51 | public static float getScreenHeight(Activity activity){ 52 | if(mScreenHeight == 0){ 53 | Point size = new Point(); 54 | activity.getWindowManager().getDefaultDisplay().getSize(size); 55 | mScreenHeight = size.y; 56 | Log.d(TAG, "screen size is " + size); 57 | } 58 | return mScreenHeight; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/me/substarry/vrplayer/Splash.java: -------------------------------------------------------------------------------- 1 | package me.substarry.vrplayer; 2 | 3 | import android.app.Activity; 4 | import android.app.AlertDialog; 5 | import android.content.DialogInterface; 6 | import android.content.Intent; 7 | import android.os.Bundle; 8 | import android.os.Environment; 9 | import android.os.Handler; 10 | import android.view.Menu; 11 | import android.view.MenuItem; 12 | 13 | import com.samskrut.vrplayer.R; 14 | 15 | import java.io.File; 16 | 17 | public class Splash extends Activity { 18 | 19 | @Override 20 | protected void onCreate(Bundle savedInstanceState) { 21 | 22 | super.onCreate(savedInstanceState); 23 | setContentView(R.layout.activity_splash); 24 | 25 | File folder = new File(Environment.getExternalStorageDirectory() + File.separator + "360Videos"); 26 | if (folder.exists()) { 27 | 28 | if (folder.listFiles() != null && folder.listFiles().length > 0) { 29 | Handler h = new Handler(); 30 | Runnable r = new Runnable() { 31 | @Override 32 | public void run() { 33 | Intent next = new Intent(Splash.this, ListActivity.class); 34 | startActivity(next); 35 | finish(); 36 | } 37 | }; 38 | h.postDelayed(r, 3000); 39 | }else{ 40 | 41 | final AlertDialog ad = new AlertDialog.Builder(this).create(); 42 | ad.setTitle("Files Not Found "); 43 | ad.setMessage("Please Copy Files to '360Videos' Folder in the SDCARD"); 44 | ad.setIcon(R.mipmap.ic_launcher); 45 | ad.setCancelable(false); 46 | ad.setButton("OK", new DialogInterface.OnClickListener() { 47 | public void onClick(DialogInterface dialog, int which) { 48 | ad.dismiss(); 49 | Intent next = new Intent(Splash.this, ListActivity.class); 50 | startActivity(next); 51 | finish(); 52 | } 53 | }); 54 | ad.show(); 55 | 56 | } 57 | } else { 58 | folder.mkdir(); 59 | 60 | final AlertDialog ad = new AlertDialog.Builder(this).create(); 61 | ad.setTitle("Folder not found"); 62 | ad.setMessage("Please Copy files to '360Videos' folder in the SDCARD"); 63 | ad.setIcon(R.mipmap.ic_launcher); 64 | ad.setCancelable(false); 65 | ad.setButton("OK", new DialogInterface.OnClickListener() { 66 | public void onClick(DialogInterface dialog, int which) { 67 | ad.dismiss(); 68 | Intent next = new Intent(Splash.this, ListActivity.class); 69 | startActivity(next); 70 | finish(); 71 | } 72 | }); 73 | ad.show(); 74 | } 75 | 76 | 77 | } 78 | 79 | @Override 80 | public boolean onCreateOptionsMenu(Menu menu) { 81 | // Inflate the menu; this adds items to the action bar if it is present. 82 | getMenuInflater().inflate(R.menu.menu_splash, menu); 83 | return true; 84 | } 85 | 86 | @Override 87 | public boolean onOptionsItemSelected(MenuItem item) { 88 | // Handle action bar item clicks here. The action bar will 89 | // automatically handle clicks on the Home/Up button, so long 90 | // as you specify a parent activity in AndroidManifest.xml. 91 | int id = item.getItemId(); 92 | 93 | //noinspection SimplifiableIfStatement 94 | if (id == R.id.action_settings) { 95 | return true; 96 | } 97 | 98 | return super.onOptionsItemSelected(item); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /app/src/main/java/me/substarry/vrplayer/VideoRenderer.java: -------------------------------------------------------------------------------- 1 | package me.substarry.vrplayer; 2 | 3 | import android.app.Activity; 4 | import android.graphics.SurfaceTexture; 5 | import android.media.MediaPlayer; 6 | import android.net.Uri; 7 | import android.text.TextUtils; 8 | import android.util.Log; 9 | 10 | import com.samskrut.vrplayer.R; 11 | 12 | import org.rajawali3d.materials.Material; 13 | import org.rajawali3d.materials.textures.ATexture; 14 | import org.rajawali3d.materials.textures.StreamingTexture; 15 | import org.rajawali3d.math.vector.Vector3; 16 | import org.rajawali3d.primitives.Sphere; 17 | import org.rajawali3d.vr.renderer.RajawaliVRRenderer; 18 | 19 | import java.io.File; 20 | 21 | public class VideoRenderer extends RajawaliVRRenderer { 22 | 23 | // Context mContext; 24 | MainActivity mainActivity; 25 | String videopath; 26 | private MediaPlayer mMediaPlayer; 27 | private StreamingTexture mVideoTexture; 28 | private Sphere mSphere; 29 | 30 | public VideoRenderer(Activity activity, String _path) { 31 | super(activity.getApplicationContext()); 32 | 33 | videopath = _path; 34 | mainActivity = (MainActivity) activity; 35 | } 36 | 37 | @Override 38 | public void initScene() { 39 | 40 | 41 | if(TextUtils.isEmpty(videopath)){ 42 | mMediaPlayer = MediaPlayer.create(getContext(), R.raw.demo); 43 | } 44 | else{ 45 | File file = new File(videopath); 46 | Uri uri = Uri.fromFile(file); 47 | Log.d("bis", "uri= " + uri.toString()); 48 | mMediaPlayer = MediaPlayer.create(getContext(), uri); 49 | 50 | } 51 | mMediaPlayer.setLooping(true); 52 | 53 | mVideoTexture = new StreamingTexture("sintelTrailer", mMediaPlayer); 54 | Material material = new Material(); 55 | material.setColorInfluence(0); 56 | try { 57 | material.addTexture(mVideoTexture); 58 | } catch (ATexture.TextureException e) { 59 | e.printStackTrace(); 60 | } 61 | 62 | mSphere = new Sphere(50, 64, 32); 63 | mSphere.setScaleX(-1); 64 | mSphere.setMaterial(material); 65 | 66 | getCurrentScene().addChild(mSphere); 67 | 68 | getCurrentCamera().setPosition(Vector3.ZERO); 69 | 70 | getCurrentCamera().setFieldOfView(75); 71 | 72 | mMediaPlayer.start(); 73 | 74 | mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 75 | @Override 76 | public void onCompletion(MediaPlayer mp) { 77 | Log.d("bis", "video completed"); 78 | mp.stop(); 79 | mainActivity.finish(); 80 | } 81 | }); 82 | mMediaPlayer.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() { 83 | @Override 84 | public void onSeekComplete(MediaPlayer mp) { 85 | Log.d("bis", "video seek completed"); 86 | mp.stop(); 87 | mainActivity.finish(); 88 | } 89 | }); 90 | 91 | } 92 | 93 | @Override 94 | public void addGestureRotateAngle(float rotateXAngle, float rotateYAngle){ 95 | 96 | super.addGestureRotateAngle(rotateXAngle, rotateYAngle); 97 | // mGestureYAngle = 0; 98 | // mSphere.rotate(Vector3.Y, rotateYAngle); 99 | } 100 | 101 | 102 | @Override 103 | public void onRender(long ellapsedRealtime, double deltaTime) { 104 | super.onRender(ellapsedRealtime, deltaTime); 105 | mVideoTexture.update(); 106 | } 107 | 108 | @Override 109 | public void onRenderSurfaceDestroyed(SurfaceTexture surfaceTexture) { 110 | super.onRenderSurfaceDestroyed(surfaceTexture); 111 | mMediaPlayer.stop(); 112 | mMediaPlayer.release(); 113 | } 114 | 115 | 116 | public void pauseVideo() { 117 | if (mMediaPlayer != null) 118 | mMediaPlayer.pause(); 119 | } 120 | 121 | public void resumeVideo() { 122 | if (mMediaPlayer != null) 123 | mMediaPlayer.start(); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/pan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/substarry/VRPlayer/8ad2c6dad39e6c2850da7ea7c2733d53bcde9059/app/src/main/res/drawable/pan.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/substarry/VRPlayer/8ad2c6dad39e6c2850da7ea7c2733d53bcde9059/app/src/main/res/drawable/splash.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ss.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/substarry/VRPlayer/8ad2c6dad39e6c2850da7ea7c2733d53bcde9059/app/src/main/res/drawable/ss.jpg -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_fullscreen.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 11 | 21 | 22 | 24 | 28 | 29 | 38 | 39 |