Compare commits

...

261 Commits

Author SHA1 Message Date
Ben Doherty
1a66f85b67 Update RELEASE_NOTES for 1.4.5 2020-01-27 12:59:35 -08:00
Romain Guy
3bba92f813 Fix build message 2020-01-27 12:03:56 -08:00
Philip Rideout
93c9674e2a Fix WebGL build. 2020-01-27 11:37:17 -08:00
John Davis
a4b879227d fix case sensitivity problem for linux 2020-01-26 19:17:57 -08:00
Philip Rideout
485dfa6cde Fix typo. 2020-01-24 20:51:31 -08:00
Mathias Agopian
3105a8330e remove unneeded includes in public headers
Replace with forward declarations if needed and includes in .cpp that
now need them.
The idea here is to have our headers have the least amount of impact as
possible on our clients (e.g. compilation time).
2020-01-24 12:13:48 -08:00
Mathias Agopian
88e8661bf3 New API to import textures into filament
If you need this, you know who you are.
The new Texture::Builder::import() allows to specify a OpenGLES texture
id from a shared GL context, effectively importing the texture into
filament.
The texture is NOT destroyed when calling Engine::destroy(Texture*), only
its filament handle.
2020-01-24 12:13:20 -08:00
Mathias Agopian
3a9629d93c Fix a NOOP backend threading bug (#2064)
The NOOP backend didn’t call user-API callbacks from the main thread
(instead calling them from the “backend thread”). This caused problems
with unit tests for instance.
2020-01-23 14:55:25 -10:00
Mathias Agopian
29c14b1053 Fix typo in documentation (#2065)
lastest -> latest
2020-01-23 14:55:09 -10:00
Philip Rideout
bd5aeb6b69 Allow non-WebGL builds to disable threads. 2020-01-23 11:06:17 -08:00
Philip Rideout
3674361f20 ModelViewer now automatically detaches. 2020-01-23 09:55:51 -08:00
Philip Rideout
4a29456a7a ModelViewer now works with TextureView. 2020-01-23 09:55:51 -08:00
Philip Rideout
3179a83cfb Android: introduce ModelViewer helper.
This reduces the LOC of our gltf-viewer app from 260 to 146. This could
have been more, but I feel this provides good balance between
flexibility and convenience.

The raw gltfio API involves multiple objects (FilamentAsset,
AssetLoader, ResourceLoader) whereas the ModelViewer has a simple facade
consisting of two methods, one for GLB and one for GLTF. The underlying
gltfio objects are available via non-settable properties.
2020-01-23 09:55:51 -08:00
Ben Doherty
5fe1fe73c4 Use Objective-C availability tests for Metal backend (#2046) 2020-01-23 09:16:19 -08:00
Philip Rideout
5025d8eb6e Remove usage of the invariant keyword. 2020-01-21 14:42:58 -08:00
Philip Rideout
71697b59a3 Disable depth prepass everywhere.
Fixes #737 and #1472. See also #475 and #1295.
2020-01-21 14:42:58 -08:00
Philip Rideout
518ae9658f gltfio + Android: improve memory management.
Add bindings for releaseSourceAsset() and fix a double-free issue.

According to the Android Studio profiler, this makes Java memory usage
go from 18.6 MB to 6.5 MB.
2020-01-21 13:01:55 -08:00
Philip Rideout
41ad8b5c18 Remove unused copy of the parquet PNG. 2020-01-21 12:58:46 -08:00
Philip Rideout
51cef3b5ca WebGL: unify the PNG and JPEG codepaths.
Fixes #2055.
2020-01-21 12:58:46 -08:00
Philip Rideout
491d16a4e5 Exercise JPG decoding in web samples. 2020-01-21 12:58:46 -08:00
Philip Rideout
e752b6fb6f Factor STB config into a header. 2020-01-21 12:58:46 -08:00
Philip Rideout
46bf6fbfdd Simplify sample-gltf-viewer as much as possible. 2020-01-21 12:57:50 -08:00
Philip Rideout
fd5fe3d18d Convert KtxLoader to Kotlin and remove usage of reflection.
Fixes #1510
2020-01-21 12:57:09 -08:00
Philip Rideout
ca2da39614 Migrate TextureLoader to filament-utils. 2020-01-21 07:59:51 -08:00
Philip Rideout
067dad2d38 camutils: rename internal enums. 2020-01-17 11:37:57 -08:00
Philip Rideout
f91a8890a6 camutils: fix bad defaults in Manipulator. 2020-01-17 11:37:10 -08:00
Philip Rideout
dd9b84f06e GestureDetector cleanup. 2020-01-17 10:45:17 -08:00
Philip Rideout
9ac17a88b3 Add new sample for glTF models and the camera manipulator.
This differs from the bloom demo in that it supports touch interaction,
has animation, loads from GLTF rather than GLB, and is overall simpler.
2020-01-17 09:09:46 -08:00
Philip Rideout
9ea8148d84 Add doubles to Manipulator for convenience. 2020-01-17 09:09:46 -08:00
Romain Guy
16c65550bb Fix javadoc syntax 2020-01-16 17:27:06 -08:00
Philip Rideout
961860adee Introduce filament-utils and Java bindings for camutils.
This library houses the KTX loader, camutils bindings, and a Kotlin math
library. More will come later. Sample app is forthcoming.
2020-01-16 16:00:23 -08:00
Philip Rideout
6146b4d2d9 Fix out-of-bounds when glTF has many UV sets.
glTF specifies that client implementations must support at least two UV
texture coordinate sets but does not seem to have an upper limit.

We use a mapping table in order to honor high-numbered UV set indices,
but our mapping table only accomodates 8 entries.

Fixes #2042
2020-01-16 14:09:48 -08:00
Philip Rideout
274cd3a1f3 Refactor some Android build things for gltfio.
We currently use static linking and will continue to do so. This means
that libfilament-jni is a subset of of libgltfio-jni, and libgltfio-jni
will become a subset of the upcoming libutils-jni.

This is a simple layer cake, but requires adding some CMake logic to the
gltfio-android CMakeLists, similar to what we already did for the
filament-android CMakeLists. This prevents an obscure CMake error about
duplicated build artifacts.

Also, previously we required clients to call AssetLoader#init(), this
is now renamed to Gltfio#init(), which is more consistent with
Filament#init().
2020-01-16 10:11:36 -08:00
Romain Guy
762e8b8b6a Add more control to surface ordering (#2041)
When UiHelper is set to translucent with setOpaque(false), the
target SurfaceView's surface is set to be composited on top of
the activity's window. There are situations however where one
may want to render regular Views on top of the SurfaceView.

The new setMediaOverlay() API allows exactly that: when this
property is enabled, rendering to a translucent target will
cause the SurfaceView's surface to be composited above other
surfaces, but below the activity's surface.
2020-01-16 10:00:26 -08:00
Philip Rideout
a5a6e9be8a Add animated GLTF model to third_party.
This asset will be used in an upcoming Android sample. I converted the
textures from PNG to JPG to reduce the footprint.
2020-01-15 16:56:46 -08:00
Philip Rideout
4ab65975f4 Update Android Studio required version. 2020-01-15 11:22:57 -08:00
BStringhamVRSK
041f26a7c5 Implemented sRGB support for DXT encoded textures (#2026)
* Added sRGB support for DXT compressed textures - OpenGL

* Added sRGB support for DXT compressed textures - Vulkan and Metal

* Added detection if OpenGL driver supports sRGB compressed textures (EXT_texture_sRGB extension)

* Fixed whitespace to use spaces rather than tabs

* Test for GL_EXT_texture_sRGB or GL_EXT_texture_compression_s3tc_srgb support for sRGB DXT compressed textures

* GL ES uses GL_EXT_texture_compression_s3tc_srgb instead of GL_EXT_texture_sRGB
2020-01-15 10:26:29 -08:00
Mathias Agopian
b351e709c1 Framegraph improvements
- added a way to compare two handle's underlaying resource
  (i.e. do they refer to the same resource)

- minor refactoring and comment fixes
2020-01-15 10:22:10 -08:00
Mathias Agopian
fbad683810 Implement a "black board" for the framegraph
FrameGraph always keeps a default Blackboard, but additional ones 
can be created if needed.

A blackboard is just a registry of FrameGraphHandles, queryable by name.
2020-01-15 10:22:10 -08:00
Philip Rideout
2854c0627d camutils: add support for Builder pattern.
This makes the upcoming Java bindings simpler and improves parity with
existing API conventions.

Note that camutils does not depend on filament and therefore cannot use
BuilderBase.

Note that the Manipulator Builder state is public which breaks with
convention but makes implementation simple and allows C++ clients to
continue using modern initializer syntax if they wish.
2020-01-14 15:26:22 -08:00
Mathias Agopian
c5fa6fe7f2 More fixes to sampled textures in the framegraph
The main purpose of this change is to fix a problem where a resource
marked as sampleable by a *culled* pass would stay sampleable.
This happened because the sampleable state was tracked on the resource
itself.

We fix this by treating sample() just like read(), such resources are
added to an array living in the pass, which ensures the state is correct
when passes are culled.

Also fixed:
- simplified read() code a bit (minor)
- simplified resource aliasing code
- don't resolve() renderTargets of culled passes
2020-01-14 11:16:34 -08:00
Mathias Agopian
40c7232bb2 revert part of a recent TransformManager change
setParent() is not supposed to reorder child/parents in the array
because it doesn't rely on them being orderer. This also has the
advantage of not invalidating Instances.

However, commitLocalTransformTransaction() does rely on child/parent
ordering and the previous change did fix that.
2020-01-14 11:16:07 -08:00
Ben Doherty
59e3465b6b Update Assimp to 5.0.1 (#2027) 2020-01-13 15:00:27 -08:00
tpsiaki
2c591d2dca Correct out-of-order transform instances (#2025)
The current code only updates the order in the transaction commit if there's a single out-of-order node in the scene graph, but if multiple are out of order (or one swap doesn't fully fix the ordering), then we end up with out of order scenes, and incorrect world transforms.

Additionally, when nodes are reparented outside of a transaction, the order is not updated.
2020-01-13 13:22:49 -08:00
Mathias Agopian
4673545f45 Fix a multisample related bug in the FrameGraph
The FrameGraph would erroneously specify a sample count on textures
that are sampleable and used as an attachment to a multisampled 
target -- however, that's not allowed.

We didn't run into issues, because had a workaround for this when
creating the texture. This is augmented by an assertion.
2020-01-13 11:29:14 -08:00
Mathias Agopian
4703a45ff5 Ensure we don't use RTTI when not available
also don't implement the graphviz export in release builds.
2020-01-13 11:28:50 -08:00
Mathias Agopian
35aabd5e44 Fix a couple minor issues in the OpenGLES backend
- we were not unbinding the renderbuffer int the right place,
  when it's created, instead we were doing that when using it the 
  first time. Unbinding soon makes sense because we never need to
  rebind it after that.

- in debug builds we were clearing render targets at creation time,
  but this was wrong because a render target won't necessarily be written
  (it could be used as the source of the blit for instance).
  This didn't cause any trouble in the framegraph, by chance, it was smart
  enough to reuse existing render targets in the case of blitting.
  Ideally we'd clear textures/renderbuffer at creation time,
2020-01-13 11:28:50 -08:00
Mathias Agopian
118944be9a Improve/simplify OpenGLDriver a bit
merge frameBufferRenderbuffer() and framebufferTexture() because
the filament API doesn't have a distinction. This actually removes
quite a bit of code too.
2020-01-13 11:28:50 -08:00
Mathias Agopian
8e1ecbb0ea Minor FrameGraph improvements
- write() is marked as [[nodiscard]] since it's
  generally an error to discard it

- graphviz export not display wether a texture resource is
an actual texture or renderbuffer
2020-01-13 11:28:50 -08:00
Romain Guy
00ba8c09f8 Rewrite Maven publish tasks to support multiple flavors (#2022)
* Rewrite Maven publish tasks to support multiple flavors

* Don't build filamat with an unused CMake option

* Don't compiler debug in release mode

* ... for real

* Link to BUILDING.md
2020-01-10 18:02:46 -08:00
Philip Rideout
15b071acaa gltfio: support external resources on Android.
This was untested because our only glTF Android sample uses glb instead
of JSON. We will soon be adding a new Android demo that uses an actual
gltf file.

This fixes #1841.
2020-01-10 09:15:38 -08:00
Romain Guy
aa3dfb9a4b Revert "Disable filamat-android's flavors for now"
This reverts commit 95e22d878a.
2020-01-09 19:17:50 -08:00
Romain Guy
95e22d878a Disable filamat-android's flavors for now 2020-01-09 17:49:30 -08:00
Philip Rideout
4f8c495563 Another gltf_bloom fixup. 2020-01-09 14:31:43 -08:00
Romain Guy
1d6ea1db0f Update README.md 2020-01-09 14:23:41 -08:00
Romain Guy
393cc5c634 Update README 2020-01-09 14:23:05 -08:00
Philip Rideout
34c2772a60 Remove unused source file. 2020-01-09 14:10:33 -08:00
Philip Rideout
4d258ab5e8 Remove a build output file. 2020-01-09 14:07:20 -08:00
Philip Rideout
a306f9074a Clean up gltf-bloom to prep for new gltf-viewer app.
This renames the app namespace and removes the unused Io file.
2020-01-09 13:49:24 -08:00
Philip Rideout
6e30566363 Bump version number in package.json 2020-01-09 12:33:17 -08:00
Romain Guy
2908224c95 Filament 1.4.4 2020-01-09 12:19:05 -08:00
Romain Guy
e011853e7e Update androidx.annotation to 1.1.0 2020-01-09 08:55:43 -08:00
Romain Guy
104105c937 Fix the build 2020-01-08 18:01:18 -08:00
Romain Guy
3fa98419a6 Add more .gitignore 2020-01-08 17:59:49 -08:00
Romain Guy
44d08ce41e Fixup javadocs 2020-01-08 17:55:17 -08:00
Mathias Agopian
0a1c1be00e Refactoring to allow rendering multi-pass rendering
specifically into the same render target.
2020-01-08 16:10:09 -08:00
Mathias Agopian
7efd7abffe Don't combine clearFlags when retrieving a rendertarget
Instead we use the clear flags that the user specified. This is needed
in the case where we're rendering in the target in two passes, the
first pass might want to clear the buffers, while the 2nd one will not.
If we were combining the clear flags, the first pass's flags would be
sticky and the view would always be cleared.

If combining is needed it must be specified by the user.
2020-01-08 16:10:09 -08:00
Mathias Agopian
e27158507e refactor Renderer to make it more flexible
This is in preparation to supporting screen-space effects.
There are two major changes:

- RenderPass is now copiable and intended to be passed by copy to
  the execute stage of frame graph passes

- The color pass is in its own function now


This actually simplify RenderPass api.
2020-01-08 16:10:09 -08:00
Romain Guy
d9ee2fa10d Use a proper Gradle plugin to generate Filament assets in samples (#2018) 2020-01-08 15:45:44 -08:00
Mathias Agopian
b30a7aa5a2 Make ResourceAllocator mockable and update test
We have one very important unit test that is supposed to make sure
the framegraph reuses the same rendertarget between 2 passes, this
unit test would always succeed when using the NoopDriver.
Now that we can mock the ResourceAllocator, we can ensure this unit
test is doing its job.
2020-01-08 15:39:40 -08:00
Mathias Agopian
34c1aaac18 improve cmgen prefiltered cubemaps
Rotate the sample pattern at every light direction, which trades
aliasing for noise (which is arguably more pleasant) for IBLs with
very high frequency (i.e. high level of HDR-ness).
2020-01-08 15:39:21 -08:00
Ben Doherty
8dbb4c6b7e Add new heightfield sample (#2004) 2020-01-08 11:55:28 -08:00
Romain Guy
f5d5afba74 Re-organize Android Gradle files (#2013)
* Re-organize Android Gradle files

Clean up our Gradle files, share versioning, etc. and prepare for
publication to sonatype.

* Use androix annotations for desktop

* Add samples as subprojects to root Gradle

* Fix build script

* Don't break when samples aren't compiled

* Better organize the Android Studio project
2020-01-07 18:37:45 -08:00
Philip Rideout
e09f0bb99f Repair gradle IBL path for gltf_bloom.
I broke this when I changed the cmgen KTX behavior.
2020-01-07 14:05:40 -08:00
Mathias Agopian
fddf51dc74 cmgen -d would force importance sampling mips generation 2020-01-06 17:43:11 -08:00
Mathias Agopian
b8d4b981e0 Better roughness remapping and comments
We were conflating two concepts in our comments about the roughness
remapping, which was confusing. Also changed the remapping so it 
matches a log2 mapping in our default configuration.
2020-01-06 17:42:56 -08:00
Daniel Lehmann
892302442f Fix Backend enum in Java to be consistent with C definition (#2006)
The C definition was changed to include METAL, moving NOOP further down.
The Java definition never caught up, making NOOP mean METAL and making the
real NOOP unreachable.

This patch puts them back in sync. Also, updated the Java comments to match
the comments from the C definition.
2020-01-06 16:27:15 -08:00
Philip Rideout
39046ddfe1 camutils: fix MSVC error. 2020-01-06 16:12:05 -08:00
Philip Rideout
ac14074bc4 camutils: flip zoom to match old manipulator. 2020-01-06 16:12:05 -08:00
Philip Rideout
7d548151d7 Introduce camutils library.
This moves the camera manipulator into its own library and adds new
functionality including a new "Google Maps" manipulator and a bookmark
feature to facilitate camera animation.

Java bindings and an Android sample will land later this week.
2020-01-06 16:12:05 -08:00
Philip Rideout
898ed70aa0 Remove <iostream> from math headers.
This speeds up our build time by using <iosfwd> and un-inlining the
vector print functions.
2020-01-06 15:09:06 -08:00
Romain Guy
78842b59c9 Only build FBX and OBJ importers (#2003) 2020-01-06 14:38:32 -08:00
Ben Doherty
f4f4f9ccd5 Implement flush for Metal backend (#1999) 2020-01-06 12:28:11 -08:00
Mathias Agopian
2ef9d72dbd Simply refraction code
This makes it easier to add new shapes and experiment.
Added a "sold box" shape that is not used yet.
2020-01-06 11:33:06 -08:00
Tim Psiaki
b030f67eb7 Make EntityManager and Panic dynamic-linkable. 2020-01-06 10:24:17 -08:00
Romain Guy
8380a87a6e Update HTML docs 2020-01-05 11:44:45 -08:00
Philip Rideout
06b9bb0c34 gltfio: honor node labels if they exist.
In glTF, multiple nodes can refer to the same mesh, and each node can be
assigned a unqiue string label. Previously we used NameComponentManager
to annotate entities with mesh labels rather than node labels. This was
wrong because Filament entities are 1:1 with nodes, not meshes.

We still fall back to mesh labels when node labels are not provided.
2020-01-03 10:13:59 -08:00
Philip Rideout
17893ecefd Repair Android extension pointers.
Fixes #1989 by fetching extension function pointers that were refactored
in #1977. Moved string-splitting utility to a common location so that
the base class and concrete classes can both use it.
2020-01-03 07:16:56 -08:00
Ben Doherty
efc1b01901 Respect colorWrite in Metal backend (#1996) 2020-01-02 13:36:59 -07:00
Ben Doherty
88fa93f1de Add support for ASTC textures on iOS / Metal (#1992) 2020-01-02 11:35:23 -07:00
Ben Doherty
36385a2432 Improve Metal textures (#1991) 2019-12-30 11:15:04 -07:00
brian.wang
1e05327c5d Fix compile error for VS 2019 16.4.2 with Vulkan (#1990) 2019-12-27 10:44:24 -07:00
Philip Rideout
0b7a08a2d8 Repair web samples by fixing typo in previous fix. 2019-12-18 18:06:21 -08:00
Philip Rideout
237e0ee367 Revert "Revert "gltfio: enable specular AO to "fix" #1870""
This reverts commit f9230856af.
2019-12-18 13:56:13 -08:00
Philip Rideout
f9230856af Revert "gltfio: enable specular AO to "fix" #1870"
This reverts commit 9bf9c3a439.
2019-12-18 13:17:52 -08:00
Philip Rideout
9bf9c3a439 gltfio: enable specular AO to "fix" #1870 2019-12-18 13:07:05 -08:00
Philip Rideout
25c4efd2db cmgen: do not create useless folder for KTX files
With KTX, we should simply create the specified output folder and put
the KTX file(s) in there. There is no need to create a subfolder of the
output folder.

This change also allows users to pick a custom name for their KTX file,
because we only use the "deployment" name when generating filenames.
2019-12-18 13:03:02 -08:00
Ben Doherty
8f6f0ef511 Add continuous build artifacts (#1978) 2019-12-16 10:38:57 -08:00
Pixelflinger
a924fbb490 Better roughness remapping for IBLs
This greatly improves the quality of semi-rough
materials.
2019-12-14 16:36:58 -08:00
Philip Rideout
4c01dfc9fd macOS: fix flash of red upon resize.
Previous to this change, we suffered from a flash-of-red followed by a
flash-with-wrong-projection every time we resized an OpenGL window.

SDL throttles the window resize events, so FilamentApp updates the View
only on the final low-level resize event. However we were calling
Cocoa's update method on every low-level resize event. Thus we were
showing uninitialized content during the resize.

FilamentApp recreates the SwapChain after the final resize event; one
reason for this is the fact that Vulkan swap chains must be recreated.

The fix is to defer the Cocoa update until the swap chain gets
recreated. This is the perfect time because FilamentApp has already set
the new Viewport at this point.
2019-12-14 09:29:35 -08:00
Mathias Agopian
5ee15239fd Split Android specific code out of PlatformEGL (#1977)
We now should be able to use PlatformEGL for all generic EGL platforms
(not tested though). Most texture streaming operations are not supported
in that case, since they're platform specific.
2019-12-13 14:23:19 -08:00
Philip Rideout
69d36b0226 WebGL: fix usage of direction estimator. 2019-12-13 12:46:11 -08:00
Philip Rideout
87db1aaa57 WebGL: remove old broken test. 2019-12-13 12:46:11 -08:00
Philip Rideout
5e096de534 Disable rounding FBO sizes on WebGL. 2019-12-13 12:46:11 -08:00
Philip Rideout
97d53bf7e9 Remove warnings about deadlock. 2019-12-13 10:25:38 -08:00
Philip Rideout
6fbc690097 macOS: pump the event queue while waiting. 2019-12-13 10:25:38 -08:00
Jordan Rupprecht
311f6eacd7 Add missing <assert.h> include. (#1969)
An version of clang is smarter about generating warnings for template code. `assert` here is not included, so clang generates: `error: use of undeclared identifier 'assert'`
2019-12-13 09:26:02 -08:00
Ben Doherty
0dee8c5f34 Deprecate Kokoro-specific logic from build scripts (#1973) 2019-12-12 13:23:43 -08:00
Philip Rideout
ddf85bae72 CMake: add a convenient "run" target for quick testing.
This is just a shortcut for building gltf_viewer, then immediately
running it, which is something we do a lot.
2019-12-12 13:12:23 -08:00
Pixelflinger
695d61f87c fix CubemapUtils::processSingleThreaded()
the state wasn't initialized from the user given prototype
2019-12-11 15:26:12 -08:00
Philip Rideout
9584371f89 macOS: add a check for "is this the right view?" 2019-12-11 14:49:23 -08:00
Philip Rideout
509bfb5b5e Add warnings (hopefully temporary) about macOS deadlock. 2019-12-11 14:49:23 -08:00
Philip Rideout
f853b7dc40 macOS: add cleanup for observer. 2019-12-11 14:49:23 -08:00
Philip Rideout
0693a97577 macOS: fix window resizing regression. 2019-12-11 14:49:23 -08:00
Romain Guy
8e00df1de5 Add Color::absorptionAtDistance() to compute absorption for refraction. (#1964)
Specifying the transmittance color at a specific distance is more
user-friendly than specifying absorption coefficients directly.
2019-12-10 18:20:23 -08:00
Philip Rideout
28f0536b31 Repair JavaScript bindings for IndirectLight. 2019-12-10 18:19:38 -08:00
Mathias Agopian
639bfbfc9a Fix SSAO when blending is used
When doing the depth path for ssao, we need to remove the blended
objects, i.e. produce a depth path similar to the regular depth prepass.

We also need to clear the SAO buffer. It's not needed for opaque
objects because they are written in the SAO's depth buffer. This fixes
"ship in a bottle" scenario.
2019-12-10 17:53:02 -08:00
Philip Rideout
0c734d6db0 Simplify PlatformCocoaGL. 2019-12-10 17:19:41 -08:00
Philip Rideout
e0f5b5125c Fix Catalina by moving some calls to the UI thread.
Fixes #1839.
2019-12-10 17:19:41 -08:00
Philip Rideout
28065e36e8 Make builds less verbose.
Fixes #1956.
2019-12-10 17:19:06 -08:00
Mathias Agopian
8088f0cd6f fix android samples
these samples broke with the new 5 lods ibls
2019-12-10 16:56:19 -08:00
Mathias Agopian
36cdadd238 fix gltf_viewer calculated light position/intensity 2019-12-10 14:44:23 -08:00
Ben Doherty
1061d5c5fa Fix MSVC 2019 16.4 build (#1943) 2019-12-10 13:34:48 -08:00
Mathias Agopian
c1bd438d89 temporary workaround for build break 2019-12-10 12:26:52 -08:00
Pixelflinger
dd8c0a759f Improve IBL's diffuse
If spherical harmonics are not specified in IndirectLight (i.e. 
omitted entirely), we instead use the roughness==1 LOD in the shader.
This produce much better results with absolute HDR environment, and 
generally works better more often.

This is now the preferred solution.

For cases where spherical harmonicas are better or preferred, they
can simply be supplied as before.
2019-12-10 12:26:52 -08:00
Mathias Agopian
0f16f3177e some cmgen fixes
- support equirect/octahedron save in more cases
- apply 1/pi when rendering SH so it's easier to compare 
  (this is used only for debugging anyways)
2019-12-10 12:26:52 -08:00
Ben Doherty
acc2fd9c94 Add depth32 fallback for GPUs without packed depth support (#1957) 2019-12-10 12:23:17 -08:00
Romain Guy
8feb842717 Ignore metallicness when refracted objects don't specify reflectance
Metals need a complex IOR but we only accept a scalar IOR.
2019-12-10 11:56:00 -08:00
Romain Guy
f19eaaa557 Fix directoy based cubemap loading 2019-12-10 10:03:56 -08:00
Romain Guy
3fa0c2d18b Add refraction to material_sandbox 2019-12-10 09:51:54 -08:00
Mathias Agopian
9393e1369b don't apply roughness remapping for solid refraction
The thin roughness remapping only makes sense for thin surfaces, it was
a mistake to apply it to solids. It assumes that a ray will go
undisturbed though the thin surface with an ior of 1.
2019-12-10 00:02:17 -08:00
Ben Doherty
8342b0ecec Update Windows READMEs for building with VS2019 (#1952) 2019-12-09 17:09:45 -08:00
Ben Doherty
9a291b6543 Refactor Metal buffers, allow in-frame vertex and index updates (#1950) 2019-12-09 15:54:40 -08:00
Romain Guy
ec403f8940 Fix material_sandbox 2019-12-09 13:37:09 -08:00
Mathias Agopian
047dab769d fix unit tests 2019-12-09 13:24:49 -08:00
Philip Rideout
5d8cd288d3 Fixed formatting in release notes. 2019-12-09 12:42:17 -08:00
Philip Rideout
8a63682382 Remove unused includes. 2019-12-09 12:41:02 -08:00
Philip Rideout
036f151a42 WebGL: enable depth buffer in swap chain.
In PR #1906 we enabled depth for all backends, but we forgot web.

Note that this required 0 new codelines whereas Vulkan required 116
additional codelines. :)
2019-12-09 10:18:23 -08:00
Ben Doherty
5bc1356192 Update RELEASE_NOTES.md 2019-12-09 10:01:25 -08:00
Ben Doherty
c04a111d10 Fix froxel coordinate calculation on Metal and Vulkan (#1934) 2019-12-09 09:57:59 -08:00
Philip Rideout
da5eabc91f Fix bad state after setIndirectLight(null).
This cleans up 3 related issues, but only the first of these caused an
actual user-visible bug:

(1) When the IBL was null, prepareLighting was failing to bind the black
1x1 texture.

(2) If you added and removed an IBL from a Scene, then Scene was not
returned to its initial state.

(3) The default 1x1 IBL used an intensity of 1 rather than 30000, which
is inconsistent with the null IBL.

Fixes #1940.
2019-12-09 09:30:59 -08:00
Mathias Agopian
79f8947bfa Improve thin layer refraction
We now take into account the light bouncing between the two interfaces
of the materials. We can do this because we assume thin surfaces, 
meaning that the light will exit where it entered and with the same
direction that the specular.

This strengthen the specular at grazing angles (and reduces the transmission).
2019-12-08 22:18:18 -08:00
Mathias Agopian
160a22519e Use unclamped roughness for IBls
This allows us to have sharp reflection and refraction -- the later
is very important.
2019-12-08 22:18:18 -08:00
Mathias Agopian
cc9a1d446c added the concept of micro thickness for thin objects
When dealing with thin objects we really have two thicknesses to 
consider, the thickness in the direction of the normal, which 
corresponds to the value used for solid objects, and the thickness of
the object's walls, which generally is a constant.

Reusing thickness in the later case is problematic for assets that have
a thickness map, but are rendered hollow.

In the future we can even imagine handling double-sided hollow objects
by using the thickness information -- e.g. a hollow cube.
2019-12-08 22:18:18 -08:00
Mathias Agopian
b78ea90c27 apply thin roughness remapping to solid as well
this is because for solids we're also handling both interfaces in one
go (as opposed to calculate the actual btdf), and roughness should
depend on the ior.

Also rename some variables for less confusion (we now use 
incident(I)/refracted(R)).
2019-12-08 22:18:18 -08:00
Mathias Agopian
cbb5d2b423 fix typos and rename refraction to refractionMode 2019-12-08 22:18:18 -08:00
Pixelflinger
c759743e40 Don't saturate absorption, unless it's a constant
Update documentation.
2019-12-08 22:18:18 -08:00
Pixelflinger
3b2ecc6003 Fix a material compiling issue when thickness wasn't defined
We also now assume a thickness of 0, if it's not set in the material.
We don't want to assume any particular thickness, because it depends
on the scene's scale.

Also clamp the remapped roughness.
2019-12-08 22:18:18 -08:00
Mathias Agopian
4790cb5009 Allow materials to override the IOR
Normally the IOR is deduced from the reflectance, but now we allow to
specify the IOR instead or in addition to the reflectance.
In the later case, it's possible to create physically impossible
materials, but this can be useful for artistic reasons.
2019-12-08 22:18:18 -08:00
Pixelflinger
ee0080487a finish plumbing for new material parameters 2019-12-08 22:18:18 -08:00
Pixelflinger
f70b820cbe update material documentation 2019-12-08 22:18:18 -08:00
Pixelflinger
1ccae61d40 shader plumbing for screen-space refraction
In this PR, the filament side is missing, so we're outputting back.
But all codepaths in the shader are implemented:
 cubemap/screenspace, solid/thin
2019-12-08 22:18:18 -08:00
Mathias Agopian
f670472e55 implement thin layers 2019-12-08 22:18:18 -08:00
Mathias Agopian
f94aa731ed Add plumbing for refraction type (solid or thin) 2019-12-08 22:18:18 -08:00
Mathias Agopian
5c80bfe430 update documentations with common IOR values 2019-12-08 22:18:18 -08:00
Mathias Agopian
8d7866b58d apply fresnel to refraction
fixes white furnace test.
2019-12-08 22:18:18 -08:00
Mathias Agopian
179bf03caf implement absorption 2019-12-08 22:18:18 -08:00
Pixelflinger
0371a805ed basic refraction 2019-12-08 22:18:18 -08:00
Pixelflinger
57b48e0719 address reviewers comments
- get rid of "thin layer thickness" property
- make absorption a vec3
2019-12-08 22:18:18 -08:00
Mathias Agopian
eb767abc55 Add material properties needed for refraction 2019-12-08 22:18:18 -08:00
Mathias Agopian
dbda77b091 Improve low roughness significantly
Filament will now allow incomplete mipmap chains for the IBL and
map the roughness to the available chain.

This allows to create roughness cubemaps with a minim size for
roughness==1, instead of always mapping it to 1x1.

cmgen will now use 16x16 cubemaps for roughness==1, which
improves the quality of rough objects significantly.

The beauty of this is that there is no asset or API change. Old assets
will continue to work like before.
2019-12-08 22:17:08 -08:00
Philip Rideout
2c1454270e OpenGL: enable cubemap filtering on desktop.
According to the OpenGL spec, proper cubemap filtering is disabled by
default in non-ES OpenGL.
2019-12-08 22:16:52 -08:00
Mathias Agopian
1ec72e606b Round non-texture FBO attachments to 32 pixels
this helps reducing churn in the resourceallocator cache.
2019-12-06 14:03:07 -08:00
Philip Rideout
24bfdd741a Revert "Fix bad state after setIndirectLight(null)."
This reverts commit f0ce4094dd.
2019-12-06 13:56:21 -08:00
Philip Rideout
f0ce4094dd Fix bad state after setIndirectLight(null).
This cleans up 3 related issues, but only the first of these caused an
actual user-visible bug:

(1) When the IBL was null, prepareLighting was failing to bind the black
1x1 texture.

(2) If you added and removed an IBL from a Scene, then Scene was not
returned to its initial state.

(3) The default 1x1 IBL used an intensity of 1 rather than 30000, which
is inconsistent with the null IBL.

Fixes #1940.
2019-12-06 13:54:49 -08:00
Philip Rideout
9cbcd88d4e WebGL: tweak helmet demo for shadows. 2019-12-06 10:27:00 -08:00
Philip Rideout
8ea6e6ce59 Upgrade hello-camera to use AHardwareBuffer. 2019-12-06 08:46:37 -08:00
Philip Rideout
6d0f8c9ead cmgen: add support for non-RLE HDR images.
The new conditional is cribbed from STB, which checks the first three
bytes.

Fixes #1937.
2019-12-06 08:45:12 -08:00
Philip Rideout
43d91a5c40 Repair twoPassesTwoSides transparency.
This regressed when we added support for dynamic backface culling
(#1641). Also note another fix we made: #1877.
2019-12-05 09:00:57 -08:00
Romain Guy
564e527ac7 Fix docs typo 2019-12-05 10:17:00 +01:00
Philip Rideout
6d3b733cb1 Bump package.json version. 2019-12-04 15:59:52 -08:00
Philip Rideout
0e967726de Simplify CameraManipulator.
This removes a lot of code and will make it easier to migrate into a new
library with Java bindings, etc.

- The clipping planes and projection matrix were unused, removed them.

- In split view mode, our demos were using only 2 of the 3 manipulators,
  removed one.

- Instead of callbacks and update methods, users can simply ask for the
  current matrix at every frame.

- The manipulator's job is to consume mouse events and maintain an
  "look at" basis, there is no need to store a reference to a Filament
  Camera.
2019-12-04 08:05:17 -08:00
Mathias Agopian
001a4c46db Added a property chunk to materials
Materials can now reflect which property is in use.
2019-12-03 17:51:44 -08:00
Mathias Agopian
1a9d0926ee Added a torus and simple cube shapes
renamed "cube.obj" to "rounded_cube.obj", which it was (rounded)
2019-12-03 17:49:40 -08:00
Mathias Agopian
05a756beaa ResourceAllocator: minor clean-up and comments 2019-12-03 17:42:43 -08:00
Mathias Agopian
1014847e9d workaround OpenGLES driver bug
some drivers declare supporting anisotropic filtering, but don't
support calling glSamplerParameter() to set the max anisotropy, presumably because they only support glTexParameter().
We simply turn off anisotropic filtering on these drivers.
2019-12-03 17:41:41 -08:00
Ben Doherty
d3309c2e84 Fix Windows build variants (#1926) 2019-12-02 17:16:15 -08:00
Romain Guy
565002a918 Remove obsolete comment 2019-12-02 14:23:12 -08:00
Romain Guy
08b83e7ed1 Make including jawt_md.h more resilient (#1922)
Sometimes CMake decides to use the JNI bits included with XCode instead
of those from the installed JDK. The header files are located in different
directories. This does the proper include.
2019-12-02 08:45:20 -08:00
Ben Doherty
b4c2f523fe Update RELEASE_NOTES.md 2019-11-27 13:14:12 -08:00
Romain Guy
4ba5d6b9a8 Update release notes 2019-11-27 13:05:34 -08:00
Ben Doherty
59ceb05f99 Add support for mapping individual planes of iOS external images (#1917) 2019-11-27 10:38:13 -08:00
Benjamin Doherty
929c8e96c6 Handle surface size changes in Metal 2019-11-27 01:08:40 -08:00
Philip Rideout
1b5a730358 VulkanDriver: add depth buffer to swap chain. 2019-11-27 01:08:40 -08:00
Benjamin Doherty
79255e8e7d Implement default depth buffer for Metal 2019-11-27 01:08:40 -08:00
Mathias Agopian
50845261fe Swap chains are now always created with a depth buffer
This is to allow direct rendering of 3D objects into the swapchain 
under certain circumstances (no msaa or postprocessing).
2019-11-27 01:08:40 -08:00
Philip Rideout
da090f0ff6 Fix missing call to glInvalidateFramebuffer().
We were over-optimizing, not always honoring the flag. This was
incorrect since bindFramebuffer can be called from other places.

Fixes #1914.
2019-11-26 15:25:59 -08:00
Philip Rideout
60ead8c5f3 Add Android sample for testing the Stream API.
This new sample differs from "Hello Camera" in that it exercises all
three ways of using Stream. It also uses Canvas instead of Camera2 to
draw into the external texture. It shows two sets of stripes, one
animated using the shader and the other animated using Canvas. If the
two stripes are aligned, then the stream is perfectly synchronized.
Users can tap the screen to cycle between the three modes.
2019-11-26 07:58:52 -08:00
Ben Doherty
6942569409 Pass shared context on Windows to wglCreateContextAttribs (#1913) 2019-11-25 13:38:07 -08:00
Romain Guy
498a608941 Remove unused lambda capture 2019-11-23 19:55:05 -08:00
Philip Rideout
eee7154c33 wasm: add support for DEBUG builds by disabling RTTI.
Unfortunately we require RTTI to be disabled for web builds
due to the way in which we handle array buffers. This may change
in the future but for now I think it's an acceptable constraint,
especially given the fact that RTTI adds bloat anyway.
2019-11-22 14:33:03 -08:00
Ben Doherty
a735660af8 Separate resource packages for gltf_viewer and lucy demo (#1908) 2019-11-22 11:34:42 -08:00
Ben Doherty
c5ed7172b3 Add release GitHub workflow (#1903) 2019-11-21 11:04:20 -08:00
Mathias Agopian
4b28362920 Better workaround a resource culling issue.
A texture resource can end-up with not usage bit set if it is used as
an attachment of a render target that gets replaced by a moveResource()
call. The framegraph should take care of culling our this resource,
in that case, but currently doesn't.

We worked around this issue by not declaring the resources, but it's
better to do this in the frame graph code, as to not affect the 
user facing API.
2019-11-20 22:26:00 -08:00
Mathias Agopian
dfeaa416c0 Tone mapping always sets alpha channel to 1 in opaque mode
This fixes an issue where the alpha channel could be left to garbage in
opaque mode with FXAA disabled.
2019-11-20 17:34:59 -08:00
Mathias Agopian
3ce4dd94f7 Use a larger blur filter for SSAO
We go from 9 to 15 taps to better match the 16x16 noise pattern.
2019-11-20 16:32:28 -08:00
Ben Doherty
0ee1d406e0 Update README.md to reflect build link removal (#1902) 2019-11-20 13:29:51 -08:00
Mathias Agopian
dad814e046 Fix a long standing bug preventing the use of transparent views (#1893)
Fix #1165

In order to use transparent views, post-processing had to be disabled
because we were not able to blit post-processed buffers with blending.
This is now fixed by simply reverting to a quad.

A side effect of this, is improved performance when a scaling blit is
needed when MSAA is active.


This also introduced new "bugs", or at least weird behaviors: the
system needs to know when blending is needed, and this has to be
based on heuristics (unless we add a new api). Currently the heuristic
is that the COLOR buffer is not discarded and the view is cleared with 
an alpha value (or not cleared).
2019-11-19 14:05:22 -08:00
Pixelflinger
6246f20e63 Always use SH3 for indirect lighting
We used to use SH2 on mobile/webgl, but the quality degradation is too
prominent. This adds ~16 adds though.
2019-11-19 14:00:37 -08:00
Ben Doherty
f4ad55f6d7 Fix Windows CI failures by specifying shell (#1890) 2019-11-19 11:20:59 -08:00
Pixelflinger
027c4b42f7 fix a few issues with MSAA blits
1) When scaling is enabled, we're using a blit at the end of the frame,
   however, if MSAA is also enabled, this blit is not allowed, so we
   need an explicit MSAA resolve.

2) When rendering directly into the default render target with MSAA
   enabled, we need an explicit resolve ONLY IF there is a format
   conversion, because those are also not allowed. 
   Before, we were doing this resolve regardless.

3) The test for "rendering directly into the default target" had
   become wrong because, the Render target can now be a user texture
   (which is assumed to have the proper MSAA-ness and a depth buffer),
   so no intermediate buffer should be needed for those. We now
   check that render target is actually the default render target
2019-11-18 20:25:53 -08:00
Pixelflinger
fb6c9f8b7d Use 16x16 blue noise for SSAO samples
The larger, blue noise texture gives a more pleasant, smoother SSAO
effect.
2019-11-18 20:25:29 -08:00
Pixelflinger
33d2eaee5b remove old 'SSAO' algorithm 2019-11-18 16:16:29 -08:00
Ben Doherty
ae3ccd7fb6 Implement headless swap chains and readPixels for Metal (#1885) 2019-11-18 11:28:20 -08:00
Russell Chou
72dbea256a Fix comment. 2019-11-16 15:10:15 -08:00
Pixelflinger
ea0ff1bc01 Add a way to override the material of a RenderPass
We used to have this functionality, but it we removed it because we
didn't have a use for it and it was costly.

This new implementation is only internal, and would (will?) be useful
if we wanted to generate a special buffer for SSAO for instance (instead
of just depth). This implementation, overrides the material at the time
the commands are executed, which is much cheaper than the previous
implementation.
2019-11-15 17:37:18 -08:00
Philip Rideout
2bca33f535 gltfio: Use JobSystem to decode PNG / JPEG.
For the street light glb from the Khronos suite, this reduces texture
loading time from 290 ms to 110 ms.

Stay tuned for another feature: notification callbacks.

Related to #1876.
2019-11-15 17:30:52 -08:00
Ben Doherty
75c5bb846b Use checkout action for GitHub Actions (#1886) 2019-11-15 16:33:23 -08:00
Pixelflinger
0da551c7fd More improvements to SSAO
- we add an 'intensity' parameter that allows to control the strength
  of the AO effect. This is useful for aesthetic reasons.

- the default intensity is now 2x that of before this change, which
  makes the intensity parameter match AO papers this implementation
  is inspired of.

- bias is now z-dependent, which reduces some self shadowing wrt the
  depth.
2019-11-15 09:42:37 -08:00
Mathias Agopian
5583dc26f9 Added a parameter to control the bilateral filter
This is needed because filament doesn't make strong assumptions about
the units used (e.g. meters), so we can't hardcode a distance in the
shader. But also, this is a cheap change.
2019-11-15 09:42:37 -08:00
Mathias Agopian
339fa3bd60 SAO and ssaogen cleanup
ssaogen now produces better formatted tables, directly usable in
shader code.

SAO shader now squares the sample radius outside of `tapLocation`, also
added some comments.
2019-11-15 09:42:37 -08:00
Mathias Agopian
dbaaa977e7 Fix depth mipmaping program
Due to a typo, we were using a nearest neighbor downsampling, instead
of picking one of the 4 pixels based on position.
2019-11-15 09:42:37 -08:00
Mathias Agopian
b10e99d374 Turn mipmapDepth material to a post-process material 2019-11-15 09:42:37 -08:00
Philip Rideout
a7d572f060 Stream API: improve dlsym usage. 2019-11-15 08:40:41 -08:00
Philip Rideout
127234f655 Stream API: release image sooner. 2019-11-15 08:40:41 -08:00
Philip Rideout
2c13c8fe6e Stream API: rename createAcquiredImage => transformAcquiredImage. 2019-11-15 08:40:41 -08:00
Philip Rideout
c0b9900cdc Stream API: privatize the AcquiredImage struct. 2019-11-15 08:40:41 -08:00
Philip Rideout
44e8d57935 Stream API: cleanup as per code review feedback. 2019-11-15 08:40:41 -08:00
Philip Rideout
d85f8164c0 Stream API: add support for acquire / release semantics.
Previously, Streams had two modes (native and texid), this adds a third
mode called "acquired", which allows for copy-free synchronized external
textures in OpenGL and paves the way for Vulkan.

The native mode is now deprecated but texid mode needs to stay around
until all clients can be upgraded.

In an early prototype, this functionality was added directly into
Texture but required quite a bit of additional state tracking, so the
Stream API seemed like a better fit.

This API is probably not necessary for Metal due to Metal's shared
ownership semantics.

This has been tested with a new Android sample that will be added in a
subsequent PR.
2019-11-15 08:40:41 -08:00
Mathias Agopian
32407c2ba5 RenderPass cleanup/refactoring
RenderPass's API now doesn't need to know about FScene, instead we
pass the geometry info as parameters.

This is one step towards keeping the "scene" concept more away from
rendering.
2019-11-14 15:31:59 -08:00
Philip Rideout
51e82a5561 Fix dynamic backface culling.
This fixes an oversight in #1641 for scenes that have only 1 primitive
when the depth prepass is enabled. In such cases, the same prim is
rendered twice in a row: once for depth and once for color.

We had enhanced the main render loop to override the primitive's
backface culling state when the material instance changed, but that was
not sufficient since the same material instance can be used for depth
and color passes.

Fixes #1872.
2019-11-13 12:15:44 -08:00
Mathias Agopian
3fb75ca904 custom command support in the renderloop
New internal API to add custom commands (lambda) before or after each
pass. These commands can be added at any point and will be sorted
properly.

e.g.:

    appendCustomCommand(Pass::COLOR, CustomCommand::PROLOG, 0, [](){
       // custom code
    });


Also split appendSortedCommands() in two functions to make it easier
to insert custom commands.
2019-11-13 11:34:34 -08:00
Tim Psiaki
64a70c7c18 Flip Tangents and Bitangents on backfaces. 2019-11-13 11:31:57 -08:00
Mathias Agopian
b9a68090b1 fix a data race on Debug builds
On Debug builds, HeapAllocatorArena needs LockingPolicy::Mutex because
it uses a TrackingPolicy, which needs to be synchronized.
On Release builds, HeapAllocatorArena doesn't need a LockingPolicy 
because HeapAllocator is intrinsically synchronized as it relies on
heap allocations (i.e.: malloc/free)
2019-11-13 09:18:57 -08:00
Mathias Agopian
5344854056 tweak how we invoke commandstream's commands
- this is to allow the use of C++17 std::invoke
- don't std::move() each argument of the tuple<> instead
  std::move() the tuple itself and perfectly-forward each argument.
- handle return values
- handle synchronous commands
2019-11-12 11:29:05 -08:00
Ben Doherty
abad894fd5 Fix UB inside FMaterial (#1862) 2019-11-12 10:08:42 -08:00
Philip Rideout
8872227af5 Fix normals with skinning when there is no normal map.
I tested this with the CesiumMan model, the lighting seems improved
around his hands.

Fixes #1848.
2019-11-11 15:03:17 -08:00
Mathias Agopian
30a07a49d0 add a way to import/export an Entity from/to an integer
This is intended to be used for interop with other programing languages.
2019-11-11 14:37:10 -08:00
Mathias Agopian
0a37cce5fe don't use our own sync primitives when TSAN is used
TSAN seems to have problems with homegrown sync primitives, such as
spinlocks, so we just don't use them when TSAN is enabled.
2019-11-11 14:36:49 -08:00
flashk
fc76ed9949 clampNoV function ignores argument
The "clampNoV" shader function is ignoring the passed dot product argument and recomputing the dot product itself. This will result in the wrong NoV value being used for clear coat IBL computations.
2019-11-08 15:34:25 -08:00
Philip Rideout
d55d042a14 Renderer: call updateStreams AFTER makeCurrent.
When using the OpenGL backend, updateStreams makes GL calls such as
glEGLImageTargetTexture2DOES and therefore requires a valid GL context.
2019-11-08 12:21:25 -08:00
Ben Doherty
d7e07f4d51 Transition to GitHub Actions for continuous builds (#1850) 2019-11-07 13:38:37 -08:00
Ben Doherty
22a6ecadbb Disable RenderingTest from CI test suite (#1858) 2019-11-07 11:17:41 -08:00
Mathias Agopian
53ff133b03 fix a possible memory corruption in debug builds
TrackingPolicy::Debug didn't store the base pointer of the Area, and
instead relied on the first allocation to discover it, however, because
of alignment, the first allocation may not match the base pointer.
Because of that there could be an overflow in onRewind(), i.e. we
could rewind to a pointer before the (wrongly computed) base. This
overflow caused the debug memset to go awry and stomped on memory.

This is fixed by passing the base pointer to the constructor of the
TrackingPolicy. This base pointer could be nullptr with certain
allocators, but in that case, onReset/onRewind should never be called;
and this is enforced at compile time.

Also fixed a (luckily) harmless buffer overflow when preparing the
dynamic lights, if the number of lights wasn't a multiple of 4. This
was harmless because we use a linear allocator, so overflows are not 
really overflows.
2019-11-07 10:03:41 -08:00
Benjamin Doherty
d1ab68ebfa Fix KTX image test on Windows 2019-11-07 09:15:07 -08:00
Philip Rideout
655b7dc13c Emit warning for too many morph targets.
Motivated by #1852.
2019-11-06 15:39:38 -08:00
Philip Rideout
48bfe0453b Fix an assert when the last uniform is an array.
Clients who do not yet have this fix can usually work around this issue
by calling the non-array overload of `MaterialInstance::setParameter`
when the array size is 1.
2019-11-06 15:39:17 -08:00
Philip Rideout
87a05f057a Fix out-of-bounds in an [unused] utility.
This was caught by ASAN.

Our algorithm header has many one-liners that compute the "next power of
two length / 2" but they all have the caveat that if the input is
already POT, then the "/ 2" part does not occur.

Usually we deal with this by testing the difference against zero.
However in `partition_point` we were skipping the test, thus causing a
potential out-of-bounds access.

I fixed `partition_point` and added a few more tests for non-POT cases.
2019-11-05 17:14:15 -08:00
Mathias Agopian
4f540fe7fd Better handling of engine shutdown
- we make sure we don't leak user callbacks or fences
- fix typos
2019-11-05 16:17:46 -08:00
Pixelflinger
1fd675fd09 Make filament's readPixels() asynchronous wrt the GPU
This doesn't change the user facing API because it already used a
callback.

With this change we implement readPixels() with a PBO, which won't
stall the GPU. Then we periodically check a fence to see when the
command is completed, at which point we map the PBO and copy the data
to the user buffer.
2019-11-05 16:17:46 -08:00
Mathias Agopian
bf72adbb57 Implement Headless SwapChain mode.
This is useful for unit tests. The content of the swapchain can be
read to main memory with Renderer::readPixels().


This PR doesn't implement this new feature in the following backends and
platforms (TODO):

VulkanDriver.cpp
MetalDriver.mm

PlatformWGL.cpp
PlatformWebGL.cpp
PlatformCocoaTouchGL.mm
2019-11-05 12:19:29 -08:00
Ben Doherty
dd45703d73 Fix Metal backend crash when rendering external image before set (#1847) 2019-11-05 09:23:58 -08:00
Ben Doherty
7c0d3cdb10 Add EAC / ETC2 and DXT compression formats to Metal backend (#1800) 2019-11-05 09:21:41 -08:00
Mathias Agopian
5462cc0fcf Renderer::readPixels() can now read back from a RenderTarget
Before it was limited to reading back from the SwapChain.
2019-11-04 17:18:39 -08:00
Philip Rideout
8fe9f15b3b JavaScript: add documentation for fetch utility. 2019-11-04 14:20:51 -08:00
Philip Rideout
c49c6e5d19 JavaScript: allow pre-population of asset data.
Fixes #1843.
2019-11-04 14:20:51 -08:00
Philip Rideout
636c54ec6f gltfio: support mesh-level morph weights.
We honored node-level defaults but not mesh-level.

Fixes #1840.
2019-11-04 12:32:02 -08:00
Nicklas Ansman Giertz
52ee07f2fd Add a clarifying comment 2019-11-03 15:03:13 -08:00
Nicklas Ansman Giertz
02ef4a99b7 Add some missing nullability annotations to the gltfio android bindings 2019-11-03 15:03:13 -08:00
Nicklas Ansman Giertz
73a4431a34 Fix some warnings in the gltfio android jni code 2019-11-03 15:03:13 -08:00
Nicklas Ansman Giertz
e252558ef6 Expose FilamentAsset.getResourceUris in the Android bindings 2019-11-03 15:03:13 -08:00
Nicklas Ansman Giertz
5680b5d9a6 Add support for GLTF files in the android gltfio bindings 2019-11-03 15:03:13 -08:00
Philip Rideout
86c0a68ccd Work around unaligned stack with clang 11.
Optimized macOS builds can trigger "stack_not_16_byte_aligned_error"
when building with clang 11. We happen to see this with resgen but it
could happen anywhere.

https://forums.developer.apple.com/thread/121887

Fixes #1823
2019-11-01 13:52:47 -07:00
Ben Doherty
9379e7ce45 Use ARC for Metal backend (#1824) 2019-11-01 10:28:28 -07:00
Philip Rideout
04d2234169 Fix WebGL debug build. 2019-11-01 09:14:38 -07:00
Philip Rideout
66f4419518 gltfio: Fix black default material.
Fixes #1828.
2019-10-31 16:45:01 -07:00
Philip Rideout
be4ad2ec07 WebGL: add a light source to the animation demo. 2019-10-31 16:45:01 -07:00
Philip Rideout
853b2205dd Upgrade emsdk for improved wasm generation.
This uses clang's wasm backend rather than fastcomp.
2019-10-31 16:41:29 -07:00
Philip Rideout
80f104c522 OpenGL: Fix up my previous fix for uvec4 attribs.
The previous fix for #1726 was not quite right because it did not
set the INTEGER flag unless the attribute was declared.

Fixes #1726.
2019-10-31 11:57:43 -07:00
Philip Rideout
1fa2fd9b7f WebGL: add morphing demo. 2019-10-31 11:57:43 -07:00
Philip Rideout
fa108d6a65 Use the Jim Arvo method for transforming AABB's.
This is from the 1990 Graphics Gems article.
2019-10-30 16:15:55 -07:00
1391 changed files with 61253 additions and 27369 deletions

View File

@@ -0,0 +1,37 @@
name: Android
on:
push:
branches:
- master
jobs:
build-android:
name: build-android
runs-on: macos-latest
steps:
- uses: actions/checkout@v1.0.0
- name: Run build script
run: |
cd build/android && ./build.sh continuous
- uses: actions/upload-artifact@v1.0.0
with:
name: filament-android
path: out/filament-android-release.aar
- uses: actions/upload-artifact@v1.0.0
with:
name: filamat-android-full
path: out/filamat-android-full-release.aar
- uses: actions/upload-artifact@v1.0.0
with:
name: filamat-android-lite
path: out/filamat-android-lite-release.aar
- uses: actions/upload-artifact@v1.0.0
with:
name: gltfio-android-release
path: out/gltfio-android-release.aar
- uses: actions/upload-artifact@v1.0.0
with:
name: filament-utils-android-release
path: out/filament-utils-android-release.aar

21
.github/workflows/ios-continuous.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: iOS
on:
push:
branches:
- master
jobs:
build-ios:
name: build-ios
runs-on: macos-latest
steps:
- uses: actions/checkout@v1.0.0
- name: Run build script
run: |
cd build/ios && ./build.sh continuous
- uses: actions/upload-artifact@v1.0.0
with:
name: filament-ios
path: out/filament-release-ios.tgz

21
.github/workflows/linux-continuous.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: Linux
on:
push:
branches:
- master
jobs:
build-linux:
name: build-linux
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1.0.0
- name: Run build script
run: |
cd build/linux && ./build.sh continuous
- uses: actions/upload-artifact@v1.0.0
with:
name: filament-linux
path: out/filament-release-linux.tgz

21
.github/workflows/mac-continuous.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: macOS
on:
push:
branches:
- master
jobs:
build-mac:
name: build-mac
runs-on: macos-latest
steps:
- uses: actions/checkout@v1.0.0
- name: Run build script
run: |
cd build/mac && ./build.sh continuous
- uses: actions/upload-artifact@v1.0.0
with:
name: filament-mac
path: out/filament-release-darwin.tgz

View File

@@ -12,15 +12,7 @@ jobs:
os: [macos-latest, ubuntu-latest]
steps:
- name: Checkout Filament
run: |
git version
git init $GITHUB_WORKSPACE
cd $GITHUB_WORKSPACE
git remote add origin https://github.com/google/filament
git config gc.auto 0
git fetch --tags --prune --progress --no-recurse-submodules origin +${GITHUB_REF}:${GITHUB_REF/refs\//refs\/remote\/}
git checkout --progress --force ${GITHUB_REF/refs\//refs\/remote\/}
- uses: actions/checkout@v1.0.0
- name: Run build script
run: |
WORKFLOW_OS=`echo \`uname\` | sed "s/Darwin/mac/" | tr [:upper:] [:lower:]`
@@ -33,34 +25,18 @@ jobs:
runs-on: windows-latest
steps:
- name: Checkout Filament
run: |
git version
git init %GITHUB_WORKSPACE%
cd %GITHUB_WORKSPACE%
git remote add origin https://github.com/google/filament
git config gc.auto 0
git fetch --tags --prune --progress --no-recurse-submodules origin +%GITHUB_REF%:%GITHUB_REF:refs/=refs/remote/%
git checkout --progress --force %GITHUB_REF:refs/=refs/remote/%
shell: cmd
- uses: actions/checkout@v1.0.0
- name: Run build script
run: |
build\windows\build-github.bat
build\windows\build-github.bat presubmit
shell: cmd
build-android:
name: build-android
runs-on: macos-latest
steps:
- name: Checkout Filament
run: |
git version
git init $GITHUB_WORKSPACE
cd $GITHUB_WORKSPACE
git remote add origin https://github.com/google/filament
git config gc.auto 0
git fetch --tags --prune --progress --no-recurse-submodules origin +${GITHUB_REF}:${GITHUB_REF/refs\//refs\/remote\/}
git checkout --progress --force ${GITHUB_REF/refs\//refs\/remote\/}
- uses: actions/checkout@v1.0.0
- name: Run build script
run: |
cd build/android && ./build.sh ${TARGET}
@@ -72,15 +48,7 @@ jobs:
runs-on: macos-latest
steps:
- name: Checkout Filament
run: |
git version
git init $GITHUB_WORKSPACE
cd $GITHUB_WORKSPACE
git remote add origin https://github.com/google/filament
git config gc.auto 0
git fetch --tags --prune --progress --no-recurse-submodules origin +${GITHUB_REF}:${GITHUB_REF/refs\//refs\/remote\/}
git checkout --progress --force ${GITHUB_REF/refs\//refs\/remote\/}
- uses: actions/checkout@v1.0.0
- name: Run build script
run: |
cd build/ios && ./build.sh ${TARGET}
@@ -92,15 +60,7 @@ jobs:
runs-on: macos-latest
steps:
- name: Checkout Filament
run: |
git version
git init $GITHUB_WORKSPACE
cd $GITHUB_WORKSPACE
git remote add origin https://github.com/google/filament
git config gc.auto 0
git fetch --tags --prune --progress --no-recurse-submodules origin +${GITHUB_REF}:${GITHUB_REF/refs\//refs\/remote\/}
git checkout --progress --force ${GITHUB_REF/refs\//refs\/remote\/}
- uses: actions/checkout@v1.0.0
- name: Run build script
run: |
cd build/web && ./build.sh ${TARGET}

176
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,176 @@
name: Release
# This Workflow can be triggered two ways:
# 1. A GitHub release is created (using the GitHub web UI). This triggers all of the platforms to build and upload assets.
# 2. A repository_dispatch API event is sent. This triggers a build for only the platform specified in the dispatch event.
env:
RELEASE_TAG: ${{ github.event.client_payload.release_tag }}
on:
repository_dispatch:
release:
types: [created]
jobs:
build-desktop:
name: build-desktop
runs-on: ${{ matrix.os }}
if: github.event_name == 'release' || github.event.client_payload.platform == 'desktop'
strategy:
matrix:
os: [macos-latest, ubuntu-latest]
steps:
- name: Decide Git ref
id: git_ref
run: |
REF=${RELEASE_TAG:-${GITHUB_REF}}
TAG=${REF##*/}
echo ::set-output name=ref::${REF}
echo ::set-output name=tag::${TAG}
- uses: actions/checkout@v1.0.0
with:
ref: ${{ steps.git_ref.outputs.ref }}
- name: Run build script
run: |
WORKFLOW_OS=`echo \`uname\` | sed "s/Darwin/mac/" | tr [:upper:] [:lower:]`
cd build/$WORKFLOW_OS && ./build.sh release
- name: Upload release assets
run: |
pip3 install setuptools
pip3 install PyGithub
DATE=`date +%Y%m%d`
if [ -f out/filament-release-darwin.tgz ]; then mv out/filament-release-darwin.tgz out/filament-${DATE}-mac.tgz; fi;
if [ -f out/filament-release-linux.tgz ]; then mv out/filament-release-linux.tgz out/filament-${DATE}-linux.tgz; fi;
python3 build/common/upload-assets.py ${TAG} out/*.tgz
env:
TAG: ${{ steps.git_ref.outputs.tag }}
GITHUB_API_KEY: ${{ secrets.GITHUB_API_KEY }}
build-web:
name: build-web
runs-on: macos-latest
if: github.event_name == 'release' || github.event.client_payload.platform == 'web'
steps:
- name: Decide Git ref
id: git_ref
run: |
REF=${RELEASE_TAG:-${GITHUB_REF}}
TAG=${REF##*/}
echo ::set-output name=ref::${REF}
echo ::set-output name=tag::${TAG}
- uses: actions/checkout@v1.0.0
with:
ref: ${{ steps.git_ref.outputs.ref }}
- name: Run build script
run: |
cd build/web && ./build.sh release
- name: Upload release assets
run: |
pip3 install setuptools
pip3 install PyGithub
DATE=`date +%Y%m%d`
mv out/filament-release-web.tgz out/filament-${DATE}-web.tgz
python3 build/common/upload-assets.py ${TAG} out/*.tgz
env:
TAG: ${{ steps.git_ref.outputs.tag }}
GITHUB_API_KEY: ${{ secrets.GITHUB_API_KEY }}
build-android:
name: build-android
runs-on: macos-latest
if: github.event_name == 'release' || github.event.client_payload.platform == 'android'
steps:
- name: Decide Git ref
id: git_ref
run: |
REF=${RELEASE_TAG:-${GITHUB_REF}}
TAG=${REF##*/}
echo ::set-output name=ref::${REF}
echo ::set-output name=tag::${TAG}
- uses: actions/checkout@v1.0.0
with:
ref: ${{ steps.git_ref.outputs.ref }}
- name: Run build script
run: |
cd build/android && ./build.sh release
- name: Upload release assets
run: |
pip3 install setuptools
pip3 install PyGithub
DATE=`date +%Y%m%d`
mv out/filament-android-release.aar out/filament-${DATE}-android.aar
mv out/filamat-android-full-release.aar out/filamat-${DATE}-full-android.aar
mv out/filamat-android-lite-release.aar out/filamat-${DATE}-lite-android.aar
mv out/gltfio-android-release.aar out/gltfio-${DATE}-android.aar
mv out/filament-utils-android-release.aar out/filament-utils-${DATE}-android.aar
python3 build/common/upload-assets.py ${TAG} out/*.aar
env:
TAG: ${{ steps.git_ref.outputs.tag }}
GITHUB_API_KEY: ${{ secrets.GITHUB_API_KEY }}
build-ios:
name: build-ios
runs-on: macos-latest
if: github.event_name == 'release' || github.event.client_payload.platform == 'ios'
steps:
- name: Decide Git ref
id: git_ref
run: |
REF=${RELEASE_TAG:-${GITHUB_REF}}
TAG=${REF##*/}
echo ::set-output name=ref::${REF}
echo ::set-output name=tag::${TAG}
- uses: actions/checkout@v1.0.0
with:
ref: ${{ steps.git_ref.outputs.ref }}
- name: Run build script
run: |
cd build/ios && ./build.sh release
- name: Upload release assets
run: |
pip3 install setuptools
pip3 install PyGithub
DATE=`date +%Y%m%d`
mv out/filament-release-ios.tgz out/filament-${DATE}-ios.tgz
python3 build/common/upload-assets.py ${TAG} out/*.tgz
env:
TAG: ${{ steps.git_ref.outputs.tag }}
GITHUB_API_KEY: ${{ secrets.GITHUB_API_KEY }}
build-windows:
name: build-windows
runs-on: windows-latest
if: github.event_name == 'release' || github.event.client_payload.platform == 'windows'
steps:
- name: Decide Git ref
id: git_ref
run: |
REF=${RELEASE_TAG:-${GITHUB_REF}}
TAG=${REF##*/}
echo ::set-output name=ref::${REF}
echo ::set-output name=tag::${TAG}
shell: bash
- uses: actions/checkout@v1.0.0
with:
ref: ${{ steps.git_ref.outputs.ref }}
- name: Run build script
run: |
build\windows\build-github.bat release
shell: cmd
- name: Upload release assets
run: |
pip3 install PyGithub
DATE=`date +%Y%m%d`
mv out/filament-windows.tgz out/filament-${DATE}-windows.tgz
python build/common/upload-assets.py ${TAG} out/*.tgz
shell: bash
env:
TAG: ${{ steps.git_ref.outputs.tag }}
GITHUB_API_KEY: ${{ secrets.GITHUB_API_KEY }}

21
.github/workflows/web-continuous.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: Web
on:
push:
branches:
- master
jobs:
build-web:
name: build-web
runs-on: macos-latest
steps:
- uses: actions/checkout@v1.0.0
- name: Run build script
run: |
cd build/web && ./build.sh continuous
- uses: actions/upload-artifact@v1.0.0
with:
name: filament-web
path: out/filament-release-web.tgz

View File

@@ -0,0 +1,22 @@
name: Windows
on:
push:
branches:
- master
jobs:
build-windows:
name: build-windows
runs-on: windows-latest
steps:
- uses: actions/checkout@v1.0.0
- name: Run build script
run: |
build\windows\build-github.bat continuous
shell: cmd
- uses: actions/upload-artifact@v1.0.0
with:
name: filament-windows
path: out/filament-windows.tgz

449
BUILDING.md Normal file
View File

@@ -0,0 +1,449 @@
## Building Filament
### Prerequisites
To build Filament, you must first install the following tools:
- CMake 3.10 (or more recent)
- clang 7.0 (or more recent)
- [ninja 1.8](https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages) (or more recent)
To build the Java based components of the project you can optionally install (recommended):
- OpenJDK 1.8 (or more recent)
Additional dependencies may be required for your operating system. Please refer to the appropriate
section below.
Building the `rays` library (used for light baking) is optional and requires the following packages:
- embree 3.0+
- libtbb-dev
To build Filament for Android you must also install the following:
- Android Studio 3.6
- Android SDK
- Android NDK "side-by-side" 20 or higher
### Environment variables
Make sure the environment variable `ANDROID_HOME` points to the location of your Android SDK.
By default our build system will attempt to compile the Java bindings. To do so, the environment
variable `JAVA_HOME` should point to the location of your JDK.
When building for WebGL, you'll also need to set `EMSDK`. See [WebAssembly](#webassembly).
### IDE
We recommend using CLion to develop for Filament. Simply open the root directory's CMakeLists.txt
in CLion to obtain a usable project.
### Easy build
Once the required OS specific dependencies listed below are installed, you can use the script
located in `build.sh` to build Filament easily on macOS and Linux.
This script can be invoked from anywhere and will produce build artifacts in the `out/` directory
inside the Filament source tree.
To trigger an incremental debug build:
```
$ ./build.sh debug
```
To trigger an incremental release build:
```
$ ./build.sh release
```
To trigger both incremental debug and release builds:
```
$ ./build.sh debug release
```
To install the libraries and executables in `out/debug/` and `out/release/`, add the `-i` flag.
You can force a clean build by adding the `-c` flag. The script offers more features described
by executing `build.sh -h`.
### Disabling Java builds
By default our build system will attempt to compile the Java bindings. If you wish to skip this
compilation step simply pass the `-j` flag to `build.sh`:
```
$ ./build.sh -j release
```
If you use CMake directly instead of the build script, pass `-DENABLE_JAVA=OFF` to CMake instead.
### Filament-specific CMake Options
The following CMake options are boolean options specific to Filament:
- `ENABLE_JAVA`: Compile Java projects: requires a JDK and the JAVA_HOME env var
- `ENABLE_LTO`: Enable link-time optimizations if supported by the compiler
- `FILAMENT_BUILD_FILAMAT`: Build filamat and JNI buildings
- `FILAMENT_SUPPORTS_METAL`: Include the Metal backend
- `FILAMENT_SUPPORTS_VULKAN`: Include the Vulkan backend
- `GENERATE_JS_DOCS`: Build WebGL documentation and tutorials
- `INSTALL_BACKEND_TEST`: Install the backend test library so it can be consumed on iOS
- `USE_EXTERNAL_GLES3`: Experimental: Compile Filament against OpenGL ES 3
To turn an option on or off:
```
$ cd <cmake-build-directory>
$ cmake . -DOPTION=ON # Relace OPTION with the option name, set to ON / OFF
```
Options can also be set with the CMake GUI.
### Linux
Make sure you've installed the following dependencies:
- `clang-7` or higher
- `libglu1-mesa-dev`
- `libc++-7-dev` (`libcxx-devel` and `libcxx-static` on Fedora) or higher
- `libc++abi-7-dev` (`libcxxabi-static` on Fedora) or higher
- `ninja-build`
- `libxi-dev`
After dependencies have been installed, we highly recommend using the [easy build](#easy-build)
script.
If you'd like to run `cmake` directly rather than using the build script, it can be invoked as
follows, with some caveats that are explained further down.
```
$ mkdir out/cmake-release
$ cd out/cmake-release
$ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../release/filament ../..
```
Your Linux distribution might default to `gcc` instead of `clang`, if that's the case invoke
`cmake` with the following command:
```
$ mkdir out/cmake-release
$ cd out/cmake-release
# Or use a specific version of clang, for instance /usr/bin/clang-7
$ CC=/usr/bin/clang CXX=/usr/bin/clang++ CXXFLAGS=-stdlib=libc++ \
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../release/filament ../..
```
You can also export the `CC` and `CXX` environment variables to always point to `clang`. Another
solution is to use `update-alternatives` to both change the default compiler, and point to a
specific version of clang:
```
$ update-alternatives --install /usr/bin/clang clang /usr/bin/clang-7 100
$ update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-7 100
$ update-alternatives --install /usr/bin/cc cc /usr/bin/clang 100
$ update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 100
```
Finally, invoke `ninja`:
```
$ ninja
```
This will build Filament, its tests and samples, and various host tools.
### macOS
To compile Filament you must have the most recent version of Xcode installed and you need to
make sure the command line tools are setup by running:
```
$ xcode-select --install
```
After installing Java 1.8 you must also ensure that your `JAVA_HOME` environment variable is
properly set. If it doesn't already point to the appropriate JDK, you can simply add the following
to your `.profile`:
```
export JAVA_HOME="$(/usr/libexec/java_home)"
```
Then run `cmake` and `ninja` to trigger a build:
```
$ mkdir out/cmake-release
$ cd out/cmake-release
$ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../release/filament ../..
$ ninja
```
### iOS
The easiest way to build Filament for iOS is to use `build.sh` and the
`-p ios` flag. For instance to build the debug target:
```
$ ./build.sh -p ios debug
```
See [ios/samples/README.md](./ios/samples/README.md) for more information.
### Windows
#### Building on Windows with Visual Studio 2019
Install the following components:
- [Visual Studio 2019](https://www.visualstudio.com/downloads)
- [Windows 10 SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk)
- [Python 3.7](https://www.python.org/ftp/python/3.7.0/python-3.7.0.exe)
- [CMake 3.14 or later](https://github.com/Kitware/CMake/releases/download/v3.14.7/cmake-3.14.7-win64-x64.msi)
The latest Windows SDK can also by installed by opening Visual Studio and selecting _Get Tools and
Features..._ under the _Tools_ menu.
Open the `x64 Native Tools Command Prompt for VS 2019`.
Create a working directory, and run cmake in it:
```
> mkdir out
> cd out
> cmake ..
```
Open the generated solution file `TNT.sln` in Visual Studio.
To build all targets, run _Build Solution_ from the _Build_ menu. Alternatively, right click on a
target in the _Solution Explorer_ and choose _Build_ to build a specific target.
For example, build the `material_sandbox` sample and run it from the `out` directory with:
```
> samples\Debug\material_sandbox.exe ..\assets\models\monkey\monkey.obj
```
### Android
Before building Filament for Android, make sure to build Filament for your host. Some of the
host tools are required to successfully build for Android.
Filament can be built for the following architectures:
- ARM 64-bit (`arm64-v8a`)
- ARM 32-bit (`armeabi-v7a`)
- Intel 64-bit (`x86_64`)
- Intel 32-bit (`x86`)
Note that the main target is the ARM 64-bit target. Our implementation is optimized first and
foremost for `arm64-v8a`.
To build Android on Windows machines, see [android/Windows.md](android/Windows.md).
#### Easy Android build
The easiest way to build Filament for Android is to use `build.sh` and the
`-p android` flag. For instance to build the release target:
```
$ ./build.sh -p android release
```
Run `build.sh -h` for more information.
#### Manual builds
Invoke CMake in a build directory of your choice, inside of filament's directory. The commands
below show how to build Filament for ARM 64-bit (`aarch64`).
```
$ mkdir out/android-build-release-aarch64
$ cd out/android-build-release-aarch64
$ cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=../../build/toolchain-aarch64-linux-android.cmake \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../android-release/filament ../..
```
And then invoke `ninja`:
```
$ ninja install
```
or
```
$ ninja install/strip
```
This will generate Filament's Android binaries in `out/android-release`. This location is important
to build the Android Studio projects located in `filament/android`. After install, the library
binaries should be found in `out/android-release/filament/lib/arm64-v8a`.
#### AAR
Before you attempt to build the AAR, make sure you've compiled and installed the native libraries
as explained in the sections above. You must have the following ABIs built in
`out/android-release/filament/lib/`:
- `arm64-v8a`
- `armeabi-v7a`
- `x86_64`
- `x86`
To build Filament's AAR simply open the Android Studio project in `android/`. The
AAR is a universal AAR that contains all supported build targets:
- `arm64-v8a`
- `armeabi-v7a`
- `x86_64`
- `x86`
To filter out unneeded ABIs, rely on the `abiFilters` of the project that links against Filament's
AAR.
Alternatively you can build the AAR from the command line by executing the following in the
`android/` directory:
```
$ ./gradlew -Pfilament_dist_dir=../../out/android-release/filament assembleRelease
```
The `-Pfilament_dist_dir` can be used to specify a different installation directory (it must match
the CMake install prefix used in the previous steps).
#### Using Filament's AAR
Create a new module in your project and select _Import .JAR or .AAR Package_ when prompted. Make
sure to add the newly created module as a dependency to your application.
If you do not wish to include all supported ABIs, make sure to create the appropriate flavors in
your Gradle build file. For example:
```
flavorDimensions 'cpuArch'
productFlavors {
arm8 {
dimension 'cpuArch'
ndk {
abiFilters 'arm64-v8a'
}
}
arm7 {
dimension 'cpuArch'
ndk {
abiFilters 'armeabi-v7a'
}
}
x86_64 {
dimension 'cpuArch'
ndk {
abiFilters 'x86_64'.
}
}
x86 {
dimension 'cpuArch'
ndk {
abiFilters 'x86'
}
}
universal {
dimension 'cpuArch'
}
}
```
### WebAssembly
The core Filament library can be cross-compiled to WebAssembly from either macOS or Linux. To get
started, follow the instructions for building Filament on your platform ([macOS](#macos) or
[linux](#linux)), which will ensure you have the proper dependencies installed.
Next, you need to install the Emscripten SDK. The following instructions show how to install the
same version that our continuous builds use.
```
cd <your chosen parent folder for the emscripten SDK>
curl -L https://github.com/emscripten-core/emsdk/archive/1b1f08f.zip > emsdk.zip
unzip emsdk.zip ; mv emsdk-* emsdk ; cd emsdk
python ./emsdk.py install latest
python ./emsdk.py activate latest
source ./emsdk_env.sh
```
After this you can invoke the [easy build](#easy-build) script as follows:
```
export EMSDK=<your chosen home for the emscripten SDK>
./build.sh -p webgl release
```
The EMSDK variable is required so that the build script can find the Emscripten SDK. The build
creates a `samples` folder that can be used as the root of a simple static web server. Note that you
cannot open the HTML directly from the filesystem due to CORS. One way to deal with this is to
use Python to create a quick localhost server:
```
cd out/cmake-webgl-release/web/samples
python3 -m http.server # Python 3
python -m SimpleHTTPServer # Python 2.7
```
You can then open http://localhost:8000/suzanne.html in your web browser.
Alternatively, if you have node installed you can use the
[live-server](https://www.npmjs.com/package/live-server) package, which automatically refreshes the
web page when it detects a change.
Each sample app has its own handwritten html file. Additionally the server folder contains assets
such as meshes, textures, and materials.
## Running the native samples
The `samples/` directory contains several examples of how to use Filament with SDL2.
Some of the samples accept FBX/OBJ meshes while others rely on the `filamesh` file format. To
generate a `filamesh ` file from an FBX/OBJ asset, run the `filamesh` tool
(`./tools/filamesh/filamesh` in your build directory):
```
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 '.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
```
The source environment map can be a PNG (8 or 16 bit), a PSD (16 or 32 bit), an HDR or an OpenEXR
file. The environment map can be an equirectangular projection, a horizontal cross, a vertical
cross, or a list of cubemap faces (horizontal or vertical).
`cmgen` will automatically create a directory based on the name of the source environment map. In
the example above, the final directory will be `./ibls/my_ibl/`. This directory should contain the
pre-filtered environment map (one file per cubemap face and per mip level), the environment map
texture for the skybox and a text file containing the level harmonics for indirect diffuse
lighting.
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.
## Generating C++ documentation
To generate the documentation you must first install `doxygen` and `graphviz`, then run the
following commands:
```
$ cd filament/filament
$ doxygen docs/doxygen/filament.doxygen
```
Finally simply open `docs/html/index.html` in your web browser.

View File

@@ -50,22 +50,19 @@ if (WIN32)
set(CRT_FLAGS_DEBUG "/MDd")
endif()
if (CMAKE_C_COMPILER_ID MATCHES "Clang")
# TODO: Figure out why pdb generation messes with incremental compilaton.
# IN RELEASE_WITH_DEBUG_INFO, generate debug info in .obj, no in pdb.
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${CRT_FLAGS_RELEASE} /Z7")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} ${CRT_FLAGS_RELEASE} /Z7")
# In DEBUG, avoid generating a PDB file which seems to mess with incremental compilation.
# Instead generate debug info directly inside obj files.
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${CRT_FLAGS_DEBUG} /Z7")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${CRT_FLAGS_DEBUG} /Z7")
endif()
# TODO: Figure out why pdb generation messes with incremental compilaton.
# IN RELEASE_WITH_DEBUG_INFO, generate debug info in .obj, no in pdb.
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${CRT_FLAGS_RELEASE} /Z7")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} ${CRT_FLAGS_RELEASE} /Z7")
# In RELEASE, also generate PDBs.
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${CRT_FLAGS_RELEASE} /Zi")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${CRT_FLAGS_RELEASE} /Zi")
# In DEBUG, avoid generating a PDB file which seems to mess with incremental compilation.
# Instead generate debug info directly inside obj files.
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${CRT_FLAGS_DEBUG} /Z7")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${CRT_FLAGS_DEBUG} /Z7")
endif()
# ==================================================================================================
@@ -211,6 +208,13 @@ if (ANDROID OR WEBGL)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-rtti")
endif()
# With WebGL, we disable RTTI even for debug builds because we pass emscripten::val back and forth
# between C++ and JavaScript in order to efficiently access typed arrays, which are unbound.
# NOTE: This is not documented in emscripten so we should consider a different approach.
if (WEBGL)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-rtti")
endif()
# ==================================================================================================
# Debug compiler flags
# ==================================================================================================
@@ -219,16 +223,24 @@ endif()
# -fsanitize=address causes a crash with assimp, which we can't explain for now
#set(EXTRA_SANITIZE_OPTIONS "-fsanitize=undefined -fsanitize=address")
# clang-cl.exe on Windows does not support -fstack-protector.
if (NOT CLANG_CL AND NOT MSVC)
if (NOT CLANG_CL AND NOT MSVC AND NOT WEBGL)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fstack-protector")
endif()
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${EXTRA_SANITIZE_OPTIONS}")
# Disable the stack check for macOS to workaround a known issue in clang 11.0.0.
# See: https://forums.developer.apple.com/thread/121887
if (APPLE)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-stack-check")
endif()
# ==================================================================================================
# Linker flags
# ==================================================================================================
# Strip unused sections
set(GC_SECTIONS "-Wl,--gc-sections")
if (NOT WEBGL)
set(GC_SECTIONS "-Wl,--gc-sections")
endif()
set(B_SYMBOLIC_FUNCTIONS "-Wl,-Bsymbolic-functions")
if (APPLE)
@@ -443,6 +455,7 @@ endfunction()
# Common to all platforms
add_subdirectory(${EXTERNAL}/libgtest/tnt)
add_subdirectory(${LIBRARIES}/camutils)
add_subdirectory(${LIBRARIES}/filabridge)
add_subdirectory(${LIBRARIES}/filaflat)
add_subdirectory(${LIBRARIES}/filameshio)

View File

@@ -40,3 +40,18 @@ information on using pull requests.
This project follows
[Google's Open Source Community Guidelines](https://opensource.google.com/conduct/).
## Dependencies
One of our design goals is that Filament itself should have no dependencies or as few dependencies
as possible. The current external dependencies of the runtime library include:
- STL
- robin-map (header only library)
When building with Vulkan enabled, we have a few additional small dependencies:
- vkmemalloc
- smol-v
Host tools (such as `matc` or `cmgen`) can use external dependencies freely.

839
README.md
View File

@@ -1,28 +1,59 @@
# Filament
<img alt="Android" src="build/img/android.png" width="20px" height="20px" hspace="2px"/>[![Android Build Status](https://filament-build.storage.googleapis.com/badges/build_status_android.svg)](https://filament-build.storage.googleapis.com/badges/build_link_android.html)
<img alt="iOS" src="build/img/macos.png" width="20px" height="20px" hspace="2px"/>[![iOS Build Status](https://filament-build.storage.googleapis.com/badges/build_status_ios.svg)](https://filament-build.storage.googleapis.com/badges/build_link_ios.html)
<img alt="Linux" src="build/img/linux.png" width="20px" height="20px" hspace="2px"/>[![Linux Build Status](https://filament-build.storage.googleapis.com/badges/build_status_linux.svg)](https://filament-build.storage.googleapis.com/badges/build_link_linux.html)
<img alt="macOS" src="build/img/macos.png" width="20px" height="20px" hspace="2px"/>[![MacOS Build Status](https://filament-build.storage.googleapis.com/badges/build_status_mac.svg)](https://filament-build.storage.googleapis.com/badges/build_link_mac.html)
<img alt="Windows" src="build/img/windows.png" width="20px" height="20px" hspace="2px"/>[![Windows Build Status](https://filament-build.storage.googleapis.com/badges/build_status_windows.svg)](https://filament-build.storage.googleapis.com/badges/build_link_windows.html)
<img alt="Web" src="build/img/web.png" width="20px" height="20px" hspace="2px"/>[![Web Build Status](https://filament-build.storage.googleapis.com/badges/build_status_web.svg)](https://filament-build.storage.googleapis.com/badges/build_link_web.html)
![Android Build Status](https://github.com/google/filament/workflows/Android/badge.svg)
![iOS Build Status](https://github.com/google/filament/workflows/iOS/badge.svg)
![Linux Build Status](https://github.com/google/filament/workflows/Linux/badge.svg)
![macOS Build Status](https://github.com/google/filament/workflows/macOS/badge.svg)
![Windows Build Status](https://github.com/google/filament/workflows/Windows/badge.svg)
![Web Build Status](https://github.com/google/filament/workflows/Web/badge.svg)
Filament is a real-time physically based rendering engine for Android, iOS, Linux, macOS, Windows,
and WebGL. It is designed to be as small as possible and as efficient as possible on Android.
Filament is currently used in the
[Sceneform](https://developers.google.com/ar/develop/java/sceneform/) library both at runtime on
Android devices and as the renderer inside the Android Studio plugin.
## Download
[Download Filament releases](https://github.com/google/filament/releases) to access stable builds.
Filament release archives contains host-side tools that are required to generate assets.
Make sure you always use tools from the same release as the runtime library. This is particularly
important for `matc` (material compiler).
If you prefer to live on the edge, you can download a continuous build by clicking one of the build
badges above.
If you'd rather build Filament yourself, please refer to our [build manual](BUILDING.md).
### Android
Android projects can simply declare Filament libraries as Maven dependencies:
```gradle
repositories {
// ...
mavenCentral()
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.4.4'
}
```
Here are all the libraries available in the group `com.google.android.filament`:
- `filament-android`: the Filament rendering engine itself
- `gltfio-android`: a glTF 2.0 loader for Filament, depends on `filament-android`
- `filament-utils-android`: KTX loading, Kotlin math, and camera utilities, depends on `gltfio-android`
- `filamat-android-full`: a runtime material builder/compiler. This library is large but contains
a full shader compiler/validator/optimizer
- `filamat-android-lite`: a much smaller alternative to `filamat-android-full` that can only
generate OpenGL shaders. It does not provide validation or optimizations
### Snapshots
If you prefer to live on the edge, you can download a continuous build by following the following
steps:
1. Find the [commit](https://github.com/google/filament/commits/master) you're interested in.
2. Click the green check mark under the commit message.
3. Click on the _Details_ link for the platform you're interested in.
4. On the top right, click on the _Artifacts_ dropdown and choose an artifact.
## Documentation
@@ -36,7 +67,9 @@ badges above.
- [Material Properties](https://google.github.io/filament/Material%20Properties.pdf), a reference
sheet for the standard material model.
## Samples
## Examples
### Materials
Here are a few sample materials rendered with Filament:
@@ -48,15 +81,15 @@ Here are a few sample materials rendered with Filament:
![Material 6](docs/images/samples/material_06.jpg)
![Material 8](docs/images/samples/material_08.jpg)
## Applications
### Applications
Here are a few screenshots of applications that use Filament in production:
### Google Maps AR Navigation
#### 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
![Google Search 3D/AR Viewer on Android](docs/images/samples/app_google_3d_viewer.jpg)
@@ -73,7 +106,7 @@ Here are a few screenshots of applications that use Filament in production:
- OpenGL 4.1+ for Linux, macOS and Windows
- OpenGL ES 3.0+ for Android and iOS
- Metal for macOS and iOS
- Vulkan 1.0 for Android, Linux, macOS and iOS (with MoltenVk), and Windows
- Vulkan 1.0 for Android, Linux, macOS, and Windows
- WebGL 2.0 for all platforms
### Rendering
@@ -98,695 +131,6 @@ Here are a few screenshots of applications that use Filament in production:
- FXAA, MSAA and specular anti-aliasing
- Dynamic resolution (on Android and iOS)
### Future
Many other features have been either prototyped or planned:
- IES light profiles/cookies
- Area lights
- Fog
- Color grading
- Bloom
- TAA
- etc.
## Directory structure
This repository not only contains the core Filament engine, but also its supporting libraries
and tools.
- `android`: Android libraries and projects
- `build`: Custom Gradle tasks for Android builds
- `filamat-android`: Filament material generation library (AAR) for Android
- `filament-android`: Filament library (AAR) for Android
- `samples`: Android-specific Filament samples
- `art`: Source for various artworks (logos, PDF manuals, etc.)
- `assets`: 3D assets to use with sample applications
- `build`: CMake build scripts
- `docs`: Documentation
- `math`: Mathematica notebooks used to explore BRDFs, equations, etc.
- `filament`: Filament rendering engine (minimal dependencies)
- `ide`: Configuration files for IDEs (CLion, etc.)
- `ios`: Sample projects for iOS
- `java`: Java bindings for Filament libraries
- `libs`: Libraries
- `bluegl`: OpenGL bindings for macOS, Linux and Windows
- `bluevk`: Vulkan bindings for macOS, Linux, Windows and Android
- `filabridge`: Library shared by the Filament engine and host tools
- `filaflat`: Serialization/deserialization library used for materials
- `filagui`: Helper library for [Dear ImGui](https://github.com/ocornut/imgui)
- `filamat`: Material generation library
- `filameshio`: Tiny filamesh parsing library (see also `tools/filamesh`)
- `geometry`: Mesh-related utilities
- `gltfio`: Loader and optional pipeline for glTF 2.0
- `ibl`: IBL generation tools
- `image`: Image filtering and simple transforms
- `imageio`: Image file reading / writing, only intended for internal use
- `matdbg`: DebugServer for inspecting shaders at run-time (debug builds only)
- `math`: Math library
- `rays`: Simple path tracer used for baking ambient occlusion, etc.
- `utils`: Utility library (threads, memory, data structures, etc.)
- `samples`: Sample desktop applications
- `shaders`: Shaders used by `filamat` and `matc`
- `third_party`: External libraries and assets
- `environments`: Environment maps under CC0 license that can be used with `cmgen`
- `models`: Models under permissive licenses
- `textures`: Textures under CC0 license
- `tools`: Host tools
- `cmgen`: Image-based lighting asset generator
- `filamesh`: Mesh converter
- `glslminifier`: Minifies GLSL source code
- `matc`: Material compiler
- `matinfo` Displays information about materials compiled with `matc`
- `mipgen` Generates a series of miplevels from a source image
- `normal-blending`: Tool to blend normal maps
- `resgen` Aggregates binary blobs into embeddable resources
- `roughness-prefilter`: Pre-filters a roughness map from a normal map to reduce aliasing
- `skygen`: Physically-based sky environment texture generator
- `specular-color`: Computes the specular color of conductors based on spectral data
- `web`: JavaScript bindings, documentation, and samples
## Building Filament
### Prerequisites
To build Filament, you must first install the following tools:
- CMake 3.10 (or more recent)
- clang 7.0 (or more recent)
- [ninja 1.8](https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages) (or more recent)
To build the Java based components of the project you can optionally install (recommended):
- OpenJDK 1.8 (or more recent)
Additional dependencies may be required for your operating system. Please refer to the appropriate
section below.
Building the `rays` library (used for light baking) is optional and requires the following packages:
- embree 3.0+
- libtbb-dev
To build Filament for Android you must also install the following:
- Android Studio 3.5
- Android SDK
- Android NDK "side-by-side" 20 or higher
### Environment variables
Make sure the environment variable `ANDROID_HOME` points to the location of your Android SDK.
By default our build system will attempt to compile the Java bindings. To do so, the environment
variable `JAVA_HOME` should point to the location of your JDK.
When building for WebGL, you'll also need to set `EMSDK`. See [WebAssembly](#webassembly).
### IDE
We recommend using CLion to develop for Filament. Simply open the root directory's CMakeLists.txt
in CLion to obtain a usable project.
### Easy build
Once the required OS specific dependencies listed below are installed, you can use the script
located in `build.sh` to build Filament easily on macOS and Linux.
This script can be invoked from anywhere and will produce build artifacts in the `out/` directory
inside the Filament source tree.
To trigger an incremental debug build:
```
$ ./build.sh debug
```
To trigger an incremental release build:
```
$ ./build.sh release
```
To trigger both incremental debug and release builds:
```
$ ./build.sh debug release
```
To install the libraries and executables in `out/debug/` and `out/release/`, add the `-i` flag.
You can force a clean build by adding the `-c` flag. The script offers more features described
by executing `build.sh -h`.
### Disabling Java builds
By default our build system will attempt to compile the Java bindings. If you wish to skip this
compilation step simply pass the `-j` flag to `build.sh`:
```
$ ./build.sh -j release
```
If you use CMake directly instead of the build script, pass `-DENABLE_JAVA=OFF` to CMake instead.
### Filament-specific CMake Options
The following CMake options are boolean options specific to Filament:
- `ENABLE_JAVA`: Compile Java projects: requires a JDK and the JAVA_HOME env var
- `ENABLE_LTO`: Enable link-time optimizations if supported by the compiler
- `FILAMENT_BUILD_FILAMAT`: Build filamat and JNI buildings
- `FILAMENT_SUPPORTS_METAL`: Include the Metal backend
- `FILAMENT_SUPPORTS_VULKAN`: Include the Vulkan backend
- `GENERATE_JS_DOCS`: Build WebGL documentation and tutorials
- `INSTALL_BACKEND_TEST`: Install the backend test library so it can be consumed on iOS
- `USE_EXTERNAL_GLES3`: Experimental: Compile Filament against OpenGL ES 3
To turn an option on or off:
```
$ cd <cmake-build-directory>
$ cmake . -DOPTION=ON # Relace OPTION with the option name, set to ON / OFF
```
Options can also be set with the CMake GUI.
### Linux
Make sure you've installed the following dependencies:
- `clang-7` or higher
- `libglu1-mesa-dev`
- `libc++-7-dev` (`libcxx-devel` and `libcxx-static` on Fedora) or higher
- `libc++abi-7-dev` (`libcxxabi-static` on Fedora) or higher
- `ninja-build`
- `libxi-dev`
After dependencies have been installed, we highly recommend using the [easy build](#easy-build)
script.
If you'd like to run `cmake` directly rather than using the build script, it can be invoked as
follows, with some caveats that are explained further down.
```
$ mkdir out/cmake-release
$ cd out/cmake-release
$ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../release/filament ../..
```
Your Linux distribution might default to `gcc` instead of `clang`, if that's the case invoke
`cmake` with the following command:
```
$ mkdir out/cmake-release
$ cd out/cmake-release
# Or use a specific version of clang, for instance /usr/bin/clang-7
$ CC=/usr/bin/clang CXX=/usr/bin/clang++ CXXFLAGS=-stdlib=libc++ \
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../release/filament ../..
```
You can also export the `CC` and `CXX` environment variables to always point to `clang`. Another
solution is to use `update-alternatives` to both change the default compiler, and point to a
specific version of clang:
```
$ update-alternatives --install /usr/bin/clang clang /usr/bin/clang-7 100
$ update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-7 100
$ update-alternatives --install /usr/bin/cc cc /usr/bin/clang 100
$ update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 100
```
Finally, invoke `ninja`:
```
$ ninja
```
This will build Filament, its tests and samples, and various host tools.
### macOS
To compile Filament you must have the most recent version of Xcode installed and you need to
make sure the command line tools are setup by running:
```
$ xcode-select --install
```
After installing Java 1.8 you must also ensure that your `JAVA_HOME` environment variable is
properly set. If it doesn't already point to the appropriate JDK, you can simply add the following
to your `.profile`:
```
export JAVA_HOME="$(/usr/libexec/java_home)"
```
Then run `cmake` and `ninja` to trigger a build:
```
$ mkdir out/cmake-release
$ cd out/cmake-release
$ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../release/filament ../..
$ ninja
```
### iOS
The easiest way to build Filament for iOS is to use `build.sh` and the
`-p ios` flag. For instance to build the debug target:
```
$ ./build.sh -p ios debug
```
See [ios/samples/README.md](./ios/samples/README.md) for more information.
### Windows
#### Building on Windows with the Visual Studio 2019 compiler
Install the following components:
- [Visual Studio 2019](https://www.visualstudio.com/downloads)
- [Python 3.7](https://www.python.org/ftp/python/3.7.0/python-3.7.0.exe)
- [CMake 3.14 or later](https://github.com/Kitware/CMake/releases/download/v3.14.7/cmake-3.14.7-win64-x64.msi)
Open the `x64 Native Tools Command Prompt for VS 2019`.
Create a working directory, and run cmake in it:
```
> mkdir out
> cd out
> cmake ..
```
Then, you should be able to load the generated solution file `TNT.sln` in Visual Studio and build the `material_sandbox` project.
Run it from the `out` directory with:
```
> samples\Debug\material_sandbox.exe ..\assets\models\monkey\monkey.obj
```
#### Building on Windows with the Clang compiler
The following instructions have been tested on a machine running Windows 10. They should take you
from a machine with only the operating system to a machine able to build and run Filament.
Google employees require additional steps which can be found here [go/filawin](http://go/filawin).
Install the following components:
- [Windows 10 SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk)
- [Visual Studio 2015 or 2017](https://www.visualstudio.com/downloads)
- [Clang 7](http://releases.llvm.org/download.html)
- [Python 3.7](https://www.python.org/ftp/python/3.7.0/python-3.7.0.exe)
- [Cmake 3.13 or later](https://github.com/Kitware/CMake/releases/download/v3.13.4/cmake-3.13.4-win64-x64.msi)
If you're using Visual Studio 2017, you'll also need to install the [LLVM Compiler
Toolchain](https://marketplace.visualstudio.com/items?itemName=LLVMExtensions.llvm-toolchain)
extension.
Open an appropriate Native Tools terminal for the version of Visual Studio you are using:
- VS 2015: VS2015 x64 Native Tools Command Prompt
- VS 2017: x64 Native Tools Command Prompt for VS 2017
You can find these by clicking the start button and typing "x64 native tools".
Create a working directory:
```
> mkdir out/cmake-release
> cd out/cmake-release
```
Create the msBuild project:
```
# Visual Studio 2015:
> cmake -T"LLVM-vs2014" -G "Visual Studio 14 2015 Win64" ../..
# Visual Studio 2017
> cmake ..\.. -T"LLVM" -G "Visual Studio 15 2017 Win64" ^
-DCMAKE_CXX_COMPILER:PATH="C:\Program Files\LLVM\bin\clang-cl.exe" ^
-DCMAKE_C_COMPILER:PATH="C:\Program Files\LLVM\bin\clang-cl.exe" ^
-DCMAKE_LINKER:PATH="C:\Program Files\LLVM\bin\lld-link.exe"
```
Check out the output and make sure Clang for Windows frontend was found. You should see a line
showing the following output. Note that for Visual Studio 2017 this line may list Microsoft's
compiler, but the build will still in fact use Clang and you can proceed.
```
Clang:C:/Program Files/LLVM/msbuild-bin/cl.exe
```
You are now ready to build:
```
> msbuild TNT.sln /t:material_sandbox /m /p:configuration=Release
```
Run it:
```
> samples\Release\material_sandbox.exe ..\..\assets\models\monkey\monkey.obj
```
#### Tips
- To troubleshoot an issue, use verbose mode via `/v:d` flag.
- To build a specific project, use `/t:NAME` flag (e.g: `/t:material_sandbox`).
- To build using more than one core, use parallel build flag: `/m`.
- To build a specific profile, use `/p:configuration=` (e.g: `/p:configuration=Debug`,
`/p:configuration=Release`, and `/p:configuration=RelWithDebInfo`).
- The msBuild project is what is used by Visual Studio behind the scene to build. Building from VS
or from the command-line is the same thing.
#### Building with Ninja on Windows
Alternatively, you can use [Ninja](https://ninja-build.org/) to build for Windows. An MSVC
installation is still necessary.
First, install the dependencies listed under [Windows](#Windows) as well as Ninja. Then open up a
Native Tools terminal as before. Create a build directory inside Filament and run the
following CMake command:
```
> cmake .. -G Ninja ^
-DCMAKE_CXX_COMPILER:PATH="C:\Program Files\LLVM\bin\clang-cl.exe" ^
-DCMAKE_C_COMPILER:PATH="C:\Program Files\LLVM\bin\clang-cl.exe" ^
-DCMAKE_LINKER:PATH="C:\Program Files\LLVM\bin\lld-link.exe" ^
-DCMAKE_BUILD_TYPE=Release
```
You should then be able to build by invoking Ninja:
```
> ninja
```
#### Development tips
- Before shipping a binary, make sure you used Release profile and make sure you have no libc/libc++
dependencies with [Dependency Walker](http://www.dependencywalker.com).
- Application Verifier and gflags.exe can be of great help to trackdown heap corruption. Application
Verifier is easy to setup with a GUI. For gflags, use: `gflags /p /enable pheap-buggy.exe`.
#### Running a simple test
To confirm Filament was properly built, run the following command from the build directory:
```
> samples\material_sandbox.exe --ibl=..\..\samples\envs\pillars ..\..\assets\models\sphere\sphere.obj
```
### Android
Before building Filament for Android, make sure to build Filament for your host. Some of the
host tools are required to successfully build for Android.
Filament can be built for the following architectures:
- ARM 64-bit (`arm64-v8a`)
- ARM 32-bit (`armeabi-v7a`)
- Intel 64-bit (`x86_64`)
- Intel 32-bit (`x86`)
Note that the main target is the ARM 64-bit target. Our implementation is optimized first and
foremost for `arm64-v8a`.
To build Android on Windows machines, see [android/Windows.md](android/Windows.md).
#### Easy Android build
The easiest way to build Filament for Android is to use `build.sh` and the
`-p android` flag. For instance to build the release target:
```
$ ./build.sh -p android release
```
Run `build.sh -h` for more information.
#### ARM 64-bit target (arm64-v8a)
Then invoke CMake in a build directory of your choice, inside of filament's directory:
```
$ mkdir out/android-build-release-aarch64
$ cd out/android-build-release-aarch64
$ cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=../../build/toolchain-aarch64-linux-android.cmake \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../android-release/filament ../..
```
And then invoke `ninja`:
```
$ ninja install
```
or
```
$ ninja install/strip
```
This will generate Filament's Android binaries in `out/android-release`. This location is important
to build the Android Studio projects located in `filament/android`. After install, the library
binaries should be found in `out/android-release/filament/lib/arm64-v8a`.
#### ARM 32-bit target (armeabi-v7a)
Then invoke CMake in a build directory of your choice, inside of filament's directory:
```
$ mkdir out/android-build-release-arm
$ cd out/android-build-release-arm
$ cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=../../build/toolchain-arm7-linux-android.cmake \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../android-release/filament ../..
```
And then invoke `ninja`:
```
$ ninja install
```
or
```
$ ninja install/strip
```
This will generate Filament's Android binaries in `out/android-release`. This location is important
to build the Android Studio projects located in `filament/android`. After install, the library
binaries should be found in `out/android-release/filament/lib/armeabi-v7a`.
#### Intel 64-bit target (x86_64)
Then invoke CMake in a build directory of your choice, sibling of filament's directory:
```
$ mkdir out/android-build-release-x86_64
$ cd out/android-build-release-x86_64
$ cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=../../filament/build/toolchain-x86_64-linux-android.cmake \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../out/android-release/filament ../..
```
And then invoke `ninja`:
```
$ ninja install
```
or
```
$ ninja install/strip
```
This will generate Filament's Android binaries in `out/android-release`. This location is important
to build the Android Studio projects located in `filament/android`. After install, the library
binaries should be found in `out/android-release/filament/lib/x86_64`.
#### Intel 32-bit target (x86)
Then invoke CMake in a build directory of your choice, sibling of filament's directory:
```
$ mkdir out/android-build-release-x86
$ cd out/android-build-release-x86
$ cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=../../filament/build/toolchain-x86-linux-android.cmake \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../out/android-release/filament ../..
```
And then invoke `ninja`:
```
$ ninja install
```
or
```
$ ninja install/strip
```
This will generate Filament's Android binaries in `out/android-release`. This location is important
to build the Android Studio projects located in `filament/android`. After install, the library
binaries should be found in `out/android-release/filament/lib/x86`.
### AAR
Before you attempt to build the AAR, make sure you've compiled and installed the native libraries
as explained in the sections above. You must have the following ABIs built in
`out/android-release/filament/lib/`:
- `arm64-v8a`
- `armeabi-v7a`
- `x86_64`
- `x86`
To build Filament's AAR simply open the Android Studio project in `android/filament-android`. The
AAR is a universal AAR that contains all supported build targets:
- `arm64-v8a`
- `armeabi-v7a`
- `x86_64`
- `x86`
To filter out unneeded ABIs, rely on the `abiFilters` of the project that links against Filament's
AAR.
Alternatively you can build the AAR from the command line by executing the following the
`android/filament-android` directory:
```
$ ./gradlew -Pfilament_dist_dir=../../out/android-release/filament assembleRelease
```
The `-Pfilament_dist_dir` can be used to specify a different installation directory (it must match
the CMake install prefix used in the previous steps).
### Using Filament's AAR
Create a new module in your project and select _Import .JAR or .AAR Package_ when prompted. Make
sure to add the newly created module as a dependency to your application.
If you do not wish to include all supported ABIs, make sure to create the appropriate flavors in
your Gradle build file. For example:
```
flavorDimensions 'cpuArch'
productFlavors {
arm8 {
dimension 'cpuArch'
ndk {
abiFilters 'arm64-v8a'
}
}
arm7 {
dimension 'cpuArch'
ndk {
abiFilters 'armeabi-v7a'
}
}
x86_64 {
dimension 'cpuArch'
ndk {
abiFilters 'x86_64'
}
}
x86 {
dimension 'cpuArch'
ndk {
abiFilters 'x86'
}
}
universal {
dimension 'cpuArch'
}
}
```
### WebAssembly
The core Filament library can be cross-compiled to WebAssembly from either macOS or Linux. To get
started, follow the instructions for building Filament on your platform ([macOS](#macos) or
[linux](#linux)), which will ensure you have the proper dependencies installed.
Next, you need to install the Emscripten SDK. The following instructions show how to install the
same version that our continuous builds use.
```
cd <your chosen parent folder for the emscripten SDK>
curl -L https://github.com/emscripten-core/emsdk/archive/a77638d.zip > emsdk.zip
unzip emsdk.zip
mv emsdk-* emsdk
cd emsdk
./emsdk update
./emsdk install sdk-1.38.28-64bit
./emsdk activate sdk-1.38.28-64bit
```
After this you can invoke the [easy build](#easy-build) script as follows:
```
export EMSDK=<your chosen home for the emscripten SDK>
./build.sh -p webgl release
```
The EMSDK variable is required so that the build script can find the Emscripten SDK. The build
creates a `samples` folder that can be used as the root of a simple static web server. Note that you
cannot open the HTML directly from the filesystem due to CORS. One way to deal with this is to
use Python to create a quick localhost server:
```
cd out/cmake-webgl-release/web/samples
python3 -m http.server # Python 3
python -m SimpleHTTPServer # Python 2.7
```
You can then open http://localhost:8000/suzanne.html in your web browser.
Alternatively, if you have node installed you can use the
[live-server](https://www.npmjs.com/package/live-server) package, which automatically refreshes the
web page when it detects a change.
Each sample app has its own handwritten html file. Additionally the server folder contains assets
such as meshes, textures, and materials.
## Running the native samples
The `samples/` directory contains several examples of how to use Filament with SDL2.
Some of the samples accept FBX/OBJ meshes while others rely on the `filamesh` file format. To
generate a `filamesh ` file from an FBX/OBJ asset, run the `filamesh` tool
(`./tools/filamesh/filamesh` in your build directory):
```
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 '.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
```
The source environment map can be a PNG (8 or 16 bit), a PSD (16 or 32 bit), an HDR or an OpenEXR
file. The environment map can be an equirectangular projection, a horizontal cross, a vertical
cross, or a list of cubemap faces (horizontal or vertical).
`cmgen` will automatically create a directory based on the name of the source environment map. In
the example above, the final directory will be `./ibls/my_ibl/`. This directory should contain the
pre-filtered environment map (one file per cubemap face and per mip level), the environment map
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.1`. The numerical
value is the desired roughness between 0 and 1.
## Rendering with Filament
### Native Linux, macOS and Windows
@@ -889,44 +233,73 @@ Filament on iOS is largely the same as native rendering with C++. A `CAEAGLLayer
is passed to the `createSwapChain` method. Filament for iOS supports both OpenGL ES and Vulkan via
MoltenVK.
## Generating C++ documentation
To generate the documentation you must first install `doxygen` and `graphviz`, then run the
following commands:
```
$ cd filament/filament
$ doxygen docs/doxygen/filament.doxygen
```
Finally simply open `docs/html/index.html` in your web browser.
## Assets
To get started you can use the textures and environment maps found respectively in
`third_party/textures` and `third_party/environments`. These assets are under CC0 license. Please
refer to their respective `URL.txt` files to know more about the original authors.
## Dependencies
One of our design goals is that Filament itself should have no dependencies or as few dependencies
as possible. The current external dependencies of the runtime library include:
- STL
- robin-map (header only library)
When building with Vulkan enabled, we have a few additional small dependencies:
- vkmemalloc
- smol-v
Host tools (such as `matc` or `cmgen`) can use external dependencies freely.
## How to make contributions
Please read and follow the steps in [CONTRIBUTING.md](/CONTRIBUTING.md). Make sure you are
familiar with the [code style](/CODE_STYLE.md).
## Directory structure
This repository not only contains the core Filament engine, but also its supporting libraries
and tools.
- `android`: Android libraries and projects
- `filamat-android`: Filament material generation library (AAR) for Android
- `filament-android`: Filament library (AAR) for Android
- `gltfio-android`: Filament glTF loading library (AAR) for Android
- `samples`: Android-specific Filament samples
- `art`: Source for various artworks (logos, PDF manuals, etc.)
- `assets`: 3D assets to use with sample applications
- `build`: CMake build scripts
- `docs`: Documentation
- `math`: Mathematica notebooks used to explore BRDFs, equations, etc.
- `filament`: Filament rendering engine (minimal dependencies)
- `ide`: Configuration files for IDEs (CLion, etc.)
- `ios`: Sample projects for iOS
- `java`: Java bindings for Filament libraries
- `libs`: Libraries
- `bluegl`: OpenGL bindings for macOS, Linux and Windows
- `bluevk`: Vulkan bindings for macOS, Linux, Windows and Android
- `filabridge`: Library shared by the Filament engine and host tools
- `filaflat`: Serialization/deserialization library used for materials
- `filagui`: Helper library for [Dear ImGui](https://github.com/ocornut/imgui)
- `filamat`: Material generation library
- `filameshio`: Tiny filamesh parsing library (see also `tools/filamesh`)
- `geometry`: Mesh-related utilities
- `gltfio`: Loader and optional pipeline for glTF 2.0
- `ibl`: IBL generation tools
- `image`: Image filtering and simple transforms
- `imageio`: Image file reading / writing, only intended for internal use
- `matdbg`: DebugServer for inspecting shaders at run-time (debug builds only)
- `math`: Math library
- `rays`: Simple path tracer used for baking ambient occlusion, etc.
- `utils`: Utility library (threads, memory, data structures, etc.)
- `samples`: Sample desktop applications
- `shaders`: Shaders used by `filamat` and `matc`
- `third_party`: External libraries and assets
- `environments`: Environment maps under CC0 license that can be used with `cmgen`
- `models`: Models under permissive licenses
- `textures`: Textures under CC0 license
- `tools`: Host tools
- `cmgen`: Image-based lighting asset generator
- `filamesh`: Mesh converter
- `glslminifier`: Minifies GLSL source code
- `matc`: Material compiler
- `matinfo` Displays information about materials compiled with `matc`
- `mipgen` Generates a series of miplevels from a source image
- `normal-blending`: Tool to blend normal maps
- `resgen` Aggregates binary blobs into embeddable resources
- `roughness-prefilter`: Pre-filters a roughness map from a normal map to reduce aliasing
- `skygen`: Physically-based sky environment texture generator
- `specular-color`: Computes the specular color of conductors based on spectral data
- `web`: JavaScript bindings, documentation, and samples
## License
Please see [LICENSE](/LICENSE).

View File

@@ -3,6 +3,49 @@
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.
## Next release
## v1.4.5
- The depth prepass setting in View is now ignored and deprecated.
- Fixed a threading bug with the NOOP backend.
- Improved memory management for gltfio on Android.
- Introduced `filament-utils` library with `TextureLoader`, `ModelViewer`, and Java bindings for `camutils`.
- Fix out-of-bounds bug when glTF has many UV sets.
- Added new `setMediaOverlay` API to `UiHelper` for controlling surface ordering.
- Implemented sRGB support for DXT encoded textures.
- Fix bug with incorrect world transforms computed in `TransformManager`.
- gltfio: support external resources on Android.
## v1.4.4
- Added support for solid and thin layer cubemap and screen-space refraction.
- Improved high roughness material rendering by default when regenerating environments maps.
- Fix bad instruction exception with macOS Catalina.
- Fixed bad state after removing an IBL from the Scene.
- Fixed incorrect punctual light binning (affected Metal and Vulkan backends).
- Fixed crash when using a Metal headless SwapChain with an Intel integrated GPU.
- Added support for ASTC textures on iOS with Metal backend.
- Added new heightfield sample.
- Removed `<iostream>` from math headers.
- cmgen now places KTX files directly in the specified deployment folder.
## v1.4.3
- Fixed an assertion when a parameter array occurs last in a material definition.
- Fixed morph shapes not rendering in WebGL.
- Added support for the latest version of emscripten.
- gltfio: fixed blackness seen with default material.
- Added ETC2 and BC compressed texture support to Metal backend.
- Rendering a `SAMPLER_EXTERNAL` texture before setting an external image no longer results in GPU errors.
- Fixed a normals issue when skinning without a normal map or anisotropy.
- Fixed an issue where transparent views couldn't be used with post-processing.
- Always use higher quality 3-bands SH for indirect lighting, even on mobile.
- The Metal backend can now handle binding individual planes of YUV external images.
- Added support for depth buffer when post-processing is turned off
- Improved performance on GPUs that use tile-based rendering
## v1.4.2
- Cleaned up the validation strategy in Engine (checks for use-after-destroy etc).
@@ -11,6 +54,7 @@ A new header is inserted each time a *tag* is created.
- gltfio: Added Java / Kotlin bindings for Animator.
- gltfio: Fixed panic with the Android gltf-bloom demo.
- gltfio: Java clients should no longer call Filament#init.
- Improved IBL diffuse by allowing to use the specular cubemap at `roughness` = 1 instead of Spherical Harmonics
## v1.4.1

9
android/.gitignore vendored Normal file
View File

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

58
android/build.gradle Normal file
View File

@@ -0,0 +1,58 @@
// 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 {
def filamentPath = file("../out/android-release/filament").absolutePath
if (project.hasProperty("filament_dist_dir")) {
filamentPath = file("$filament_dist_dir").absolutePath
}
ext.filamentPath = filamentPath
// Our minSdkVersion is actually 19, we lie and say 14 here so apps don't have
// to increase their minSdkVersion unnecessarily. It is however up to them to
// ensure they do not initialize Filament on API levels < 19.
ext.versions = [
'minSdk': 14,
'targetSdk': 29,
'compileSdk': 29,
'kotlin': '1.3.61',
'buildTools': '29.0.2',
]
ext.deps = [
'androidx': [
'annotations': "androidx.annotation:annotation:1.1.0",
'core': "androidx.core:core:1.1.0",
],
'kotlin': "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${versions.kotlin}"
]
repositories {
mavenCentral()
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.0-rc01'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
}
}
subprojects { project ->
group = GROUP
version = VERSION_NAME
repositories {
mavenCentral()
google()
jcenter()
}
}

9
android/buildSrc/.gitignore vendored Normal file
View File

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

View File

@@ -9,61 +9,63 @@
import java.nio.file.Paths
import org.gradle.internal.os.OperatingSystem
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.LogLevel;
import org.gradle.api.*
import org.gradle.api.logging.*
import org.gradle.api.tasks.*
import org.gradle.api.tasks.incremental.*
def filamentToolsPath = file("../../../../out/release/filament")
if (project.hasProperty("filament_tools_dir")) {
filamentToolsPath = file("$filament_tools_dir")
}
class TaskWithBinary extends DefaultTask {
private final String binaryName
private File binaryPath = null
List<File> getBinaries(String name, File toolsPath) {
def tool = ["/bin/${name}.exe", "/bin/${name}"]
def toolFullPath = tool.collect { path -> Paths.get(toolsPath.absolutePath, path).toFile() }
// Ensure that at least one matc binary and Filament library is present
if (!toolFullPath.any { path -> file(path).exists() }) {
throw new StopActionException("No ${name} binary could be found in " + toolsPath +
"/bin. Ensure Filament has been built/installed before building this app.")
TaskWithBinary(String name) {
binaryName = name
}
return toolFullPath
}
String getBinaryName() {
return binaryName
}
ext.matcFullPath = getBinaries('matc', filamentToolsPath)
ext.cmgenFullPath = getBinaries('cmgen', filamentToolsPath)
ext.filameshFullPath = getBinaries('filamesh', filamentToolsPath)
ext.resgenFullPath = getBinaries('resgen', filamentToolsPath)
File getBinary() {
if (binaryPath == null) {
def tool = ["/bin/${binaryName}.exe", "/bin/${binaryName}"]
def fullPath = tool.collect { path ->
Paths.get(project.ext.filamentToolsPath.absolutePath, path).toFile()
}
binaryPath = OperatingSystem.current().isWindows() ? fullPath[0] : fullPath[1]
}
return binaryPath
}
}
class LogOutputStream extends ByteArrayOutputStream {
private final Logger logger;
private final LogLevel level;
private final Logger logger
private final LogLevel level
public LogOutputStream(Logger logger, LogLevel level) {
this.logger = logger;
this.level = level;
LogOutputStream(Logger logger, LogLevel level) {
this.logger = logger
this.level = level
}
public Logger getLogger() {
return logger;
Logger getLogger() {
return logger
}
public LogLevel getLevel() {
return level;
LogLevel getLevel() {
return level
}
@Override
public void flush() {
logger.log(level, toString());
reset();
void flush() {
logger.log(level, toString())
reset()
}
}
// Custom task to compile material files using matc
// This task handles incremental builds
class MaterialCompiler extends DefaultTask {
File matcPath
class MaterialCompiler extends TaskWithBinary {
@SuppressWarnings("GroovyUnusedDeclaration")
@InputDirectory
File inputDir
@@ -72,8 +74,7 @@ class MaterialCompiler extends DefaultTask {
File outputDir
MaterialCompiler() {
matcPath = OperatingSystem.current().isWindows() ?
project.ext.matcFullPath[0] : project.ext.matcFullPath[1]
super("matc")
}
@SuppressWarnings("GroovyUnusedDeclaration")
@@ -94,10 +95,15 @@ class MaterialCompiler extends DefaultTask {
out.write(header)
out.flush()
if (!getBinary().exists()) {
throw new GradleException("Could not find ${getBinary()}." +
" Ensure Filament has been built/installed before building this app.")
}
project.exec {
standardOutput out
errorOutput err
executable "${matcPath}"
executable "${getBinary()}"
args('-a', 'all', '-p', 'mobile', '-o', getOutputFile(file), file)
}
}
@@ -114,9 +120,8 @@ class MaterialCompiler extends DefaultTask {
// Custom task to process IBLs using cmgen
// This task handles incremental builds
class IblGenerator extends DefaultTask {
File cmgenPath
String cmgenArgs = null;
class IblGenerator extends TaskWithBinary {
String cmgenArgs = null
@SuppressWarnings("GroovyUnusedDeclaration")
@InputFile
@@ -126,8 +131,7 @@ class IblGenerator extends DefaultTask {
File outputDir
IblGenerator() {
cmgenPath = OperatingSystem.current().isWindows() ?
project.ext.cmgenFullPath[0] : project.ext.cmgenFullPath[1]
super("cmgen")
}
@SuppressWarnings("GroovyUnusedDeclaration")
@@ -147,21 +151,20 @@ class IblGenerator extends DefaultTask {
out.write(header)
out.flush()
project.exec {
standardOutput out
errorOutput err
executable "${cmgenPath}"
args('-x', outputDir, file)
if (!getBinary().exists()) {
throw new GradleException("Could not find ${getBinary()}." +
" Ensure Filament has been built/installed before building this app.")
}
project.exec {
standardOutput out
if (!cmgenArgs) {
cmgenArgs = '--format=rgb32f --extract-blur=0.08 --extract=' + outputDir.absolutePath
cmgenArgs = '-q -x ' + outputDir +
' --format=rgb32f --extract-blur=0.08 --extract=' + outputDir.absolutePath
}
cmgenArgs = cmgenArgs + " " + file
errorOutput err
executable "${cmgenPath}"
executable "${getBinary()}"
args(cmgenArgs.split())
}
}
@@ -178,9 +181,7 @@ class IblGenerator extends DefaultTask {
// Custom task to compile mesh files using filamesh
// This task handles incremental builds
class MeshCompiler extends DefaultTask {
File filameshPath
class MeshCompiler extends TaskWithBinary {
@SuppressWarnings("GroovyUnusedDeclaration")
@InputFile
File inputFile
@@ -189,8 +190,7 @@ class MeshCompiler extends DefaultTask {
File outputDir
MeshCompiler() {
filameshPath = OperatingSystem.current().isWindows() ?
project.ext.filameshFullPath[0] : project.ext.filameshFullPath[1]
super("filamesh")
}
@SuppressWarnings("GroovyUnusedDeclaration")
@@ -210,10 +210,15 @@ class MeshCompiler extends DefaultTask {
out.write(header)
out.flush()
if (!getBinary().exists()) {
throw new GradleException("Could not find ${getBinary()}." +
" Ensure Filament has been built/installed before building this app.")
}
project.exec {
standardOutput out
errorOutput err
executable "${filameshPath}"
executable "${getBinary()}"
args(file, getOutputFile(file))
}
}
@@ -228,8 +233,50 @@ class MeshCompiler extends DefaultTask {
}
}
task compileMaterials(type: MaterialCompiler)
class FilamentToolsPluginExtension {
File materialInputDir
File materialOutputDir
task generateIbl(type: IblGenerator)
String cmgenArgs
File iblInputFile
File iblOutputDir
task compileMesh(type: MeshCompiler)
File meshInputFile
File meshOutputDir
}
class FilamentToolsPlugin implements Plugin<Project> {
void apply(Project project) {
def extension = project.extensions.create('filamentTools', FilamentToolsPluginExtension)
project.ext.filamentToolsPath = project.file("../../../out/release/filament")
if (project.hasProperty("filament_tools_dir")) {
project.ext.filamentToolsPath = project.file("$filament_tools_dir")
}
project.tasks.register("filamentCompileMaterials", MaterialCompiler) {
enabled = extension.materialInputDir != null && extension.materialOutputDir != null
inputDir = extension.materialInputDir
outputDir = extension.materialOutputDir
}
project.preBuild.dependsOn "filamentCompileMaterials"
project.tasks.register("filamentGenerateIbl", IblGenerator) {
enabled = extension.iblInputFile != null && extension.iblOutputDir != null
cmgenArgs = extension.cmgenArgs
inputFile = extension.iblInputFile
outputDir = extension.iblOutputDir
}
project.preBuild.dependsOn "filamentGenerateIbl"
project.tasks.register("filamentCompileMesh", MeshCompiler) {
enabled = extension.meshInputFile != null && extension.meshOutputDir != null
inputFile = extension.meshInputFile
outputDir = extension.meshOutputDir
}
project.preBuild.dependsOn "filamentCompileMesh"
}
}

View File

@@ -27,39 +27,6 @@ struct {
jmethodID execute;
} gCallbackUtils;
JniCallback* JniCallback::make(filament::Engine* engine,
JNIEnv* env, jobject handler, jobject callback) {
void* that = engine->streamAlloc(sizeof(JniCallback), alignof(JniCallback));
return new (that) JniCallback(env, handler, callback);
}
JniCallback::JniCallback(JNIEnv* env, jobject handler, jobject callback)
: mEnv(env)
, mHandler(env->NewGlobalRef(handler))
, mCallback(env->NewGlobalRef(callback)) {
}
JniCallback::~JniCallback() {
if (mHandler && mCallback) {
#ifdef ANDROID
if (mEnv->IsInstanceOf(mHandler, gCallbackUtils.handlerClass)) {
mEnv->CallBooleanMethod(mHandler, gCallbackUtils.post, mCallback);
}
#endif
if (mEnv->IsInstanceOf(mHandler, gCallbackUtils.executorClass)) {
mEnv->CallVoidMethod(mHandler, gCallbackUtils.execute, mCallback);
}
}
mEnv->DeleteGlobalRef(mHandler);
mEnv->DeleteGlobalRef(mCallback);
}
void JniCallback::invoke(void*, size_t, void* user) {
JniCallback* data = reinterpret_cast<JniCallback*>(user);
// don't call delete here, because we don't own the storage
data->~JniCallback();
}
JniBufferCallback* JniBufferCallback::make(filament::Engine* engine,
JNIEnv* env, jobject handler, jobject callback, AutoBuffer&& buffer) {
void* that = engine->streamAlloc(sizeof(JniBufferCallback), alignof(JniBufferCallback));
@@ -95,6 +62,37 @@ void JniBufferCallback::invoke(void*, size_t, void* user) {
data->~JniBufferCallback();
}
JniImageCallback* JniImageCallback::make(filament::Engine* engine,
JNIEnv* env, jobject handler, jobject callback, long image) {
void* that = engine->streamAlloc(sizeof(JniImageCallback), alignof(JniImageCallback));
return new (that) JniImageCallback(env, handler, callback, image);
}
JniImageCallback::JniImageCallback(JNIEnv* env, jobject handler, jobject callback, long image)
: mEnv(env)
, mHandler(env->NewGlobalRef(handler))
, mCallback(env->NewGlobalRef(callback))
, mImage(image) { }
JniImageCallback::~JniImageCallback() {
if (mHandler && mCallback) {
#ifdef ANDROID
if (mEnv->IsInstanceOf(mHandler, gCallbackUtils.handlerClass)) {
mEnv->CallBooleanMethod(mHandler, gCallbackUtils.post, mCallback);
}
#endif
if (mEnv->IsInstanceOf(mHandler, gCallbackUtils.executorClass)) {
mEnv->CallVoidMethod(mHandler, gCallbackUtils.execute, mCallback);
}
}
mEnv->DeleteGlobalRef(mHandler);
mEnv->DeleteGlobalRef(mCallback);
}
void JniImageCallback::invoke(void* image, void* user) {
reinterpret_cast<JniImageCallback*>(user)->~JniImageCallback();
}
void registerCallbackUtils(JNIEnv *env) {
#ifdef ANDROID
gCallbackUtils.handlerClass = env->FindClass("android/os/Handler");

View File

@@ -23,21 +23,6 @@
#include <filament/Engine.h>
struct JniCallback {
static JniCallback* make(filament::Engine* engine,
JNIEnv* env, jobject handler, jobject callback);
static void invoke(void* buffer, size_t n, void* user);
private:
JniCallback(JNIEnv* env, jobject handler, jobject callback);
~JniCallback();
JNIEnv* mEnv;
jobject mHandler;
jobject mCallback;
};
struct JniBufferCallback {
static JniBufferCallback* make(filament::Engine* engine,
JNIEnv* env, jobject handler, jobject callback, AutoBuffer&& buffer);
@@ -53,3 +38,19 @@ private:
jobject mCallback;
AutoBuffer mBuffer;
};
struct JniImageCallback {
static JniImageCallback* make(filament::Engine* engine, JNIEnv* env, jobject handler,
jobject runnable, long image);
static void invoke(void* image, void* user);
private:
JniImageCallback(JNIEnv* env, jobject handler, jobject runnable, long image);
~JniImageCallback();
JNIEnv* mEnv;
jobject mHandler;
jobject mCallback;
long mImage;
};

View File

@@ -1,55 +1,18 @@
// 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.5.0'
}
}
allprojects {
repositories {
google()
jcenter()
}
}
group = "com.google.android.filament"
version = "1.3"
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 29
buildToolsVersion versions.buildTools
compileSdkVersion versions.compileSdk
defaultConfig {
minSdkVersion 14
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk
externalNativeBuild {
cmake {
arguments.add("-DANDROID_PIE=ON")
arguments.add("-DANDROID_PLATFORM=android-19")
arguments.add("-DANDROID_PLATFORM=android-${versions.targetSdk}".toString())
arguments.add("-DANDROID_STL=c++_static")
arguments.add("-DFILAMENT_DIST_DIR=${filament_path}".toString())
arguments.add("-DFILAMENT_DIST_DIR=${filamentPath}".toString())
cppFlags.add("-std=c++14")
if (project.hasProperty('extra_cmake_args')) {
arguments.add(extra_cmake_args)
@@ -58,13 +21,6 @@ android {
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
flavorDimensions "functionality"
productFlavors {
full {
@@ -101,6 +57,23 @@ android {
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:support-annotations:28.0.0'
implementation deps.androidx.annotations
}
apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
afterEvaluate { project ->
publishing {
publications {
fullRelease(MavenPublication) {
artifactId = POM_ARTIFACT_ID_FULL
from components.fullRelease
}
liteRelease(MavenPublication) {
artifactId = POM_ARTIFACT_ID_LITE
from components.liteRelease
}
}
}
}

View File

@@ -0,0 +1,4 @@
POM_NAME=Filament Material Builder
POM_ARTIFACT_ID_FULL=filamat-android-full
POM_ARTIFACT_ID_LITE=filamat-android-lite
POM_PACKAGING=aar

View File

@@ -1,5 +0,0 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -1,10 +0,0 @@
/*
* 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
*/
rootProject.name = 'filamat-android'

View File

@@ -16,7 +16,7 @@
package com.google.android.filament.filamat;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
import java.nio.ByteBuffer;
public class MaterialBuilder {

View File

@@ -16,7 +16,7 @@
package com.google.android.filament.filamat;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
import java.nio.ByteBuffer;
public class MaterialPackage {

View File

@@ -1,113 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<codeStyleSettings language="XML">
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
</code_scheme>
</component>

View File

@@ -1,5 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
</wildcardResourcePatterns>
</component>
</project>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>

View File

@@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="5">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/filament-android.iml" filepath="$PROJECT_DIR$/filament-android.iml" />
</modules>
</component>
</project>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
</component>
</project>

View File

@@ -1,58 +1,18 @@
// 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.5.0'
}
}
allprojects {
repositories {
google()
jcenter()
}
}
group = "com.google.android.filament"
version = "1.3"
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 29
buildToolsVersion versions.buildTools
compileSdkVersion versions.compileSdk
defaultConfig {
// Our minSdkVersion is actually 19, we lie and say 14 here so apps don't have
// to increase their minSdkVersion unnecessarily. It is however up to them to
// ensure they do not initialize Filament on API levels < 19.
minSdkVersion 14
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk
externalNativeBuild {
cmake {
arguments.add("-DANDROID_PIE=ON")
arguments.add("-DANDROID_PLATFORM=android-19")
arguments.add("-DANDROID_PLATFORM=android-${versions.targetSdk}".toString())
arguments.add("-DANDROID_STL=c++_static")
arguments.add("-DFILAMENT_DIST_DIR=${filament_path}".toString())
arguments.add("-DFILAMENT_DIST_DIR=${filamentPath}".toString())
cppFlags.add("-std=c++14")
if (project.hasProperty('extra_cmake_args')) {
arguments.add(extra_cmake_args)
@@ -61,13 +21,6 @@ android {
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
@@ -93,6 +46,18 @@ android {
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:support-annotations:28.0.0'
implementation deps.androidx.annotations
}
apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
afterEvaluate { project ->
publishing {
publications {
release(MavenPublication) {
artifactId = POM_ARTIFACT_ID
from components.release
}
}
}
}

View File

@@ -0,0 +1,3 @@
POM_NAME=Filament
POM_ARTIFACT_ID=filament-android
POM_PACKAGING=aar

View File

@@ -1,172 +0,0 @@
#!/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" "$@"

View File

@@ -1,84 +0,0 @@
@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

@@ -1,22 +0,0 @@
# 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
# JNI is an entry point that's hard to keep track of, so there's
# an annotation to mark fields and methods used by native code.
# Keep the annotations that proguard needs to process.
-keep class com.google.android.filament.proguard.UsedBy*
# Just because native code accesses members of a class, does not mean that the
# class itself needs to be annotated - only annotate classes that are
# referenced themselves in native code.
-keep @com.google.android.filament.proguard.UsedBy* class * {
<init>();
}
-keepclassmembers class * {
@com.google.android.filament.proguard.UsedBy* *;
}

View File

@@ -1 +0,0 @@
rootProject.name = 'filament-android'

View File

@@ -18,6 +18,9 @@
#include <filament/Engine.h>
#include <utils/Entity.h>
#include <utils/EntityManager.h>
using namespace filament;
using namespace utils;
@@ -59,6 +62,13 @@ Java_com_google_android_filament_Engine_nCreateSwapChain(JNIEnv* env,
return (jlong) engine->createSwapChain(win, (uint64_t) flags);
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_Engine_nCreateSwapChainHeadless(JNIEnv* env,
jclass klass, jlong nativeEngine, jint width, jint height, jlong flags) {
Engine* engine = (Engine*) nativeEngine;
return (jlong) engine->createSwapChain(width, height, (uint64_t) flags);
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_Engine_nCreateSwapChainFromRawPointer(JNIEnv*,
jclass, jlong nativeEngine, jlong pointer, jlong flags) {

View File

@@ -22,6 +22,8 @@
#include <filament/IndexBuffer.h>
#include <backend/BufferDescriptor.h>
#include "common/CallbackUtils.h"
#include "common/NioUtils.h"

View File

@@ -135,10 +135,31 @@ Java_com_google_android_filament_IndirectLight_nGetDirectionEstimate(JNIEnv* env
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_IndirectLight_nGetColorEstimate(JNIEnv* env, jclass,
jlong nativeIndirectLight, jfloatArray outColor_, float x, float y, float z) {
jlong nativeIndirectLight, jfloatArray outColor_, jfloat x, jfloat y, jfloat z) {
IndirectLight *indirectLight = (IndirectLight *) nativeIndirectLight;
jfloat *outColor = env->GetFloatArrayElements(outColor_, NULL);
*reinterpret_cast<filament::math::float4*>(outColor) =
indirectLight->getColorEstimate(math::float3{x, y, z});
env->ReleaseFloatArrayElements(outColor_, outColor, 0);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_IndirectLight_nGetDirectionEstimateStatic(JNIEnv *env, jclass,
jfloatArray sh_, jfloatArray outDirection_) {
jfloat* sh = env->GetFloatArrayElements(sh_, NULL);
jfloat *outDirection = env->GetFloatArrayElements(outDirection_, NULL);
*reinterpret_cast<filament::math::float3*>(outDirection) = IndirectLight::getDirectionEstimate((filament::math::float3*)sh);
env->ReleaseFloatArrayElements(outDirection_, outDirection, 0);
env->ReleaseFloatArrayElements(sh_, sh, JNI_ABORT);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_IndirectLight_nGetColorEstimateStatic(JNIEnv *env, jclass,
jfloatArray outColor_, jfloatArray sh_, jfloat x, jfloat y, jfloat z) {
jfloat* sh = env->GetFloatArrayElements(sh_, NULL);
jfloat *outColor = env->GetFloatArrayElements(outColor_, NULL);
*reinterpret_cast<filament::math::float4*>(outColor) =
IndirectLight::getColorEstimate((filament::math::float3*)sh, math::float3{x, y, z});
env->ReleaseFloatArrayElements(outColor_, outColor, 0);
env->ReleaseFloatArrayElements(sh_, sh, JNI_ABORT);
}

View File

@@ -18,6 +18,8 @@
#include <filament/LightManager.h>
#include <utils/Entity.h>
using namespace filament;
using namespace utils;

View File

@@ -84,6 +84,23 @@ Java_com_google_android_filament_Material_nGetBlendingMode(JNIEnv*, jclass,
return (jint) material->getBlendingMode();
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_google_android_filament_Material_nGetRefraction(JNIEnv*, jclass,
jlong nativeMaterial) {
Material* material = (Material*) nativeMaterial;
return (jint)material->getRefractionMode();
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_google_android_filament_Material_nGetRefractionType(JNIEnv*, jclass,
jlong nativeMaterial) {
Material* material = (Material*) nativeMaterial;
return (jint) material->getRefractionType();
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_google_android_filament_Material_nGetVertexDomain(JNIEnv*, jclass,

View File

@@ -18,6 +18,10 @@
#include <jni.h>
#include <filament/RenderableManager.h>
#include <filament/MaterialInstance.h>
#include <utils/Entity.h>
#include "common/NioUtils.h"
using namespace filament;

View File

@@ -97,6 +97,42 @@ Java_com_google_android_filament_Renderer_nReadPixels(JNIEnv *env, jclass,
return 0;
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_Renderer_nReadPixelsEx(JNIEnv *env, jclass,
jlong nativeRenderer, jlong nativeEngine, jlong nativeRenderTarget,
jint xoffset, jint yoffset, jint width, jint height,
jobject storage, jint remaining,
jint left, jint top, jint type, jint alignment, jint stride, jint format,
jobject handler, jobject runnable) {
Renderer *renderer = (Renderer *) nativeRenderer;
Engine *engine = (Engine *) nativeEngine;
RenderTarget *renderTarget = (RenderTarget *) nativeRenderTarget;
stride = stride ? stride : width;
size_t sizeInBytes = PixelBufferDescriptor::computeDataSize(
(PixelDataFormat) format, (PixelDataType) type,
(size_t) stride, (size_t) (height + top), (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));
PixelBufferDescriptor desc(buffer, sizeInBytes, (backend::PixelDataFormat) format,
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t) left, (uint32_t) top,
(uint32_t) stride, &JniBufferCallback::invoke, callback);
renderer->readPixels(renderTarget,
uint32_t(xoffset), uint32_t(yoffset), uint32_t(width), uint32_t(height),
std::move(desc));
return 0;
}
extern "C" JNIEXPORT jdouble JNICALL
Java_com_google_android_filament_Renderer_nGetUserTime(JNIEnv*, jclass, jlong nativeRenderer) {
Renderer *renderer = (Renderer *) nativeRenderer;

View File

@@ -18,6 +18,8 @@
#include <filament/Scene.h>
#include <utils/Entity.h>
using namespace filament;
using namespace utils;

View File

@@ -24,6 +24,25 @@
#include "common/NioUtils.h"
#include "common/CallbackUtils.h"
#ifdef ANDROID
#if __has_include(<android/hardware_buffer_jni.h>)
#include <android/hardware_buffer_jni.h>
#else
struct AHardwareBuffer;
typedef struct AHardwareBuffer AHardwareBuffer;
#endif
#include <android/log.h>
#include <dlfcn.h>
using PFN_FROMHARDWAREBUFFER = AHardwareBuffer* (*)(JNIEnv*, jobject);
static PFN_FROMHARDWAREBUFFER AHardwareBuffer_fromHardwareBuffer_fn = nullptr;
static bool sHardwareBufferSupported = true;
#endif
using namespace filament;
using namespace backend;
@@ -108,10 +127,10 @@ Java_com_google_android_filament_Stream_nBuilderBuild(JNIEnv*, jclass,
return (jlong) builder->builder()->build(*engine);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Stream_nIsNative(JNIEnv*, jclass, jlong nativeStream) {
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_Stream_nGetStreamType(JNIEnv*, jclass, jlong nativeStream) {
Stream* stream = (Stream*) nativeStream;
return (jboolean) stream->isNativeStream();
return (jint) stream->getStreamType();
}
extern "C" JNIEXPORT void JNICALL
@@ -160,3 +179,44 @@ Java_com_google_android_filament_Stream_nGetTimestamp(JNIEnv*, jclass, jlong nat
Stream *stream = (Stream *) nativeStream;
return stream->getTimestamp();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Stream_nSetAcquiredImage(JNIEnv* env, jclass, jlong nativeStream,
jlong nativeEngine, jobject hwbuffer, jobject handler, jobject runnable) {
Engine* engine = (Engine*) nativeEngine;
Stream* stream = (Stream*) nativeStream;
#ifdef ANDROID
// This function is not available before NDK 15 or before Android 8.
if (UTILS_UNLIKELY(!AHardwareBuffer_fromHardwareBuffer_fn)) {
if (!sHardwareBufferSupported) {
return;
}
AHardwareBuffer_fromHardwareBuffer_fn = (PFN_FROMHARDWAREBUFFER) dlsym(RTLD_DEFAULT, "AHardwareBuffer_fromHardwareBuffer");
if (!AHardwareBuffer_fromHardwareBuffer_fn) {
__android_log_print(ANDROID_LOG_WARN, "Filament", "AHardwareBuffer_fromHardwareBuffer is not available.");
sHardwareBufferSupported = false;
}
return;
}
AHardwareBuffer* nativeBuffer = AHardwareBuffer_fromHardwareBuffer_fn(env, hwbuffer);
if (!nativeBuffer) {
__android_log_print(ANDROID_LOG_INFO, "Filament", "Unable to obtain native HardwareBuffer.");
return;
}
auto* callback = JniImageCallback::make(engine, env, handler, runnable, (long) nativeBuffer);
#else
// TODO: for non-Android platforms, it is unclear how to go from "jobject" to "void*"
// For now this code is reserved for future use.
auto* callback = JniImageCallback::make(engine, env, handler, runnable, 0);
void* nativeBuffer = nullptr;
#endif
stream->setAcquiredImage((void*) nativeBuffer, &JniImageCallback::invoke, callback);
}

View File

@@ -17,6 +17,7 @@
#include <jni.h>
#include <filament/View.h>
#include <filament/Viewport.h>
using namespace filament;
@@ -241,8 +242,14 @@ Java_com_google_android_filament_View_nGetAmbientOcclusion(JNIEnv*, jclass, jlon
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetAmbientOcclusionOptions(JNIEnv*, jclass,
jlong nativeView, jfloat radius, jfloat bias, jfloat power, jfloat resolution) {
jlong nativeView, jfloat radius, jfloat bias, jfloat power, jfloat resolution, jfloat intensity) {
View* view = (View*) nativeView;
View::AmbientOcclusionOptions options = { .radius = radius, .bias = bias, .power = power, .resolution = resolution};
View::AmbientOcclusionOptions options = {
.radius = radius,
.bias = bias,
.power = power,
.resolution = resolution,
.intensity = intensity
};
view->setAmbientOcclusionOptions(options);
}

View File

@@ -17,7 +17,16 @@
#include <stdio.h>
#include <jawt.h>
#if defined(__has_include)
#if __has_include(<darwin/jawt_md.h>)
#include <darwin/jawt_md.h>
#else
#include <jawt_md.h>
#endif
#else
#include <darwin/jawt_md.h>
#endif
#include <filament/Engine.h>
#include "JAWTUtils.h"

View File

@@ -16,9 +16,9 @@
package com.google.android.filament;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.Size;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Size;
final class Asserts {
private Asserts() {

View File

@@ -16,8 +16,8 @@
package com.google.android.filament;
import android.support.annotation.NonNull;
import android.support.annotation.Size;
import androidx.annotation.NonNull;
import androidx.annotation.Size;
/**
* An axis-aligned 3D box represented by its center and half-extent.

View File

@@ -16,9 +16,9 @@
package com.google.android.filament;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.Size;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Size;
/**
* Camera represents the eye through which the scene is viewed.

View File

@@ -16,8 +16,8 @@
package com.google.android.filament;
import android.support.annotation.NonNull;
import android.support.annotation.Size;
import androidx.annotation.NonNull;
import androidx.annotation.Size;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

View File

@@ -16,7 +16,7 @@
package com.google.android.filament;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
import com.google.android.filament.proguard.UsedByReflection;
@@ -119,13 +119,17 @@ public class Engine {
*/
DEFAULT,
/**
* Selects the OpenGL ES driver.
* Selects the OpenGL driver (which supports OpenGL ES as well).
*/
OPENGL,
/**
* Selects the experimental Vulkan driver.
* Selects the Vulkan driver if the platform supports it.
*/
VULKAN,
/**
* Selects the Metal driver if the platform supports it.
*/
METAL,
/**
* Selects the no-op driver for testing purposes.
*/
@@ -290,6 +294,32 @@ public class Engine {
throw new IllegalArgumentException("Invalid surface " + surface);
}
/**
* Creates a headless {@link SwapChain}
*
* @param width width of the rendering buffer
* @param height height of the rendering buffer
* @param flags configuration flags, see {@link SwapChain}
*
* @return a newly created {@link SwapChain} object
*
* @exception IllegalStateException can be thrown if the SwapChain couldn't be created
*
* @see SwapChain#CONFIG_DEFAULT
* @see SwapChain#CONFIG_TRANSPARENT
* @see SwapChain#CONFIG_READABLE
*
*/
@NonNull
public SwapChain createSwapChain(int width, int height, long flags) {
if (width >= 0 && height >= 0) {
long nativeSwapChain = nCreateSwapChainHeadless(getNativeObject(), width, height, flags);
if (nativeSwapChain == 0) throw new IllegalStateException("Couldn't create SwapChain");
return new SwapChain(nativeSwapChain, null);
}
throw new IllegalArgumentException("Invalid parameters");
}
/**
* Creates a {@link SwapChain} from a {@link NativeSurface}.
*
@@ -608,6 +638,7 @@ public class Engine {
private static native void nDestroyEngine(long nativeEngine);
private static native long nGetBackend(long nativeEngine);
private static native long nCreateSwapChain(long nativeEngine, Object nativeWindow, long flags);
private static native long nCreateSwapChainHeadless(long nativeEngine, int width, int height, long flags);
private static native long nCreateSwapChainFromRawPointer(long nativeEngine, long pointer, long flags);
private static native void nDestroySwapChain(long nativeEngine, long nativeSwapChain);
private static native long nCreateView(long nativeEngine);

View File

@@ -16,8 +16,8 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import com.google.android.filament.proguard.UsedByReflection;

View File

@@ -15,7 +15,7 @@ package com.google.android.filament;
* limitations under the License.
*/
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
public class Fence {
private long mNativeObject;
@@ -37,6 +37,9 @@ public class Fence {
TIMEOUT_EXPIRED
}
/**
* Blocks the current thread until the Fence signals.
*/
public FenceStatus wait(@NonNull Mode mode, long timeoutNanoSeconds) {
int nativeResult = nWait(getNativeObject(), mode.ordinal(), timeoutNanoSeconds);
switch (nativeResult) {

View File

@@ -16,9 +16,9 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.nio.Buffer;
import java.nio.BufferOverflowException;

View File

@@ -16,10 +16,10 @@
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;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Size;
import com.google.android.filament.proguard.UsedByReflection;
@@ -63,7 +63,10 @@ import com.google.android.filament.proguard.UsedByReflection;
* <h1>Irradiance</h1>
*
* <p>The irradiance represents the light that comes from the environment and shines an
* object's surface. It is represented as
* object's surface.
* The irradiance is calculated automatically from the Reflections (see below), and generally
* doesn't need to be provided explicitly. However, it can be provided separately from the
* Reflections as
* <a href="https://en.wikipedia.org/wiki/Spherical_harmonics">Spherical Harmonics</a> (SH) of 1, 2 or
* 3 bands, respectively 1, 4 or 9 coefficients.</p>
*
@@ -83,8 +86,7 @@ import com.google.android.filament.proguard.UsedByReflection;
public class IndirectLight {
long mNativeObject;
@UsedByReflection("KtxLoader.java")
IndirectLight(long indirectLight) {
public IndirectLight(long indirectLight) {
mNativeObject = indirectLight;
}
@@ -402,6 +404,7 @@ public class IndirectLight {
* <p>The dominant light direction can be used to set a directional light's direction,
* for instance to produce shadows that match the environment.</p>
*
* @param sh pre-scaled 3-bands spherical harmonics
* @param direction an array of 3 floats to receive a unit vector representing the direction of
* the dominant light or <code>null</code>
* @return the <code>direction</code> paramter if it was provided, or a newly allocated float
@@ -410,6 +413,19 @@ public class IndirectLight {
* @see LightManager.Builder#direction
* @see #getColorEstimate
*/
@NonNull @Size(min = 3)
public static float[] getDirectionEstimate(@NonNull float[] sh, @Nullable @Size(min = 3) float[] direction) {
if (sh.length < 9 * 3) {
throw new ArrayIndexOutOfBoundsException(
"3 bands SH required, array must be at least 9 x float3");
}
direction = Asserts.assertFloat3(direction);
nGetDirectionEstimateStatic(sh, direction);
return direction;
}
/** @deprecated */
@NonNull @Size(min = 3)
public float[] getDirectionEstimate(@Nullable @Size(min = 3) float[] direction) {
direction = Asserts.assertFloat3(direction);
@@ -417,6 +433,7 @@ public class IndirectLight {
return direction;
}
/**
* Helper to estimate the color and relative intensity of the environment in a given direction.
*
@@ -424,6 +441,7 @@ public class IndirectLight {
* make sure to multiply this relative intensity by the the intensity of this indirect light.</p>
*
* @param colorIntensity an array of 4 floats to receive the result or <code>null</code>
* @param sh pre-scaled 3-bands spherical harmonics
* @param x the x coordinate of a unit vector representing the direction of the light
* @param y the x coordinate of a unit vector representing the direction of the light
* @param z the x coordinate of a unit vector representing the direction of the light
@@ -438,6 +456,19 @@ public class IndirectLight {
* @see #setIntensity
*/
@NonNull @Size(min = 4)
public static float[] getColorEstimate(@Nullable @Size(min = 4) float[] colorIntensity, @NonNull float[] sh, float x, float y, float z) {
if (sh.length < 9 * 3) {
throw new ArrayIndexOutOfBoundsException(
"3 bands SH required, array must be at least 9 x float3");
}
colorIntensity = Asserts.assertFloat4(colorIntensity);
nGetColorEstimateStatic(colorIntensity, sh, x, y, z);
return colorIntensity;
}
/** @deprecated */
@NonNull @Size(min = 4)
public float[] getColorEstimate(@Nullable @Size(min = 4) float[] colorIntensity, float x, float y, float z) {
colorIntensity = Asserts.assertFloat4(colorIntensity);
nGetColorEstimate(getNativeObject(), colorIntensity, x, y, z);
@@ -472,4 +503,7 @@ public class IndirectLight {
private static native void nGetRotation(long nativeIndirectLight, float[] outRotation);
private static native void nGetDirectionEstimate(long nativeIndirectLight, float[] outDirection);
private static native void nGetColorEstimate(long nativeIndirectLight, float[] outColor, float x, float y, float z);
private static native void nGetDirectionEstimateStatic(float[] sh, float[] direction);
private static native void nGetColorEstimateStatic(float[] colorIntensity, float[] sh, float x, float y, float z);
}

View File

@@ -16,9 +16,9 @@
package com.google.android.filament;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.Size;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Size;
public class LightManager {
private long mNativeObject;

View File

@@ -16,9 +16,9 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Size;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Size;
import com.google.android.filament.proguard.UsedByNative;
@@ -141,6 +141,31 @@ public class Material {
SCREEN,
}
/**
* Supported refraction modes
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/blendingandtransparency:refraction">
* Blending and transparency: refractionMode</a>
*/
public enum RefractionMode {
NONE,
CUBEMAP,
SCREEN_SPACE
}
/**
* Supported refraction types
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/blendingandtransparency:refractiontype">
* Blending and transparency: refractionType</a>
*/
public enum RefractionType {
SOLID,
THIN
}
/**
* Supported types of vertex domains
*
@@ -351,13 +376,35 @@ public class Material {
return BlendingMode.values()[nGetBlendingMode(getNativeObject())];
}
/**
* Returns the refraction mode of this material.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/blendingandtransparency:refraction">
* Blending and transparency: refraction</a>
*/
public RefractionMode getRefractionMode() {
return RefractionMode.values()[nGetRefractionMode(getNativeObject())];
}
/**
* Returns the refraction type of this material.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/blendingandtransparency:refractiontype">
* Blending and transparency: refractionType</a>
*/
public RefractionType getRefractionType() {
return RefractionType.values()[nGetRefractionType(getNativeObject())];
}
/**
* Returns the vertex domain of this material.
*
* @se
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/vertexandattributes:vertexdomain">
* Vertex and attributes: vertexDomain</a>
* @return
*/
public VertexDomain getVertexDomain() {
return VertexDomain.values()[nGetVertexDomain(getNativeObject())];
@@ -847,6 +894,9 @@ public class Material {
private static native float nGetMaskThreshold(long nativeMaterial);
private static native float nGetSpecularAntiAliasingVariance(long nativeMaterial);
private static native float nGetSpecularAntiAliasingThreshold(long nativeMaterial);
private static native int nGetRefractionMode(long nativeMaterial);
private static native int nGetRefractionType(long nativeMaterial);
private static native int nGetParameterCount(long nativeMaterial);
private static native void nGetParameters(long nativeMaterial,

View File

@@ -16,9 +16,9 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Size;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Size;
public class MaterialInstance {
private Material mMaterial;
@@ -356,7 +356,7 @@ public class MaterialInstance {
* to produce a resolvable offset for a given implementation. This offset is added before the
* depth test.
*
* @warning using a polygon offset other than zero has a significant negative performance
* Warning: using a polygon offset other than zero has a significant negative performance
* impact, as most implementations have to disable early depth culling. DO NOT USE unless
* absolutely necessary.
*

View File

@@ -16,9 +16,9 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Size;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Size;
public final class MathUtils {
private MathUtils() { }

View File

@@ -16,7 +16,7 @@
package com.google.android.filament;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
import com.google.android.filament.proguard.UsedByNative;

View File

@@ -16,7 +16,7 @@
package com.google.android.filament;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
abstract class Platform {
private static Platform mCurrentPlatform = null;

View File

@@ -16,9 +16,9 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
/**
* An offscreen render target that can be associated with a {@link View} and contains

View File

@@ -16,10 +16,10 @@
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;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Size;
import java.nio.Buffer;
import java.nio.BufferOverflowException;

View File

@@ -16,8 +16,8 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import java.nio.Buffer;
import java.nio.BufferOverflowException;
@@ -299,6 +299,94 @@ public class Renderer {
}
}
/**
* Reads back the content of a specified {@link RenderTarget}.
*
*<pre>
*
* Framebuffer as seen on User buffer (PixelBufferDescriptor)
* screen
* +--------------------+
* | | .stride .alignment
* | | ----------------------->-->
* | | O----------------------+--+ low addresses
* | | | | | |
* | w | | | .top | |
* | <---------> | | V | |
* | +---------+ | | +---------+ | |
* | | ^ | | ======> | | | | |
* | x | h| | | |.left| | | |
* +------>| v | | +---->| | | |
* | +.........+ | | +.........+ | |
* | ^ | | | |
* | y | | +----------------------+--+ high addresses
* O------------+-------+
*
*</pre>
*
*
* <p>Typically <code>readPixels</code> will be called after {@link #render} and before
* {@link #endFrame}.</p>
* <br>
* <p>After calling this method, the callback associated with <code>buffer</code>
* will be invoked on the main thread, indicating that the read-back has completed.
* Typically, this will happen after multiple calls to {@link #beginFrame},
* {@link #render}, {@link #endFrame}.</p>
* <br>
* <p><code>readPixels</code> is intended for debugging and testing.
* It will impact performance significantly.</p>
*
* @param renderTarget {@link RenderTarget} to read back from
* @param xoffset left offset of the sub-region to read back
* @param yoffset bottom offset of the sub-region to read back
* @param width width of the sub-region to read back
* @param height height of the sub-region to read back
* @param buffer client-side buffer where the read-back will be written
*
* <p>
* The following format are always supported:
* <li>{@link Texture.Format#RGBA}</li>
* <li>{@link Texture.Format#RGBA_INTEGER}</li>
* </p>
*
* <p>
* The following types are always supported:
* <li>{@link Texture.Type#UBYTE}</li>
* <li>{@link Texture.Type#UINT}</li>
* <li>{@link Texture.Type#INT}</li>
* <li>{@link Texture.Type#FLOAT}</li>
* </p>
*
* <p>Other combination of format/type may be supported. If a combination is
* not supported, this operation may fail silently. Use a DEBUG build
* to get some logs about the failure.</p>
*
* @exception BufferOverflowException if the specified parameters would result in reading
* outside of <code>buffer</code>.
*/
public void readPixels(
@NonNull RenderTarget renderTarget,
@IntRange(from = 0) int xoffset, @IntRange(from = 0) int yoffset,
@IntRange(from = 0) int width, @IntRange(from = 0) int height,
@NonNull Texture.PixelBufferDescriptor buffer) {
if (buffer.storage.isReadOnly()) {
throw new ReadOnlyBufferException();
}
int result = nReadPixelsEx(getNativeObject(), mEngine.getNativeObject(),
renderTarget.getNativeObject(),
xoffset, yoffset, width, height,
buffer.storage, buffer.storage.remaining(),
buffer.left, buffer.top, buffer.type.ordinal(), buffer.alignment,
buffer.stride, buffer.format.ordinal(),
buffer.handler, buffer.callback);
if (result < 0) {
throw new BufferOverflowException();
}
}
/**
* Returns a timestamp (in seconds) for the last call to {@link #beginFrame}. This value is
* constant for all {@link View views} rendered during a frame. The epoch is set with
@@ -355,7 +443,7 @@ public class Renderer {
* <br>
* <p>Use this method used to keep the precision of time high in materials, in practice it should
* be called at least when the application is paused, e.g.
* {@link android.app.Activity#onPause() Activity.onPause} in Android.</p>
* <code>Activity.onPause</code> in Android.</p>
*
* @see #getUserTime
*/
@@ -386,6 +474,12 @@ public class Renderer {
Buffer storage, int remaining,
int left, int top, int type, int alignment, int stride, int format,
Object handler, Runnable callback);
private static native int nReadPixelsEx(long nativeRenderer, long nativeEngine,
long nativeRenderTarget,
int xoffset, int yoffset, int width, int height,
Buffer storage, int remaining,
int left, int top, int type, int alignment, int stride, int format,
Object handler, Runnable callback);
private static native double nGetUserTime(long nativeRenderer);
private static native void nResetUserTime(long nativeRenderer);
}

View File

@@ -16,7 +16,7 @@
package com.google.android.filament;
import android.support.annotation.Nullable;
import androidx.annotation.Nullable;
/**
* A <code>Scene</code> is a flat container of {@link RenderableManager} and {@link LightManager}

View File

@@ -16,8 +16,8 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import com.google.android.filament.proguard.UsedByReflection;
@@ -49,8 +49,7 @@ import com.google.android.filament.proguard.UsedByReflection;
public class Skybox {
private long mNativeObject;
@UsedByReflection("KtxLoader.java")
Skybox(long nativeSkybox) {
public Skybox(long nativeSkybox) {
mNativeObject = nativeSkybox;
}

View File

@@ -16,8 +16,8 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import java.nio.Buffer;
import java.nio.BufferOverflowException;
@@ -33,6 +33,20 @@ public class Stream {
private long mNativeObject;
private long mNativeEngine;
/**
* Represents the immutable stream type.
*/
public enum StreamType {
/** Not synchronized but copy-free. Good for video. */
NATIVE,
/** Synchronized, but GL-only and incurs copies. Good for AR on devices before API 26. */
TEXTURE_ID,
/** Synchronized, copy-free, and take a release callback. Good for AR but requires API 26+. */
ACQUIRED,
};
Stream(long nativeStream, Engine engine) {
mNativeObject = nativeStream;
mNativeEngine = engine.getNativeObject();
@@ -40,6 +54,12 @@ public class Stream {
/**
* Use <code>Builder</code> to construct an Stream object instance.
*
* By default, Stream objects are {@link StreamType#ACQUIRED ACQUIRED} and must have external images pushed to them via
* {@link #setAcquiredImage}.
*
* To create a {@link StreamType#NATIVE NATIVE} or {@link StreamType#TEXTURE_ID TEXTURE_ID} stream, call one of the <pre>stream</pre> methods
* on the builder.
*/
public static class Builder {
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) // Keep to finalize native resources
@@ -55,8 +75,8 @@ public class Stream {
}
/**
* Creates a native stream. Native streams can sample data directly from an
* opaque platform object such as a {@link android.graphics.SurfaceTexture SurfaceTexture}
* Creates a {@link StreamType#NATIVE NATIVE} stream. Native streams can sample data
* directly from an opaque platform object such as a {@link android.graphics.SurfaceTexture SurfaceTexture}
* on Android.
*
* @param streamSource an opaque native stream handle, e.g.: on Android this must be a
@@ -74,7 +94,7 @@ public class Stream {
}
/**
* Creates a copy stream. A copy stream will sample data from the supplied
* Creates a {@link StreamType#TEXTURE_ID TEXTURE_ID} stream. A copy stream will sample data from the supplied
* external texture and copy it into an internal private texture.
*
* <p>Currently only OpenGL external texture ids are supported.</p>
@@ -150,12 +170,24 @@ public class Stream {
}
/**
* Indicates whether this <code>Stream</code> is a native stream or a copy stream.
*
* @return true if this is a native <code>Stream</code>, false otherwise.
* Indicates whether this <code>Stream</code> is NATIVE, TEXTURE_ID, or ACQUIRED.
*/
public boolean isNative() {
return nIsNative(getNativeObject());
public StreamType getStreamType() {
return StreamType.values()[nGetStreamType(getNativeObject())];
}
/**
* Updates an <pre>ACQUIRED</pre> stream with an image that is guaranteed to be used in the next frame.
*
* This method should be called on the same thread that calls {#link Renderer#beginFrame}, which is
* also where the callback is invoked.
*
* @param hwbuffer {@link android.hardware.HardwareBuffer HardwareBuffer} (requires API level 26)
* @param handler {@link java.util.concurrent.Executor Executor} or {@link android.os.Handler Handler}.
* @param callback a callback invoked by <code>handler</code> when the <code>hwbuffer</code> can be released.
*/
public void setAcquiredImage(Object hwbuffer, Object handler, Runnable callback) {
nSetAcquiredImage(getNativeObject(), mNativeEngine, hwbuffer, handler, callback);
}
/**
@@ -174,7 +206,7 @@ public class Stream {
* Reads back the content of the last frame of a <code>Stream</code> since the last call to
* {@link Renderer#beginFrame}.
*
* <p>The Stream must be a copy stream, which can be checked with {@link #isNative()}.
* <p>The Stream must be a copy stream, which can be checked with {@link #getStreamType()}.
* This function is a no-op otherwise.</p>
*
* <pre>
@@ -286,6 +318,7 @@ public class Stream {
private static native void nBuilderHeight(long nativeStreamBuilder, int height);
private static native long nBuilderBuild(long nativeStreamBuilder, long nativeEngine);
private static native int nGetStreamType(long nativeStream);
private static native void nSetDimensions(long nativeStream, int width, int height);
private static native int nReadPixels(long nativeStream, long nativeEngine,
int xoffset, int yoffset, int width, int height,
@@ -293,6 +326,6 @@ public class Stream {
int left, int top, int type, int alignment, int stride, int format,
Object handler, Runnable callback);
private static native long nGetTimestamp(long nativeStream);
private static native boolean nIsNative(long nativeStream);
private static native void nSetAcquiredImage(long nativeStream, long nativeEngine,
Object hwbuffer, Object handler, Runnable callback);
}

View File

@@ -16,7 +16,7 @@
package com.google.android.filament;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
/**
* A <code>SwapChain</code> represents an Operating System's <b>native</b> renderable surface.
@@ -85,15 +85,15 @@ public class SwapChain {
*/
public static final long CONFIG_READABLE = 0x2;
SwapChain(long nativeSwapChain, @NonNull Object surface) {
SwapChain(long nativeSwapChain, Object surface) {
mNativeObject = nativeSwapChain;
mSurface = surface;
}
/**
* @return the native <code>Object</code> this <code>SwapChain</code> was created from.
* @return the native <code>Object</code> this <code>SwapChain</code> was created from or null
* for a headless SwapChain.
*/
@NonNull
public Object getNativeWindow() {
return mSurface;
}

View File

@@ -16,10 +16,10 @@
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;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Size;
import com.google.android.filament.proguard.UsedByReflection;
@@ -73,8 +73,7 @@ import static com.google.android.filament.Texture.Type.COMPRESSED;
public class Texture {
private long mNativeObject;
@UsedByReflection("KtxLoader.java")
Texture(long nativeTexture) {
public Texture(long nativeTexture) {
mNativeObject = nativeTexture;
}
@@ -322,13 +321,26 @@ public class Texture {
public CompressedFormat compressedFormat;
@Nullable public Object handler;
@Nullable public Runnable callback;
/**
* Valid handler types:
* - Android: Handler, Executor
* - Other: Executor
* Callback used to destroy the buffer data.
* <p>
* Guarantees:
* <ul>
* <li>Called on the main filament thread.</li>
* </ul>
* </p>
*
* <p>
* Limitations:
* <ul>
* <li>Must be lightweight.</li>
* <li>Must not call filament APIs.</li>
* </ul>
* </p>
*/
@Nullable public Runnable callback;
/**
* Creates a <code>PixelBufferDescriptor</code>

View File

@@ -16,7 +16,7 @@
package com.google.android.filament;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
/**
* <code>TextureSampler</code> defines how a texture is accessed.

View File

@@ -16,9 +16,9 @@
package com.google.android.filament;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.Size;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Size;
/**
* <code>TransformManager</code> is used to add transform components to entities.

View File

@@ -16,9 +16,9 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.nio.Buffer;
import java.nio.BufferOverflowException;

View File

@@ -16,10 +16,10 @@
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;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Size;
import static com.google.android.filament.Colors.LinearColor;
@@ -149,6 +149,11 @@ public class View {
* How each dimension of the AO buffer is scaled. Must be positive and <= 1.
*/
public float resolution = 0.5f;
/**
* Strength of the Ambient Occlusion effect. Must be positive.
*/
public float intensity = 1.0f;
}
/**
@@ -620,6 +625,8 @@ public class View {
/**
* Sets whether this view is rendered with or without a depth pre-pass.
*
* <p><b>This setting is ignored and will be removed in future versions of Filament.</b></p>
*
* <p>
* By default, the system picks the most appropriate strategy for your platform; this method
* lets you override that strategy.
@@ -642,6 +649,7 @@ public class View {
* <li>DepthPrepass::ENABLE enables the depth pre-pass</li>
* </ul>
*/
@Deprecated
public void setDepthPrepass(@NonNull DepthPrepass depthPrepass) {
mDepthPrepass = depthPrepass;
nSetDepthPrepass(getNativeObject(), depthPrepass.value);
@@ -761,7 +769,8 @@ public class View {
*/
public void setAmbientOcclusionOptions(@NonNull AmbientOcclusionOptions options) {
mAmbientOcclusionOptions = options;
nSetAmbientOcclusionOptions(getNativeObject(), options.radius, options.bias, options.power, options.resolution);
nSetAmbientOcclusionOptions(getNativeObject(), options.radius, options.bias, options.power,
options.resolution, options.intensity);
}
/**
@@ -819,5 +828,5 @@ public class View {
private static native boolean nIsFrontFaceWindingInverted(long nativeView);
private static native void nSetAmbientOcclusion(long nativeView, int ordinal);
private static native int nGetAmbientOcclusion(long nativeView);
private static native void nSetAmbientOcclusionOptions(long nativeView, float radius, float bias, float power, float resolution);
private static native void nSetAmbientOcclusionOptions(long nativeView, float radius, float bias, float power, float resolution, float intensity);
}

View File

@@ -16,7 +16,7 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import androidx.annotation.IntRange;
/**
* Specifies a rectangular region within a render target in terms of pixel coordinates.

View File

@@ -17,8 +17,8 @@
package com.google.android.filament.android;
import android.graphics.Bitmap;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import com.google.android.filament.Engine;
import com.google.android.filament.Texture;

View File

@@ -19,8 +19,8 @@ package com.google.android.filament.android;
import android.graphics.PixelFormat;
import android.graphics.SurfaceTexture;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
@@ -131,6 +131,7 @@ public class UiHelper {
private RenderSurface mRenderSurface;
private boolean mOpaque = true;
private boolean mOverlay = false;
/**
* Enum used to decide whether UiHelper should perform extra error checking.
@@ -173,7 +174,7 @@ public class UiHelper {
void detach();
}
private class SurfaceViewHandler implements RenderSurface {
private static class SurfaceViewHandler implements RenderSurface {
private SurfaceView mSurfaceView;
SurfaceViewHandler(SurfaceView surface) {
@@ -323,6 +324,30 @@ public class UiHelper {
mOpaque = opaque;
}
/**
* Returns true if the SurfaceView used as a render target should be positioned above
* other surfaces but below the activity's surface. False by default.
*/
public boolean isMediaOverlay() {
return mOverlay;
}
/**
* Controls whether the surface of the SurfaceView used as a render target should be
* positioned above other surfaces but below the activity's surface. This property
* only has an effect when used in combination with {@link #setOpaque(boolean) setOpaque(false)}
* and does not affect TextureView targets.
*
* Must be called before calling {@link #attachTo(SurfaceView)}
* or {@link #attachTo(TextureView)}.
*
* @param overlay Indicates whether the render target should be rendered below the activity's
* surface when transparent.
*/
public void setMediaOverlay(boolean overlay) {
mOverlay = overlay;
}
/**
* Returns the flags to pass to
* {@link com.google.android.filament.Engine#createSwapChain(Object, long)} to honor all
@@ -340,11 +365,18 @@ public class UiHelper {
*/
public void attachTo(@NonNull SurfaceView view) {
if (attach(view)) {
if (!isOpaque()) {
view.setZOrderOnTop(true);
view.getHolder().setFormat(PixelFormat.TRANSLUCENT);
boolean translucent = !isOpaque();
// setZOrderOnTop() and setZOrderMediaOverlay() override each other,
// we must only call one of them
if (isMediaOverlay()) {
view.setZOrderMediaOverlay(translucent);
} else {
view.setZOrderOnTop(translucent);
}
int format = isOpaque() ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT;
view.getHolder().setFormat(format);
mRenderSurface = new SurfaceViewHandler(view);
final SurfaceHolder.Callback callback = new SurfaceHolder.Callback() {
@@ -377,7 +409,6 @@ public class UiHelper {
final Surface surface = holder.getSurface();
if (surface != null && surface.isValid()) {
callback.surfaceCreated(holder);
int format = isOpaque() ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT;
callback.surfaceChanged(holder, format,
holder.getSurfaceFrame().width(), holder.getSurfaceFrame().height());
}

View File

@@ -8,5 +8,5 @@
.DS_Store
/build
/captures
/app/src/main/assets
.externalNativeBuild
/.cxx

View File

@@ -0,0 +1,104 @@
cmake_minimum_required(VERSION 3.6)
set(FILAMENT_DIR ${FILAMENT_DIST_DIR})
set(DISABLE_GLTFIO_JNI TRUE)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../gltfio-android ${CMAKE_CURRENT_BINARY_DIR}/gltfio-android)
add_library(filament STATIC IMPORTED)
set_target_properties(filament PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilament.a)
add_library(backend STATIC IMPORTED)
set_target_properties(backend PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libbackend.a)
add_library(camutils STATIC IMPORTED)
set_target_properties(camutils PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libcamutils.a)
add_library(utils STATIC IMPORTED)
set_target_properties(utils PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libutils.a)
add_library(filaflat STATIC IMPORTED)
set_target_properties(filaflat PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilaflat.a)
add_library(image STATIC IMPORTED)
set_target_properties(image PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libimage.a)
add_library(ibl STATIC IMPORTED)
set_target_properties(ibl PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libibl.a)
add_library(geometry STATIC IMPORTED)
set_target_properties(geometry PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libgeometry.a)
add_library(filabridge STATIC IMPORTED)
set_target_properties(filabridge PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilabridge.a)
add_library(gltfio STATIC IMPORTED)
set_target_properties(gltfio PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libgltfio_core.a)
add_library(gltfio_resources STATIC IMPORTED)
set_target_properties(gltfio_resources PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libgltfio_resources.a)
add_library(bluevk STATIC IMPORTED)
set_target_properties(bluevk PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libbluevk.a)
add_library(smol-v STATIC IMPORTED)
set_target_properties(smol-v PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libsmol-v.a)
include_directories(${FILAMENT_DIR}/include
..
../../libs/utils/include)
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/libfilament-utils-jni.map")
add_library(filament-utils-jni SHARED
src/main/cpp/Bookmark.cpp
src/main/cpp/Utils.cpp
src/main/cpp/Manipulator.cpp
../common/CallbackUtils.cpp
../common/NioUtils.cpp
$<TARGET_OBJECTS:gltfio-jni-obj>
$<TARGET_OBJECTS:filament-jni-obj>
)
set_target_properties(filament-utils-jni PROPERTIES LINK_DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/libfilament-utils-jni.symbols)
# The ordering in the following list is important because CMake does not have dependency information.
target_link_libraries(filament-utils-jni
gltfio
filament
backend
filaflat
filabridge
camutils
geometry
image
ibl
utils
log
GLESv3
EGL
android
jnigraphics
gltfio_resources
m
)
if (FILAMENT_SUPPORTS_VULKAN)
target_link_libraries(filament-utils-jni bluevk smol-v)
endif()

View File

@@ -0,0 +1,63 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
buildToolsVersion versions.buildTools
compileSdkVersion versions.compileSdk
defaultConfig {
minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk
externalNativeBuild {
cmake {
arguments.add("-DANDROID_PIE=ON")
arguments.add("-DANDROID_PLATFORM=android-${versions.targetSdk}".toString())
arguments.add("-DANDROID_STL=c++_static")
arguments.add("-DFILAMENT_DIST_DIR=${filamentPath}".toString())
cppFlags.add("-std=c++14")
if (project.hasProperty('extra_cmake_args')) {
arguments.add(extra_cmake_args)
}
}
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
sourceSets {
main {
jni.srcDirs "src/main/cpp"
kotlin.srcDirs += "src/main/java"
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation deps.kotlin
implementation deps.androidx.annotations
implementation project(':filament-android')
implementation project(':gltfio-android')
}
apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
afterEvaluate { project ->
publishing {
publications {
release(MavenPublication) {
artifactId = POM_ARTIFACT_ID
from components.release
}
}
}
}

View File

@@ -0,0 +1,3 @@
POM_NAME=Filament Android Utilities
POM_ARTIFACT_ID=filament-utils-android
POM_PACKAGING=aar

View File

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

View File

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

View File

@@ -0,0 +1,18 @@
<!--
Copyright (C) 2020 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.filament.utils" />

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 The Android Open Source Project
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,15 +14,14 @@
* limitations under the License.
*/
#ifndef TNT_METALDEFINES_H
#define TNT_METALDEFINES_H
#include <jni.h>
// Filament fences are implemented with MTLSharedEvent, which are only available on
// OSX 10.14+ and iOS 12.0+
#if defined(IOS)
#define METAL_FENCES_SUPPORTED (__IPHONE_OS_VERSION_MAX_ALLOWED > 120000)
#else
#define METAL_FENCES_SUPPORTED (MAC_OS_X_VERSION_MAX_ALLOWED > 101400)
#endif
#include <camutils/Bookmark.h>
#endif //TNT_METALDEFINES_H
using namespace filament::camutils;
using namespace filament::math;
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Bookmark_nDestroyBookmark(JNIEnv*, jclass, jlong nativeBookmark) {
Bookmark<float>* bookmark = (Bookmark<float>*) nativeBookmark;
delete bookmark;
}

View File

@@ -0,0 +1,193 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <jni.h>
#include <math/mat3.h>
#include <math/vec3.h>
#include <camutils/Manipulator.h>
using namespace filament::camutils;
using namespace filament::math;
using Builder = Manipulator<float>::Builder;
extern "C" JNIEXPORT jlong Java_com_google_android_filament_utils_Manipulator_nCreateBuilder(JNIEnv*, jclass) {
return (jlong) new Builder {};
}
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nDestroyBuilder(JNIEnv*, jclass, jlong nativeBuilder) {
Builder* builder = (Builder*) nativeBuilder;
delete builder;
}
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderViewport(JNIEnv*, jclass, jlong nativeBuilder, jint width, jint height) {
Builder* builder = (Builder*) nativeBuilder;
builder->viewport(width, height);
}
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderTargetPosition(JNIEnv*, jclass, jlong nativeBuilder, jfloat x, jfloat y, jfloat z) {
Builder* builder = (Builder*) nativeBuilder;
builder->targetPosition(x, y, z);
}
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderUpVector(JNIEnv*, jclass, jlong nativeBuilder, jfloat x, jfloat y, jfloat z) {
Builder* builder = (Builder*) nativeBuilder;
builder->upVector(x, y, z);
}
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderZoomSpeed(JNIEnv*, jclass, jlong nativeBuilder, jfloat arg) {
Builder* builder = (Builder*) nativeBuilder;
builder->zoomSpeed(arg);
}
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderOrbitHomePosition(JNIEnv*, jclass, jlong nativeBuilder, jfloat x, jfloat y, jfloat z) {
Builder* builder = (Builder*) nativeBuilder;
builder->orbitHomePosition(x, y, z);
}
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderOrbitSpeed(JNIEnv*, jclass, jlong nativeBuilder, jfloat x, jfloat y) {
Builder* builder = (Builder*) nativeBuilder;
builder->orbitSpeed(x, y);
}
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderFovDirection(JNIEnv*, jclass, jlong nativeBuilder, jint arg) {
Builder* builder = (Builder*) nativeBuilder;
builder->fovDirection((Fov) arg);
}
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderFovDegrees(JNIEnv*, jclass, jlong nativeBuilder, jfloat arg) {
Builder* builder = (Builder*) nativeBuilder;
builder->fovDegrees(arg);
}
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderFarPlane(JNIEnv*, jclass, jlong nativeBuilder, jfloat distance) {
Builder* builder = (Builder*) nativeBuilder;
builder->farPlane(distance);
}
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderMapExtent(JNIEnv*, jclass, jlong nativeBuilder, jfloat width, jfloat height) {
Builder* builder = (Builder*) nativeBuilder;
builder->mapExtent(width, height);
}
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderMapMinDistance(JNIEnv*, jclass, jlong nativeBuilder, jfloat arg) {
Builder* builder = (Builder*) nativeBuilder;
builder->mapMinDistance(arg);
}
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderGroundPlane(JNIEnv*, jclass, jlong nativeBuilder, jfloat a, jfloat b, jfloat c, jfloat d) {
Builder* builder = (Builder*) nativeBuilder;
builder->groundPlane(a, b, c, d);
}
extern "C" JNIEXPORT long Java_com_google_android_filament_utils_Manipulator_nBuilderBuild(JNIEnv*, jclass, jlong nativeBuilder, jint mode) {
Builder* builder = (Builder*) nativeBuilder;
return (jlong) builder->build((Mode) mode);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_utils_Manipulator_nDestroyManipulator(JNIEnv*, jclass, jlong nativeManip) {
auto manip = (Manipulator<float>*) nativeManip;
delete manip;
}
extern "C" JNIEXPORT jint JNICALL Java_com_google_android_filament_utils_Manipulator_nGetMode(JNIEnv*, jclass, jlong nativeManip) {
auto manip = (Manipulator<float>*) nativeManip;
return (int) manip->getMode();
}
extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_utils_Manipulator_nSetViewport(JNIEnv*, jclass, jlong nativeManip, jint width, jint height) {
auto manip = (Manipulator<float>*) nativeManip;
manip->setViewport(width, height);
}
extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_utils_Manipulator_nGetLookAtFloat(JNIEnv* env, jclass, jlong nativeManip, jfloatArray eyePosition, jfloatArray targetPosition, jfloatArray upward) {
auto manip = (Manipulator<float>*) nativeManip;
jfloat *eye = env->GetFloatArrayElements(eyePosition, NULL);
jfloat *target = env->GetFloatArrayElements(targetPosition, NULL);
jfloat *up = env->GetFloatArrayElements(upward, NULL);
manip->getLookAt((float3*) eye, (float3*) target, (float3*) up);
env->ReleaseFloatArrayElements(eyePosition, eye, 0);
env->ReleaseFloatArrayElements(targetPosition, target, 0);
env->ReleaseFloatArrayElements(upward, up, 0);
}
extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_utils_Manipulator_nGetLookAtDouble(JNIEnv* env, jclass, jlong nativeManip, jdoubleArray eyePosition, jdoubleArray targetPosition, jdoubleArray upward) {
auto manip = (Manipulator<float>*) nativeManip;
float3 eyef, targetf, upf;
manip->getLookAt(&eyef, &targetf, &upf);
jdouble *eye = env->GetDoubleArrayElements(eyePosition, NULL);
jdouble *target = env->GetDoubleArrayElements(targetPosition, NULL);
jdouble *up = env->GetDoubleArrayElements(upward, NULL);
*((double3*) eye) = eyef;
*((double3*) target) = targetf;
*((double3*) up) = upf;
env->ReleaseDoubleArrayElements(eyePosition, eye, 0);
env->ReleaseDoubleArrayElements(targetPosition, target, 0);
env->ReleaseDoubleArrayElements(upward, up, 0);
}
extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_utils_Manipulator_nRaycast(JNIEnv* env, jclass, jlong nativeManip, jint x, jint y, jfloatArray result) {
auto manip = (Manipulator<float>*) nativeManip;
jfloat *presult = env->GetFloatArrayElements(result, NULL);
manip->raycast(x, y, (float3*) presult);
env->ReleaseFloatArrayElements(result, presult, 0);
}
extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_utils_Manipulator_nGrabBegin(JNIEnv*, jclass, jlong nativeManip, jint x, jint y, jboolean strafe) {
auto manip = (Manipulator<float>*) nativeManip;
manip->grabBegin(x, y, (bool) strafe);
}
extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_utils_Manipulator_nGrabUpdate(JNIEnv*, jclass, jlong nativeManip, jint x, jint y) {
auto manip = (Manipulator<float>*) nativeManip;
manip->grabUpdate(x, y);
}
extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_utils_Manipulator_nGrabEnd(JNIEnv*, jclass, jlong nativeManip) {
auto manip = (Manipulator<float>*) nativeManip;
manip->grabEnd();
}
extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_utils_Manipulator_nZoom(JNIEnv*, jclass, jlong nativeManip, jint x, jint y, jfloat scrolldelta) {
auto manip = (Manipulator<float>*) nativeManip;
manip->zoom(x, y, scrolldelta);
}
extern "C" JNIEXPORT jlong JNICALL Java_com_google_android_filament_utils_Manipulator_nGetCurrentBookmark(JNIEnv*, jclass, jlong nativeManip) {
auto manip = (Manipulator<float>*) nativeManip;
return (jlong) new Bookmark<float>(manip->getCurrentBookmark());
}
extern "C" JNIEXPORT jlong JNICALL Java_com_google_android_filament_utils_Manipulator_nGetHomeBookmark(JNIEnv*, jclass, jlong nativeManip) {
auto manip = (Manipulator<float>*) nativeManip;
return (jlong) new Bookmark<float>(manip->getHomeBookmark());
}
extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_utils_Manipulator_nJumpToBookmark(JNIEnv*, jclass, jlong nativeManip, jlong nativeBookmark) {
auto manip = (Manipulator<float>*) nativeManip;
auto bookmark = (Bookmark<float>*) nativeBookmark;
manip->jumpToBookmark(*bookmark);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 The Android Open Source Project
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,8 +28,23 @@ using namespace filament;
using namespace filament::math;
using namespace image;
extern void registerCallbackUtils(JNIEnv*);
extern void registerNioUtils(JNIEnv*);
jint JNI_OnLoad(JavaVM* vm, void*) {
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
return -1;
}
registerCallbackUtils(env);
registerNioUtils(env);
return JNI_VERSION_1_6;
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_gltfio_KtxLoader_nCreateTexture(JNIEnv* env, jclass,
Java_com_google_android_filament_utils_KtxLoader_nCreateTexture(JNIEnv* env, jclass,
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb) {
Engine* engine = (Engine*) nativeEngine;
AutoBuffer buffer(env, javaBuffer, remaining);
@@ -41,7 +56,7 @@ Java_com_google_android_filament_gltfio_KtxLoader_nCreateTexture(JNIEnv* env, jc
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_gltfio_KtxLoader_nCreateIndirectLight(JNIEnv* env, jclass,
Java_com_google_android_filament_utils_KtxLoader_nCreateIndirectLight(JNIEnv* env, jclass,
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb) {
Engine* engine = (Engine*) nativeEngine;
AutoBuffer buffer(env, javaBuffer, remaining);
@@ -64,7 +79,7 @@ Java_com_google_android_filament_gltfio_KtxLoader_nCreateIndirectLight(JNIEnv* e
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_gltfio_KtxLoader_nCreateSkybox(JNIEnv* env, jclass,
Java_com_google_android_filament_utils_KtxLoader_nCreateSkybox(JNIEnv* env, jclass,
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb) {
Engine* engine = (Engine*) nativeEngine;
AutoBuffer buffer(env, javaBuffer, remaining);

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.filament.utils;
public class Bookmark {
private long mNativeObject;
Bookmark(long nativeObject) {
mNativeObject = nativeObject;
}
long getNativeObject() {
return mNativeObject;
}
@Override
protected void finalize() throws Throwable {
nDestroyBookmark(mNativeObject);
super.finalize();
}
private static native void nDestroyBookmark(long nativeObject);
}

View File

@@ -0,0 +1,154 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.filament.utils
import android.view.MotionEvent
import android.view.View
import java.util.*
/**
* Responds to Android touch events and manages a camera manipulator.
* Supports one-touch orbit, two-touch pan, and pinch-to-zoom.
*/
class GestureDetector(private val view: View, private val manipulator: Manipulator) {
private enum class Gesture { NONE, ORBIT, PAN, ZOOM }
// Simplified memento of MotionEvent, minimal but sufficient for our purposes.
private data class TouchPair(var pt0: Float2, var pt1: Float2, var count: Int) {
constructor() : this(Float2(0f), Float2(0f), 0)
constructor(me: MotionEvent, height: Int) : this() {
if (me.pointerCount >= 1) {
this.pt0 = Float2(me.getX(0), height - me.getY(0))
this.pt1 = this.pt0
this.count++
}
if (me.pointerCount >= 2) {
this.pt1 = Float2(me.getX(1), height - me.getY(1))
this.count++
}
}
val separation get() = distance(pt0, pt1)
val midpoint get() = mix(pt0, pt1, 0.5f)
val x: Int get() = midpoint.x.toInt()
val y: Int get() = midpoint.y.toInt()
}
private var currentGesture = Gesture.NONE
private var previousTouch = TouchPair()
private val tentativePanEvents = ArrayList<TouchPair>()
private val tentativeOrbitEvents = ArrayList<TouchPair>()
private val tentativeZoomEvents = ArrayList<TouchPair>()
private val kGestureConfidenceCount = 2
private val kPanConfidenceDistance = 4
private val kZoomConfidenceDistance = 10
private val kZoomSpeed = 1f / 10f
fun onTouchEvent(event: MotionEvent) {
val touch = TouchPair(event, view.height)
when (event.actionMasked) {
MotionEvent.ACTION_MOVE -> {
// CANCEL GESTURE DUE TO UNEXPECTED POINTER COUNT
if ((event.pointerCount != 1 && currentGesture == Gesture.ORBIT) ||
(event.pointerCount != 2 && currentGesture == Gesture.PAN) ||
(event.pointerCount != 2 && currentGesture == Gesture.ZOOM)) {
endGesture()
return
}
// UPDATE EXISTING GESTURE
if (currentGesture == Gesture.ZOOM) {
val d0 = previousTouch.separation
val d1 = touch.separation
manipulator.zoom(touch.x, touch.y, (d0 - d1) * kZoomSpeed)
previousTouch = touch
return
}
if (currentGesture != Gesture.NONE) {
manipulator.grabUpdate(touch.x, touch.y)
return
}
// DETECT NEW GESTURE
if (event.pointerCount == 1) {
tentativeOrbitEvents.add(touch)
}
if (event.pointerCount == 2) {
tentativePanEvents.add(touch)
tentativeZoomEvents.add(touch)
}
if (isOrbitGesture()) {
manipulator.grabBegin(touch.x, touch.y, false)
currentGesture = Gesture.ORBIT
return
}
if (isZoomGesture()) {
currentGesture = Gesture.ZOOM
previousTouch = touch
return
}
if (isPanGesture()) {
manipulator.grabBegin(touch.x, touch.y, true)
currentGesture = Gesture.PAN
return
}
}
MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_UP -> {
endGesture()
}
}
}
private fun endGesture() {
tentativePanEvents.clear()
tentativeOrbitEvents.clear()
tentativeZoomEvents.clear()
currentGesture = Gesture.NONE
manipulator.grabEnd()
}
private fun isOrbitGesture(): Boolean {
return tentativeOrbitEvents.size > kGestureConfidenceCount
}
private fun isPanGesture(): Boolean {
if (tentativePanEvents.size <= kGestureConfidenceCount) {
return false
}
val oldest = tentativePanEvents.first().midpoint
val newest = tentativePanEvents.last().midpoint
return distance(oldest, newest) > kPanConfidenceDistance
}
private fun isZoomGesture(): Boolean {
if (tentativeZoomEvents.size <= kGestureConfidenceCount) {
return false
}
val oldest = tentativeZoomEvents.first().separation
val newest = tentativeZoomEvents.last().separation
return kotlin.math.abs(newest - oldest) > kZoomConfidenceDistance
}
}

View File

@@ -0,0 +1,82 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.filament.utils
import 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
/**
* Utilities for consuming KTX files and producing Filament textures, IBLs, and sky boxes.
*
* KTX is a simple container format that makes it easy to bundle miplevels and cubemap faces
* into a single file.
*/
object KtxLoader {
class Options {
var srgb = false
}
/**
* Consumes the content of a KTX file and produces a [Texture] object.
*
* @param engine Gets passed to the builder.
* @param buffer The content of the KTX File.
* @param options Loader options.
* @return The resulting Filament texture, or null on failure.
*/
fun createTexture(engine: Engine, buffer: Buffer, options: Options): Texture {
val nativeEngine = engine.nativeObject
val nativeTexture = nCreateTexture(nativeEngine, buffer, buffer.remaining(), options.srgb)
return Texture(nativeTexture)
}
/**
* Consumes the content of a KTX file and produces an [IndirectLight] object.
*
* @param engine Gets passed to the builder.
* @param buffer The content of the KTX File.
* @param options Loader options.
* @return The resulting Filament texture, or null on failure.
*/
fun createIndirectLight(engine: Engine, buffer: Buffer, options: Options): IndirectLight {
val nativeEngine = engine.nativeObject
val nativeIndirectLight = nCreateIndirectLight(nativeEngine, buffer, buffer.remaining(), options.srgb)
return IndirectLight(nativeIndirectLight)
}
/**
* Consumes the content of a KTX file and produces a [Skybox] object.
*
* @param engine Gets passed to the builder.
* @param buffer The content of the KTX File.
* @param options Loader options.
* @return The resulting Filament texture, or null on failure.
*/
fun createSkybox(engine: Engine, buffer: Buffer, options: Options): Skybox {
val nativeEngine = engine.nativeObject
val nativeSkybox = nCreateSkybox(nativeEngine, buffer, buffer.remaining(), options.srgb)
return Skybox(nativeSkybox)
}
private external fun nCreateTexture(nativeEngine: Long, buffer: Buffer, remaining: Int, srgb: Boolean): Long
private external fun nCreateIndirectLight(nativeEngine: Long, buffer: Buffer, remaining: Int, srgb: Boolean): Long
private external fun nCreateSkybox(nativeEngine: Long, buffer: Buffer, remaining: Int, srgb: Boolean): Long
}

View File

@@ -0,0 +1,378 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.filament.utils;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Size;
/**
* Helper that enables camera interaction similar to sketchfab or Google Maps.
*
* Clients notify the camera manipulator of various mouse or touch events, then periodically call
* its getLookAt() method so that they can adjust their camera(s). Two modes are supported: ORBIT
* and MAP. To construct a manipulator instance, the desired mode is passed into the create method.
*
* @see Bookmark
*/
public class Manipulator {
private long mNativeObject;
private Manipulator(long nativeIndexBuffer) {
mNativeObject = nativeIndexBuffer;
}
public enum Mode { ORBIT, MAP };
public enum Fov { VERTICAL, HORIZONTAL };
public static class Builder {
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
// Keep to finalize native resources
private final BuilderFinalizer mFinalizer;
private final long mNativeBuilder;
public Builder() {
mNativeBuilder = nCreateBuilder();
mFinalizer = new BuilderFinalizer(mNativeBuilder);
}
/**
* Width and height of the viewing area.
*
* @return this <code>Builder</code> object for chaining calls
*/
@NonNull
public Builder viewport(@IntRange(from = 1) int width, @IntRange(from = 1) int height) {
nBuilderViewport(mNativeBuilder, width, height);
return this;
}
/**
* Sets world-space position of interest, which defaults to (0,0,0).
*
* @return this <code>Builder</code> object for chaining calls
*/
@NonNull
public Builder targetPosition(float x, float y, float z) {
nBuilderTargetPosition(mNativeBuilder, x, y, z);
return this;
}
/**
* Sets orientation for the home position, which defaults to (0,1,0).
*
* @return this <code>Builder</code> object for chaining calls
*/
@NonNull
public Builder upVector(float x, float y, float z) {
nBuilderUpVector(mNativeBuilder, x, y, z);
return this;
}
/**
* Sets the scroll delta multiplier, which defaults to 0.01.
*
* @return this <code>Builder</code> object for chaining calls
*/
@NonNull
public Builder zoomSpeed(float arg) {
nBuilderZoomSpeed(mNativeBuilder, arg);
return this;
}
/**
* Sets initial eye position in world space for ORBIT mode.
* This defaults to (0,0,1).
*
* @return this <code>Builder</code> object for chaining calls
*/
@NonNull
public Builder orbitHomePosition(float x, float y, float z) {
nBuilderOrbitHomePosition(mNativeBuilder, x, y, z);
return this;
}
/**
* Sets the multiplier with viewport delta for ORBIT mode.
* This defaults to 0.01
*
* @return this <code>Builder</code> object for chaining calls
*/
@NonNull
public Builder orbitSpeed(float x, float y) {
nBuilderOrbitSpeed(mNativeBuilder, x, y);
return this;
}
/**
* Sets the FOV axis that's held constant when the viewport changes.
* This defaults to Vertical.
*
* @return this <code>Builder</code> object for chaining calls
*/
@NonNull
public Builder fovDirection(Fov fov) {
nBuilderFovDirection(mNativeBuilder, fov.ordinal());
return this;
}
/**
* Sets the full FOV (not the half-angle) in the degrees.
* This defaults to 33.
*
* @return this <code>Builder</code> object for chaining calls
*/
@NonNull
public Builder fovDegrees(float arg) {
nBuilderFovDegrees(mNativeBuilder, arg);
return this;
}
/**
* Sets the distance to the far plane, which defaults to 5000.
*
* @return this <code>Builder</code> object for chaining calls
*/
@NonNull
public Builder farPlane(float arg) {
nBuilderFarPlane(mNativeBuilder, arg);
return this;
}
/**
* Sets the ground plane size used to compute the home position for MAP mode.
* This defaults to 512 x 512
*
* @return this <code>Builder</code> object for chaining calls
*/
@NonNull
public Builder mapExtent(float width, float height) {
nBuilderMapExtent(mNativeBuilder, width, height);
return this;
}
/**
* Constrains the zoom-in level. Defaults to 0.
*
* @return this <code>Builder</code> object for chaining calls
*/
@NonNull
public Builder mapMinDistance(float arg) {
nBuilderMapMinDistance(mNativeBuilder, arg);
return this;
}
/**
* Sets the ground plane equation used for ray casts.
* This is a plane equation as in Ax + By + Cz + D = 0.
* Defaults to (0, 0, 1, 0).
*
* @return this <code>Builder</code> object for chaining calls
*/
@NonNull
public Builder groundPlane(float a, float b, float c, float d) {
nBuilderGroundPlane(mNativeBuilder, a, b, c, d);
return this;
}
/**
* Creates and returns the <code>Manipulator</code> object.
*
* @return the newly created <code>Manipulator</code> object
*
* @exception IllegalStateException if the Manipulator could not be created
*
*/
@NonNull
public Manipulator build(Mode mode) {
long nativeManipulator = nBuilderBuild(mNativeBuilder, mode.ordinal());
if (nativeManipulator == 0)
throw new IllegalStateException("Couldn't create Manipulator");
return new Manipulator(nativeManipulator);
}
private static class BuilderFinalizer {
private final long mNativeObject;
BuilderFinalizer(long nativeObject) {
mNativeObject = nativeObject;
}
@Override
public void finalize() {
try {
super.finalize();
} catch (Throwable t) { // Ignore
} finally {
nDestroyBuilder(mNativeObject);
}
}
}
};
@Override
public void finalize() {
try {
super.finalize();
} catch (Throwable t) { // Ignore
} finally {
nDestroyManipulator(mNativeObject);
}
}
/**
* Gets the immutable mode of the manipulator.
*/
public Mode getMode() { return Mode.values()[nGetMode(mNativeObject)]; }
/**
* Sets the viewport dimensions in terms of pixels.
*
* The manipulator uses this only in the grab and raycast methods, since
* those methods consume coordinates in viewport space.
*/
public void setViewport(int width, int height) {
nSetViewport(mNativeObject, width, height);
}
/**
* Gets the current orthonormal basis. This is usually called once per frame.
*/
public void getLookAt(
@NonNull @Size(min = 3) float[] eyePosition,
@NonNull @Size(min = 3) float[] targetPosition,
@NonNull @Size(min = 3) float[] upward) {
nGetLookAtFloat(mNativeObject, eyePosition, targetPosition, upward);
}
public void getLookAt(
@NonNull @Size(min = 3) double[] eyePosition,
@NonNull @Size(min = 3) double[] targetPosition,
@NonNull @Size(min = 3) double[] upward) {
nGetLookAtDouble(mNativeObject, eyePosition, targetPosition, upward);
}
/**
* Given a viewport coordinate, picks a point in the ground plane.
*/
@Nullable @Size(min = 3)
public float[] raycast(int x, int y) {
float[] result = new float[3];
nRaycast(mNativeObject, x, y, result);
return result;
}
/**
* Starts a grabbing session (i.e. the user is dragging around in the viewport).
*
* This starts a panning session in MAP mode, and start either rotating or strafing in ORBIT.
*
* @param x X-coordinate for point of interest in viewport space
* @param y Y-coordinate for point of interest in viewport space
* @param strafe ORBIT mode only; if true, starts a translation rather than a rotation.
*/
public void grabBegin(int x, int y, boolean strafe) {
nGrabBegin(mNativeObject, x, y, strafe);
}
/**
* Updates a grabbing session.
*
* This must be called at least once between grabBegin / grabEnd to dirty the camera.
*/
public void grabUpdate(int x, int y) {
nGrabUpdate(mNativeObject, x, y);
}
/**
* Ends a grabbing session.
*/
public void grabEnd() {
nGrabEnd(mNativeObject);
}
/**
* Dollys the camera along the viewing direction.
*
* @param x X-coordinate for point of interest in viewport space
* @param y Y-coordinate for point of interest in viewport space
* @param scrolldelta Positive means "zoom in", negative means "zoom out"
*/
public void zoom(int x, int y, float scrolldelta) {
nZoom(mNativeObject, x, y, scrolldelta);
}
/**
* Gets a handle that can be used to reset the manipulator back to its current position.
*
* @see #jumpToBookmark(Bookmark)
*/
public Bookmark getCurrentBookmark() {
return new Bookmark(nGetCurrentBookmark(mNativeObject));
}
/**
* Gets a handle that can be used to reset the manipulator back to its home position.
*
* see jumpToBookmark
*/
public Bookmark getHomeBookmark() {
return new Bookmark(nGetHomeBookmark(mNativeObject));
}
/**
* Sets the manipulator position and orientation back to a stashed state.
*
* @see #getCurrentBookmark()
* @see #getHomeBookmark()
*/
public void jumpToBookmark(Bookmark bookmark) {
nJumpToBookmark(mNativeObject, bookmark.getNativeObject());
}
private static native long nCreateBuilder();
private static native void nDestroyBuilder(long nativeBuilder);
private static native void nBuilderViewport(long nativeBuilder, int width, int height);
private static native void nBuilderTargetPosition(long nativeBuilder, float x, float y, float z);
private static native void nBuilderUpVector(long nativeBuilder, float x, float y, float z);
private static native void nBuilderZoomSpeed(long nativeBuilder, float arg);
private static native void nBuilderOrbitHomePosition(long nativeBuilder, float x, float y, float z);
private static native void nBuilderOrbitSpeed(long nativeBuilder, float x, float y);
private static native void nBuilderFovDirection(long nativeBuilder, int arg);
private static native void nBuilderFovDegrees(long nativeBuilder, float arg);
private static native void nBuilderFarPlane(long nativeBuilder, float distance);
private static native void nBuilderMapExtent(long nativeBuilder, float width, float height);
private static native void nBuilderMapMinDistance(long nativeBuilder, float arg);
private static native void nBuilderGroundPlane(long nativeBuilder, float a, float b, float c, float d);
private static native long nBuilderBuild(long nativeBuilder, int mode);
private static native void nDestroyManipulator(long nativeManip);
private static native int nGetMode(long nativeManip);
private static native void nSetViewport(long nativeManip, int width, int height);
private static native void nGetLookAtFloat(long nativeManip, float[] eyePosition, float[] targetPosition, float[] upward);
private static native void nGetLookAtDouble(long nativeManip, double[] eyePosition, double[] targetPosition, double[] upward);
private static native void nRaycast(long nativeManip, int x, int y, float[] result);
private static native void nGrabBegin(long nativeManip, int x, int y, boolean strafe);
private static native void nGrabUpdate(long nativeManip, int x, int y);
private static native void nGrabEnd(long nativeManip);
private static native void nZoom(long nativeManip, int x, int y, float scrolldelta);
private static native long nGetCurrentBookmark(long nativeManip);
private static native long nGetHomeBookmark(long nativeManip);
private static native void nJumpToBookmark(long nativeManip, long nativeBookmark);
}

View File

@@ -0,0 +1,520 @@
/*
* Copyright (C) 2017 Romain Guy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.filament.utils
import kotlin.math.*
enum class MatrixColumn {
X, Y, Z, W
}
data class Mat2(
var x: Float2 = Float2(x = 1.0f),
var y: Float2 = Float2(y = 1.0f)) {
constructor(m: Mat2) : this(m.x.copy(), m.y.copy())
companion object {
fun of(vararg a: Float): Mat2 {
require(a.size >= 4)
return Mat2(
Float2(a[0], a[2]),
Float2(a[1], a[3])
)
}
fun identity() = Mat2()
}
operator fun get(column: Int) = when(column) {
0 -> x
1 -> y
else -> throw IllegalArgumentException("column must be in 0..1")
}
operator fun get(column: Int, row: Int) = get(column)[row]
operator fun get(column: MatrixColumn) = when(column) {
MatrixColumn.X -> x
MatrixColumn.Y -> y
else -> throw IllegalArgumentException("column must be X or Y")
}
operator fun get(column: MatrixColumn, row: Int) = get(column)[row]
operator fun invoke(row: Int, column: Int) = get(column - 1)[row - 1]
operator fun invoke(row: Int, column: Int, v: Float) = set(column - 1, row - 1, v)
operator fun set(column: Int, v: Float2) {
this[column].xy = v
}
operator fun set(column: Int, row: Int, v: Float) {
this[column][row] = v
}
operator fun unaryMinus() = Mat2(-x, -y)
operator fun inc(): Mat2 {
x++
y++
return this
}
operator fun dec(): Mat2 {
x--
y--
return this
}
operator fun plus(v: Float) = Mat2(x + v, y + v)
operator fun minus(v: Float) = Mat2(x - v, y - v)
operator fun times(v: Float) = Mat2(x * v, y * v)
operator fun div(v: Float) = Mat2(x / v, y / v)
operator fun times(m: Mat2): Mat2 {
val t = transpose(this)
return Mat2(
Float2(dot(t.x, m.x), dot(t.y, m.x)),
Float2(dot(t.x, m.y), dot(t.y, m.y))
)
}
operator fun times(v: Float2): Float2 {
val t = transpose(this)
return Float2(dot(t.x, v), dot(t.y, v))
}
fun toFloatArray() = floatArrayOf(
x.x, y.x,
x.y, y.y
)
override fun toString(): String {
return """
|${x.x} ${y.x}|
|${x.y} ${y.y}|
""".trimIndent()
}
}
data class Mat3(
var x: Float3 = Float3(x = 1.0f),
var y: Float3 = Float3(y = 1.0f),
var z: Float3 = Float3(z = 1.0f)) {
constructor(m: Mat3) : this(m.x.copy(), m.y.copy(), m.z.copy())
companion object {
fun of(vararg a: Float): Mat3 {
require(a.size >= 9)
return Mat3(
Float3(a[0], a[3], a[6]),
Float3(a[1], a[4], a[7]),
Float3(a[2], a[5], a[8])
)
}
fun identity() = Mat3()
}
operator fun get(column: Int) = when(column) {
0 -> x
1 -> y
2 -> z
else -> throw IllegalArgumentException("column must be in 0..2")
}
operator fun get(column: Int, row: Int) = get(column)[row]
operator fun get(column: MatrixColumn) = when(column) {
MatrixColumn.X -> x
MatrixColumn.Y -> y
MatrixColumn.Z -> z
else -> throw IllegalArgumentException("column must be X, Y or Z")
}
operator fun get(column: MatrixColumn, row: Int) = get(column)[row]
operator fun invoke(row: Int, column: Int) = get(column - 1)[row - 1]
operator fun invoke(row: Int, column: Int, v: Float) = set(column - 1, row - 1, v)
operator fun set(column: Int, v: Float3) {
this[column].xyz = v
}
operator fun set(column: Int, row: Int, v: Float) {
this[column][row] = v
}
operator fun unaryMinus() = Mat3(-x, -y, -z)
operator fun inc(): Mat3 {
x++
y++
z++
return this
}
operator fun dec(): Mat3 {
x--
y--
z--
return this
}
operator fun plus(v: Float) = Mat3(x + v, y + v, z + v)
operator fun minus(v: Float) = Mat3(x - v, y - v, z - v)
operator fun times(v: Float) = Mat3(x * v, y * v, z * v)
operator fun div(v: Float) = Mat3(x / v, y / v, z / v)
operator fun times(m: Mat3): Mat3 {
val t = transpose(this)
return Mat3(
Float3(dot(t.x, m.x), dot(t.y, m.x), dot(t.z, m.x)),
Float3(dot(t.x, m.y), dot(t.y, m.y), dot(t.z, m.y)),
Float3(dot(t.x, m.z), dot(t.y, m.z), dot(t.z, m.z))
)
}
operator fun times(v: Float3): Float3 {
val t = transpose(this)
return Float3(dot(t.x, v), dot(t.y, v), dot(t.z, v))
}
fun toFloatArray() = floatArrayOf(
x.x, y.x, z.x,
x.y, y.y, z.y,
x.z, y.z, z.z
)
override fun toString(): String {
return """
|${x.x} ${y.x} ${z.x}|
|${x.y} ${y.y} ${z.y}|
|${x.z} ${y.z} ${z.z}|
""".trimIndent()
}
}
data class Mat4(
var x: Float4 = Float4(x = 1.0f),
var y: Float4 = Float4(y = 1.0f),
var z: Float4 = Float4(z = 1.0f),
var w: Float4 = Float4(w = 1.0f)) {
constructor(right: Float3, up: Float3, forward: Float3, position: Float3 = Float3()) :
this(Float4(right), Float4(up), Float4(forward), Float4(position, 1.0f))
constructor(m: Mat4) : this(m.x.copy(), m.y.copy(), m.z.copy(), m.w.copy())
companion object {
fun of(vararg a: Float): Mat4 {
require(a.size >= 16)
return Mat4(
Float4(a[0], a[4], a[8], a[12]),
Float4(a[1], a[5], a[9], a[13]),
Float4(a[2], a[6], a[10], a[14]),
Float4(a[3], a[7], a[11], a[15])
)
}
fun identity() = Mat4()
}
inline var right: Float3
get() = x.xyz
set(value) {
x.xyz = value
}
inline var up: Float3
get() = y.xyz
set(value) {
y.xyz = value
}
inline var forward: Float3
get() = z.xyz
set(value) {
z.xyz = value
}
inline var position: Float3
get() = w.xyz
set(value) {
w.xyz = value
}
inline val scale: Float3
get() = Float3(length(x.xyz), length(y.xyz), length(z.xyz))
inline val translation: Float3
get() = w.xyz
val rotation: Float3
get() {
val x = normalize(right)
val y = normalize(up)
val z = normalize(forward)
return when {
z.y <= -1.0f -> Float3(degrees(-HALF_PI), 0.0f, degrees(atan2( x.z, y.z)))
z.y >= 1.0f -> Float3(degrees( HALF_PI), 0.0f, degrees(atan2(-x.z, -y.z)))
else -> Float3(
degrees(-asin(z.y)), degrees(-atan2(z.x, z.z)), degrees(atan2( x.y, y.y)))
}
}
inline val upperLeft: Mat3
get() = Mat3(x.xyz, y.xyz, z.xyz)
operator fun get(column: Int) = when(column) {
0 -> x
1 -> y
2 -> z
3 -> w
else -> throw IllegalArgumentException("column must be in 0..3")
}
operator fun get(column: Int, row: Int) = get(column)[row]
operator fun get(column: MatrixColumn) = when(column) {
MatrixColumn.X -> x
MatrixColumn.Y -> y
MatrixColumn.Z -> z
MatrixColumn.W -> w
}
operator fun get(column: MatrixColumn, row: Int) = get(column)[row]
operator fun invoke(row: Int, column: Int) = get(column - 1)[row - 1]
operator fun invoke(row: Int, column: Int, v: Float) = set(column - 1, row - 1, v)
operator fun set(column: Int, v: Float4) {
this[column].xyzw = v
}
operator fun set(column: Int, row: Int, v: Float) {
this[column][row] = v
}
operator fun unaryMinus() = Mat4(-x, -y, -z, -w)
operator fun inc(): Mat4 {
x++
y++
z++
w++
return this
}
operator fun dec(): Mat4 {
x--
y--
z--
w--
return this
}
operator fun plus(v: Float) = Mat4(x + v, y + v, z + v, w + v)
operator fun minus(v: Float) = Mat4(x - v, y - v, z - v, w - v)
operator fun times(v: Float) = Mat4(x * v, y * v, z * v, w * v)
operator fun div(v: Float) = Mat4(x / v, y / v, z / v, w / v)
operator fun times(m: Mat4): Mat4 {
val t = transpose(this)
return Mat4(
Float4(dot(t.x, m.x), dot(t.y, m.x), dot(t.z, m.x), dot(t.w, m.x)),
Float4(dot(t.x, m.y), dot(t.y, m.y), dot(t.z, m.y), dot(t.w, m.y)),
Float4(dot(t.x, m.z), dot(t.y, m.z), dot(t.z, m.z), dot(t.w, m.z)),
Float4(dot(t.x, m.w), dot(t.y, m.w), dot(t.z, m.w), dot(t.w, m.w))
)
}
operator fun times(v: Float4): Float4 {
val t = transpose(this)
return Float4(dot(t.x, v), dot(t.y, v), dot(t.z, v), dot(t.w, v))
}
fun toFloatArray() = floatArrayOf(
x.x, y.x, z.x, w.x,
x.y, y.y, z.y, w.y,
x.z, y.z, z.z, w.z,
x.w, y.w, z.w, w.w
)
override fun toString(): String {
return """
|${x.x} ${y.x} ${z.x} ${w.x}|
|${x.y} ${y.y} ${z.y} ${w.y}|
|${x.z} ${y.z} ${z.z} ${w.z}|
|${x.w} ${y.w} ${z.w} ${w.w}|
""".trimIndent()
}
}
fun transpose(m: Mat2) = Mat2(
Float2(m.x.x, m.y.x),
Float2(m.x.y, m.y.y)
)
fun transpose(m: Mat3) = Mat3(
Float3(m.x.x, m.y.x, m.z.x),
Float3(m.x.y, m.y.y, m.z.y),
Float3(m.x.z, m.y.z, m.z.z)
)
fun inverse(m: Mat3): Mat3 {
val a = m.x.x
val b = m.x.y
val c = m.x.z
val d = m.y.x
val e = m.y.y
val f = m.y.z
val g = m.z.x
val h = m.z.y
val i = m.z.z
val A = e * i - f * h
val B = f * g - d * i
val C = d * h - e * g
val det = a * A + b * B + c * C
return Mat3.of(
A / det, B / det, C / det,
(c * h - b * i) / det, (a * i - c * g) / det, (b * g - a * h) / det,
(b * f - c * e) / det, (c * d - a * f) / det, (a * e - b * d) / det
)
}
fun transpose(m: Mat4) = Mat4(
Float4(m.x.x, m.y.x, m.z.x, m.w.x),
Float4(m.x.y, m.y.y, m.z.y, m.w.y),
Float4(m.x.z, m.y.z, m.z.z, m.w.z),
Float4(m.x.w, m.y.w, m.z.w, m.w.w)
)
fun inverse(m: Mat4): Mat4 {
val result = Mat4()
var pair0 = m.z.z * m.w.w
var pair1 = m.w.z * m.z.w
var pair2 = m.y.z * m.w.w
var pair3 = m.w.z * m.y.w
var pair4 = m.y.z * m.z.w
var pair5 = m.z.z * m.y.w
var pair6 = m.x.z * m.w.w
var pair7 = m.w.z * m.x.w
var pair8 = m.x.z * m.z.w
var pair9 = m.z.z * m.x.w
var pair10 = m.x.z * m.y.w
var pair11 = m.y.z * m.x.w
result.x.x = pair0 * m.y.y + pair3 * m.z.y + pair4 * m.w.y
result.x.x -= pair1 * m.y.y + pair2 * m.z.y + pair5 * m.w.y
result.x.y = pair1 * m.x.y + pair6 * m.z.y + pair9 * m.w.y
result.x.y -= pair0 * m.x.y + pair7 * m.z.y + pair8 * m.w.y
result.x.z = pair2 * m.x.y + pair7 * m.y.y + pair10 * m.w.y
result.x.z -= pair3 * m.x.y + pair6 * m.y.y + pair11 * m.w.y
result.x.w = pair5 * m.x.y + pair8 * m.y.y + pair11 * m.z.y
result.x.w -= pair4 * m.x.y + pair9 * m.y.y + pair10 * m.z.y
result.y.x = pair1 * m.y.x + pair2 * m.z.x + pair5 * m.w.x
result.y.x -= pair0 * m.y.x + pair3 * m.z.x + pair4 * m.w.x
result.y.y = pair0 * m.x.x + pair7 * m.z.x + pair8 * m.w.x
result.y.y -= pair1 * m.x.x + pair6 * m.z.x + pair9 * m.w.x
result.y.z = pair3 * m.x.x + pair6 * m.y.x + pair11 * m.w.x
result.y.z -= pair2 * m.x.x + pair7 * m.y.x + pair10 * m.w.x
result.y.w = pair4 * m.x.x + pair9 * m.y.x + pair10 * m.z.x
result.y.w -= pair5 * m.x.x + pair8 * m.y.x + pair11 * m.z.x
pair0 = m.z.x * m.w.y
pair1 = m.w.x * m.z.y
pair2 = m.y.x * m.w.y
pair3 = m.w.x * m.y.y
pair4 = m.y.x * m.z.y
pair5 = m.z.x * m.y.y
pair6 = m.x.x * m.w.y
pair7 = m.w.x * m.x.y
pair8 = m.x.x * m.z.y
pair9 = m.z.x * m.x.y
pair10 = m.x.x * m.y.y
pair11 = m.y.x * m.x.y
result.z.x = pair0 * m.y.w + pair3 * m.z.w + pair4 * m.w.w
result.z.x -= pair1 * m.y.w + pair2 * m.z.w + pair5 * m.w.w
result.z.y = pair1 * m.x.w + pair6 * m.z.w + pair9 * m.w.w
result.z.y -= pair0 * m.x.w + pair7 * m.z.w + pair8 * m.w.w
result.z.z = pair2 * m.x.w + pair7 * m.y.w + pair10 * m.w.w
result.z.z -= pair3 * m.x.w + pair6 * m.y.w + pair11 * m.w.w
result.z.w = pair5 * m.x.w + pair8 * m.y.w + pair11 * m.z.w
result.z.w -= pair4 * m.x.w + pair9 * m.y.w + pair10 * m.z.w
result.w.x = pair2 * m.z.z + pair5 * m.w.z + pair1 * m.y.z
result.w.x -= pair4 * m.w.z + pair0 * m.y.z + pair3 * m.z.z
result.w.y = pair8 * m.w.z + pair0 * m.x.z + pair7 * m.z.z
result.w.y -= pair6 * m.z.z + pair9 * m.w.z + pair1 * m.x.z
result.w.z = pair6 * m.y.z + pair11 * m.w.z + pair3 * m.x.z
result.w.z -= pair10 * m.w.z + pair2 * m.x.z + pair7 * m.y.z
result.w.w = pair10 * m.z.z + pair4 * m.x.z + pair9 * m.y.z
result.w.w -= pair8 * m.y.z + pair11 * m.z.z + pair5 * m.x.z
val determinant = m.x.x * result.x.x + m.y.x * result.x.y + m.z.x * result.x.z + m.w.x * result.x.w
return result / determinant
}
fun scale(s: Float3) = Mat4(Float4(x = s.x), Float4(y = s.y), Float4(z = s.z))
fun scale(m: Mat4) = scale(m.scale)
fun translation(t: Float3) = Mat4(w = Float4(t, 1.0f))
fun translation(m: Mat4) = translation(m.translation)
fun rotation(m: Mat4) = Mat4(normalize(m.right), normalize(m.up), normalize(m.forward))
fun rotation(d: Float3): Mat4 {
val r = transform(d, ::radians)
val c = transform(r, { x -> cos(x) })
val s = transform(r, { x -> sin(x) })
return Mat4.of(
c.y * c.z, -c.x * s.z + s.x * s.y * c.z, s.x * s.z + c.x * s.y * c.z, 0.0f,
c.y * s.z, c.x * c.z + s.x * s.y * s.z, -s.x * c.z + c.x * s.y * s.z, 0.0f,
-s.y , s.x * c.y , c.x * c.y , 0.0f,
0.0f , 0.0f , 0.0f , 1.0f
)
}
fun rotation(axis: Float3, angle: Float): Mat4 {
val x = axis.x
val y = axis.y
val z = axis.z
val r = radians(angle)
val c = cos(r)
val s = sin(r)
val d = 1.0f - c
return Mat4.of(
x * x * d + c , x * y * d - z * s, x * z * d + y * s, 0.0f,
y * x * d + z * s, y * y * d + c , y * z * d - x * s, 0.0f,
z * x * d - y * s, z * y * d + x * s, z * z * d + c , 0.0f,
0.0f , 0.0f , 0.0f , 1.0f
)
}
fun normal(m: Mat4) = scale(1.0f / Float3(length2(m.right), length2(m.up), length2(m.forward))) * m
fun lookAt(eye: Float3, target: Float3, up: Float3 = Float3(z = 1.0f)): Mat4 {
return lookTowards(eye, target - eye, up)
}
fun lookTowards(eye: Float3, forward: Float3, up: Float3 = Float3(z = 1.0f)): Mat4 {
val f = normalize(forward)
val r = normalize(f x up)
val u = normalize(r x f)
return Mat4(Float4(r), Float4(u), Float4(f), Float4(eye, 1.0f))
}
fun perspective(fov: Float, ratio: Float, near: Float, far: Float): Mat4 {
val t = 1.0f / tan(radians(fov) * 0.5f)
val a = (far + near) / (far - near)
val b = (2.0f * far * near) / (far - near)
val c = t / ratio
return Mat4(Float4(x = c), Float4(y = t), Float4(z = a, w = 1.0f), Float4(z = -b))
}
fun ortho(l: Float, r: Float, b: Float, t: Float, n: Float, f: Float) = Mat4(
Float4(x = 2.0f / (r - 1.0f)),
Float4(y = 2.0f / (t - b)),
Float4(z = -2.0f / (f - n)),
Float4(-(r + l) / (r - l), -(t + b) / (t - b), -(f + n) / (f - n), 1.0f)
)

View File

@@ -0,0 +1,268 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.filament.utils
import android.view.MotionEvent
import android.view.Surface
import android.view.SurfaceView
import android.view.TextureView
import com.google.android.filament.*
import com.google.android.filament.android.UiHelper
import com.google.android.filament.gltfio.*
import java.nio.Buffer
/**
* Helps render glTF models into a [SurfaceView] or [TextureView] with an orbit controller.
*
* `ModelViewer` owns a Filament engine, renderer, swapchain, view, and scene. It allows clients
* to access these objects via read-only properties. The viewer can display only one glTF scene
* at a time, which can be scaled and translated into the viewing frustum by calling
* [transformToUnitCube]. All ECS entities can be accessed and modified via the [asset] property.
*
* For GLB files, clients can call [loadModelGlb] and pass in a [Buffer] with the contents of the
* GLB file. For glTF files, clients can call [loadModelGltf] and pass in a [Buffer] with the JSON
* contents, as well as a callback for loading external resources.
*
* `ModelViewer` reduces much of the boilerplate required for simple Filament applications, but
* clients still have the responsibility of adding an [IndirectLight] and [Skybox] to the scene.
* Additionally, clients should:
*
* 1. Call [onTouchEvent] from a touch handler.
* 2. Call [render] and [Animator.applyAnimation] from a `Choreographer` frame callback.
*
* NOTE: if its associated SurfaceView or TextureView has become detached from its window, the
* ModelViewer becomes invalid and must be recreated.
*
* See `sample-gltf-viewer` for a usage example.
*/
class ModelViewer {
var asset: FilamentAsset? = null
private set
var animator: Animator? = null
private set
val engine: Engine
val scene: Scene
val view: View
val camera: Camera
@Entity val light: Int
private val uiHelper: UiHelper = UiHelper(UiHelper.ContextErrorPolicy.DONT_CHECK)
private val cameraManipulator: Manipulator
private val gestureDetector: GestureDetector
private val renderer: Renderer
private var swapChain: SwapChain? = null
private var assetLoader: AssetLoader
private val eyePos = DoubleArray(3)
private val target = DoubleArray(3)
private val upward = DoubleArray(3)
private val kNearPlane = 0.5
private val kFarPlane = 10000.0
private val kFovDegrees = 45.0
private val kAperture = 16f
private val kShutterSpeed = 1f / 125f
private val kSensitivity = 100f
init {
engine = Engine.create()
renderer = engine.createRenderer()
scene = engine.createScene()
camera = engine.createCamera().apply { setExposure(kAperture, kShutterSpeed, kSensitivity) }
view = engine.createView()
view.scene = scene
view.camera = camera
assetLoader = AssetLoader(engine, MaterialProvider(engine), EntityManager.get())
// Always add a direct light source since it is required for shadowing.
// We highly recommend adding an indirect light as well.
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)
scene.addEntity(light)
}
constructor(surfaceView: SurfaceView) {
cameraManipulator = Manipulator.Builder()
.targetPosition(0.0f, 0.0f, -4.0f)
.viewport(surfaceView.width, surfaceView.height)
.build(Manipulator.Mode.ORBIT)
gestureDetector = GestureDetector(surfaceView, cameraManipulator)
uiHelper.renderCallback = SurfaceCallback()
uiHelper.attachTo(surfaceView)
addDetachListener(surfaceView)
}
@Suppress("unused")
constructor(textureView: TextureView) {
cameraManipulator = Manipulator.Builder()
.targetPosition(0.0f, 0.0f, -4.0f)
.viewport(textureView.width, textureView.height)
.build(Manipulator.Mode.ORBIT)
gestureDetector = GestureDetector(textureView, cameraManipulator)
uiHelper.renderCallback = SurfaceCallback()
uiHelper.attachTo(textureView)
addDetachListener(textureView)
}
/**
* Loads a monolithic binary glTF and populates the Filament scene.
*/
fun loadModelGlb(buffer: Buffer) {
destroyModel()
asset = assetLoader.createAssetFromJson(buffer)
asset?.let { asset ->
val resourceLoader = ResourceLoader(engine)
resourceLoader.loadResources(asset)
resourceLoader.destroy()
animator = asset.animator
asset.releaseSourceData()
scene.addEntities(asset.entities)
}
}
/**
* Loads a JSON-style glTF file and populates the Filament scene.
*/
fun loadModelGltf(buffer: Buffer, callback: (String) -> Buffer) {
destroyModel()
asset = assetLoader.createAssetFromJson(buffer)
asset?.let { asset ->
val resourceLoader = ResourceLoader(engine)
for (uri in asset.resourceUris) {
resourceLoader.addResourceData(uri, callback(uri))
}
resourceLoader.loadResources(asset)
resourceLoader.destroy()
animator = asset.animator
asset.releaseSourceData()
scene.addEntities(asset.entities)
}
}
/**
* Sets up a root transform on the current model to make it fit into the viewing frustum.
*/
fun transformToUnitCube() {
asset?.let { asset ->
val tm = engine.transformManager
val center = asset.boundingBox.center.let { v-> Float3(v[0], v[1], v[2]) }
val halfExtent = asset.boundingBox.halfExtent.let { v-> Float3(v[0], v[1], v[2]) }
val maxExtent = 2.0f * max(halfExtent)
val scaleFactor = 2.0f / maxExtent
center.z = center.z + 4.0f / scaleFactor
val transform = scale(Float3(scaleFactor)) * translation(Float3(-center))
tm.setTransform(tm.getInstance(asset.root), transpose(transform).toFloatArray())
}
}
/**
* Frees all entities associated with the most recently-loaded model.
*/
fun destroyModel() {
asset?.let { asset ->
assetLoader.destroyAsset(asset)
this.asset = null
this.animator = null
}
}
/**
* Renders the model and updates the Filament camera.
*/
fun render() {
if (!uiHelper.isReadyToRender) {
return
}
cameraManipulator.getLookAt(eyePos, target, upward)
camera.lookAt(
eyePos[0], eyePos[1], eyePos[2],
target[0], target[1], target[2],
upward[0], upward[1], upward[2])
if (renderer.beginFrame(swapChain!!)) {
renderer.render(view)
renderer.endFrame()
}
}
private fun addDetachListener(view: android.view.View) {
view.addOnAttachStateChangeListener(object : android.view.View.OnAttachStateChangeListener {
override fun onViewAttachedToWindow(v: android.view.View?) {}
override fun onViewDetachedFromWindow(v: android.view.View?) {
uiHelper.detach()
destroyModel()
assetLoader.destroy()
engine.destroyEntity(light)
engine.destroyRenderer(renderer)
engine.destroyView(this@ModelViewer.view)
engine.destroyScene(scene)
engine.destroyCamera(camera)
EntityManager.get().destroy(light)
engine.destroy()
}
})
}
/**
* Handles a [MotionEvent] to enable one-finger orbit, two-finger pan, and pinch-to-zoom.
*/
fun onTouchEvent(event: MotionEvent) {
gestureDetector.onTouchEvent(event)
}
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)
engine.flushAndWait()
swapChain = null
}
}
override fun onResized(width: Int, height: Int) {
view.viewport = Viewport(0, 0, width, height)
val aspect = width.toDouble() / height.toDouble()
camera.setProjection(kFovDegrees, aspect, kNearPlane, kFarPlane, Camera.Fov.VERTICAL)
cameraManipulator.setViewport(width, height)
}
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright (C) 2018 The Android Open Source Project
* Copyright (C) 2017 Romain Guy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -14,9 +14,8 @@
* limitations under the License.
*/
// Empty symbol used to suppress warnings on Darwin
#if __has_attribute(visibility)
__attribute__((visibility("hidden")))
#endif
void e() {
}
package com.google.android.filament.utils
data class Ray(var origin: Float3 = Float3(), var direction: Float3)
fun pointAt(r: Ray, t: Float) = r.origin + r.direction * t

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2017 Romain Guy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@file:Suppress("NOTHING_TO_INLINE")
package com.google.android.filament.utils
const val FPI = 3.1415926536f
const val HALF_PI = FPI * 0.5f
const val TWO_PI = FPI * 2.0f
const val FOUR_PI = FPI * 4.0f
const val INV_PI = 1.0f / FPI
const val INV_TWO_PI = INV_PI * 0.5f
const val INV_FOUR_PI = INV_PI * 0.25f
inline fun clamp(x: Float, min: Float, max: Float)= if (x < min) min else (if (x > max) max else x)
inline fun saturate(x: Float) = clamp(x, 0.0f, 1.0f)
inline fun mix(a: Float, b: Float, x: Float) = a * (1.0f - x) + b * x
inline fun degrees(v: Float) = v * (180.0f * INV_PI)
inline fun radians(v: Float) = v * (FPI / 180.0f)
inline fun fract(v: Float) = v % 1
inline fun sqr(v: Float) = v * v
inline fun pow(x: Float, y: Float) = StrictMath.pow(x.toDouble(), y.toDouble()).toFloat()

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