Introduce filament-utils and Java bindings for camutils.
This library houses the KTX loader, camutils bindings, and a Kotlin math library. More will come later. Sample app is forthcoming.
This commit is contained in:
4
.github/workflows/android-continuous.yml
vendored
4
.github/workflows/android-continuous.yml
vendored
@@ -31,3 +31,7 @@ jobs:
|
||||
with:
|
||||
name: gltfio-android-release
|
||||
path: out/gltfio-android-release.aar
|
||||
- uses: actions/upload-artifact@v1.0.0
|
||||
with:
|
||||
name: filament-utils-android-release
|
||||
path: out/filament-utils-android-release.aar
|
||||
|
||||
1
.github/workflows/release.yml
vendored
1
.github/workflows/release.yml
vendored
@@ -107,6 +107,7 @@ jobs:
|
||||
mv out/filamat-android-full-release.aar out/filamat-${DATE}-full-android.aar
|
||||
mv out/filamat-android-lite-release.aar out/filamat-${DATE}-lite-android.aar
|
||||
mv out/gltfio-android-release.aar out/gltfio-${DATE}-android.aar
|
||||
mv out/filament-utils-android-release.aar out/filament-utils-${DATE}-android.aar
|
||||
python3 build/common/upload-assets.py ${TAG} out/*.aar
|
||||
env:
|
||||
TAG: ${{ steps.git_ref.outputs.tag }}
|
||||
|
||||
@@ -39,10 +39,11 @@ Here are all the libraries available in the group `com.google.android.filament`:
|
||||
|
||||
- `filament-android`: the Filament rendering engine itself
|
||||
- `gltfio-android`: a glTF 2.0 loader for Filament, depends on `filament-android`
|
||||
- `filament-utils-android`: KTX loading, Kotlin math, and camera utilities, depends on `gltfio-android`
|
||||
- `filamat-android-full`: a runtime material builder/compiler. This library is large but contains
|
||||
a full shader compiler/validator/optimizer
|
||||
- `filamat-android-lite`: a much smaller alternative to `filamat-android-full` that can only
|
||||
generate OpenGL shaders. It does not provide validation nor optimizations
|
||||
generate OpenGL shaders. It does not provide validation or optimizations
|
||||
|
||||
### Snapshots
|
||||
|
||||
|
||||
12
android/filament-utils-android/.gitignore
vendored
Normal file
12
android/filament-utils-android/.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
/.idea/caches
|
||||
/.idea/gradle.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
/.cxx
|
||||
104
android/filament-utils-android/CMakeLists.txt
Normal file
104
android/filament-utils-android/CMakeLists.txt
Normal file
@@ -0,0 +1,104 @@
|
||||
cmake_minimum_required(VERSION 3.6)
|
||||
|
||||
set(FILAMENT_DIR ${FILAMENT_DIST_DIR})
|
||||
|
||||
set(DISABLE_GLTFIO_JNI TRUE)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../gltfio-android ${CMAKE_CURRENT_BINARY_DIR}/gltfio-android)
|
||||
|
||||
add_library(filament STATIC IMPORTED)
|
||||
set_target_properties(filament PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilament.a)
|
||||
|
||||
add_library(backend STATIC IMPORTED)
|
||||
set_target_properties(backend PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libbackend.a)
|
||||
|
||||
add_library(camutils STATIC IMPORTED)
|
||||
set_target_properties(camutils PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libcamutils.a)
|
||||
|
||||
add_library(utils STATIC IMPORTED)
|
||||
set_target_properties(utils PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libutils.a)
|
||||
|
||||
add_library(filaflat STATIC IMPORTED)
|
||||
set_target_properties(filaflat PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilaflat.a)
|
||||
|
||||
add_library(image STATIC IMPORTED)
|
||||
set_target_properties(image PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libimage.a)
|
||||
|
||||
add_library(ibl STATIC IMPORTED)
|
||||
set_target_properties(ibl PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libibl.a)
|
||||
|
||||
add_library(geometry STATIC IMPORTED)
|
||||
set_target_properties(geometry PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libgeometry.a)
|
||||
|
||||
add_library(filabridge STATIC IMPORTED)
|
||||
set_target_properties(filabridge PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilabridge.a)
|
||||
|
||||
add_library(gltfio STATIC IMPORTED)
|
||||
set_target_properties(gltfio PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libgltfio_core.a)
|
||||
|
||||
add_library(gltfio_resources STATIC IMPORTED)
|
||||
set_target_properties(gltfio_resources PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libgltfio_resources.a)
|
||||
|
||||
add_library(bluevk STATIC IMPORTED)
|
||||
set_target_properties(bluevk PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libbluevk.a)
|
||||
|
||||
add_library(smol-v STATIC IMPORTED)
|
||||
set_target_properties(smol-v PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libsmol-v.a)
|
||||
|
||||
include_directories(${FILAMENT_DIR}/include
|
||||
..
|
||||
../../libs/utils/include)
|
||||
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/libfilament-utils-jni.map")
|
||||
|
||||
add_library(filament-utils-jni SHARED
|
||||
src/main/cpp/Bookmark.cpp
|
||||
src/main/cpp/Utils.cpp
|
||||
src/main/cpp/Manipulator.cpp
|
||||
|
||||
../common/CallbackUtils.cpp
|
||||
../common/NioUtils.cpp
|
||||
|
||||
$<TARGET_OBJECTS:gltfio-jni-obj>
|
||||
$<TARGET_OBJECTS:filament-jni-obj>
|
||||
)
|
||||
|
||||
set_target_properties(filament-utils-jni PROPERTIES LINK_DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libfilament-utils-jni.symbols)
|
||||
|
||||
# The ordering in the following list is important because CMake does not have dependency information.
|
||||
target_link_libraries(filament-utils-jni
|
||||
gltfio
|
||||
filament
|
||||
backend
|
||||
filaflat
|
||||
filabridge
|
||||
camutils
|
||||
geometry
|
||||
image
|
||||
ibl
|
||||
utils
|
||||
log
|
||||
GLESv3
|
||||
EGL
|
||||
android
|
||||
jnigraphics
|
||||
gltfio_resources
|
||||
m
|
||||
)
|
||||
|
||||
if (FILAMENT_SUPPORTS_VULKAN)
|
||||
target_link_libraries(filament-utils-jni bluevk smol-v)
|
||||
endif()
|
||||
63
android/filament-utils-android/build.gradle
Normal file
63
android/filament-utils-android/build.gradle
Normal file
@@ -0,0 +1,63 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
android {
|
||||
buildToolsVersion versions.buildTools
|
||||
compileSdkVersion versions.compileSdk
|
||||
defaultConfig {
|
||||
minSdkVersion versions.minSdk
|
||||
targetSdkVersion versions.targetSdk
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments.add("-DANDROID_PIE=ON")
|
||||
arguments.add("-DANDROID_PLATFORM=android-${versions.targetSdk}".toString())
|
||||
arguments.add("-DANDROID_STL=c++_static")
|
||||
arguments.add("-DFILAMENT_DIST_DIR=${filamentPath}".toString())
|
||||
cppFlags.add("-std=c++14")
|
||||
if (project.hasProperty('extra_cmake_args')) {
|
||||
arguments.add(extra_cmake_args)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path "CMakeLists.txt"
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
jni.srcDirs "src/main/cpp"
|
||||
kotlin.srcDirs += "src/main/java"
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation deps.kotlin
|
||||
implementation deps.androidx.annotations
|
||||
implementation project(':filament-android')
|
||||
implementation project(':gltfio-android')
|
||||
}
|
||||
|
||||
apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
|
||||
|
||||
afterEvaluate { project ->
|
||||
publishing {
|
||||
publications {
|
||||
release(MavenPublication) {
|
||||
artifactId = POM_ARTIFACT_ID
|
||||
from components.release
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
android/filament-utils-android/gradle.properties
Normal file
3
android/filament-utils-android/gradle.properties
Normal file
@@ -0,0 +1,3 @@
|
||||
POM_NAME=Filament Android Utilities
|
||||
POM_ARTIFACT_ID=filament-utils-android
|
||||
POM_PACKAGING=aar
|
||||
4
android/filament-utils-android/libfilament-utils-jni.map
Normal file
4
android/filament-utils-android/libfilament-utils-jni.map
Normal file
@@ -0,0 +1,4 @@
|
||||
LIBFILAMENT_UTILS {
|
||||
global: Java_com_google_android_filament_*; JNI*;
|
||||
local: *;
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
_Java_com_google_android_filament_*
|
||||
18
android/filament-utils-android/src/main/AndroidManifest.xml
Normal file
18
android/filament-utils-android/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<!--
|
||||
Copyright (C) 2020 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.android.filament.utils" />
|
||||
27
android/filament-utils-android/src/main/cpp/Bookmark.cpp
Normal file
27
android/filament-utils-android/src/main/cpp/Bookmark.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <camutils/Bookmark.h>
|
||||
|
||||
using namespace filament::camutils;
|
||||
using namespace filament::math;
|
||||
|
||||
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Bookmark_nDestroyBookmark(JNIEnv*, jclass, jlong nativeBookmark) {
|
||||
Bookmark<float>* bookmark = (Bookmark<float>*) nativeBookmark;
|
||||
delete bookmark;
|
||||
}
|
||||
175
android/filament-utils-android/src/main/cpp/Manipulator.cpp
Normal file
175
android/filament-utils-android/src/main/cpp/Manipulator.cpp
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <math/mat3.h>
|
||||
#include <math/vec3.h>
|
||||
|
||||
#include <camutils/Manipulator.h>
|
||||
|
||||
using namespace filament::camutils;
|
||||
using namespace filament::math;
|
||||
|
||||
using Builder = Manipulator<float>::Builder;
|
||||
|
||||
extern "C" JNIEXPORT jlong Java_com_google_android_filament_utils_Manipulator_nCreateBuilder(JNIEnv*, jclass) {
|
||||
return (jlong) new Builder {};
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nDestroyBuilder(JNIEnv*, jclass, jlong nativeBuilder) {
|
||||
Builder* builder = (Builder*) nativeBuilder;
|
||||
delete builder;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderViewport(JNIEnv*, jclass, jlong nativeBuilder, jint width, jint height) {
|
||||
Builder* builder = (Builder*) nativeBuilder;
|
||||
builder->viewport(width, height);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderTargetPosition(JNIEnv*, jclass, jlong nativeBuilder, jfloat x, jfloat y, jfloat z) {
|
||||
Builder* builder = (Builder*) nativeBuilder;
|
||||
builder->targetPosition(x, y, z);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderUpVector(JNIEnv*, jclass, jlong nativeBuilder, jfloat x, jfloat y, jfloat z) {
|
||||
Builder* builder = (Builder*) nativeBuilder;
|
||||
builder->upVector(x, y, z);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderZoomSpeed(JNIEnv*, jclass, jlong nativeBuilder, jfloat arg) {
|
||||
Builder* builder = (Builder*) nativeBuilder;
|
||||
builder->zoomSpeed(arg);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderOrbitHomePosition(JNIEnv*, jclass, jlong nativeBuilder, jfloat x, jfloat y, jfloat z) {
|
||||
Builder* builder = (Builder*) nativeBuilder;
|
||||
builder->orbitHomePosition(x, y, z);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderOrbitSpeed(JNIEnv*, jclass, jlong nativeBuilder, jfloat x, jfloat y) {
|
||||
Builder* builder = (Builder*) nativeBuilder;
|
||||
builder->orbitSpeed(x, y);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderFovDirection(JNIEnv*, jclass, jlong nativeBuilder, jint arg) {
|
||||
Builder* builder = (Builder*) nativeBuilder;
|
||||
builder->fovDirection((Fov) arg);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderFovDegrees(JNIEnv*, jclass, jlong nativeBuilder, jfloat arg) {
|
||||
Builder* builder = (Builder*) nativeBuilder;
|
||||
builder->fovDegrees(arg);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderFarPlane(JNIEnv*, jclass, jlong nativeBuilder, jfloat distance) {
|
||||
Builder* builder = (Builder*) nativeBuilder;
|
||||
builder->farPlane(distance);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderMapExtent(JNIEnv*, jclass, jlong nativeBuilder, jfloat width, jfloat height) {
|
||||
Builder* builder = (Builder*) nativeBuilder;
|
||||
builder->mapExtent(width, height);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderMapMinDistance(JNIEnv*, jclass, jlong nativeBuilder, jfloat arg) {
|
||||
Builder* builder = (Builder*) nativeBuilder;
|
||||
builder->mapMinDistance(arg);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderGroundPlane(JNIEnv*, jclass, jlong nativeBuilder, jfloat a, jfloat b, jfloat c, jfloat d) {
|
||||
Builder* builder = (Builder*) nativeBuilder;
|
||||
builder->groundPlane(a, b, c, d);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT long Java_com_google_android_filament_utils_Manipulator_nBuilderBuild(JNIEnv*, jclass, jlong nativeBuilder, jint mode) {
|
||||
Builder* builder = (Builder*) nativeBuilder;
|
||||
return (jlong) builder->build((Mode) mode);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_utils_Manipulator_nDestroyManipulator(JNIEnv*, jclass, jlong nativeManip) {
|
||||
auto manip = (Manipulator<float>*) nativeManip;
|
||||
delete manip;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL Java_com_google_android_filament_utils_Manipulator_nGetMode(JNIEnv*, jclass, jlong nativeManip) {
|
||||
auto manip = (Manipulator<float>*) nativeManip;
|
||||
return (int) manip->getMode();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_utils_Manipulator_nSetViewport(JNIEnv*, jclass, jlong nativeManip, jint width, jint height) {
|
||||
auto manip = (Manipulator<float>*) nativeManip;
|
||||
manip->setViewport(width, height);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_utils_Manipulator_nGetLookAt(JNIEnv* env, jclass, jlong nativeManip, jfloatArray eyePosition, jfloatArray targetPosition, jfloatArray upward) {
|
||||
auto manip = (Manipulator<float>*) nativeManip;
|
||||
|
||||
jfloat *eye = env->GetFloatArrayElements(eyePosition, NULL);
|
||||
jfloat *target = env->GetFloatArrayElements(targetPosition, NULL);
|
||||
jfloat *up = env->GetFloatArrayElements(upward, NULL);
|
||||
|
||||
manip->getLookAt((float3*) eye, (float3*) target, (float3*) up);
|
||||
|
||||
env->ReleaseFloatArrayElements(eyePosition, eye, 0);
|
||||
env->ReleaseFloatArrayElements(targetPosition, target, 0);
|
||||
env->ReleaseFloatArrayElements(upward, up, 0);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_utils_Manipulator_nRaycast(JNIEnv* env, jclass, jlong nativeManip, jint x, jint y, jfloatArray result) {
|
||||
auto manip = (Manipulator<float>*) nativeManip;
|
||||
jfloat *presult = env->GetFloatArrayElements(result, NULL);
|
||||
manip->raycast(x, y, (float3*) presult);
|
||||
env->ReleaseFloatArrayElements(result, presult, 0);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_utils_Manipulator_nGrabBegin(JNIEnv*, jclass, jlong nativeManip, jint x, jint y, jboolean strafe) {
|
||||
auto manip = (Manipulator<float>*) nativeManip;
|
||||
manip->grabBegin(x, y, (bool) strafe);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_utils_Manipulator_nGrabUpdate(JNIEnv*, jclass, jlong nativeManip, jint x, jint y) {
|
||||
auto manip = (Manipulator<float>*) nativeManip;
|
||||
manip->grabUpdate(x, y);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_utils_Manipulator_nGrabEnd(JNIEnv*, jclass, jlong nativeManip) {
|
||||
auto manip = (Manipulator<float>*) nativeManip;
|
||||
manip->grabEnd();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_utils_Manipulator_nZoom(JNIEnv*, jclass, jlong nativeManip, jint x, jint y, jfloat scrolldelta) {
|
||||
auto manip = (Manipulator<float>*) nativeManip;
|
||||
manip->zoom(x, y, scrolldelta);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL Java_com_google_android_filament_utils_Manipulator_nGetCurrentBookmark(JNIEnv*, jclass, jlong nativeManip) {
|
||||
auto manip = (Manipulator<float>*) nativeManip;
|
||||
return (jlong) new Bookmark<float>(manip->getCurrentBookmark());
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL Java_com_google_android_filament_utils_Manipulator_nGetHomeBookmark(JNIEnv*, jclass, jlong nativeManip) {
|
||||
auto manip = (Manipulator<float>*) nativeManip;
|
||||
return (jlong) new Bookmark<float>(manip->getHomeBookmark());
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_utils_Manipulator_nJumpToBookmark(JNIEnv*, jclass, jlong nativeManip, jlong nativeBookmark) {
|
||||
auto manip = (Manipulator<float>*) nativeManip;
|
||||
auto bookmark = (Bookmark<float>*) nativeBookmark;
|
||||
manip->jumpToBookmark(*bookmark);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,8 +28,23 @@ using namespace filament;
|
||||
using namespace filament::math;
|
||||
using namespace image;
|
||||
|
||||
extern void registerCallbackUtils(JNIEnv*);
|
||||
extern void registerNioUtils(JNIEnv*);
|
||||
|
||||
jint JNI_OnLoad(JavaVM* vm, void*) {
|
||||
JNIEnv* env;
|
||||
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
registerCallbackUtils(env);
|
||||
registerNioUtils(env);
|
||||
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_gltfio_KtxLoader_nCreateTexture(JNIEnv* env, jclass,
|
||||
Java_com_google_android_filament_utils_KtxLoader_nCreateTexture(JNIEnv* env, jclass,
|
||||
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
AutoBuffer buffer(env, javaBuffer, remaining);
|
||||
@@ -41,7 +56,7 @@ Java_com_google_android_filament_gltfio_KtxLoader_nCreateTexture(JNIEnv* env, jc
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_gltfio_KtxLoader_nCreateIndirectLight(JNIEnv* env, jclass,
|
||||
Java_com_google_android_filament_utils_KtxLoader_nCreateIndirectLight(JNIEnv* env, jclass,
|
||||
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
AutoBuffer buffer(env, javaBuffer, remaining);
|
||||
@@ -64,7 +79,7 @@ Java_com_google_android_filament_gltfio_KtxLoader_nCreateIndirectLight(JNIEnv* e
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_gltfio_KtxLoader_nCreateSkybox(JNIEnv* env, jclass,
|
||||
Java_com_google_android_filament_utils_KtxLoader_nCreateSkybox(JNIEnv* env, jclass,
|
||||
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
AutoBuffer buffer(env, javaBuffer, remaining);
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.filament.utils;
|
||||
|
||||
public class Bookmark {
|
||||
private long mNativeObject;
|
||||
|
||||
Bookmark(long nativeObject) {
|
||||
mNativeObject = nativeObject;
|
||||
}
|
||||
|
||||
long getNativeObject() {
|
||||
return mNativeObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
nDestroyBookmark(mNativeObject);
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
private static native void nDestroyBookmark(long nativeObject);
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.filament.utils
|
||||
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Sets up a touch listener on an Android View and forwards events to a camera manipulator.
|
||||
* Supports one-touch orbit, two-touch pan, and pinch-to-zoom.
|
||||
*/
|
||||
class GestureDetector(private val view: View, private val manipulator: Manipulator) {
|
||||
private enum class Gesture { NONE, ORBIT, PAN, ZOOM }
|
||||
|
||||
// Simplified memento of MotionEvent, minimal but sufficient for our purposes.
|
||||
private data class TouchEvent(var pt0: Float2, var pt1: Float2, var count: Int) {
|
||||
constructor() : this(Float2(0f), Float2(0f), 0)
|
||||
constructor(me: MotionEvent) : this() {
|
||||
if (me.pointerCount >= 1) {
|
||||
this.pt0 = Float2(me.getX(0), me.getY(0))
|
||||
this.count++
|
||||
}
|
||||
if (me.pointerCount >= 2) {
|
||||
this.pt1 = Float2(me.getX(1), me.getY(1))
|
||||
this.count++
|
||||
}
|
||||
}
|
||||
fun getPinchDistance(): Float { return distance(pt0, pt1) }
|
||||
fun getTouchesMidpoint(): Float2 { return mix(pt0, pt1, 0.5f) }
|
||||
}
|
||||
|
||||
private var currentGesture = Gesture.NONE
|
||||
private var previousEvent = TouchEvent()
|
||||
private val tentativePanEvents = ArrayList<TouchEvent>()
|
||||
private val tentativeOrbitEvents = ArrayList<TouchEvent>()
|
||||
private val tentativeZoomEvents = ArrayList<TouchEvent>()
|
||||
|
||||
private val kGestureConfidenceCount = 2
|
||||
private val kPanConfidenceDistance = 5
|
||||
private val kZoomConfidenceDistance = 10
|
||||
private val kZoomSpeed = 1f / 10f
|
||||
|
||||
init {
|
||||
view.setOnTouchListener func@{ _, event ->
|
||||
val x = event.getX(0).toInt()
|
||||
val y = view.height - event.getY(0).toInt()
|
||||
when (event.actionMasked) {
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
|
||||
// CANCEL GESTURE DUE TO UNEXPECTED POINTER COUNT
|
||||
|
||||
if ((event.pointerCount != 1 && currentGesture == Gesture.ORBIT) ||
|
||||
(event.pointerCount != 2 && currentGesture == Gesture.PAN) ||
|
||||
(event.pointerCount != 2 && currentGesture == Gesture.ZOOM)) {
|
||||
endGesture()
|
||||
return@func true
|
||||
}
|
||||
|
||||
// UPDATE EXISTING GESTURE
|
||||
|
||||
if (currentGesture == Gesture.ZOOM) {
|
||||
val d0 = previousEvent.getPinchDistance()
|
||||
val d1 = TouchEvent(event).getPinchDistance()
|
||||
manipulator.zoom(x, y, (d0 - d1) * kZoomSpeed)
|
||||
previousEvent = TouchEvent(event)
|
||||
return@func true
|
||||
}
|
||||
|
||||
if (currentGesture != Gesture.NONE) {
|
||||
manipulator.grabUpdate(x, y)
|
||||
return@func true
|
||||
}
|
||||
|
||||
// DETECT NEW GESTURE
|
||||
|
||||
if (event.pointerCount == 1) {
|
||||
tentativeOrbitEvents.add(TouchEvent(event))
|
||||
}
|
||||
|
||||
if (event.pointerCount == 2) {
|
||||
tentativePanEvents.add(TouchEvent(event))
|
||||
tentativeZoomEvents.add(TouchEvent(event))
|
||||
}
|
||||
|
||||
if (isOrbitGesture()) {
|
||||
manipulator.grabBegin(x, y, false)
|
||||
currentGesture = Gesture.ORBIT
|
||||
return@func true
|
||||
}
|
||||
|
||||
if (isZoomGesture()) {
|
||||
currentGesture = Gesture.ZOOM
|
||||
previousEvent = TouchEvent(event)
|
||||
return@func true
|
||||
}
|
||||
|
||||
if (isPanGesture()) {
|
||||
manipulator.grabBegin(x, y, true)
|
||||
currentGesture = Gesture.PAN
|
||||
return@func true
|
||||
}
|
||||
}
|
||||
MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_UP -> {
|
||||
endGesture()
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun endGesture() {
|
||||
tentativePanEvents.clear()
|
||||
tentativeOrbitEvents.clear()
|
||||
tentativeZoomEvents.clear()
|
||||
currentGesture = Gesture.NONE
|
||||
manipulator.grabEnd()
|
||||
}
|
||||
|
||||
private fun isOrbitGesture(): Boolean {
|
||||
return tentativeOrbitEvents.size > kGestureConfidenceCount
|
||||
}
|
||||
|
||||
private fun isPanGesture(): Boolean {
|
||||
if (tentativePanEvents.size <= kGestureConfidenceCount) {
|
||||
return false
|
||||
}
|
||||
val oldest = tentativePanEvents.first().getTouchesMidpoint()
|
||||
val newest = tentativePanEvents.last().getTouchesMidpoint()
|
||||
return distance(oldest, newest) > kPanConfidenceDistance
|
||||
}
|
||||
|
||||
private fun isZoomGesture(): Boolean {
|
||||
if (tentativeZoomEvents.size <= kGestureConfidenceCount) {
|
||||
return false
|
||||
}
|
||||
val oldest = tentativeZoomEvents.first().getPinchDistance()
|
||||
val newest = tentativeZoomEvents.last().getPinchDistance()
|
||||
return kotlin.math.abs(newest - oldest) > kZoomConfidenceDistance
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.filament.gltfio;
|
||||
package com.google.android.filament.utils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -25,7 +25,6 @@ import com.google.android.filament.Skybox;
|
||||
import com.google.android.filament.Texture;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.Buffer;
|
||||
|
||||
/**
|
||||
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.filament.utils;
|
||||
|
||||
import androidx.annotation.IntRange;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.Size;
|
||||
|
||||
/**
|
||||
* Helper that enables camera interaction similar to sketchfab or Google Maps.
|
||||
*
|
||||
* Clients notify the camera manipulator of various mouse or touch events, then periodically call
|
||||
* its getLookAt() method so that they can adjust their camera(s). Two modes are supported: ORBIT
|
||||
* and MAP. To construct a manipulator instance, the desired mode is passed into the create method.
|
||||
*
|
||||
* @see Bookmark
|
||||
*/
|
||||
public class Manipulator {
|
||||
private long mNativeObject;
|
||||
|
||||
private Manipulator(long nativeIndexBuffer) {
|
||||
mNativeObject = nativeIndexBuffer;
|
||||
}
|
||||
|
||||
public enum Mode { ORBIT, MAP };
|
||||
|
||||
public enum Fov { VERTICAL, HORIZONTAL };
|
||||
|
||||
public static class Builder {
|
||||
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
|
||||
// Keep to finalize native resources
|
||||
private final BuilderFinalizer mFinalizer;
|
||||
private final long mNativeBuilder;
|
||||
|
||||
public Builder() {
|
||||
mNativeBuilder = nCreateBuilder();
|
||||
mFinalizer = new BuilderFinalizer(mNativeBuilder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Width and height of the viewing area.
|
||||
*
|
||||
* @return this <code>Builder</code> object for chaining calls
|
||||
*/
|
||||
@NonNull
|
||||
public Builder viewport(@IntRange(from = 1) int width, @IntRange(from = 1) int height) {
|
||||
nBuilderViewport(mNativeBuilder, width, height);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets world-space position of interest, which defaults to (0,0,0).
|
||||
*
|
||||
* @return this <code>Builder</code> object for chaining calls
|
||||
*/
|
||||
@NonNull
|
||||
public Builder targetPosition(float x, float y, float z) {
|
||||
nBuilderTargetPosition(mNativeBuilder, x, y, z);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets orientation for the home position, which defaults to (0,1,0).
|
||||
*
|
||||
* @return this <code>Builder</code> object for chaining calls
|
||||
*/
|
||||
@NonNull
|
||||
public Builder upVector(float x, float y, float z) {
|
||||
nBuilderUpVector(mNativeBuilder, x, y, z);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the scroll delta multiplier, which defaults to 0.01.
|
||||
*
|
||||
* @return this <code>Builder</code> object for chaining calls
|
||||
*/
|
||||
@NonNull
|
||||
public Builder zoomSpeed(float arg) {
|
||||
nBuilderZoomSpeed(mNativeBuilder, arg);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets initial eye position in world space for ORBIT mode.
|
||||
* This defaults to (0,0,1).
|
||||
*
|
||||
* @return this <code>Builder</code> object for chaining calls
|
||||
*/
|
||||
@NonNull
|
||||
public Builder orbitHomePosition(float x, float y, float z) {
|
||||
nBuilderOrbitHomePosition(mNativeBuilder, x, y, z);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the multiplier with viewport delta for ORBIT mode.
|
||||
* This defaults to 0.01
|
||||
*
|
||||
* @return this <code>Builder</code> object for chaining calls
|
||||
*/
|
||||
@NonNull
|
||||
public Builder orbitSpeed(float x, float y) {
|
||||
nBuilderOrbitSpeed(mNativeBuilder, x, y);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the FOV axis that's held constant when the viewport changes.
|
||||
* This defaults to Vertical.
|
||||
*
|
||||
* @return this <code>Builder</code> object for chaining calls
|
||||
*/
|
||||
@NonNull
|
||||
public Builder fovDirection(Fov fov) {
|
||||
nBuilderFovDirection(mNativeBuilder, fov.ordinal());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the full FOV (not the half-angle) in the degrees.
|
||||
* This defaults to 33.
|
||||
*
|
||||
* @return this <code>Builder</code> object for chaining calls
|
||||
*/
|
||||
@NonNull
|
||||
public Builder fovDegrees(float arg) {
|
||||
nBuilderFovDegrees(mNativeBuilder, arg);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the distance to the far plane, which defaults to 5000.
|
||||
*
|
||||
* @return this <code>Builder</code> object for chaining calls
|
||||
*/
|
||||
@NonNull
|
||||
public Builder farPlane(float arg) {
|
||||
nBuilderFarPlane(mNativeBuilder, arg);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ground plane size used to compute the home position for MAP mode.
|
||||
* This defaults to 512 x 512
|
||||
*
|
||||
* @return this <code>Builder</code> object for chaining calls
|
||||
*/
|
||||
@NonNull
|
||||
public Builder mapExtent(float width, float height) {
|
||||
nBuilderMapExtent(mNativeBuilder, width, height);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constrains the zoom-in level. Defaults to 0.
|
||||
*
|
||||
* @return this <code>Builder</code> object for chaining calls
|
||||
*/
|
||||
@NonNull
|
||||
public Builder mapMinDistance(float arg) {
|
||||
nBuilderMapMinDistance(mNativeBuilder, arg);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ground plane equation used for ray casts.
|
||||
* This is a plane equation as in Ax + By + Cz + D = 0.
|
||||
* Defaults to (0, 0, 1, 0).
|
||||
*
|
||||
* @return this <code>Builder</code> object for chaining calls
|
||||
*/
|
||||
@NonNull
|
||||
public Builder groundPlane(float a, float b, float c, float d) {
|
||||
nBuilderGroundPlane(mNativeBuilder, a, b, c, d);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns the <code>Manipulator</code> object.
|
||||
*
|
||||
* @return the newly created <code>Manipulator</code> object
|
||||
*
|
||||
* @exception IllegalStateException if the Manipulator could not be created
|
||||
*
|
||||
*/
|
||||
@NonNull
|
||||
public Manipulator build(Mode mode) {
|
||||
long nativeManipulator = nBuilderBuild(mNativeBuilder, mode.ordinal());
|
||||
if (nativeManipulator == 0)
|
||||
throw new IllegalStateException("Couldn't create Manipulator");
|
||||
return new Manipulator(nativeManipulator);
|
||||
}
|
||||
|
||||
private static class BuilderFinalizer {
|
||||
private final long mNativeObject;
|
||||
|
||||
BuilderFinalizer(long nativeObject) {
|
||||
mNativeObject = nativeObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finalize() {
|
||||
try {
|
||||
super.finalize();
|
||||
} catch (Throwable t) { // Ignore
|
||||
} finally {
|
||||
nDestroyBuilder(mNativeObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void finalize() {
|
||||
try {
|
||||
super.finalize();
|
||||
} catch (Throwable t) { // Ignore
|
||||
} finally {
|
||||
nDestroyManipulator(mNativeObject);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the immutable mode of the manipulator.
|
||||
*/
|
||||
public Mode getMode() { return Mode.values()[nGetMode(mNativeObject)]; }
|
||||
|
||||
/**
|
||||
* Sets the viewport dimensions in terms of pixels.
|
||||
*
|
||||
* The manipulator uses this only in the grab and raycast methods, since
|
||||
* those methods consume coordinates in viewport space.
|
||||
*/
|
||||
public void setViewport(int width, int height) {
|
||||
nSetViewport(mNativeObject, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current orthonormal basis. This is usually called once per frame.
|
||||
*/
|
||||
public void getLookAt(
|
||||
@NonNull @Size(min = 3) float[] eyePosition,
|
||||
@NonNull @Size(min = 3) float[] targetPosition,
|
||||
@NonNull @Size(min = 3) float[] upward) {
|
||||
nGetLookAt(mNativeObject, eyePosition, targetPosition, upward);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a viewport coordinate, picks a point in the ground plane.
|
||||
*/
|
||||
@Nullable @Size(min = 3)
|
||||
public float[] raycast(int x, int y) {
|
||||
float[] result = new float[3];
|
||||
nRaycast(mNativeObject, x, y, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a grabbing session (i.e. the user is dragging around in the viewport).
|
||||
*
|
||||
* This starts a panning session in MAP mode, and start either rotating or strafing in ORBIT.
|
||||
*
|
||||
* @param x X-coordinate for point of interest in viewport space
|
||||
* @param y Y-coordinate for point of interest in viewport space
|
||||
* @param strafe ORBIT mode only; if true, starts a translation rather than a rotation.
|
||||
*/
|
||||
public void grabBegin(int x, int y, boolean strafe) {
|
||||
nGrabBegin(mNativeObject, x, y, strafe);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a grabbing session.
|
||||
*
|
||||
* This must be called at least once between grabBegin / grabEnd to dirty the camera.
|
||||
*/
|
||||
public void grabUpdate(int x, int y) {
|
||||
nGrabUpdate(mNativeObject, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends a grabbing session.
|
||||
*/
|
||||
public void grabEnd() {
|
||||
nGrabEnd(mNativeObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dollys the camera along the viewing direction.
|
||||
*
|
||||
* @param x X-coordinate for point of interest in viewport space
|
||||
* @param y Y-coordinate for point of interest in viewport space
|
||||
* @param scrolldelta Positive means "zoom in", negative means "zoom out"
|
||||
*/
|
||||
public void zoom(int x, int y, float scrolldelta) {
|
||||
nZoom(mNativeObject, x, y, scrolldelta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a handle that can be used to reset the manipulator back to its current position.
|
||||
*
|
||||
* \see jumpToBookmark
|
||||
*/
|
||||
public Bookmark getCurrentBookmark() {
|
||||
return new Bookmark(nGetCurrentBookmark(mNativeObject));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a handle that can be used to reset the manipulator back to its home position.
|
||||
*
|
||||
* see jumpToBookmark
|
||||
*/
|
||||
public Bookmark getHomeBookmark() {
|
||||
return new Bookmark(nGetHomeBookmark(mNativeObject));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the manipulator position and orientation back to a stashed state.
|
||||
*
|
||||
* \see getCurrentBookmark, getHomeBookmark
|
||||
*/
|
||||
public void jumpToBookmark(Bookmark bookmark) {
|
||||
nJumpToBookmark(mNativeObject, bookmark.getNativeObject());
|
||||
}
|
||||
|
||||
private static native long nCreateBuilder();
|
||||
private static native void nDestroyBuilder(long nativeBuilder);
|
||||
private static native void nBuilderViewport(long nativeBuilder, int width, int height);
|
||||
private static native void nBuilderTargetPosition(long nativeBuilder, float x, float y, float z);
|
||||
private static native void nBuilderUpVector(long nativeBuilder, float x, float y, float z);
|
||||
private static native void nBuilderZoomSpeed(long nativeBuilder, float arg);
|
||||
private static native void nBuilderOrbitHomePosition(long nativeBuilder, float x, float y, float z);
|
||||
private static native void nBuilderOrbitSpeed(long nativeBuilder, float x, float y);
|
||||
private static native void nBuilderFovDirection(long nativeBuilder, int arg);
|
||||
private static native void nBuilderFovDegrees(long nativeBuilder, float arg);
|
||||
private static native void nBuilderFarPlane(long nativeBuilder, float distance);
|
||||
private static native void nBuilderMapExtent(long nativeBuilder, float width, float height);
|
||||
private static native void nBuilderMapMinDistance(long nativeBuilder, float arg);
|
||||
private static native void nBuilderGroundPlane(long nativeBuilder, float a, float b, float c, float d);
|
||||
private static native long nBuilderBuild(long nativeBuilder, int mode);
|
||||
|
||||
private static native void nDestroyManipulator(long nativeManip);
|
||||
private static native int nGetMode(long nativeManip);
|
||||
private static native void nSetViewport(long nativeManip, int width, int height);
|
||||
private static native void nGetLookAt(long nativeManip, float[] eyePosition, float[] targetPosition, float[] upward);
|
||||
private static native void nRaycast(long nativeManip, int x, int y, float[] result);
|
||||
private static native void nGrabBegin(long nativeManip, int x, int y, boolean strafe);
|
||||
private static native void nGrabUpdate(long nativeManip, int x, int y);
|
||||
private static native void nGrabEnd(long nativeManip);
|
||||
private static native void nZoom(long nativeManip, int x, int y, float scrolldelta);
|
||||
private static native long nGetCurrentBookmark(long nativeManip);
|
||||
private static native long nGetHomeBookmark(long nativeManip);
|
||||
private static native void nJumpToBookmark(long nativeManip, long nativeBookmark);
|
||||
}
|
||||
@@ -0,0 +1,520 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Romain Guy
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.filament.utils
|
||||
|
||||
import kotlin.math.*
|
||||
|
||||
enum class MatrixColumn {
|
||||
X, Y, Z, W
|
||||
}
|
||||
|
||||
data class Mat2(
|
||||
var x: Float2 = Float2(x = 1.0f),
|
||||
var y: Float2 = Float2(y = 1.0f)) {
|
||||
constructor(m: Mat2) : this(m.x.copy(), m.y.copy())
|
||||
|
||||
companion object {
|
||||
fun of(vararg a: Float): Mat2 {
|
||||
require(a.size >= 4)
|
||||
return Mat2(
|
||||
Float2(a[0], a[2]),
|
||||
Float2(a[1], a[3])
|
||||
)
|
||||
}
|
||||
|
||||
fun identity() = Mat2()
|
||||
}
|
||||
|
||||
operator fun get(column: Int) = when(column) {
|
||||
0 -> x
|
||||
1 -> y
|
||||
else -> throw IllegalArgumentException("column must be in 0..1")
|
||||
}
|
||||
operator fun get(column: Int, row: Int) = get(column)[row]
|
||||
|
||||
operator fun get(column: MatrixColumn) = when(column) {
|
||||
MatrixColumn.X -> x
|
||||
MatrixColumn.Y -> y
|
||||
else -> throw IllegalArgumentException("column must be X or Y")
|
||||
}
|
||||
operator fun get(column: MatrixColumn, row: Int) = get(column)[row]
|
||||
|
||||
operator fun invoke(row: Int, column: Int) = get(column - 1)[row - 1]
|
||||
operator fun invoke(row: Int, column: Int, v: Float) = set(column - 1, row - 1, v)
|
||||
|
||||
operator fun set(column: Int, v: Float2) {
|
||||
this[column].xy = v
|
||||
}
|
||||
operator fun set(column: Int, row: Int, v: Float) {
|
||||
this[column][row] = v
|
||||
}
|
||||
|
||||
operator fun unaryMinus() = Mat2(-x, -y)
|
||||
operator fun inc(): Mat2 {
|
||||
x++
|
||||
y++
|
||||
return this
|
||||
}
|
||||
operator fun dec(): Mat2 {
|
||||
x--
|
||||
y--
|
||||
return this
|
||||
}
|
||||
|
||||
operator fun plus(v: Float) = Mat2(x + v, y + v)
|
||||
operator fun minus(v: Float) = Mat2(x - v, y - v)
|
||||
operator fun times(v: Float) = Mat2(x * v, y * v)
|
||||
operator fun div(v: Float) = Mat2(x / v, y / v)
|
||||
|
||||
operator fun times(m: Mat2): Mat2 {
|
||||
val t = transpose(this)
|
||||
return Mat2(
|
||||
Float2(dot(t.x, m.x), dot(t.y, m.x)),
|
||||
Float2(dot(t.x, m.y), dot(t.y, m.y))
|
||||
)
|
||||
}
|
||||
|
||||
operator fun times(v: Float2): Float2 {
|
||||
val t = transpose(this)
|
||||
return Float2(dot(t.x, v), dot(t.y, v))
|
||||
}
|
||||
|
||||
fun toFloatArray() = floatArrayOf(
|
||||
x.x, y.x,
|
||||
x.y, y.y
|
||||
)
|
||||
|
||||
override fun toString(): String {
|
||||
return """
|
||||
|${x.x} ${y.x}|
|
||||
|${x.y} ${y.y}|
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data class Mat3(
|
||||
var x: Float3 = Float3(x = 1.0f),
|
||||
var y: Float3 = Float3(y = 1.0f),
|
||||
var z: Float3 = Float3(z = 1.0f)) {
|
||||
constructor(m: Mat3) : this(m.x.copy(), m.y.copy(), m.z.copy())
|
||||
|
||||
companion object {
|
||||
fun of(vararg a: Float): Mat3 {
|
||||
require(a.size >= 9)
|
||||
return Mat3(
|
||||
Float3(a[0], a[3], a[6]),
|
||||
Float3(a[1], a[4], a[7]),
|
||||
Float3(a[2], a[5], a[8])
|
||||
)
|
||||
}
|
||||
|
||||
fun identity() = Mat3()
|
||||
}
|
||||
|
||||
operator fun get(column: Int) = when(column) {
|
||||
0 -> x
|
||||
1 -> y
|
||||
2 -> z
|
||||
else -> throw IllegalArgumentException("column must be in 0..2")
|
||||
}
|
||||
operator fun get(column: Int, row: Int) = get(column)[row]
|
||||
|
||||
operator fun get(column: MatrixColumn) = when(column) {
|
||||
MatrixColumn.X -> x
|
||||
MatrixColumn.Y -> y
|
||||
MatrixColumn.Z -> z
|
||||
else -> throw IllegalArgumentException("column must be X, Y or Z")
|
||||
}
|
||||
operator fun get(column: MatrixColumn, row: Int) = get(column)[row]
|
||||
|
||||
operator fun invoke(row: Int, column: Int) = get(column - 1)[row - 1]
|
||||
operator fun invoke(row: Int, column: Int, v: Float) = set(column - 1, row - 1, v)
|
||||
|
||||
operator fun set(column: Int, v: Float3) {
|
||||
this[column].xyz = v
|
||||
}
|
||||
operator fun set(column: Int, row: Int, v: Float) {
|
||||
this[column][row] = v
|
||||
}
|
||||
|
||||
operator fun unaryMinus() = Mat3(-x, -y, -z)
|
||||
operator fun inc(): Mat3 {
|
||||
x++
|
||||
y++
|
||||
z++
|
||||
return this
|
||||
}
|
||||
operator fun dec(): Mat3 {
|
||||
x--
|
||||
y--
|
||||
z--
|
||||
return this
|
||||
}
|
||||
|
||||
operator fun plus(v: Float) = Mat3(x + v, y + v, z + v)
|
||||
operator fun minus(v: Float) = Mat3(x - v, y - v, z - v)
|
||||
operator fun times(v: Float) = Mat3(x * v, y * v, z * v)
|
||||
operator fun div(v: Float) = Mat3(x / v, y / v, z / v)
|
||||
|
||||
operator fun times(m: Mat3): Mat3 {
|
||||
val t = transpose(this)
|
||||
return Mat3(
|
||||
Float3(dot(t.x, m.x), dot(t.y, m.x), dot(t.z, m.x)),
|
||||
Float3(dot(t.x, m.y), dot(t.y, m.y), dot(t.z, m.y)),
|
||||
Float3(dot(t.x, m.z), dot(t.y, m.z), dot(t.z, m.z))
|
||||
)
|
||||
}
|
||||
|
||||
operator fun times(v: Float3): Float3 {
|
||||
val t = transpose(this)
|
||||
return Float3(dot(t.x, v), dot(t.y, v), dot(t.z, v))
|
||||
}
|
||||
|
||||
fun toFloatArray() = floatArrayOf(
|
||||
x.x, y.x, z.x,
|
||||
x.y, y.y, z.y,
|
||||
x.z, y.z, z.z
|
||||
)
|
||||
|
||||
override fun toString(): String {
|
||||
return """
|
||||
|${x.x} ${y.x} ${z.x}|
|
||||
|${x.y} ${y.y} ${z.y}|
|
||||
|${x.z} ${y.z} ${z.z}|
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
|
||||
data class Mat4(
|
||||
var x: Float4 = Float4(x = 1.0f),
|
||||
var y: Float4 = Float4(y = 1.0f),
|
||||
var z: Float4 = Float4(z = 1.0f),
|
||||
var w: Float4 = Float4(w = 1.0f)) {
|
||||
constructor(right: Float3, up: Float3, forward: Float3, position: Float3 = Float3()) :
|
||||
this(Float4(right), Float4(up), Float4(forward), Float4(position, 1.0f))
|
||||
constructor(m: Mat4) : this(m.x.copy(), m.y.copy(), m.z.copy(), m.w.copy())
|
||||
|
||||
companion object {
|
||||
fun of(vararg a: Float): Mat4 {
|
||||
require(a.size >= 16)
|
||||
return Mat4(
|
||||
Float4(a[0], a[4], a[8], a[12]),
|
||||
Float4(a[1], a[5], a[9], a[13]),
|
||||
Float4(a[2], a[6], a[10], a[14]),
|
||||
Float4(a[3], a[7], a[11], a[15])
|
||||
)
|
||||
}
|
||||
|
||||
fun identity() = Mat4()
|
||||
}
|
||||
|
||||
inline var right: Float3
|
||||
get() = x.xyz
|
||||
set(value) {
|
||||
x.xyz = value
|
||||
}
|
||||
inline var up: Float3
|
||||
get() = y.xyz
|
||||
set(value) {
|
||||
y.xyz = value
|
||||
}
|
||||
inline var forward: Float3
|
||||
get() = z.xyz
|
||||
set(value) {
|
||||
z.xyz = value
|
||||
}
|
||||
inline var position: Float3
|
||||
get() = w.xyz
|
||||
set(value) {
|
||||
w.xyz = value
|
||||
}
|
||||
|
||||
inline val scale: Float3
|
||||
get() = Float3(length(x.xyz), length(y.xyz), length(z.xyz))
|
||||
inline val translation: Float3
|
||||
get() = w.xyz
|
||||
val rotation: Float3
|
||||
get() {
|
||||
val x = normalize(right)
|
||||
val y = normalize(up)
|
||||
val z = normalize(forward)
|
||||
|
||||
return when {
|
||||
z.y <= -1.0f -> Float3(degrees(-HALF_PI), 0.0f, degrees(atan2( x.z, y.z)))
|
||||
z.y >= 1.0f -> Float3(degrees( HALF_PI), 0.0f, degrees(atan2(-x.z, -y.z)))
|
||||
else -> Float3(
|
||||
degrees(-asin(z.y)), degrees(-atan2(z.x, z.z)), degrees(atan2( x.y, y.y)))
|
||||
}
|
||||
}
|
||||
|
||||
inline val upperLeft: Mat3
|
||||
get() = Mat3(x.xyz, y.xyz, z.xyz)
|
||||
|
||||
operator fun get(column: Int) = when(column) {
|
||||
0 -> x
|
||||
1 -> y
|
||||
2 -> z
|
||||
3 -> w
|
||||
else -> throw IllegalArgumentException("column must be in 0..3")
|
||||
}
|
||||
operator fun get(column: Int, row: Int) = get(column)[row]
|
||||
|
||||
operator fun get(column: MatrixColumn) = when(column) {
|
||||
MatrixColumn.X -> x
|
||||
MatrixColumn.Y -> y
|
||||
MatrixColumn.Z -> z
|
||||
MatrixColumn.W -> w
|
||||
}
|
||||
operator fun get(column: MatrixColumn, row: Int) = get(column)[row]
|
||||
|
||||
operator fun invoke(row: Int, column: Int) = get(column - 1)[row - 1]
|
||||
operator fun invoke(row: Int, column: Int, v: Float) = set(column - 1, row - 1, v)
|
||||
|
||||
operator fun set(column: Int, v: Float4) {
|
||||
this[column].xyzw = v
|
||||
}
|
||||
operator fun set(column: Int, row: Int, v: Float) {
|
||||
this[column][row] = v
|
||||
}
|
||||
|
||||
operator fun unaryMinus() = Mat4(-x, -y, -z, -w)
|
||||
operator fun inc(): Mat4 {
|
||||
x++
|
||||
y++
|
||||
z++
|
||||
w++
|
||||
return this
|
||||
}
|
||||
operator fun dec(): Mat4 {
|
||||
x--
|
||||
y--
|
||||
z--
|
||||
w--
|
||||
return this
|
||||
}
|
||||
|
||||
operator fun plus(v: Float) = Mat4(x + v, y + v, z + v, w + v)
|
||||
operator fun minus(v: Float) = Mat4(x - v, y - v, z - v, w - v)
|
||||
operator fun times(v: Float) = Mat4(x * v, y * v, z * v, w * v)
|
||||
operator fun div(v: Float) = Mat4(x / v, y / v, z / v, w / v)
|
||||
|
||||
operator fun times(m: Mat4): Mat4 {
|
||||
val t = transpose(this)
|
||||
return Mat4(
|
||||
Float4(dot(t.x, m.x), dot(t.y, m.x), dot(t.z, m.x), dot(t.w, m.x)),
|
||||
Float4(dot(t.x, m.y), dot(t.y, m.y), dot(t.z, m.y), dot(t.w, m.y)),
|
||||
Float4(dot(t.x, m.z), dot(t.y, m.z), dot(t.z, m.z), dot(t.w, m.z)),
|
||||
Float4(dot(t.x, m.w), dot(t.y, m.w), dot(t.z, m.w), dot(t.w, m.w))
|
||||
)
|
||||
}
|
||||
|
||||
operator fun times(v: Float4): Float4 {
|
||||
val t = transpose(this)
|
||||
return Float4(dot(t.x, v), dot(t.y, v), dot(t.z, v), dot(t.w, v))
|
||||
}
|
||||
|
||||
fun toFloatArray() = floatArrayOf(
|
||||
x.x, y.x, z.x, w.x,
|
||||
x.y, y.y, z.y, w.y,
|
||||
x.z, y.z, z.z, w.z,
|
||||
x.w, y.w, z.w, w.w
|
||||
)
|
||||
|
||||
override fun toString(): String {
|
||||
return """
|
||||
|${x.x} ${y.x} ${z.x} ${w.x}|
|
||||
|${x.y} ${y.y} ${z.y} ${w.y}|
|
||||
|${x.z} ${y.z} ${z.z} ${w.z}|
|
||||
|${x.w} ${y.w} ${z.w} ${w.w}|
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
|
||||
fun transpose(m: Mat2) = Mat2(
|
||||
Float2(m.x.x, m.y.x),
|
||||
Float2(m.x.y, m.y.y)
|
||||
)
|
||||
|
||||
fun transpose(m: Mat3) = Mat3(
|
||||
Float3(m.x.x, m.y.x, m.z.x),
|
||||
Float3(m.x.y, m.y.y, m.z.y),
|
||||
Float3(m.x.z, m.y.z, m.z.z)
|
||||
)
|
||||
fun inverse(m: Mat3): Mat3 {
|
||||
val a = m.x.x
|
||||
val b = m.x.y
|
||||
val c = m.x.z
|
||||
val d = m.y.x
|
||||
val e = m.y.y
|
||||
val f = m.y.z
|
||||
val g = m.z.x
|
||||
val h = m.z.y
|
||||
val i = m.z.z
|
||||
|
||||
val A = e * i - f * h
|
||||
val B = f * g - d * i
|
||||
val C = d * h - e * g
|
||||
|
||||
val det = a * A + b * B + c * C
|
||||
|
||||
return Mat3.of(
|
||||
A / det, B / det, C / det,
|
||||
(c * h - b * i) / det, (a * i - c * g) / det, (b * g - a * h) / det,
|
||||
(b * f - c * e) / det, (c * d - a * f) / det, (a * e - b * d) / det
|
||||
)
|
||||
}
|
||||
|
||||
fun transpose(m: Mat4) = Mat4(
|
||||
Float4(m.x.x, m.y.x, m.z.x, m.w.x),
|
||||
Float4(m.x.y, m.y.y, m.z.y, m.w.y),
|
||||
Float4(m.x.z, m.y.z, m.z.z, m.w.z),
|
||||
Float4(m.x.w, m.y.w, m.z.w, m.w.w)
|
||||
)
|
||||
fun inverse(m: Mat4): Mat4 {
|
||||
val result = Mat4()
|
||||
|
||||
var pair0 = m.z.z * m.w.w
|
||||
var pair1 = m.w.z * m.z.w
|
||||
var pair2 = m.y.z * m.w.w
|
||||
var pair3 = m.w.z * m.y.w
|
||||
var pair4 = m.y.z * m.z.w
|
||||
var pair5 = m.z.z * m.y.w
|
||||
var pair6 = m.x.z * m.w.w
|
||||
var pair7 = m.w.z * m.x.w
|
||||
var pair8 = m.x.z * m.z.w
|
||||
var pair9 = m.z.z * m.x.w
|
||||
var pair10 = m.x.z * m.y.w
|
||||
var pair11 = m.y.z * m.x.w
|
||||
|
||||
result.x.x = pair0 * m.y.y + pair3 * m.z.y + pair4 * m.w.y
|
||||
result.x.x -= pair1 * m.y.y + pair2 * m.z.y + pair5 * m.w.y
|
||||
result.x.y = pair1 * m.x.y + pair6 * m.z.y + pair9 * m.w.y
|
||||
result.x.y -= pair0 * m.x.y + pair7 * m.z.y + pair8 * m.w.y
|
||||
result.x.z = pair2 * m.x.y + pair7 * m.y.y + pair10 * m.w.y
|
||||
result.x.z -= pair3 * m.x.y + pair6 * m.y.y + pair11 * m.w.y
|
||||
result.x.w = pair5 * m.x.y + pair8 * m.y.y + pair11 * m.z.y
|
||||
result.x.w -= pair4 * m.x.y + pair9 * m.y.y + pair10 * m.z.y
|
||||
result.y.x = pair1 * m.y.x + pair2 * m.z.x + pair5 * m.w.x
|
||||
result.y.x -= pair0 * m.y.x + pair3 * m.z.x + pair4 * m.w.x
|
||||
result.y.y = pair0 * m.x.x + pair7 * m.z.x + pair8 * m.w.x
|
||||
result.y.y -= pair1 * m.x.x + pair6 * m.z.x + pair9 * m.w.x
|
||||
result.y.z = pair3 * m.x.x + pair6 * m.y.x + pair11 * m.w.x
|
||||
result.y.z -= pair2 * m.x.x + pair7 * m.y.x + pair10 * m.w.x
|
||||
result.y.w = pair4 * m.x.x + pair9 * m.y.x + pair10 * m.z.x
|
||||
result.y.w -= pair5 * m.x.x + pair8 * m.y.x + pair11 * m.z.x
|
||||
|
||||
pair0 = m.z.x * m.w.y
|
||||
pair1 = m.w.x * m.z.y
|
||||
pair2 = m.y.x * m.w.y
|
||||
pair3 = m.w.x * m.y.y
|
||||
pair4 = m.y.x * m.z.y
|
||||
pair5 = m.z.x * m.y.y
|
||||
pair6 = m.x.x * m.w.y
|
||||
pair7 = m.w.x * m.x.y
|
||||
pair8 = m.x.x * m.z.y
|
||||
pair9 = m.z.x * m.x.y
|
||||
pair10 = m.x.x * m.y.y
|
||||
pair11 = m.y.x * m.x.y
|
||||
|
||||
result.z.x = pair0 * m.y.w + pair3 * m.z.w + pair4 * m.w.w
|
||||
result.z.x -= pair1 * m.y.w + pair2 * m.z.w + pair5 * m.w.w
|
||||
result.z.y = pair1 * m.x.w + pair6 * m.z.w + pair9 * m.w.w
|
||||
result.z.y -= pair0 * m.x.w + pair7 * m.z.w + pair8 * m.w.w
|
||||
result.z.z = pair2 * m.x.w + pair7 * m.y.w + pair10 * m.w.w
|
||||
result.z.z -= pair3 * m.x.w + pair6 * m.y.w + pair11 * m.w.w
|
||||
result.z.w = pair5 * m.x.w + pair8 * m.y.w + pair11 * m.z.w
|
||||
result.z.w -= pair4 * m.x.w + pair9 * m.y.w + pair10 * m.z.w
|
||||
result.w.x = pair2 * m.z.z + pair5 * m.w.z + pair1 * m.y.z
|
||||
result.w.x -= pair4 * m.w.z + pair0 * m.y.z + pair3 * m.z.z
|
||||
result.w.y = pair8 * m.w.z + pair0 * m.x.z + pair7 * m.z.z
|
||||
result.w.y -= pair6 * m.z.z + pair9 * m.w.z + pair1 * m.x.z
|
||||
result.w.z = pair6 * m.y.z + pair11 * m.w.z + pair3 * m.x.z
|
||||
result.w.z -= pair10 * m.w.z + pair2 * m.x.z + pair7 * m.y.z
|
||||
result.w.w = pair10 * m.z.z + pair4 * m.x.z + pair9 * m.y.z
|
||||
result.w.w -= pair8 * m.y.z + pair11 * m.z.z + pair5 * m.x.z
|
||||
|
||||
val determinant = m.x.x * result.x.x + m.y.x * result.x.y + m.z.x * result.x.z + m.w.x * result.x.w
|
||||
|
||||
return result / determinant
|
||||
}
|
||||
|
||||
fun scale(s: Float3) = Mat4(Float4(x = s.x), Float4(y = s.y), Float4(z = s.z))
|
||||
fun scale(m: Mat4) = scale(m.scale)
|
||||
|
||||
fun translation(t: Float3) = Mat4(w = Float4(t, 1.0f))
|
||||
fun translation(m: Mat4) = translation(m.translation)
|
||||
|
||||
fun rotation(m: Mat4) = Mat4(normalize(m.right), normalize(m.up), normalize(m.forward))
|
||||
fun rotation(d: Float3): Mat4 {
|
||||
val r = transform(d, ::radians)
|
||||
val c = transform(r, { x -> cos(x) })
|
||||
val s = transform(r, { x -> sin(x) })
|
||||
|
||||
return Mat4.of(
|
||||
c.y * c.z, -c.x * s.z + s.x * s.y * c.z, s.x * s.z + c.x * s.y * c.z, 0.0f,
|
||||
c.y * s.z, c.x * c.z + s.x * s.y * s.z, -s.x * c.z + c.x * s.y * s.z, 0.0f,
|
||||
-s.y , s.x * c.y , c.x * c.y , 0.0f,
|
||||
0.0f , 0.0f , 0.0f , 1.0f
|
||||
)
|
||||
}
|
||||
fun rotation(axis: Float3, angle: Float): Mat4 {
|
||||
val x = axis.x
|
||||
val y = axis.y
|
||||
val z = axis.z
|
||||
|
||||
val r = radians(angle)
|
||||
val c = cos(r)
|
||||
val s = sin(r)
|
||||
val d = 1.0f - c
|
||||
|
||||
return Mat4.of(
|
||||
x * x * d + c , x * y * d - z * s, x * z * d + y * s, 0.0f,
|
||||
y * x * d + z * s, y * y * d + c , y * z * d - x * s, 0.0f,
|
||||
z * x * d - y * s, z * y * d + x * s, z * z * d + c , 0.0f,
|
||||
0.0f , 0.0f , 0.0f , 1.0f
|
||||
)
|
||||
}
|
||||
|
||||
fun normal(m: Mat4) = scale(1.0f / Float3(length2(m.right), length2(m.up), length2(m.forward))) * m
|
||||
|
||||
fun lookAt(eye: Float3, target: Float3, up: Float3 = Float3(z = 1.0f)): Mat4 {
|
||||
return lookTowards(eye, target - eye, up)
|
||||
}
|
||||
|
||||
fun lookTowards(eye: Float3, forward: Float3, up: Float3 = Float3(z = 1.0f)): Mat4 {
|
||||
val f = normalize(forward)
|
||||
val r = normalize(f x up)
|
||||
val u = normalize(r x f)
|
||||
return Mat4(Float4(r), Float4(u), Float4(f), Float4(eye, 1.0f))
|
||||
}
|
||||
|
||||
fun perspective(fov: Float, ratio: Float, near: Float, far: Float): Mat4 {
|
||||
val t = 1.0f / tan(radians(fov) * 0.5f)
|
||||
val a = (far + near) / (far - near)
|
||||
val b = (2.0f * far * near) / (far - near)
|
||||
val c = t / ratio
|
||||
return Mat4(Float4(x = c), Float4(y = t), Float4(z = a, w = 1.0f), Float4(z = -b))
|
||||
}
|
||||
|
||||
fun ortho(l: Float, r: Float, b: Float, t: Float, n: Float, f: Float) = Mat4(
|
||||
Float4(x = 2.0f / (r - 1.0f)),
|
||||
Float4(y = 2.0f / (t - b)),
|
||||
Float4(z = -2.0f / (f - n)),
|
||||
Float4(-(r + l) / (r - l), -(t + b) / (t - b), -(f + n) / (f - n), 1.0f)
|
||||
)
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Romain Guy
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.filament.utils
|
||||
|
||||
data class Ray(var origin: Float3 = Float3(), var direction: Float3)
|
||||
|
||||
fun pointAt(r: Ray, t: Float) = r.origin + r.direction * t
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Romain Guy
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@file:Suppress("NOTHING_TO_INLINE")
|
||||
|
||||
package com.google.android.filament.utils
|
||||
|
||||
const val FPI = 3.1415926536f
|
||||
const val HALF_PI = FPI * 0.5f
|
||||
const val TWO_PI = FPI * 2.0f
|
||||
const val FOUR_PI = FPI * 4.0f
|
||||
const val INV_PI = 1.0f / FPI
|
||||
const val INV_TWO_PI = INV_PI * 0.5f
|
||||
const val INV_FOUR_PI = INV_PI * 0.25f
|
||||
|
||||
inline fun clamp(x: Float, min: Float, max: Float)= if (x < min) min else (if (x > max) max else x)
|
||||
|
||||
inline fun saturate(x: Float) = clamp(x, 0.0f, 1.0f)
|
||||
|
||||
inline fun mix(a: Float, b: Float, x: Float) = a * (1.0f - x) + b * x
|
||||
|
||||
inline fun degrees(v: Float) = v * (180.0f * INV_PI)
|
||||
|
||||
inline fun radians(v: Float) = v * (FPI / 180.0f)
|
||||
|
||||
inline fun fract(v: Float) = v % 1
|
||||
|
||||
inline fun sqr(v: Float) = v * v
|
||||
|
||||
inline fun pow(x: Float, y: Float) = StrictMath.pow(x.toDouble(), y.toDouble()).toFloat()
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.filament.utils;
|
||||
|
||||
public class Utils {
|
||||
|
||||
/**
|
||||
* Initializes the utils JNI layer. Must be called before using any utils functionality.
|
||||
*/
|
||||
public static void init() {
|
||||
System.loadLibrary("filament-utils-jni");
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,10 +21,6 @@ add_library(filaflat STATIC IMPORTED)
|
||||
set_target_properties(filaflat PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilaflat.a)
|
||||
|
||||
add_library(image STATIC IMPORTED)
|
||||
set_target_properties(image PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libimage.a)
|
||||
|
||||
add_library(ibl STATIC IMPORTED)
|
||||
set_target_properties(ibl PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libibl.a)
|
||||
@@ -61,7 +57,6 @@ add_library(gltfio-jni-obj OBJECT
|
||||
src/main/cpp/Animator.cpp
|
||||
src/main/cpp/AssetLoader.cpp
|
||||
src/main/cpp/FilamentAsset.cpp
|
||||
src/main/cpp/KtxLoader.cpp
|
||||
src/main/cpp/MaterialProvider.cpp
|
||||
src/main/cpp/ResourceLoader.cpp)
|
||||
|
||||
@@ -91,7 +86,6 @@ if (NOT DISABLE_GLTFIO_JNI)
|
||||
filaflat
|
||||
filabridge
|
||||
geometry
|
||||
image
|
||||
ibl
|
||||
utils
|
||||
log
|
||||
|
||||
@@ -42,4 +42,5 @@ dependencies {
|
||||
implementation deps.kotlin
|
||||
implementation project(':filament-android')
|
||||
implementation project(':gltfio-android')
|
||||
implementation project(':filament-utils-android')
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.view.animation.LinearInterpolator
|
||||
import com.google.android.filament.*
|
||||
import com.google.android.filament.android.UiHelper
|
||||
import com.google.android.filament.gltfio.*
|
||||
import com.google.android.filament.utils.*
|
||||
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
@@ -46,7 +47,7 @@ class MainActivity : Activity() {
|
||||
|
||||
companion object {
|
||||
init {
|
||||
Gltfio.init()
|
||||
Utils.init()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
include ':filament-android'
|
||||
include ':filamat-android'
|
||||
include ':gltfio-android'
|
||||
include ':filament-utils-android'
|
||||
|
||||
// Samples
|
||||
include ':samples:sample-gltf-bloom'
|
||||
|
||||
14
build.sh
14
build.sh
@@ -129,6 +129,8 @@ function build_clean {
|
||||
rm -Rf android/filamat-android/build android/filamat-android/.cxx
|
||||
rm -Rf android/gltfio-android/build android/gltfio-android/.externalNativeBuild
|
||||
rm -Rf android/gltfio-android/build android/gltfio-android/.cxx
|
||||
rm -Rf android/filament-utils-android/build android/filament-utils-android/.externalNativeBuild
|
||||
rm -Rf android/filament-utils-android/build android/filament-utils-android/.cxx
|
||||
}
|
||||
|
||||
function build_desktop_target {
|
||||
@@ -373,7 +375,8 @@ function build_android {
|
||||
-Pfilament_dist_dir=../out/android-debug/filament \
|
||||
-Pextra_cmake_args=${VULKAN_ANDROID_OPTION} \
|
||||
:filament-android:assembleDebug \
|
||||
:gltfio-android:assembleDebug
|
||||
:gltfio-android:assembleDebug \
|
||||
:filament-utils-android:assembleDebug
|
||||
|
||||
./gradlew \
|
||||
-Pfilament_dist_dir=../out/android-debug/filament \
|
||||
@@ -389,6 +392,9 @@ function build_android {
|
||||
|
||||
echo "Installing out/gltfio-android-debug.aar..."
|
||||
cp gltfio-android/build/outputs/aar/gltfio-android-debug.aar ../out/
|
||||
|
||||
echo "Installing out/filament-utils-android-debug.aar..."
|
||||
cp filament-utils-android/build/outputs/aar/filament-utils-android-debug.aar ../out/
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -396,7 +402,8 @@ function build_android {
|
||||
./gradlew \
|
||||
-Pfilament_dist_dir=../out/android-release/filament \
|
||||
:filament-android:assembleRelease \
|
||||
:gltfio-android:assembleRelease
|
||||
:gltfio-android:assembleRelease \
|
||||
:filament-utils-android:assembleRelease
|
||||
|
||||
./gradlew \
|
||||
-Pfilament_dist_dir=../out/android-release/filament \
|
||||
@@ -412,6 +419,9 @@ function build_android {
|
||||
|
||||
echo "Installing out/gltfio-android-release.aar..."
|
||||
cp gltfio-android/build/outputs/aar/gltfio-android-release.aar ../out/
|
||||
|
||||
echo "Installing out/filament-utils-android-debug.aar..."
|
||||
cp filament-utils-android/build/outputs/aar/filament-utils-android-release.aar ../out/
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
Reference in New Issue
Block a user