Compare commits

..

99 Commits

Author SHA1 Message Date
prideout
073a6c7696 Prepare for a new npm release. 2019-07-03 11:26:49 -07:00
Philip Rideout
b30f6e5332 gltfio: JavaScript friendly error message for glb files. 2019-07-03 10:20:17 -07:00
Philip Rideout
384651e21a gltfio: fix JavaScript utility for glb files. 2019-07-03 10:20:17 -07:00
Philip Rideout
22dcdc770f gltfio: fix issue with bounding box computation.
If the client opts in to "recomputeBoundingBoxes", then we manually
compute a bounding box that ignores the glTF min / max annotations.

This computation was erroneously including the transform of the injected
root node, which is not part of the model.

This could cause a problem when creating the asset, then immediately
positioning it with its injected root node before the ResourceLoader
is done downloading vertex buffers.
2019-07-03 10:20:17 -07:00
Philip Rideout
fd4d6c0d44 Use std::move in MeshAssimp.
Tested this via material_sandbox, seems to be fine.

Fixes #1366.
2019-07-02 14:20:55 -07:00
Philip Rideout
ca5b52b2ce Add JavaScript / TypeScript support for RenderTarget. 2019-07-02 13:26:56 -07:00
Ben Doherty
cc4e9db81b Fix spherical harmonics parsing (#1370) 2019-07-02 12:54:52 -07:00
Ben Doherty
2bfea16459 Update usage of KtxUtility in iOS projects (#1371) 2019-07-02 12:33:55 -07:00
Philip Rideout
927662ea4d Add JNI for KTX, simplify the bloom Android demo. 2019-07-02 11:02:45 -07:00
Ben Doherty
5b2dc1d3de Link against IBL library in iOS projects, update README (#1369) 2019-07-02 10:43:54 -07:00
Ben Doherty
097feb0372 Delete accidentally committed file (#1368) 2019-07-02 09:58:48 -07:00
Romain Guy
9cd2971b65 Fix typo in documentation 2019-07-01 17:58:03 -07:00
Ben Doherty
fb16516480 Post-process materials: add post-process variant enum, split writeChunks function (#1365) 2019-07-01 12:57:41 -10:00
Mathias Agopian
76027cab85 fix a JobSystem bug in waitAndRelease()
We were not checking for jobs to execute during waitAndRelease(), so
this thread would essentially not participate to the work pool.
2019-07-01 14:25:26 -07:00
Mathias Agopian
64c95c615a Fix a theoretical wrapping around issue in WSDQ
The Work-stealing dequeue indices could wrap around after ~2 billion
calls to steal(). This could probably be achieved in a few hours.
By using 64-bits indices, we avoid the problem entirely.
2019-07-01 14:25:26 -07:00
Mathias Agopian
31745f6025 fix benchamrk JobSystem de-initialization
JobSystem's API requires to call emancipate() for each adopt() before
destroying the JobSystem.
2019-07-01 14:25:26 -07:00
Ben Doherty
2a8f04c791 Limit material compilation to supported backends (#1359) 2019-07-01 10:05:00 -10:00
Philip Rideout
3fdecfdefa gltf_viewer should not crash when there is no IBL. 2019-06-28 15:40:43 -07:00
Philip Rideout
26cbef7452 Fix intermittent cmgen crash. 2019-06-28 14:49:40 -07:00
Romain Guy
571a9b1ff3 Update README 2019-06-28 13:52:52 -07:00
Romain Guy
b84117eb92 Update READMEs 2019-06-28 13:51:57 -07:00
Romain Guy
6af0c72d0d Add missing getter in IndirectLight (#1356)
This change also factors a bunch of assert methods in a single place
which should slightly decrease binary size.
2019-06-28 13:38:51 -07:00
Mathias Agopian
12fde30f31 better comments and potential fix for work-stealing dequeue
It's better to use std::memory_order_seq_cst in pop() and
steal() because we rely on ordering of access to
mTop and mBottom members.
2019-06-28 13:08:56 -07:00
Philip Rideout
56c2d6338e Add spherical harmonics parser, reduce code duplication.
This uses strtof rather than stringstream and provides a common location
that can be leveraged by the upcoming JNI bindings.

Note that this new method lives in KtxBundle rather than KtxUtility. The
latter creates Filament textures and therefore does not get built into
libimage.
2019-06-28 11:10:04 -07:00
Romain Guy
10c8ff352d Try with clang 7.0.1 on Windows 2019-06-27 10:52:48 -07:00
Romain Guy
53ea1a00ec Fix warnings 2019-06-27 10:46:52 -07:00
Romain Guy
62a458099a Fix more warnings 2019-06-27 09:56:43 -07:00
Romain Guy
826d52bca2 Fix Windows build and warnings 2019-06-27 09:18:31 -07:00
Romain Guy
299a600377 Add CMake to PATH during install 2019-06-26 19:02:21 -07:00
Romain Guy
a4ebf23baa Update PATH 2019-06-26 18:53:05 -07:00
Romain Guy
d23a703ca5 Echo on again 2019-06-26 18:45:47 -07:00
Romain Guy
2beb9c5588 Don't update PATH 2019-06-26 18:40:43 -07:00
Romain Guy
a7fc4d8fbb Update PATH 2019-06-26 18:28:48 -07:00
Romain Guy
a5dc89b071 Don't use refreshenv 2019-06-26 18:18:16 -07:00
Philip Rideout
2bfec9f4af gltfio: Disable file formats that we do not need.
This only removes 40k but at least it is easy.
2019-06-26 18:15:02 -07:00
Romain Guy
1aa7fac8c2 Remove ci-common 2019-06-26 18:03:58 -07:00
Romain Guy
c01107fd52 Exit from the if statement to see what's going on 2019-06-26 17:55:43 -07:00
Romain Guy
5b27361ef0 Try with LLVM 6 2019-06-26 17:47:41 -07:00
Romain Guy
494ddc10e4 More logging 2019-06-26 17:36:24 -07:00
Mathias Agopian
6151f78d28 Update RELEASE_NOTES.md 2019-06-26 17:29:46 -07:00
Romain Guy
46c67632c7 Add logging to test Windows build 2019-06-26 17:28:33 -07:00
Philip Rideout
3f7cf2f971 Increase epsilon in test_cmgen. 2019-06-26 16:46:57 -07:00
Mathias Agopian
84cc8ff9c8 update release notes 2019-06-26 16:05:30 -07:00
Mathias Agopian
921c2bcd61 mitigate overhead of jobsystem
For jobs with that do very little work, the jobsystem can introduce
a lot of overhead, we mitigate this by:

- don't wake-up worker threads when scheduling several very small jobs,
like when scheduling the per-face jobs. 

- don't wait for per-face jobs to finish -- we only did that to avoid
a copy of the job's data.

- don't use multi-threading at all if the job has too little work. We
evaluate the work using the scanline length and number of samples.
2019-06-26 16:05:30 -07:00
Mathias Agopian
6ea8ed07ed a few libibl optimizations 2019-06-26 16:05:30 -07:00
Mathias Agopian
a5addd2257 convert libibl from double to float
since libibl is now used online, it makes more sense to do all the
math in float instead of double. It doesn't seem to impact quality.
2019-06-26 16:05:30 -07:00
Mathias Agopian
8b1d4ee06a a way to fold mirroring with prefiltering 2019-06-26 16:05:30 -07:00
Mathias Agopian
3e23d9742b fixup: remove code that wasn't supposed to be comited 2019-06-26 16:05:30 -07:00
Romain Guy
847d7dd71a Fix various errors discovered by clang-tidy (#1351)
- Move the static function declared in MaterialVariants.h to the .cpp
- Fix several use-after-move that were horribly wrong
2019-06-26 15:25:58 -07:00
Philip Rideout
10dc3a24e8 Add Kotlin sample for gltfio and custom render targets. 2019-06-26 13:55:23 -07:00
Romain Guy
c6c1cfef3c Small cleanups 2019-06-26 12:43:37 -07:00
Romain Guy
cc8a2f736b Fix progress bars display in cmgen 2019-06-26 12:43:37 -07:00
Philip Rideout
7fcd3e1a4f Java clients can now get material instances from renderables.
Discussed this feature with Mathias, we decided to create
MaterialInstance Java wrappers on the fly, and create Material Java
wrappers lazily. This is simple and avoids caching the wrapper objects,
which might otherwise lead to complexity and bugs.

Note that gltfio creates material instances behind the scenes, so this
feature is particularly useful for gltfio clients.
2019-06-25 19:47:49 -07:00
Philip Rideout
481fe5a087 Fix build break of gltfio-android. 2019-06-25 16:31:30 -07:00
Philip Rideout
2d690ac585 Add View::getRenderTarget to JNI. 2019-06-25 16:31:25 -07:00
Philip Rideout
a118299cfb Fix JNI for parameter arrays in MaterialInstance.
Previously we used the <T=float> template instantiation of setParameter
when the client specified FLOAT4. This resulted in the lower layer
adding needless padding, thus causing a buffer overflow.

Moreover the JNI code for this was somewhat cryptic because it casted an
enum value to an int, then added 1 to compute the size. We now use
a switch statement to improve readability.

This issue was discovered (and the fix was verified) with the upcoming
Android port of the bloom demo.
2019-06-25 15:32:30 -07:00
Mathias Agopian
bc01475920 optimize libibl for smaller workloads
We now never process mirroring or mipmaping with multithreading
it's just not worth it given the overhead of the jobsystem.

We also require 64 lines per job, below that, we only multithread per
face (6 threads). This should probably depends on the sample count,
but we don't have this facility yet.

Special case downsampling for mipmaping.

This alone improves performance by 2x for small cubemaps (e.g. 16x16).
2019-06-25 15:08:15 -07:00
Mathias Agopian
56e9d8eda5 Utility to prefilter an environment at runtime
This adds a utility function on IndirectLight populate the reflection
map from an environment at runtime. This performs some processing
similar to cmgen, albeit at a reduced quality.
2019-06-25 15:08:15 -07:00
Mathias Agopian
902e7021fd libibl doesn't use its own JobSystem instance 2019-06-25 15:08:15 -07:00
Adrian Perez
1773c42398 Comment fixes (#1346) 2019-06-25 13:42:52 -07:00
Philip Rideout
ae88536f0c Fix GL_INVALID_OPERATION in the default IBL.
In commit d955e73 we changed the default IBL from RGBM to RGB, but we
kept its internal format of RGBA8. Since the internal format is not
compatible with the data format, we see GL_INVALID_OPERATION during the
texture upload.

This is a single-pixel black texture, so the format does not really
matter, but this clears up a GL error seen on some platforms.
2019-06-24 13:22:34 -07:00
Philip Rideout
b4d6583901 Fix up WebGL bindings after RGBM removal. 2019-06-24 13:22:34 -07:00
Philip Rideout
b31e420064 Fix GL_INVALID_OPERATION in the default IBL.
In commit d955e73 we changed the default IBL from RGBM to RGB, but we
kept its internal format of RGBA8. Since the internal format is not
compatible with the data format, we see GL_INVALID_OPERATION during the
texture upload.

This is a single-pixel black texture, so the format does not really
matter, but this clears up a GL error seen on some platforms.
2019-06-24 13:21:45 -07:00
Philip Rideout
e4e439e2bf Fix build break. 2019-06-21 18:48:40 -07:00
Philip Rideout
a79a83d6da gltfio: gracefully error when mesh uses draco. 2019-06-21 16:12:59 -07:00
Philip Rideout
50d4dc6499 Update cgltf. 2019-06-21 14:51:41 -07:00
Philip Rideout
cbc662085e cgltf: expose extension lists 2019-06-21 14:51:41 -07:00
Philip Rideout
02a5541fed gltfio: minor improvements to error handling. 2019-06-21 10:09:57 -07:00
Romain Guy
14248621fe Workaround for a Mali driver bug (#1337)
Fixes #1320
2019-06-21 09:57:50 -07:00
Romain Guy
8c299d7b0b Update documentation to fix #1336 2019-06-21 09:29:49 -07:00
Ben Doherty
57d6bdff1b Allow mutliple API flags in matc (#1327) 2019-06-21 09:27:49 -07:00
Romain Guy
957ec9be60 Use R11G11B10F instead of RGBM in Android sample apps (#1333) 2019-06-20 16:31:17 -07:00
Philip Rideout
76147a7231 gltfio: fix bug with colliding TANGENT buffers.
ResourceLoader was mistakenly assuming that all primitives in the
entire model have TANGENTS in the same slot index.

Fixes #1326.
2019-06-20 16:29:22 -07:00
Philip Rideout
eff3d1a09b gltfio: show warning for missing normals. 2019-06-20 16:29:22 -07:00
Mathias Agopian
5f6d7a279c fix some warnings 2019-06-20 16:19:02 -07:00
Mathias Agopian
9bce361b3e Remove RGBM support entirely from filament.
⚠️ this break c++ and java source compatibility
2019-06-20 16:17:27 -07:00
Mathias Agopian
925e414e7b fix cmgen test 2019-06-20 15:19:59 -07:00
Mathias Agopian
aeec6f2df5 skygen handles rgb_11_11_10 2019-06-20 14:36:37 -07:00
Mathias Agopian
9358650bd4 remove generated test ibls
we're not using them in the build and they can easily get out of date.
2019-06-20 14:36:37 -07:00
Mathias Agopian
54d44a76a7 fix linux builds 2019-06-20 14:36:37 -07:00
Mathias Agopian
cc22183f20 update samples/envs 2019-06-20 14:36:37 -07:00
Mathias Agopian
2ded1c955f cmgen and filament now support RGB_10_11_11_REV
- RGB_11_11_10 is exported in a RGBA PNG file where the 4 channels are
  used as a uint32 storing a RGB_10_11_11_REV pixel.
  We use the .rgb32f extension, and those PNG files contain garbage 
  when seen in a PNG viewer.

- This is now the default for the -x option.

- compressed KTX files don't encode RGBM, which means they can't
  support HDR, unless an HDR compression scheme is used.
2019-06-20 14:36:37 -07:00
Mathias Agopian
d955e733bf remove RGBM support for skybox and ibl cubemap 2019-06-20 14:36:37 -07:00
Mathias Agopian
99a501f0c3 fix s3tc compression with HDR input
HDR input where producing garbage pixels, instead we saturate.
2019-06-20 14:36:37 -07:00
Ben Doherty
cdb2b47e0f Add material domains boilerplate (#1305) 2019-06-20 08:53:36 -07:00
joetoth
366e20cbe8 Compile gltfio with -fPIC 2019-06-19 19:34:25 -07:00
Philip Rideout
d5179bd9ed Fix JsonishParser to handle parameter arrays. 2019-06-19 15:32:40 -07:00
Philip Rideout
12506784da Expose texture usage flags to Java / Kotlin. 2019-06-19 15:32:26 -07:00
Romain Guy
4fee4d8da2 Don't use clear coat roughness as base roughness if clear coat is 0 (#1323)
This change finds the max of the clear coat and base layer roughness
then lerps the base layer roughness according to the amount of clear
coat.
2019-06-19 15:22:09 -07:00
Romain Guy
b1242163f7 Make CMake 3.10 the minimum version, add LTO option (#1316)
* Make CMake 3.10 the minimum version, add LTO option

* Install a newer CMake on Linux CI builds

* Update LLVM and Cmake on Windows CI

* Update build/windows/ci-common.bat

Co-Authored-By: Ben Doherty <benjdoherty15@gmail.com>

* Update formatting

* Apply suggestions from code review

* Update build/windows/ci-common.bat

* Update CMake

* Switch Android projects back to CMake 3.6
2019-06-19 12:53:03 -07:00
Mathias Agopian
8cd44fb2e8 rework math::half to be more generic
We introduce a templated fp<> class that can represent any float
format and convert to/from float32.
2019-06-19 12:22:01 -07:00
Romain Guy
33a8c9da7e Don't enable specularAO and multiBounceAO by default on mobile (#1319) 2019-06-19 11:04:40 -07:00
Pixelflinger
37facf7f7b fix build breakage on OpenGL ES targets 2019-06-19 01:25:37 -07:00
Mathias Agopian
1d20973363 IBL cubemaps can now be any size.
⚠️ breaks materials

There used to be a constraint that ibl cubemap needed to be
256x256. This constraint is now relaxed. IBL cubemaps can be any size.

We also add 16 float4 of padding to the frameUniform, which brings
its size to 1 KiB, the idea is to prevent more breakages in the
future.
2019-06-18 18:39:06 -07:00
Ben Doherty
0cb08cd114 Add mipmap level selection to Metal render targets (#1310) 2019-06-18 16:13:04 -07:00
Philip Rideout
c97ba45eed Fix several bugs in the gltfio JNI build. 2019-06-18 13:53:45 -07:00
Philip Rideout
74fcc456dc gltfio-android code review changes. 2019-06-18 13:53:45 -07:00
Philip Rideout
b17d606ed2 Introduce JNI bindings for gltfio.
For now this uses gltfio in the ubershader configuration in order
to avoid the filamat dependency. Note that we have not yet done a size
analysis of the `gltfio_core` library.

New Kotlin-based sample app is forthcoming.
2019-06-18 13:53:45 -07:00
Philip Rideout
3e97ac5268 Add Scene::getEntities to JNI. 2019-06-17 15:17:37 -07:00
716 changed files with 5501 additions and 1643 deletions

View File

@@ -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
# ==================================================================================================

View File

@@ -43,13 +43,23 @@ Here are a few sample materials rendered with Filament:
![Damaged Helmet](docs/images/samples/model_damaged_helmet.jpg)
![Helmet](docs/images/samples/model_helmet.jpg)
![Brushed copper](docs/images/samples/brushed_copper_2.jpg)
![Chess set](docs/images/samples/chess1.jpg)
![Material 1](docs/images/samples/material_01.jpg)
![Material 2](docs/images/samples/material_02.jpg)
![Material 3](docs/images/samples/material_03.jpg)
![Material 6](docs/images/samples/material_06.jpg)
![Material 8](docs/images/samples/material_08.jpg)
## Applications
Here are a few screenshots of applications that use Filament in production:
### Google Maps AR Navigation
![Google Maps AR Navigation](docs/images/samples/app_gmm_ar_nav.jpg)
### Google Search 3D/AR Viewer on Android
![Google Search 3D/AR Viewer on Android](docs/images/samples/app_google_3d_viewer.jpg)
## 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

View File

@@ -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.

View File

@@ -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)
}
}

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.4.1)
cmake_minimum_required(VERSION 3.6)
set(FILAMENT_DIR ${FILAMENT_DIST_DIR})

View File

@@ -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'
}
}

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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

View File

@@ -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'
}
}

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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,

View File

@@ -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) {

View File

@@ -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
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -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;
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -65,7 +65,7 @@ public class Renderer {
flags);
}
/** @deprecated */
@Deprecated
public void mirrorFrame(
@NonNull SwapChain dstSwapChain, @NonNull Viewport dstViewport,
@NonNull Viewport srcViewport, int flags) {

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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
View File

@@ -0,0 +1,11 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
/.idea/caches
/.idea/gradle.xml
.DS_Store
/build
/captures
.externalNativeBuild

View 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
)

View 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'
}

Binary file not shown.

View 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
View 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
View 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

View File

@@ -0,0 +1,4 @@
LIBGLTFIO {
global: Java_com_google_android_filament_*; JNI*;
local: *;
};

View File

@@ -0,0 +1 @@
_Java_com_google_android_filament_*

View 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'

View 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" />

View 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);
}

View 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);
}

View 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);
}

View 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;
}

View 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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -46,6 +46,12 @@ host machine:
![Material Builder](../../docs/images/samples/sample_image_based_lighting.jpg)
### `gltf-bloom`
Demonstrates how to load glTF models and render to an offscreen buffer:
![glTF Bloom](../../docs/images/samples/sample_gltf_bloom.jpg)
## 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
View 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

View File

@@ -0,0 +1 @@
/build

View 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'
}

View 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

View 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>

View File

@@ -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
}

View File

@@ -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
}
}
}

View 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());
}
}

View 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;
}
}

View 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);
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -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>

View File

@@ -0,0 +1,3 @@
<resources>
<string name="app_name">gltf bloom</string>
</resources>

View File

@@ -0,0 +1,8 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
<!-- Customize your theme here. -->
</style>
</resources>

View 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
}

View 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

Binary file not shown.

View 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
View 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
View 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

View File

@@ -0,0 +1,4 @@
includeBuild '../../filament-android'
includeBuild '../../gltfio-android'
include ':app'

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

Some files were not shown because too many files have changed in this diff Show More