Compare commits
99 Commits
sceneform-
...
v1.3.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
073a6c7696 | ||
|
|
b30f6e5332 | ||
|
|
384651e21a | ||
|
|
22dcdc770f | ||
|
|
fd4d6c0d44 | ||
|
|
ca5b52b2ce | ||
|
|
cc4e9db81b | ||
|
|
2bfea16459 | ||
|
|
927662ea4d | ||
|
|
5b2dc1d3de | ||
|
|
097feb0372 | ||
|
|
9cd2971b65 | ||
|
|
fb16516480 | ||
|
|
76027cab85 | ||
|
|
64c95c615a | ||
|
|
31745f6025 | ||
|
|
2a8f04c791 | ||
|
|
3fdecfdefa | ||
|
|
26cbef7452 | ||
|
|
571a9b1ff3 | ||
|
|
b84117eb92 | ||
|
|
6af0c72d0d | ||
|
|
12fde30f31 | ||
|
|
56c2d6338e | ||
|
|
10c8ff352d | ||
|
|
53ea1a00ec | ||
|
|
62a458099a | ||
|
|
826d52bca2 | ||
|
|
299a600377 | ||
|
|
a4ebf23baa | ||
|
|
d23a703ca5 | ||
|
|
2beb9c5588 | ||
|
|
a7fc4d8fbb | ||
|
|
a5dc89b071 | ||
|
|
2bfec9f4af | ||
|
|
1aa7fac8c2 | ||
|
|
c01107fd52 | ||
|
|
5b27361ef0 | ||
|
|
494ddc10e4 | ||
|
|
6151f78d28 | ||
|
|
46c67632c7 | ||
|
|
3f7cf2f971 | ||
|
|
84cc8ff9c8 | ||
|
|
921c2bcd61 | ||
|
|
6ea8ed07ed | ||
|
|
a5addd2257 | ||
|
|
8b1d4ee06a | ||
|
|
3e23d9742b | ||
|
|
847d7dd71a | ||
|
|
10dc3a24e8 | ||
|
|
c6c1cfef3c | ||
|
|
cc8a2f736b | ||
|
|
7fcd3e1a4f | ||
|
|
481fe5a087 | ||
|
|
2d690ac585 | ||
|
|
a118299cfb | ||
|
|
bc01475920 | ||
|
|
56e9d8eda5 | ||
|
|
902e7021fd | ||
|
|
1773c42398 | ||
|
|
ae88536f0c | ||
|
|
b4d6583901 | ||
|
|
b31e420064 | ||
|
|
e4e439e2bf | ||
|
|
a79a83d6da | ||
|
|
50d4dc6499 | ||
|
|
cbc662085e | ||
|
|
02a5541fed | ||
|
|
14248621fe | ||
|
|
8c299d7b0b | ||
|
|
57d6bdff1b | ||
|
|
957ec9be60 | ||
|
|
76147a7231 | ||
|
|
eff3d1a09b | ||
|
|
5f6d7a279c | ||
|
|
9bce361b3e | ||
|
|
925e414e7b | ||
|
|
aeec6f2df5 | ||
|
|
9358650bd4 | ||
|
|
54d44a76a7 | ||
|
|
cc22183f20 | ||
|
|
2ded1c955f | ||
|
|
d955e733bf | ||
|
|
99a501f0c3 | ||
|
|
cdb2b47e0f | ||
|
|
366e20cbe8 | ||
|
|
d5179bd9ed | ||
|
|
12506784da | ||
|
|
4fee4d8da2 | ||
|
|
b1242163f7 | ||
|
|
8cd44fb2e8 | ||
|
|
33a8c9da7e | ||
|
|
37facf7f7b | ||
|
|
1d20973363 | ||
|
|
0cb08cd114 | ||
|
|
c97ba45eed | ||
|
|
74fcc456dc | ||
|
|
b17d606ed2 | ||
|
|
3e97ac5268 |
@@ -1,7 +1,7 @@
|
||||
# ==================================================================================================
|
||||
# CMake
|
||||
# ==================================================================================================
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
# ==================================================================================================
|
||||
# Project declaration
|
||||
@@ -18,6 +18,8 @@ option(USE_EXTERNAL_GLES3 "Experimental: Compile Filament against OpenGL ES 3" O
|
||||
|
||||
option(GENERATE_JS_DOCS "Build WebGL documentation and tutorials" OFF)
|
||||
|
||||
option(ENABLE_LTO "Enable link-time optimizations if supported by the compiler" OFF)
|
||||
|
||||
# ==================================================================================================
|
||||
# OS specific
|
||||
# ==================================================================================================
|
||||
@@ -25,6 +27,10 @@ if (UNIX AND NOT APPLE AND NOT ANDROID AND NOT WEBGL)
|
||||
set(LINUX TRUE)
|
||||
endif()
|
||||
|
||||
if (ANDROID OR WEBGL OR IOS)
|
||||
set(IS_MOBILE_TARGET TRUE)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
# Link statically against c/c++ lib to avoid missing redistriburable such as
|
||||
# "VCRUNTIME140.dll not found. Try reinstalling the app.", but give users
|
||||
@@ -101,7 +107,7 @@ set(TOOLS ${CMAKE_CURRENT_SOURCE_DIR}/tools)
|
||||
# ==================================================================================================
|
||||
# Compiler check
|
||||
# ==================================================================================================
|
||||
set(MIN_CLANG_VERSION "5.0")
|
||||
set(MIN_CLANG_VERSION "6.0")
|
||||
|
||||
if (CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
if (CMAKE_C_COMPILER_VERSION VERSION_LESS MIN_CLANG_VERSION)
|
||||
@@ -124,6 +130,20 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND "${CMAKE_CXX_SIMULATE_ID}" S
|
||||
set(CLANG_CL true)
|
||||
endif()
|
||||
|
||||
# ==================================================================================================
|
||||
# Link time optimizations (LTO)
|
||||
# ==================================================================================================
|
||||
if (ENABLE_LTO)
|
||||
include(CheckIPOSupported)
|
||||
|
||||
check_ipo_supported(RESULT IPO_SUPPORT)
|
||||
|
||||
if (IPO_SUPPORT)
|
||||
message(STATUS "LTO support is enabled")
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# ==================================================================================================
|
||||
# General compiler flags
|
||||
# ==================================================================================================
|
||||
@@ -260,6 +280,36 @@ else()
|
||||
option(FILAMENT_BUILD_FILAMAT "Build filamat and JNI buildings" OFF)
|
||||
endif()
|
||||
|
||||
# ==================================================================================================
|
||||
# Material compilation flags
|
||||
# ==================================================================================================
|
||||
|
||||
# Target system.
|
||||
if (IS_MOBILE_TARGET)
|
||||
set(MATC_TARGET mobile)
|
||||
else()
|
||||
set(MATC_TARGET desktop)
|
||||
endif()
|
||||
|
||||
set(MATC_API_FLAGS )
|
||||
|
||||
# TODO: Add a flag to build Filament without support for OpenGL.
|
||||
set(MATC_API_FLAGS ${MATC_API_FLAGS} -a opengl)
|
||||
|
||||
if (FILAMENT_SUPPORTS_VULKAN)
|
||||
set(MATC_API_FLAGS ${MATC_API_FLAGS} -a vulkan)
|
||||
endif()
|
||||
if (FILAMENT_SUPPORTS_METAL)
|
||||
set(MATC_API_FLAGS ${MATC_API_FLAGS} -a metal)
|
||||
endif()
|
||||
|
||||
# Only optimize materials in Release mode (so error message lines match the source code)
|
||||
if (NOT CMAKE_BUILD_TYPE MATCHES Release)
|
||||
set(MATC_OPT_FLAGS -g)
|
||||
endif()
|
||||
|
||||
set(MATC_BASE_FLAGS ${MATC_API_FLAGS} -p ${MATC_TARGET} ${MATC_OPT_FLAGS})
|
||||
|
||||
# ==================================================================================================
|
||||
# Distribution
|
||||
# ==================================================================================================
|
||||
|
||||
23
README.md
@@ -43,13 +43,23 @@ Here are a few sample materials rendered with Filament:
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
## Applications
|
||||
|
||||
Here are a few screenshots of applications that use Filament in production:
|
||||
|
||||
### Google Maps AR Navigation
|
||||
|
||||

|
||||
|
||||
### Google Search 3D/AR Viewer on Android
|
||||
|
||||

|
||||
|
||||
## Features
|
||||
|
||||
### APIs
|
||||
@@ -86,7 +96,7 @@ Here are a few sample materials rendered with Filament:
|
||||
- ACES-like tone-mapping
|
||||
- Temporal dithering
|
||||
- FXAA, MSAA and specular anti-aliasing
|
||||
- Dynamic resolution (on Android)
|
||||
- Dynamic resolution (on Android and iOS)
|
||||
|
||||
### Future
|
||||
|
||||
@@ -706,8 +716,9 @@ filamesh ./assets/models/monkey/monkey.obj monkey.filamesh
|
||||
```
|
||||
|
||||
Most samples accept an IBL that must be generated using the `cmgen` tool (`./tools/filamesh/cmgen`
|
||||
in your build directory). These sample apps expect a path to a directory containing the RGBM files
|
||||
for the IBL. To generate an IBL simply use this command:
|
||||
in your build directory). These sample apps expect a path to a directory containing the '.rgb32f'
|
||||
files for the IBL (which are PNGs containing `R11F_G11F_B10F` data). To generate an IBL simply use
|
||||
this command:
|
||||
|
||||
```
|
||||
cmgen -x ./ibls/ my_ibl.exr
|
||||
@@ -723,7 +734,7 @@ pre-filtered environment map (one file per cubemap face and per mip level), the
|
||||
texture for the skybox and a text file containing the spherical harmonics for indirect diffuse
|
||||
lighting.
|
||||
|
||||
If you prefer a blurred background, run `cmgen` with this flag: `--extract-blur=0.5`. The numerical
|
||||
If you prefer a blurred background, run `cmgen` with this flag: `--extract-blur=0.1`. The numerical
|
||||
value is the desired roughness between 0 and 1.
|
||||
|
||||
## Rendering with Filament
|
||||
|
||||
@@ -3,9 +3,24 @@
|
||||
This file contains one line summaries of commits that are worthy of mentioning in release notes.
|
||||
A new header is inserted each time a *tag* is created.
|
||||
|
||||
- Added Java / Kotlin bindings for KtxLoader.
|
||||
- Added JavaScript / Typescript bindings for the new `RenderTarget` class.
|
||||
|
||||
# Release notes
|
||||
## sceneform-1.9pr4
|
||||
|
||||
- Added `gltf_bloom` Android sample to show gltfio and the `RenderTarget` API.
|
||||
- Added `getMaterialInstanceAt` to the Java version of RenderableManager.
|
||||
- Fix JNI bindings for setting values in parameter arrays.
|
||||
- Added JNI bindings for the gltfio library.
|
||||
- Fix support for parameter arrays in `.mat` files.
|
||||
- Added support for `RGB_11_11_10`
|
||||
- Removed support for `RGBM` (**warning:** source compatibility breakage)
|
||||
- IBL cubemap can now be of any size
|
||||
- `Texture::generatePrefilterMipmap` can be used for runtime generation of a reflection cubemap
|
||||
|
||||
## sceneform-1.9pr3
|
||||
|
||||
- Added `Scene.addEntities()` to the Java / Kotlin bindings.
|
||||
- Improved robustness in the tangents utility for meshes that have tangents *and* normals.
|
||||
- Introduced `RenderTarget` API that allows View to reference an offscreen render target.
|
||||
- Added `lucy_bloom` sample to demonstrate the new `RenderTarget` API.
|
||||
|
||||
@@ -33,6 +33,7 @@ List<File> getBinaries(String name, File toolsPath) {
|
||||
ext.matcFullPath = getBinaries('matc', filamentToolsPath)
|
||||
ext.cmgenFullPath = getBinaries('cmgen', filamentToolsPath)
|
||||
ext.filameshFullPath = getBinaries('filamesh', filamentToolsPath)
|
||||
ext.resgenFullPath = getBinaries('resgen', filamentToolsPath)
|
||||
|
||||
class LogOutputStream extends ByteArrayOutputStream {
|
||||
private final Logger logger;
|
||||
@@ -156,7 +157,7 @@ class IblGenerator extends DefaultTask {
|
||||
standardOutput out
|
||||
errorOutput err
|
||||
executable "${cmgenPath}"
|
||||
args('--format=rgbm', '--extract-blur=0.08', "--extract=${outputDir.absolutePath}", file)
|
||||
args('--format=rgb32f', '--extract-blur=0.08', "--extract=${outputDir.absolutePath}", file)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
cmake_minimum_required(VERSION 3.6)
|
||||
|
||||
set(FILAMENT_DIR ${FILAMENT_DIST_DIR})
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.4.0'
|
||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -144,9 +144,16 @@ public class MaterialBuilder {
|
||||
}
|
||||
|
||||
public enum TargetApi {
|
||||
ALL,
|
||||
OPENGL,
|
||||
VULKAN,
|
||||
OPENGL (0x1),
|
||||
VULKAN (0x2),
|
||||
METAL (0x4),
|
||||
ALL (0x7);
|
||||
|
||||
final int number;
|
||||
|
||||
private TargetApi(int number) {
|
||||
this.number = number;
|
||||
}
|
||||
}
|
||||
|
||||
public enum Optimization {
|
||||
@@ -347,7 +354,7 @@ public class MaterialBuilder {
|
||||
|
||||
@NonNull
|
||||
public MaterialBuilder targetApi(@NonNull TargetApi api) {
|
||||
nMaterialBuilderTargetApi(mNativeObject, api.ordinal());
|
||||
nMaterialBuilderTargetApi(mNativeObject, api.number);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Google Configuration Checker Style" />
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
</state>
|
||||
</component>
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
cmake_minimum_required(VERSION 3.6)
|
||||
|
||||
set(FILAMENT_DIR ${FILAMENT_DIST_DIR})
|
||||
|
||||
@@ -14,6 +14,10 @@ add_library(utils STATIC IMPORTED)
|
||||
set_target_properties(utils PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libutils.a)
|
||||
|
||||
add_library(ibl STATIC IMPORTED)
|
||||
set_target_properties(ibl PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libibl.a)
|
||||
|
||||
add_library(filaflat STATIC IMPORTED)
|
||||
set_target_properties(filaflat PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilaflat.a)
|
||||
@@ -86,6 +90,7 @@ target_link_libraries(filament-jni
|
||||
filaflat
|
||||
filabridge
|
||||
geometry
|
||||
ibl
|
||||
utils
|
||||
log
|
||||
GLESv3
|
||||
|
||||
@@ -13,7 +13,7 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.4.0'
|
||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
#include <jni.h>
|
||||
|
||||
#include <filament/IndirectLight.h>
|
||||
#include <filament/Texture.h>
|
||||
#include <common/NioUtils.h>
|
||||
#include <common/CallbackUtils.h>
|
||||
|
||||
using namespace filament;
|
||||
|
||||
@@ -89,8 +92,6 @@ Java_com_google_android_filament_IndirectLight_nRotation(JNIEnv *, jclass, jlong
|
||||
builder->rotation(filament::math::mat3f{v0, v1, v2, v3, v4, v5, v6, v7, v8});
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_IndirectLight_nSetIntensity(JNIEnv*, jclass,
|
||||
jlong nativeIndirectLight, jfloat intensity) {
|
||||
@@ -106,9 +107,19 @@ Java_com_google_android_filament_IndirectLight_nGetIntensity(JNIEnv*, jclass,
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_IndirectLight_nSetRotation(JNIEnv *env, jclass type,
|
||||
jlong nativeIndirectLight, jfloat v0, jfloat v1, jfloat v2, jfloat v3, jfloat v4, jfloat v5,
|
||||
jfloat v6, jfloat v7, jfloat v8) {
|
||||
Java_com_google_android_filament_IndirectLight_nSetRotation(JNIEnv*, jclass,
|
||||
jlong nativeIndirectLight, jfloat v0, jfloat v1, jfloat v2,
|
||||
jfloat v3, jfloat v4, jfloat v5, jfloat v6, jfloat v7, jfloat v8) {
|
||||
IndirectLight *indirectLight = (IndirectLight *) nativeIndirectLight;
|
||||
indirectLight->setRotation(filament::math::mat3f{v0, v1, v2, v3, v4, v5, v6, v7, v8});
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_IndirectLight_nGetRotation(JNIEnv* env, jclass,
|
||||
jlong nativeIndirectLight, jfloatArray outRotation_) {
|
||||
IndirectLight *indirectLight = (IndirectLight *) nativeIndirectLight;
|
||||
jfloat *outRotation = env->GetFloatArrayElements(outRotation_, NULL);
|
||||
*reinterpret_cast<filament::math::mat3f*>(outRotation) = indirectLight->getRotation();
|
||||
env->ReleaseFloatArrayElements(outRotation_, outRotation, 0);
|
||||
|
||||
}
|
||||
|
||||
@@ -27,6 +27,30 @@
|
||||
#include <math/vec4.h>
|
||||
|
||||
using namespace filament;
|
||||
using namespace filament::math;
|
||||
|
||||
enum BooleanElement {
|
||||
BOOL,
|
||||
BOOL2,
|
||||
BOOL3,
|
||||
BOOL4
|
||||
};
|
||||
|
||||
enum IntElement {
|
||||
INT,
|
||||
INT2,
|
||||
INT3,
|
||||
INT4
|
||||
};
|
||||
|
||||
enum FloatElement {
|
||||
FLOAT,
|
||||
FLOAT2,
|
||||
FLOAT3,
|
||||
FLOAT4,
|
||||
MAT3,
|
||||
MAT4
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
static void setParameter(JNIEnv* env, jlong nativeMaterialInstance, jstring name_, T v) {
|
||||
@@ -47,14 +71,14 @@ extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetParameterBool2(JNIEnv *env, jclass,
|
||||
jlong nativeMaterialInstance, jstring name_, jboolean x, jboolean y) {
|
||||
setParameter(env, nativeMaterialInstance, name_, filament::math::bool2{x, y});
|
||||
setParameter(env, nativeMaterialInstance, name_, bool2{x, y});
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetParameterBool3(JNIEnv *env, jclass,
|
||||
jlong nativeMaterialInstance, jstring name_, jboolean x, jboolean y, jboolean z) {
|
||||
setParameter(env, nativeMaterialInstance, name_, filament::math::bool3{x, y, z});
|
||||
setParameter(env, nativeMaterialInstance, name_, bool3{x, y, z});
|
||||
}
|
||||
|
||||
extern "C"
|
||||
@@ -62,7 +86,7 @@ JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetParameterBool4(JNIEnv *env, jclass,
|
||||
jlong nativeMaterialInstance, jstring name_,
|
||||
jboolean x, jboolean y, jboolean z, jboolean w) {
|
||||
setParameter(env, nativeMaterialInstance, name_, filament::math::bool4{x, y, z, w});
|
||||
setParameter(env, nativeMaterialInstance, name_, bool4{x, y, z, w});
|
||||
}
|
||||
|
||||
extern "C"
|
||||
@@ -76,14 +100,14 @@ extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetParameterInt2(JNIEnv *env, jclass,
|
||||
jlong nativeMaterialInstance, jstring name_, jint x, jint y) {
|
||||
setParameter(env, nativeMaterialInstance, name_, filament::math::int2{x, y});
|
||||
setParameter(env, nativeMaterialInstance, name_, int2{x, y});
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetParameterInt3(JNIEnv *env, jclass,
|
||||
jlong nativeMaterialInstance, jstring name_, jint x, jint y, jint z) {
|
||||
setParameter(env, nativeMaterialInstance, name_, filament::math::int3{x, y, z});
|
||||
setParameter(env, nativeMaterialInstance, name_, int3{x, y, z});
|
||||
}
|
||||
|
||||
extern "C"
|
||||
@@ -91,7 +115,7 @@ JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetParameterInt4(JNIEnv *env, jclass,
|
||||
jlong nativeMaterialInstance, jstring name_,
|
||||
jint x, jint y, jint z, jint w) {
|
||||
setParameter(env, nativeMaterialInstance, name_, filament::math::int4{x, y, z, w});
|
||||
setParameter(env, nativeMaterialInstance, name_, int4{x, y, z, w});
|
||||
}
|
||||
|
||||
extern "C"
|
||||
@@ -105,14 +129,14 @@ extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetParameterFloat2(JNIEnv *env, jclass,
|
||||
jlong nativeMaterialInstance, jstring name_, jfloat x, jfloat y) {
|
||||
setParameter(env, nativeMaterialInstance, name_, filament::math::float2{x, y});
|
||||
setParameter(env, nativeMaterialInstance, name_, float2{x, y});
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetParameterFloat3(JNIEnv *env, jclass,
|
||||
jlong nativeMaterialInstance, jstring name_, jfloat x, jfloat y, jfloat z) {
|
||||
setParameter(env, nativeMaterialInstance, name_, filament::math::float3{x, y, z});
|
||||
setParameter(env, nativeMaterialInstance, name_, float3{x, y, z});
|
||||
}
|
||||
|
||||
extern "C"
|
||||
@@ -120,7 +144,7 @@ JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetParameterFloat4(JNIEnv *env, jclass,
|
||||
jlong nativeMaterialInstance, jstring name_,
|
||||
jfloat x, jfloat y, jfloat z, jfloat w) {
|
||||
setParameter(env, nativeMaterialInstance, name_, filament::math::float4{x, y, z, w});
|
||||
setParameter(env, nativeMaterialInstance, name_, float4{x, y, z, w});
|
||||
}
|
||||
|
||||
extern "C"
|
||||
@@ -131,9 +155,26 @@ Java_com_google_android_filament_MaterialInstance_nSetBooleanParameterArray(JNIE
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
|
||||
const char* name = env->GetStringUTFChars(name_, 0);
|
||||
size_t size = (size_t) element + 1;
|
||||
jboolean* v = env->GetBooleanArrayElements(v_, NULL);
|
||||
instance->setParameter(name, (bool*) (v + offset * size), (size_t) (count * size));
|
||||
|
||||
// NOTE: In C++, bool has an implementation-defined size. Here we assume
|
||||
// it has the same size as jboolean, which is 1 byte.
|
||||
|
||||
switch ((BooleanElement) element) {
|
||||
case BOOL:
|
||||
instance->setParameter(name, ((const bool*) v) + offset, count);
|
||||
break;
|
||||
case BOOL2:
|
||||
instance->setParameter(name, ((const bool2*) v) + offset, count);
|
||||
break;
|
||||
case BOOL3:
|
||||
instance->setParameter(name, ((const bool3*) v) + offset, count);
|
||||
break;
|
||||
case BOOL4:
|
||||
instance->setParameter(name, ((const bool4*) v) + offset, count);
|
||||
break;
|
||||
}
|
||||
|
||||
env->ReleaseBooleanArrayElements(v_, v, 0);
|
||||
|
||||
env->ReleaseStringUTFChars(name_, name);
|
||||
@@ -147,10 +188,23 @@ Java_com_google_android_filament_MaterialInstance_nSetIntParameterArray(JNIEnv *
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
|
||||
const char* name = env->GetStringUTFChars(name_, 0);
|
||||
size_t size = (size_t) element + 1;
|
||||
jint* v = env->GetIntArrayElements(v_, NULL);
|
||||
instance->setParameter(name, reinterpret_cast<int32_t*>(v + offset * size),
|
||||
(size_t) (count * size));
|
||||
|
||||
switch ((IntElement) element) {
|
||||
case INT:
|
||||
instance->setParameter(name, ((const int32_t*) v) + offset, count);
|
||||
break;
|
||||
case INT2:
|
||||
instance->setParameter(name, ((const int2*) v) + offset, count);
|
||||
break;
|
||||
case INT3:
|
||||
instance->setParameter(name, ((const int3*) v) + offset, count);
|
||||
break;
|
||||
case INT4:
|
||||
instance->setParameter(name, ((const int4*) v) + offset, count);
|
||||
break;
|
||||
}
|
||||
|
||||
env->ReleaseIntArrayElements(v_, v, 0);
|
||||
|
||||
env->ReleaseStringUTFChars(name_, name);
|
||||
@@ -164,16 +218,29 @@ Java_com_google_android_filament_MaterialInstance_nSetFloatParameterArray(JNIEnv
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
|
||||
const char* name = env->GetStringUTFChars(name_, 0);
|
||||
size_t size = (size_t) element + 1;
|
||||
if (size == 5) {
|
||||
// mat3
|
||||
size = 9;
|
||||
} else if (size == 6) {
|
||||
// mat4
|
||||
size = 16;
|
||||
}
|
||||
jfloat* v = env->GetFloatArrayElements(v_, NULL);
|
||||
instance->setParameter(name, v + offset * size, (size_t) (count * size));
|
||||
|
||||
switch ((FloatElement) element) {
|
||||
case FLOAT:
|
||||
instance->setParameter(name, ((const float*) v) + offset, count);
|
||||
break;
|
||||
case FLOAT2:
|
||||
instance->setParameter(name, ((const float2*) v) + offset, count);
|
||||
break;
|
||||
case FLOAT3:
|
||||
instance->setParameter(name, ((const float3*) v) + offset, count);
|
||||
break;
|
||||
case FLOAT4:
|
||||
instance->setParameter(name, ((const float4*) v) + offset, count);
|
||||
break;
|
||||
case MAT3:
|
||||
instance->setParameter(name, ((const mat3f*) v) + offset, count);
|
||||
break;
|
||||
case MAT4:
|
||||
instance->setParameter(name, ((const mat4f*) v) + offset, count);
|
||||
break;
|
||||
}
|
||||
|
||||
env->ReleaseFloatArrayElements(v_, v, 0);
|
||||
|
||||
env->ReleaseStringUTFChars(name_, name);
|
||||
|
||||
@@ -299,6 +299,21 @@ Java_com_google_android_filament_RenderableManager_nSetMaterialInstanceAt(JNIEnv
|
||||
materialInstance);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT long JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nGetMaterialInstanceAt(JNIEnv*, jclass,
|
||||
jlong nativeRenderableManager, jint i, jint primitiveIndex) {
|
||||
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
|
||||
return (long) rm->getMaterialInstanceAt((RenderableManager::Instance) i, (size_t) primitiveIndex);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT long JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nGetMaterialAt(JNIEnv*, jclass,
|
||||
jlong nativeRenderableManager, jint i, jint primitiveIndex) {
|
||||
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
|
||||
MaterialInstance *mi = rm->getMaterialInstanceAt((RenderableManager::Instance) i, (size_t) primitiveIndex);
|
||||
return (long) mi->getMaterial();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nSetGeometryAt__JIIIJJII(JNIEnv*,
|
||||
jclass, jlong nativeRenderableManager, jint i, jint primitiveIndex, jint primitiveType,
|
||||
|
||||
@@ -44,6 +44,15 @@ Java_com_google_android_filament_Scene_nAddEntity(JNIEnv *env, jclass type, jlon
|
||||
scene->addEntity((Entity&) entity);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_Scene_nAddEntities(JNIEnv *env, jclass type, jlong nativeScene,
|
||||
jintArray entities) {
|
||||
Scene* scene = (Scene*) nativeScene;
|
||||
Entity* nativeEntities = (Entity*) env->GetIntArrayElements(entities, nullptr);
|
||||
scene->addEntities(nativeEntities, env->GetArrayLength(entities));
|
||||
env->ReleaseIntArrayElements(entities, (jint*) nativeEntities, JNI_ABORT);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_Scene_nRemove(JNIEnv *env, jclass type, jlong nativeScene,
|
||||
jint entity) {
|
||||
|
||||
@@ -107,10 +107,10 @@ Java_com_google_android_filament_Texture_nBuilderFormat(JNIEnv*, jclass,
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_Texture_nBuilderRgbm(JNIEnv*, jclass,
|
||||
jlong nativeBuilder, jboolean enable) {
|
||||
Java_com_google_android_filament_Texture_nBuilderUsage(JNIEnv*, jclass,
|
||||
jlong nativeBuilder, jint flags) {
|
||||
Texture::Builder *builder = (Texture::Builder *) nativeBuilder;
|
||||
builder->rgbm(enable);
|
||||
builder->usage((Texture::Usage) flags);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
@@ -163,12 +163,6 @@ Java_com_google_android_filament_Texture_nGetInternalFormat(JNIEnv*, jclass,
|
||||
return (jint) texture->getFormat();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_Texture_nGetRgbm(JNIEnv*, jclass, jlong nativeTexture) {
|
||||
Texture *texture = (Texture *) nativeTexture;
|
||||
return static_cast<jboolean>(texture->isRgbm());
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_Texture_nSetImage(JNIEnv* env, jclass, jlong nativeTexture,
|
||||
jlong nativeEngine, jint level, jint xoffset, jint yoffset, jint width, jint height,
|
||||
@@ -335,6 +329,48 @@ Java_com_google_android_filament_Texture_nIsStreamValidForTexture(JNIEnv*, jclas
|
||||
return (jboolean) (texture->getTarget() == SamplerType::SAMPLER_EXTERNAL);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_Texture_nGeneratePrefilterMipmap(JNIEnv *env, jclass,
|
||||
jlong nativeTexture, jlong nativeEngine, jint width, jint height,
|
||||
jobject storage, jint remaining, jint left,
|
||||
jint top, jint type, jint alignment, jint stride, jint format,
|
||||
jintArray faceOffsetsInBytes_, jobject handler, jobject runnable, jint sampleCount,
|
||||
jboolean mirror) {
|
||||
|
||||
Texture *texture = (Texture *) nativeTexture;
|
||||
Engine *engine = (Engine *) nativeEngine;
|
||||
|
||||
jint *faceOffsetsInBytes = env->GetIntArrayElements(faceOffsetsInBytes_, NULL);
|
||||
Texture::FaceOffsets faceOffsets;
|
||||
std::copy_n(faceOffsetsInBytes, 6, faceOffsets.offsets);
|
||||
env->ReleaseIntArrayElements(faceOffsetsInBytes_, faceOffsetsInBytes, JNI_ABORT);
|
||||
|
||||
stride = stride ? stride : width;
|
||||
size_t sizeInBytes = 6 *
|
||||
Texture::computeTextureDataSize((Texture::Format) format, (Texture::Type) type,
|
||||
(size_t) stride, (size_t) height, (size_t) alignment);
|
||||
|
||||
AutoBuffer nioBuffer(env, storage, 0);
|
||||
if (sizeInBytes > (remaining << nioBuffer.getShift())) {
|
||||
// BufferOverflowException
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *buffer = nioBuffer.getData();
|
||||
auto *callback = JniBufferCallback::make(engine, env, handler, runnable, std::move(nioBuffer));
|
||||
|
||||
Texture::PixelBufferDescriptor desc(buffer, sizeInBytes, (backend::PixelDataFormat) format,
|
||||
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t)0, (uint32_t)0,
|
||||
(uint32_t) stride, &JniBufferCallback::invoke, callback);
|
||||
|
||||
Texture::PrefilterOptions options;
|
||||
options.sampleCount = sampleCount;
|
||||
options.mirror = mirror;
|
||||
texture->generatePrefilterMipmap(*engine, std::move(desc), faceOffsets, &options);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ANDROID SPECIFIC BITS
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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;
|
||||
|
||||
import android.support.annotation.IntRange;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.Size;
|
||||
|
||||
final class Asserts {
|
||||
private Asserts() {
|
||||
}
|
||||
|
||||
@NonNull @Size(min = 9)
|
||||
static float[] assertMat3f(@Nullable float[] out) {
|
||||
if (out == null) out = new float[9];
|
||||
else if (out.length < 9) {
|
||||
throw new ArrayIndexOutOfBoundsException("Array length must be at least 9");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static void assertMat3fIn(@NonNull @Size(min = 9) float[] in) {
|
||||
if (in.length < 9) {
|
||||
throw new ArrayIndexOutOfBoundsException("Array length must be at least 9");
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull @Size(min = 16)
|
||||
static double[] assertMat4d(@Nullable double[] out) {
|
||||
if (out == null) out = new double[16];
|
||||
else if (out.length < 16) {
|
||||
throw new ArrayIndexOutOfBoundsException("Array length must be at least 16");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static void assertMat4dIn(@NonNull @Size(min = 16) double[] in) {
|
||||
if (in.length < 16) {
|
||||
throw new ArrayIndexOutOfBoundsException("Array length must be at least 16");
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull @Size(min = 16)
|
||||
static float[] assertMat4f(@Nullable float[] out) {
|
||||
if (out == null) out = new float[16];
|
||||
else if (out.length < 16) {
|
||||
throw new ArrayIndexOutOfBoundsException("Array length must be at least 16");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static void assertMat4fIn(@NonNull @Size(min = 16) float[] in) {
|
||||
if (in.length < 16) {
|
||||
throw new ArrayIndexOutOfBoundsException("Array length must be at least 16");
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull @Size(min = 3)
|
||||
static float[] assertFloat3(@Nullable float[] out) {
|
||||
if (out == null) out = new float[3];
|
||||
else if (out.length < 3) {
|
||||
throw new ArrayIndexOutOfBoundsException("Array length must be at least 3");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@NonNull @Size(min = 4)
|
||||
static float[] assertFloat4(@Nullable float[] out) {
|
||||
if (out == null) out = new float[4];
|
||||
else if (out.length < 4) {
|
||||
throw new ArrayIndexOutOfBoundsException("Array length must be at least 4");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
@@ -219,7 +219,7 @@ public class Camera {
|
||||
*/
|
||||
public void setCustomProjection(@NonNull @Size(min = 16) double inMatrix[],
|
||||
double near, double far) {
|
||||
assertMat4dIn(inMatrix);
|
||||
Asserts.assertMat4dIn(inMatrix);
|
||||
nSetCustomProjection(getNativeObject(), inMatrix, near, far);
|
||||
}
|
||||
|
||||
@@ -228,7 +228,7 @@ public class Camera {
|
||||
* @param in
|
||||
*/
|
||||
public void setModelMatrix(@NonNull @Size(min = 16) float in[]) {
|
||||
assertMat4fIn(in);
|
||||
Asserts.assertMat4fIn(in);
|
||||
nSetModelMatrix(getNativeObject(), in);
|
||||
}
|
||||
|
||||
@@ -273,7 +273,7 @@ public class Camera {
|
||||
*/
|
||||
@NonNull @Size(min = 16)
|
||||
public double[] getProjectionMatrix(@Nullable @Size(min = 16) double out[]) {
|
||||
out = assertMat4d(out);
|
||||
out = Asserts.assertMat4d(out);
|
||||
nGetProjectionMatrix(getNativeObject(), out);
|
||||
return out;
|
||||
}
|
||||
@@ -287,7 +287,7 @@ public class Camera {
|
||||
*/
|
||||
@NonNull @Size(min = 16)
|
||||
public float[] getModelMatrix(@Nullable @Size(min = 16) float out[]) {
|
||||
out = assertMat4f(out);
|
||||
out = Asserts.assertMat4f(out);
|
||||
nGetModelMatrix(getNativeObject(), out);
|
||||
return out;
|
||||
}
|
||||
@@ -301,7 +301,7 @@ public class Camera {
|
||||
*/
|
||||
@NonNull @Size(min = 16)
|
||||
public float[] getViewMatrix(@Nullable @Size(min = 16) float out[]) {
|
||||
out = assertMat4f(out);
|
||||
out = Asserts.assertMat4f(out);
|
||||
nGetViewMatrix(getNativeObject(), out);
|
||||
return out;
|
||||
}
|
||||
@@ -314,7 +314,7 @@ public class Camera {
|
||||
*/
|
||||
@NonNull @Size(min = 3)
|
||||
public float[] getPosition(@Nullable @Size(min = 3) float out[]) {
|
||||
out = assertFloat3(out);
|
||||
out = Asserts.assertFloat3(out);
|
||||
nGetPosition(getNativeObject(), out);
|
||||
return out;
|
||||
}
|
||||
@@ -328,7 +328,7 @@ public class Camera {
|
||||
*/
|
||||
@NonNull @Size(min = 3)
|
||||
public float[] getLeftVector(@Nullable @Size(min = 3) float out[]) {
|
||||
out = assertFloat3(out);
|
||||
out = Asserts.assertFloat3(out);
|
||||
nGetLeftVector(getNativeObject(), out);
|
||||
return out;
|
||||
}
|
||||
@@ -342,7 +342,7 @@ public class Camera {
|
||||
*/
|
||||
@NonNull @Size(min = 3)
|
||||
public float[] getUpVector(@Nullable @Size(min = 3) float out[]) {
|
||||
out = assertFloat3(out);
|
||||
out = Asserts.assertFloat3(out);
|
||||
nGetUpVector(getNativeObject(), out);
|
||||
return out;
|
||||
}
|
||||
@@ -356,7 +356,7 @@ public class Camera {
|
||||
*/
|
||||
@NonNull @Size(min = 3)
|
||||
public float[] getForwardVector(@Nullable @Size(min = 3) float out[]) {
|
||||
out = assertFloat3(out);
|
||||
out = Asserts.assertFloat3(out);
|
||||
nGetForwardVector(getNativeObject(), out);
|
||||
return out;
|
||||
}
|
||||
@@ -406,45 +406,6 @@ public class Camera {
|
||||
mNativeObject = 0;
|
||||
}
|
||||
|
||||
@NonNull @Size(min = 16)
|
||||
private static double[] assertMat4d(@Nullable double[] out) {
|
||||
if (out == null) out = new double[16];
|
||||
else if (out.length < 16) {
|
||||
throw new ArrayIndexOutOfBoundsException("Array length must be at least 16");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@NonNull @Size(min = 16)
|
||||
private static float[] assertMat4f(@Nullable float[] out) {
|
||||
if (out == null) out = new float[16];
|
||||
else if (out.length < 16) {
|
||||
throw new ArrayIndexOutOfBoundsException("Array length must be at least 16");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private static void assertMat4dIn(@NonNull @Size(min = 16) double[] in) {
|
||||
if (in.length < 16) {
|
||||
throw new ArrayIndexOutOfBoundsException("Array length must be at least 16");
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertMat4fIn(@NonNull @Size(min = 16) float[] in) {
|
||||
if (in.length < 16) {
|
||||
throw new ArrayIndexOutOfBoundsException("Array length must be at least 16");
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull @Size(min = 3)
|
||||
private static float[] assertFloat3(@Nullable float[] out) {
|
||||
if (out == null) out = new float[3];
|
||||
else if (out.length < 3) {
|
||||
throw new ArrayIndexOutOfBoundsException("Array length must be at least 3");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private static native void nSetProjection(long nativeCamera, int projection, double left, double right, double bottom, double top, double near, double far);
|
||||
private static native void nSetProjectionFov(long nativeCamera, double fovInDegrees, double aspect, double near, double far, int fov);
|
||||
private static native void nSetLensProjection(long nativeCamera, double focalLength, double near, double far);
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.google.android.filament;
|
||||
|
||||
import com.google.android.filament.proguard.UsedByReflection;
|
||||
|
||||
import android.support.annotation.IntRange;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
@@ -66,6 +68,11 @@ public class EntityManager {
|
||||
return nIsAlive(mNativeObject, entity);
|
||||
}
|
||||
|
||||
@UsedByReflection("AssetLoader.java")
|
||||
long getNativeObject() {
|
||||
return mNativeObject;
|
||||
}
|
||||
|
||||
private static native long nGetEntityManager();
|
||||
private static native void nCreateArray(long nativeEntityManager, int n, int[] entities);
|
||||
private static native int nCreate(long nativeEntityManager);
|
||||
|
||||
@@ -16,14 +16,18 @@
|
||||
|
||||
package com.google.android.filament;
|
||||
|
||||
import com.google.android.filament.proguard.UsedByReflection;
|
||||
|
||||
import android.support.annotation.IntRange;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.Size;
|
||||
|
||||
public class IndirectLight {
|
||||
long mNativeObject;
|
||||
|
||||
private IndirectLight(long indirectLight) {
|
||||
@UsedByReflection("KtxLoader.java")
|
||||
IndirectLight(long indirectLight) {
|
||||
mNativeObject = indirectLight;
|
||||
}
|
||||
|
||||
@@ -92,7 +96,7 @@ public class IndirectLight {
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Builder rotation(@NonNull @Size(min = 9) float rotation[]) {
|
||||
public Builder rotation(@NonNull @Size(min = 9) float[] rotation) {
|
||||
nRotation(mNativeBuilder,
|
||||
rotation[0], rotation[1], rotation[2],
|
||||
rotation[3], rotation[4], rotation[5],
|
||||
@@ -132,13 +136,21 @@ public class IndirectLight {
|
||||
return nGetIntensity(getNativeObject());
|
||||
}
|
||||
|
||||
public void setRotation(@NonNull @Size(min = 9) float rotation[]) {
|
||||
public void setRotation(@NonNull @Size(min = 9) float[] rotation) {
|
||||
Asserts.assertMat3fIn(rotation);
|
||||
nSetRotation(getNativeObject(),
|
||||
rotation[0], rotation[1], rotation[2],
|
||||
rotation[3], rotation[4], rotation[5],
|
||||
rotation[6], rotation[7], rotation[8]);
|
||||
}
|
||||
|
||||
@NonNull @Size(min = 9)
|
||||
public float[] getRotation(@Nullable @Size(min = 9) float[] rotation) {
|
||||
rotation = Asserts.assertMat3f(rotation);
|
||||
nGetRotation(getNativeObject(), rotation);
|
||||
return rotation;
|
||||
}
|
||||
|
||||
long getNativeObject() {
|
||||
if (mNativeObject == 0) {
|
||||
throw new IllegalStateException("Calling method on destroyed IndirectLight");
|
||||
@@ -164,5 +176,5 @@ public class IndirectLight {
|
||||
private static native void nSetIntensity(long nativeIndirectLight, float intensity);
|
||||
private static native float nGetIntensity(long nativeIndirectLight);
|
||||
private static native void nSetRotation(long nativeIndirectLight, float v0, float v1, float v2, float v3, float v4, float v5, float v6, float v7, float v8);
|
||||
|
||||
private static native void nGetRotation(long nativeIndirectLight, float[] outRotation);
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ public class LightManager {
|
||||
|
||||
@NonNull
|
||||
public float[] getPosition(@EntityInstance int i, @Nullable @Size(min = 3) float[] out) {
|
||||
out = assertFloat3(out);
|
||||
out = Asserts.assertFloat3(out);
|
||||
nGetPosition(mNativeObject, i, out);
|
||||
return out;
|
||||
}
|
||||
@@ -198,7 +198,7 @@ public class LightManager {
|
||||
|
||||
@NonNull
|
||||
public float[] getDirection(@EntityInstance int i, @Nullable @Size(min = 3) float[] out) {
|
||||
out = assertFloat3(out);
|
||||
out = Asserts.assertFloat3(out);
|
||||
nGetDirection(mNativeObject, i, out);
|
||||
return out;
|
||||
}
|
||||
@@ -209,7 +209,7 @@ public class LightManager {
|
||||
|
||||
@NonNull
|
||||
public float[] getColor(@EntityInstance int i, @Nullable @Size(min = 3) float[] out) {
|
||||
out = assertFloat3(out);
|
||||
out = Asserts.assertFloat3(out);
|
||||
nGetColor(mNativeObject, i, out);
|
||||
return out;
|
||||
}
|
||||
@@ -262,15 +262,6 @@ public class LightManager {
|
||||
return nGetSunHaloFalloff(mNativeObject, i);
|
||||
}
|
||||
|
||||
@NonNull @Size(min = 3)
|
||||
private static float[] assertFloat3(@Nullable float[] out) {
|
||||
if (out == null) out = new float[3];
|
||||
else if (out.length < 3) {
|
||||
throw new ArrayIndexOutOfBoundsException("Array length must be at least 3");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private static native boolean nHasComponent(long nativeLightManager, int entity);
|
||||
private static native int nGetInstance(long nativeLightManager, int entity);
|
||||
private static native void nDestroy(long nativeLightManager, int entity);
|
||||
|
||||
@@ -134,8 +134,9 @@ public class Material {
|
||||
}
|
||||
}
|
||||
|
||||
private Material(long nativeMaterial, long nativeDefaultInstance) {
|
||||
Material(long nativeMaterial) {
|
||||
mNativeObject = nativeMaterial;
|
||||
long nativeDefaultInstance = nGetDefaultInstance(nativeMaterial);
|
||||
mDefaultInstance = new MaterialInstance(this, nativeDefaultInstance);
|
||||
}
|
||||
|
||||
@@ -154,8 +155,7 @@ public class Material {
|
||||
public Material build(@NonNull Engine engine) {
|
||||
long nativeMaterial = nBuilderBuild(engine.getNativeObject(), mBuffer, mSize);
|
||||
if (nativeMaterial == 0) throw new IllegalStateException("Couldn't create Material");
|
||||
long nativeDefaultInstance = nGetDefaultInstance(nativeMaterial);
|
||||
return new Material(nativeMaterial, nativeDefaultInstance);
|
||||
return new Material(nativeMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,8 +21,9 @@ import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Size;
|
||||
|
||||
public class MaterialInstance {
|
||||
private final Material mMaterial;
|
||||
private Material mMaterial;
|
||||
private long mNativeObject;
|
||||
private long mNativeMaterial;
|
||||
|
||||
public enum BooleanElement {
|
||||
BOOL,
|
||||
@@ -52,8 +53,16 @@ public class MaterialInstance {
|
||||
mNativeObject = nativeMaterialInstance;
|
||||
}
|
||||
|
||||
MaterialInstance(long nativeMaterial, long nativeMaterialInstance) {
|
||||
mNativeMaterial = nativeMaterial;
|
||||
mNativeObject = nativeMaterialInstance;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Material getMaterial() {
|
||||
if (mMaterial == null) {
|
||||
mMaterial = new Material(mNativeMaterial);
|
||||
}
|
||||
return mMaterial;
|
||||
}
|
||||
|
||||
|
||||
@@ -282,6 +282,14 @@ public class RenderableManager {
|
||||
nSetMaterialInstanceAt(mNativeObject, i, primitiveIndex, materialInstance.getNativeObject());
|
||||
}
|
||||
|
||||
// creates a MaterialInstance Java wrapper object for a particular material instance
|
||||
public @NonNull MaterialInstance getMaterialInstanceAt(@EntityInstance int i,
|
||||
@IntRange(from = 0) int primitiveIndex) {
|
||||
long nativeMatInstance = nGetMaterialInstanceAt(mNativeObject, i, primitiveIndex);
|
||||
long nativeMaterial = nGetMaterialAt(mNativeObject, i, primitiveIndex);
|
||||
return new MaterialInstance(nativeMaterial, nativeMatInstance);
|
||||
}
|
||||
|
||||
// set/change the geometry (vertex/index buffers) of a given primitive
|
||||
public void setGeometryAt(@EntityInstance int i, @IntRange(from = 0) int primitiveIndex,
|
||||
@NonNull PrimitiveType type, @NonNull VertexBuffer vertices,
|
||||
@@ -356,6 +364,8 @@ public class RenderableManager {
|
||||
private static native void nGetAxisAlignedBoundingBox(long nativeRenderableManager, int i, float[] center, float[] halfExtent);
|
||||
private static native int nGetPrimitiveCount(long nativeRenderableManager, int i);
|
||||
private static native void nSetMaterialInstanceAt(long nativeRenderableManager, int i, int primitiveIndex, long nativeMaterialInstance);
|
||||
private static native long nGetMaterialInstanceAt(long nativeRenderableManager, int i, int primitiveIndex);
|
||||
private static native long nGetMaterialAt(long nativeRenderableManager, int i, int primitiveIndex);
|
||||
private static native void nSetGeometryAt(long nativeRenderableManager, int i, int primitiveIndex, int primitiveType, long nativeVertexBuffer, long nativeIndexBuffer, int offset, int count);
|
||||
private static native void nSetGeometryAt(long nativeRenderableManager, int i, int primitiveIndex, int primitiveType, int offset, int count);
|
||||
private static native void nSetBlendOrderAt(long nativeRenderableManager, int i, int primitiveIndex, int blendOrder);
|
||||
|
||||
@@ -65,7 +65,7 @@ public class Renderer {
|
||||
flags);
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
public void mirrorFrame(
|
||||
@NonNull SwapChain dstSwapChain, @NonNull Viewport dstViewport,
|
||||
@NonNull Viewport srcViewport, int flags) {
|
||||
|
||||
@@ -52,6 +52,10 @@ public class Scene {
|
||||
nAddEntity(getNativeObject(), entity);
|
||||
}
|
||||
|
||||
public void addEntities(@Entity int[] entities) {
|
||||
nAddEntities(getNativeObject(), entities);
|
||||
}
|
||||
|
||||
public void removeEntity(@Entity int entity) {
|
||||
nRemove(getNativeObject(), entity);
|
||||
}
|
||||
@@ -85,6 +89,7 @@ public class Scene {
|
||||
private static native void nSetSkybox(long nativeScene, long nativeSkybox);
|
||||
private static native void nSetIndirectLight(long nativeScene, long nativeIndirectLight);
|
||||
private static native void nAddEntity(long nativeScene, int entity);
|
||||
private static native void nAddEntities(long nativeScene, int[] entities);
|
||||
private static native void nRemove(long nativeScene, int entity);
|
||||
private static native int nGetRenderableCount(long nativeScene);
|
||||
private static native int nGetLightCount(long nativeScene);
|
||||
|
||||
@@ -16,13 +16,16 @@
|
||||
|
||||
package com.google.android.filament;
|
||||
|
||||
import com.google.android.filament.proguard.UsedByReflection;
|
||||
|
||||
import android.support.annotation.IntRange;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
public class Skybox {
|
||||
private long mNativeObject;
|
||||
|
||||
private Skybox(long nativeSkybox) {
|
||||
@UsedByReflection("KtxLoader.java")
|
||||
Skybox(long nativeSkybox) {
|
||||
mNativeObject = nativeSkybox;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ import static com.google.android.filament.Texture.Type.COMPRESSED;
|
||||
public class Texture {
|
||||
private long mNativeObject;
|
||||
|
||||
@UsedByReflection("KtxLoader.java")
|
||||
Texture(long nativeTexture) {
|
||||
mNativeObject = nativeTexture;
|
||||
}
|
||||
@@ -62,7 +63,7 @@ public class Texture {
|
||||
RG16F, RG16UI, RG16I,
|
||||
R11F_G11F_B10F,
|
||||
RGBA8, SRGB8_A8, RGBA8_SNORM,
|
||||
UNUSED, // The RGBM InternalFormat has been replaced with a flag (Texture.Builder.rgbm)
|
||||
UNUSED, // used to be rgbm
|
||||
RGB10_A2, RGBA8UI, RGBA8I,
|
||||
DEPTH32F, DEPTH24_STENCIL8, DEPTH32F_STENCIL8,
|
||||
|
||||
@@ -120,7 +121,7 @@ public class Texture {
|
||||
RGB_INTEGER,
|
||||
RGBA,
|
||||
RGBA_INTEGER,
|
||||
RGBM,
|
||||
UNUSED,
|
||||
DEPTH_COMPONENT,
|
||||
DEPTH_STENCIL,
|
||||
STENCIL_INDEX,
|
||||
@@ -136,7 +137,8 @@ public class Texture {
|
||||
INT,
|
||||
HALF,
|
||||
FLOAT,
|
||||
COMPRESSED
|
||||
COMPRESSED,
|
||||
UINT_10F_11F_11F_REV
|
||||
}
|
||||
|
||||
public static class PixelBufferDescriptor {
|
||||
@@ -254,7 +256,6 @@ public class Texture {
|
||||
break;
|
||||
case RGBA:
|
||||
case RGBA_INTEGER:
|
||||
case RGBM:
|
||||
n = 4;
|
||||
break;
|
||||
}
|
||||
@@ -275,6 +276,10 @@ public class Texture {
|
||||
case FLOAT:
|
||||
bpp *= 4;
|
||||
break;
|
||||
case UINT_10F_11F_11F_REV:
|
||||
// Special case, format must be RGB and uses 4 bytes
|
||||
bpp = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
int bpr = bpp * stride;
|
||||
@@ -283,6 +288,11 @@ public class Texture {
|
||||
}
|
||||
}
|
||||
|
||||
public static class PrefilterOptions {
|
||||
public int sampleCount = 8;
|
||||
public boolean mirror = true;
|
||||
}
|
||||
|
||||
public static boolean isTextureFormatSupported(@NonNull Engine engine,
|
||||
@NonNull InternalFormat format) {
|
||||
return nIsTextureFormatSupported(engine.getNativeObject(), format.ordinal());
|
||||
@@ -335,9 +345,14 @@ public class Texture {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the usage flags, which is necessary when attaching to {@link RenderTarget}.
|
||||
*
|
||||
* The flags argument much be a combination of {@link Usage} flags.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder rgbm(boolean enabled) {
|
||||
nBuilderRgbm(mNativeBuilder, enabled);
|
||||
public Builder usage(int flags) {
|
||||
nBuilderUsage(mNativeBuilder, flags);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -367,6 +382,15 @@ public class Texture {
|
||||
}
|
||||
}
|
||||
|
||||
public static class Usage {
|
||||
public static final int COLOR_ATTACHMENT = 0x1;
|
||||
public static final int DEPTH_ATTACHMENT = 0x2;
|
||||
public static final int STENCIL_ATTACHMENT = 0x4;
|
||||
public static final int UPLOADABLE = 0x8;
|
||||
public static final int SAMPLEABLE = 0x10;
|
||||
public static final int DEFAULT = UPLOADABLE | SAMPLEABLE;
|
||||
}
|
||||
|
||||
public static final int BASE_LEVEL = 0;
|
||||
|
||||
public int getWidth(@IntRange(from = 0) int level) {
|
||||
@@ -472,6 +496,33 @@ public class Texture {
|
||||
nGenerateMipmaps(getNativeObject(), engine.getNativeObject());
|
||||
}
|
||||
|
||||
public void generatePrefilterMipmap(@NonNull Engine engine,
|
||||
@NonNull PixelBufferDescriptor buffer, @NonNull @Size(min = 6) int[] faceOffsetsInBytes,
|
||||
PrefilterOptions options) {
|
||||
|
||||
int width = getWidth(0);
|
||||
int height= getHeight(0);
|
||||
int sampleCount = 8;
|
||||
boolean mirror = true;
|
||||
if (options != null) {
|
||||
sampleCount = options.sampleCount;
|
||||
mirror = options.mirror;
|
||||
}
|
||||
|
||||
int result = nGeneratePrefilterMipmap(getNativeObject(), engine.getNativeObject(),
|
||||
width, height,
|
||||
buffer.storage, buffer.storage.remaining(),
|
||||
buffer.left, buffer.top, buffer.type.ordinal(), buffer.alignment,
|
||||
buffer.stride, buffer.format.ordinal(), faceOffsetsInBytes,
|
||||
buffer.handler, buffer.callback,
|
||||
sampleCount, mirror);
|
||||
|
||||
if (result < 0) {
|
||||
throw new BufferOverflowException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@UsedByReflection("TextureHelper.java")
|
||||
long getNativeObject() {
|
||||
if (mNativeObject == 0) {
|
||||
@@ -495,7 +546,7 @@ public class Texture {
|
||||
private static native void nBuilderLevels(long nativeBuilder, int levels);
|
||||
private static native void nBuilderSampler(long nativeBuilder, int sampler);
|
||||
private static native void nBuilderFormat(long nativeBuilder, int format);
|
||||
private static native void nBuilderRgbm(long nativeBuilder, boolean enabled);
|
||||
private static native void nBuilderUsage(long nativeBuilder, int flags);
|
||||
private static native long nBuilderBuild(long nativeBuilder, long nativeEngine);
|
||||
|
||||
private static native int nGetWidth(long nativeTexture, int level);
|
||||
@@ -536,4 +587,9 @@ public class Texture {
|
||||
private static native void nGenerateMipmaps(long nativeTexture, long nativeEngine);
|
||||
|
||||
private static native boolean nIsStreamValidForTexture(long nativeTexture, long nativeStream);
|
||||
|
||||
private static native int nGeneratePrefilterMipmap(long nativeIndirectLight, long nativeEngine,
|
||||
int width, int height, Buffer storage, int remaining, int left, int top,
|
||||
int type, int alignment, int stride, int format, int[] faceOffsetsInBytes,
|
||||
Object handler, Runnable callback, int sampleCount, boolean mirror);
|
||||
}
|
||||
|
||||
@@ -57,9 +57,7 @@ public class TransformManager {
|
||||
|
||||
public void setTransform(@EntityInstance int i,
|
||||
@NonNull @Size(min = 16) float[] localTransform) {
|
||||
if (localTransform.length < 16) {
|
||||
throw new ArrayIndexOutOfBoundsException("Array length must be at least 16");
|
||||
}
|
||||
Asserts.assertMat4fIn(localTransform);
|
||||
nSetTransform(mNativeObject, i, localTransform);
|
||||
}
|
||||
|
||||
@@ -67,7 +65,7 @@ public class TransformManager {
|
||||
@Size(min = 16)
|
||||
public float[] getTransform(@EntityInstance int i,
|
||||
@Nullable @Size(min = 16) float[] outLocalTransform) {
|
||||
outLocalTransform = assertMat4f(outLocalTransform);
|
||||
outLocalTransform = Asserts.assertMat4f(outLocalTransform);
|
||||
nGetTransform(mNativeObject, i, outLocalTransform);
|
||||
return outLocalTransform;
|
||||
}
|
||||
@@ -76,7 +74,7 @@ public class TransformManager {
|
||||
@Size(min = 16)
|
||||
public float[] getWorldTransform(@EntityInstance int i,
|
||||
@Nullable @Size(min = 16) float[] outWorldTransform) {
|
||||
outWorldTransform = assertMat4f(outWorldTransform);
|
||||
outWorldTransform = Asserts.assertMat4f(outWorldTransform);
|
||||
nGetWorldTransform(mNativeObject, i, outWorldTransform);
|
||||
return outWorldTransform;
|
||||
}
|
||||
@@ -89,15 +87,6 @@ public class TransformManager {
|
||||
nCommitLocalTransformTransaction(mNativeObject);
|
||||
}
|
||||
|
||||
@NonNull @Size(min = 16)
|
||||
private static float[] assertMat4f(@Nullable float[] out) {
|
||||
if (out == null) out = new float[16];
|
||||
else if (out.length < 16) {
|
||||
throw new ArrayIndexOutOfBoundsException("Array length must be at least 16");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private static native boolean nHasComponent(long nativeTransformManager, int entity);
|
||||
private static native int nGetInstance(long nativeTransformManager, int entity);
|
||||
private static native int nCreate(long nativeTransformManager, int entity);
|
||||
|
||||
@@ -33,6 +33,7 @@ public class View {
|
||||
private RenderQuality mRenderQuality;
|
||||
private DepthPrepass mDepthPrepass = DepthPrepass.DEFAULT;
|
||||
private AmbientOcclusionOptions mAmbientOcclusionOptions;
|
||||
private RenderTarget mRenderTarget;
|
||||
|
||||
public static class DynamicResolutionOptions {
|
||||
public boolean enabled = false;
|
||||
@@ -147,7 +148,7 @@ public class View {
|
||||
|
||||
@NonNull @Size(min = 4)
|
||||
public float[] getClearColor(@NonNull @Size(min = 4) float[] out) {
|
||||
out = assertFloat4(out);
|
||||
out = Asserts.assertFloat4(out);
|
||||
nGetClearColor(getNativeObject(), out);
|
||||
return out;
|
||||
}
|
||||
@@ -167,9 +168,15 @@ public class View {
|
||||
}
|
||||
|
||||
public void setRenderTarget(@Nullable RenderTarget target) {
|
||||
mRenderTarget = target;
|
||||
nSetRenderTarget(getNativeObject(), target != null ? target.getNativeObject() : 0);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public RenderTarget getRenderTarget() {
|
||||
return mRenderTarget;
|
||||
}
|
||||
|
||||
public void setSampleCount(int count) {
|
||||
nSetSampleCount(getNativeObject(), count);
|
||||
}
|
||||
@@ -302,15 +309,6 @@ public class View {
|
||||
mNativeObject = 0;
|
||||
}
|
||||
|
||||
@NonNull @Size(min = 4)
|
||||
private static float[] assertFloat4(@Nullable float[] out) {
|
||||
if (out == null) out = new float[4];
|
||||
else if (out.length < 4) {
|
||||
throw new ArrayIndexOutOfBoundsException("Array length must be at least 4");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private static native void nSetName(long nativeView, String name);
|
||||
private static native void nSetScene(long nativeView, long nativeScene);
|
||||
private static native void nSetCamera(long nativeView, long nativeCamera);
|
||||
|
||||
@@ -58,7 +58,7 @@ import com.google.android.filament.SwapChain;
|
||||
* mUiHelper = new UiHelper(UiHelper.ContextErrorPolicy.DONT_CHECK);
|
||||
*
|
||||
* // Attach the SurfaceView to the helper, you could do the same with a TextureView
|
||||
* mUiHelper.attachTo(surfaceView)
|
||||
* mUiHelper.attachTo(mSurfaceView);
|
||||
*
|
||||
* // Set a rendering callback that we will use to invoke Filament
|
||||
* mUiHelper.setRenderCallback(new UiHelper.RendererCallback() {
|
||||
@@ -95,15 +95,15 @@ import com.google.android.filament.SwapChain;
|
||||
* }
|
||||
*
|
||||
* public void onDestroy() {
|
||||
* super.onDestroy()
|
||||
* super.onDestroy();
|
||||
* // Always detach the surface before destroying the engine
|
||||
* mUiHelper.detach()
|
||||
* mUiHelper.detach();
|
||||
*
|
||||
* // This ensures that all the commands we've sent to Filament have
|
||||
* // been processed before we attempt to destroy anything
|
||||
* Fence.waitAndDestroy(mEngine.createFence(Fence.Type.SOFT), Fence.Mode.FLUSH);
|
||||
*
|
||||
* mEngine.destroy()
|
||||
* mEngine.destroy();
|
||||
* }
|
||||
*
|
||||
* // This is an example of a render function. You will most likely invoke this from
|
||||
@@ -113,8 +113,8 @@ import com.google.android.filament.SwapChain;
|
||||
* // If beginFrame() returns false you should skip the frame
|
||||
* // This means you are sending frames too quickly to the GPU
|
||||
* if (mRenderer.beginFrame(swapChain)) {
|
||||
* mRenderer.render(mView)
|
||||
* mRenderer.endFrame()
|
||||
* mRenderer.render(mView);
|
||||
* mRenderer.endFrame();
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
|
||||
11
android/gltfio-android/.gitignore
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
/.idea/caches
|
||||
/.idea/gradle.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
89
android/gltfio-android/CMakeLists.txt
Normal file
@@ -0,0 +1,89 @@
|
||||
cmake_minimum_required(VERSION 3.6)
|
||||
|
||||
set(FILAMENT_DIR ${FILAMENT_DIST_DIR})
|
||||
|
||||
add_library(filament SHARED IMPORTED)
|
||||
set_target_properties(filament PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilament.a)
|
||||
|
||||
add_library(backend SHARED IMPORTED)
|
||||
set_target_properties(backend PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libbackend.a)
|
||||
|
||||
add_library(utils SHARED IMPORTED)
|
||||
set_target_properties(utils PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libutils.a)
|
||||
|
||||
add_library(filaflat SHARED 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 SHARED IMPORTED)
|
||||
set_target_properties(geometry PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libgeometry.a)
|
||||
|
||||
add_library(filabridge SHARED IMPORTED)
|
||||
set_target_properties(filabridge PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilabridge.a)
|
||||
|
||||
add_library(gltfio SHARED IMPORTED)
|
||||
set_target_properties(gltfio PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libgltfio_core.a)
|
||||
|
||||
add_library(gltfio_resources SHARED IMPORTED)
|
||||
set_target_properties(gltfio_resources PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libgltfio_resources.a)
|
||||
|
||||
include_directories(${FILAMENT_DIR}/include
|
||||
..
|
||||
../../libs/utils/include)
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-stack-protector")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-rtti")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ffast-math -ffp-contract=fast")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fvisibility-inlines-hidden")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fvisibility=hidden")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fomit-frame-pointer -ffunction-sections -fdata-sections")
|
||||
|
||||
set(CMAKE_SHARED_LINKER_FLAGS " ${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS " ${CMAKE_SHARED_LINKER_FLAGS} -Wl,-Bsymbolic-functions")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${CMAKE_SOURCE_DIR}/libgltfio-jni.map")
|
||||
|
||||
add_library(gltfio-jni SHARED
|
||||
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
|
||||
../common/CallbackUtils.cpp
|
||||
../common/NioUtils.cpp
|
||||
)
|
||||
|
||||
set_target_properties(gltfio-jni PROPERTIES LINK_DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libgltfio-jni.symbols)
|
||||
|
||||
# The ordering in the following list is important because CMake does not have dependency information.
|
||||
target_link_libraries(gltfio-jni
|
||||
gltfio
|
||||
gltfio_resources
|
||||
filament
|
||||
filabridge
|
||||
backend
|
||||
filaflat
|
||||
geometry
|
||||
image
|
||||
ibl
|
||||
utils
|
||||
GLESv3
|
||||
EGL
|
||||
m
|
||||
log
|
||||
)
|
||||
90
android/gltfio-android/build.gradle
Normal file
@@ -0,0 +1,90 @@
|
||||
// This script accepts the following parameters:
|
||||
//
|
||||
// filament_dist_dir
|
||||
// Path to the Filament distribution/install directory for Android
|
||||
// (produced by make/ninja install). This directory must contain lib/arm64-v8a/ etc.
|
||||
//
|
||||
// Example:
|
||||
// ./gradlew -Pfilament_dist_dir=../../dist-android-release assembleRelease
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
group = "com.google.android.filament"
|
||||
version = "0.1"
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
def filament_path = file("../../out/android-release/filament").absolutePath
|
||||
if (project.hasProperty("filament_dist_dir")) {
|
||||
filament_path = file("$filament_dist_dir").absolutePath
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 28
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments.add("-DANDROID_PIE=ON")
|
||||
arguments.add("-DANDROID_PLATFORM=android-21")
|
||||
arguments.add("-DANDROID_STL=c++_static")
|
||||
arguments.add("-DFILAMENT_DIST_DIR=${filament_path}".toString())
|
||||
cppFlags.add("-std=c++14")
|
||||
if (project.hasProperty('extra_cmake_args')) {
|
||||
arguments.add(extra_cmake_args)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path "CMakeLists.txt"
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
jni.srcDirs "src/main/cpp"
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation 'com.android.support:support-annotations:28.0.0'
|
||||
implementation 'com.google.android.filament:filament-android'
|
||||
}
|
||||
BIN
android/gltfio-android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
5
android/gltfio-android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
172
android/gltfio-android/gradlew
vendored
Executable file
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
84
android/gltfio-android/gradlew.bat
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
4
android/gltfio-android/libgltfio-jni.map
Normal file
@@ -0,0 +1,4 @@
|
||||
LIBGLTFIO {
|
||||
global: Java_com_google_android_filament_*; JNI*;
|
||||
local: *;
|
||||
};
|
||||
1
android/gltfio-android/libgltfio-jni.symbols
Normal file
@@ -0,0 +1 @@
|
||||
_Java_com_google_android_filament_*
|
||||
12
android/gltfio-android/settings.gradle
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*
|
||||
* The settings file is used to specify which projects to include in your build.
|
||||
*
|
||||
* Detailed information about configuring a multi-project build in Gradle can be found
|
||||
* in the user guide at https://docs.gradle.org/4.6/userguide/multi_project_builds.html
|
||||
*/
|
||||
|
||||
includeBuild '../filament-android'
|
||||
|
||||
rootProject.name = 'gltfio-android'
|
||||
18
android/gltfio-android/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<!--
|
||||
Copyright (C) 2019 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.gltfio" />
|
||||
85
android/gltfio-android/src/main/cpp/AssetLoader.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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 <filament/Engine.h>
|
||||
|
||||
#include <utils/EntityManager.h>
|
||||
|
||||
#include <gltfio/AssetLoader.h>
|
||||
#include <gltfio/MaterialProvider.h>
|
||||
|
||||
#include "common/NioUtils.h"
|
||||
|
||||
using namespace filament;
|
||||
using namespace gltfio;
|
||||
using namespace utils;
|
||||
|
||||
extern void registerCallbackUtils(JNIEnv*);
|
||||
extern void registerNioUtils(JNIEnv*);
|
||||
|
||||
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
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_AssetLoader_nCreateAssetLoader(JNIEnv*, jclass,
|
||||
jlong nativeEngine, jlong nativeProvider, jlong nativeEntities) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
MaterialProvider* materials = (MaterialProvider*) nativeProvider;
|
||||
EntityManager* entities = (EntityManager*) nativeEntities;
|
||||
return (jlong) AssetLoader::create({engine, materials, nullptr, entities});
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_AssetLoader_nDestroyAssetLoader(JNIEnv*, jclass,
|
||||
jlong nativeLoader) {
|
||||
AssetLoader* loader = (AssetLoader*) nativeLoader;
|
||||
AssetLoader::destroy(&loader);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_gltfio_AssetLoader_nCreateAssetFromBinary(JNIEnv* env, jclass,
|
||||
jlong nativeLoader, jobject javaBuffer, jint remaining) {
|
||||
AssetLoader* loader = (AssetLoader*) nativeLoader;
|
||||
AutoBuffer buffer(env, javaBuffer, remaining);
|
||||
return (jlong) loader->createAssetFromBinary((const uint8_t *) buffer.getData(),
|
||||
buffer.getSize());
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_AssetLoader_nEnableDiagnostics(JNIEnv*, jclass,
|
||||
jlong nativeLoader, jboolean enable) {
|
||||
AssetLoader* loader = (AssetLoader*) nativeLoader;
|
||||
loader->enableDiagnostics(enable);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_AssetLoader_nDestroyAsset(JNIEnv*, jclass,
|
||||
jlong nativeLoader, jlong nativeAsset) {
|
||||
AssetLoader* loader = (AssetLoader*) nativeLoader;
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
loader->destroyAsset(asset);
|
||||
}
|
||||
63
android/gltfio-android/src/main/cpp/FilamentAsset.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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 <gltfio/FilamentAsset.h>
|
||||
|
||||
using namespace filament;
|
||||
using namespace filament::math;
|
||||
using namespace gltfio;
|
||||
using namespace utils;
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nGetRoot(JNIEnv*, jclass, jlong nativeAsset) {
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
return asset->getRoot().getId();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nGetEntityCount(JNIEnv*, jclass,
|
||||
jlong nativeAsset) {
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
return asset->getEntityCount();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nGetEntities(JNIEnv* env, jclass,
|
||||
jlong nativeAsset, jintArray result) {
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
Entity* entities = (Entity*) env->GetIntArrayElements(result, nullptr);
|
||||
std::copy_n(asset->getEntities(), asset->getEntityCount(), entities);
|
||||
env->ReleaseIntArrayElements(result, (jint*) entities, 0);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nGetBoundingBox(JNIEnv* env, jclass,
|
||||
jlong nativeAsset, jfloatArray result) {
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
float* values = (float*) env->GetFloatArrayElements(result, nullptr);
|
||||
const filament::Aabb box = asset->getBoundingBox();
|
||||
const float3 center = box.center();
|
||||
const float3 extent = box.extent();
|
||||
values[0] = center.x;
|
||||
values[1] = center.y;
|
||||
values[2] = center.z;
|
||||
values[3] = extent.x;
|
||||
values[4] = extent.y;
|
||||
values[5] = extent.z;
|
||||
env->ReleaseFloatArrayElements(result, (jfloat*) values, 0);
|
||||
}
|
||||
77
android/gltfio-android/src/main/cpp/KtxLoader.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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 <filament/Engine.h>
|
||||
#include <filament/IndirectLight.h>
|
||||
#include <filament/Skybox.h>
|
||||
|
||||
#include <image/KtxUtility.h>
|
||||
|
||||
#include "common/NioUtils.h"
|
||||
|
||||
using namespace filament;
|
||||
using namespace filament::math;
|
||||
using namespace image;
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_gltfio_KtxLoader_nCreateTexture(JNIEnv* env, jclass,
|
||||
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
AutoBuffer buffer(env, javaBuffer, remaining);
|
||||
KtxBundle* bundle = new KtxBundle((const uint8_t*) buffer.getData(), buffer.getSize());
|
||||
return (jlong) KtxUtility::createTexture(engine, *bundle, srgb, [](void* userdata) {
|
||||
KtxBundle* bundle = (KtxBundle*) userdata;
|
||||
delete bundle;
|
||||
}, bundle);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_gltfio_KtxLoader_nCreateIndirectLight(JNIEnv* env, jclass,
|
||||
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
AutoBuffer buffer(env, javaBuffer, remaining);
|
||||
KtxBundle* bundle = new KtxBundle((const uint8_t*) buffer.getData(), buffer.getSize());
|
||||
Texture* cubemap = KtxUtility::createTexture(engine, *bundle, srgb, [](void* userdata) {
|
||||
KtxBundle* bundle = (KtxBundle*) userdata;
|
||||
delete bundle;
|
||||
}, bundle);
|
||||
|
||||
float3 harmonics[9];
|
||||
bundle->getSphericalHarmonics(harmonics);
|
||||
|
||||
IndirectLight* indirectLight = IndirectLight::Builder()
|
||||
.reflections(cubemap)
|
||||
.irradiance(3, harmonics)
|
||||
.intensity(30000)
|
||||
.build(*engine);
|
||||
|
||||
return (jlong) indirectLight;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_gltfio_KtxLoader_nCreateSkybox(JNIEnv* env, jclass,
|
||||
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
AutoBuffer buffer(env, javaBuffer, remaining);
|
||||
KtxBundle* bundle = new KtxBundle((const uint8_t*) buffer.getData(), buffer.getSize());
|
||||
Texture* cubemap = KtxUtility::createTexture(engine, *bundle, srgb, [](void* userdata) {
|
||||
KtxBundle* bundle = (KtxBundle*) userdata;
|
||||
delete bundle;
|
||||
}, bundle);
|
||||
return (jlong) Skybox::Builder().environment(cubemap).showSun(true).build(*engine);
|
||||
}
|
||||
36
android/gltfio-android/src/main/cpp/MaterialProvider.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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 <gltfio/MaterialProvider.h>
|
||||
|
||||
using namespace filament;
|
||||
using namespace gltfio;
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_gltfio_MaterialProvider_nCreateMaterialProvider(JNIEnv*, jclass,
|
||||
jlong nativeEngine) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
return (jlong) createUbershaderLoader(engine);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_MaterialProvider_nDestroyMaterialProvider(JNIEnv*, jclass,
|
||||
jlong nativeProvider) {
|
||||
auto provider = (MaterialProvider*) nativeProvider;
|
||||
delete provider;
|
||||
}
|
||||
67
android/gltfio-android/src/main/cpp/ResourceLoader.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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 <filament/Engine.h>
|
||||
|
||||
#include <gltfio/ResourceLoader.h>
|
||||
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "common/NioUtils.h"
|
||||
|
||||
using namespace filament;
|
||||
using namespace gltfio;
|
||||
using namespace utils;
|
||||
|
||||
static void destroy(void* data, size_t size, void *userData) {
|
||||
AutoBuffer* buffer = (AutoBuffer*) userData;
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_gltfio_ResourceLoader_nCreateResourceLoader(JNIEnv*, jclass,
|
||||
jlong nativeEngine) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
return (jlong) new ResourceLoader({ engine, utils::Path(), true, true });
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_ResourceLoader_nDestroyResourceLoader(JNIEnv*, jclass,
|
||||
jlong nativeLoader) {
|
||||
ResourceLoader* loader = (ResourceLoader*) nativeLoader;
|
||||
delete loader;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_ResourceLoader_nAddResourceData(JNIEnv* env, jclass,
|
||||
jlong nativeLoader, jstring url, jobject javaBuffer, jint remaining) {
|
||||
ResourceLoader* loader = (ResourceLoader*) nativeLoader;
|
||||
AutoBuffer* buffer = new AutoBuffer(env, javaBuffer, remaining);
|
||||
const char* curl = env->GetStringUTFChars(url, nullptr);
|
||||
loader->addResourceData(curl,
|
||||
ResourceLoader::BufferDescriptor(buffer->getData(), buffer->getSize(), &destroy,
|
||||
buffer));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_ResourceLoader_nLoadResources(JNIEnv*, jclass,
|
||||
jlong nativeLoader, jlong nativeAsset) {
|
||||
ResourceLoader* loader = (ResourceLoader*) nativeLoader;
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
loader->loadResources(asset);
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.gltfio;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.google.android.filament.Engine;
|
||||
import com.google.android.filament.EntityManager;
|
||||
import com.google.android.filament.IndirectLight;
|
||||
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;
|
||||
|
||||
public class AssetLoader {
|
||||
private long mNativeObject;
|
||||
|
||||
static Method sEngineGetNativeObject;
|
||||
static Method sEntityManagerGetNativeObject;
|
||||
static Constructor<Texture> sTextureConstructor;
|
||||
static Constructor<IndirectLight> sIndirectLightConstructor;
|
||||
static Constructor<Skybox> sSkyboxConstructor;
|
||||
|
||||
public static void init() {
|
||||
System.loadLibrary("gltfio-jni");
|
||||
try {
|
||||
sEngineGetNativeObject = Engine.class.getDeclaredMethod("getNativeObject");
|
||||
sEngineGetNativeObject.setAccessible(true);
|
||||
|
||||
sEntityManagerGetNativeObject = EntityManager.class.getDeclaredMethod("getNativeObject");
|
||||
sEntityManagerGetNativeObject.setAccessible(true);
|
||||
|
||||
sTextureConstructor = Texture.class.getDeclaredConstructor(long.class);
|
||||
sTextureConstructor.setAccessible(true);
|
||||
|
||||
sIndirectLightConstructor = IndirectLight.class.getDeclaredConstructor(long.class);
|
||||
sIndirectLightConstructor.setAccessible(true);
|
||||
|
||||
sSkyboxConstructor = Skybox.class.getDeclaredConstructor(long.class);
|
||||
sSkyboxConstructor.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
// Cannot happen
|
||||
}
|
||||
}
|
||||
|
||||
public AssetLoader(@NonNull Engine engine, @NonNull MaterialProvider generator,
|
||||
@NonNull EntityManager entities) {
|
||||
try {
|
||||
long nativeEngine = (long) sEngineGetNativeObject.invoke(engine);
|
||||
long nativeMaterials = generator.getNativeObject();
|
||||
long nativeEntities = (long) sEntityManagerGetNativeObject.invoke(entities);
|
||||
mNativeObject = nCreateAssetLoader(nativeEngine, nativeMaterials, nativeEntities);
|
||||
} catch (Exception e) {
|
||||
// Ignored
|
||||
}
|
||||
if (mNativeObject == 0) {
|
||||
throw new IllegalStateException("Unable to parse glTF asset.");
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
nDestroyAssetLoader(mNativeObject);
|
||||
mNativeObject = 0;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FilamentAsset createAssetFromBinary(@NonNull Buffer buffer) {
|
||||
long nativeAsset = nCreateAssetFromBinary(mNativeObject, buffer, buffer.remaining());
|
||||
return new FilamentAsset(nativeAsset);
|
||||
}
|
||||
|
||||
public void enableDiagnostics(boolean enable) {
|
||||
nEnableDiagnostics(mNativeObject, enable);
|
||||
}
|
||||
|
||||
public void destroyAsset(@Nullable FilamentAsset asset) {
|
||||
nDestroyAsset(mNativeObject, asset.getNativeObject());
|
||||
asset.clearNativeObject();
|
||||
}
|
||||
|
||||
private static native long nCreateAssetLoader(long nativeEngine, long nativeGenerator, long nativeEntities);
|
||||
private static native void nDestroyAssetLoader(long nativeLoader);
|
||||
private static native long nCreateAssetFromBinary(long nativeLoader, Buffer buffer, int remaining);
|
||||
private static native void nEnableDiagnostics(long nativeLoader, boolean enable);
|
||||
private static native void nDestroyAsset(long nativeLoader, long nativeAsset);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.gltfio;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.google.android.filament.Box;
|
||||
import com.google.android.filament.Entity;
|
||||
|
||||
public class FilamentAsset {
|
||||
private long mNativeObject;
|
||||
|
||||
FilamentAsset(long nativeObject) {
|
||||
mNativeObject = nativeObject;
|
||||
}
|
||||
|
||||
long getNativeObject() {
|
||||
return mNativeObject;
|
||||
}
|
||||
|
||||
public @Entity int getRoot() {
|
||||
return nGetRoot(mNativeObject);
|
||||
}
|
||||
|
||||
public @Entity int[] getEntities() {
|
||||
int[] result = new int[nGetEntityCount(mNativeObject)];
|
||||
nGetEntities(mNativeObject, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public @NonNull Box getBoundingBox() {
|
||||
float[] box = new float[6];
|
||||
nGetBoundingBox(mNativeObject, box);
|
||||
return new Box(box[0], box[1], box[2], box[3], box[4], box[5]);
|
||||
}
|
||||
|
||||
void clearNativeObject() {
|
||||
mNativeObject = 0;
|
||||
}
|
||||
|
||||
private static native int nGetRoot(long nativeAsset);
|
||||
private static native int nGetEntityCount(long nativeAsset);
|
||||
private static native void nGetEntities(long nativeAsset, int[] result);
|
||||
private static native void nGetBoundingBox(long nativeAsset, float[] box);
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.gltfio;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.google.android.filament.Engine;
|
||||
import com.google.android.filament.IndirectLight;
|
||||
import com.google.android.filament.Skybox;
|
||||
import com.google.android.filament.Texture;
|
||||
|
||||
import java.nio.Buffer;
|
||||
|
||||
public class KtxLoader {
|
||||
|
||||
public static class Options {
|
||||
public boolean srgb;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Texture createTexture(@NonNull Engine engine, @NonNull Buffer buffer, @NonNull Options options) {
|
||||
try {
|
||||
long nativeEngine = (long) AssetLoader.sEngineGetNativeObject.invoke(engine);
|
||||
long nativeTexture = nCreateTexture(nativeEngine, buffer, buffer.remaining(), options.srgb);
|
||||
return AssetLoader.sTextureConstructor.newInstance(nativeTexture);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static IndirectLight createIndirectLight(@NonNull Engine engine, @NonNull Buffer buffer, @NonNull Options options) {
|
||||
try {
|
||||
long nativeEngine = (long) AssetLoader.sEngineGetNativeObject.invoke(engine);
|
||||
long nativeIndirectLight = nCreateIndirectLight(nativeEngine, buffer, buffer.remaining(), options.srgb);
|
||||
return AssetLoader.sIndirectLightConstructor.newInstance(nativeIndirectLight);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Skybox createSkybox(@NonNull Engine engine, @NonNull Buffer buffer, @NonNull Options options) {
|
||||
try {
|
||||
long nativeEngine = (long) AssetLoader.sEngineGetNativeObject.invoke(engine);
|
||||
long nativeSkybox = nCreateSkybox(nativeEngine, buffer, buffer.remaining(), options.srgb);
|
||||
return AssetLoader.sSkyboxConstructor.newInstance(nativeSkybox);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static native long nCreateTexture(long nativeEngine, Buffer buffer, int remaining, boolean srgb);
|
||||
private static native long nCreateIndirectLight(long nativeEngine, Buffer buffer, int remaining, boolean srgb);
|
||||
private static native long nCreateSkybox(long nativeEngine, Buffer buffer, int remaining, boolean srgb);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.gltfio;
|
||||
|
||||
import com.google.android.filament.Engine;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class MaterialProvider {
|
||||
private long mNativeObject;
|
||||
|
||||
private static Method sEngineGetNativeObject;
|
||||
|
||||
static {
|
||||
try {
|
||||
sEngineGetNativeObject = Engine.class.getDeclaredMethod("getNativeObject");
|
||||
sEngineGetNativeObject.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
// Cannot happen
|
||||
}
|
||||
}
|
||||
|
||||
public MaterialProvider(Engine engine) {
|
||||
try {
|
||||
long nativeEngine = (long) sEngineGetNativeObject.invoke(engine);
|
||||
mNativeObject = nCreateMaterialProvider(nativeEngine);
|
||||
} catch (Exception e) {
|
||||
// Ignored
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
nDestroyMaterialProvider(mNativeObject);
|
||||
mNativeObject = 0;
|
||||
}
|
||||
|
||||
long getNativeObject() {
|
||||
return mNativeObject;
|
||||
}
|
||||
|
||||
private static native long nCreateMaterialProvider(long nativeEngine);
|
||||
private static native void nDestroyMaterialProvider(long nativeProvider);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.gltfio;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.filament.Engine;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.Buffer;
|
||||
|
||||
public class ResourceLoader {
|
||||
private final long mNativeObject;
|
||||
|
||||
private static Method sEngineGetNativeObject;
|
||||
|
||||
static {
|
||||
try {
|
||||
sEngineGetNativeObject = Engine.class.getDeclaredMethod("getNativeObject");
|
||||
sEngineGetNativeObject.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
// Cannot happen
|
||||
}
|
||||
}
|
||||
|
||||
public ResourceLoader(@NonNull Engine engine) throws IllegalAccessException, InvocationTargetException {
|
||||
long nativeEngine = (long) sEngineGetNativeObject.invoke(engine);
|
||||
mNativeObject = nCreateResourceLoader(nativeEngine);
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
nDestroyResourceLoader(mNativeObject);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public ResourceLoader addResourceData(@NonNull String url, @NonNull Buffer buffer) {
|
||||
nAddResourceData(mNativeObject, url, buffer, buffer.remaining());
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public ResourceLoader loadResources(@NonNull FilamentAsset asset) {
|
||||
nLoadResources(mNativeObject, asset.getNativeObject());
|
||||
return this;
|
||||
}
|
||||
|
||||
private static native long nCreateResourceLoader(long nativeEngine);
|
||||
private static native void nDestroyResourceLoader(long nativeLoader);
|
||||
private static native void nAddResourceData(long nativeLoader, String url, Buffer buffer,
|
||||
int remaining);
|
||||
private static native void nLoadResources(long nativeLoader, long nativeAsset);
|
||||
}
|
||||
@@ -46,6 +46,12 @@ host machine:
|
||||
|
||||

|
||||
|
||||
### `gltf-bloom`
|
||||
|
||||
Demonstrates how to load glTF models and render to an offscreen buffer:
|
||||
|
||||

|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you start, make sure to read [Filament's README](../../README.md). You need to be able to
|
||||
|
||||
12
android/samples/gltf-bloom/.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
|
||||
/app/src/main/assets
|
||||
.externalNativeBuild
|
||||
1
android/samples/gltf-bloom/app/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
70
android/samples/gltf-bloom/app/build.gradle
Normal file
@@ -0,0 +1,70 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
apply from: '../../../build/filament-tasks.gradle'
|
||||
|
||||
compileMaterials {
|
||||
group 'Filament'
|
||||
description 'Compile materials'
|
||||
|
||||
inputDir = file("src/main/materials")
|
||||
outputDir = file("src/main/assets/materials")
|
||||
}
|
||||
|
||||
task copyMesh(type: Copy) {
|
||||
from file("../../../../third_party/models/lucy/lucy.glb")
|
||||
into file("src/main/assets/models")
|
||||
}
|
||||
|
||||
task copySky(type: Copy) {
|
||||
from file("../../../../samples/envs/venetian_crossroads/venetian_crossroads_ibl.ktx")
|
||||
into file("src/main/assets/envs")
|
||||
}
|
||||
|
||||
task copyIbl(type: Copy) {
|
||||
from file("../../../../samples/envs/venetian_crossroads/venetian_crossroads_skybox.ktx")
|
||||
into file("src/main/assets/envs")
|
||||
}
|
||||
|
||||
preBuild.dependsOn compileMaterials
|
||||
preBuild.dependsOn copyMesh
|
||||
preBuild.dependsOn copySky
|
||||
preBuild.dependsOn copyIbl
|
||||
|
||||
clean.doFirst {
|
||||
delete "src/main/assets"
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
defaultConfig {
|
||||
applicationId "com.google.android.filament.gltf"
|
||||
minSdkVersion 26
|
||||
targetSdkVersion 28
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
// We use the .filamat extension for materials compiled with matc
|
||||
// Telling aapt to not compress them allows to load them efficiently
|
||||
aaptOptions {
|
||||
noCompress 'filamat', 'ktx'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
|
||||
// Depend on Filament
|
||||
implementation 'com.google.android.filament:filament-android'
|
||||
implementation 'com.google.android.filament:gltfio-android'
|
||||
}
|
||||
21
android/samples/gltf-bloom/app/proguard-rules.pro
vendored
Normal file
@@ -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
|
||||
21
android/samples/gltf-bloom/app/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.android.filament.gltf">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity android:name="com.google.android.filament.gltf.MainActivity" android:screenOrientation="portrait">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.gltf
|
||||
|
||||
import java.io.InputStream
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
|
||||
fun readIntLE(input: InputStream): Int {
|
||||
return input.read() and 0xff or (
|
||||
input.read() and 0xff shl 8) or (
|
||||
input.read() and 0xff shl 16) or (
|
||||
input.read() and 0xff shl 24)
|
||||
}
|
||||
|
||||
fun readFloat32LE(input: InputStream): Float {
|
||||
val bytes = ByteArray(4)
|
||||
input.read(bytes, 0, 4)
|
||||
return ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).float
|
||||
}
|
||||
|
||||
fun readUIntLE(input: InputStream): Long {
|
||||
return readIntLE(input).toLong() and 0xFFFFFFFFL
|
||||
}
|
||||
@@ -0,0 +1,573 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.gltf
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import android.view.Choreographer
|
||||
import android.view.Surface
|
||||
import android.view.SurfaceView
|
||||
import android.view.animation.LinearInterpolator
|
||||
|
||||
import com.google.android.filament.*
|
||||
import com.google.android.filament.android.UiHelper
|
||||
import com.google.android.filament.gltfio.*
|
||||
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
import java.nio.channels.Channels
|
||||
import kotlin.math.*
|
||||
|
||||
data class Framebuffer(
|
||||
val camera: Camera,
|
||||
val view: View,
|
||||
val scene: Scene,
|
||||
var color: Texture? = null,
|
||||
var depth: Texture? = null,
|
||||
var target: RenderTarget? = null)
|
||||
|
||||
class MainActivity : Activity() {
|
||||
|
||||
// Be sure to initialize not only Filament, but also gltfio (via AssetLoader)
|
||||
companion object {
|
||||
init {
|
||||
Filament.init()
|
||||
AssetLoader.init()
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var surfaceView: SurfaceView
|
||||
private lateinit var uiHelper: UiHelper
|
||||
private lateinit var choreographer: Choreographer
|
||||
|
||||
private lateinit var engine: Engine
|
||||
private lateinit var renderer: Renderer
|
||||
|
||||
private lateinit var assetLoader: AssetLoader
|
||||
private lateinit var filamentAsset: FilamentAsset
|
||||
|
||||
private lateinit var finalScene: Scene
|
||||
private lateinit var finalView: View
|
||||
private lateinit var finalCamera: Camera
|
||||
|
||||
private val kGaussianSampleCount = 9
|
||||
private val kGaussianFilterSize = 1 + 2 * (kGaussianSampleCount - 1)
|
||||
private val kGaussianWeights = FloatArray(kGaussianSampleCount * 4 * 2)
|
||||
|
||||
@Entity private var finalQuad = 0
|
||||
@Entity private var hblurQuad = 0
|
||||
@Entity private var vblurQuad = 0
|
||||
|
||||
private lateinit var primary: Framebuffer
|
||||
private lateinit var hblur: Framebuffer
|
||||
private lateinit var vblur: Framebuffer
|
||||
|
||||
private var quadVertBufferGpu: VertexBuffer? = null
|
||||
private var quadIndxBufferGpu: IndexBuffer? = null
|
||||
|
||||
enum class ImageOp { MIX, HBLUR, VBLUR}
|
||||
|
||||
private lateinit var mixMaterial: Material
|
||||
private lateinit var blurMaterial: Material
|
||||
|
||||
@Entity private var light = 0
|
||||
|
||||
private var swapChain: SwapChain? = null
|
||||
|
||||
private val frameScheduler = FrameCallback()
|
||||
|
||||
private val animator = ValueAnimator.ofFloat(0.0f, (2.0 * PI).toFloat())
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
computeGaussianWeights()
|
||||
|
||||
surfaceView = SurfaceView(this)
|
||||
setContentView(surfaceView)
|
||||
|
||||
choreographer = Choreographer.getInstance()
|
||||
|
||||
uiHelper = UiHelper(UiHelper.ContextErrorPolicy.DONT_CHECK)
|
||||
uiHelper.renderCallback = SurfaceCallback()
|
||||
uiHelper.setDesiredSize(720, 1280)
|
||||
uiHelper.attachTo(surfaceView)
|
||||
|
||||
engine = Engine.create()
|
||||
renderer = engine.createRenderer()
|
||||
|
||||
primary = Framebuffer(engine.createCamera(), engine.createView(), engine.createScene())
|
||||
primary.view.setName("primary")
|
||||
primary.view.scene = primary.scene
|
||||
primary.view.camera = primary.camera
|
||||
primary.view.dithering = View.Dithering.NONE
|
||||
primary.view.toneMapping = View.ToneMapping.LINEAR
|
||||
|
||||
hblur = Framebuffer(engine.createCamera(), engine.createView(), engine.createScene())
|
||||
hblur.view.setName("hblur")
|
||||
hblur.view.scene = hblur.scene
|
||||
hblur.view.camera = hblur.camera
|
||||
hblur.view.sampleCount = 1
|
||||
hblur.view.isPostProcessingEnabled = false
|
||||
|
||||
vblur = Framebuffer(engine.createCamera(), engine.createView(), engine.createScene())
|
||||
vblur.view.setName("vblur")
|
||||
vblur.view.scene = vblur.scene
|
||||
vblur.view.camera = vblur.camera
|
||||
vblur.view.sampleCount = 1
|
||||
vblur.view.isPostProcessingEnabled = false
|
||||
|
||||
finalScene = engine.createScene()
|
||||
finalView = engine.createView()
|
||||
finalView.setName("final")
|
||||
finalCamera = engine.createCamera()
|
||||
finalCamera.setExposure(16.0f, 1.0f / 125.0f, 100.0f)
|
||||
finalView.scene = finalScene
|
||||
finalView.camera = finalCamera
|
||||
finalView.sampleCount = 1
|
||||
|
||||
// Materials
|
||||
// ---------
|
||||
|
||||
readUncompressedAsset("materials/blur.filamat").let {
|
||||
blurMaterial = Material.Builder().payload(it, it.remaining()).build(engine)
|
||||
}
|
||||
|
||||
readUncompressedAsset("materials/mix.filamat").let {
|
||||
mixMaterial = Material.Builder().payload(it, it.remaining()).build(engine)
|
||||
}
|
||||
|
||||
// IndirectLight and SkyBox
|
||||
// ------------------------
|
||||
|
||||
readUncompressedAsset("envs/venetian_crossroads_ibl.ktx").let {
|
||||
primary.scene.indirectLight = KtxLoader.createIndirectLight(engine, it, KtxLoader.Options())
|
||||
primary.scene.indirectLight!!.intensity = 50_000.0f
|
||||
}
|
||||
|
||||
readUncompressedAsset("envs/venetian_crossroads_skybox.ktx").let {
|
||||
primary.scene.skybox = KtxLoader.createSkybox(engine, it, KtxLoader.Options())
|
||||
}
|
||||
|
||||
val theta = PI * 2.7
|
||||
val distance = 5.0
|
||||
primary.camera.lookAt(
|
||||
cos(theta) * distance , 0.0, sin(theta) * distance ,
|
||||
0.0, -0.1, 0.0,
|
||||
0.0, 1.0, 0.0)
|
||||
|
||||
// glTF Entities, Textures, and Materials
|
||||
// --------------------------------------
|
||||
|
||||
assetLoader = AssetLoader(engine, MaterialProvider(engine), EntityManager.get())
|
||||
|
||||
filamentAsset = assets.open("models/lucy.glb").use { input ->
|
||||
val bytes = ByteArray(input.available())
|
||||
input.read(bytes)
|
||||
assetLoader.createAssetFromBinary(ByteBuffer.wrap(bytes))!!
|
||||
}
|
||||
|
||||
// Since this is a GLB file, the ResourceLoader does not need any additional files, and
|
||||
// we can destroy it immediately.
|
||||
ResourceLoader(engine).loadResources(filamentAsset).destroy()
|
||||
|
||||
primary.scene.addEntities(filamentAsset.entities)
|
||||
val tm = engine.transformManager
|
||||
tm.setTransform(tm.getInstance(filamentAsset.root),
|
||||
floatArrayOf(
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, -1.7f, 0.0f, 1.0f
|
||||
))
|
||||
|
||||
val rm = engine.renderableManager
|
||||
for (entity in filamentAsset.entities) {
|
||||
val instance = rm.getInstance(entity)
|
||||
val primCount = rm.getPrimitiveCount(instance)
|
||||
for (primIndex in 0 until primCount) {
|
||||
val mi = rm.getMaterialInstanceAt(instance, primIndex)
|
||||
mi.setParameter("roughnessFactor", 0.1f)
|
||||
mi.setParameter("baseColorFactor", 0.5f, 0.5f, 0.0f, 1.0f)
|
||||
}
|
||||
}
|
||||
|
||||
// Punctual Light Sources
|
||||
// ----------------------
|
||||
|
||||
light = EntityManager.get().create()
|
||||
|
||||
val (r, g, b) = Colors.cct(6_500.0f)
|
||||
LightManager.Builder(LightManager.Type.DIRECTIONAL)
|
||||
.color(r, g, b)
|
||||
.intensity(300_000.0f)
|
||||
.direction(0.0f, -1.0f, 0.0f)
|
||||
.castShadows(true)
|
||||
.build(engine, light)
|
||||
|
||||
primary.scene.addEntity(light)
|
||||
|
||||
// Start Animation
|
||||
// ---------------
|
||||
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.duration = 1_000_000
|
||||
animator.repeatMode = ValueAnimator.RESTART
|
||||
animator.repeatCount = ValueAnimator.INFINITE
|
||||
animator.addUpdateListener { a ->
|
||||
val v = 5.0f * PI.toFloat() * (a.animatedValue as Float)
|
||||
|
||||
tm.setTransform(tm.getInstance(filamentAsset.root),
|
||||
floatArrayOf(
|
||||
cos(v), 0.0f, -sin(v), 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
sin(v), 0.0f, cos(v), 0.0f,
|
||||
0.0f, -1.7f, 0.0f, 1.0f
|
||||
))
|
||||
|
||||
}
|
||||
animator.start()
|
||||
}
|
||||
|
||||
private fun initRenderTargets() {
|
||||
val width = surfaceView.width
|
||||
val height = surfaceView.height
|
||||
android.util.Log.i("gltf-bloom", "RenderTarget objects are $width x $height.")
|
||||
|
||||
primary.color = Texture.Builder()
|
||||
.width(width).height(height).levels(1)
|
||||
.usage(Texture.Usage.COLOR_ATTACHMENT or Texture.Usage.SAMPLEABLE)
|
||||
.format(Texture.InternalFormat.RGBA16F)
|
||||
.build(engine)
|
||||
|
||||
primary.depth = Texture.Builder()
|
||||
.width(width).height(height).levels(1)
|
||||
.usage(Texture.Usage.DEPTH_ATTACHMENT)
|
||||
.format(Texture.InternalFormat.DEPTH24)
|
||||
.build(engine)
|
||||
|
||||
primary.target = RenderTarget.Builder()
|
||||
.texture(RenderTarget.AttachmentPoint.COLOR, primary.color)
|
||||
.texture(RenderTarget.AttachmentPoint.DEPTH, primary.depth)
|
||||
.build(engine)
|
||||
|
||||
hblur.color = Texture.Builder()
|
||||
.width(width).height(height).levels(1)
|
||||
.usage(Texture.Usage.COLOR_ATTACHMENT or Texture.Usage.SAMPLEABLE)
|
||||
.format(Texture.InternalFormat.RGBA16F)
|
||||
.build(engine)
|
||||
|
||||
hblur.target = RenderTarget.Builder()
|
||||
.texture(RenderTarget.AttachmentPoint.COLOR, hblur.color)
|
||||
.build(engine)
|
||||
|
||||
vblur.color = Texture.Builder()
|
||||
.width(width).height(height).levels(1)
|
||||
.usage(Texture.Usage.COLOR_ATTACHMENT or Texture.Usage.SAMPLEABLE)
|
||||
.format(Texture.InternalFormat.RGBA16F)
|
||||
.build(engine)
|
||||
|
||||
vblur.target = RenderTarget.Builder()
|
||||
.texture(RenderTarget.AttachmentPoint.COLOR, vblur.color)
|
||||
.build(engine)
|
||||
|
||||
hblurQuad = createQuad(engine, ImageOp.HBLUR, primary.color!!)
|
||||
vblurQuad = createQuad(engine, ImageOp.VBLUR, hblur.color!!)
|
||||
finalQuad = createQuad(engine, ImageOp.MIX, primary.color!!, vblur.color)
|
||||
|
||||
hblur.scene.addEntity(hblurQuad)
|
||||
vblur.scene.addEntity(vblurQuad)
|
||||
finalScene.addEntity(finalQuad)
|
||||
|
||||
primary.view.viewport = Viewport(0, 0, width, height)
|
||||
primary.view.renderTarget = primary.target
|
||||
|
||||
hblur.view.viewport = Viewport(0, 0, width, height)
|
||||
hblur.view.renderTarget = hblur.target
|
||||
hblur.camera.setProjection(Camera.Projection.ORTHO, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0)
|
||||
|
||||
vblur.view.viewport = Viewport(0, 0, width, height)
|
||||
vblur.view.renderTarget = vblur.target
|
||||
vblur.camera.setProjection(Camera.Projection.ORTHO, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0)
|
||||
|
||||
finalView.viewport = Viewport(0, 0, width, height)
|
||||
finalCamera.setProjection(Camera.Projection.ORTHO, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0)
|
||||
}
|
||||
|
||||
@Entity private fun createQuad(engine: Engine, op: ImageOp, primary: Texture, secondary: Texture? = null): Int {
|
||||
|
||||
if (quadVertBufferGpu == null) {
|
||||
|
||||
val vb = VertexBuffer.Builder()
|
||||
.vertexCount(4)
|
||||
.bufferCount(1)
|
||||
.attribute(VertexBuffer.VertexAttribute.POSITION, 0, VertexBuffer.AttributeType.FLOAT2, 0, 16)
|
||||
.attribute(VertexBuffer.VertexAttribute.UV0, 0, VertexBuffer.AttributeType.FLOAT2, 8, 16)
|
||||
.build(engine)
|
||||
|
||||
data class Vertex(val x: Float, val y: Float, val u: Float, val v: Float)
|
||||
fun ByteBuffer.put(v: Vertex): ByteBuffer {
|
||||
putFloat(v.x)
|
||||
putFloat(v.y)
|
||||
putFloat(v.u)
|
||||
putFloat(v.v)
|
||||
return this
|
||||
}
|
||||
|
||||
val quadVertexBuffer = ByteBuffer.allocateDirect(16 * 4)
|
||||
.order(ByteOrder.nativeOrder())
|
||||
.put(Vertex(0f, 0f, 0f, 0f))
|
||||
.put(Vertex(1f, 0f, 1f, 0f))
|
||||
.put(Vertex(0f, 1f, 0f, 1f))
|
||||
.put(Vertex(1f, 1f, 1f, 1f))
|
||||
.flip()
|
||||
|
||||
vb.setBufferAt(engine, 0, quadVertexBuffer)
|
||||
|
||||
quadVertBufferGpu = vb
|
||||
}
|
||||
val vb = quadVertBufferGpu!!
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (quadIndxBufferGpu == null) {
|
||||
|
||||
val ib = IndexBuffer.Builder()
|
||||
.indexCount(6)
|
||||
.bufferType(IndexBuffer.Builder.IndexType.USHORT)
|
||||
.build(engine)
|
||||
|
||||
data class Triangle(val x: Short, val y: Short, val z: Short)
|
||||
fun ByteBuffer.put(t: Triangle): ByteBuffer {
|
||||
putShort(t.x)
|
||||
putShort(t.y)
|
||||
putShort(t.z)
|
||||
return this
|
||||
}
|
||||
|
||||
val buf = ByteBuffer.allocateDirect(6 * 2)
|
||||
.order(ByteOrder.LITTLE_ENDIAN)
|
||||
.put(Triangle(2, 1, 0))
|
||||
.put(Triangle(1, 2, 3))
|
||||
.flip()
|
||||
|
||||
ib.setBuffer(engine, buf)
|
||||
quadIndxBufferGpu = ib
|
||||
}
|
||||
val ib = quadIndxBufferGpu!!
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
val sampler = TextureSampler(TextureSampler.MinFilter.LINEAR, TextureSampler.MagFilter.LINEAR, TextureSampler.WrapMode.CLAMP_TO_EDGE)
|
||||
|
||||
val material = when (op) {
|
||||
ImageOp.HBLUR -> {
|
||||
// Extract the first half of the weights array for the horizontal pass.
|
||||
this.blurMaterial.createInstance().apply {
|
||||
setParameter("weights", MaterialInstance.FloatElement.FLOAT4, kGaussianWeights, 0, kGaussianSampleCount)
|
||||
setParameter("passIndex", 0)
|
||||
}
|
||||
}
|
||||
ImageOp.VBLUR -> {
|
||||
// Extract the second half of the weights array for the vertical pass.
|
||||
this.blurMaterial.createInstance().apply {
|
||||
setParameter("weights", MaterialInstance.FloatElement.FLOAT4, kGaussianWeights, kGaussianSampleCount, kGaussianSampleCount)
|
||||
setParameter("passIndex", 1)
|
||||
}
|
||||
}
|
||||
ImageOp.MIX -> {
|
||||
this.mixMaterial.createInstance().apply {
|
||||
setParameter("secondary", secondary!!, sampler)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
material.setParameter("color", primary, sampler)
|
||||
|
||||
val entity = EntityManager.get().create()
|
||||
|
||||
RenderableManager.Builder(1)
|
||||
.boundingBox(Box(0.0f, 0.0f, 0.0f, 9000.0f, 9000.0f, 9000.0f))
|
||||
.geometry(0, RenderableManager.PrimitiveType.TRIANGLES, vb, ib)
|
||||
.material(0, material)
|
||||
.build(engine, entity)
|
||||
|
||||
return entity
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
choreographer.postFrameCallback(frameScheduler)
|
||||
animator.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
choreographer.removeFrameCallback(frameScheduler)
|
||||
animator.cancel()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
// Always detach the surface before destroying the engine
|
||||
uiHelper.detach()
|
||||
|
||||
// This ensures that all the commands we've sent to Filament have
|
||||
// been processed before we attempt to destroy anything
|
||||
Fence.waitAndDestroy(engine.createFence(Fence.Type.SOFT), Fence.Mode.FLUSH)
|
||||
|
||||
assetLoader.destroyAsset(filamentAsset)
|
||||
assetLoader.destroy()
|
||||
|
||||
engine.destroyEntity(light)
|
||||
engine.destroyRenderer(renderer)
|
||||
engine.destroyView(finalView)
|
||||
engine.destroyScene(finalScene)
|
||||
engine.destroyCamera(finalCamera)
|
||||
|
||||
// Engine.destroyEntity() destroys Filament related resources only
|
||||
// (components), not the entity itself
|
||||
val entityManager = EntityManager.get()
|
||||
entityManager.destroy(light)
|
||||
|
||||
// Destroying the engine will free up any resource you may have forgotten
|
||||
// to destroy, but it's recommended to do the cleanup properly
|
||||
engine.destroy()
|
||||
}
|
||||
|
||||
inner class FrameCallback : Choreographer.FrameCallback {
|
||||
override fun doFrame(frameTimeNanos: Long) {
|
||||
choreographer.postFrameCallback(this)
|
||||
|
||||
if (uiHelper.isReadyToRender) {
|
||||
if (renderer.beginFrame(swapChain!!)) {
|
||||
renderer.render(primary.view)
|
||||
renderer.render(hblur.view)
|
||||
renderer.render(vblur.view)
|
||||
renderer.render(finalView)
|
||||
renderer.endFrame()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class SurfaceCallback : UiHelper.RendererCallback {
|
||||
override fun onNativeWindowChanged(surface: Surface) {
|
||||
swapChain?.let { engine.destroySwapChain(it) }
|
||||
swapChain = engine.createSwapChain(surface)
|
||||
}
|
||||
|
||||
override fun onDetachedFromSurface() {
|
||||
swapChain?.let {
|
||||
engine.destroySwapChain(it)
|
||||
// Required to ensure we don't return before Filament is done executing the
|
||||
// destroySwapChain command, otherwise Android might destroy the Surface
|
||||
// too early
|
||||
engine.flushAndWait()
|
||||
swapChain = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResized(width: Int, height: Int) {
|
||||
|
||||
// Lazily create RenderTarget objects, now that we know the size of the view.
|
||||
if (primary.color == null) {
|
||||
initRenderTargets()
|
||||
}
|
||||
|
||||
val aspect = width.toDouble() / height.toDouble()
|
||||
primary.camera.setProjection(45.0, aspect, 0.1, 20.0, Camera.Fov.VERTICAL)
|
||||
|
||||
primary.view.viewport = Viewport(0, 0, width, height)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun readUncompressedAsset(assetName: String): ByteBuffer {
|
||||
assets.openFd(assetName).use { fd ->
|
||||
val input = fd.createInputStream()
|
||||
val dst = ByteBuffer.allocate(fd.length.toInt())
|
||||
|
||||
val src = Channels.newChannel(input)
|
||||
src.read(dst)
|
||||
src.close()
|
||||
|
||||
return dst.apply { rewind() }
|
||||
}
|
||||
}
|
||||
|
||||
private fun computeGaussianWeights() {
|
||||
|
||||
val filter = fun(t0: Float): Float {
|
||||
val t = t0 / 2.0f
|
||||
if (t >= 1.0) return 0.0f
|
||||
val scale = 1.0f / sqrt(0.5f * PI.toFloat())
|
||||
return exp(-2.0f * t * t) * scale
|
||||
}
|
||||
|
||||
val pixelWidth = 2.0f / kGaussianFilterSize.toFloat()
|
||||
var sum = 0.0f
|
||||
|
||||
repeat (kGaussianSampleCount) { s ->
|
||||
|
||||
// Determine which two texels to sample from.
|
||||
val i: Int
|
||||
val j: Int
|
||||
when {
|
||||
s < kGaussianSampleCount/ 2 -> {
|
||||
i = s * 2
|
||||
j = i + 1
|
||||
}
|
||||
s == kGaussianSampleCount/ 2 -> {
|
||||
j = s * 2
|
||||
i = j
|
||||
}
|
||||
else -> {
|
||||
j = s * 2
|
||||
i = j - 1
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the normalized (x,y) along the Gaussian curve for each of the two samples.
|
||||
val weighti = filter(abs(-1.0f + pixelWidth / 2.0f + pixelWidth * i))
|
||||
val weightj = filter(abs(-1.0f + pixelWidth / 2.0f + pixelWidth * j))
|
||||
val offseti = i - (kGaussianFilterSize - 1) / 2
|
||||
|
||||
// Leverage hardware interpolation by sampling between the texel centers.
|
||||
// Nudge the left sample rightward by an amount proportional to its weight.
|
||||
val offset = offseti + weightj / (weighti + weightj)
|
||||
val weight = weighti + weightj
|
||||
|
||||
kGaussianWeights[s * 4 + 0] = weight
|
||||
kGaussianWeights[s * 4 + 1] = offset
|
||||
kGaussianWeights[s * 4 + 2] = 0.0f
|
||||
|
||||
kGaussianWeights[s * 4 + kGaussianSampleCount * 4 + 0] = weight
|
||||
kGaussianWeights[s * 4 + kGaussianSampleCount * 4 + 2] = offset
|
||||
kGaussianWeights[s * 4 + kGaussianSampleCount * 4 + 1] = 0.0f
|
||||
|
||||
sum += kGaussianWeights[s * 4]
|
||||
}
|
||||
|
||||
repeat (kGaussianSampleCount) { s ->
|
||||
kGaussianWeights[s * 4 + 0] /= sum
|
||||
kGaussianWeights[s * 4 + kGaussianSampleCount * 4 + 0] /= sum
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
22
android/samples/gltf-bloom/app/src/main/materials/blit.mat
Normal file
@@ -0,0 +1,22 @@
|
||||
material {
|
||||
name : blit,
|
||||
shadingModel : unlit,
|
||||
depthWrite: false,
|
||||
depthCulling: false,
|
||||
parameters : [
|
||||
{
|
||||
type : sampler2d,
|
||||
name : color
|
||||
}
|
||||
],
|
||||
requires: [
|
||||
uv0
|
||||
]
|
||||
}
|
||||
|
||||
fragment {
|
||||
void material(inout MaterialInputs material) {
|
||||
prepareMaterial(material);
|
||||
material.baseColor = texture(materialParams_color, getUV0());
|
||||
}
|
||||
}
|
||||
49
android/samples/gltf-bloom/app/src/main/materials/blur.mat
Normal file
@@ -0,0 +1,49 @@
|
||||
material {
|
||||
name : blur,
|
||||
shadingModel : unlit,
|
||||
depthWrite: false,
|
||||
depthCulling: false,
|
||||
parameters : [
|
||||
{
|
||||
type : sampler2d,
|
||||
name : color
|
||||
},
|
||||
{
|
||||
type : float4[9],
|
||||
name : weights
|
||||
},
|
||||
{
|
||||
type : int,
|
||||
name : passIndex
|
||||
}
|
||||
],
|
||||
requires: [
|
||||
uv0
|
||||
]
|
||||
|
||||
}
|
||||
fragment {
|
||||
|
||||
const int kGaussianSampleCount = 9;
|
||||
const float kReinhardWeight = 5.0;
|
||||
|
||||
vec3 Tonemap_ReinhardWeighted(const vec3 x, float weight) {
|
||||
// Weighted Reinhard tone-mapping operator designed for post-processing
|
||||
// This tone-mapping operator is invertible
|
||||
return x * (weight / (max3(x) + 1.0));
|
||||
}
|
||||
|
||||
void material(inout MaterialInputs material) {
|
||||
prepareMaterial(material);
|
||||
vec3 c = vec3(0);
|
||||
for (int i = 0; i < kGaussianSampleCount; i++) {
|
||||
float2 st = getUV0() + materialParams.weights[i].yz * getResolution().zw;
|
||||
vec3 color = texture(materialParams_color, st).rgb;
|
||||
if (materialParams.passIndex == 0) {
|
||||
color = Tonemap_ReinhardWeighted(color, kReinhardWeight);
|
||||
}
|
||||
c += color * materialParams.weights[i].x;
|
||||
}
|
||||
material.baseColor.rgb = c;
|
||||
}
|
||||
}
|
||||
50
android/samples/gltf-bloom/app/src/main/materials/mix.mat
Normal file
@@ -0,0 +1,50 @@
|
||||
material {
|
||||
name : mix,
|
||||
shadingModel : unlit,
|
||||
depthWrite: false,
|
||||
depthCulling: false,
|
||||
parameters : [
|
||||
{
|
||||
type : sampler2d,
|
||||
name : color
|
||||
},
|
||||
{
|
||||
type : sampler2d,
|
||||
name : secondary
|
||||
}
|
||||
],
|
||||
requires: [
|
||||
uv0
|
||||
]
|
||||
}
|
||||
|
||||
fragment {
|
||||
|
||||
const float kReinhardWeight = 5.0;
|
||||
|
||||
vec3 Tonemap_ReinhardWeighted(const vec3 x, float weight) {
|
||||
// Weighted Reinhard tone-mapping operator designed for post-processing
|
||||
// This tone-mapping operator is invertible
|
||||
return x * (weight / (max3(x) + 1.0));
|
||||
}
|
||||
|
||||
vec3 Tonemap_ReinhardWeighted_Invert(const vec3 x) {
|
||||
// Inverse Reinhard tone-mapping operator, designed to be used in conjunction
|
||||
// with the weighted Reinhard tone-mapping operator
|
||||
return x / (1.0 - max3(x));
|
||||
}
|
||||
|
||||
void material(inout MaterialInputs material) {
|
||||
prepareMaterial(material);
|
||||
vec3 primary = texture(materialParams_color, getUV0()).rgb;
|
||||
primary = Tonemap_ReinhardWeighted(primary, kReinhardWeight);
|
||||
vec3 blurred = texture(materialParams_secondary, getUV0()).rgb;
|
||||
|
||||
// HACK: this is a crude bloom effect
|
||||
float brightness = max(blurred.r, max(blurred.g, blurred.b));
|
||||
float soft_mask = smoothstep(1.5, 2.0, brightness);
|
||||
|
||||
material.baseColor.rgb = mix(primary, blurred, soft_mask);
|
||||
material.baseColor.rgb = Tonemap_ReinhardWeighted_Invert(material.baseColor.rgb / kReinhardWeight);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="78.5885"
|
||||
android:endY="90.9159"
|
||||
android:startX="48.7653"
|
||||
android:startY="61.0927"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0"/>
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,171 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillColor="#26A69A"
|
||||
android:pathData="M0,0h108v108h-108z"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#3F51B5</color>
|
||||
<color name="colorPrimaryDark">#303F9F</color>
|
||||
<color name="colorAccent">#FF4081</color>
|
||||
</resources>
|
||||
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">gltf bloom</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,8 @@
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
27
android/samples/gltf-bloom/build.gradle
Normal file
@@ -0,0 +1,27 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.11'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
13
android/samples/gltf-bloom/gradle.properties
Normal file
@@ -0,0 +1,13 @@
|
||||
# Project-wide Gradle settings.
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
BIN
android/samples/gltf-bloom/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
6
android/samples/gltf-bloom/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#Tue Jun 11 08:52:48 PDT 2019
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
|
||||
172
android/samples/gltf-bloom/gradlew
vendored
Executable file
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
84
android/samples/gltf-bloom/gradlew.bat
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
4
android/samples/gltf-bloom/settings.gradle
Normal file
@@ -0,0 +1,4 @@
|
||||
includeBuild '../../filament-android'
|
||||
includeBuild '../../gltfio-android'
|
||||
|
||||
include ':app'
|
||||
@@ -1,13 +1,13 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.11'
|
||||
ext.kotlin_version = '1.3.31'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.4.0'
|
||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
||||
@@ -60,13 +60,12 @@ private fun loadIndirectLight(
|
||||
assets: AssetManager,
|
||||
name: String,
|
||||
engine: Engine): Pair<IndirectLight, Texture> {
|
||||
val (w, h) = peekSize(assets, "$name/m0_nx.rgbm")
|
||||
val (w, h) = peekSize(assets, "$name/m0_nx.rgb32f")
|
||||
val texture = Texture.Builder()
|
||||
.width(w)
|
||||
.height(h)
|
||||
.levels(log2(w.toFloat()).toInt() + 1)
|
||||
.format(Texture.InternalFormat.RGBA8)
|
||||
.rgbm(true)
|
||||
.format(Texture.InternalFormat.R11F_G11F_B10F)
|
||||
.sampler(Texture.Sampler.SAMPLER_CUBEMAP)
|
||||
.build(engine)
|
||||
|
||||
@@ -101,13 +100,12 @@ private fun loadSphericalHarmonics(assets: AssetManager, name: String): FloatArr
|
||||
}
|
||||
|
||||
private fun loadSkybox(assets: AssetManager, name: String, engine: Engine): Pair<Skybox, Texture> {
|
||||
val (w, h) = peekSize(assets, "$name/nx.rgbm")
|
||||
val (w, h) = peekSize(assets, "$name/nx.rgb32f")
|
||||
val texture = Texture.Builder()
|
||||
.width(w)
|
||||
.height(h)
|
||||
.levels(1)
|
||||
.format(Texture.InternalFormat.RGBA8)
|
||||
.rgbm(true)
|
||||
.format(Texture.InternalFormat.R11F_G11F_B10F)
|
||||
.sampler(Texture.Sampler.SAMPLER_CUBEMAP)
|
||||
.build(engine)
|
||||
|
||||
@@ -122,19 +120,19 @@ private fun loadCubemap(texture: Texture,
|
||||
engine: Engine,
|
||||
prefix: String = "",
|
||||
level: Int = 0) {
|
||||
// This is important, in the RGBM format the alpha channel does not encode
|
||||
// opacity but a scale factor (to represent HDR data). We must tell Android
|
||||
// to not premultiply the RGB channels by the alpha channel
|
||||
// This is important, the alpha channel does not encode opacity but some
|
||||
// of the bits of an R11G11B10F image to represent HDR data. We must tell
|
||||
// Android to not premultiply the RGB channels by the alpha channel
|
||||
val opts = BitmapFactory.Options().apply { inPremultiplied = false }
|
||||
|
||||
// RGBM is always 4 bytes per pixel
|
||||
// R11G11B10F is always 4 bytes per pixel
|
||||
val faceSize = texture.getWidth(level) * texture.getHeight(level) * 4
|
||||
val offsets = IntArray(6) { it * faceSize }
|
||||
// Allocate enough memory for all the cubemap faces
|
||||
val storage = ByteBuffer.allocateDirect(faceSize * 6)
|
||||
|
||||
arrayOf("px", "nx", "py", "ny", "pz", "nz").forEach { suffix ->
|
||||
assets.open("$name/$prefix$suffix.rgbm").use {
|
||||
assets.open("$name/$prefix$suffix.rgb32f").use {
|
||||
val bitmap = BitmapFactory.decodeStream(it, null, opts)
|
||||
bitmap?.copyPixelsToBuffer(storage)
|
||||
}
|
||||
@@ -142,8 +140,8 @@ private fun loadCubemap(texture: Texture,
|
||||
|
||||
// Rewind the texture buffer
|
||||
storage.flip()
|
||||
android.util.Log.d("Texture", "Cubemap level: $level $faceSize ${texture.getWidth(level)}")
|
||||
|
||||
val buffer = Texture.PixelBufferDescriptor(storage, Texture.Format.RGBM, Texture.Type.UBYTE)
|
||||
val buffer = Texture.PixelBufferDescriptor(storage,
|
||||
Texture.Format.RGB, Texture.Type.UINT_10F_11F_11F_REV)
|
||||
texture.setImage(engine, level, buffer, offsets)
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.11'
|
||||
ext.kotlin_version = '1.3.31'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.4.0'
|
||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.11'
|
||||
ext.kotlin_version = '1.3.31'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.4.0'
|
||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
||||
@@ -26,7 +26,7 @@ preBuild.dependsOn generateIbl
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
defaultConfig {
|
||||
applicationId "com.google.android.filament.ibl"
|
||||
applicationId "com.google.android.filament.material_builder"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 28
|
||||
versionCode 1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.android.filament.ibl">
|
||||
package="com.google.android.filament.material_builder">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.filament.ibl
|
||||
package com.google.android.filament.material_builder
|
||||
|
||||
import android.content.res.AssetManager
|
||||
import android.graphics.BitmapFactory
|
||||
@@ -60,13 +60,12 @@ private fun loadIndirectLight(
|
||||
assets: AssetManager,
|
||||
name: String,
|
||||
engine: Engine): Pair<IndirectLight, Texture> {
|
||||
val (w, h) = peekSize(assets, "$name/m0_nx.rgbm")
|
||||
val (w, h) = peekSize(assets, "$name/m0_nx.rgb32f")
|
||||
val texture = Texture.Builder()
|
||||
.width(w)
|
||||
.height(h)
|
||||
.levels(log2(w.toFloat()).toInt() + 1)
|
||||
.format(Texture.InternalFormat.RGBA8)
|
||||
.rgbm(true)
|
||||
.format(Texture.InternalFormat.R11F_G11F_B10F)
|
||||
.sampler(Texture.Sampler.SAMPLER_CUBEMAP)
|
||||
.build(engine)
|
||||
|
||||
@@ -101,13 +100,12 @@ private fun loadSphericalHarmonics(assets: AssetManager, name: String): FloatArr
|
||||
}
|
||||
|
||||
private fun loadSkybox(assets: AssetManager, name: String, engine: Engine): Pair<Skybox, Texture> {
|
||||
val (w, h) = peekSize(assets, "$name/nx.rgbm")
|
||||
val (w, h) = peekSize(assets, "$name/nx.rgb32f")
|
||||
val texture = Texture.Builder()
|
||||
.width(w)
|
||||
.height(h)
|
||||
.levels(1)
|
||||
.format(Texture.InternalFormat.RGBA8)
|
||||
.rgbm(true)
|
||||
.format(Texture.InternalFormat.R11F_G11F_B10F)
|
||||
.sampler(Texture.Sampler.SAMPLER_CUBEMAP)
|
||||
.build(engine)
|
||||
|
||||
@@ -122,19 +120,19 @@ private fun loadCubemap(texture: Texture,
|
||||
engine: Engine,
|
||||
prefix: String = "",
|
||||
level: Int = 0) {
|
||||
// This is important, in the RGBM format the alpha channel does not encode
|
||||
// opacity but a scale factor (to represent HDR data). We must tell Android
|
||||
// to not premultiply the RGB channels by the alpha channel
|
||||
// This is important, the alpha channel does not encode opacity but some
|
||||
// of the bits of an R11G11B10F image to represent HDR data. We must tell
|
||||
// Android to not premultiply the RGB channels by the alpha channel
|
||||
val opts = BitmapFactory.Options().apply { inPremultiplied = false }
|
||||
|
||||
// RGBM is always 4 bytes per pixel
|
||||
// R11G11B10F is always 4 bytes per pixel
|
||||
val faceSize = texture.getWidth(level) * texture.getHeight(level) * 4
|
||||
val offsets = IntArray(6) { it * faceSize }
|
||||
// Allocate enough memory for all the cubemap faces
|
||||
val storage = ByteBuffer.allocateDirect(faceSize * 6)
|
||||
|
||||
arrayOf("px", "nx", "py", "ny", "pz", "nz").forEach { suffix ->
|
||||
assets.open("$name/$prefix$suffix.rgbm").use {
|
||||
assets.open("$name/$prefix$suffix.rgb32f").use {
|
||||
val bitmap = BitmapFactory.decodeStream(it, null, opts)
|
||||
bitmap?.copyPixelsToBuffer(storage)
|
||||
}
|
||||
@@ -142,8 +140,8 @@ private fun loadCubemap(texture: Texture,
|
||||
|
||||
// Rewind the texture buffer
|
||||
storage.flip()
|
||||
android.util.Log.d("Texture", "Cubemap level: $level $faceSize ${texture.getWidth(level)}")
|
||||
|
||||
val buffer = Texture.PixelBufferDescriptor(storage, Texture.Format.RGBM, Texture.Type.UBYTE)
|
||||
val buffer = Texture.PixelBufferDescriptor(storage,
|
||||
Texture.Format.RGB, Texture.Type.UINT_10F_11F_11F_REV)
|
||||
texture.setImage(engine, level, buffer, offsets)
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.filament.ibl
|
||||
package com.google.android.filament.material_builder
|
||||
|
||||
import java.io.InputStream
|
||||
import java.nio.ByteBuffer
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.filament.ibl
|
||||
package com.google.android.filament.material_builder
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.app.Activity
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.filament.ibl
|
||||
package com.google.android.filament.material_builder
|
||||
|
||||
import android.content.res.AssetManager
|
||||
import android.util.Log
|
||||
@@ -1,13 +1,13 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.11'
|
||||
ext.kotlin_version = '1.3.31'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.4.0'
|
||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.11'
|
||||
ext.kotlin_version = '1.3.31'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.4.0'
|
||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
||||