Compare commits
33 Commits
thermion_f
...
thermion_f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7c0eeb7b4 | ||
|
|
fd31b4dcad | ||
|
|
41bf9ededa | ||
|
|
d745712650 | ||
|
|
1df732be7c | ||
|
|
8b413eca52 | ||
|
|
3597077d39 | ||
|
|
7704a06601 | ||
|
|
7b3ad027bf | ||
|
|
cde3af08aa | ||
|
|
7418fb867d | ||
|
|
ce71e09f65 | ||
|
|
5dec13f00b | ||
|
|
7464c05483 | ||
|
|
7b97b2e6c3 | ||
|
|
168f46cf56 | ||
|
|
5622b0ce9f | ||
|
|
c7a0b2f5cc | ||
|
|
7546b2a6c5 | ||
|
|
e363c82f2d | ||
|
|
b9643dbd94 | ||
|
|
2664e08eb3 | ||
|
|
733ba7d439 | ||
|
|
2255be3a86 | ||
|
|
03f8e2e353 | ||
|
|
be1bf3f3ca | ||
|
|
5f1334660e | ||
|
|
ec381f43ef | ||
|
|
eba843535b | ||
|
|
4fa286bd60 | ||
|
|
7293b0f8dd | ||
|
|
0279ee1985 | ||
|
|
83053c60f9 |
191
CHANGELOG.md
191
CHANGELOG.md
@@ -3,6 +3,197 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## 2024-07-23
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`thermion_dart` - `v0.1.3`](#thermion_dart---v013)
|
||||
- [`thermion_flutter_ffi` - `v0.1.0+12`](#thermion_flutter_ffi---v01012)
|
||||
- [`thermion_flutter_web` - `v0.0.3`](#thermion_flutter_web---v003)
|
||||
- [`thermion_flutter_platform_interface` - `v0.1.0+11`](#thermion_flutter_platform_interface---v01011)
|
||||
- [`thermion_flutter` - `v0.1.1+13`](#thermion_flutter---v01113)
|
||||
|
||||
Packages with dependency updates only:
|
||||
|
||||
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
|
||||
|
||||
- `thermion_flutter_platform_interface` - `v0.1.0+11`
|
||||
- `thermion_flutter` - `v0.1.1+13`
|
||||
|
||||
---
|
||||
|
||||
#### `thermion_dart` - `v0.1.3`
|
||||
|
||||
- **FIX**: manually remove leading slash for compiler path on Windows when building for Android.
|
||||
- **FIX**: web/JS bool checks need to compare to int.
|
||||
- **FIX**: shadow JS<->WASM bridge methods.
|
||||
- **FIX**: manually remove leading slash for compiler path on Windows when building for Android.
|
||||
- **FIX**: web/JS bool checks need to compare to int.
|
||||
- **FIX**: shadow JS<->WASM bridge methods.
|
||||
- **FEAT**: add clearMorphAnimationData function.
|
||||
- **FEAT**: allow passing assetPathPrefix to ThermionViewerWasm to account for Flutter build asset paths.
|
||||
- **FEAT**: allow passing assetPathPrefix to ThermionViewerWasm to account for Flutter build asset paths.
|
||||
|
||||
#### `thermion_flutter_ffi` - `v0.1.0+12`
|
||||
|
||||
- **FIX**: add logging dependency.
|
||||
- **FIX**: web/JS bool checks need to compare to int.
|
||||
- **FIX**: add logging dependency.
|
||||
- **FIX**: web/JS bool checks need to compare to int.
|
||||
|
||||
#### `thermion_flutter_web` - `v0.0.3`
|
||||
|
||||
- **FEAT**: allow passing assetPathPrefix to ThermionViewerWasm to account for Flutter build asset paths.
|
||||
- **FEAT**: allow passing assetPathPrefix to ThermionViewerWasm to account for Flutter build asset paths.
|
||||
|
||||
|
||||
## 2024-07-11
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`thermion_flutter_ffi` - `v0.1.0+11`](#thermion_flutter_ffi---v01011)
|
||||
- [`thermion_flutter` - `v0.1.1+12`](#thermion_flutter---v01112)
|
||||
|
||||
Packages with dependency updates only:
|
||||
|
||||
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
|
||||
|
||||
- `thermion_flutter` - `v0.1.1+12`
|
||||
|
||||
---
|
||||
|
||||
#### `thermion_flutter_ffi` - `v0.1.0+11`
|
||||
|
||||
- **FIX**: add logging dependency.
|
||||
|
||||
|
||||
## 2024-07-11
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`thermion_dart` - `v0.1.2`](#thermion_dart---v012)
|
||||
- [`thermion_flutter_ffi` - `v0.1.0+10`](#thermion_flutter_ffi---v01010)
|
||||
- [`thermion_flutter_web` - `v0.0.2`](#thermion_flutter_web---v002)
|
||||
- [`thermion_flutter` - `v0.1.1+11`](#thermion_flutter---v01111)
|
||||
- [`thermion_flutter_platform_interface` - `v0.1.0+10`](#thermion_flutter_platform_interface---v01010)
|
||||
|
||||
Packages with dependency updates only:
|
||||
|
||||
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
|
||||
|
||||
- `thermion_flutter` - `v0.1.1+11`
|
||||
- `thermion_flutter_platform_interface` - `v0.1.0+10`
|
||||
|
||||
---
|
||||
|
||||
#### `thermion_dart` - `v0.1.2`
|
||||
|
||||
- **FIX**: manually remove leading slash for compiler path on Windows when building for Android.
|
||||
- **FIX**: web/JS bool checks need to compare to int.
|
||||
- **FIX**: shadow JS<->WASM bridge methods.
|
||||
- **FEAT**: allow passing assetPathPrefix to ThermionViewerWasm to account for Flutter build asset paths.
|
||||
|
||||
#### `thermion_flutter_ffi` - `v0.1.0+10`
|
||||
|
||||
- **FIX**: web/JS bool checks need to compare to int.
|
||||
|
||||
#### `thermion_flutter_web` - `v0.0.2`
|
||||
|
||||
- **FEAT**: allow passing assetPathPrefix to ThermionViewerWasm to account for Flutter build asset paths.
|
||||
|
||||
|
||||
## 2024-07-04
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`thermion_dart` - `v0.1.1+5`](#thermion_dart---v0115)
|
||||
- [`thermion_flutter_web` - `v0.0.1+9`](#thermion_flutter_web---v0019)
|
||||
- [`thermion_flutter` - `v0.1.1+10`](#thermion_flutter---v01110)
|
||||
- [`thermion_flutter_platform_interface` - `v0.1.0+9`](#thermion_flutter_platform_interface---v0109)
|
||||
- [`thermion_flutter_ffi` - `v0.1.0+9`](#thermion_flutter_ffi---v0109)
|
||||
|
||||
Packages with dependency updates only:
|
||||
|
||||
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
|
||||
|
||||
- `thermion_flutter_web` - `v0.0.1+9`
|
||||
- `thermion_flutter` - `v0.1.1+10`
|
||||
- `thermion_flutter_platform_interface` - `v0.1.0+9`
|
||||
- `thermion_flutter_ffi` - `v0.1.0+9`
|
||||
|
||||
---
|
||||
|
||||
#### `thermion_dart` - `v0.1.1+5`
|
||||
|
||||
- Bump "thermion_dart" to `0.1.1+5`.
|
||||
|
||||
|
||||
## 2024-07-02
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`thermion_dart` - `v0.1.1+4`](#thermion_dart---v0114)
|
||||
- [`thermion_flutter_web` - `v0.0.1+8`](#thermion_flutter_web---v0018)
|
||||
- [`thermion_flutter` - `v0.1.1+9`](#thermion_flutter---v0119)
|
||||
- [`thermion_flutter_platform_interface` - `v0.1.0+8`](#thermion_flutter_platform_interface---v0108)
|
||||
- [`thermion_flutter_ffi` - `v0.1.0+8`](#thermion_flutter_ffi---v0108)
|
||||
|
||||
Packages with dependency updates only:
|
||||
|
||||
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
|
||||
|
||||
- `thermion_flutter_web` - `v0.0.1+8`
|
||||
- `thermion_flutter` - `v0.1.1+9`
|
||||
- `thermion_flutter_platform_interface` - `v0.1.0+8`
|
||||
- `thermion_flutter_ffi` - `v0.1.0+8`
|
||||
|
||||
---
|
||||
|
||||
#### `thermion_dart` - `v0.1.1+4`
|
||||
|
||||
- **FIX**: defer creating image entity/material/etc until actually requested.
|
||||
|
||||
|
||||
## 2024-06-27
|
||||
|
||||
### Changes
|
||||
|
||||
10
README.md
10
README.md
@@ -1,14 +1,14 @@
|
||||

|
||||
|
||||
<p align="center">
|
||||
<a href="https://docs.page/nmfisher/thermion/quickstart">Quickstart (Flutter)</a> •
|
||||
<a href="https://docs.page/nmfisher/thermion">Documentation</a> •
|
||||
<a href="https://docs.page/nmfisher/thermion/examples">Showcase</a> •
|
||||
<a href="https://thermion.dev/quickstart">Quickstart (Flutter)</a> •
|
||||
<a href="https://thermion.dev/">Documentation</a> •
|
||||
<a href="https://thermion.dev/examples">Showcase</a> •
|
||||
<a href="https://dartpad.thermion.dev/">Playground</a> •
|
||||
<a href="https://discord.gg/h2VdDK3EAQ">Discord</a>
|
||||
</p>
|
||||
|
||||
## Cross-platform 3D engine for Dart and Flutter.
|
||||
## Cross-platform 3D toolkit for Dart and Flutter.
|
||||
|
||||
<a href="https://pub.dev/packages/thermion_dart"><img src="https://img.shields.io/pub/v/thermion_dart?label=pub.dev&labelColor=333940&logo=dart&color=00589B" alt="pub"></a>
|
||||
<a href="https://github.com/nmfisher/thermion"><img src="https://img.shields.io/github/stars/nmfisher/flutter_filament?style=flat&label=stars&labelColor=333940&color=8957e5&logo=github" alt="github"></a>
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
### Sponsors, Contributors & Acknowledgments
|
||||
|
||||
Thermion uses the [Filament](https://github.com/google/filament) physically based rendering package under the hood.
|
||||
Thermion uses the [Filament](https://github.com/google/filament) Physically Based Rendering engine under the hood.
|
||||
|
||||
Special thanks to [odd-io](https://github.com/odd-io/) for sponsoring work on supporting Windows, raycasting, testing and documentation.
|
||||
|
||||
|
||||
@@ -7,14 +7,16 @@
|
||||
"Getting Started",
|
||||
[
|
||||
["Overview", "/"],
|
||||
["Quick Start", "/quickstart"],
|
||||
["Playground", "https://dartpad.thermion.dev"]
|
||||
["Quick Start", "/quickstart"]
|
||||
]
|
||||
],
|
||||
["Misc.", [
|
||||
["Playground", "https://dartpad.thermion.dev"],
|
||||
["Showcase", "/showcase"],
|
||||
["Windows", "/windows"],
|
||||
["Android", "/android"],
|
||||
["Contributing", "/contributing"]
|
||||
["Contributing", "/contributing"],
|
||||
["Discord", "https://discord.gg/h2VdDK3EAQ"]
|
||||
]]
|
||||
]
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
## Contributing
|
||||
|
||||
Thermion is an open source project and we welcome all contributions from every level of experience.
|
||||
Thermion is an open source project and all contributions are welcome, no matter the level of experience.
|
||||
|
||||
Please [join us on Discord](https://discord.gg/h2VdDK3EAQ) if you'd like some guidance or just want to chat.
|
||||
|
||||
##
|
||||
Note that the Thermion project uses [Melos](https://melos.invertase.dev/) to manage the repository.
|
||||
|
||||
We are now using [Melos](https://melos.invertase.dev/) to manage the repository. This lets us auto-generate changelogs & versioning from commit messages, so if you wish to submit a PR, please use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
|
||||
This lets us auto-generate changelogs & versioning from commit messages, so if you wish to submit a PR, please use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
|
||||
|
||||
|
||||
@@ -4,6 +4,10 @@ Thermion is a framework for creating cross-platform 3D applications with Dart an
|
||||
|
||||
## Overview
|
||||
|
||||
Below is a general overview of how the Thermion packages are structured to ensure a clean separation between the general Dart components, and the Flutter specific components.
|
||||
|
||||
If you want a more detailed explanation of how to start rendering 3D content inside a Flutter app, [click here to view the quickstart page](/quickstart).
|
||||
|
||||
### Package structure
|
||||
|
||||
Thermion is divided into two packages:
|
||||
@@ -18,8 +22,39 @@ For example, Thermion ships with examples for rendering with Dart only (no Flutt
|
||||
|
||||
### ThermionViewer (`thermion_dart`)
|
||||
|
||||
// TODO
|
||||
The ThermionViewer class provides an API for creating and interacting with 3D scenes powered by the Filament rendering engine.
|
||||
|
||||
It allows loading 3D models in glTF format, adding lights and a skybox, manipulating the camera, animating objects, and more.
|
||||
|
||||
Key functionalities include:
|
||||
- Scene Management: Load and manipulate entities, lights, skyboxes, and background elements within a 3D scene.
|
||||
- Rendering Control: Manage rendering loop, frame rate, and post-processing effects like tone mapping and bloom.
|
||||
- Camera Control: Position and orient the camera, adjust focal length, and control exposure settings.
|
||||
- Animation: Play, pause, and manipulate skeletal and morph target animations.
|
||||
- Entity Manipulation: Transform entities (position, rotation, scale), set material properties, and manage parent-child relationships.
|
||||
- Collision Detection (experimental): Add collision components to entities and test for collisions within the scene.
|
||||
- Input Handling: Interact with the scene using touch gestures for panning, rotating, and zooming.
|
||||
- Developers use the ThermionViewer class to build and control the behavior of their 3D applications.
|
||||
|
||||
### ThermionFlutterPlugin
|
||||
|
||||
The ThermionFlutterPlugin class handles the platform-specific initialization required to embed a Filament rendering surface within a Flutter Widget.
|
||||
|
||||
This includes creating a texture and managing the application lifecycle to pause rendering when the app is inactive.
|
||||
|
||||
You will generally only need to interact with `ThermionFlutterPlugin` directly to create or dispose of a ThermionViewer.
|
||||
|
||||
### ThermionWidget (`thermion_flutter`)
|
||||
|
||||
// TODO
|
||||
`ThermionWidget` is a Flutter widget that displays the 3D content rendered by a ThermionViewer.
|
||||
|
||||
It handles creating and managing the underlying platform-specific texture that Filament renders to, and provides a way to embed this texture within the Flutter widget tree.
|
||||
|
||||
Key features of ThermionWidget include:
|
||||
- Texture Management: It creates, resizes, and destroys the ThermionFlutterTexture used to display the rendered content from the ThermionViewer.
|
||||
- Platform Adaption: It handles platform-specific differences, such as texture coordinate systems, to ensure consistent rendering across different platforms.
|
||||
- Initialization Handling: Displays a placeholder (configurable via the initial property) while the Filament texture is being initialized, providing a smoother user experience.
|
||||
- Seamless Integration: Integrates seamlessly within the Flutter widget tree, allowing developers to combine 2D and 3D content easily.
|
||||
- Resize Handling: It listens for resize events and automatically resizes the underlying texture to match, ensuring the 3D content scales correctly.
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
## Quickstart (Flutter)
|
||||
|
||||
> You can find the entire project below in the [https://github.com/nmfisher/thermion_examples/tree/master/flutter/quickstart](flutter/quickstart) folder of the `thermion_examples` repository.
|
||||
> You can find the entire project below in the [flutter/quickstart](https://github.com/nmfisher/thermion_examples/tree/master/flutter/quickstart) folder of the `thermion_examples` repository.
|
||||
|
||||
1. Switch to Flutter master channel, create a new project, then add `thermion_flutter` as a dependency
|
||||
1. Switch to Flutter master channel, upgrade Flutter, create a new project, then add `thermion_flutter` as a dependency
|
||||
|
||||
```bash
|
||||
$ flutter channel master
|
||||
$ flutter upgrade
|
||||
$ flutter config --enable-native-assets
|
||||
$ flutter create thermion_sample_project && cd thermion_sample_project
|
||||
$ flutter pub add thermion_flutter
|
||||
@@ -39,7 +40,7 @@ and change the minimum deployment target to 13.0:
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Click to open Windows instructions">
|
||||
See the [/windows](Windows) page for steps needed to build on Windows.
|
||||
See the [/windows](/windows) page for steps needed to build on Windows.
|
||||
</Accordion>
|
||||
|
||||
|
||||
@@ -217,4 +218,4 @@ $ flutter run -d macos
|
||||
|
||||

|
||||
|
||||
Your first Thermion project is complete!
|
||||
Your first Thermion project is complete!
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
|
||||
A custom DartPad that lets you experiment with Thermion from your browser (currently, only Chrome is supported).
|
||||
|
||||
[](https://thermion.dev)
|
||||
[](https://dartpad.thermion.dev)
|
||||
|
||||
## Nick Fisher
|
||||
|
||||
My personal website, where I create an interactive clone of myself with Avaturn & Cartesia (no Flutter, made with Thermion and the [Jaspr Dart UI framework](https://github.com/schultek/jaspr).
|
||||
My personal website, where I create an interactive clone of myself with Avaturn & Cartesia (no Flutter, made with Thermion and the [Jaspr Dart UI framework](https://github.com/schultek/jaspr)).
|
||||
|
||||
[](https://nick-fisher.com)
|
||||
|
||||
@@ -1,3 +1,30 @@
|
||||
## 0.1.3
|
||||
|
||||
- **FIX**: manually remove leading slash for compiler path on Windows when building for Android.
|
||||
- **FIX**: web/JS bool checks need to compare to int.
|
||||
- **FIX**: shadow JS<->WASM bridge methods.
|
||||
- **FIX**: manually remove leading slash for compiler path on Windows when building for Android.
|
||||
- **FIX**: web/JS bool checks need to compare to int.
|
||||
- **FIX**: shadow JS<->WASM bridge methods.
|
||||
- **FEAT**: add clearMorphAnimationData function.
|
||||
- **FEAT**: allow passing assetPathPrefix to ThermionViewerWasm to account for Flutter build asset paths.
|
||||
- **FEAT**: allow passing assetPathPrefix to ThermionViewerWasm to account for Flutter build asset paths.
|
||||
|
||||
## 0.1.2
|
||||
|
||||
- **FIX**: manually remove leading slash for compiler path on Windows when building for Android.
|
||||
- **FIX**: web/JS bool checks need to compare to int.
|
||||
- **FIX**: shadow JS<->WASM bridge methods.
|
||||
- **FEAT**: allow passing assetPathPrefix to ThermionViewerWasm to account for Flutter build asset paths.
|
||||
|
||||
## 0.1.1+5
|
||||
|
||||
- Bump "thermion_dart" to `0.1.1+5`.
|
||||
|
||||
## 0.1.1+4
|
||||
|
||||
- **FIX**: defer creating image entity/material/etc until actually requested.
|
||||
|
||||
## 0.1.1+3
|
||||
|
||||
- **FIX**: bump ffigen dependency version & regenerate bindings (and revert to ffi.Int rather than ffi.Int32).
|
||||
|
||||
1
thermion_dart/example/README.md
Normal file
1
thermion_dart/example/README.md
Normal file
@@ -0,0 +1 @@
|
||||
For an example with both pure Dart and Flutter, see the [example repository](https://github.com/nmfisher/thermion_examples).
|
||||
@@ -176,9 +176,17 @@ void main(List<String> args) async {
|
||||
Architecture.ia32 => "i686-linux-android",
|
||||
_ => throw FormatException('Invalid')
|
||||
};
|
||||
var ndkRoot = File(config.cCompiler.compiler!.path).parent.parent.path;
|
||||
|
||||
var compilerPath = config.cCompiler.compiler!.path;
|
||||
|
||||
if(Platform.isWindows && compilerPath.startsWith("/")) {
|
||||
compilerPath = compilerPath.substring(1);
|
||||
}
|
||||
|
||||
var ndkRoot = File(compilerPath).parent.parent.uri.toFilePath(windows:true);
|
||||
|
||||
var stlPath =
|
||||
File("$ndkRoot/sysroot/usr/lib/${archExtension}/libc++_shared.so");
|
||||
File([ndkRoot, "sysroot", "usr", "lib", archExtension, "libc++_shared.so"].join(Platform.pathSeparator));
|
||||
output.addAsset(NativeCodeAsset(
|
||||
package: "thermion_dart",
|
||||
name: "libc++_shared.so",
|
||||
|
||||
@@ -368,6 +368,12 @@ external bool set_morph_animation(
|
||||
double frameLengthInMs,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int)>()
|
||||
external void clear_morph_animation(
|
||||
ffi.Pointer<ffi.Void> sceneManager,
|
||||
int entity,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int)>()
|
||||
external void reset_to_rest_pose(
|
||||
ffi.Pointer<ffi.Void> sceneManager,
|
||||
@@ -796,6 +802,25 @@ external void set_post_processing(
|
||||
bool enabled,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Bool)>()
|
||||
external void set_shadows_enabled(
|
||||
ffi.Pointer<ffi.Void> viewer,
|
||||
bool enabled,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Int)>()
|
||||
external void set_shadow_type(
|
||||
ffi.Pointer<ffi.Void> viewer,
|
||||
int shadowType,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Float, ffi.Float)>()
|
||||
external void set_soft_shadow_options(
|
||||
ffi.Pointer<ffi.Void> viewer,
|
||||
double penumbraScale,
|
||||
double penumbraRatioScale,
|
||||
);
|
||||
|
||||
@ffi.Native<
|
||||
ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Bool, ffi.Bool, ffi.Bool)>()
|
||||
external void set_antialiasing(
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
library thermion_flutter_js;
|
||||
|
||||
import 'dart:js_interop';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:thermion_dart/thermion_dart/compatibility/web/interop/thermion_viewer_js_shim.dart';
|
||||
|
||||
import 'package:vector_math/vector_math_64.dart' as v64;
|
||||
@@ -21,6 +22,7 @@ import 'package:vector_math/vector_math_64.dart';
|
||||
///
|
||||
@JSExport()
|
||||
class ThermionViewerJSDartBridge {
|
||||
final _logger = Logger("ThermionViewerJSDartBridge");
|
||||
final ThermionViewer viewer;
|
||||
|
||||
ThermionViewerJSDartBridge(this.viewer);
|
||||
@@ -76,7 +78,7 @@ class ThermionViewerJSDartBridge {
|
||||
|
||||
@JSExport()
|
||||
JSPromise loadIbl(String lightingPath, double intensity) {
|
||||
print("Loading IBL from $lightingPath with intensity $intensity");
|
||||
_logger.info("Loading IBL from $lightingPath with intensity $intensity");
|
||||
return viewer.loadIbl(lightingPath, intensity: intensity).toJS;
|
||||
}
|
||||
|
||||
@@ -130,13 +132,13 @@ class ThermionViewerJSDartBridge {
|
||||
|
||||
@JSExport()
|
||||
JSPromise<JSNumber> loadGlb(String path, {int numInstances = 1}) {
|
||||
print("Loading GLB from path $path with numInstances $numInstances");
|
||||
_logger.info("Loading GLB from path $path with numInstances $numInstances");
|
||||
return viewer
|
||||
.loadGlb(path, numInstances: numInstances)
|
||||
.then((entity) => entity.toJS)
|
||||
.catchError((err) {
|
||||
print("Error: $err");
|
||||
}).toJS;
|
||||
_logger.info("Error: $err");
|
||||
}).toJS;
|
||||
}
|
||||
|
||||
@JSExport()
|
||||
@@ -224,6 +226,11 @@ class ThermionViewerJSDartBridge {
|
||||
.then((v) => v.toJS)
|
||||
.toJS;
|
||||
|
||||
@JSExport()
|
||||
void clearMorphAnimationData(ThermionEntity entity) {
|
||||
viewer.clearMorphAnimationData(entity);
|
||||
}
|
||||
|
||||
@JSExport()
|
||||
JSPromise setMorphAnimationData(
|
||||
ThermionEntity entity,
|
||||
@@ -253,13 +260,13 @@ class ThermionViewerJSDartBridge {
|
||||
targetMeshNames: targetMeshNamesDart,
|
||||
)
|
||||
.onError((err, st) {
|
||||
print("ERROR SETTING MORPH ANIMATION DATA : $err\n$st");
|
||||
_logger.severe("ERROR SETTING MORPH ANIMATION DATA : $err\n$st");
|
||||
return null;
|
||||
});
|
||||
return result.toJS;
|
||||
} catch (err, st) {
|
||||
print(err);
|
||||
print(st);
|
||||
_logger.severe(err);
|
||||
_logger.severe(st);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
@@ -618,7 +625,7 @@ class ThermionViewerJSDartBridge {
|
||||
)
|
||||
.then((entities) => entities.map((entity) => entity.toJS).toList().toJS)
|
||||
.onError((e, st) async {
|
||||
print("Error : $e\n$st");
|
||||
_logger.severe("Error : $e\n$st");
|
||||
return <JSNumber>[].toJS;
|
||||
}).toJS;
|
||||
}
|
||||
@@ -632,7 +639,7 @@ class ThermionViewerJSDartBridge {
|
||||
)
|
||||
.then((entity) => entity.toJS)
|
||||
.onError((e, st) async {
|
||||
print("Error getChildEntity : $e\n$st");
|
||||
_logger.severe("Error getChildEntity : $e\n$st");
|
||||
return 0.toJS;
|
||||
}).toJS;
|
||||
}
|
||||
@@ -720,4 +727,20 @@ class ThermionViewerJSDartBridge {
|
||||
{JSFunction? callback, bool affectsTransform = false}) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@JSExport()
|
||||
JSPromise setShadowsEnabled(bool enabled) {
|
||||
return viewer.setShadowsEnabled(enabled).toJS;
|
||||
}
|
||||
|
||||
@JSExport()
|
||||
JSPromise setShadowType(int shadowType) {
|
||||
return viewer.setShadowType(ShadowType.values[shadowType]).toJS;
|
||||
}
|
||||
|
||||
@JSExport()
|
||||
JSPromise setSoftShadowOptions(
|
||||
double penumbraScale, double penumbraRatioScale) {
|
||||
return viewer.setSoftShadowOptions(penumbraScale, penumbraRatioScale).toJS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'dart:js_interop_unsafe';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:animation_tools_dart/animation_tools_dart.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:thermion_dart/thermion_dart/scene.dart';
|
||||
import 'package:thermion_dart/thermion_dart/thermion_viewer.dart';
|
||||
|
||||
@@ -15,6 +16,7 @@ import 'thermion_viewer_js_shim.dart';
|
||||
/// a corresponding Javascript shim implementation (see [ThermionViewerJSShim]).
|
||||
///
|
||||
class ThermionViewerJS implements ThermionViewer {
|
||||
final _logger = Logger("ThermionViewerJS");
|
||||
late final ThermionViewerJSShim _shim;
|
||||
|
||||
ThermionViewerJS.fromGlobalProperty(String globalPropertyName) {
|
||||
@@ -261,6 +263,11 @@ class ThermionViewerJS implements ThermionViewer {
|
||||
.toDartDouble;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> clearMorphAnimationData(ThermionEntity entity) async {
|
||||
_shim.clearMorphAnimationData(entity);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setMorphAnimationData(
|
||||
ThermionEntity entity, MorphAnimationData animation,
|
||||
@@ -282,8 +289,8 @@ class ThermionViewerJS implements ThermionViewer {
|
||||
targetMeshNamesJS, animation.frameLengthInMs)
|
||||
.toDart;
|
||||
} catch (err, st) {
|
||||
print(err);
|
||||
print(st);
|
||||
_logger.severe(err);
|
||||
_logger.severe(st);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
@@ -826,4 +833,19 @@ class ThermionViewerJS implements ThermionViewer {
|
||||
void onDispose(Future Function() callback) {
|
||||
_onDispose.add(callback);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setShadowType(ShadowType shadowType) {
|
||||
return _shim.setShadowType(shadowType.index).toDart;
|
||||
}
|
||||
|
||||
@override
|
||||
Future setShadowsEnabled(bool enabled) {
|
||||
return _shim.setShadowsEnabled(enabled).toDart;
|
||||
}
|
||||
|
||||
@override
|
||||
Future setSoftShadowOptions(double penumbraScale, double penumbraRatioScale) {
|
||||
return _shim.setSoftShadowOptions(penumbraScale, penumbraRatioScale).toDart;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,11 +6,10 @@ import 'dart:js_interop';
|
||||
import 'package:thermion_dart/thermion_dart/thermion_viewer.dart';
|
||||
|
||||
///
|
||||
/// An extension type on [JSObject] that represents a
|
||||
/// An extension type on [JSObject] that represents a
|
||||
/// Javascript shim implementation of the [ThermionViewer] interface.
|
||||
///
|
||||
///
|
||||
extension type ThermionViewerJSShim(JSObject _) implements JSObject {
|
||||
|
||||
@JS('initialized')
|
||||
external JSPromise<JSBoolean> get initialized;
|
||||
|
||||
@@ -136,6 +135,9 @@ extension type ThermionViewerJSShim(JSObject _) implements JSObject {
|
||||
external JSPromise<JSNumber> getAnimationDuration(
|
||||
ThermionEntity entity, int animationIndex);
|
||||
|
||||
@JS('clearMorphAnimationData')
|
||||
external void clearMorphAnimationData(ThermionEntity entity);
|
||||
|
||||
@JS('setMorphAnimationData')
|
||||
external JSPromise setMorphAnimationData(
|
||||
ThermionEntity entity,
|
||||
@@ -403,7 +405,16 @@ extension type ThermionViewerJSShim(JSObject _) implements JSObject {
|
||||
ThermionEntity entity, JSArray<JSNumber> transform);
|
||||
|
||||
@JS('setBoneTransform')
|
||||
external JSPromise setBoneTransform(
|
||||
ThermionEntity entity, int boneIndex, JSArray<JSNumber> transform, int skinIndex);
|
||||
}
|
||||
external JSPromise setBoneTransform(ThermionEntity entity, int boneIndex,
|
||||
JSArray<JSNumber> transform, int skinIndex);
|
||||
|
||||
@JS('setShadowsEnabled')
|
||||
external JSPromise setShadowsEnabled(bool enabled);
|
||||
|
||||
@JS('setShadowType')
|
||||
external JSPromise setShadowType(int shadowType);
|
||||
|
||||
@JS('setSoftShadowOptions')
|
||||
external JSPromise setSoftShadowOptions(
|
||||
double penumbraScale, double penumbraRatioScale);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'dart:js_interop_unsafe';
|
||||
import 'dart:math';
|
||||
import 'dart:typed_data' as td;
|
||||
import 'dart:typed_data';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:thermion_dart/thermion_dart/scene.dart';
|
||||
import 'package:web/web.dart';
|
||||
import 'package:animation_tools_dart/animation_tools_dart.dart';
|
||||
@@ -35,19 +36,48 @@ extension type _EmscriptenModule(JSObject _) implements JSObject {
|
||||
|
||||
typedef ThermionViewerImpl = ThermionViewerWasm;
|
||||
|
||||
|
||||
///
|
||||
/// A [ThermionViewer] implementation that forwards calls to
|
||||
/// the (Emscripten-generated) ThermionDart JS module.
|
||||
/// A [ThermionViewer] implementation that forwards calls to the
|
||||
/// (Emscripten-generated) ThermionDart JS module.
|
||||
///
|
||||
class ThermionViewerWasm implements ThermionViewer {
|
||||
final _logger = Logger("ThermionViewerWasm");
|
||||
|
||||
late _EmscriptenModule _module;
|
||||
|
||||
bool _initialized = false;
|
||||
bool _rendering = false;
|
||||
|
||||
ThermionViewerWasm({JSObject? module, String moduleName = "thermion_dart"}) {
|
||||
_module = module as _EmscriptenModule? ?? window.getProperty<_EmscriptenModule>(moduleName.toJS);
|
||||
///
|
||||
/// Construct an instance of this class by explicitly passing the
|
||||
/// module instance via the [module] property, or by specifying [moduleName],
|
||||
/// being the name of the window property where the module has already been
|
||||
/// loaded.
|
||||
///
|
||||
/// Pass [assetPathPrefix] if you need to prepend a path to all asset paths
|
||||
/// (e.g. on Flutter where the asset directory /foo is actually shipped under
|
||||
/// the directory /assets/foo, you would construct this as:
|
||||
///
|
||||
/// final viewer = ThermionViewerWasm(assetPathPrefix:"/assets/")
|
||||
///
|
||||
ThermionViewerWasm(
|
||||
{JSObject? module,
|
||||
String moduleName = "thermion_dart",
|
||||
String? assetPathPrefix}) {
|
||||
_module = module as _EmscriptenModule? ??
|
||||
window.getProperty<_EmscriptenModule>(moduleName.toJS);
|
||||
if (assetPathPrefix != null) {
|
||||
_setAssetPathPrefix(assetPathPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
void _setAssetPathPrefix(String assetPathPrefix) {
|
||||
_module.ccall(
|
||||
"thermion_dart_web_set_asset_path_prefix",
|
||||
"void",
|
||||
<JSString>["string".toJS].toJS,
|
||||
<JSAny>[assetPathPrefix.toJS].toJS,
|
||||
null);
|
||||
}
|
||||
|
||||
JSNumber? _viewer;
|
||||
@@ -631,8 +661,8 @@ class ThermionViewerWasm implements ThermionViewer {
|
||||
final promise = _module.ccall(
|
||||
"load_gltf",
|
||||
"int",
|
||||
["void*".toJS, "string".toJS, "string".toJS, "bool".toJS].toJS,
|
||||
[_sceneManager!, path.toJS, relativeResourcePath.toJS, force.toJS].toJS,
|
||||
["void*".toJS, "string".toJS, "string".toJS].toJS,
|
||||
[_sceneManager!, path.toJS, relativeResourcePath.toJS].toJS,
|
||||
{"async": true}.jsify()) as JSPromise<JSNumber>;
|
||||
final entityId = (await promise.toDart).toDartInt;
|
||||
if (entityId == -1) {
|
||||
@@ -758,6 +788,27 @@ class ThermionViewerWasm implements ThermionViewer {
|
||||
null);
|
||||
}
|
||||
|
||||
@override
|
||||
Future clearMorphAnimationData(
|
||||
ThermionEntity entity) async {
|
||||
var meshEntities = await getChildEntities(entity, false);
|
||||
for(final childEntity in meshEntities) {
|
||||
_module.ccall(
|
||||
"clear_morph_animation",
|
||||
"void",
|
||||
[
|
||||
"void*".toJS,
|
||||
"int".toJS,
|
||||
].toJS,
|
||||
[
|
||||
_sceneManager!,
|
||||
childEntity.toJS,
|
||||
].toJS,
|
||||
null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
Future setMorphAnimationData(
|
||||
ThermionEntity entity, MorphAnimationData animation,
|
||||
@@ -785,7 +836,7 @@ class ThermionViewerWasm implements ThermionViewer {
|
||||
var meshEntity = meshEntities[i];
|
||||
|
||||
if (targetMeshNames?.contains(meshName) == false) {
|
||||
// print("Skipping $meshName, not contained in target");
|
||||
// _logger.info("Skipping $meshName, not contained in target");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -793,7 +844,7 @@ class ThermionViewerWasm implements ThermionViewer {
|
||||
|
||||
var meshMorphTargets = await getMorphTargetNames(entity, meshEntity);
|
||||
|
||||
print("Got mesh morph targets ${meshMorphTargets}");
|
||||
_logger.info("Got mesh morph targets ${meshMorphTargets}");
|
||||
|
||||
var intersection = animation.morphTargets
|
||||
.toSet()
|
||||
@@ -835,35 +886,42 @@ class ThermionViewerWasm implements ThermionViewer {
|
||||
// Copy the morph indices to WASM
|
||||
_module.writeArrayToMemory(
|
||||
idxList.buffer.asUint8List(idxList.offsetInBytes).toJS, idxPtr);
|
||||
|
||||
var result = _module.ccall(
|
||||
"set_morph_animation",
|
||||
"bool",
|
||||
[
|
||||
"void*".toJS,
|
||||
"int".toJS,
|
||||
"float*".toJS,
|
||||
"int*".toJS,
|
||||
"int".toJS,
|
||||
"int".toJS,
|
||||
"float".toJS
|
||||
].toJS,
|
||||
[
|
||||
_sceneManager!,
|
||||
meshEntity.toJS,
|
||||
dataPtr,
|
||||
idxPtr,
|
||||
indices.length.toJS,
|
||||
animation.numFrames.toJS,
|
||||
animation.frameLengthInMs.toJS
|
||||
].toJS,
|
||||
null) as JSBoolean;
|
||||
bool result = false;
|
||||
try {
|
||||
var jsResult = _module.ccall(
|
||||
"set_morph_animation",
|
||||
"bool",
|
||||
[
|
||||
"void*".toJS,
|
||||
"int".toJS,
|
||||
"float*".toJS,
|
||||
"int*".toJS,
|
||||
"int".toJS,
|
||||
"int".toJS,
|
||||
"float".toJS
|
||||
].toJS,
|
||||
[
|
||||
_sceneManager!,
|
||||
meshEntity.toJS,
|
||||
dataPtr,
|
||||
idxPtr,
|
||||
indices.length.toJS,
|
||||
animation.numFrames.toJS,
|
||||
animation.frameLengthInMs.toJS
|
||||
].toJS,
|
||||
null);
|
||||
_logger.info("Got jsResult $jsResult");
|
||||
result = (jsResult as JSNumber).toDartInt == 1;
|
||||
} catch (err, st) {
|
||||
_logger.severe(err);
|
||||
_logger.severe(st);
|
||||
}
|
||||
|
||||
// Free the memory allocated in WASM
|
||||
_module._free(dataPtr);
|
||||
_module._free(idxPtr);
|
||||
|
||||
if (!result.toDart) {
|
||||
if (!result) {
|
||||
throw Exception("Failed to set morph animation data for ${meshName}");
|
||||
}
|
||||
}
|
||||
@@ -1847,4 +1905,27 @@ class ThermionViewerWasm implements ThermionViewer {
|
||||
// TODO: implement zoomUpdate
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setShadowType(ShadowType shadowType) async {
|
||||
_module.ccall("set_shadow_type", "void", ["void*".toJS, "int".toJS].toJS,
|
||||
[_viewer!, shadowType.index.toJS].toJS, null);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setShadowsEnabled(bool enabled) async {
|
||||
_module.ccall("set_shadows_enabled", "void",
|
||||
["void*".toJS, "bool".toJS].toJS, [_viewer!, enabled.toJS].toJS, null);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setSoftShadowOptions(
|
||||
double penumbraScale, double penumbraRatioScale) async {
|
||||
_module.ccall(
|
||||
"set_soft_shadow_options",
|
||||
"void",
|
||||
["void*".toJS, "float".toJS, "float".toJS].toJS,
|
||||
[_viewer!, penumbraScale.toJS, penumbraRatioScale.toJS].toJS,
|
||||
null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,13 @@ enum LightType {
|
||||
SPOT,
|
||||
}
|
||||
|
||||
enum ShadowType {
|
||||
PCF, //!< percentage-closer filtered shadows (default)
|
||||
VSM, //!< variance shadows
|
||||
DPCF, //!< PCF with contact hardening simulation
|
||||
PCSS, //!< PCF with soft shadows and contact hardening
|
||||
}
|
||||
|
||||
// copied from filament/backened/DriverEnums.h
|
||||
enum PrimitiveType {
|
||||
// don't change the enums values (made to match GL)
|
||||
@@ -262,6 +269,12 @@ abstract class ThermionViewer {
|
||||
ThermionEntity entity, MorphAnimationData animation,
|
||||
{List<String>? targetMeshNames});
|
||||
|
||||
///
|
||||
/// Clear all current morph animations for [entity].
|
||||
///
|
||||
Future clearMorphAnimationData(
|
||||
ThermionEntity entity);
|
||||
|
||||
///
|
||||
/// Resets all bones in the given entity to their rest pose.
|
||||
/// This should be done before every call to addBoneAnimation.
|
||||
@@ -562,10 +575,25 @@ abstract class ThermionViewer {
|
||||
{bool relative = false});
|
||||
|
||||
///
|
||||
/// Enable/disable postprocessing.
|
||||
/// Enable/disable postprocessing (disabled by default).
|
||||
///
|
||||
Future setPostProcessing(bool enabled);
|
||||
|
||||
///
|
||||
/// Enable/disable shadows (disabled by default).
|
||||
///
|
||||
Future setShadowsEnabled(bool enabled);
|
||||
|
||||
///
|
||||
/// Set shadow type.
|
||||
///
|
||||
Future setShadowType(ShadowType shadowType);
|
||||
|
||||
///
|
||||
/// Set soft shadow options (ShadowType DPCF and PCSS)
|
||||
///
|
||||
Future setSoftShadowOptions(double penumbraScale, double penumbraRatioScale);
|
||||
|
||||
///
|
||||
/// Set antialiasing options.
|
||||
///
|
||||
@@ -707,6 +735,7 @@ abstract class ThermionViewer {
|
||||
/// Register a callback to be invoked when this viewer is disposed.
|
||||
///
|
||||
void onDispose(Future Function() callback);
|
||||
|
||||
}
|
||||
|
||||
abstract class AbstractGizmo {
|
||||
|
||||
@@ -198,6 +198,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
await callback.call();
|
||||
}
|
||||
_onDispose.clear();
|
||||
|
||||
}
|
||||
|
||||
///
|
||||
@@ -598,6 +599,18 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
return getAnimationDuration(entity, index);
|
||||
}
|
||||
|
||||
Future clearMorphAnimationData(ThermionEntity entity) async {
|
||||
var meshEntities = await getChildEntities(entity, true);
|
||||
|
||||
for(final childEntity in meshEntities) {
|
||||
clear_morph_animation(
|
||||
_sceneManager!,
|
||||
childEntity);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
@@ -1063,6 +1076,29 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
set_post_processing_ffi(_viewer!, enabled);
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
@override
|
||||
Future setShadowsEnabled(bool enabled) async {
|
||||
set_shadows_enabled(_viewer!, enabled);
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
Future setShadowType(ShadowType shadowType) async {
|
||||
set_shadow_type(_viewer!, shadowType.index);
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
Future setSoftShadowOptions(
|
||||
double penumbraScale, double penumbraRatioScale) async {
|
||||
set_soft_shadow_options(_viewer!, penumbraScale, penumbraRatioScale);
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
@@ -1564,8 +1600,9 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
// ignore: sdk_version_since
|
||||
|
||||
if (callback != null) {
|
||||
var ptr = NativeCallable<
|
||||
Void Function(Int entityId1, Int entityId2)>.listener(callback);
|
||||
var ptr =
|
||||
NativeCallable<Void Function(Int entityId1, Int entityId2)>.listener(
|
||||
callback);
|
||||
add_collision_component(
|
||||
_sceneManager!, entity, ptr.nativeFunction, affectsTransform);
|
||||
_collisions[entity] = ptr;
|
||||
|
||||
@@ -586,6 +586,11 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future clearMorphAnimationData(ThermionEntity entity) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setMorphAnimationData(
|
||||
ThermionEntity entity, MorphAnimationData animation,
|
||||
@@ -726,4 +731,22 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
// TODO: implement zoomUpdate
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setShadowType(ShadowType shadowType) {
|
||||
// TODO: implement setShadowType
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setShadowsEnabled(bool enabled) {
|
||||
// TODO: implement setShadowsEnabled
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setSoftShadowOptions(double penumbraScale, double penumbraRatioScale) {
|
||||
// TODO: implement setSoftShadowOptions
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,6 +153,9 @@ namespace thermion_filament
|
||||
|
||||
void setAntiAliasing(bool msaaEnabled, bool fxaaEnabled, bool taaEnabled);
|
||||
void setDepthOfField();
|
||||
void setShadowsEnabled(bool enabled);
|
||||
void setShadowType(ShadowType shadowType);
|
||||
void setSoftShadowOptions( float penumbraScale, float penumbraRatioScale);
|
||||
|
||||
EntityId createGeometry(float *vertices, uint32_t numVertices, uint16_t *indices, uint32_t numIndices, filament::RenderableManager::PrimitiveType primitiveType = RenderableManager::PrimitiveType::TRIANGLES, const char *materialPath = nullptr);
|
||||
|
||||
@@ -222,6 +225,7 @@ namespace thermion_filament
|
||||
void loadPngTexture(std::string path, ResourceBuffer data);
|
||||
void loadTextureFromPath(std::string path);
|
||||
void savePng(void *data, size_t size, int frameNumber);
|
||||
void createBackgroundImage();
|
||||
|
||||
time_point_t _recordingStartTime = std::chrono::high_resolution_clock::now();
|
||||
time_point_t _fpsCounterStartTime = std::chrono::high_resolution_clock::now();
|
||||
@@ -229,6 +233,7 @@ namespace thermion_filament
|
||||
bool _recording = false;
|
||||
std::string _recordingOutputDirectory = std::string("/tmp");
|
||||
std::mutex _recordingMutex;
|
||||
std::mutex _imageMutex;
|
||||
double _cumulativeAnimationUpdateTime = 0;
|
||||
int _frameCount = 0;
|
||||
int _skippedFrames = 0;
|
||||
|
||||
@@ -87,6 +87,9 @@ namespace thermion_filament
|
||||
int numFrames,
|
||||
float frameLengthInMs);
|
||||
|
||||
void clearMorphAnimationBuffer(
|
||||
EntityId entityId);
|
||||
|
||||
bool setMorphTargetWeights(EntityId entityId, const float *const weights, int count);
|
||||
|
||||
math::mat4f getLocalTransform(EntityId entityId);
|
||||
|
||||
@@ -136,6 +136,9 @@ extern "C"
|
||||
int numMorphTargets,
|
||||
int numFrames,
|
||||
float frameLengthInMs);
|
||||
EMSCRIPTEN_KEEPALIVE void clear_morph_animation(
|
||||
void *sceneManager,
|
||||
EntityId entity);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void reset_to_rest_pose(
|
||||
void *sceneManager,
|
||||
@@ -216,6 +219,9 @@ extern "C"
|
||||
EMSCRIPTEN_KEEPALIVE int hide_mesh(void *sceneManager, EntityId entity, const char *meshName);
|
||||
EMSCRIPTEN_KEEPALIVE int reveal_mesh(void *sceneManager, EntityId entity, const char *meshName);
|
||||
EMSCRIPTEN_KEEPALIVE void set_post_processing(void *const viewer, bool enabled);
|
||||
EMSCRIPTEN_KEEPALIVE void set_shadows_enabled(void *const viewer, bool enabled);
|
||||
EMSCRIPTEN_KEEPALIVE void set_shadow_type(void *const viewer, int shadowType);
|
||||
EMSCRIPTEN_KEEPALIVE void set_soft_shadow_options(void *const viewer, float penumbraScale, float penumbraRatioScale);
|
||||
EMSCRIPTEN_KEEPALIVE void set_antialiasing(void *const viewer, bool msaa, bool fxaa, bool taa);
|
||||
EMSCRIPTEN_KEEPALIVE void filament_pick(void *const viewer, int x, int y, void (*callback)(EntityId entityId, int x, int y));
|
||||
EMSCRIPTEN_KEEPALIVE const char *get_name_for_entity(void *const sceneManager, const EntityId entityId);
|
||||
|
||||
@@ -214,60 +214,6 @@ namespace thermion_filament
|
||||
|
||||
Log("Created scene maager");
|
||||
|
||||
_dummyImageTexture = Texture::Builder()
|
||||
.width(1)
|
||||
.height(1)
|
||||
.levels(0x01)
|
||||
.format(Texture::InternalFormat::RGB16F)
|
||||
.sampler(Texture::Sampler::SAMPLER_2D)
|
||||
.build(*_engine);
|
||||
try
|
||||
{
|
||||
_imageMaterial =
|
||||
Material::Builder()
|
||||
.package(IMAGE_IMAGE_DATA, IMAGE_IMAGE_SIZE)
|
||||
.build(*_engine);
|
||||
_imageMaterial->setDefaultParameter("showImage", 0);
|
||||
_imageMaterial->setDefaultParameter("backgroundColor", RgbaType::sRGB, float4(1.0f, 1.0f, 1.0f, 0.0f));
|
||||
_imageMaterial->setDefaultParameter("image", _dummyImageTexture, _imageSampler);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Log("Failed to load background image material provider");
|
||||
std::rethrow_exception(std::current_exception());
|
||||
}
|
||||
_imageScale = mat4f{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
|
||||
|
||||
_imageMaterial->setDefaultParameter("transform", _imageScale);
|
||||
|
||||
_imageVb = VertexBuffer::Builder()
|
||||
.vertexCount(3)
|
||||
.bufferCount(1)
|
||||
.attribute(VertexAttribute::POSITION, 0,
|
||||
VertexBuffer::AttributeType::FLOAT4, 0)
|
||||
.build(*_engine);
|
||||
|
||||
_imageVb->setBufferAt(
|
||||
*_engine, 0,
|
||||
{sFullScreenTriangleVertices, sizeof(sFullScreenTriangleVertices)});
|
||||
|
||||
_imageIb = IndexBuffer::Builder()
|
||||
.indexCount(3)
|
||||
.bufferType(IndexBuffer::IndexType::USHORT)
|
||||
.build(*_engine);
|
||||
|
||||
_imageIb->setBuffer(*_engine, {sFullScreenTriangleIndices,
|
||||
sizeof(sFullScreenTriangleIndices)});
|
||||
|
||||
_imageEntity = em.create();
|
||||
RenderableManager::Builder(1)
|
||||
.boundingBox({{}, {1.0f, 1.0f, 1.0f}})
|
||||
.material(0, _imageMaterial->getDefaultInstance())
|
||||
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, _imageVb,
|
||||
_imageIb, 0, 3)
|
||||
.culling(false)
|
||||
.build(*_engine, _imageEntity);
|
||||
_scene->addEntity(_imageEntity);
|
||||
}
|
||||
|
||||
void FilamentViewer::setAntiAliasing(bool msaa, bool fxaa, bool taa)
|
||||
@@ -287,6 +233,24 @@ namespace thermion_filament
|
||||
_view->setPostProcessingEnabled(enabled);
|
||||
}
|
||||
|
||||
void FilamentViewer::setShadowsEnabled(bool enabled)
|
||||
{
|
||||
_view->setShadowingEnabled(enabled);
|
||||
}
|
||||
|
||||
void FilamentViewer::setShadowType(ShadowType shadowType)
|
||||
{
|
||||
_view->setShadowType(shadowType);
|
||||
}
|
||||
|
||||
void FilamentViewer::setSoftShadowOptions(float penumbraScale, float penumbraRatioScale) {
|
||||
SoftShadowOptions opts;
|
||||
opts.penumbraRatioScale = penumbraRatioScale;
|
||||
opts.penumbraScale = penumbraScale;
|
||||
_view->setSoftShadowOptions(opts);
|
||||
}
|
||||
|
||||
|
||||
void FilamentViewer::setBloom(float strength)
|
||||
{
|
||||
#ifndef __EMSCRIPTEN__
|
||||
@@ -541,14 +505,81 @@ namespace thermion_filament
|
||||
|
||||
void FilamentViewer::setBackgroundColor(const float r, const float g, const float b, const float a)
|
||||
{
|
||||
// Log("Setting background color to rgba(%f,%f,%f,%f)", r, g, b, a);
|
||||
std::lock_guard lock(_imageMutex);
|
||||
|
||||
if(_imageEntity.isNull()) {
|
||||
createBackgroundImage();
|
||||
}
|
||||
_imageMaterial->setDefaultParameter("showImage", 0);
|
||||
_imageMaterial->setDefaultParameter("backgroundColor", RgbaType::sRGB, float4(r, g, b, a));
|
||||
_imageMaterial->setDefaultParameter("transform", _imageScale);
|
||||
}
|
||||
|
||||
void FilamentViewer::createBackgroundImage() {
|
||||
|
||||
_dummyImageTexture = Texture::Builder()
|
||||
.width(1)
|
||||
.height(1)
|
||||
.levels(0x01)
|
||||
.format(Texture::InternalFormat::RGB16F)
|
||||
.sampler(Texture::Sampler::SAMPLER_2D)
|
||||
.build(*_engine);
|
||||
try
|
||||
{
|
||||
_imageMaterial =
|
||||
Material::Builder()
|
||||
.package(IMAGE_IMAGE_DATA, IMAGE_IMAGE_SIZE)
|
||||
.build(*_engine);
|
||||
_imageMaterial->setDefaultParameter("showImage", 0);
|
||||
_imageMaterial->setDefaultParameter("backgroundColor", RgbaType::sRGB, float4(1.0f, 1.0f, 1.0f, 0.0f));
|
||||
_imageMaterial->setDefaultParameter("image", _dummyImageTexture, _imageSampler);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Log("Failed to load background image material provider");
|
||||
std::rethrow_exception(std::current_exception());
|
||||
}
|
||||
_imageScale = mat4f{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
|
||||
|
||||
_imageMaterial->setDefaultParameter("transform", _imageScale);
|
||||
|
||||
_imageVb = VertexBuffer::Builder()
|
||||
.vertexCount(3)
|
||||
.bufferCount(1)
|
||||
.attribute(VertexAttribute::POSITION, 0,
|
||||
VertexBuffer::AttributeType::FLOAT4, 0)
|
||||
.build(*_engine);
|
||||
|
||||
_imageVb->setBufferAt(
|
||||
*_engine, 0,
|
||||
{sFullScreenTriangleVertices, sizeof(sFullScreenTriangleVertices)});
|
||||
|
||||
_imageIb = IndexBuffer::Builder()
|
||||
.indexCount(3)
|
||||
.bufferType(IndexBuffer::IndexType::USHORT)
|
||||
.build(*_engine);
|
||||
|
||||
_imageIb->setBuffer(*_engine, {sFullScreenTriangleIndices,
|
||||
sizeof(sFullScreenTriangleIndices)});
|
||||
auto & em = EntityManager::get();
|
||||
_imageEntity = em.create();
|
||||
RenderableManager::Builder(1)
|
||||
.boundingBox({{}, {1.0f, 1.0f, 1.0f}})
|
||||
.material(0, _imageMaterial->getDefaultInstance())
|
||||
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, _imageVb,
|
||||
_imageIb, 0, 3)
|
||||
.culling(false)
|
||||
.build(*_engine, _imageEntity);
|
||||
_scene->addEntity(_imageEntity);
|
||||
}
|
||||
|
||||
void FilamentViewer::clearBackgroundImage()
|
||||
{
|
||||
std::lock_guard lock(_imageMutex);
|
||||
|
||||
if(_imageEntity.isNull()) {
|
||||
createBackgroundImage();
|
||||
}
|
||||
_imageMaterial->setDefaultParameter("image", _dummyImageTexture, _imageSampler);
|
||||
_imageMaterial->setDefaultParameter("showImage", 0);
|
||||
if (_imageTexture)
|
||||
@@ -562,6 +593,12 @@ namespace thermion_filament
|
||||
void FilamentViewer::setBackgroundImage(const char *resourcePath, bool fillHeight)
|
||||
{
|
||||
|
||||
std::lock_guard lock(_imageMutex);
|
||||
|
||||
if(_imageEntity.isNull()) {
|
||||
createBackgroundImage();
|
||||
}
|
||||
|
||||
string resourcePathString(resourcePath);
|
||||
|
||||
Log("Setting background image to %s", resourcePath);
|
||||
@@ -602,6 +639,11 @@ namespace thermion_filament
|
||||
///
|
||||
void FilamentViewer::setBackgroundImagePosition(float x, float y, bool clamp = false)
|
||||
{
|
||||
std::lock_guard lock(_imageMutex);
|
||||
|
||||
if(_imageEntity.isNull()) {
|
||||
createBackgroundImage();
|
||||
}
|
||||
|
||||
// to translate the background image, we apply a transform to the UV coordinates of the quad texture, not the quad itself (see image.mat).
|
||||
// this allows us to set a background colour for the quad when the texture has been translated outside the quad's bounds.
|
||||
@@ -682,11 +724,13 @@ namespace thermion_filament
|
||||
{
|
||||
clearLights();
|
||||
destroySwapChain();
|
||||
_engine->destroy(_imageEntity);
|
||||
_engine->destroy(_imageTexture);
|
||||
_engine->destroy(_imageVb);
|
||||
_engine->destroy(_imageIb);
|
||||
_engine->destroy(_imageMaterial);
|
||||
if(!_imageEntity.isNull()) {
|
||||
_engine->destroy(_imageEntity);
|
||||
_engine->destroy(_imageTexture);
|
||||
_engine->destroy(_imageVb);
|
||||
_engine->destroy(_imageIb);
|
||||
_engine->destroy(_imageMaterial);
|
||||
}
|
||||
delete _sceneManager;
|
||||
_engine->destroyCameraComponent(_mainCamera->getEntity());
|
||||
_mainCamera = nullptr;
|
||||
|
||||
@@ -781,6 +781,27 @@ namespace thermion_filament
|
||||
return true;
|
||||
}
|
||||
|
||||
void SceneManager::clearMorphAnimationBuffer(
|
||||
EntityId entityId)
|
||||
{
|
||||
std::lock_guard lock(_mutex);
|
||||
|
||||
auto entity = Entity::import(entityId);
|
||||
|
||||
if (entity.isNull())
|
||||
{
|
||||
Log("ERROR: invalid entity %d.", entityId);
|
||||
return;
|
||||
}
|
||||
|
||||
auto animationComponentInstance = _animationComponentManager->getInstance(entity);
|
||||
auto &animationComponent = _animationComponentManager->elementAt<0>(animationComponentInstance);
|
||||
auto &morphAnimations = animationComponent.morphAnimations;
|
||||
|
||||
morphAnimations.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
bool SceneManager::setMaterialColor(EntityId entityId, const char *meshName, int materialIndex, const float r, const float g, const float b, const float a)
|
||||
{
|
||||
|
||||
|
||||
@@ -405,7 +405,7 @@ extern "C"
|
||||
return ((SceneManager *)sceneManager)->setMorphTargetWeights(asset, weights, numWeights);
|
||||
}
|
||||
|
||||
bool set_morph_animation(
|
||||
EMSCRIPTEN_KEEPALIVE bool set_morph_animation(
|
||||
void *sceneManager,
|
||||
EntityId asset,
|
||||
const float *const morphData,
|
||||
@@ -418,6 +418,10 @@ extern "C"
|
||||
return result;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void clear_morph_animation(void* sceneManager, EntityId asset) {
|
||||
((SceneManager *)sceneManager)->clearMorphAnimationBuffer(asset);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void reset_to_rest_pose(void *sceneManager, EntityId entityId)
|
||||
{
|
||||
((SceneManager *)sceneManager)->resetBones(entityId);
|
||||
@@ -443,6 +447,21 @@ extern "C"
|
||||
((FilamentViewer *)viewer)->setPostProcessing(enabled);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_shadows_enabled(void *const viewer, bool enabled)
|
||||
{
|
||||
((FilamentViewer *)viewer)->setShadowsEnabled(enabled);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_shadow_type(void *const viewer, int shadowType)
|
||||
{
|
||||
((FilamentViewer *)viewer)->setShadowType((ShadowType)shadowType);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_soft_shadow_options(void *const viewer, float penumbraScale, float penumbraRatioScale)
|
||||
{
|
||||
((FilamentViewer *)viewer)->setSoftShadowOptions(penumbraScale, penumbraRatioScale);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_antialiasing(void *const viewer, bool msaa, bool fxaa, bool taa)
|
||||
{
|
||||
((FilamentViewer *)viewer)->setAntiAliasing(msaa, fxaa, taa);
|
||||
|
||||
@@ -19,7 +19,7 @@ set(EMCC_CFLAGS ${EMCC_CFLAGS} -sEXPORT_NAME=${MODULE_NAME})
|
||||
set(EMCC_CFLAGS ${EMCC_CFLAGS} -sINITIAL_MEMORY=512mb)
|
||||
set(EMCC_CFLAGS ${EMCC_CFLAGS} -sMODULARIZE)
|
||||
set(EMCC_CFLAGS ${EMCC_CFLAGS} -sERROR_ON_UNDEFINED_SYMBOLS=0 )
|
||||
set(EMCC_CFLAGS ${EMCC_CFLAGS} -sEXPORTED_RUNTIME_METHODS=wasmExports,wasmTable,addFunction,ccall,cwrap,allocate,intArrayFromString,intArrayToString,getValue,setValue,UTF8ToString,stringToUTF8,writeArrayToMemory,_free)
|
||||
set(EMCC_CFLAGS ${EMCC_CFLAGS} -sEXPORTED_RUNTIME_METHODS=wasmExports,wasmTable,addFunction,ccall,cwrap,allocate,intArrayFromString,intArrayToString,getValue,setValue,UTF8ToString,stringToUTF8,writeArrayToMemory)
|
||||
set(EMCC_CFLAGS ${EMCC_CFLAGS} -sEXPORTED_FUNCTIONS=_malloc,stackAlloc,_free)
|
||||
set(EMCC_CFLAGS ${EMCC_CFLAGS} -sFULL_ES3)
|
||||
set(EMCC_CFLAGS ${EMCC_CFLAGS} -sASSERTIONS)
|
||||
@@ -35,10 +35,13 @@ set(EMCC_CFLAGS ${EMCC_CFLAGS} -sFETCH=1)
|
||||
# set(EMCC_CFLAGS ${EMCC_CFLAGS} -sUSE_PTHREADS)
|
||||
# set(EMCC_CFLAGS ${EMCC_CFLAGS} -sPROXY_TO_WORKER=1)
|
||||
set(EMCC_CFLAGS ${EMCC_CFLAGS} -sSHARED_MEMORY=0)
|
||||
set(EMCC_CFLAGS ${EMCC_CFLAGS} -lidbfs.js)
|
||||
set(EMCC_CFLAGS ${EMCC_CFLAGS} -sFORCE_FILESYSTEM=1)
|
||||
|
||||
# set(EMCC_CFLAGS ${EMCC_CFLAGS} -pie)
|
||||
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-field-initializers -Wno-deprecated-literal-operator -stdlib=libc++ -std=c++17 -fPIC -O3 --no-entry")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-field-initializers -Wno-deprecated-literal-operator -stdlib=libc++ -std=c++17 -fPIC -O3 --no-entry ")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -pie")
|
||||
|
||||
add_link_options(${EMCC_CFLAGS})
|
||||
|
||||
@@ -15,37 +15,6 @@
|
||||
#include <emscripten/val.h>
|
||||
#include <emscripten/fetch.h>
|
||||
|
||||
class PendingCall
|
||||
{
|
||||
public:
|
||||
PendingCall()
|
||||
{
|
||||
}
|
||||
~PendingCall() {}
|
||||
|
||||
void Wait()
|
||||
{
|
||||
std::future<int32_t> accumulate_future = prom.get_future();
|
||||
std::cout << "Loaded asset from Flutter of length " << accumulate_future.get() << std::endl;
|
||||
}
|
||||
|
||||
void HandleResponse(void* data, int32_t length)
|
||||
{
|
||||
this->data = data;
|
||||
this->length = length;
|
||||
prom.set_value(length);
|
||||
}
|
||||
void* data = nullptr;
|
||||
int32_t length = 0;
|
||||
|
||||
private:
|
||||
std::mutex mutex_;
|
||||
std::condition_variable cv_;
|
||||
bool notified_ = false;
|
||||
std::promise<int32_t> prom;
|
||||
|
||||
};
|
||||
|
||||
using emscripten::val;
|
||||
|
||||
extern "C"
|
||||
@@ -60,61 +29,26 @@ extern "C"
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void thermion_filament_web_load_resource_callback(void* data, int32_t length, void* context) {
|
||||
((PendingCall*)context)->HandleResponse(data, length);
|
||||
}
|
||||
std::string _assetPathPrefix;
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void thermion_filament_web_set(char* ptr, int32_t offset, int32_t val) {
|
||||
memset(ptr+offset, val, 1);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void thermion_filament_web_set_float(float* ptr, int32_t offset, float val) {
|
||||
ptr[offset] = val;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE float thermion_filament_web_get_float(float* ptr, int32_t offset) {
|
||||
return ptr[offset];
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE double thermion_filament_web_get_double(double* ptr, int32_t offset) {
|
||||
return ptr[offset];
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void thermion_filament_web_set_double(double* ptr, int32_t offset, double value) {
|
||||
ptr[offset] = value;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int32_t thermion_filament_web_get_int32(int32_t* ptr, int32_t offset) {
|
||||
return ptr[offset];
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void thermion_filament_web_set_int32(int32_t* ptr, int32_t offset, int32_t value) {
|
||||
ptr[offset] = value;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void thermion_filament_web_set_pointer(void** ptr, int32_t offset, void* val) {
|
||||
ptr[offset] = val;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void* thermion_filament_web_get_pointer(void** ptr, int32_t offset) {
|
||||
return ptr[offset];
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE char thermion_filament_web_get(char* ptr, int32_t offset) {
|
||||
return ptr[offset];
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void* thermion_filament_web_allocate(int32_t size) {
|
||||
void* allocated = (void*)calloc(size, 1);
|
||||
return allocated;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE long thermion_filament_web_get_address(void** out) {
|
||||
return (long)*out;
|
||||
EMSCRIPTEN_KEEPALIVE void thermion_dart_web_set_asset_path_prefix(const char* prefix) {
|
||||
_assetPathPrefix = std::string(prefix);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EMSCRIPTEN_WEBGL_CONTEXT_HANDLE thermion_dart_web_create_gl_context() {
|
||||
|
||||
EM_ASM(
|
||||
FS.mkdir('/indexed');
|
||||
FS.mount(IDBFS, {}, '/indexed');
|
||||
FS.syncfs(true, function (err) {
|
||||
if (err) {
|
||||
console.error('Error mounting IDBFS:', err);
|
||||
} else {
|
||||
console.log('IDBFS mounted successfully');
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
std::cout << "Creating WebGL context." << std::endl;
|
||||
|
||||
EmscriptenWebGLContextAttributes attr;
|
||||
@@ -181,7 +115,7 @@ extern "C"
|
||||
// const char* headers[] = {"Accept-Encoding", "gzip, deflate", NULL};
|
||||
// attr.requestHeaders = headers;
|
||||
|
||||
auto pathString = std::string(path);
|
||||
// auto pathString = std::string(path);
|
||||
// if(pathString.rfind("/",0) != 0) {
|
||||
// pathString = std::string("/") + pathString;
|
||||
// }
|
||||
@@ -197,18 +131,76 @@ extern "C"
|
||||
// memcpy(data, request->data, request->numBytes);
|
||||
// emscripten_fetch_close(request);
|
||||
// return ResourceBuffer { data, (int32_t) request->numBytes, _lastResourceId } ;
|
||||
auto pathString = _assetPathPrefix + std::string(path);
|
||||
void* data = nullptr;
|
||||
int32_t numBytes = 0;
|
||||
|
||||
void** pBuffer = (void**)malloc(sizeof(void*));
|
||||
int* pNum = (int*) malloc(sizeof(int*));
|
||||
int* pError = (int*)malloc(sizeof(int*));
|
||||
emscripten_wget_data(pathString.c_str(), pBuffer, pNum, pError);
|
||||
data = *pBuffer;
|
||||
numBytes = *pNum;
|
||||
free(pBuffer);
|
||||
free(pNum);
|
||||
free(pError);
|
||||
|
||||
|
||||
// Check if the file exists in IndexedDB first
|
||||
bool fileExists = EM_ASM_INT({
|
||||
var filename = UTF8ToString($0);
|
||||
try {
|
||||
var stat = FS.stat('/indexed/' + filename);
|
||||
return stat.size > 0;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}, pathString.c_str());
|
||||
|
||||
if (fileExists) {
|
||||
// File exists in IndexedDB, read it
|
||||
EM_ASM({
|
||||
var filename = UTF8ToString($0);
|
||||
var content = FS.readFile('/indexed/' + filename);
|
||||
var numBytes = content.length;
|
||||
var ptr = _malloc(numBytes);
|
||||
HEAPU8.set(content, ptr);
|
||||
setValue($1, ptr, 'i32');
|
||||
setValue($2, numBytes, 'i32');
|
||||
}, pathString.c_str(), &data, &numBytes);
|
||||
} else {
|
||||
void** pBuffer = (void**)malloc(sizeof(void*));
|
||||
int* pNum = (int*) malloc(sizeof(int*));
|
||||
int* pError = (int*)malloc(sizeof(int*));
|
||||
emscripten_wget_data(pathString.c_str(), pBuffer, pNum, pError);
|
||||
data = *pBuffer;
|
||||
numBytes = *pNum;
|
||||
|
||||
// Save the file to IndexedDB filesystem
|
||||
EM_ASM({
|
||||
var filename = UTF8ToString($0);
|
||||
var data = new Uint8Array(HEAPU8.subarray($1, $1 + $2));
|
||||
|
||||
// Ensure the '/indexed' directory exists
|
||||
if (!FS.analyzePath('/indexed').exists) {
|
||||
FS.mkdir('/indexed');
|
||||
}
|
||||
|
||||
// Create all parent directories
|
||||
var parts = filename.split('/');
|
||||
var currentPath = '/indexed';
|
||||
for (var i = 0; i < parts.length - 1; i++) {
|
||||
currentPath += '/' + parts[i];
|
||||
if (!FS.analyzePath(currentPath).exists) {
|
||||
FS.mkdir(currentPath);
|
||||
}
|
||||
}
|
||||
// Write the file
|
||||
FS.writeFile('/indexed/' + filename, data);
|
||||
|
||||
FS.syncfs(false, function (err) {
|
||||
if (err) {
|
||||
console.error('Failed to save file to IndexedDB:', err);
|
||||
} else {
|
||||
console.log('File saved to IndexedDB successfully');
|
||||
}
|
||||
});
|
||||
}, pathString.c_str(), data, numBytes);
|
||||
|
||||
free(pBuffer);
|
||||
free(pNum);
|
||||
free(pError);
|
||||
}
|
||||
return ResourceBuffer { data, numBytes, _lastResourceId } ;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: thermion_dart
|
||||
description: 3D rendering toolkit for Dart.
|
||||
version: 0.1.1+3
|
||||
version: 0.1.3
|
||||
homepage: https://thermion.dev
|
||||
repository: https://github.com/nmfisher/thermion
|
||||
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
## 0.1.1+13
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.1.1+12
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.1.1+11
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.1.1+10
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.1.1+9
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.1.1+8
|
||||
|
||||
- **DOCS**: update homepage links and minor documentation updates.
|
||||
|
||||
96
thermion_flutter/thermion_flutter/example/README.md
Normal file
96
thermion_flutter/thermion_flutter/example/README.md
Normal file
@@ -0,0 +1,96 @@
|
||||
For a more thorough example with both Flutter and pure Dart, see the [example repository](https://github.com/nmfisher/thermion_examples).
|
||||
|
||||
[flutter/quickstart/lib/main.dart](https://github.com/nmfisher/thermion_examples/blob/master/flutter/quickstart/lib/main.dart)
|
||||
|
||||
```dart
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:thermion_flutter/thermion_flutter.dart';
|
||||
|
||||
import 'package:vector_math/vector_math_64.dart' as v;
|
||||
import 'dart:math';
|
||||
|
||||
void main() {
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'Flutter Demo',
|
||||
theme: ThemeData(
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
||||
useMaterial3: true,
|
||||
),
|
||||
home: const MyHomePage(title: 'Flutter Demo Home Page'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyHomePage extends StatefulWidget {
|
||||
const MyHomePage({super.key, required this.title});
|
||||
final String title;
|
||||
|
||||
@override
|
||||
State<MyHomePage> createState() => _MyHomePageState();
|
||||
}
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage> {
|
||||
bool _loaded = false;
|
||||
ThermionViewer? _thermionViewer;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
Future _load() async {
|
||||
var viewer = await ThermionFlutterPlugin.createViewer();
|
||||
_thermionViewer = viewer;
|
||||
_thermionViewer!.loadSkybox("assets/default_env_skybox.ktx");
|
||||
_thermionViewer!.loadGlb("assets/cube.glb");
|
||||
|
||||
_thermionViewer!.setCameraPosition(0, 1, 10);
|
||||
_thermionViewer!.setCameraRotation(
|
||||
v.Quaternion.axisAngle(v.Vector3(1, 0, 0), -30 / 180 * pi) *
|
||||
v.Quaternion.axisAngle(v.Vector3(0, 1, 0), 15 / 180 * pi));
|
||||
_thermionViewer!.addLight(LightType.SUN, 7500, 50000, 0, 0, 0, 1, -1, -1);
|
||||
_thermionViewer!.setRendering(true);
|
||||
_loaded = true;
|
||||
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
Future _unload() async {
|
||||
var viewer = _thermionViewer!;
|
||||
_thermionViewer = null;
|
||||
setState(() {});
|
||||
await viewer.dispose();
|
||||
_loaded = false;
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
Widget _loadButton() {
|
||||
return Center(
|
||||
child: ElevatedButton(child: const Text("Load"), onPressed: _load));
|
||||
}
|
||||
|
||||
Widget _unloadButton() {
|
||||
return Center(
|
||||
child: ElevatedButton(child: const Text("Unload"), onPressed: _unload));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(children: [
|
||||
if (_thermionViewer != null)
|
||||
Positioned.fill(child: ThermionWidget(viewer: _thermionViewer!)),
|
||||
if (!_loaded) _loadButton(),
|
||||
if (_loaded) _unloadButton(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: thermion_flutter
|
||||
description: Flutter plugin for 3D rendering with the Thermion toolkit.
|
||||
version: 0.1.1+8
|
||||
version: 0.1.1+13
|
||||
homepage: https://thermion.dev
|
||||
repository: https://github.com/nmfisher/thermion
|
||||
|
||||
@@ -17,10 +17,10 @@ dependencies:
|
||||
plugin_platform_interface: ^2.0.0
|
||||
ffi: ^2.1.2
|
||||
animation_tools_dart: ^0.0.4
|
||||
thermion_dart: ^0.1.1+3
|
||||
thermion_flutter_platform_interface: ^0.1.0+7
|
||||
thermion_flutter_ffi: ^0.1.0+7
|
||||
thermion_flutter_web: ^0.0.1+7
|
||||
thermion_dart: ^0.1.3
|
||||
thermion_flutter_platform_interface: ^0.1.0+11
|
||||
thermion_flutter_ffi: ^0.1.0+12
|
||||
thermion_flutter_web: ^0.0.3
|
||||
logging: ^1.2.0
|
||||
|
||||
dev_dependencies:
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
## 0.1.0+12
|
||||
|
||||
- **FIX**: add logging dependency.
|
||||
- **FIX**: web/JS bool checks need to compare to int.
|
||||
- **FIX**: add logging dependency.
|
||||
- **FIX**: web/JS bool checks need to compare to int.
|
||||
|
||||
## 0.1.0+11
|
||||
|
||||
- **FIX**: add logging dependency.
|
||||
|
||||
## 0.1.0+10
|
||||
|
||||
- **FIX**: web/JS bool checks need to compare to int.
|
||||
|
||||
## 0.1.0+9
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.1.0+8
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.1.0+7
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:thermion_dart/thermion_dart/thermion_viewer_ffi.dart';
|
||||
import 'package:thermion_flutter_platform_interface/thermion_flutter_platform_interface.dart';
|
||||
import 'package:thermion_flutter_platform_interface/thermion_flutter_texture.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
///
|
||||
/// An implementation of [ThermionFlutterPlatform] that uses a Flutter platform
|
||||
@@ -13,6 +14,7 @@ import 'package:thermion_flutter_platform_interface/thermion_flutter_texture.dar
|
||||
///
|
||||
class ThermionFlutterFFI extends ThermionFlutterPlatform {
|
||||
final _channel = const MethodChannel("dev.thermion.flutter/event");
|
||||
final _logger = Logger("ThermionFlutterFFI");
|
||||
|
||||
ThermionViewerFFI? _viewer;
|
||||
|
||||
@@ -133,7 +135,7 @@ class ThermionFlutterFFI extends ThermionFlutterPlatform {
|
||||
final hardwareTextureId = result[1] as int?;
|
||||
final surfaceAddress = result[2] as int?;
|
||||
|
||||
print(
|
||||
_logger.info(
|
||||
"Created texture with flutter texture id ${flutterTextureId}, hardwareTextureId $hardwareTextureId and surfaceAddress $surfaceAddress");
|
||||
|
||||
_viewer?.viewportDimensions = (width.toDouble(), height.toDouble());
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: thermion_flutter_ffi
|
||||
description: An FFI interface for the thermion_flutter plugin (all platforms except web).
|
||||
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
|
||||
version: 0.1.0+7
|
||||
version: 0.1.0+12
|
||||
|
||||
environment:
|
||||
sdk: ">=3.3.0 <4.0.0"
|
||||
@@ -22,8 +22,9 @@ dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
plugin_platform_interface: ^2.1.0
|
||||
thermion_flutter_platform_interface: ^0.1.0+7
|
||||
thermion_dart: ^0.1.1+3
|
||||
thermion_flutter_platform_interface: ^0.1.0+11
|
||||
thermion_dart: ^0.1.3
|
||||
logging: ^1.2.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
## 0.1.0+11
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.1.0+10
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.1.0+9
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.1.0+8
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.1.0+7
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: thermion_flutter_platform_interface
|
||||
description: A common platform interface for the thermion_flutter plugin.
|
||||
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
|
||||
version: 0.1.0+7
|
||||
version: 0.1.0+11
|
||||
|
||||
environment:
|
||||
sdk: ">=3.3.0 <4.0.0"
|
||||
@@ -11,7 +11,7 @@ dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
plugin_platform_interface: ^2.1.0
|
||||
thermion_dart: ^0.1.1+3
|
||||
thermion_dart: ^0.1.3
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
## 0.0.3
|
||||
|
||||
- **FEAT**: allow passing assetPathPrefix to ThermionViewerWasm to account for Flutter build asset paths.
|
||||
- **FEAT**: allow passing assetPathPrefix to ThermionViewerWasm to account for Flutter build asset paths.
|
||||
|
||||
## 0.0.2
|
||||
|
||||
- **FEAT**: allow passing assetPathPrefix to ThermionViewerWasm to account for Flutter build asset paths.
|
||||
|
||||
## 0.0.1+9
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.0.1+8
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.0.1+7
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
@@ -35,7 +35,7 @@ class ThermionFlutterWebPlugin extends ThermionFlutterPlatform {
|
||||
var width = window.innerWidth;
|
||||
var height = window.innerHeight;
|
||||
|
||||
var viewer = ThermionViewerWasm();
|
||||
var viewer = ThermionViewerWasm(assetPathPrefix: "/assets/");
|
||||
await viewer.initialize(width, height, uberArchivePath: uberArchivePath);
|
||||
return viewer;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: thermion_flutter_web
|
||||
description: A web platform interface for the thermion_flutter plugin.
|
||||
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
|
||||
version: 0.0.1+7
|
||||
version: 0.0.3
|
||||
|
||||
environment:
|
||||
sdk: ">=3.3.0 <4.0.0"
|
||||
@@ -20,8 +20,8 @@ dependencies:
|
||||
sdk: flutter
|
||||
plugin_platform_interface: ^2.1.0
|
||||
web: ^0.5.1
|
||||
thermion_dart: ^0.1.1+3
|
||||
thermion_flutter_platform_interface: ^0.1.0+7
|
||||
thermion_dart: ^0.1.3
|
||||
thermion_flutter_platform_interface: ^0.1.0+11
|
||||
flutter_web_plugins:
|
||||
sdk: flutter
|
||||
|
||||
|
||||
Reference in New Issue
Block a user