Compare commits
18 Commits
thermion_f
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d16474784d | ||
|
|
1c07d576d3 | ||
|
|
961b2ae1ee | ||
|
|
a7ac118899 | ||
|
|
d92ad4ef12 | ||
|
|
437e91e7bd | ||
|
|
e169bf6c41 | ||
|
|
23b060c329 | ||
|
|
5fd0a10630 | ||
|
|
ddfb649733 | ||
|
|
ecffc5b62a | ||
|
|
429b8eb93b | ||
|
|
413faec849 | ||
|
|
433b6373a9 | ||
|
|
ad2c5afb7f | ||
|
|
a561c847a7 | ||
|
|
ef7ba24ecc | ||
|
|
ee176d2684 |
24
.github/workflows/dart.yml
vendored
@@ -117,8 +117,28 @@ jobs:
|
||||
# D:\a\thermion\thermion\thermion_dart\.dart_tool\thermion_dart\log\build.log
|
||||
/Users/runner/work/thermion/thermion/thermion_dart/.dart_tool/thermion_dart/log/build.log
|
||||
retention-days: 5
|
||||
|
||||
|
||||
flutter_examples_windows:
|
||||
name: flutter_examples_windows
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: examples/flutter
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: master
|
||||
- run: cd quickstart && flutter pub get && flutter build windows
|
||||
- run: cd picking && flutter pub get && flutter build windows
|
||||
- name: Upload logs
|
||||
if: failure() || steps.build.outcome == 'failure'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-logs
|
||||
path: |
|
||||
D:\a\thermion\thermion\thermion_dart\.dart_tool\thermion_dart\log\build.log
|
||||
retention-days: 5
|
||||
# thermion_dart:
|
||||
# name: thermion_dart
|
||||
# runs-on: macos-latest
|
||||
|
||||
83
CHANGELOG.md
@@ -3,6 +3,89 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## 2025-07-24
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`thermion_dart` - `v0.3.3`](#thermion_dart---v033)
|
||||
- [`thermion_flutter_method_channel` - `v0.3.3`](#thermion_flutter_method_channel---v033)
|
||||
- [`thermion_flutter_platform_interface` - `v0.3.3`](#thermion_flutter_platform_interface---v033)
|
||||
- [`thermion_flutter_web` - `v0.3.3`](#thermion_flutter_web---v033)
|
||||
- [`thermion_flutter` - `v0.3.3`](#thermion_flutter---v033)
|
||||
|
||||
---
|
||||
|
||||
#### `thermion_dart` - `v0.3.3`
|
||||
|
||||
- Bump "thermion_dart" to `0.3.3`.
|
||||
|
||||
#### `thermion_flutter_method_channel` - `v0.3.3`
|
||||
|
||||
- Bump "thermion_flutter_method_channel" to `0.3.3`.
|
||||
|
||||
#### `thermion_flutter_platform_interface` - `v0.3.3`
|
||||
|
||||
- Bump "thermion_flutter_platform_interface" to `0.3.3`.
|
||||
|
||||
#### `thermion_flutter_web` - `v0.3.3`
|
||||
|
||||
- Bump "thermion_flutter_web" to `0.3.3`.
|
||||
|
||||
#### `thermion_flutter` - `v0.3.3`
|
||||
|
||||
- Bump "thermion_flutter" to `0.3.3`.
|
||||
|
||||
|
||||
## 2025-07-17
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`thermion_dart` - `v0.3.3-pre`](#thermion_dart---v033-pre)
|
||||
- [`thermion_flutter` - `v0.3.3-pre`](#thermion_flutter---v033-pre)
|
||||
- [`thermion_flutter_method_channel` - `v0.3.3-pre`](#thermion_flutter_method_channel---v033-pre)
|
||||
- [`thermion_flutter_platform_interface` - `v0.3.3-pre`](#thermion_flutter_platform_interface---v033-pre)
|
||||
- [`thermion_flutter_web` - `v0.3.3-pre`](#thermion_flutter_web---v033-pre)
|
||||
|
||||
---
|
||||
|
||||
#### `thermion_dart` - `v0.3.3-pre`
|
||||
|
||||
- **FIX**: fix Windows build.dart.
|
||||
- **FIX**: add nan/negative checks inside setLensProjection.
|
||||
|
||||
#### `thermion_flutter` - `v0.3.3-pre`
|
||||
|
||||
- **DOCS**: replace thermion_flutter README with symlink to thermion_dart README.
|
||||
|
||||
#### `thermion_flutter_method_channel` - `v0.3.3-pre`
|
||||
|
||||
- **FEAT**: allow passing renderTargetColorTextureFormat via ThermionFlutterOptions.
|
||||
|
||||
#### `thermion_flutter_platform_interface` - `v0.3.3-pre`
|
||||
|
||||
- **FEAT**: allow passing renderTargetColorTextureFormat via ThermionFlutterOptions.
|
||||
|
||||
#### `thermion_flutter_web` - `v0.3.3-pre`
|
||||
|
||||
- Bump "thermion_flutter_web" to `0.3.3-pre`.
|
||||
|
||||
|
||||
## 2025-07-08
|
||||
|
||||
### Changes
|
||||
|
||||
@@ -79,4 +79,4 @@ Thank you to the following people:
|
||||
- @LukasPoque for CI/refactoring work
|
||||
- @alexmercerind for his work on integrating ANGLE textures on Flutter Windows
|
||||
- @BrutalCoding for documentation fixes
|
||||
|
||||
- @chenriji for testing and bug fixes
|
||||
|
||||
@@ -14,6 +14,8 @@ This is a simplified, Flutter-only wrapper around the underlying 3D rendering AP
|
||||
|
||||
Follow the steps listed in [Getting Started](./getting_started) to configure your Flutter installation and project.
|
||||
|
||||
If you're running Windows, delete the `examples/flutter/quickstart/assets` symlink and copy the `assets` folder from `examples/assets` to `examples/flutter/quickstart/assets`.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```dart
|
||||
|
||||
BIN
examples/assets/bin/mac/upscayl-bin
Executable file
BIN
examples/assets/bin/windows/upscayl-bin.exe
Normal file
BIN
examples/assets/bin/windows/vcomp140.dll
Normal file
BIN
examples/assets/bin/windows/vcomp140d.dll
Normal file
BIN
examples/assets/cup/model.bin
Normal file
|
After Width: | Height: | Size: 960 KiB |
1
examples/assets/cup/model.gltf
Normal file
@@ -0,0 +1 @@
|
||||
{"asset":{"version":"2.0","generator":"babylon.js glTF exporter for 3dsmax 2021 v20210607.3"},"scene":0,"scenes":[{"nodes":[0]}],"nodes":[{"mesh":0,"translation":[0.0,-1.14751673,-5.015955E-08],"name":"Cylinder001"}],"meshes":[{"primitives":[{"attributes":{"POSITION":1,"NORMAL":2,"TEXCOORD_0":3},"indices":0,"material":0},{"attributes":{"POSITION":5,"NORMAL":6,"TEXCOORD_0":7},"indices":4,"material":1},{"attributes":{"POSITION":9,"NORMAL":10,"TEXCOORD_0":11},"indices":8,"material":2},{"attributes":{"POSITION":13,"NORMAL":14,"TEXCOORD_0":15},"indices":12,"material":3},{"attributes":{"POSITION":17,"NORMAL":18,"TEXCOORD_0":19},"indices":16,"material":4}],"name":"Cylinder001"}],"accessors":[{"bufferView":0,"componentType":5123,"count":858,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"componentType":5126,"count":858,"max":[0.9673312,-0.0665806457,0.9673312],"min":[-0.9673312,-0.09678768,-0.9673312],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":10296,"componentType":5126,"count":858,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"componentType":5126,"count":858,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":1716,"componentType":5123,"count":14592,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":20592,"componentType":5126,"count":14592,"max":[1.01214123,2.33892131,1.02725148],"min":[-1.01214123,-0.09678768,-1.01214123],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":195696,"componentType":5126,"count":14592,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":6864,"componentType":5126,"count":14592,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":30900,"componentType":5123,"count":1620,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":370800,"componentType":5126,"count":1620,"max":[1.006612,2.3633275,1.006612],"min":[-1.006612,2.338921,-1.006612],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":390240,"componentType":5126,"count":1620,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":123600,"componentType":5126,"count":1620,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":34140,"componentType":5123,"count":318,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":409680,"componentType":5126,"count":318,"max":[0.9454922,2.3548696,0.9454922],"min":[-0.9454921,0.0617354736,-0.945492268],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":413496,"componentType":5126,"count":318,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":136560,"componentType":5126,"count":318,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":34776,"componentType":5123,"count":11520,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":417312,"componentType":5126,"count":11520,"max":[0.196413681,2.12139344,1.90955186],"min":[-0.196414649,0.165008187,1.00927675],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":555552,"componentType":5126,"count":11520,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":139104,"componentType":5126,"count":11520,"type":"VEC2","name":"accessorUVs"}],"bufferViews":[{"buffer":0,"byteLength":57816,"name":"bufferViewScalar"},{"buffer":0,"byteOffset":57816,"byteLength":693792,"byteStride":12,"name":"bufferViewFloatVec3"},{"buffer":0,"byteOffset":751608,"byteLength":231264,"byteStride":8,"name":"bufferViewFloatVec2"}],"buffers":[{"uri":"model.bin","byteLength":982872}],"materials":[{"pbrMetallicRoughness":{"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"01 - Default"},{"pbrMetallicRoughness":{"baseColorTexture":{"index":0},"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"02 - Default"},{"pbrMetallicRoughness":{"baseColorFactor":[0.0,1.0,0.117647067,1.0],"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"03 - Default"},{"pbrMetallicRoughness":{"baseColorFactor":[0.2784314,0.0,0.9921569,1.0],"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"04 - Default"},{"pbrMetallicRoughness":{"baseColorFactor":[0.9725491,0.776470661,0.0,1.0],"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"05 - Default"}],"textures":[{"sampler":0,"source":0,"name":"texture.jpg"}],"images":[{"uri":"./texture.jpg"}],"samplers":[{"magFilter":9729,"minFilter":9987}]}
|
||||
BIN
examples/assets/cup/new.jpg
Normal file
|
After Width: | Height: | Size: 720 KiB |
BIN
examples/assets/cup/texture.jpg
Normal file
|
After Width: | Height: | Size: 8.2 MiB |
BIN
examples/assets/cup/texture_tmp.jpg
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
examples/assets/image/texture.jpg
Normal file
|
After Width: | Height: | Size: 8.2 MiB |
BIN
examples/assets/models/digital-art-4x.bin
Normal file
270
examples/assets/models/digital-art-4x.param
Normal file
@@ -0,0 +1,270 @@
|
||||
7767517
|
||||
268 473
|
||||
Input input.1 0 1 data
|
||||
Convolution Conv_0 1 1 data 193 0=64 1=3 4=1 5=1 6=1728
|
||||
Split splitncnn_0 1 8 193 193_splitncnn_0 193_splitncnn_1 193_splitncnn_2 193_splitncnn_3 193_splitncnn_4 193_splitncnn_5 193_splitncnn_6 193_splitncnn_7
|
||||
Convolution Conv_1 1 1 193_splitncnn_7 195 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_1 1 4 195 195_splitncnn_0 195_splitncnn_1 195_splitncnn_2 195_splitncnn_3
|
||||
Concat Concat_3 2 1 193_splitncnn_6 195_splitncnn_3 196
|
||||
Convolution Conv_4 1 1 196 198 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_2 1 3 198 198_splitncnn_0 198_splitncnn_1 198_splitncnn_2
|
||||
Concat Concat_6 3 1 193_splitncnn_5 195_splitncnn_2 198_splitncnn_2 199
|
||||
Convolution Conv_7 1 1 199 201 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_3 1 2 201 201_splitncnn_0 201_splitncnn_1
|
||||
Concat Concat_9 4 1 193_splitncnn_4 195_splitncnn_1 198_splitncnn_1 201_splitncnn_1 202
|
||||
Convolution Conv_10 1 1 202 204 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_12 5 1 193_splitncnn_3 195_splitncnn_0 198_splitncnn_0 201_splitncnn_0 204 205
|
||||
Convolution Conv_13 1 1 205 206 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_16 2 1 206 193_splitncnn_2 209 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_4 1 6 209 209_splitncnn_0 209_splitncnn_1 209_splitncnn_2 209_splitncnn_3 209_splitncnn_4 209_splitncnn_5
|
||||
Convolution Conv_17 1 1 209_splitncnn_5 211 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_5 1 4 211 211_splitncnn_0 211_splitncnn_1 211_splitncnn_2 211_splitncnn_3
|
||||
Concat Concat_19 2 1 209_splitncnn_4 211_splitncnn_3 212
|
||||
Convolution Conv_20 1 1 212 214 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_6 1 3 214 214_splitncnn_0 214_splitncnn_1 214_splitncnn_2
|
||||
Concat Concat_22 3 1 209_splitncnn_3 211_splitncnn_2 214_splitncnn_2 215
|
||||
Convolution Conv_23 1 1 215 217 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_7 1 2 217 217_splitncnn_0 217_splitncnn_1
|
||||
Concat Concat_25 4 1 209_splitncnn_2 211_splitncnn_1 214_splitncnn_1 217_splitncnn_1 218
|
||||
Convolution Conv_26 1 1 218 220 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_28 5 1 209_splitncnn_1 211_splitncnn_0 214_splitncnn_0 217_splitncnn_0 220 221
|
||||
Convolution Conv_29 1 1 221 222 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_32 2 1 222 209_splitncnn_0 225 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_8 1 6 225 225_splitncnn_0 225_splitncnn_1 225_splitncnn_2 225_splitncnn_3 225_splitncnn_4 225_splitncnn_5
|
||||
Convolution Conv_33 1 1 225_splitncnn_5 227 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_9 1 4 227 227_splitncnn_0 227_splitncnn_1 227_splitncnn_2 227_splitncnn_3
|
||||
Concat Concat_35 2 1 225_splitncnn_4 227_splitncnn_3 228
|
||||
Convolution Conv_36 1 1 228 230 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_10 1 3 230 230_splitncnn_0 230_splitncnn_1 230_splitncnn_2
|
||||
Concat Concat_38 3 1 225_splitncnn_3 227_splitncnn_2 230_splitncnn_2 231
|
||||
Convolution Conv_39 1 1 231 233 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_11 1 2 233 233_splitncnn_0 233_splitncnn_1
|
||||
Concat Concat_41 4 1 225_splitncnn_2 227_splitncnn_1 230_splitncnn_1 233_splitncnn_1 234
|
||||
Convolution Conv_42 1 1 234 236 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_44 5 1 225_splitncnn_1 227_splitncnn_0 230_splitncnn_0 233_splitncnn_0 236 237
|
||||
Convolution Conv_45 1 1 237 238 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_48 2 1 238 225_splitncnn_0 241 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Eltwise Add_51 2 1 241 193_splitncnn_1 244 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_12 1 7 244 244_splitncnn_0 244_splitncnn_1 244_splitncnn_2 244_splitncnn_3 244_splitncnn_4 244_splitncnn_5 244_splitncnn_6
|
||||
Convolution Conv_52 1 1 244_splitncnn_6 246 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_13 1 4 246 246_splitncnn_0 246_splitncnn_1 246_splitncnn_2 246_splitncnn_3
|
||||
Concat Concat_54 2 1 244_splitncnn_5 246_splitncnn_3 247
|
||||
Convolution Conv_55 1 1 247 249 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_14 1 3 249 249_splitncnn_0 249_splitncnn_1 249_splitncnn_2
|
||||
Concat Concat_57 3 1 244_splitncnn_4 246_splitncnn_2 249_splitncnn_2 250
|
||||
Convolution Conv_58 1 1 250 252 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_15 1 2 252 252_splitncnn_0 252_splitncnn_1
|
||||
Concat Concat_60 4 1 244_splitncnn_3 246_splitncnn_1 249_splitncnn_1 252_splitncnn_1 253
|
||||
Convolution Conv_61 1 1 253 255 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_63 5 1 244_splitncnn_2 246_splitncnn_0 249_splitncnn_0 252_splitncnn_0 255 256
|
||||
Convolution Conv_64 1 1 256 257 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_67 2 1 257 244_splitncnn_1 260 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_16 1 6 260 260_splitncnn_0 260_splitncnn_1 260_splitncnn_2 260_splitncnn_3 260_splitncnn_4 260_splitncnn_5
|
||||
Convolution Conv_68 1 1 260_splitncnn_5 262 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_17 1 4 262 262_splitncnn_0 262_splitncnn_1 262_splitncnn_2 262_splitncnn_3
|
||||
Concat Concat_70 2 1 260_splitncnn_4 262_splitncnn_3 263
|
||||
Convolution Conv_71 1 1 263 265 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_18 1 3 265 265_splitncnn_0 265_splitncnn_1 265_splitncnn_2
|
||||
Concat Concat_73 3 1 260_splitncnn_3 262_splitncnn_2 265_splitncnn_2 266
|
||||
Convolution Conv_74 1 1 266 268 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_19 1 2 268 268_splitncnn_0 268_splitncnn_1
|
||||
Concat Concat_76 4 1 260_splitncnn_2 262_splitncnn_1 265_splitncnn_1 268_splitncnn_1 269
|
||||
Convolution Conv_77 1 1 269 271 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_79 5 1 260_splitncnn_1 262_splitncnn_0 265_splitncnn_0 268_splitncnn_0 271 272
|
||||
Convolution Conv_80 1 1 272 273 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_83 2 1 273 260_splitncnn_0 276 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_20 1 6 276 276_splitncnn_0 276_splitncnn_1 276_splitncnn_2 276_splitncnn_3 276_splitncnn_4 276_splitncnn_5
|
||||
Convolution Conv_84 1 1 276_splitncnn_5 278 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_21 1 4 278 278_splitncnn_0 278_splitncnn_1 278_splitncnn_2 278_splitncnn_3
|
||||
Concat Concat_86 2 1 276_splitncnn_4 278_splitncnn_3 279
|
||||
Convolution Conv_87 1 1 279 281 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_22 1 3 281 281_splitncnn_0 281_splitncnn_1 281_splitncnn_2
|
||||
Concat Concat_89 3 1 276_splitncnn_3 278_splitncnn_2 281_splitncnn_2 282
|
||||
Convolution Conv_90 1 1 282 284 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_23 1 2 284 284_splitncnn_0 284_splitncnn_1
|
||||
Concat Concat_92 4 1 276_splitncnn_2 278_splitncnn_1 281_splitncnn_1 284_splitncnn_1 285
|
||||
Convolution Conv_93 1 1 285 287 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_95 5 1 276_splitncnn_1 278_splitncnn_0 281_splitncnn_0 284_splitncnn_0 287 288
|
||||
Convolution Conv_96 1 1 288 289 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_99 2 1 289 276_splitncnn_0 292 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Eltwise Add_102 2 1 292 244_splitncnn_0 295 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_24 1 7 295 295_splitncnn_0 295_splitncnn_1 295_splitncnn_2 295_splitncnn_3 295_splitncnn_4 295_splitncnn_5 295_splitncnn_6
|
||||
Convolution Conv_103 1 1 295_splitncnn_6 297 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_25 1 4 297 297_splitncnn_0 297_splitncnn_1 297_splitncnn_2 297_splitncnn_3
|
||||
Concat Concat_105 2 1 295_splitncnn_5 297_splitncnn_3 298
|
||||
Convolution Conv_106 1 1 298 300 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_26 1 3 300 300_splitncnn_0 300_splitncnn_1 300_splitncnn_2
|
||||
Concat Concat_108 3 1 295_splitncnn_4 297_splitncnn_2 300_splitncnn_2 301
|
||||
Convolution Conv_109 1 1 301 303 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_27 1 2 303 303_splitncnn_0 303_splitncnn_1
|
||||
Concat Concat_111 4 1 295_splitncnn_3 297_splitncnn_1 300_splitncnn_1 303_splitncnn_1 304
|
||||
Convolution Conv_112 1 1 304 306 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_114 5 1 295_splitncnn_2 297_splitncnn_0 300_splitncnn_0 303_splitncnn_0 306 307
|
||||
Convolution Conv_115 1 1 307 308 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_118 2 1 308 295_splitncnn_1 311 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_28 1 6 311 311_splitncnn_0 311_splitncnn_1 311_splitncnn_2 311_splitncnn_3 311_splitncnn_4 311_splitncnn_5
|
||||
Convolution Conv_119 1 1 311_splitncnn_5 313 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_29 1 4 313 313_splitncnn_0 313_splitncnn_1 313_splitncnn_2 313_splitncnn_3
|
||||
Concat Concat_121 2 1 311_splitncnn_4 313_splitncnn_3 314
|
||||
Convolution Conv_122 1 1 314 316 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_30 1 3 316 316_splitncnn_0 316_splitncnn_1 316_splitncnn_2
|
||||
Concat Concat_124 3 1 311_splitncnn_3 313_splitncnn_2 316_splitncnn_2 317
|
||||
Convolution Conv_125 1 1 317 319 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_31 1 2 319 319_splitncnn_0 319_splitncnn_1
|
||||
Concat Concat_127 4 1 311_splitncnn_2 313_splitncnn_1 316_splitncnn_1 319_splitncnn_1 320
|
||||
Convolution Conv_128 1 1 320 322 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_130 5 1 311_splitncnn_1 313_splitncnn_0 316_splitncnn_0 319_splitncnn_0 322 323
|
||||
Convolution Conv_131 1 1 323 324 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_134 2 1 324 311_splitncnn_0 327 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_32 1 6 327 327_splitncnn_0 327_splitncnn_1 327_splitncnn_2 327_splitncnn_3 327_splitncnn_4 327_splitncnn_5
|
||||
Convolution Conv_135 1 1 327_splitncnn_5 329 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_33 1 4 329 329_splitncnn_0 329_splitncnn_1 329_splitncnn_2 329_splitncnn_3
|
||||
Concat Concat_137 2 1 327_splitncnn_4 329_splitncnn_3 330
|
||||
Convolution Conv_138 1 1 330 332 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_34 1 3 332 332_splitncnn_0 332_splitncnn_1 332_splitncnn_2
|
||||
Concat Concat_140 3 1 327_splitncnn_3 329_splitncnn_2 332_splitncnn_2 333
|
||||
Convolution Conv_141 1 1 333 335 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_35 1 2 335 335_splitncnn_0 335_splitncnn_1
|
||||
Concat Concat_143 4 1 327_splitncnn_2 329_splitncnn_1 332_splitncnn_1 335_splitncnn_1 336
|
||||
Convolution Conv_144 1 1 336 338 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_146 5 1 327_splitncnn_1 329_splitncnn_0 332_splitncnn_0 335_splitncnn_0 338 339
|
||||
Convolution Conv_147 1 1 339 340 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_150 2 1 340 327_splitncnn_0 343 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Eltwise Add_153 2 1 343 295_splitncnn_0 346 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_36 1 7 346 346_splitncnn_0 346_splitncnn_1 346_splitncnn_2 346_splitncnn_3 346_splitncnn_4 346_splitncnn_5 346_splitncnn_6
|
||||
Convolution Conv_154 1 1 346_splitncnn_6 348 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_37 1 4 348 348_splitncnn_0 348_splitncnn_1 348_splitncnn_2 348_splitncnn_3
|
||||
Concat Concat_156 2 1 346_splitncnn_5 348_splitncnn_3 349
|
||||
Convolution Conv_157 1 1 349 351 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_38 1 3 351 351_splitncnn_0 351_splitncnn_1 351_splitncnn_2
|
||||
Concat Concat_159 3 1 346_splitncnn_4 348_splitncnn_2 351_splitncnn_2 352
|
||||
Convolution Conv_160 1 1 352 354 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_39 1 2 354 354_splitncnn_0 354_splitncnn_1
|
||||
Concat Concat_162 4 1 346_splitncnn_3 348_splitncnn_1 351_splitncnn_1 354_splitncnn_1 355
|
||||
Convolution Conv_163 1 1 355 357 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_165 5 1 346_splitncnn_2 348_splitncnn_0 351_splitncnn_0 354_splitncnn_0 357 358
|
||||
Convolution Conv_166 1 1 358 359 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_169 2 1 359 346_splitncnn_1 362 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_40 1 6 362 362_splitncnn_0 362_splitncnn_1 362_splitncnn_2 362_splitncnn_3 362_splitncnn_4 362_splitncnn_5
|
||||
Convolution Conv_170 1 1 362_splitncnn_5 364 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_41 1 4 364 364_splitncnn_0 364_splitncnn_1 364_splitncnn_2 364_splitncnn_3
|
||||
Concat Concat_172 2 1 362_splitncnn_4 364_splitncnn_3 365
|
||||
Convolution Conv_173 1 1 365 367 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_42 1 3 367 367_splitncnn_0 367_splitncnn_1 367_splitncnn_2
|
||||
Concat Concat_175 3 1 362_splitncnn_3 364_splitncnn_2 367_splitncnn_2 368
|
||||
Convolution Conv_176 1 1 368 370 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_43 1 2 370 370_splitncnn_0 370_splitncnn_1
|
||||
Concat Concat_178 4 1 362_splitncnn_2 364_splitncnn_1 367_splitncnn_1 370_splitncnn_1 371
|
||||
Convolution Conv_179 1 1 371 373 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_181 5 1 362_splitncnn_1 364_splitncnn_0 367_splitncnn_0 370_splitncnn_0 373 374
|
||||
Convolution Conv_182 1 1 374 375 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_185 2 1 375 362_splitncnn_0 378 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_44 1 6 378 378_splitncnn_0 378_splitncnn_1 378_splitncnn_2 378_splitncnn_3 378_splitncnn_4 378_splitncnn_5
|
||||
Convolution Conv_186 1 1 378_splitncnn_5 380 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_45 1 4 380 380_splitncnn_0 380_splitncnn_1 380_splitncnn_2 380_splitncnn_3
|
||||
Concat Concat_188 2 1 378_splitncnn_4 380_splitncnn_3 381
|
||||
Convolution Conv_189 1 1 381 383 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_46 1 3 383 383_splitncnn_0 383_splitncnn_1 383_splitncnn_2
|
||||
Concat Concat_191 3 1 378_splitncnn_3 380_splitncnn_2 383_splitncnn_2 384
|
||||
Convolution Conv_192 1 1 384 386 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_47 1 2 386 386_splitncnn_0 386_splitncnn_1
|
||||
Concat Concat_194 4 1 378_splitncnn_2 380_splitncnn_1 383_splitncnn_1 386_splitncnn_1 387
|
||||
Convolution Conv_195 1 1 387 389 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_197 5 1 378_splitncnn_1 380_splitncnn_0 383_splitncnn_0 386_splitncnn_0 389 390
|
||||
Convolution Conv_198 1 1 390 391 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_201 2 1 391 378_splitncnn_0 394 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Eltwise Add_204 2 1 394 346_splitncnn_0 397 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_48 1 7 397 397_splitncnn_0 397_splitncnn_1 397_splitncnn_2 397_splitncnn_3 397_splitncnn_4 397_splitncnn_5 397_splitncnn_6
|
||||
Convolution Conv_205 1 1 397_splitncnn_6 399 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_49 1 4 399 399_splitncnn_0 399_splitncnn_1 399_splitncnn_2 399_splitncnn_3
|
||||
Concat Concat_207 2 1 397_splitncnn_5 399_splitncnn_3 400
|
||||
Convolution Conv_208 1 1 400 402 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_50 1 3 402 402_splitncnn_0 402_splitncnn_1 402_splitncnn_2
|
||||
Concat Concat_210 3 1 397_splitncnn_4 399_splitncnn_2 402_splitncnn_2 403
|
||||
Convolution Conv_211 1 1 403 405 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_51 1 2 405 405_splitncnn_0 405_splitncnn_1
|
||||
Concat Concat_213 4 1 397_splitncnn_3 399_splitncnn_1 402_splitncnn_1 405_splitncnn_1 406
|
||||
Convolution Conv_214 1 1 406 408 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_216 5 1 397_splitncnn_2 399_splitncnn_0 402_splitncnn_0 405_splitncnn_0 408 409
|
||||
Convolution Conv_217 1 1 409 410 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_220 2 1 410 397_splitncnn_1 413 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_52 1 6 413 413_splitncnn_0 413_splitncnn_1 413_splitncnn_2 413_splitncnn_3 413_splitncnn_4 413_splitncnn_5
|
||||
Convolution Conv_221 1 1 413_splitncnn_5 415 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_53 1 4 415 415_splitncnn_0 415_splitncnn_1 415_splitncnn_2 415_splitncnn_3
|
||||
Concat Concat_223 2 1 413_splitncnn_4 415_splitncnn_3 416
|
||||
Convolution Conv_224 1 1 416 418 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_54 1 3 418 418_splitncnn_0 418_splitncnn_1 418_splitncnn_2
|
||||
Concat Concat_226 3 1 413_splitncnn_3 415_splitncnn_2 418_splitncnn_2 419
|
||||
Convolution Conv_227 1 1 419 421 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_55 1 2 421 421_splitncnn_0 421_splitncnn_1
|
||||
Concat Concat_229 4 1 413_splitncnn_2 415_splitncnn_1 418_splitncnn_1 421_splitncnn_1 422
|
||||
Convolution Conv_230 1 1 422 424 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_232 5 1 413_splitncnn_1 415_splitncnn_0 418_splitncnn_0 421_splitncnn_0 424 425
|
||||
Convolution Conv_233 1 1 425 426 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_236 2 1 426 413_splitncnn_0 429 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_56 1 6 429 429_splitncnn_0 429_splitncnn_1 429_splitncnn_2 429_splitncnn_3 429_splitncnn_4 429_splitncnn_5
|
||||
Convolution Conv_237 1 1 429_splitncnn_5 431 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_57 1 4 431 431_splitncnn_0 431_splitncnn_1 431_splitncnn_2 431_splitncnn_3
|
||||
Concat Concat_239 2 1 429_splitncnn_4 431_splitncnn_3 432
|
||||
Convolution Conv_240 1 1 432 434 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_58 1 3 434 434_splitncnn_0 434_splitncnn_1 434_splitncnn_2
|
||||
Concat Concat_242 3 1 429_splitncnn_3 431_splitncnn_2 434_splitncnn_2 435
|
||||
Convolution Conv_243 1 1 435 437 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_59 1 2 437 437_splitncnn_0 437_splitncnn_1
|
||||
Concat Concat_245 4 1 429_splitncnn_2 431_splitncnn_1 434_splitncnn_1 437_splitncnn_1 438
|
||||
Convolution Conv_246 1 1 438 440 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_248 5 1 429_splitncnn_1 431_splitncnn_0 434_splitncnn_0 437_splitncnn_0 440 441
|
||||
Convolution Conv_249 1 1 441 442 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_252 2 1 442 429_splitncnn_0 445 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Eltwise Add_255 2 1 445 397_splitncnn_0 448 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_60 1 7 448 448_splitncnn_0 448_splitncnn_1 448_splitncnn_2 448_splitncnn_3 448_splitncnn_4 448_splitncnn_5 448_splitncnn_6
|
||||
Convolution Conv_256 1 1 448_splitncnn_6 450 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_61 1 4 450 450_splitncnn_0 450_splitncnn_1 450_splitncnn_2 450_splitncnn_3
|
||||
Concat Concat_258 2 1 448_splitncnn_5 450_splitncnn_3 451
|
||||
Convolution Conv_259 1 1 451 453 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_62 1 3 453 453_splitncnn_0 453_splitncnn_1 453_splitncnn_2
|
||||
Concat Concat_261 3 1 448_splitncnn_4 450_splitncnn_2 453_splitncnn_2 454
|
||||
Convolution Conv_262 1 1 454 456 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_63 1 2 456 456_splitncnn_0 456_splitncnn_1
|
||||
Concat Concat_264 4 1 448_splitncnn_3 450_splitncnn_1 453_splitncnn_1 456_splitncnn_1 457
|
||||
Convolution Conv_265 1 1 457 459 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_267 5 1 448_splitncnn_2 450_splitncnn_0 453_splitncnn_0 456_splitncnn_0 459 460
|
||||
Convolution Conv_268 1 1 460 461 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_271 2 1 461 448_splitncnn_1 464 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_64 1 6 464 464_splitncnn_0 464_splitncnn_1 464_splitncnn_2 464_splitncnn_3 464_splitncnn_4 464_splitncnn_5
|
||||
Convolution Conv_272 1 1 464_splitncnn_5 466 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_65 1 4 466 466_splitncnn_0 466_splitncnn_1 466_splitncnn_2 466_splitncnn_3
|
||||
Concat Concat_274 2 1 464_splitncnn_4 466_splitncnn_3 467
|
||||
Convolution Conv_275 1 1 467 469 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_66 1 3 469 469_splitncnn_0 469_splitncnn_1 469_splitncnn_2
|
||||
Concat Concat_277 3 1 464_splitncnn_3 466_splitncnn_2 469_splitncnn_2 470
|
||||
Convolution Conv_278 1 1 470 472 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_67 1 2 472 472_splitncnn_0 472_splitncnn_1
|
||||
Concat Concat_280 4 1 464_splitncnn_2 466_splitncnn_1 469_splitncnn_1 472_splitncnn_1 473
|
||||
Convolution Conv_281 1 1 473 475 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_283 5 1 464_splitncnn_1 466_splitncnn_0 469_splitncnn_0 472_splitncnn_0 475 476
|
||||
Convolution Conv_284 1 1 476 477 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_287 2 1 477 464_splitncnn_0 480 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_68 1 6 480 480_splitncnn_0 480_splitncnn_1 480_splitncnn_2 480_splitncnn_3 480_splitncnn_4 480_splitncnn_5
|
||||
Convolution Conv_288 1 1 480_splitncnn_5 482 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_69 1 4 482 482_splitncnn_0 482_splitncnn_1 482_splitncnn_2 482_splitncnn_3
|
||||
Concat Concat_290 2 1 480_splitncnn_4 482_splitncnn_3 483
|
||||
Convolution Conv_291 1 1 483 485 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_70 1 3 485 485_splitncnn_0 485_splitncnn_1 485_splitncnn_2
|
||||
Concat Concat_293 3 1 480_splitncnn_3 482_splitncnn_2 485_splitncnn_2 486
|
||||
Convolution Conv_294 1 1 486 488 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_71 1 2 488 488_splitncnn_0 488_splitncnn_1
|
||||
Concat Concat_296 4 1 480_splitncnn_2 482_splitncnn_1 485_splitncnn_1 488_splitncnn_1 489
|
||||
Convolution Conv_297 1 1 489 491 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_299 5 1 480_splitncnn_1 482_splitncnn_0 485_splitncnn_0 488_splitncnn_0 491 492
|
||||
Convolution Conv_300 1 1 492 493 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_303 2 1 493 480_splitncnn_0 496 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Eltwise Add_306 2 1 496 448_splitncnn_0 499 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Convolution Conv_307 1 1 499 500 0=64 1=3 4=1 5=1 6=36864
|
||||
BinaryOp Add_308 2 1 193_splitncnn_0 500 501
|
||||
Interp Resize_310 1 1 501 506 0=1 1=2.000000e+00 2=2.000000e+00
|
||||
Convolution Conv_311 1 1 506 508 0=64 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Interp Resize_314 1 1 508 513 0=1 1=2.000000e+00 2=2.000000e+00
|
||||
Convolution Conv_315 1 1 513 515 0=64 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Convolution Conv_317 1 1 515 517 0=64 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Convolution Conv_319 1 1 517 output 0=3 1=3 4=1 5=1 6=1728
|
||||
BIN
examples/assets/models/high-fidelity-4x.bin
Normal file
1001
examples/assets/models/high-fidelity-4x.param
Normal file
BIN
examples/assets/models/model.bin
Normal file
|
After Width: | Height: | Size: 960 KiB |
1
examples/assets/models/model.gltf
Normal file
@@ -0,0 +1 @@
|
||||
{"asset":{"version":"2.0","generator":"babylon.js glTF exporter for 3dsmax 2021 v20210607.3"},"scene":0,"scenes":[{"nodes":[0]}],"nodes":[{"mesh":0,"translation":[0.0,-1.14751673,-5.015955E-08],"name":"Cylinder001"}],"meshes":[{"primitives":[{"attributes":{"POSITION":1,"NORMAL":2,"TEXCOORD_0":3},"indices":0,"material":0},{"attributes":{"POSITION":5,"NORMAL":6,"TEXCOORD_0":7},"indices":4,"material":1},{"attributes":{"POSITION":9,"NORMAL":10,"TEXCOORD_0":11},"indices":8,"material":2},{"attributes":{"POSITION":13,"NORMAL":14,"TEXCOORD_0":15},"indices":12,"material":3},{"attributes":{"POSITION":17,"NORMAL":18,"TEXCOORD_0":19},"indices":16,"material":4}],"name":"Cylinder001"}],"accessors":[{"bufferView":0,"componentType":5123,"count":858,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"componentType":5126,"count":858,"max":[0.9673312,-0.0665806457,0.9673312],"min":[-0.9673312,-0.09678768,-0.9673312],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":10296,"componentType":5126,"count":858,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"componentType":5126,"count":858,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":1716,"componentType":5123,"count":14592,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":20592,"componentType":5126,"count":14592,"max":[1.01214123,2.33892131,1.02725148],"min":[-1.01214123,-0.09678768,-1.01214123],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":195696,"componentType":5126,"count":14592,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":6864,"componentType":5126,"count":14592,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":30900,"componentType":5123,"count":1620,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":370800,"componentType":5126,"count":1620,"max":[1.006612,2.3633275,1.006612],"min":[-1.006612,2.338921,-1.006612],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":390240,"componentType":5126,"count":1620,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":123600,"componentType":5126,"count":1620,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":34140,"componentType":5123,"count":318,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":409680,"componentType":5126,"count":318,"max":[0.9454922,2.3548696,0.9454922],"min":[-0.9454921,0.0617354736,-0.945492268],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":413496,"componentType":5126,"count":318,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":136560,"componentType":5126,"count":318,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":34776,"componentType":5123,"count":11520,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":417312,"componentType":5126,"count":11520,"max":[0.196413681,2.12139344,1.90955186],"min":[-0.196414649,0.165008187,1.00927675],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":555552,"componentType":5126,"count":11520,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":139104,"componentType":5126,"count":11520,"type":"VEC2","name":"accessorUVs"}],"bufferViews":[{"buffer":0,"byteLength":57816,"name":"bufferViewScalar"},{"buffer":0,"byteOffset":57816,"byteLength":693792,"byteStride":12,"name":"bufferViewFloatVec3"},{"buffer":0,"byteOffset":751608,"byteLength":231264,"byteStride":8,"name":"bufferViewFloatVec2"}],"buffers":[{"uri":"model.bin","byteLength":982872}],"materials":[{"pbrMetallicRoughness":{"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"01 - Default"},{"pbrMetallicRoughness":{"baseColorTexture":{"index":0},"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"02 - Default"},{"pbrMetallicRoughness":{"baseColorFactor":[0.0,1.0,0.117647067,1.0],"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"03 - Default"},{"pbrMetallicRoughness":{"baseColorFactor":[0.2784314,0.0,0.9921569,1.0],"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"04 - Default"},{"pbrMetallicRoughness":{"baseColorFactor":[0.9725491,0.776470661,0.0,1.0],"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"05 - Default"}],"textures":[{"sampler":0,"source":0,"name":"texture.jpg"}],"images":[{"uri":"./texture.jpg"}],"samplers":[{"magFilter":9729,"minFilter":9987}]}
|
||||
BIN
examples/assets/models/remacri-4x.bin
Normal file
1372
examples/assets/models/remacri-4x.param
Normal file
BIN
examples/assets/models/texture.jpg
Normal file
|
After Width: | Height: | Size: 8.2 MiB |
BIN
examples/assets/models/ultramix-balanced-4x.bin
Normal file
1372
examples/assets/models/ultramix-balanced-4x.param
Normal file
BIN
examples/assets/models/ultrasharp-4x.bin
Normal file
1001
examples/assets/models/ultrasharp-4x.param
Normal file
BIN
examples/assets/models/upscayl-lite-4x.bin
Normal file
74
examples/assets/models/upscayl-lite-4x.param
Normal file
@@ -0,0 +1,74 @@
|
||||
7767517
|
||||
72 73
|
||||
Input input.1 0 1 data
|
||||
Split splitncnn_input0 1 2 data input_splitncnn_0 input_splitncnn_1
|
||||
Convolution Conv_0 1 1 input_splitncnn_1 102 0=64 1=3 4=1 5=1 6=1728
|
||||
PReLU PRelu_1 1 1 102 105 0=64
|
||||
Convolution Conv_2 1 1 105 106 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_3 1 1 106 109 0=64
|
||||
Convolution Conv_4 1 1 109 110 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_5 1 1 110 113 0=64
|
||||
Convolution Conv_6 1 1 113 114 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_7 1 1 114 117 0=64
|
||||
Convolution Conv_8 1 1 117 118 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_9 1 1 118 121 0=64
|
||||
Convolution Conv_10 1 1 121 122 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_11 1 1 122 125 0=64
|
||||
Convolution Conv_12 1 1 125 126 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_13 1 1 126 129 0=64
|
||||
Convolution Conv_14 1 1 129 130 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_15 1 1 130 133 0=64
|
||||
Convolution Conv_16 1 1 133 134 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_17 1 1 134 137 0=64
|
||||
Convolution Conv_18 1 1 137 138 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_19 1 1 138 141 0=64
|
||||
Convolution Conv_20 1 1 141 142 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_21 1 1 142 145 0=64
|
||||
Convolution Conv_22 1 1 145 146 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_23 1 1 146 149 0=64
|
||||
Convolution Conv_24 1 1 149 150 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_25 1 1 150 153 0=64
|
||||
Convolution Conv_26 1 1 153 154 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_27 1 1 154 157 0=64
|
||||
Convolution Conv_28 1 1 157 158 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_29 1 1 158 161 0=64
|
||||
Convolution Conv_30 1 1 161 162 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_31 1 1 162 165 0=64
|
||||
Convolution Conv_32 1 1 165 166 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_33 1 1 166 169 0=64
|
||||
Convolution Conv_34 1 1 169 170 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_35 1 1 170 173 0=64
|
||||
Convolution Conv_36 1 1 173 174 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_37 1 1 174 177 0=64
|
||||
Convolution Conv_38 1 1 177 178 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_39 1 1 178 181 0=64
|
||||
Convolution Conv_40 1 1 181 182 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_41 1 1 182 185 0=64
|
||||
Convolution Conv_42 1 1 185 186 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_43 1 1 186 189 0=64
|
||||
Convolution Conv_44 1 1 189 190 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_45 1 1 190 193 0=64
|
||||
Convolution Conv_46 1 1 193 194 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_47 1 1 194 197 0=64
|
||||
Convolution Conv_48 1 1 197 198 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_49 1 1 198 201 0=64
|
||||
Convolution Conv_50 1 1 201 202 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_51 1 1 202 205 0=64
|
||||
Convolution Conv_52 1 1 205 206 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_53 1 1 206 209 0=64
|
||||
Convolution Conv_54 1 1 209 210 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_55 1 1 210 213 0=64
|
||||
Convolution Conv_56 1 1 213 214 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_57 1 1 214 217 0=64
|
||||
Convolution Conv_58 1 1 217 218 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_59 1 1 218 221 0=64
|
||||
Convolution Conv_60 1 1 221 222 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_61 1 1 222 225 0=64
|
||||
Convolution Conv_62 1 1 225 226 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_63 1 1 226 229 0=64
|
||||
Convolution Conv_64 1 1 229 230 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_65 1 1 230 233 0=64
|
||||
Convolution Conv_66 1 1 233 234 0=48 1=3 4=1 5=1 6=27648
|
||||
PixelShuffle DepthToSpace_67 1 1 234 235 0=4
|
||||
Interp Resize_68 1 1 input_splitncnn_0 240 0=1 1=4.000000e+00 2=4.000000e+00
|
||||
BinaryOp Add_69 2 1 235 240 output
|
||||
BIN
examples/assets/models/upscayl-standard-4x.bin
Normal file
1001
examples/assets/models/upscayl-standard-4x.param
Normal file
30
examples/assets/upscale_resize.sh
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/bin/zsh
|
||||
setopt null_glob
|
||||
|
||||
INPUT="./images"
|
||||
OUTPUT="./images_output"
|
||||
MODELPATH="./models"
|
||||
MODELNAME="ultramix-balanced-4x"
|
||||
TARGET_WIDTH="4320"
|
||||
FORMAT="jpg" # 或 webp
|
||||
SCALE=3
|
||||
MAX_SIZE=$((20 * 1024 * 1024)) # 20MB
|
||||
|
||||
|
||||
./bin/mac/upscayl-bin -i "$INPUT" -o "$OUTPUT" -f $FORMAT -m $MODELPATH -n $MODELNAME -w $TARGET_WIDTH -j 4:8:4 -v
|
||||
|
||||
echo "\n===== 输入目录: $INPUT ====="
|
||||
for img in "$INPUT"/*.{png,jpg,jpeg}; do
|
||||
[ -e "$img" ] || continue
|
||||
size=$(stat -f%z "$img")
|
||||
res=$(sips -g pixelWidth -g pixelHeight "$img" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
|
||||
echo "$(basename "$img"): ${size} bytes, ${res}"
|
||||
done
|
||||
|
||||
echo "\n===== 输出目录: $OUTPUT ====="
|
||||
for img in "$OUTPUT"/*.{png,jpg,jpeg}; do
|
||||
[ -e "$img" ] || continue
|
||||
size=$(stat -f%z "$img")
|
||||
res=$(sips -g pixelWidth -g pixelHeight "$img" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
|
||||
echo "$(basename "$img"): ${size} bytes, ${res}"
|
||||
done
|
||||
114
examples/assets/upscale_to_8k.sh
Executable file
@@ -0,0 +1,114 @@
|
||||
#!/bin/zsh
|
||||
setopt null_glob
|
||||
|
||||
# 设置默认值或从环境变量获取
|
||||
INPUT="${INPUT_DIR:-./images}"
|
||||
OUTPUT="${OUTPUT_DIR:-./images_output}"
|
||||
MODELPATH="${MODELPATH:-./models}"
|
||||
MODELNAME="${MODELNAME:-ultramix-balanced-4x}"
|
||||
BIN_PATH="${BIN_PATH:-./bin/mac/upscayl-bin}"
|
||||
TARGET_WIDTH=4320
|
||||
TARGET_HEIGHT=7680
|
||||
FORMAT="jpg"
|
||||
THREADS="4:8:4"
|
||||
TARGET_SIZE=$((10 * 1024 * 1024)) # 10MB
|
||||
MAX_SIZE=$((20 * 1024 * 1024)) # 20MB
|
||||
|
||||
echo "===== 开始批量处理图片 ====="
|
||||
echo "输入目录: $INPUT"
|
||||
echo "输出目录: $OUTPUT"
|
||||
echo "模型路径: $MODELPATH"
|
||||
echo "模型名称: $MODELNAME"
|
||||
echo "二进制文件: $BIN_PATH"
|
||||
|
||||
# 确保输出目录存在
|
||||
mkdir -p "$OUTPUT"
|
||||
|
||||
# 循环对每个图片单独执行 upscayl-bin,输出路径为文件路径
|
||||
for img in "$INPUT"/*.{png,jpg,jpeg}; do
|
||||
[ -e "$img" ] || continue
|
||||
base=$(basename "$img")
|
||||
out_img="$OUTPUT/${base%.*}.$FORMAT"
|
||||
compress=10 # 0为无压缩,100为最大压缩
|
||||
try=1
|
||||
echo "\n==== 开始处理: $base ===="
|
||||
echo "输入文件: $img"
|
||||
echo "输出文件: $out_img"
|
||||
echo "模型: $MODELNAME, 模型路径: $MODELPATH"
|
||||
echo "格式: $FORMAT"
|
||||
|
||||
|
||||
# 获取原图宽高
|
||||
read orig_w orig_h <<< $(sips -g pixelWidth -g pixelHeight "$img" 2>/dev/null | awk '/pixelWidth/ {w=$2} /pixelHeight/ {h=$2} END{print w,h}')
|
||||
if [ "$orig_w" -lt "$orig_h" ]; then
|
||||
short=$orig_w
|
||||
long=$orig_h
|
||||
else
|
||||
short=$orig_h
|
||||
long=$orig_w
|
||||
fi
|
||||
echo "DEBUG: orig_w=$orig_w, orig_h=$orig_h, short=$short, long=$long"
|
||||
scale1=$(echo "scale=8; 4320/$short" | bc)
|
||||
scale2=$(echo "scale=8; 7680/$long" | bc)
|
||||
echo "DEBUG: scale1=$scale1, scale2=$scale2"
|
||||
# 取scale1和scale2的最大值
|
||||
scale=$(echo "$scale1 > $scale2" | bc -l)
|
||||
if [ "$scale" -eq 1 ]; then
|
||||
use_scale=$scale1
|
||||
else
|
||||
use_scale=$scale2
|
||||
fi
|
||||
use_scale=$(printf "%f" "$use_scale")
|
||||
echo "DEBUG: use_scale=$use_scale"
|
||||
# 保证不缩小
|
||||
scale_cmp=$(echo "$use_scale > 1" | bc -l)
|
||||
echo "DEBUG: scale_cmp=$scale_cmp"
|
||||
if [ "$scale_cmp" -eq 1 ]; then
|
||||
target_w=$(awk -v w="$orig_w" -v s="$use_scale" 'BEGIN{printf "%d", w*s+0.5}')
|
||||
target_h=$(awk -v h="$orig_h" -v s="$use_scale" 'BEGIN{printf "%d", h*s+0.5}')
|
||||
echo "原图分辨率: ${orig_w}x${orig_h}, 目标分辨率: ${target_w}x${target_h} (短边≥4320, 长边≥7680)"
|
||||
else
|
||||
target_w=$orig_w
|
||||
target_h=$orig_h
|
||||
echo "原图分辨率: ${orig_w}x${orig_h}, 已满足短边≥4320且长边≥7680,无需放大"
|
||||
fi
|
||||
|
||||
while true; do
|
||||
echo "尝试第 $try 次: compress=$compress"
|
||||
upscale_cmd="\"$BIN_PATH\" -i \"$img\" -o \"$out_img\" -f $FORMAT -m \"$MODELPATH\" -n $MODELNAME -r \"${target_w}x${target_h}\" -c $compress -j $THREADS -v"
|
||||
echo "执行命令: $upscale_cmd"
|
||||
eval $upscale_cmd
|
||||
if [ ! -f "$out_img" ]; then
|
||||
echo "$base: 未生成图片,compress=$compress"
|
||||
break
|
||||
fi
|
||||
size=$(stat -f%z "$out_img")
|
||||
res=$(sips -g pixelWidth -g pixelHeight "$out_img" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
|
||||
echo "$base: compress=$compress, size=${size} bytes, 分辨率=${res}"
|
||||
if [ $size -le $MAX_SIZE ] || [ $compress -ge 100 ]; then
|
||||
echo "$base: 满足大小要求,最终 compress=$compress"
|
||||
break
|
||||
fi
|
||||
# compress 每次递增10,最大不超过100
|
||||
compress=$((compress + 10))
|
||||
[ $compress -gt 100 ] && compress=100
|
||||
try=$((try+1))
|
||||
[ $try -gt 10 ] && echo "$base: 达到最大尝试次数,停止调整" && break
|
||||
done
|
||||
done
|
||||
|
||||
echo "\n===== 输入目录: $INPUT ====="
|
||||
for img in "$INPUT"/*.{png,jpg,jpeg}; do
|
||||
[ -e "$img" ] || continue
|
||||
size=$(stat -f%z "$img")
|
||||
res=$(sips -g pixelWidth -g pixelHeight "$img" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
|
||||
echo "$(basename "$img"): ${size} bytes, ${res}"
|
||||
done
|
||||
|
||||
echo "\n===== 输出目录: $OUTPUT ====="
|
||||
for img in "$OUTPUT"/*.{png,jpg,jpeg}; do
|
||||
[ -e "$img" ] || continue
|
||||
size=$(stat -f%z "$img")
|
||||
res=$(sips -g pixelWidth -g pixelHeight "$img" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
|
||||
echo "$(basename "$img"): ${size} bytes, ${res}"
|
||||
done
|
||||
0
examples/assets/upscale_to_8k_single.bat
Normal file
131
examples/assets/upscale_to_8k_single.sh
Executable file
@@ -0,0 +1,131 @@
|
||||
#!/bin/zsh
|
||||
setopt null_glob
|
||||
|
||||
# 从环境变量或参数获取配置
|
||||
INPUT_FILE="${INPUT_FILE:-$1}"
|
||||
OUTPUT_FILE="${OUTPUT_FILE:-$2}"
|
||||
MODELPATH="${MODELPATH:-./models}"
|
||||
MODELNAME="${MODELNAME:-ultramix-balanced-4x}"
|
||||
BIN_PATH="${BIN_PATH:-./bin/mac/upscayl-bin}"
|
||||
TARGET_WIDTH=4320
|
||||
TARGET_HEIGHT=7680
|
||||
FORMAT="jpg"
|
||||
THREADS="4:8:4"
|
||||
TARGET_SIZE=$((10 * 1024 * 1024)) # 10MB
|
||||
MAX_SIZE=$((20 * 1024 * 1024)) # 20MB
|
||||
|
||||
# 检查输入参数
|
||||
if [ -z "$INPUT_FILE" ] || [ -z "$OUTPUT_FILE" ]; then
|
||||
echo "错误: 需要指定输入和输出文件路径"
|
||||
echo "用法: $0 <输入文件> <输出文件>"
|
||||
echo "或者设置环境变量 INPUT_FILE 和 OUTPUT_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$INPUT_FILE" ]; then
|
||||
echo "错误: 输入文件不存在: $INPUT_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "===== 开始处理单张图片 ====="
|
||||
echo "输入文件: $INPUT_FILE"
|
||||
echo "输出文件: $OUTPUT_FILE"
|
||||
echo "模型路径: $MODELPATH"
|
||||
echo "模型名称: $MODELNAME"
|
||||
echo "二进制文件: $BIN_PATH"
|
||||
|
||||
# 确保输出目录存在
|
||||
output_dir=$(dirname "$OUTPUT_FILE")
|
||||
mkdir -p "$output_dir"
|
||||
|
||||
base=$(basename "$INPUT_FILE")
|
||||
compress=10 # 0为无压缩,100为最大压缩
|
||||
try=1
|
||||
|
||||
echo "\n==== 开始处理: $base ===="
|
||||
echo "输入文件: $INPUT_FILE"
|
||||
echo "输出文件: $OUTPUT_FILE"
|
||||
echo "模型: $MODELNAME, 模型路径: $MODELPATH"
|
||||
echo "格式: $FORMAT"
|
||||
|
||||
# 获取原图宽高
|
||||
read orig_w orig_h <<< $(sips -g pixelWidth -g pixelHeight "$INPUT_FILE" 2>/dev/null | awk '/pixelWidth/ {w=$2} /pixelHeight/ {h=$2} END{print w,h}')
|
||||
if [ "$orig_w" -lt "$orig_h" ]; then
|
||||
short=$orig_w
|
||||
long=$orig_h
|
||||
else
|
||||
short=$orig_h
|
||||
long=$orig_w
|
||||
fi
|
||||
echo "DEBUG: orig_w=$orig_w, orig_h=$orig_h, short=$short, long=$long"
|
||||
|
||||
scale1=$(echo "scale=8; 4320/$short" | bc)
|
||||
scale2=$(echo "scale=8; 7680/$long" | bc)
|
||||
echo "DEBUG: scale1=$scale1, scale2=$scale2"
|
||||
|
||||
# 取scale1和scale2的最大值
|
||||
scale=$(echo "$scale1 > $scale2" | bc -l)
|
||||
if [ "$scale" -eq 1 ]; then
|
||||
use_scale=$scale1
|
||||
else
|
||||
use_scale=$scale2
|
||||
fi
|
||||
use_scale=$(printf "%f" "$use_scale")
|
||||
echo "DEBUG: use_scale=$use_scale"
|
||||
|
||||
# 保证不缩小
|
||||
scale_cmp=$(echo "$use_scale > 1" | bc -l)
|
||||
echo "DEBUG: scale_cmp=$scale_cmp"
|
||||
if [ "$scale_cmp" -eq 1 ]; then
|
||||
target_w=$(awk -v w="$orig_w" -v s="$use_scale" 'BEGIN{printf "%d", w*s+0.5}')
|
||||
target_h=$(awk -v h="$orig_h" -v s="$use_scale" 'BEGIN{printf "%d", h*s+0.5}')
|
||||
echo "原图分辨率: ${orig_w}x${orig_h}, 目标分辨率: ${target_w}x${target_h} (短边≥4320, 长边≥7680)"
|
||||
else
|
||||
target_w=$orig_w
|
||||
target_h=$orig_h
|
||||
echo "原图分辨率: ${orig_w}x${orig_h}, 已满足短边≥4320且长边≥7680,无需放大"
|
||||
fi
|
||||
|
||||
# 处理图片,循环调整压缩率直到满足大小要求
|
||||
while true; do
|
||||
echo "尝试第 $try 次: compress=$compress"
|
||||
upscale_cmd="\"$BIN_PATH\" -i \"$INPUT_FILE\" -o \"$OUTPUT_FILE\" -f $FORMAT -m \"$MODELPATH\" -n $MODELNAME -r \"${target_w}x${target_h}\" -c $compress -j $THREADS -v"
|
||||
echo "执行命令: $upscale_cmd"
|
||||
eval $upscale_cmd
|
||||
|
||||
if [ ! -f "$OUTPUT_FILE" ]; then
|
||||
echo "$base: 未生成图片,compress=$compress"
|
||||
echo "处理失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
size=$(stat -f%z "$OUTPUT_FILE")
|
||||
res=$(sips -g pixelWidth -g pixelHeight "$OUTPUT_FILE" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
|
||||
echo "$base: compress=$compress, size=${size} bytes, 分辨率=${res}"
|
||||
|
||||
if [ $size -le $MAX_SIZE ] || [ $compress -ge 100 ]; then
|
||||
echo "$base: 满足大小要求,最终 compress=$compress"
|
||||
break
|
||||
fi
|
||||
|
||||
# compress 每次递增10,最大不超过100
|
||||
compress=$((compress + 10))
|
||||
[ $compress -gt 100 ] && compress=100
|
||||
try=$((try+1))
|
||||
[ $try -gt 10 ] && echo "$base: 达到最大尝试次数,停止调整" && break
|
||||
done
|
||||
|
||||
echo "\n===== 处理完成 ====="
|
||||
if [ -f "$OUTPUT_FILE" ]; then
|
||||
input_size=$(stat -f%z "$INPUT_FILE")
|
||||
output_size=$(stat -f%z "$OUTPUT_FILE")
|
||||
input_res=$(sips -g pixelWidth -g pixelHeight "$INPUT_FILE" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
|
||||
output_res=$(sips -g pixelWidth -g pixelHeight "$OUTPUT_FILE" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
|
||||
|
||||
echo "输入: $(basename "$INPUT_FILE") - ${input_size} bytes, ${input_res}"
|
||||
echo "输出: $(basename "$OUTPUT_FILE") - ${output_size} bytes, ${output_res}"
|
||||
echo "处理成功完成!"
|
||||
else
|
||||
echo "处理失败:未生成输出文件"
|
||||
exit 1
|
||||
fi
|
||||
@@ -21,6 +21,6 @@
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>12.0</string>
|
||||
<string>13.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -1,22 +1,88 @@
|
||||
PODS:
|
||||
- DKImagePickerController/Core (4.3.9):
|
||||
- DKImagePickerController/ImageDataManager
|
||||
- DKImagePickerController/Resource
|
||||
- DKImagePickerController/ImageDataManager (4.3.9)
|
||||
- DKImagePickerController/PhotoGallery (4.3.9):
|
||||
- DKImagePickerController/Core
|
||||
- DKPhotoGallery
|
||||
- DKImagePickerController/Resource (4.3.9)
|
||||
- DKPhotoGallery (0.0.19):
|
||||
- DKPhotoGallery/Core (= 0.0.19)
|
||||
- DKPhotoGallery/Model (= 0.0.19)
|
||||
- DKPhotoGallery/Preview (= 0.0.19)
|
||||
- DKPhotoGallery/Resource (= 0.0.19)
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Core (0.0.19):
|
||||
- DKPhotoGallery/Model
|
||||
- DKPhotoGallery/Preview
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Model (0.0.19):
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Preview (0.0.19):
|
||||
- DKPhotoGallery/Model
|
||||
- DKPhotoGallery/Resource
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Resource (0.0.19):
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- file_picker (0.0.1):
|
||||
- DKImagePickerController/PhotoGallery
|
||||
- Flutter
|
||||
- Flutter (1.0.0)
|
||||
- package_info_plus (0.4.5):
|
||||
- Flutter
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- SDWebImage (5.21.1):
|
||||
- SDWebImage/Core (= 5.21.1)
|
||||
- SDWebImage/Core (5.21.1)
|
||||
- SwiftyGif (5.4.5)
|
||||
- thermion_flutter (0.0.1):
|
||||
- Flutter
|
||||
|
||||
DEPENDENCIES:
|
||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- thermion_flutter (from `.symlinks/plugins/thermion_flutter/ios`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- DKImagePickerController
|
||||
- DKPhotoGallery
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
file_picker:
|
||||
:path: ".symlinks/plugins/file_picker/ios"
|
||||
Flutter:
|
||||
:path: Flutter
|
||||
package_info_plus:
|
||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||
path_provider_foundation:
|
||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||
thermion_flutter:
|
||||
:path: ".symlinks/plugins/thermion_flutter/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||
thermion_flutter: c965e09831858465a1a8df59ff97e40a4d002773
|
||||
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
|
||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||
package_info_plus: 580e9a5f1b6ca5594e7c9ed5f92d1dfb2a66b5e1
|
||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||
SDWebImage: f29024626962457f3470184232766516dee8dfea
|
||||
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
||||
thermion_flutter: d0c4adbb1de69e5ecc244d70bbde81d8497246b2
|
||||
|
||||
PODFILE CHECKSUM: a57f30d18f102dd3ce366b1d62a55ecbef2158e5
|
||||
|
||||
COCOAPODS: 1.15.2
|
||||
COCOAPODS: 1.16.2
|
||||
|
||||
@@ -197,6 +197,7 @@
|
||||
97C146EC1CF9000F007C117D /* Resources */,
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
6DA127E3193C7EF5F7B6B4C0 /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -284,6 +285,23 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
||||
};
|
||||
6DA127E3193C7EF5F7B6B4C0 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
78F05AF37D9E628BE6E89ABD /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -436,7 +454,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
@@ -452,7 +470,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = TM2B4SJXNJ;
|
||||
DEVELOPMENT_TEAM = 979UK3QQJ3;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
@@ -567,7 +585,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -618,7 +636,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
@@ -636,7 +654,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = TM2B4SJXNJ;
|
||||
DEVELOPMENT_TEAM = 979UK3QQJ3;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
@@ -660,7 +678,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = TM2B4SJXNJ;
|
||||
DEVELOPMENT_TEAM = 979UK3QQJ3;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
@@ -54,11 +55,13 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
enableGPUValidationMode = "1"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
|
||||
114
examples/flutter/animations/lib/cup.dart
Normal file
@@ -0,0 +1,114 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:thermion_flutter/thermion_flutter.dart';
|
||||
|
||||
class Cup extends StatefulWidget {
|
||||
const Cup({super.key});
|
||||
|
||||
@override
|
||||
State<Cup> createState() => _CupState();
|
||||
}
|
||||
|
||||
class _CupState extends State<Cup> {
|
||||
bool _isLoading = true;
|
||||
String? _modelPath, _modelUri;
|
||||
String _statusMessage = "正在加载本地模型...";
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadLocalModel();
|
||||
}
|
||||
|
||||
// 从应用支持目录加载模型
|
||||
Future<void> _loadLocalModel() async {
|
||||
try {
|
||||
setState(() {
|
||||
_statusMessage = "获取本地模型路径...";
|
||||
});
|
||||
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final modelFile = File(p.join(supportDir.path, 'cup', 'model.gltf'));
|
||||
|
||||
String modelPath =
|
||||
File(p.join(supportDir.path, 'cup', 'model.gltf')).absolute.path;
|
||||
final cupDir = Directory('${supportDir.path}/cup');
|
||||
final modelUri = File('${cupDir.path}/model.gltf').uri.toString();
|
||||
print('加载本地模modelPath: $modelPath');
|
||||
print('加载本地模modelUri: $modelUri');
|
||||
|
||||
if (await modelFile.exists()) {
|
||||
setState(() {
|
||||
_modelPath = modelPath;
|
||||
_modelUri = modelUri;
|
||||
|
||||
_isLoading = false;
|
||||
_statusMessage = "本地模型加载完成";
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_statusMessage = "本地模型文件不存在";
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
print('加载本地模型失败: $e');
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_statusMessage = "加载失败: $e";
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('本地模型查看'),
|
||||
),
|
||||
body: _isLoading
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const CircularProgressIndicator(),
|
||||
const SizedBox(height: 16),
|
||||
Text(_statusMessage),
|
||||
],
|
||||
),
|
||||
)
|
||||
: _modelPath == null
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.error, size: 48, color: Colors.red),
|
||||
const SizedBox(height: 16),
|
||||
Text(_statusMessage),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: _loadLocalModel,
|
||||
child: const Text('重试'),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: ViewerWidget(
|
||||
// assetPath: "file://$_modelPath",
|
||||
assetPath: _modelUri,
|
||||
skyboxPath: "assets/default_env_skybox.ktx",
|
||||
iblPath: "assets/default_env_ibl.ktx",
|
||||
transformToUnitCube: true,
|
||||
initialCameraPosition: Vector3(0, 0, 6),
|
||||
background: Colors.grey[200],
|
||||
manipulatorType: ManipulatorType.ORBIT,
|
||||
initial: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
142
examples/flutter/animations/lib/cup_page.dart
Normal file
@@ -0,0 +1,142 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:thermion_flutter/thermion_flutter.dart';
|
||||
// import 'package:thermion_dart/src/viewer/src/thermion_viewer_base.dart';
|
||||
|
||||
class CupPage1 extends StatelessWidget {
|
||||
const CupPage1({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Stack(children: [
|
||||
Positioned.fill(
|
||||
child: ViewerWidget(
|
||||
assetPath: "assets/cup/model.gltf",
|
||||
skyboxPath: "assets/default_env_skybox.ktx",
|
||||
iblPath: "assets/default_env_ibl.ktx",
|
||||
transformToUnitCube: true,
|
||||
initialCameraPosition: Vector3(0, 0, 6),
|
||||
background: Colors.blue,
|
||||
manipulatorType: ManipulatorType.ORBIT,
|
||||
onViewerAvailable: (viewer) async {
|
||||
await Future.delayed(const Duration(seconds: 5));
|
||||
await viewer.removeSkybox();
|
||||
},
|
||||
initial: Container(
|
||||
color: Colors.grey,
|
||||
),
|
||||
))
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
class CupPage extends StatefulWidget {
|
||||
const CupPage({super.key});
|
||||
|
||||
@override
|
||||
State<CupPage> createState() => _CupPageState();
|
||||
}
|
||||
|
||||
class _CupPageState extends State<CupPage> {
|
||||
bool _isLoading = true;
|
||||
String? _modelPath, modelUri;
|
||||
String _statusMessage = "正在加载本地模型...";
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadLocalModel();
|
||||
}
|
||||
|
||||
// 从应用支持目录加载模型
|
||||
Future<void> _loadLocalModel() async {
|
||||
try {
|
||||
setState(() {
|
||||
_statusMessage = "获取本地模型路径...";
|
||||
});
|
||||
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final modelFile = File(p.join(supportDir.path, 'cup', 'model.gltf'));
|
||||
|
||||
String modelPath =
|
||||
File(p.join(supportDir.path, 'cup', 'model.gltf')).absolute.path;
|
||||
final cupDir = Directory('${supportDir.path}/cup');
|
||||
final modelUri = File('${cupDir.path}/model.gltf').uri;
|
||||
print('加载本地模modelPath: $modelPath');
|
||||
print('加载本地模modelUri: $modelUri');
|
||||
|
||||
if (await modelFile.exists()) {
|
||||
setState(() {
|
||||
_modelPath = modelPath;
|
||||
|
||||
_isLoading = false;
|
||||
_statusMessage = "本地模型加载完成";
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_statusMessage = "本地模型文件不存在";
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
print('加载本地模型失败: $e');
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_statusMessage = "加载失败: $e";
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('本地模型查看'),
|
||||
),
|
||||
body: _isLoading
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const CircularProgressIndicator(),
|
||||
const SizedBox(height: 16),
|
||||
Text(_statusMessage),
|
||||
],
|
||||
),
|
||||
)
|
||||
: _modelPath == null
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.error, size: 48, color: Colors.red),
|
||||
const SizedBox(height: 16),
|
||||
Text(_statusMessage),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: _loadLocalModel,
|
||||
child: const Text('重试'),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: ViewerWidget(
|
||||
assetPath: "file://$_modelPath",
|
||||
// assetPath: modelUri,
|
||||
skyboxPath: "assets/default_env_skybox.ktx",
|
||||
iblPath: "assets/default_env_ibl.ktx",
|
||||
transformToUnitCube: true,
|
||||
initialCameraPosition: Vector3(0, 0, 6),
|
||||
background: Colors.grey[200],
|
||||
manipulatorType: ManipulatorType.ORBIT,
|
||||
initial: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,407 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:animations/utils/binary_manager.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
import 'cup.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// 初始化3D模型资源
|
||||
try {
|
||||
await BinaryManager.initializeAppResources();
|
||||
print('3D模型资源初始化成功');
|
||||
} catch (e) {
|
||||
print('无法初始化3D模型资源: $e');
|
||||
}
|
||||
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: '3D模型纹理替换',
|
||||
theme: ThemeData(
|
||||
primarySwatch: Colors.blue,
|
||||
visualDensity: VisualDensity.adaptivePlatformDensity,
|
||||
),
|
||||
home: ModelViewerWithTextureReplace(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ModelViewerWithTextureReplace extends StatefulWidget {
|
||||
const ModelViewerWithTextureReplace({super.key});
|
||||
|
||||
@override
|
||||
State<ModelViewerWithTextureReplace> createState() =>
|
||||
_ModelViewerWithTextureReplaceState();
|
||||
}
|
||||
|
||||
class _ModelViewerWithTextureReplaceState
|
||||
extends State<ModelViewerWithTextureReplace> {
|
||||
bool _isLoading = true;
|
||||
String? _modelPath;
|
||||
String? _texturePath;
|
||||
int _keyValue = 0;
|
||||
String _statusMessage = "正在加载模型...";
|
||||
bool _isReplacingTexture = false;
|
||||
File? _selectedImage;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_load3DModels();
|
||||
// _loadModel();
|
||||
}
|
||||
|
||||
// 加载3D模型文件
|
||||
Future<void> _load3DModels() async {
|
||||
try {
|
||||
setState(() {
|
||||
_statusMessage = "获取模型路径...";
|
||||
});
|
||||
|
||||
// 使用BinaryManager获取3D模型文件路径
|
||||
// final supportDir = await getApplicationSupportDirectory();
|
||||
// final cupDir = Directory('${supportDir.path}/cup');
|
||||
// final modelFile = File('${cupDir.path}/model.gltf');
|
||||
|
||||
final modelPath = await BinaryManager.get3DModelPath("model.gltf");
|
||||
|
||||
final texturePath = await BinaryManager.get3DModelPath("texture.jpg");
|
||||
|
||||
// print("路径: $modelPath");
|
||||
// print("文件是否存在: ${await File(modelPath).exists()}");
|
||||
// print("文件路径: ${await File(modelPath).uri}");
|
||||
//
|
||||
// setState(() {
|
||||
// _modelPath = File(modelPath).uri.toString(); // 确保是本地路径
|
||||
// });
|
||||
|
||||
// if (!await File(modelPath).exists()) {
|
||||
// print("❌ 模型文件不存在: $modelPath");
|
||||
// }
|
||||
// if (!await File(texturePath).exists()) {
|
||||
// print("❌ 纹理文件不存在: $texturePath");
|
||||
// }
|
||||
print('modelPath=${modelPath}\ntexturePath=${texturePath}');
|
||||
setState(() {
|
||||
_modelPath = modelPath;
|
||||
_texturePath = texturePath;
|
||||
_isLoading = false;
|
||||
_statusMessage = "加载完成";
|
||||
});
|
||||
} catch (e) {
|
||||
print('加载3D模型失败: $e');
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_statusMessage = "加载失败: $e";
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 使用FilePicker选择新纹理
|
||||
Future<void> _pickNewTexture() async {
|
||||
if (_isReplacingTexture || _texturePath == null) return;
|
||||
|
||||
setState(() {
|
||||
_isReplacingTexture = true;
|
||||
_statusMessage = "正在选择纹理文件...";
|
||||
});
|
||||
|
||||
try {
|
||||
// 选择图片文件
|
||||
FilePickerResult? result = await FilePicker.platform.pickFiles(
|
||||
type: FileType.image,
|
||||
allowMultiple: false,
|
||||
);
|
||||
|
||||
if (result == null ||
|
||||
result.files.isEmpty ||
|
||||
result.files.single.path == null) {
|
||||
setState(() {
|
||||
_statusMessage = "取消选择";
|
||||
});
|
||||
return;
|
||||
}
|
||||
_selectedImage = File(result.files.single.path!);
|
||||
|
||||
final selectedFile = result.files.single;
|
||||
final fileExtension = p.extension(selectedFile.path!).toLowerCase();
|
||||
|
||||
// 可选:仅允许特定图片格式
|
||||
if (!['.jpg', '.jpeg', '.png'].contains(fileExtension)) {
|
||||
setState(() {
|
||||
_statusMessage = "仅支持 JPG / PNG 格式纹理";
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
final newTexture = File(selectedFile.path!);
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final modelDir = p.join(supportDir.path, 'cup');
|
||||
final modelPath = p.join(modelDir, 'model.gltf');
|
||||
final modelFile = File(modelPath);
|
||||
|
||||
if (!await newTexture.exists()) {
|
||||
setState(() {
|
||||
_statusMessage = "所选纹理文件不存在";
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 复制新纹理为固定名 new.jpg 到模型目录
|
||||
final newTexturePath = p.join(modelDir, 'new.jpg');
|
||||
await newTexture.copy(newTexturePath);
|
||||
_texturePath = newTexturePath;
|
||||
|
||||
// 修改 GLTF 文件
|
||||
if (await modelFile.exists()) {
|
||||
String gltfContent = await modelFile.readAsString();
|
||||
|
||||
// ✅ 修复 GLTF 中非法负号格式(例如 "- 0.123" => "-0.123")
|
||||
gltfContent = gltfContent.replaceAllMapped(
|
||||
RegExp(r'-\s+(\d+(\.\d+)?)'),
|
||||
(match) => '-${match.group(1)}',
|
||||
);
|
||||
|
||||
final gltfJson = jsonDecode(gltfContent);
|
||||
|
||||
// 安全修改 images[0].uri
|
||||
if (gltfJson['images'] != null && gltfJson['images'].isNotEmpty) {
|
||||
gltfJson['images'][0]['uri'] = './new.jpg';
|
||||
}
|
||||
|
||||
// 可选:修改 textures[0].name
|
||||
if (gltfJson['textures'] != null && gltfJson['textures'].isNotEmpty) {
|
||||
gltfJson['textures'][0]['name'] = 'new.jpg';
|
||||
}
|
||||
|
||||
// 写回更新后的内容
|
||||
final updatedContent =
|
||||
const JsonEncoder.withIndent(' ').convert(gltfJson);
|
||||
await modelFile.writeAsString(updatedContent);
|
||||
|
||||
print('GLTF文件已成功更新');
|
||||
|
||||
// 重建模型视图
|
||||
setState(() {
|
||||
_keyValue++;
|
||||
_statusMessage = "纹理已更新为 new.jpg";
|
||||
});
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('纹理已成功更新为 new.jpg')),
|
||||
);
|
||||
} else {
|
||||
print('GLTF文件不存在: $modelPath');
|
||||
setState(() {
|
||||
_statusMessage = "GLTF文件不存在";
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
print('更换纹理失败: $e');
|
||||
setState(() {
|
||||
_statusMessage = "更换纹理失败: $e";
|
||||
});
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('更换纹理失败: $e')),
|
||||
);
|
||||
} finally {
|
||||
setState(() {
|
||||
_isReplacingTexture = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 重置纹理到原始状态
|
||||
Future<void> _resetTexture() async {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => Cup(),
|
||||
// builder: (context) => CupPage(),
|
||||
),
|
||||
);
|
||||
return;
|
||||
|
||||
if (_isReplacingTexture || _texturePath == null) return;
|
||||
|
||||
setState(() {
|
||||
_isReplacingTexture = true;
|
||||
_statusMessage = "正在重置纹理...";
|
||||
});
|
||||
|
||||
try {
|
||||
// 检查备份文件是否存在
|
||||
final backupTexturePath = '${_texturePath!}.backup';
|
||||
final backupFile = File(backupTexturePath);
|
||||
|
||||
if (await backupFile.exists()) {
|
||||
// 恢复备份文件
|
||||
await backupFile.copy(_texturePath!);
|
||||
|
||||
// 给渲染器一点时间来处理文件变化
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
// 强制重建ViewerWidget以应用恢复的纹理
|
||||
setState(() {
|
||||
_keyValue++;
|
||||
_statusMessage = "纹理已重置";
|
||||
});
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('纹理已重置到原始状态')),
|
||||
);
|
||||
} else {
|
||||
setState(() {
|
||||
_statusMessage = "没有备份文件可恢复";
|
||||
});
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('没有备份文件可恢复')),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
print('重置纹理失败: $e');
|
||||
setState(() {
|
||||
_statusMessage = "重置纹理失败: $e";
|
||||
});
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('重置纹理失败: $e')),
|
||||
);
|
||||
} finally {
|
||||
setState(() {
|
||||
_isReplacingTexture = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('3D模型纹理替换'),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.texture),
|
||||
onPressed: _isReplacingTexture ? null : _pickNewTexture,
|
||||
tooltip: '更换纹理',
|
||||
),
|
||||
],
|
||||
),
|
||||
body: _isLoading
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const CircularProgressIndicator(),
|
||||
const SizedBox(height: 16),
|
||||
Text(_statusMessage),
|
||||
],
|
||||
),
|
||||
)
|
||||
: _modelPath == null
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.error, size: 48, color: Colors.red),
|
||||
const SizedBox(height: 16),
|
||||
const Text('加载模型失败'),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: _load3DModels,
|
||||
child: const Text('重试'),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: Column(
|
||||
children: [
|
||||
if (_selectedImage != null)
|
||||
Container(
|
||||
width: 300,
|
||||
height: 300,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.blue, width: 2),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: Image.file(
|
||||
_selectedImage!,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
// Expanded(
|
||||
// child: ViewerWidget(
|
||||
// key: ValueKey(_keyValue),
|
||||
// assetPath: "file://$_modelPath",
|
||||
// skyboxPath: "assets/default_env_skybox.ktx",
|
||||
// iblPath: "assets/default_env_ibl.ktx",
|
||||
// transformToUnitCube: true,
|
||||
// initialCameraPosition: Vector3(0, 0, 6),
|
||||
// background: Colors.grey[200],
|
||||
// manipulatorType: ManipulatorType.ORBIT,
|
||||
// initial: const Center(
|
||||
// child: CircularProgressIndicator(),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
color: Colors.grey[100],
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
ElevatedButton.icon(
|
||||
icon: const Icon(Icons.texture),
|
||||
label: const Text('选择纹理图片'),
|
||||
onPressed: _isReplacingTexture
|
||||
? null
|
||||
: _pickNewTexture,
|
||||
),
|
||||
ElevatedButton.icon(
|
||||
icon: const Icon(Icons.refresh),
|
||||
label: const Text('3d查看'),
|
||||
onPressed:
|
||||
_isReplacingTexture ? null : _resetTexture,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
_statusMessage,
|
||||
style: TextStyle(
|
||||
color: Colors.grey[600],
|
||||
fontStyle: FontStyle.italic,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
/*
|
||||
import 'dart:async';
|
||||
import 'package:animations/cup_page.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:flutter/material.dart' hide View;
|
||||
import 'package:thermion_flutter/thermion_flutter.dart';
|
||||
@@ -21,7 +424,7 @@ class MyApp extends StatelessWidget {
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
||||
useMaterial3: true,
|
||||
),
|
||||
home: const MyHomePage(title: 'Thermion Demo Home Page'),
|
||||
home: const CupPage(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -39,7 +442,7 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||
ThermionViewer? _thermionViewer;
|
||||
|
||||
ThermionAsset? _asset;
|
||||
final _droneUri = "assets/BusterDrone/scene.gltf";
|
||||
final _droneUri = "assets/cup/model.gltf";
|
||||
final _cubeUri = "assets/cube_with_morph_targets.glb";
|
||||
String? _loaded;
|
||||
|
||||
@@ -68,7 +471,6 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||
gltfAnimations.clear();
|
||||
gltfAnimations.addAll(labels);
|
||||
selectedGltfAnimation = 0;
|
||||
|
||||
}
|
||||
setState(() {});
|
||||
}
|
||||
@@ -165,3 +567,4 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||
]);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
284
examples/flutter/animations/lib/main1.dart
Normal file
@@ -0,0 +1,284 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:thermion_flutter/thermion_flutter.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: '3D模型纹理替换',
|
||||
theme: ThemeData(
|
||||
primarySwatch: Colors.blue,
|
||||
visualDensity: VisualDensity.adaptivePlatformDensity,
|
||||
),
|
||||
home: const ModelViewerScreen(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ModelViewerScreen extends StatefulWidget {
|
||||
const ModelViewerScreen({super.key});
|
||||
|
||||
@override
|
||||
State<ModelViewerScreen> createState() => _ModelViewerScreenState();
|
||||
}
|
||||
|
||||
class _ModelViewerScreenState extends State<ModelViewerScreen> {
|
||||
bool _isLoading = true;
|
||||
String? _modelPath;
|
||||
String? _texturePath;
|
||||
int _keyValue = 0;
|
||||
String _statusMessage = "正在加载模型...";
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadModel();
|
||||
}
|
||||
|
||||
// 加载模型文件到临时目录
|
||||
Future<void> _loadModel() async {
|
||||
try {
|
||||
setState(() {
|
||||
_statusMessage = "准备模型目录...";
|
||||
});
|
||||
|
||||
final directory = await getApplicationDocumentsDirectory();
|
||||
final modelDir = Directory('${directory.path}/model');
|
||||
|
||||
// 确保目录存在
|
||||
if (!await modelDir.exists()) {
|
||||
await modelDir.create(recursive: true);
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_statusMessage = "加载GLTF文件...";
|
||||
});
|
||||
|
||||
// 加载 .gltf 文件并写入本地
|
||||
final gltfData =
|
||||
await DefaultAssetBundle.of(context).load('assets/cup/model.gltf');
|
||||
final gltfFile = File('${modelDir.path}/model.gltf');
|
||||
await gltfFile.writeAsBytes(gltfData.buffer.asUint8List());
|
||||
|
||||
/// ✅ 打印本地路径(关键)
|
||||
print('✅ GLTF 本地路径: ${gltfFile.path}');
|
||||
print('✅ 是否存在: ${await gltfFile.exists()}');
|
||||
|
||||
setState(() {
|
||||
_statusMessage = "加载模型数据...";
|
||||
});
|
||||
|
||||
// 加载 .bin 文件并写入本地
|
||||
final binData =
|
||||
await DefaultAssetBundle.of(context).load('assets/cup/model.bin');
|
||||
final binFile = File('${modelDir.path}/model.bin');
|
||||
await binFile.writeAsBytes(binData.buffer.asUint8List());
|
||||
|
||||
setState(() {
|
||||
_statusMessage = "加载纹理...";
|
||||
});
|
||||
|
||||
// 加载纹理文件并写入本地
|
||||
final textureData =
|
||||
await DefaultAssetBundle.of(context).load('assets/cup/texture.jpg');
|
||||
final textureFile = File('${modelDir.path}/texture.jpg');
|
||||
await textureFile.writeAsBytes(textureData.buffer.asUint8List());
|
||||
|
||||
/// ✅ 打印纹理路径
|
||||
print('✅ 纹理本地路径: ${textureFile.path}');
|
||||
print('✅ 是否存在: ${await textureFile.exists()}');
|
||||
|
||||
setState(() {
|
||||
_modelPath = gltfFile.path;
|
||||
_texturePath = textureFile.path;
|
||||
_isLoading = false;
|
||||
_statusMessage = "加载完成";
|
||||
});
|
||||
} catch (e) {
|
||||
print('❌ 加载模型失败: $e');
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_statusMessage = "加载失败: $e";
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 使用FilePicker选择新纹理 - 修复配置错误
|
||||
Future<void> _pickNewTexture() async {
|
||||
try {
|
||||
setState(() {
|
||||
_statusMessage = "正在选择纹理文件...";
|
||||
});
|
||||
|
||||
// 使用FilePicker选择文件 - 修复配置
|
||||
// 选项1: 使用FileType.image(不能指定allowedExtensions)
|
||||
FilePickerResult? result = await FilePicker.platform.pickFiles(
|
||||
type: FileType.image,
|
||||
allowMultiple: false,
|
||||
);
|
||||
|
||||
// 选项2: 如果需要特定扩展名,使用FileType.custom
|
||||
/*
|
||||
FilePickerResult? result = await FilePicker.platform.pickFiles(
|
||||
type: FileType.custom,
|
||||
allowMultiple: false,
|
||||
allowedExtensions: ['jpg', 'jpeg', 'png', 'bmp', 'tga'],
|
||||
);
|
||||
*/
|
||||
|
||||
if (result != null &&
|
||||
result.files.isNotEmpty &&
|
||||
result.files.single.path != null &&
|
||||
_texturePath != null) {
|
||||
setState(() {
|
||||
_statusMessage = "正在应用新纹理...";
|
||||
});
|
||||
|
||||
// 获取选中的文件
|
||||
PlatformFile file = result.files.first;
|
||||
File newTexture = File(file.path!);
|
||||
|
||||
// 检查文件是否存在
|
||||
if (await newTexture.exists()) {
|
||||
// 复制选中的图片到纹理路径
|
||||
await newTexture.copy(_texturePath!);
|
||||
|
||||
// 强制重建ViewerWidget以应用新纹理
|
||||
setState(() {
|
||||
_keyValue++;
|
||||
_statusMessage = "纹理已更新";
|
||||
});
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('纹理已成功更新')),
|
||||
);
|
||||
} else {
|
||||
setState(() {
|
||||
_statusMessage = "文件不存在";
|
||||
});
|
||||
}
|
||||
} else {
|
||||
setState(() {
|
||||
_statusMessage = "取消选择";
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
print('更换纹理失败: $e');
|
||||
setState(() {
|
||||
_statusMessage = "更换纹理失败";
|
||||
});
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('更换纹理失败: $e')),
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('3D模型纹理替换'),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.texture),
|
||||
onPressed: _pickNewTexture,
|
||||
tooltip: '更换纹理',
|
||||
),
|
||||
],
|
||||
),
|
||||
body: _isLoading
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const CircularProgressIndicator(),
|
||||
const SizedBox(height: 16),
|
||||
Text(_statusMessage),
|
||||
],
|
||||
),
|
||||
)
|
||||
: _modelPath == null
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.error, size: 48, color: Colors.red),
|
||||
const SizedBox(height: 16),
|
||||
const Text('加载模型失败'),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: _loadModel,
|
||||
child: const Text('重试'),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ViewerWidget(
|
||||
key: ValueKey(_keyValue),
|
||||
assetPath: _modelPath!,
|
||||
skyboxPath: "assets/default_env_skybox.ktx",
|
||||
iblPath: "assets/default_env_ibl.ktx",
|
||||
transformToUnitCube: true,
|
||||
initialCameraPosition: Vector3(0, 0, 6),
|
||||
background: Colors.grey[200],
|
||||
manipulatorType: ManipulatorType.ORBIT,
|
||||
initial: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
color: Colors.grey[100],
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
ElevatedButton.icon(
|
||||
icon: const Icon(Icons.texture),
|
||||
label: const Text('选择纹理图片'),
|
||||
onPressed: _pickNewTexture,
|
||||
),
|
||||
ElevatedButton.icon(
|
||||
icon: const Icon(Icons.refresh),
|
||||
label: const Text('重置视图'),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_keyValue++;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
_statusMessage,
|
||||
style: TextStyle(
|
||||
color: Colors.grey[600],
|
||||
fontStyle: FontStyle.italic,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
190
examples/flutter/animations/lib/model_viewer.dart
Normal file
@@ -0,0 +1,190 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:thermion_flutter/thermion_flutter.dart';
|
||||
|
||||
class LocalModelViewer extends StatefulWidget {
|
||||
@override
|
||||
_LocalModelViewerState createState() => _LocalModelViewerState();
|
||||
}
|
||||
|
||||
class _LocalModelViewerState extends State<LocalModelViewer> {
|
||||
ThermionViewer? _viewer;
|
||||
ThermionAsset? _asset;
|
||||
bool _isLoading = true;
|
||||
bool _hasError = false;
|
||||
String _statusMessage = "初始化中...";
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
ThermionFlutterPlugin.createViewer().then((viewer) async {
|
||||
_viewer = viewer;
|
||||
_loadLocalModel(); // 在 viewer 初始化之后再加载模型
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _loadLocalModel() async {
|
||||
try {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
_statusMessage = "获取本地模型路径...";
|
||||
});
|
||||
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final modelDir = p.join(supportDir.path, 'cup');
|
||||
final modelPath = p.join(modelDir, 'model.gltf');
|
||||
final modelFile = File(modelPath);
|
||||
|
||||
if (await modelFile.exists()) {
|
||||
// 检查二进制文件
|
||||
final binPath = p.join(modelDir, 'model.bin');
|
||||
final binFile = File(binPath);
|
||||
if (!await binFile.exists()) {
|
||||
throw Exception("二进制文件不存在: $binPath");
|
||||
}
|
||||
|
||||
// 检查文件大小
|
||||
final binSize = await binFile.length();
|
||||
if (binSize == 0) {
|
||||
throw Exception("二进制文件为空");
|
||||
}
|
||||
|
||||
// 检查纹理文件
|
||||
final texturePath = p.join(modelDir, 'texture.jpg');
|
||||
final textureFile = File(texturePath);
|
||||
if (!await textureFile.exists()) {
|
||||
throw Exception("纹理文件不存在: $texturePath");
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_statusMessage = "读取和修改模型数据...";
|
||||
});
|
||||
|
||||
// 读取GLTF文件内容
|
||||
String gltfContent = await modelFile.readAsString();
|
||||
|
||||
// 修改纹理路径(去掉"./"前缀)
|
||||
gltfContent = gltfContent.replaceAll('"./texture.jpg"', '"new.jpg"');
|
||||
|
||||
// 转换为字节数组
|
||||
Uint8List gltfBytes = Uint8List.fromList(utf8.encode(gltfContent));
|
||||
|
||||
// 使用绝对路径作为资源URI
|
||||
final resourceUri = "file://${Directory(modelDir).absolute.path}";
|
||||
|
||||
setState(() {
|
||||
_statusMessage = "加载模型中...";
|
||||
});
|
||||
|
||||
final asset = await _viewer?.loadGltfFromBuffer(
|
||||
gltfBytes,
|
||||
resourceUri: resourceUri,
|
||||
addToScene: true,
|
||||
);
|
||||
|
||||
setState(() {
|
||||
_asset = asset;
|
||||
_isLoading = false;
|
||||
_statusMessage = "模型加载完成";
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_statusMessage = "本地模型文件不存在";
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
print('加载本地模型失败: $e');
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_hasError = true;
|
||||
_statusMessage = "加载失败: $e";
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_isLoading) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
CircularProgressIndicator(),
|
||||
SizedBox(height: 16),
|
||||
Text(_statusMessage),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (_hasError || _viewer == null) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.error_outline, color: Colors.red, size: 48),
|
||||
SizedBox(height: 16),
|
||||
Text("加载3D模型失败"),
|
||||
Text(_statusMessage, style: TextStyle(color: Colors.red)),
|
||||
SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: _loadLocalModel,
|
||||
child: Text("重试"),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('本地模型查看'),
|
||||
),
|
||||
body: ThermionListenerWidget(
|
||||
inputHandler: DelegateInputHandler.fixedOrbit(_viewer!),
|
||||
child: ThermionWidget(
|
||||
viewer: _viewer!,
|
||||
showFpsCounter: true, // 可选:显示FPS计数器
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// 使用ThermionWidget显示3D内容
|
||||
return ThermionListenerWidget(
|
||||
inputHandler: DelegateInputHandler.fixedOrbit(_viewer!),
|
||||
child: ThermionWidget(
|
||||
viewer: _viewer!,
|
||||
showFpsCounter: true, // 可选:显示FPS计数器
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> deleteModelFile() async {
|
||||
// 获取应用支持目录
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
|
||||
// 构建 model.gltf 的完整路径
|
||||
final modelFile = File(p.join(supportDir.path, 'cup', 'model.gltf'));
|
||||
|
||||
// 检查文件是否存在,然后删除
|
||||
if (await modelFile.exists()) {
|
||||
await modelFile.delete();
|
||||
print('model.gltf 已删除');
|
||||
} else {
|
||||
print('model.gltf 文件不存在');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// deleteModelFile();
|
||||
// 清理资源
|
||||
_viewer?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
405
examples/flutter/animations/lib/utils/binary_manager.dart
Normal file
@@ -0,0 +1,405 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
class BinaryManager {
|
||||
/// 当前应用版本(用于初始化检查)
|
||||
static String? _currentVersion;
|
||||
|
||||
/// 获取当前应用版本
|
||||
static Future<String> _getCurrentVersion() async {
|
||||
if (_currentVersion == null) {
|
||||
final packageInfo = await PackageInfo.fromPlatform();
|
||||
_currentVersion = '${packageInfo.version}+${packageInfo.buildNumber}';
|
||||
}
|
||||
return _currentVersion!;
|
||||
}
|
||||
|
||||
/// 检查是否已完成初始化(基于版本号)
|
||||
static Future<bool> isInitialized() async {
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final currentVersion = await _getCurrentVersion();
|
||||
final initMarker = File(
|
||||
p.join(supportDir.path, '.initialized_$currentVersion'),
|
||||
);
|
||||
|
||||
return await initMarker.exists();
|
||||
}
|
||||
|
||||
/// 标记初始化完成(文件名包含版本号)
|
||||
static Future<void> markInitialized() async {
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final currentVersion = await _getCurrentVersion();
|
||||
final initMarker = File(
|
||||
p.join(supportDir.path, '.initialized_$currentVersion'),
|
||||
);
|
||||
await initMarker.writeAsString('${DateTime.now().toIso8601String()}\n');
|
||||
}
|
||||
|
||||
/// 从assets目录提取文件到指定路径
|
||||
static Future<void> _extractAsset(String assetPath, String localPath) async {
|
||||
final localFile = File(localPath);
|
||||
|
||||
try {
|
||||
// 从assets中读取数据
|
||||
final ByteData data = await rootBundle.load(assetPath);
|
||||
final List<int> bytes = data.buffer.asUint8List();
|
||||
|
||||
// 确保目录存在
|
||||
final dir = Directory(p.dirname(localPath));
|
||||
if (!await dir.exists()) {
|
||||
await dir.create(recursive: true);
|
||||
}
|
||||
|
||||
// 写入本地文件
|
||||
await localFile.writeAsBytes(bytes);
|
||||
print('成功提取文件: $assetPath -> $localPath');
|
||||
} catch (e) {
|
||||
print('提取资源文件失败 $assetPath: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
/// 初始化应用程序资源 - 将所有必要的assets迁移到系统文件夹
|
||||
static Future<void> initializeAppResources() async {
|
||||
final currentVersion = await _getCurrentVersion();
|
||||
|
||||
if (await isInitialized()) {
|
||||
print('应用程序资源已初始化,当前版本: $currentVersion');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 迁移shell脚本
|
||||
await _migrateShellScript();
|
||||
|
||||
// 迁移二进制文件
|
||||
await _migrateBinaries();
|
||||
|
||||
// 迁移模型文件
|
||||
await _migrateModels();
|
||||
|
||||
// 迁移3D模型文件
|
||||
await migrate3DModels();
|
||||
|
||||
// 标记初始化完成
|
||||
await markInitialized();
|
||||
|
||||
print('应用程序资源初始化完成');
|
||||
} catch (e) {
|
||||
print('应用程序资源初始化失败: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
/// 迁移3D模型文件
|
||||
static Future<void> migrate3DModels() async {
|
||||
print('开始迁移3D模型文件...');
|
||||
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final models3dDir = Directory(p.join(supportDir.path, 'cup'));
|
||||
|
||||
// 创建3D模型目录
|
||||
if (!await models3dDir.exists()) {
|
||||
await models3dDir.create(recursive: true);
|
||||
}
|
||||
|
||||
// 3D模型文件列表
|
||||
final model3dFiles = ['model.gltf', 'model.bin', 'texture.jpg'];
|
||||
|
||||
// 迁移所有3D模型文件
|
||||
for (final modelFile in model3dFiles) {
|
||||
try {
|
||||
// if (modelFile == 'model.gltf') {
|
||||
// // 对于GLTF文件,我们需要修改内容
|
||||
// await _extractAndModifyGltfAsset(
|
||||
// 'assets/cup/$modelFile',
|
||||
// p.join(models3dDir.path, modelFile),
|
||||
// );
|
||||
// } else {
|
||||
// 对于其他文件,直接复制
|
||||
await _extractAsset(
|
||||
'assets/cup/$modelFile',
|
||||
p.join(models3dDir.path, modelFile),
|
||||
);
|
||||
// }
|
||||
} catch (e) {
|
||||
print('迁移3D模型文件失败 $modelFile: $e');
|
||||
// 继续迁移其他模型文件
|
||||
}
|
||||
}
|
||||
|
||||
print('3D模型文件迁移完成');
|
||||
}
|
||||
|
||||
static Future<void> _extractAndModifyGltfAsset(
|
||||
String assetPath, String targetPath) async {
|
||||
try {
|
||||
// 读取资源文件内容
|
||||
final byteData = await rootBundle.load(assetPath);
|
||||
final buffer = byteData.buffer;
|
||||
final gltfContent = utf8.decode(
|
||||
buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
|
||||
|
||||
// 修改纹理路径(去掉"./"前缀)
|
||||
final modifiedGltfContent =
|
||||
gltfContent.replaceAll('"./texture.jpg"', '"texture.jpg"');
|
||||
|
||||
// 写入修改后的内容到目标文件
|
||||
final file = File(targetPath);
|
||||
await file.writeAsBytes(utf8.encode(modifiedGltfContent));
|
||||
|
||||
print('已修改并迁移: $assetPath -> $targetPath');
|
||||
} catch (e) {
|
||||
print('提取并修改GLTF资源失败: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> _migrateShellScript() async {
|
||||
print('开始迁移脚本文件...');
|
||||
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
|
||||
// 迁移 Shell 脚本 (macOS/Linux)
|
||||
final shellScriptPath = p.join(supportDir.path, 'upscale_to_8k_single.sh');
|
||||
await _extractAsset('assets/upscale_to_8k_single.sh', shellScriptPath);
|
||||
|
||||
// 设置脚本执行权限(仅限 macOS/Linux)
|
||||
if (Platform.isMacOS || Platform.isLinux) {
|
||||
try {
|
||||
final result = await Process.run('chmod', ['+x', shellScriptPath]);
|
||||
if (result.exitCode == 0) {
|
||||
print('成功设置Shell脚本执行权限: $shellScriptPath');
|
||||
} else {
|
||||
print('设置Shell脚本执行权限失败: ${result.stderr}');
|
||||
}
|
||||
} catch (e) {
|
||||
print('设置Shell脚本权限异常: $e');
|
||||
}
|
||||
}
|
||||
|
||||
print('脚本文件迁移完成');
|
||||
}
|
||||
|
||||
/// 迁移二进制文件
|
||||
static Future<void> _migrateBinaries() async {
|
||||
print('开始迁移二进制文件...');
|
||||
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final binDir = Directory(p.join(supportDir.path, 'bin'));
|
||||
|
||||
// 创建bin目录
|
||||
if (!await binDir.exists()) {
|
||||
await binDir.create(recursive: true);
|
||||
}
|
||||
|
||||
// macOS 二进制文件
|
||||
final macBinDir = Directory(p.join(binDir.path, 'macos'));
|
||||
if (!await macBinDir.exists()) {
|
||||
await macBinDir.create(recursive: true);
|
||||
}
|
||||
|
||||
await _extractAsset(
|
||||
'assets/bin/mac/upscayl-bin',
|
||||
p.join(macBinDir.path, 'upscayl-bin'),
|
||||
);
|
||||
|
||||
// Windows 二进制文件
|
||||
final winBinDir = Directory(p.join(binDir.path, 'windows'));
|
||||
if (!await winBinDir.exists()) {
|
||||
await winBinDir.create(recursive: true);
|
||||
}
|
||||
|
||||
await _extractAsset(
|
||||
'assets/bin/windows/upscayl-bin.exe',
|
||||
p.join(winBinDir.path, 'upscayl-bin.exe'),
|
||||
);
|
||||
|
||||
await _extractAsset(
|
||||
'assets/bin/windows/vcomp140.dll',
|
||||
p.join(winBinDir.path, 'vcomp140.dll'),
|
||||
);
|
||||
|
||||
await _extractAsset(
|
||||
'assets/bin/windows/vcomp140d.dll',
|
||||
p.join(winBinDir.path, 'vcomp140d.dll'),
|
||||
);
|
||||
|
||||
// 设置 macOS/Linux 二进制文件执行权限
|
||||
if (Platform.isMacOS || Platform.isLinux) {
|
||||
final binPath = p.join(macBinDir.path, 'upscayl-bin');
|
||||
try {
|
||||
final result = await Process.run('chmod', ['+x', binPath]);
|
||||
if (result.exitCode == 0) {
|
||||
print('成功设置执行权限: $binPath');
|
||||
} else {
|
||||
print('设置执行权限失败: ${result.stderr}');
|
||||
}
|
||||
} catch (e) {
|
||||
print('设置权限异常: $e');
|
||||
}
|
||||
}
|
||||
|
||||
print('二进制文件迁移完成');
|
||||
}
|
||||
|
||||
/// 迁移模型文件
|
||||
static Future<void> _migrateModels() async {
|
||||
print('开始迁移模型文件...');
|
||||
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final modelsDir = Directory(p.join(supportDir.path, 'models'));
|
||||
|
||||
// 创建models目录
|
||||
if (!await modelsDir.exists()) {
|
||||
await modelsDir.create(recursive: true);
|
||||
}
|
||||
|
||||
// 模型文件列表
|
||||
final modelFiles = [
|
||||
'high-fidelity-4x.bin',
|
||||
'high-fidelity-4x.param',
|
||||
'digital-art-4x.bin',
|
||||
'digital-art-4x.param',
|
||||
'remacri-4x.bin',
|
||||
'remacri-4x.param',
|
||||
'ultrasharp-4x.bin',
|
||||
'ultrasharp-4x.param',
|
||||
'upscayl-standard-4x.bin',
|
||||
'upscayl-standard-4x.param',
|
||||
'ultramix-balanced-4x.bin',
|
||||
'ultramix-balanced-4x.param',
|
||||
'upscayl-lite-4x.bin',
|
||||
'upscayl-lite-4x.param',
|
||||
];
|
||||
|
||||
// 迁移所有模型文件
|
||||
for (final modelFile in modelFiles) {
|
||||
try {
|
||||
await _extractAsset(
|
||||
'assets/models/$modelFile',
|
||||
p.join(modelsDir.path, modelFile),
|
||||
);
|
||||
} catch (e) {
|
||||
print('迁移模型文件失败 $modelFile: $e');
|
||||
// 继续迁移其他模型文件
|
||||
}
|
||||
}
|
||||
|
||||
print('模型文件迁移完成');
|
||||
}
|
||||
|
||||
/// 获取模型文件目录路径
|
||||
static Future<String> getModelsPath() async {
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
return p.join(supportDir.path, 'cup', "model.gltf");
|
||||
}
|
||||
|
||||
/// 获取3D模型文件目录路径
|
||||
static Future<String> get3DModelsPath() async {
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
return p.join(supportDir.path, 'cup');
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> readLocalJson() async {
|
||||
// 获取应用支持目录(默认在 ~/Library/Application Support/)
|
||||
final appSupportDir = await getApplicationSupportDirectory();
|
||||
final targetDir = Directory('${appSupportDir.path}/cup');
|
||||
|
||||
// 检查目录是否存在,若不存在则创建
|
||||
if (!await targetDir.exists()) {
|
||||
await targetDir.create(recursive: true);
|
||||
}
|
||||
print('file=${targetDir.path}/model.gltf');
|
||||
// 构建 JSON 文件路径
|
||||
final file = File('${targetDir.path}/model.gltf');
|
||||
|
||||
if (await file.exists()) {
|
||||
final content = await file.readAsString();
|
||||
return jsonDecode(content);
|
||||
} else {
|
||||
throw Exception('JSON 文件不存在');
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取特定的3D模型文件路径
|
||||
static Future<String> get3DModelPath(String filename) async {
|
||||
final models3dPath = await get3DModelsPath();
|
||||
return p.join(models3dPath, filename);
|
||||
}
|
||||
|
||||
/// 获取脚本文件路径 (仅适用于macOS/Linux)
|
||||
static Future<String> getScriptPath() async {
|
||||
if (Platform.isWindows) {
|
||||
throw UnsupportedError('Windows平台已使用专门的UpscaleWindowsService,不再需要脚本文件');
|
||||
}
|
||||
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final scriptName = 'upscale_to_8k_single.sh';
|
||||
final scriptPath = p.join(supportDir.path, scriptName);
|
||||
final scriptFile = File(scriptPath);
|
||||
|
||||
if (!await scriptFile.exists()) {
|
||||
throw FileSystemException(
|
||||
'脚本文件不存在: $scriptPath\n请确保应用程序已正确初始化资源',
|
||||
scriptPath,
|
||||
);
|
||||
}
|
||||
|
||||
return scriptPath;
|
||||
}
|
||||
|
||||
/// 获取二进制文件路径
|
||||
static Future<String> getBinaryPath() async {
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
|
||||
String platformDir;
|
||||
String binaryName;
|
||||
|
||||
if (Platform.isMacOS) {
|
||||
platformDir = 'macos';
|
||||
binaryName = 'upscayl-bin';
|
||||
} else if (Platform.isWindows) {
|
||||
platformDir = 'windows';
|
||||
binaryName = 'upscayl-bin.exe';
|
||||
} else if (Platform.isLinux) {
|
||||
platformDir = 'macos'; // Linux 使用 macOS 的二进制文件
|
||||
binaryName = 'upscayl-bin';
|
||||
} else {
|
||||
throw UnsupportedError('不支持的操作系统: ${Platform.operatingSystem}');
|
||||
}
|
||||
|
||||
final binPath = p.join(supportDir.path, 'bin', platformDir, binaryName);
|
||||
|
||||
// 检查文件是否存在
|
||||
final binFile = File(binPath);
|
||||
if (!await binFile.exists()) {
|
||||
throw FileSystemException('二进制文件不存在: $binPath\n请确保应用程序已正确初始化资源', binPath);
|
||||
}
|
||||
|
||||
return binPath;
|
||||
}
|
||||
|
||||
/// 设置脚本执行权限
|
||||
static Future<void> setScriptExecutable(String scriptPath) async {
|
||||
// 设置脚本执行权限(仅限 macOS/Linux)
|
||||
if (Platform.isMacOS || Platform.isLinux) {
|
||||
try {
|
||||
final result = await Process.run('chmod', ['+x', scriptPath]);
|
||||
if (result.exitCode == 0) {
|
||||
print('成功设置脚本执行权限: $scriptPath');
|
||||
} else {
|
||||
print('设置脚本执行权限失败: ${result.stderr}');
|
||||
}
|
||||
} catch (e) {
|
||||
print('设置脚本权限异常: $e');
|
||||
}
|
||||
}
|
||||
// Windows 不需要设置执行权限
|
||||
}
|
||||
}
|
||||
204
examples/flutter/animations/lib/utils/model_manager.dart
Normal file
@@ -0,0 +1,204 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
class ModelManager {
|
||||
/// 当前应用版本(用于初始化检查)
|
||||
static String? _currentVersion;
|
||||
|
||||
/// 获取当前应用版本
|
||||
static Future<String> _getCurrentVersion() async {
|
||||
if (_currentVersion == null) {
|
||||
final packageInfo = await PackageInfo.fromPlatform();
|
||||
_currentVersion = '${packageInfo.version}+${packageInfo.buildNumber}';
|
||||
}
|
||||
return _currentVersion!;
|
||||
}
|
||||
|
||||
/// 检查3D模型资源是否已完成初始化(基于版本号)
|
||||
static Future<bool> isInitialized() async {
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final currentVersion = await _getCurrentVersion();
|
||||
final initMarker = File(
|
||||
p.join(supportDir.path, '3d_models', '.initialized_$currentVersion'),
|
||||
);
|
||||
|
||||
return await initMarker.exists();
|
||||
}
|
||||
|
||||
/// 标记3D模型资源初始化完成
|
||||
static Future<void> markInitialized() async {
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final currentVersion = await _getCurrentVersion();
|
||||
final modelsDir = Directory(p.join(supportDir.path, '3d_models'));
|
||||
|
||||
if (!await modelsDir.exists()) {
|
||||
await modelsDir.create(recursive: true);
|
||||
}
|
||||
|
||||
final initMarker = File(
|
||||
p.join(modelsDir.path, '.initialized_$currentVersion'),
|
||||
);
|
||||
await initMarker.writeAsString('${DateTime.now().toIso8601String()}\n');
|
||||
}
|
||||
|
||||
/// 从assets目录提取文件到指定路径
|
||||
static Future<void> _extractAsset(String assetPath, String localPath) async {
|
||||
final localFile = File(localPath);
|
||||
final localDir = Directory(p.dirname(localPath));
|
||||
|
||||
// 确保目录存在
|
||||
if (!await localDir.exists()) {
|
||||
await localDir.create(recursive: true);
|
||||
}
|
||||
|
||||
try {
|
||||
// 从assets中读取数据
|
||||
final ByteData data = await rootBundle.load(assetPath);
|
||||
final List<int> bytes = data.buffer.asUint8List();
|
||||
|
||||
// 写入本地文件
|
||||
await localFile.writeAsBytes(bytes);
|
||||
print('成功提取3D模型文件: $assetPath -> $localPath');
|
||||
} catch (e) {
|
||||
print('提取3D模型资源文件失败 $assetPath: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
/// 初始化3D模型资源
|
||||
static Future<void> initializeAppResources() async {
|
||||
final currentVersion = await _getCurrentVersion();
|
||||
|
||||
if (await isInitialized()) {
|
||||
print('3D模型资源已初始化,当前版本: $currentVersion');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 迁移模型文件
|
||||
await _migrateModels();
|
||||
|
||||
// 标记初始化完成
|
||||
await markInitialized();
|
||||
|
||||
print('3D模型资源初始化完成');
|
||||
} catch (e) {
|
||||
print('3D模型资源初始化失败: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
/// 迁移3D模型文件
|
||||
/// 迁移3D模型文件
|
||||
static Future<void> _migrateModels() async {
|
||||
print('开始迁移3D模型文件...');
|
||||
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final modelsDir = Directory(p.join(supportDir.path, 'models'));
|
||||
|
||||
// 创建3D模型目录
|
||||
if (!await modelsDir.exists()) {
|
||||
await modelsDir.create(recursive: true);
|
||||
}
|
||||
|
||||
// 创建cup子目录
|
||||
final cupDir = Directory(p.join(modelsDir.path, 'cup'));
|
||||
if (!await cupDir.exists()) {
|
||||
await cupDir.create(recursive: true);
|
||||
}
|
||||
|
||||
// 3D模型文件列表 - 修正路径
|
||||
final modelFiles = [
|
||||
'cup/model.gltf',
|
||||
'cup/model.bin',
|
||||
'cup/texture.jpg',
|
||||
];
|
||||
|
||||
// 迁移所有3D模型文件
|
||||
for (final modelFile in modelFiles) {
|
||||
try {
|
||||
// 确保源文件路径正确
|
||||
final assetPath = 'assets/$modelFile';
|
||||
|
||||
// 检查资源是否存在
|
||||
try {
|
||||
await rootBundle.load(assetPath);
|
||||
} catch (e) {
|
||||
print('资源文件不存在: $assetPath');
|
||||
continue;
|
||||
}
|
||||
|
||||
await _extractAsset(
|
||||
assetPath,
|
||||
p.join(modelsDir.path, modelFile),
|
||||
);
|
||||
} catch (e) {
|
||||
print('迁移3D模型文件失败 $modelFile: $e');
|
||||
// 继续迁移其他模型文件
|
||||
}
|
||||
}
|
||||
|
||||
print('3D模型文件迁移完成');
|
||||
}
|
||||
|
||||
/// 获取3D模型文件目录路径
|
||||
static Future<String> getModelsPath() async {
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
return p.join(supportDir.path, 'models/cup/');
|
||||
}
|
||||
|
||||
/// 获取特定3D模型文件的路径
|
||||
static Future<String> getModelFilePath(String relativePath) async {
|
||||
final modelsPath = await getModelsPath();
|
||||
final filePath = p.join(modelsPath, relativePath);
|
||||
final file = File(filePath);
|
||||
|
||||
if (!await file.exists()) {
|
||||
throw FileSystemException(
|
||||
'3D模型文件不存在: $filePath\n请确保应用程序已正确初始化3D模型资源',
|
||||
filePath,
|
||||
);
|
||||
}
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
/// 获取GLTF模型文件路径
|
||||
static Future<String> getGltfModelPath() async {
|
||||
return getModelFilePath('cup/model.gltf');
|
||||
}
|
||||
|
||||
/// 获取BIN模型文件路径
|
||||
static Future<String> getBinModelPath() async {
|
||||
return getModelFilePath('cup/model.bin');
|
||||
}
|
||||
|
||||
/// 获取纹理文件路径
|
||||
static Future<String> getTexturePath() async {
|
||||
return getModelFilePath('cup/texture.jpg');
|
||||
}
|
||||
|
||||
/// 更新纹理文件
|
||||
static Future<void> updateTexture(File newTextureFile) async {
|
||||
try {
|
||||
final texturePath = await getTexturePath();
|
||||
final textureFile = File(texturePath);
|
||||
|
||||
// 删除旧纹理文件
|
||||
if (await textureFile.exists()) {
|
||||
await textureFile.delete();
|
||||
}
|
||||
|
||||
// 复制新纹理文件
|
||||
await newTextureFile.copy(texturePath);
|
||||
print('纹理文件更新成功: $texturePath');
|
||||
} catch (e) {
|
||||
print('更新纹理文件失败: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,14 @@
|
||||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import file_picker
|
||||
import package_info_plus
|
||||
import path_provider_foundation
|
||||
import thermion_flutter
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin"))
|
||||
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
SwiftThermionFlutterPlugin.register(with: registry.registrar(forPlugin: "SwiftThermionFlutterPlugin"))
|
||||
}
|
||||
|
||||
@@ -1,22 +1,41 @@
|
||||
PODS:
|
||||
- file_picker (0.0.1):
|
||||
- FlutterMacOS
|
||||
- FlutterMacOS (1.0.0)
|
||||
- package_info_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- thermion_flutter (0.0.1):
|
||||
- FlutterMacOS
|
||||
|
||||
DEPENDENCIES:
|
||||
- file_picker (from `Flutter/ephemeral/.symlinks/plugins/file_picker/macos`)
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
|
||||
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- thermion_flutter (from `Flutter/ephemeral/.symlinks/plugins/thermion_flutter/macos`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
file_picker:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/file_picker/macos
|
||||
FlutterMacOS:
|
||||
:path: Flutter/ephemeral
|
||||
package_info_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos
|
||||
path_provider_foundation:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
|
||||
thermion_flutter:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/thermion_flutter/macos
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a
|
||||
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
|
||||
thermion_flutter: debb51a861788780ce40e11e4400c2e5a8681fdf
|
||||
package_info_plus: a8a591e70e87ce97ce5d21b2594f69cea9e0312f
|
||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||
thermion_flutter: d5d52ef933321eedbee6c4ddda4259c8cbcc84ed
|
||||
|
||||
PODFILE CHECKSUM: 1888651be91a8ad58692c1add9ce24279fd4e950
|
||||
|
||||
COCOAPODS: 1.15.2
|
||||
COCOAPODS: 1.16.2
|
||||
|
||||
@@ -3,9 +3,19 @@
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<false/>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.downloads.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.pictures.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.bookmarks.app-scope</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<true/>
|
||||
</dict>
|
||||
|
||||
@@ -3,6 +3,20 @@
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<false/>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.downloads.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.pictures.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.bookmarks.app-scope</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -16,6 +16,12 @@ dependencies:
|
||||
win32: 5.5.1
|
||||
web: 1.0.0
|
||||
thermion_flutter: ^0.2.1-dev.9
|
||||
file_picker: ^8.3.2
|
||||
path_provider: ^2.1.5
|
||||
package_info_plus: ^8.0.2
|
||||
path: ^1.8.0
|
||||
|
||||
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
@@ -40,3 +46,9 @@ flutter:
|
||||
- assets/
|
||||
- assets/BusterDrone/
|
||||
- assets/BusterDrone/textures/
|
||||
- assets/cup/
|
||||
- assets/image/
|
||||
- assets/bin/mac/
|
||||
- assets/bin/windows/
|
||||
- assets/models/
|
||||
- assets/upscale_to_8k_single.sh
|
||||
103
examples/flutter/camera_manipulation/lib/main.dart
Normal file
@@ -0,0 +1,103 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:thermion_flutter/thermion_flutter.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const MyApp());
|
||||
Logger.root.onRecord.listen((record) {
|
||||
print(record);
|
||||
});
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'Thermion Demo',
|
||||
theme: ThemeData(
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
||||
useMaterial3: true,
|
||||
),
|
||||
home: const MyHomePage(title: 'Thermion 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> {
|
||||
|
||||
late DelegateInputHandler _fixedOrbitInputHandler;
|
||||
late DelegateInputHandler _freeFlightInputHandler;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
_thermionViewer = await ThermionFlutterPlugin.createViewer();
|
||||
var assetData = await rootBundle.load("assets/cube.glb");
|
||||
var asset =
|
||||
await _thermionViewer!.loadGltfFromBuffer(assetData.buffer.asUint8List(assetData.offsetInBytes), keepData: true, loadResourcesAsync: true);
|
||||
await _thermionViewer!.loadSkybox("assets/default_env_skybox.ktx");
|
||||
await _thermionViewer!.loadIbl("assets/default_env_ibl.ktx");
|
||||
await _thermionViewer!.setPostProcessing(true);
|
||||
await _thermionViewer!.setRendering(true);
|
||||
|
||||
_fixedOrbitInputHandler =
|
||||
DelegateInputHandler.fixedOrbit(_thermionViewer!)
|
||||
..setActionForType(InputType.MMB_HOLD_AND_MOVE, InputAction.ROTATE)
|
||||
..setActionForType(InputType.SCALE1, InputAction.ROTATE)
|
||||
..setActionForType(InputType.SCALE2, InputAction.ZOOM)
|
||||
..setActionForType(InputType.SCROLLWHEEL, InputAction.ZOOM);
|
||||
|
||||
_freeFlightInputHandler =
|
||||
DelegateInputHandler.flight(_thermionViewer!)
|
||||
..setActionForType(InputType.MMB_HOLD_AND_MOVE, InputAction.ROTATE)
|
||||
..setActionForType(InputType.SCALE1, InputAction.ROTATE)
|
||||
..setActionForType(InputType.SCALE2, InputAction.ZOOM)
|
||||
..setActionForType(InputType.SCROLLWHEEL, InputAction.ZOOM);
|
||||
|
||||
setState(() {});
|
||||
});
|
||||
}
|
||||
|
||||
ThermionViewer? _thermionViewer;
|
||||
|
||||
bool isOrbit = true;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(children: [
|
||||
if (_thermionViewer != null) ...[
|
||||
Positioned.fill(
|
||||
child: ThermionListenerWidget(
|
||||
inputHandler: isOrbit
|
||||
? _fixedOrbitInputHandler : _freeFlightInputHandler,
|
||||
child:ThermionWidget(
|
||||
viewer: _thermionViewer!,
|
||||
))),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
isOrbit = !isOrbit;
|
||||
setState(() {});
|
||||
},
|
||||
child: Text("Switch to ${isOrbit ? "Free Flight" : "Orbit"}"))
|
||||
],
|
||||
)
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -108,10 +108,13 @@ fragment {
|
||||
1.0
|
||||
);
|
||||
|
||||
color.rgb = (axes.x < 1e-8) ? color.rgb : AXIS_COLOR_X;
|
||||
color.rgb = (axes.z < 1e-8) ? color.rgb : AXIS_COLOR_Z;
|
||||
|
||||
material.baseColor = color * gridAlpha;
|
||||
|
||||
if(axes.x > 1e-8) {
|
||||
material.baseColor = vec4(AXIS_COLOR_X, 1.0);
|
||||
} else if(axes.z > 1e-8) {
|
||||
material.baseColor = vec4(AXIS_COLOR_Z, 1.0);
|
||||
} else {
|
||||
material.baseColor = color * gridAlpha;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
name: thermion_workspace
|
||||
packages:
|
||||
- thermion_dart
|
||||
- thermion_flutter/**
|
||||
- thermion_flutter/thermion_flutter_platform_interface
|
||||
- thermion_flutter/thermion_flutter_method_channel
|
||||
- thermion_flutter/thermion_flutter_web
|
||||
- thermion_flutter/thermion_flutter
|
||||
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
## 0.3.3
|
||||
|
||||
- Bump "thermion_dart" to `0.3.3`.
|
||||
|
||||
## 0.3.3-pre
|
||||
|
||||
- **FIX**: fix Windows build.dart.
|
||||
- **FIX**: add nan/negative checks inside setLensProjection.
|
||||
|
||||
## 0.3.2
|
||||
|
||||
- Bump "thermion_dart" to `0.3.2`.
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:archive/archive.dart';
|
||||
import 'package:code_assets/code_assets.dart';
|
||||
import 'package:hooks/hooks.dart';
|
||||
import 'package:native_toolchain_c/native_toolchain_c.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
import 'package:native_toolchain_c/native_toolchain_c.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
void main(List<String> args) async {
|
||||
@@ -130,7 +131,7 @@ void main(List<String> args) async {
|
||||
|
||||
var frameworks = [];
|
||||
|
||||
if (platform != "windows") {
|
||||
if (targetOS != OS.windows) {
|
||||
flags.addAll(['-std=c++17']);
|
||||
} else {
|
||||
defines["WIN32"] = "1";
|
||||
@@ -193,7 +194,7 @@ void main(List<String> args) async {
|
||||
name: packageName,
|
||||
language: Language.cpp,
|
||||
assetName: 'thermion_dart.dart',
|
||||
sources: platform == "windows" ? [] : sources,
|
||||
sources: targetOS == OS.windows ? [] : sources,
|
||||
includes: platform == "windows"
|
||||
? []
|
||||
: ['native/include', 'native/include/filament'],
|
||||
@@ -219,12 +220,12 @@ void main(List<String> args) async {
|
||||
"/I${path.join(pkgRootFilePath, "native", "include", "windows", "vulkan")}",
|
||||
"@${srcs.uri.toFilePath(windows: true)}",
|
||||
// ...sources,
|
||||
'/link',
|
||||
"/LIBPATH:$libDir",
|
||||
'/DLL',
|
||||
// '/link',
|
||||
// "/LIBPATH:$libDir",
|
||||
// '/DLL',
|
||||
]
|
||||
],
|
||||
dartBuildFiles: ['hook/build.dart'],
|
||||
libraryDirectories: [libDir],
|
||||
);
|
||||
|
||||
await cbuilder.run(
|
||||
|
||||
@@ -5,11 +5,10 @@ import '../../../utils/src/matrix.dart';
|
||||
|
||||
class FFICamera extends Camera<Pointer<TCamera>> {
|
||||
final Pointer<TCamera> camera;
|
||||
|
||||
|
||||
@override
|
||||
Pointer<TCamera> getNativeHandle() {
|
||||
return camera;
|
||||
|
||||
}
|
||||
|
||||
final FFIFilamentApp app;
|
||||
@@ -92,6 +91,16 @@ class FFICamera extends Camera<Pointer<TCamera>> {
|
||||
double far = kFar,
|
||||
double aspect = 1.0,
|
||||
double focalLength = kFocalLength}) async {
|
||||
if (near.isNaN ||
|
||||
far.isNaN ||
|
||||
aspect.isNaN ||
|
||||
focalLength.isNaN ||
|
||||
near.isNegative ||
|
||||
far.isNegative ||
|
||||
aspect.isNegative ||
|
||||
focalLength.isNegative) {
|
||||
throw FormatException();
|
||||
}
|
||||
Camera_setLensProjection(camera, near, far, aspect, focalLength);
|
||||
}
|
||||
|
||||
|
||||
@@ -344,13 +344,14 @@ abstract class ThermionViewer {
|
||||
int getCameraCount();
|
||||
|
||||
///
|
||||
/// Adds the asset to the scene, meaning the asset will be rendered/visible.
|
||||
/// Adds the asset to the scene. All renderable entities attached to
|
||||
/// the asset will be visible.
|
||||
///
|
||||
Future addToScene(covariant ThermionAsset asset);
|
||||
|
||||
///
|
||||
/// Removes the asset from the scene, meaning the asset will not be rendered/visible.
|
||||
/// The asset itself will remain valid.
|
||||
/// Removes the asset from the scene. None of the renderable entities
|
||||
/// attached to the asset will be visible, but the asset itself remains valid.
|
||||
///
|
||||
Future removeFromScene(covariant ThermionAsset asset);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#pragma comment(lib, "dracodec.lib")
|
||||
#pragma comment(lib, "ibl.lib")
|
||||
#pragma comment(lib, "ktxreader.lib")
|
||||
#pragma comment(lib, "png.lib")
|
||||
#pragma comment(lib, "z.lib")
|
||||
#pragma comment(lib, "stb.lib")
|
||||
#pragma comment(lib, "uberzlib.lib")
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "ThermionWin32.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace thermion {
|
||||
extern "C"
|
||||
@@ -16,35 +20,35 @@ enum TProjection {
|
||||
typedef enum TProjection TProjection;
|
||||
|
||||
// Camera methods
|
||||
void Camera_setExposure(TCamera *camera, float aperture, float shutterSpeed, float sensitivity);
|
||||
double4x4 Camera_getModelMatrix(TCamera *const camera);
|
||||
double4x4 Camera_getViewMatrix(TCamera *const camera);
|
||||
double4x4 Camera_getProjectionMatrix(TCamera *const camera);
|
||||
double4x4 Camera_getCullingProjectionMatrix(TCamera *const camera);
|
||||
void Camera_getFrustum(TCamera *camera, double* out);
|
||||
void Camera_setProjectionMatrix(TCamera *camera, double *matrix, double near, double far);
|
||||
void Camera_setProjectionFromFov(TCamera *camera, double fovInDegrees, double aspect, double near, double far, bool horizontal);
|
||||
double Camera_getFocalLength(TCamera *const camera);
|
||||
double4x4 Camera_getViewMatrix(TCamera *const camera);
|
||||
double4x4 Camera_getModelMatrix(TCamera* camera);
|
||||
void Camera_lookAt(TCamera* camera, double3 eye, double3 focus, double3 up);
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setExposure(TCamera *camera, float aperture, float shutterSpeed, float sensitivity);
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getModelMatrix(TCamera *const camera);
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getViewMatrix(TCamera *const camera);
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getProjectionMatrix(TCamera *const camera);
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getCullingProjectionMatrix(TCamera *const camera);
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_getFrustum(TCamera *camera, double* out);
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setProjectionMatrix(TCamera *camera, double *matrix, double near, double far);
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setProjectionFromFov(TCamera *camera, double fovInDegrees, double aspect, double near, double far, bool horizontal);
|
||||
EMSCRIPTEN_KEEPALIVE double Camera_getFocalLength(TCamera *const camera);
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getViewMatrix(TCamera *const camera);
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getModelMatrix(TCamera* camera);
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_lookAt(TCamera* camera, double3 eye, double3 focus, double3 up);
|
||||
|
||||
double Camera_getNear(TCamera *camera);
|
||||
double Camera_getCullingFar(TCamera *camera);
|
||||
float Camera_getFov(TCamera *camera, bool horizontal);
|
||||
double Camera_getFocusDistance(TCamera *camera);
|
||||
void Camera_setFocusDistance(TCamera *camera, float focusDistance);
|
||||
EMSCRIPTEN_KEEPALIVE double Camera_getNear(TCamera *camera);
|
||||
EMSCRIPTEN_KEEPALIVE double Camera_getCullingFar(TCamera *camera);
|
||||
EMSCRIPTEN_KEEPALIVE float Camera_getFov(TCamera *camera, bool horizontal);
|
||||
EMSCRIPTEN_KEEPALIVE double Camera_getFocusDistance(TCamera *camera);
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setFocusDistance(TCamera *camera, float focusDistance);
|
||||
|
||||
void Camera_setCustomProjectionWithCulling(
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setCustomProjectionWithCulling(
|
||||
TCamera* camera,
|
||||
double4x4 projectionMatrix,
|
||||
double near,
|
||||
double far
|
||||
);
|
||||
void Camera_setModelMatrix(TCamera* camera, double *tModelMatrix);
|
||||
void Camera_setLensProjection(TCamera *camera, double near, double far, double aspect, double focalLength);
|
||||
EntityId Camera_getEntity(TCamera* camera);
|
||||
void Camera_setProjection(TCamera *const tCamera, TProjection projection, double left, double right,
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setModelMatrix(TCamera* camera, double *tModelMatrix);
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setLensProjection(TCamera *camera, double near, double far, double aspect, double focalLength);
|
||||
EMSCRIPTEN_KEEPALIVE EntityId Camera_getEntity(TCamera* camera);
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setProjection(TCamera *const tCamera, TProjection projection, double left, double right,
|
||||
double bottom, double top,
|
||||
double near, double far);
|
||||
|
||||
|
||||
@@ -16,16 +16,16 @@ namespace thermion
|
||||
typedef int32_t EntityId;
|
||||
typedef void (*FilamentRenderCallback)(void *const owner);
|
||||
|
||||
void RenderThread_create();
|
||||
void RenderThread_destroy();
|
||||
void RenderThread_requestFrameAsync();
|
||||
void RenderThread_setRenderTicker(TRenderTicker *tRenderTicker);
|
||||
void RenderThread_addTask(void (*task)());
|
||||
EMSCRIPTEN_KEEPALIVE void RenderThread_create();
|
||||
EMSCRIPTEN_KEEPALIVE void RenderThread_destroy();
|
||||
EMSCRIPTEN_KEEPALIVE void RenderThread_requestFrameAsync();
|
||||
EMSCRIPTEN_KEEPALIVE void RenderThread_setRenderTicker(TRenderTicker *tRenderTicker);
|
||||
EMSCRIPTEN_KEEPALIVE void RenderThread_addTask(void (*task)());
|
||||
|
||||
void RenderTicker_renderRenderThread(TRenderTicker *tRenderTicker, uint64_t frameTimeInNanos, uint32_t requestId, VoidCallback onComplete);
|
||||
void AnimationManager_createRenderThread(TEngine *tEngine, TScene *tScene, void (*onComplete)(TAnimationManager *));
|
||||
EMSCRIPTEN_KEEPALIVE void RenderTicker_renderRenderThread(TRenderTicker *tRenderTicker, uint64_t frameTimeInNanos, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_createRenderThread(TEngine *tEngine, TScene *tScene, void (*onComplete)(TAnimationManager *));
|
||||
|
||||
void Engine_createRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_createRenderThread(
|
||||
TBackend backend,
|
||||
void* platform,
|
||||
void* sharedContext,
|
||||
@@ -33,22 +33,22 @@ namespace thermion
|
||||
bool disableHandleUseAfterFreeCheck,
|
||||
void (*onComplete)(TEngine *)
|
||||
);
|
||||
void Engine_createRendererRenderThread(TEngine *tEngine, void (*onComplete)(TRenderer *));
|
||||
void Engine_createSwapChainRenderThread(TEngine *tEngine, void *window, uint64_t flags, void (*onComplete)(TSwapChain *));
|
||||
void Engine_createHeadlessSwapChainRenderThread(TEngine *tEngine, uint32_t width, uint32_t height, uint64_t flags, void (*onComplete)(TSwapChain *));
|
||||
void Engine_createCameraRenderThread(TEngine* tEngine, void (*onComplete)(TCamera *));
|
||||
void Engine_createViewRenderThread(TEngine *tEngine, void (*onComplete)(TView *));
|
||||
void Engine_buildMaterialRenderThread(TEngine *tEngine, const uint8_t *materialData, size_t length, void (*onComplete)(TMaterial *));
|
||||
void Engine_destroyRenderThread(TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_destroySwapChainRenderThread(TEngine *tEngine, TSwapChain *tSwapChain, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_destroyViewRenderThread(TEngine *tEngine, TView *tView, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_destroySceneRenderThread(TEngine *tEngine, TScene *tScene, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_destroyColorGradingRenderThread(TEngine *tEngine, TColorGrading *tColorGrading, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_destroyMaterialRenderThread(TEngine *tEngine, TMaterial *tMaterial, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_destroyMaterialInstanceRenderThread(TEngine *tEngine, TMaterialInstance *tMaterialInstance, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_destroySkyboxRenderThread(TEngine *tEngine, TSkybox *tSkybox, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_destroyIndirectLightRenderThread(TEngine *tEngine, TIndirectLight *tIndirectLight, uint32_t requestId, VoidCallback onComplete);
|
||||
void Texture_buildRenderThread(TEngine *engine,
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_createRendererRenderThread(TEngine *tEngine, void (*onComplete)(TRenderer *));
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_createSwapChainRenderThread(TEngine *tEngine, void *window, uint64_t flags, void (*onComplete)(TSwapChain *));
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_createHeadlessSwapChainRenderThread(TEngine *tEngine, uint32_t width, uint32_t height, uint64_t flags, void (*onComplete)(TSwapChain *));
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_createCameraRenderThread(TEngine* tEngine, void (*onComplete)(TCamera *));
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_createViewRenderThread(TEngine *tEngine, void (*onComplete)(TView *));
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_buildMaterialRenderThread(TEngine *tEngine, const uint8_t *materialData, size_t length, void (*onComplete)(TMaterial *));
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroyRenderThread(TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroySwapChainRenderThread(TEngine *tEngine, TSwapChain *tSwapChain, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroyViewRenderThread(TEngine *tEngine, TView *tView, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroySceneRenderThread(TEngine *tEngine, TScene *tScene, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroyColorGradingRenderThread(TEngine *tEngine, TColorGrading *tColorGrading, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterialRenderThread(TEngine *tEngine, TMaterial *tMaterial, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterialInstanceRenderThread(TEngine *tEngine, TMaterialInstance *tMaterialInstance, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroySkyboxRenderThread(TEngine *tEngine, TSkybox *tSkybox, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroyIndirectLightRenderThread(TEngine *tEngine, TIndirectLight *tIndirectLight, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Texture_buildRenderThread(TEngine *engine,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
uint32_t depth,
|
||||
@@ -59,25 +59,25 @@ namespace thermion
|
||||
TTextureFormat format,
|
||||
void (*onComplete)(TTexture*)
|
||||
);
|
||||
void Texture_generateMipMapsRenderThread(TTexture *tTexture, TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
||||
void Ktx1Reader_createTextureRenderThread(TEngine *tEngine, TKtx1Bundle *tBundle, uint32_t requestId, VoidCallback onTextureUploadComplete, void (*onComplete)(TTexture *));
|
||||
EMSCRIPTEN_KEEPALIVE void Texture_generateMipMapsRenderThread(TTexture *tTexture, TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Ktx1Reader_createTextureRenderThread(TEngine *tEngine, TKtx1Bundle *tBundle, uint32_t requestId, VoidCallback onTextureUploadComplete, void (*onComplete)(TTexture *));
|
||||
|
||||
void Engine_destroyTextureRenderThread(TEngine *engine, TTexture* tTexture, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_createFenceRenderThread(TEngine *tEngine, void (*onComplete)(TFence*));
|
||||
void Fence_waitAndDestroyRenderThread(TFence *tFence, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_destroyFenceRenderThread(TEngine *tEngine, TFence *tFence, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_flushAndWaitRenderThread(TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_executeRenderThread(TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_buildSkyboxRenderThread(TEngine *tEngine, TTexture *tTexture, void (*onComplete)(TSkybox *));
|
||||
void Engine_buildIndirectLightFromIrradianceTextureRenderThread(TEngine *tEngine, TTexture *tReflectionsTexture, TTexture* tIrradianceTexture, float intensity, void (*onComplete)(TIndirectLight *));
|
||||
void Engine_buildIndirectLightFromIrradianceHarmonicsRenderThread(TEngine *tEngine, TTexture *tReflectionsTexture, float *harmonics, float intensity, void (*onComplete)(TIndirectLight *));
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroyTextureRenderThread(TEngine *engine, TTexture* tTexture, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_createFenceRenderThread(TEngine *tEngine, void (*onComplete)(TFence*));
|
||||
EMSCRIPTEN_KEEPALIVE void Fence_waitAndDestroyRenderThread(TFence *tFence, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroyFenceRenderThread(TEngine *tEngine, TFence *tFence, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_flushAndWaitRenderThread(TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_executeRenderThread(TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_buildSkyboxRenderThread(TEngine *tEngine, TTexture *tTexture, void (*onComplete)(TSkybox *));
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_buildIndirectLightFromIrradianceTextureRenderThread(TEngine *tEngine, TTexture *tReflectionsTexture, TTexture* tIrradianceTexture, float intensity, void (*onComplete)(TIndirectLight *));
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_buildIndirectLightFromIrradianceHarmonicsRenderThread(TEngine *tEngine, TTexture *tReflectionsTexture, float *harmonics, float intensity, void (*onComplete)(TIndirectLight *));
|
||||
|
||||
void Renderer_setClearOptionsRenderThread(TRenderer *tRenderer, double clearR, double clearG, double clearB, double clearA, uint8_t clearStencil, bool clear, bool discard, uint32_t requestId, VoidCallback onComplete);
|
||||
void Renderer_beginFrameRenderThread(TRenderer *tRenderer, TSwapChain *tSwapChain, uint64_t frameTimeInNanos, void (*onComplete)(bool));
|
||||
void Renderer_endFrameRenderThread(TRenderer *tRenderer, uint32_t requestId, VoidCallback onComplete);
|
||||
void Renderer_renderRenderThread(TRenderer *tRenderer, TView *tView, uint32_t requestId, VoidCallback onComplete);
|
||||
void Renderer_renderStandaloneViewRenderThread(TRenderer *tRenderer, TView *tView, uint32_t requestId, VoidCallback onComplete);
|
||||
void Renderer_readPixelsRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void Renderer_setClearOptionsRenderThread(TRenderer *tRenderer, double clearR, double clearG, double clearB, double clearA, uint8_t clearStencil, bool clear, bool discard, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Renderer_beginFrameRenderThread(TRenderer *tRenderer, TSwapChain *tSwapChain, uint64_t frameTimeInNanos, void (*onComplete)(bool));
|
||||
EMSCRIPTEN_KEEPALIVE void Renderer_endFrameRenderThread(TRenderer *tRenderer, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Renderer_renderRenderThread(TRenderer *tRenderer, TView *tView, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Renderer_renderStandaloneViewRenderThread(TRenderer *tRenderer, TView *tView, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Renderer_readPixelsRenderThread(
|
||||
TRenderer *tRenderer,
|
||||
uint32_t width, uint32_t height, uint32_t xOffset, uint32_t yOffset,
|
||||
TRenderTarget *tRenderTarget,
|
||||
@@ -87,29 +87,29 @@ namespace thermion
|
||||
size_t outLength,
|
||||
uint32_t requestId, VoidCallback onComplete);
|
||||
|
||||
void Material_createInstanceRenderThread(TMaterial *tMaterial, void (*onComplete)(TMaterialInstance *));
|
||||
void Material_createImageMaterialRenderThread(TEngine *tEngine, void (*onComplete)(TMaterial *));
|
||||
void Material_createGizmoMaterialRenderThread(TEngine *tEngine, void (*onComplete)(TMaterial *));
|
||||
void Material_createOutlineMaterialRenderThread(TEngine *tEngine, void (*onComplete)(TMaterial *));
|
||||
EMSCRIPTEN_KEEPALIVE void Material_createInstanceRenderThread(TMaterial *tMaterial, void (*onComplete)(TMaterialInstance *));
|
||||
EMSCRIPTEN_KEEPALIVE void Material_createImageMaterialRenderThread(TEngine *tEngine, void (*onComplete)(TMaterial *));
|
||||
EMSCRIPTEN_KEEPALIVE void Material_createGizmoMaterialRenderThread(TEngine *tEngine, void (*onComplete)(TMaterial *));
|
||||
EMSCRIPTEN_KEEPALIVE void Material_createOutlineMaterialRenderThread(TEngine *tEngine, void (*onComplete)(TMaterial *));
|
||||
|
||||
void ColorGrading_createRenderThread(TEngine *tEngine, TToneMapping toneMapping, void (*callback)(TColorGrading *));
|
||||
void View_pickRenderThread(TView *tView, uint32_t requestId, uint32_t x, uint32_t y, PickCallback callback);
|
||||
void View_setColorGradingRenderThread(TView *tView, TColorGrading *tColorGrading, uint32_t requestId, VoidCallback onComplete);
|
||||
void View_setBloomRenderThread(TView *tView, bool enabled, double strength, uint32_t requestId, VoidCallback onComplete);
|
||||
void View_setCameraRenderThread(TView *tView, TCamera *tCamera, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void ColorGrading_createRenderThread(TEngine *tEngine, TToneMapping toneMapping, void (*callback)(TColorGrading *));
|
||||
EMSCRIPTEN_KEEPALIVE void View_pickRenderThread(TView *tView, uint32_t requestId, uint32_t x, uint32_t y, PickCallback callback);
|
||||
EMSCRIPTEN_KEEPALIVE void View_setColorGradingRenderThread(TView *tView, TColorGrading *tColorGrading, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void View_setBloomRenderThread(TView *tView, bool enabled, double strength, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void View_setCameraRenderThread(TView *tView, TCamera *tCamera, uint32_t requestId, VoidCallback onComplete);
|
||||
|
||||
void SceneAsset_createGridRenderThread(TEngine *tEngine, TMaterial * tMaterial, void (*callback)(TSceneAsset *));
|
||||
EMSCRIPTEN_KEEPALIVE void SceneAsset_createGridRenderThread(TEngine *tEngine, TMaterial * tMaterial, void (*callback)(TSceneAsset *));
|
||||
|
||||
void SceneAsset_destroyRenderThread(TSceneAsset *tSceneAsset, uint32_t requestId, VoidCallback onComplete);
|
||||
void SceneAsset_createFromFilamentAssetRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void SceneAsset_destroyRenderThread(TSceneAsset *tSceneAsset, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void SceneAsset_createFromFilamentAssetRenderThread(
|
||||
TEngine *tEngine,
|
||||
TGltfAssetLoader *tAssetLoader,
|
||||
TNameComponentManager *tNameComponentManager,
|
||||
TFilamentAsset *tFilamentAsset,
|
||||
void (*onComplete)(TSceneAsset *)
|
||||
);
|
||||
void SceneAsset_createInstanceRenderThread(TSceneAsset *asset, TMaterialInstance **tMaterialInstances, int materialInstanceCount, void (*callback)(TSceneAsset *));
|
||||
void SceneAsset_createGeometryRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void SceneAsset_createInstanceRenderThread(TSceneAsset *asset, TMaterialInstance **tMaterialInstances, int materialInstanceCount, void (*callback)(TSceneAsset *));
|
||||
EMSCRIPTEN_KEEPALIVE void SceneAsset_createGeometryRenderThread(
|
||||
TEngine *tEngine,
|
||||
float *vertices,
|
||||
uint32_t numVertices,
|
||||
@@ -124,7 +124,7 @@ namespace thermion
|
||||
int materialInstanceCount,
|
||||
void (*callback)(TSceneAsset *)
|
||||
);
|
||||
void MaterialProvider_createMaterialInstanceRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialProvider_createMaterialInstanceRenderThread(
|
||||
TMaterialProvider *tMaterialProvider,
|
||||
bool doubleSided,
|
||||
bool unlit,
|
||||
@@ -166,12 +166,12 @@ namespace thermion
|
||||
bool hasVolume,
|
||||
void (*callback)(TMaterialInstance *));
|
||||
|
||||
void AnimationManager_updateBoneMatricesRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_updateBoneMatricesRenderThread(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
void (*callback)(bool));
|
||||
|
||||
void AnimationManager_setMorphTargetWeightsRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_setMorphTargetWeightsRenderThread(
|
||||
TAnimationManager *tAnimationManager,
|
||||
EntityId entityId,
|
||||
const float *const morphData,
|
||||
@@ -179,16 +179,16 @@ namespace thermion
|
||||
void (*callback)(bool));
|
||||
|
||||
// Image methods
|
||||
void Image_createEmptyRenderThread(uint32_t width, uint32_t height, uint32_t channel, void (*onComplete)(TLinearImage *));
|
||||
void Image_decodeRenderThread(uint8_t* data, size_t length, const char* name, bool alpha, void (*onComplete)(TLinearImage *));
|
||||
void Image_getBytesRenderThread(TLinearImage *tLinearImage, void (*onComplete)(float *));
|
||||
void Image_destroyRenderThread(TLinearImage *tLinearImage, uint32_t requestId, VoidCallback onComplete);
|
||||
void Image_getWidthRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t));
|
||||
void Image_getHeightRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t));
|
||||
void Image_getChannelsRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t));
|
||||
EMSCRIPTEN_KEEPALIVE void Image_createEmptyRenderThread(uint32_t width, uint32_t height, uint32_t channel, void (*onComplete)(TLinearImage *));
|
||||
EMSCRIPTEN_KEEPALIVE void Image_decodeRenderThread(uint8_t* data, size_t length, const char* name, bool alpha, void (*onComplete)(TLinearImage *));
|
||||
EMSCRIPTEN_KEEPALIVE void Image_getBytesRenderThread(TLinearImage *tLinearImage, void (*onComplete)(float *));
|
||||
EMSCRIPTEN_KEEPALIVE void Image_destroyRenderThread(TLinearImage *tLinearImage, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Image_getWidthRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t));
|
||||
EMSCRIPTEN_KEEPALIVE void Image_getHeightRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t));
|
||||
EMSCRIPTEN_KEEPALIVE void Image_getChannelsRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t));
|
||||
|
||||
|
||||
void Texture_loadImageRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void Texture_loadImageRenderThread(
|
||||
TEngine *tEngine,
|
||||
TTexture *tTexture,
|
||||
TLinearImage *tImage,
|
||||
@@ -197,7 +197,7 @@ namespace thermion
|
||||
int level,
|
||||
void (*onComplete)(bool)
|
||||
);
|
||||
void Texture_setImageRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void Texture_setImageRenderThread(
|
||||
TEngine *tEngine,
|
||||
TTexture *tTexture,
|
||||
uint32_t level,
|
||||
@@ -213,8 +213,8 @@ namespace thermion
|
||||
uint32_t pixelDataType,
|
||||
void (*onComplete)(bool)
|
||||
);
|
||||
void RenderTarget_getColorTextureRenderThread(TRenderTarget *tRenderTarget, void (*onComplete)(TTexture *));
|
||||
void RenderTarget_createRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void RenderTarget_getColorTextureRenderThread(TRenderTarget *tRenderTarget, void (*onComplete)(TTexture *));
|
||||
EMSCRIPTEN_KEEPALIVE void RenderTarget_createRenderThread(
|
||||
TEngine *tEngine,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
@@ -222,7 +222,7 @@ namespace thermion
|
||||
TTexture *depth,
|
||||
void (*onComplete)(TRenderTarget *)
|
||||
);
|
||||
void RenderTarget_destroyRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void RenderTarget_destroyRenderThread(
|
||||
TEngine *tEngine,
|
||||
TRenderTarget *tRenderTarget,
|
||||
uint32_t requestId, VoidCallback onComplete
|
||||
@@ -230,8 +230,8 @@ namespace thermion
|
||||
|
||||
|
||||
// TextureSampler methods
|
||||
void TextureSampler_createRenderThread(void (*onComplete)(TTextureSampler*));
|
||||
void TextureSampler_createWithFilteringRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_createRenderThread(void (*onComplete)(TTextureSampler*));
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_createWithFilteringRenderThread(
|
||||
TSamplerMinFilter minFilter,
|
||||
TSamplerMagFilter magFilter,
|
||||
TSamplerWrapMode wrapS,
|
||||
@@ -239,53 +239,53 @@ namespace thermion
|
||||
TSamplerWrapMode wrapR,
|
||||
void (*onComplete)(TTextureSampler*)
|
||||
);
|
||||
void TextureSampler_createWithComparisonRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_createWithComparisonRenderThread(
|
||||
TSamplerCompareMode compareMode,
|
||||
TSamplerCompareFunc compareFunc,
|
||||
void (*onComplete)(TTextureSampler*)
|
||||
);
|
||||
void TextureSampler_setMinFilterRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_setMinFilterRenderThread(
|
||||
TTextureSampler* sampler,
|
||||
TSamplerMinFilter filter,
|
||||
uint32_t requestId, VoidCallback onComplete
|
||||
);
|
||||
void TextureSampler_setMagFilterRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_setMagFilterRenderThread(
|
||||
TTextureSampler* sampler,
|
||||
TSamplerMagFilter filter,
|
||||
uint32_t requestId, VoidCallback onComplete
|
||||
);
|
||||
void TextureSampler_setWrapModeSRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeSRenderThread(
|
||||
TTextureSampler* sampler,
|
||||
TSamplerWrapMode mode,
|
||||
uint32_t requestId, VoidCallback onComplete
|
||||
);
|
||||
void TextureSampler_setWrapModeTRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeTRenderThread(
|
||||
TTextureSampler* sampler,
|
||||
TSamplerWrapMode mode,
|
||||
uint32_t requestId, VoidCallback onComplete
|
||||
);
|
||||
void TextureSampler_setWrapModeRRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeRRenderThread(
|
||||
TTextureSampler* sampler,
|
||||
TSamplerWrapMode mode,
|
||||
uint32_t requestId, VoidCallback onComplete
|
||||
);
|
||||
void TextureSampler_setAnisotropyRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_setAnisotropyRenderThread(
|
||||
TTextureSampler* sampler,
|
||||
double anisotropy,
|
||||
uint32_t requestId, VoidCallback onComplete
|
||||
);
|
||||
void TextureSampler_setCompareModeRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_setCompareModeRenderThread(
|
||||
TTextureSampler* sampler,
|
||||
TSamplerCompareMode mode,
|
||||
TTextureSamplerCompareFunc func,
|
||||
uint32_t requestId, VoidCallback onComplete
|
||||
);
|
||||
void TextureSampler_destroyRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_destroyRenderThread(
|
||||
TTextureSampler* sampler,
|
||||
uint32_t requestId, VoidCallback onComplete
|
||||
);
|
||||
|
||||
void AnimationManager_setBoneTransformRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_setBoneTransformRenderThread(
|
||||
TAnimationManager *tAnimationManager,
|
||||
EntityId asset,
|
||||
int skinIndex,
|
||||
@@ -293,18 +293,18 @@ namespace thermion
|
||||
const float *const transform,
|
||||
void (*callback)(bool));
|
||||
|
||||
void AnimationManager_resetToRestPoseRenderThread(TAnimationManager *tAnimationManager, TSceneAsset *tSceneAsset, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_resetToRestPoseRenderThread(TAnimationManager *tAnimationManager, TSceneAsset *tSceneAsset, uint32_t requestId, VoidCallback onComplete);
|
||||
|
||||
void GltfAssetLoader_createRenderThread(TEngine *tEngine, TMaterialProvider *tMaterialProvider, TNameComponentManager *tNameComponentManager, void (*callback)(TGltfAssetLoader *));
|
||||
void GltfResourceLoader_createRenderThread(TEngine *tEngine, void (*callback)(TGltfResourceLoader *));
|
||||
void GltfResourceLoader_destroyRenderThread(TEngine *tEngine, TGltfResourceLoader *tResourceLoader, uint32_t requestId, VoidCallback onComplete);
|
||||
void GltfResourceLoader_loadResourcesRenderThread(TGltfResourceLoader *tGltfResourceLoader, TFilamentAsset *tFilamentAsset, void (*callback)(bool));
|
||||
void GltfResourceLoader_addResourceDataRenderThread(TGltfResourceLoader *tGltfResourceLoader, const char *uri, uint8_t *data, size_t length, uint32_t requestId, VoidCallback onComplete);
|
||||
void GltfResourceLoader_asyncBeginLoadRenderThread(TGltfResourceLoader *tGltfResourceLoader, TFilamentAsset *tFilamentAsset, void (*callback)(bool));
|
||||
void GltfResourceLoader_asyncUpdateLoadRenderThread(TGltfResourceLoader *tGltfResourceLoader);
|
||||
void GltfResourceLoader_asyncGetLoadProgressRenderThread(TGltfResourceLoader *tGltfResourceLoader, void (*callback)(float));
|
||||
EMSCRIPTEN_KEEPALIVE void GltfAssetLoader_createRenderThread(TEngine *tEngine, TMaterialProvider *tMaterialProvider, TNameComponentManager *tNameComponentManager, void (*callback)(TGltfAssetLoader *));
|
||||
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_createRenderThread(TEngine *tEngine, void (*callback)(TGltfResourceLoader *));
|
||||
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_destroyRenderThread(TEngine *tEngine, TGltfResourceLoader *tResourceLoader, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_loadResourcesRenderThread(TGltfResourceLoader *tGltfResourceLoader, TFilamentAsset *tFilamentAsset, void (*callback)(bool));
|
||||
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_addResourceDataRenderThread(TGltfResourceLoader *tGltfResourceLoader, const char *uri, uint8_t *data, size_t length, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_asyncBeginLoadRenderThread(TGltfResourceLoader *tGltfResourceLoader, TFilamentAsset *tFilamentAsset, void (*callback)(bool));
|
||||
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_asyncUpdateLoadRenderThread(TGltfResourceLoader *tGltfResourceLoader);
|
||||
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_asyncGetLoadProgressRenderThread(TGltfResourceLoader *tGltfResourceLoader, void (*callback)(float));
|
||||
|
||||
void GltfAssetLoader_loadRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void GltfAssetLoader_loadRenderThread(
|
||||
TEngine *tEngine,
|
||||
TGltfAssetLoader *tAssetLoader,
|
||||
uint8_t *data,
|
||||
@@ -312,8 +312,8 @@ namespace thermion
|
||||
uint8_t numInstances,
|
||||
void (*callback)(TFilamentAsset *)
|
||||
);
|
||||
void Scene_addFilamentAssetRenderThread(TScene* tScene, TFilamentAsset *tAsset, uint32_t requestId, VoidCallback onComplete);
|
||||
void Gizmo_createRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void Scene_addFilamentAssetRenderThread(TScene* tScene, TFilamentAsset *tAsset, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Gizmo_createRenderThread(
|
||||
TEngine *tEngine,
|
||||
TGltfAssetLoader *tAssetLoader,
|
||||
TGltfResourceLoader *tGltfResourceLoader,
|
||||
@@ -330,4 +330,3 @@ namespace thermion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -8,5 +8,5 @@ GRID_PACKAGE:
|
||||
GRID_GRID_OFFSET:
|
||||
.int 0
|
||||
GRID_GRID_SIZE:
|
||||
.int 50913
|
||||
.int 49793
|
||||
|
||||
|
||||
@@ -8,5 +8,5 @@ _GRID_PACKAGE:
|
||||
_GRID_GRID_OFFSET:
|
||||
.int 0
|
||||
_GRID_GRID_SIZE:
|
||||
.int 50913
|
||||
.int 49793
|
||||
|
||||
|
||||
@@ -85,10 +85,10 @@ EMSCRIPTEN_KEEPALIVE TFilamentAsset *GltfAssetLoader_load(
|
||||
const char *const *const resourceUris = asset->getResourceUris();
|
||||
const size_t resourceUriCount = asset->getResourceUriCount();
|
||||
|
||||
Log("glTF asset : %d resource URIs, %d instances", resourceUriCount, numInstances);
|
||||
TRACE("Loading glTF asset with %d resource URIs (allocating %d reserved instances", resourceUriCount, numInstances);
|
||||
|
||||
for(int i = 0; i < resourceUriCount; i++) {
|
||||
Log("%s", resourceUris[i]);
|
||||
TRACE("%s", resourceUris[i]);
|
||||
}
|
||||
|
||||
return reinterpret_cast<TFilamentAsset *>(asset);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: thermion_dart
|
||||
description: 3D rendering toolkit for Dart.
|
||||
version: 0.3.2
|
||||
version: 0.3.3
|
||||
homepage: https://thermion.dev
|
||||
repository: https://github.com/nmfisher/thermion
|
||||
|
||||
|
||||
@@ -82,10 +82,6 @@ class TestHelper {
|
||||
testDir = Directory("${packageUri}test").path;
|
||||
outDir = Directory("$testDir/output/${dir}");
|
||||
outDir.createSync(recursive: true);
|
||||
if (Platform.isMacOS) {
|
||||
DynamicLibrary.open('${testDir}/generated/objective_c.dylib');
|
||||
DynamicLibrary.open('${testDir}/generated/libThermionTextureSwift.dylib');
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
@@ -226,6 +222,10 @@ class TestHelper {
|
||||
|
||||
FFIRenderTarget? renderTarget;
|
||||
if (createRenderTarget) {
|
||||
// if (Platform.isMacOS) {
|
||||
// DynamicLibrary.open('${testDir}/generated/objective_c.dylib');
|
||||
// DynamicLibrary.open('${testDir}/generated/libThermionTextureSwift.dylib');
|
||||
// }
|
||||
// var metalColorTexture = await createTexture(
|
||||
// viewportDimensions.width, viewportDimensions.height);
|
||||
// var metalDepthTexture = await createTexture(
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
## 0.3.3
|
||||
|
||||
- Bump "thermion_flutter" to `0.3.3`.
|
||||
|
||||
## 0.3.3-pre
|
||||
|
||||
- **DOCS**: replace thermion_flutter README with symlink to thermion_dart README.
|
||||
|
||||
## 0.3.2
|
||||
|
||||
- Bump "thermion_flutter" to `0.3.2`.
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||

|
||||
|
||||
<p align="center">
|
||||
<a href="https://thermion.dev/quickstart">Quickstart (Flutter)</a> •
|
||||
<a href="https://thermion.dev/quickstart">Documentation</a> •
|
||||
<a href="https://thermion.dev/showcase">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.
|
||||
|
||||
<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>
|
||||
<a href="https://discord.gg/h2VdDK3EAQ"><img src="https://img.shields.io/discord/993167615587520602?logo=discord&logoColor=fff&labelColor=333940" alt="discord"></a>
|
||||
<a href="https://github.com/nmfisher/thermion"><img src="https://img.shields.io/github/contributors/nmfisher/flutter_filament?logo=github&labelColor=333940" alt="contributors"></a>
|
||||
|
||||
### Quickstart (Flutter)
|
||||
|
||||
```
|
||||
_thermionViewer = await ThermionFlutterPlugin.createViewer();
|
||||
|
||||
// Geometry and models are represented as "entities". Here, we load a glTF
|
||||
// file containing a plain cube.
|
||||
// By default, all paths are treated as asset paths. To load from a file
|
||||
// instead, use file:// URIs.
|
||||
var entity =
|
||||
await _thermionViewer!.loadGlb("assets/cube.glb", keepData: true);
|
||||
|
||||
// Thermion uses a right-handed coordinate system where +Y is up and -Z is
|
||||
// "into" the screen.
|
||||
// By default, the camera is located at (0,0,0) looking at (0,0,-1); this
|
||||
// would place it directly inside the cube we just loaded.
|
||||
//
|
||||
// Let's move the camera to (0,0,10) to ensure the cube is visible in the
|
||||
// viewport.
|
||||
await _thermionViewer!.setCameraPosition(0, 0, 10);
|
||||
|
||||
// Without a light source, your scene will be totally black. Let's load a skybox
|
||||
// (a cubemap image that is rendered behind everything else in the scene)
|
||||
// and an image-based indirect light that has been precomputed from the same
|
||||
// skybox.
|
||||
await _thermionViewer!.loadSkybox("assets/default_env_skybox.ktx");
|
||||
await _thermionViewer!.loadIbl("assets/default_env_ibl.ktx");
|
||||
|
||||
// Finally, you need to explicitly enable rendering. Setting rendering to
|
||||
// false is designed to allow you to pause rendering to conserve battery life
|
||||
await _thermionViewer!.setRendering(true);
|
||||
```
|
||||
|
||||
and then in your Flutter application:
|
||||
```
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(children: [
|
||||
if (_thermionViewer != null)
|
||||
Positioned.fill(
|
||||
child: ThermionWidget(
|
||||
viewer: _thermionViewer!,
|
||||
)),
|
||||
]);
|
||||
}
|
||||
```
|
||||
1
thermion_flutter/thermion_flutter/README.md
Symbolic link
@@ -0,0 +1 @@
|
||||
../../thermion_dart/README.md
|
||||
@@ -1,6 +1,6 @@
|
||||
name: thermion_flutter
|
||||
description: Flutter plugin for 3D rendering with the Thermion toolkit.
|
||||
version: 0.3.2
|
||||
version: 0.3.3
|
||||
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.1.0
|
||||
thermion_dart: ^0.3.2
|
||||
thermion_flutter_platform_interface: ^0.3.2
|
||||
thermion_flutter_method_channel: ^0.3.2
|
||||
thermion_flutter_web: ^0.3.2
|
||||
thermion_dart: ^0.3.3
|
||||
thermion_flutter_platform_interface: ^0.3.3
|
||||
thermion_flutter_method_channel: ^0.3.3
|
||||
thermion_flutter_web: ^0.3.3
|
||||
logging: ^1.2.0
|
||||
web: ^1.0.0
|
||||
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
## 0.3.3
|
||||
|
||||
- Bump "thermion_flutter_method_channel" to `0.3.3`.
|
||||
|
||||
## 0.3.3-pre
|
||||
|
||||
- **FEAT**: allow passing renderTargetColorTextureFormat via ThermionFlutterOptions.
|
||||
|
||||
## 0.3.2
|
||||
|
||||
- Bump "thermion_flutter_method_channel" to `0.3.2`.
|
||||
|
||||
@@ -212,7 +212,7 @@ class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
||||
TextureUsage.TEXTURE_USAGE_COLOR_ATTACHMENT,
|
||||
TextureUsage.TEXTURE_USAGE_SAMPLEABLE,
|
||||
},
|
||||
textureFormat: TextureFormat.RGBA32F,
|
||||
textureFormat: options.renderTargetColorTextureFormat,
|
||||
textureSamplerType: TextureSamplerType.SAMPLER_2D,
|
||||
);
|
||||
final depth = await FilamentApp.instance!.createTexture(
|
||||
@@ -225,7 +225,7 @@ class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
||||
TextureUsage.TEXTURE_USAGE_STENCIL_ATTACHMENT
|
||||
},
|
||||
textureFormat:
|
||||
TextureFormat.DEPTH24_STENCIL8, // TextureFormat.DEPTH32F,
|
||||
options.renderTargetDepthTextureFormat,
|
||||
textureSamplerType: TextureSamplerType.SAMPLER_2D,
|
||||
);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: thermion_flutter_method_channel
|
||||
description: Desktop + mobile implementation for texture creation + registration with Flutter.
|
||||
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
|
||||
version: 0.3.2
|
||||
version: 0.3.3
|
||||
|
||||
environment:
|
||||
sdk: ">=3.3.0 <4.0.0"
|
||||
@@ -23,8 +23,8 @@ dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
plugin_platform_interface: ^2.1.0
|
||||
thermion_flutter_platform_interface: ^0.3.2
|
||||
thermion_dart: ^0.3.2
|
||||
thermion_flutter_platform_interface: ^0.3.3
|
||||
thermion_dart: ^0.3.3
|
||||
logging: ^1.2.0
|
||||
dependency_overrides:
|
||||
thermion_dart:
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
## 0.3.3
|
||||
|
||||
- Bump "thermion_flutter_platform_interface" to `0.3.3`.
|
||||
|
||||
## 0.3.3-pre
|
||||
|
||||
- **FEAT**: allow passing renderTargetColorTextureFormat via ThermionFlutterOptions.
|
||||
|
||||
## 0.3.2
|
||||
|
||||
- Bump "thermion_flutter_platform_interface" to `0.3.2`.
|
||||
|
||||
@@ -7,13 +7,25 @@ import 'thermion_flutter_texture.dart';
|
||||
class ThermionFlutterOptions {
|
||||
final String? uberarchivePath;
|
||||
final Backend? backend;
|
||||
|
||||
/// The format to use for the default render target color attachment.
|
||||
/// Currently only applicable on iOS/macOS.
|
||||
///
|
||||
final TextureFormat renderTargetColorTextureFormat;
|
||||
|
||||
/// The format to use for the default render target depth attachment.
|
||||
/// Currently only applicable on iOS/macOS.
|
||||
///
|
||||
final TextureFormat renderTargetDepthTextureFormat;
|
||||
|
||||
const ThermionFlutterOptions(
|
||||
{this.uberarchivePath = null, this.backend = null});
|
||||
{this.uberarchivePath = null,
|
||||
this.backend = null,
|
||||
this.renderTargetColorTextureFormat = TextureFormat.RGBA32F,
|
||||
this.renderTargetDepthTextureFormat = TextureFormat.DEPTH24_STENCIL8});
|
||||
}
|
||||
|
||||
class ThermionFlutterWebOptions extends ThermionFlutterOptions {
|
||||
|
||||
final bool createCanvas;
|
||||
final bool importCanvasAsWidget;
|
||||
|
||||
@@ -22,8 +34,6 @@ class ThermionFlutterWebOptions extends ThermionFlutterOptions {
|
||||
this.createCanvas = true,
|
||||
String? uberarchivePath})
|
||||
: super(uberarchivePath: uberarchivePath);
|
||||
|
||||
|
||||
}
|
||||
|
||||
abstract class ThermionFlutterPlatform extends PlatformInterface {
|
||||
@@ -42,15 +52,11 @@ abstract class ThermionFlutterPlatform extends PlatformInterface {
|
||||
_options ??= const ThermionFlutterOptions();
|
||||
return _options!;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
void setOptions(covariant ThermionFlutterOptions options) {
|
||||
if (_options != null) {
|
||||
throw Exception(
|
||||
"Options can only be set once for the entire app lifecycle.");
|
||||
}
|
||||
_options = options;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.3.2
|
||||
version: 0.3.3
|
||||
|
||||
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.3.2
|
||||
thermion_dart: ^0.3.3
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
## 0.3.3
|
||||
|
||||
- Bump "thermion_flutter_web" to `0.3.3`.
|
||||
|
||||
## 0.3.3-pre
|
||||
|
||||
- Bump "thermion_flutter_web" to `0.3.3-pre`.
|
||||
|
||||
## 0.3.2
|
||||
|
||||
- **FIX**: add missing destroySwapchain argument for web.
|
||||
|
||||
@@ -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.3.2
|
||||
version: 0.3.3
|
||||
|
||||
environment:
|
||||
sdk: ">=3.3.0 <4.0.0"
|
||||
@@ -20,8 +20,8 @@ dependencies:
|
||||
sdk: flutter
|
||||
plugin_platform_interface: ^2.1.0
|
||||
web: ^1.0.0
|
||||
thermion_dart: ^0.3.2
|
||||
thermion_flutter_platform_interface: ^0.3.2
|
||||
thermion_dart: ^0.3.3
|
||||
thermion_flutter_platform_interface: ^0.3.3
|
||||
flutter_web_plugins:
|
||||
sdk: flutter
|
||||
logging: ^1.3.0
|
||||
|
||||