diff --git a/solar-system/.gitignore b/solar-system/.gitignore new file mode 100644 index 0000000..fd45b12 --- /dev/null +++ b/solar-system/.gitignore @@ -0,0 +1,11 @@ +*.iml +.gradle +/local.properties +/.idea/caches/build_file_checksums.ser +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +.DS_Store +/build +/captures +.externalNativeBuild diff --git a/solar-system/.idea/codeStyles/Project.xml b/solar-system/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..34dc27c --- /dev/null +++ b/solar-system/.idea/codeStyles/Project.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/solar-system/.idea/codeStyles/codeStyleConfig.xml b/solar-system/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/solar-system/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/solar-system/.idea/copyright/GPL_v__2_0.xml b/solar-system/.idea/copyright/GPL_v__2_0.xml new file mode 100644 index 0000000..534f537 --- /dev/null +++ b/solar-system/.idea/copyright/GPL_v__2_0.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/solar-system/.idea/copyright/profiles_settings.xml b/solar-system/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..466f184 --- /dev/null +++ b/solar-system/.idea/copyright/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/solar-system/.idea/gradle.xml b/solar-system/.idea/gradle.xml new file mode 100644 index 0000000..7ac24c7 --- /dev/null +++ b/solar-system/.idea/gradle.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/solar-system/.idea/misc.xml b/solar-system/.idea/misc.xml new file mode 100644 index 0000000..b0c7b20 --- /dev/null +++ b/solar-system/.idea/misc.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/solar-system/.idea/runConfigurations.xml b/solar-system/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/solar-system/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/solar-system/app/.gitignore b/solar-system/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/solar-system/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/solar-system/app/build.gradle b/solar-system/app/build.gradle new file mode 100644 index 0000000..a7b3ac9 --- /dev/null +++ b/solar-system/app/build.gradle @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2019, norangebit + * + * This file is part of solar-system. + * + * solar-system is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * solar-system is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with solar-system. If not, see + * + */ + +apply plugin: 'com.android.application' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "it.norangeb.solarsystem" + minSdkVersion 26 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation 'com.android.support:design:28.0.0' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + implementation "com.google.ar.sceneform.ux:sceneform-ux:1.6.0" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.0" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.0" + implementation 'com.google.ar.sceneform:assets:1.6.0' +} diff --git a/solar-system/app/proguard-rules.pro b/solar-system/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/solar-system/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/solar-system/app/src/androidTest/java/it/norangeb/solarsystem/ExampleInstrumentedTest.kt b/solar-system/app/src/androidTest/java/it/norangeb/solarsystem/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..eacd59d --- /dev/null +++ b/solar-system/app/src/androidTest/java/it/norangeb/solarsystem/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package it.norangeb.solarsystem + +import android.support.test.InstrumentationRegistry +import android.support.test.runner.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getTargetContext() + assertEquals("it.norangeb.solarsystem", appContext.packageName) + } +} diff --git a/solar-system/app/src/main/AndroidManifest.xml b/solar-system/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..18ffe50 --- /dev/null +++ b/solar-system/app/src/main/AndroidManifest.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/solar-system/app/src/main/java/it/norangeb/solarsystem/MainActivity.kt b/solar-system/app/src/main/java/it/norangeb/solarsystem/MainActivity.kt new file mode 100644 index 0000000..8b4c537 --- /dev/null +++ b/solar-system/app/src/main/java/it/norangeb/solarsystem/MainActivity.kt @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2019, norangebit + * + * This file is part of solar-system. + * + * solar-system is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * solar-system is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with solar-system. If not, see + * + */ + +package it.norangeb.solarsystem + +import android.os.Bundle +import android.support.v7.app.AppCompatActivity +import android.view.MotionEvent +import com.google.ar.core.HitResult +import com.google.ar.core.Plane +import com.google.ar.sceneform.rendering.ModelRenderable +import com.google.ar.sceneform.ux.ArFragment +import kotlinx.coroutines.* + +class MainActivity : AppCompatActivity() { + private val TAG = MainActivity::class.java.canonicalName + private lateinit var arFragment: ArFragment + private var isModelAdded = false + private lateinit var planets: Map + private lateinit var loadPlanetsJob: Job + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + if (!checkIsSupportedDeviceOrFinish(this, TAG)) + return + + setContentView(R.layout.activity_main) + arFragment = supportFragmentManager.findFragmentById(R.id.ar_fragment) as ArFragment + + loadPlanetsJob = GlobalScope.launch (Dispatchers.Main) { + planets = loadPlanets(this@MainActivity) + } + + arFragment.setOnTapArPlaneListener(this::placeSolarSystem) + } + + private fun placeSolarSystem(hitResult: HitResult, plane: Plane, motionEvent: MotionEvent) { + GlobalScope.launch(Dispatchers.Main) { + loadPlanetsJob.join() + addTransformableNodeToScene(arFragment, hitResult.createAnchor(), planets[Planet.EARTH]!!) + } + } +} diff --git a/solar-system/app/src/main/java/it/norangeb/solarsystem/Util.kt b/solar-system/app/src/main/java/it/norangeb/solarsystem/Util.kt new file mode 100644 index 0000000..2df232d --- /dev/null +++ b/solar-system/app/src/main/java/it/norangeb/solarsystem/Util.kt @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2019, norangebit + * + * This file is part of solar-system. + * + * solar-system is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * solar-system is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with solar-system. If not, see + * + */ + +package it.norangeb.solarsystem + +import android.annotation.SuppressLint +import android.app.Activity +import android.app.ActivityManager +import android.content.Context +import android.net.Uri +import android.os.Build +import android.util.Log +import android.widget.Toast +import com.google.ar.core.Anchor +import com.google.ar.sceneform.AnchorNode +import com.google.ar.sceneform.Node +import com.google.ar.sceneform.assets.RenderableSource +import com.google.ar.sceneform.rendering.* +import com.google.ar.sceneform.ux.ArFragment +import com.google.ar.sceneform.ux.TransformableNode +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.async +import java.util.concurrent.CompletableFuture + +private val MIN_OPENGL_VERSION = 3.0 + +@SuppressLint("ObsoleteSdkInt") +fun checkIsSupportedDeviceOrFinish(activity: Activity, tag: String): Boolean { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + Log.e(tag, "Sceneform requires Android N or later") + Toast.makeText(activity, "Sceneform requires Android N or later", Toast.LENGTH_LONG).show() + activity.finish() + return false + } + val openGlVersionString = (activity.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager) + .deviceConfigurationInfo + .glEsVersion + if (java.lang.Double.parseDouble(openGlVersionString) < MIN_OPENGL_VERSION) { + Log.e(tag, "Sceneform requires OpenGL ES 3.0 later") + Toast.makeText(activity, "Sceneform requires OpenGL ES 3.0 or later", Toast.LENGTH_LONG) + .show() + activity.finish() + return false + } + return true +} + +suspend fun loadPlanets(context: Context): Map { + threadLog("load planets") + val sun = loadPlanet(context, Planet.SUN) + val mercury = loadPlanet(context, Planet.MERCURY) + val venus = loadPlanet(context, Planet.VENUS) + val earth = loadPlanet(context, Planet.EARTH) + val mars = loadPlanet(context, Planet.MARS) + val jupiter = loadPlanet(context, Planet.JUPITER) + val saturn = loadPlanet(context, Planet.SATURN) + val uranus = loadPlanet(context, Planet.URANUS) + val neptune = loadPlanet(context, Planet.NEPTUNE) + + return mapOf( + Pair(Planet.SUN, sun.await()), + Pair(Planet.MERCURY, mercury.await()), + Pair(Planet.VENUS, venus.await()), + Pair(Planet.EARTH, earth.await()), + Pair(Planet.MARS, mars.await()), + Pair(Planet.JUPITER, jupiter.await()), + Pair(Planet.SATURN, saturn.await()), + Pair(Planet.URANUS, uranus.await()), + Pair(Planet.NEPTUNE, neptune.await()) + ) +} + +fun loadPlanet(context: Context, planet: Planet): Deferred { + val modelSource = fetchModel(context, Uri.parse(planet.value)) + val futureRenderable = buildFutureRenderable( + context, + modelSource, + Uri.parse(planet.value) + ) + + return GlobalScope.async(Dispatchers.IO) { + threadLog("start load: $planet") + val renderable = futureRenderable.get() + threadLog("end load: $planet") + renderable + } +} + +fun buildFutureRenderable( + context: Context, + model: RenderableSource, + modelUri: Uri +): CompletableFuture = + ModelRenderable.builder() + .setRegistryId(modelUri) + .setSource(context, model) + .build() + +fun fetchModel( + context: Context, + source: Uri +): RenderableSource = + RenderableSource.builder() + .setSource(context, source, RenderableSource.SourceType.GLTF2) + .setRecenterMode(RenderableSource.RecenterMode.ROOT) + .build() + +fun addTransformableNodeToScene(arFragment: ArFragment, anchor: Anchor, renderable: ModelRenderable): Node { + val anchorNode = AnchorNode(anchor) + val transformableNode = TransformableNode(arFragment.transformationSystem) + transformableNode.renderable = renderable + transformableNode.setParent(anchorNode) + arFragment.arSceneView.scene.addChild(anchorNode) + transformableNode.select() + return transformableNode +} + +enum class Planet(val value: String) { + SUN("https://poly.googleusercontent.com/downloads/69ejysWdDXG/2Gi-kna7W1j/Sun_01.gltf"), + MERCURY("https://poly.googleusercontent.com/downloads/9PBDNYhgXDS/0ikSBktlxQd/model.gltf"), + VENUS("https://poly.googleusercontent.com/downloads/5BKXL2tO5C6/7l37kn7jUdv/model.gltf"), + EARTH("https://poly.googleusercontent.com/downloads/dQcv6bKXuQD/3NFGAgmwv5x/model.gltf"), + MARS("https://poly.googleusercontent.com/downloads/8sNKYRTUFAe/f9eC5eU749w/model.gltf"), + JUPITER("https://poly.googleusercontent.com/downloads/6jv2Cl_xK2i/9lyFWlFV2GO/model.gltf"), + SATURN("https://poly.googleusercontent.com/downloads/b-y9HDTsu7q/4y6CcWQ0Yu0/model.gltf"), + URANUS("https://poly.googleusercontent.com/downloads/7qZDvQcXQWN/2GW1CXvX6g4/model.gltf"), + NEPTUNE("https://poly.googleusercontent.com/downloads/38LOedsa9ES/9oKqBu_hVcY/model.gltf") +} + +fun threadLog(message: String) = Log.d( + "COROUTINES", + "[${Thread.currentThread().name}]: $message" + ) diff --git a/solar-system/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/solar-system/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c1598bc --- /dev/null +++ b/solar-system/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + diff --git a/solar-system/app/src/main/res/drawable/ic_launcher_background.xml b/solar-system/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..4481380 --- /dev/null +++ b/solar-system/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/solar-system/app/src/main/res/layout/activity_main.xml b/solar-system/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..127e3fe --- /dev/null +++ b/solar-system/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,32 @@ + + + + + + + + \ No newline at end of file diff --git a/solar-system/app/src/main/res/layout/content_main.xml b/solar-system/app/src/main/res/layout/content_main.xml new file mode 100644 index 0000000..f92bc35 --- /dev/null +++ b/solar-system/app/src/main/res/layout/content_main.xml @@ -0,0 +1,36 @@ + + + + + + + \ No newline at end of file diff --git a/solar-system/app/src/main/res/menu/menu_main.xml b/solar-system/app/src/main/res/menu/menu_main.xml new file mode 100644 index 0000000..d4a595d --- /dev/null +++ b/solar-system/app/src/main/res/menu/menu_main.xml @@ -0,0 +1,29 @@ + + + + + diff --git a/solar-system/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/solar-system/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..bbd3e02 --- /dev/null +++ b/solar-system/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/solar-system/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/solar-system/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..bbd3e02 --- /dev/null +++ b/solar-system/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/solar-system/app/src/main/res/mipmap-hdpi/ic_launcher.png b/solar-system/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..898f3ed Binary files /dev/null and b/solar-system/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/solar-system/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/solar-system/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..dffca36 Binary files /dev/null and b/solar-system/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/solar-system/app/src/main/res/mipmap-mdpi/ic_launcher.png b/solar-system/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..64ba76f Binary files /dev/null and b/solar-system/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/solar-system/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/solar-system/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..dae5e08 Binary files /dev/null and b/solar-system/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/solar-system/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/solar-system/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..e5ed465 Binary files /dev/null and b/solar-system/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/solar-system/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/solar-system/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..14ed0af Binary files /dev/null and b/solar-system/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/solar-system/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/solar-system/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..b0907ca Binary files /dev/null and b/solar-system/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/solar-system/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/solar-system/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..d8ae031 Binary files /dev/null and b/solar-system/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/solar-system/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/solar-system/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..2c18de9 Binary files /dev/null and b/solar-system/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/solar-system/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/solar-system/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..beed3cd Binary files /dev/null and b/solar-system/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/solar-system/app/src/main/res/values/colors.xml b/solar-system/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..69b2233 --- /dev/null +++ b/solar-system/app/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #008577 + #00574B + #D81B60 + diff --git a/solar-system/app/src/main/res/values/dimens.xml b/solar-system/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..59a0b0c --- /dev/null +++ b/solar-system/app/src/main/res/values/dimens.xml @@ -0,0 +1,3 @@ + + 16dp + diff --git a/solar-system/app/src/main/res/values/strings.xml b/solar-system/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..2850471 --- /dev/null +++ b/solar-system/app/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + Solar system + Settings + diff --git a/solar-system/app/src/main/res/values/styles.xml b/solar-system/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..be9bed5 --- /dev/null +++ b/solar-system/app/src/main/res/values/styles.xml @@ -0,0 +1,37 @@ + + + + + + + +