Skip to content

Commit

Permalink
glTF Camera Sample
Browse files Browse the repository at this point in the history
  • Loading branch information
ThomasGorisse committed Jun 19, 2024
1 parent fac4c1e commit 1e303ad
Show file tree
Hide file tree
Showing 8 changed files with 254 additions and 0 deletions.
1 change: 1 addition & 0 deletions samples/gltf-camera/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
55 changes: 55 additions & 0 deletions samples/gltf-camera/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
}

android {
namespace "io.github.sceneview.sample.gltfcamera"

compileSdk 34

defaultConfig {
applicationId "io.github.sceneview.sample.gltfcamera"
minSdk 28
targetSdk 34
versionCode 1
versionName "1.0.0"
}

buildTypes {
release {
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17
}
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.14"
}
androidResources {
noCompress 'filamat', 'ktx'
}
}

dependencies {
implementation project(":samples:common")

implementation "androidx.compose.ui:ui:1.6.7"
implementation "androidx.compose.foundation:foundation:1.6.7"
implementation 'androidx.activity:activity-compose:1.9.0'
implementation 'androidx.compose.material:material:1.6.7'
implementation "androidx.compose.ui:ui-tooling-preview:1.6.7"
implementation "androidx.navigation:navigation-compose:2.7.7"
debugImplementation "androidx.compose.ui:ui-tooling:1.6.7"

// SceneView
releaseImplementation "io.github.sceneview:sceneview:2.2.1"
debugImplementation project(":sceneview")
}
20 changes: 20 additions & 0 deletions samples/gltf-camera/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.SceneViewSample">
<activity
android:name="io.github.sceneview.sample.gltfcamera.MainActivity"
android:configChanges="orientation|screenSize"
android:exported="true"
android:label="@string/app_name"
android:screenOrientation="locked">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package io.github.sceneview.sample.gltfcamera

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Done
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilterChip
import androidx.compose.material3.FilterChipDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import io.github.sceneview.Scene
import io.github.sceneview.node.ModelNode
import io.github.sceneview.rememberEngine
import io.github.sceneview.rememberEnvironmentLoader
import io.github.sceneview.rememberModelLoader
import io.github.sceneview.rememberNode
import io.github.sceneview.sample.SceneviewTheme

private const val kAperture = 16f
private const val kShutterSpeed = 1f / 125f
private const val kSensitivity = 100f

class MainActivity : ComponentActivity() {

@OptIn(
ExperimentalMaterial3Api::class
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

setContent {
SceneviewTheme {
Box(modifier = Modifier.fillMaxSize()) {
val engine = rememberEngine()
val modelLoader = rememberModelLoader(engine)
val environmentLoader = rememberEnvironmentLoader(engine)

val modelNode = rememberNode {
ModelNode(
modelInstance = modelLoader.createModelInstance(
assetFileLocation = "models/halls_green_haa_emplacement.glb"
)
)
}
val cameraNodes = remember(modelNode) {
modelNode.cameraNodes.onEach {
it.setExposure(kAperture, kShutterSpeed, kSensitivity)
}
}

var selectedCameraNode by remember { mutableStateOf(cameraNodes[0]) }

Scene(
modifier = Modifier
.fillMaxSize()
.onSizeChanged { modelNode.updateCamerasProjection(it) },
engine = engine,
modelLoader = modelLoader,
cameraNode = selectedCameraNode,
childNodes = listOf(modelNode),
environment = environmentLoader.createHDREnvironment(
assetFileLocation = "environments/symmetrical_garden_02_4k.hdr"
)!!
)
ChipsGroup(
labels = cameraNodes.map { it.name ?: "" },
onSelected = {
selectedCameraNode = cameraNodes[it]
}
)

TopAppBar(
title = {
Image(
modifier = Modifier
.width(192.dp),
painter = painterResource(id = R.drawable.logo),
contentDescription = "Logo"
)
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.25f),
titleContentColor = MaterialTheme.colorScheme.onPrimary

)
)
}
}
}
}

@OptIn(ExperimentalLayoutApi::class)
@Composable
fun BoxScope.ChipsGroup(labels: List<String>, onSelected: (index: Int) -> Unit) {
var selectedIndex by remember { mutableIntStateOf(0) }
FlowRow(
modifier = Modifier
.fillMaxWidth()
.align(Alignment.BottomEnd)
.background(MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.5f))
.navigationBarsPadding()
.padding(8.dp)
) {

labels.forEachIndexed { index, label ->
val selected = selectedIndex == index
FilterChip(
label = {
Text(
style = MaterialTheme.typography.bodyLarge.copy(),
text = label
)
},
modifier = Modifier.padding(4.dp),
selected = selected,
onClick = {
selectedIndex = index
onSelected(index)
},
leadingIcon = if (selected) {
{
Icon(
imageVector = Icons.Filled.Done,
contentDescription = "Done icon",
modifier = Modifier.size(FilterChipDefaults.IconSize)
)
}
} else {
null
}
)
}
}
}
}

fun ModelNode.updateCamerasProjection(viewPortSize: IntSize) {
cameraNodes.forEach { cameraNode ->
cameraNode.updateProjection(
aspect = viewPortSize.let { it.width.toDouble() / it.height.toDouble() },
near = 0.05f,
far = 5000.0f
)
}
}
3 changes: 3 additions & 0 deletions samples/gltf-camera/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<resources>
<string name="app_name">glTF Camera</string>
</resources>
1 change: 1 addition & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ include ':samples:ar-cloud-anchor'
include ':samples:ar-model-viewer'
include ':samples:ar-model-viewer-compose'
include ':samples:ar-point-cloud'
include ':samples:gltf-camera'
include ':samples:model-viewer'
include ':samples:model-viewer-compose'

0 comments on commit 1e303ad

Please sign in to comment.