feat: more work on multiple views/swapchains
This commit is contained in:
@@ -6,12 +6,12 @@ import '../../../../utils/matrix.dart';
|
||||
import '../../thermion_viewer_base.dart';
|
||||
import 'thermion_dart.g.dart';
|
||||
|
||||
class ThermionFFICamera extends Camera {
|
||||
class FFICamera extends Camera {
|
||||
final Pointer<TCamera> camera;
|
||||
final Pointer<TEngine> engine;
|
||||
late ThermionEntity _entity;
|
||||
|
||||
ThermionFFICamera(this.camera, this.engine) {
|
||||
FFICamera(this.camera, this.engine) {
|
||||
_entity = Camera_getEntity(camera);
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ class ThermionFFICamera extends Camera {
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is ThermionFFICamera &&
|
||||
other is FFICamera &&
|
||||
runtimeType == other.runtimeType &&
|
||||
camera == other.camera;
|
||||
|
||||
|
||||
@@ -1832,6 +1832,19 @@ external void unproject_texture_render_thread(
|
||||
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
|
||||
);
|
||||
|
||||
@ffi.Native<TViewport Function(ffi.Pointer<TView>)>(isLeaf: true)
|
||||
external TViewport View_getViewport(
|
||||
ffi.Pointer<TView> view,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Uint32, ffi.Uint32)>(
|
||||
isLeaf: true)
|
||||
external void View_updateViewport(
|
||||
ffi.Pointer<TView> view,
|
||||
int width,
|
||||
int height,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Pointer<TRenderTarget>)>(
|
||||
isLeaf: true)
|
||||
external void View_setRenderTarget(
|
||||
@@ -1845,14 +1858,6 @@ external void View_setFrustumCullingEnabled(
|
||||
bool enabled,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Uint32, ffi.Uint32)>(
|
||||
isLeaf: true)
|
||||
external void View_updateViewport(
|
||||
ffi.Pointer<TView> tView,
|
||||
int width,
|
||||
int height,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Bool)>(isLeaf: true)
|
||||
external void View_setPostProcessing(
|
||||
ffi.Pointer<TView> tView,
|
||||
@@ -2197,6 +2202,20 @@ typedef FilamentRenderCallbackFunction = ffi.Void Function(
|
||||
typedef DartFilamentRenderCallbackFunction = void Function(
|
||||
ffi.Pointer<ffi.Void> owner);
|
||||
|
||||
final class TViewport extends ffi.Struct {
|
||||
@ffi.Int32()
|
||||
external int left;
|
||||
|
||||
@ffi.Int32()
|
||||
external int bottom;
|
||||
|
||||
@ffi.Uint32()
|
||||
external int width;
|
||||
|
||||
@ffi.Uint32()
|
||||
external int height;
|
||||
}
|
||||
|
||||
const int __bool_true_false_are_defined = 1;
|
||||
|
||||
const int true1 = 1;
|
||||
|
||||
@@ -162,7 +162,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
{Pointer<Void>? surface}) async {
|
||||
var swapChain = await withPointerCallback<TSwapChain>((callback) {
|
||||
return Viewer_createSwapChainRenderThread(_viewer!, surface ?? nullptr,
|
||||
width.toInt(), height.toInt(), callback);
|
||||
width, height, callback);
|
||||
});
|
||||
return FFISwapChain(swapChain, _viewer!);
|
||||
}
|
||||
@@ -234,19 +234,19 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
///
|
||||
@override
|
||||
Future<Uint8List> capture(FFISwapChain swapChain,
|
||||
{FFIRenderTarget? renderTarget}) async {
|
||||
{FFIView? view, FFIRenderTarget? renderTarget}) async {
|
||||
final length = this.viewportDimensions.$1.toInt() *
|
||||
this.viewportDimensions.$2.toInt() *
|
||||
4;
|
||||
final out = Uint8List(length);
|
||||
final view = (await getViewAt(0)) as FFIView;
|
||||
view ??= (await getViewAt(0)) as FFIView;
|
||||
await withVoidCallback((cb) {
|
||||
if (renderTarget != null) {
|
||||
Viewer_captureRenderTargetRenderThread(_viewer!, view.view,
|
||||
Viewer_captureRenderTargetRenderThread(_viewer!, view!.view,
|
||||
swapChain.swapChain, renderTarget.renderTarget, out.address, cb);
|
||||
} else {
|
||||
Viewer_captureRenderThread(
|
||||
_viewer!, view.view, swapChain.swapChain, out.address, cb);
|
||||
_viewer!, view!.view, swapChain.swapChain, out.address, cb);
|
||||
}
|
||||
});
|
||||
return out;
|
||||
@@ -1131,7 +1131,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
Future<Camera?> getCameraComponent(ThermionEntity cameraEntity) async {
|
||||
var engine = Viewer_getEngine(_viewer!);
|
||||
var camera = Engine_getCameraComponent(engine, cameraEntity);
|
||||
return ThermionFFICamera(camera, engine);
|
||||
return FFICamera(camera, engine);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -1224,7 +1224,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
///
|
||||
///
|
||||
Future<double> getCameraFov(bool horizontal) async {
|
||||
var mainCamera = await getMainCamera() as ThermionFFICamera;
|
||||
var mainCamera = await getMainCamera() as FFICamera;
|
||||
return get_camera_fov(mainCamera.camera, horizontal);
|
||||
}
|
||||
|
||||
@@ -1253,7 +1253,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
}
|
||||
|
||||
Future<double> getCameraNear() async {
|
||||
var mainCamera = await getMainCamera() as ThermionFFICamera;
|
||||
var mainCamera = await getMainCamera() as FFICamera;
|
||||
return get_camera_near(mainCamera.camera);
|
||||
}
|
||||
|
||||
@@ -1262,7 +1262,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
///
|
||||
@override
|
||||
Future<double> getCameraCullingFar() async {
|
||||
var mainCamera = await getMainCamera() as ThermionFFICamera;
|
||||
var mainCamera = await getMainCamera() as FFICamera;
|
||||
return get_camera_culling_far(mainCamera.camera);
|
||||
}
|
||||
|
||||
@@ -1271,7 +1271,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
///
|
||||
@override
|
||||
Future setCameraFocusDistance(double focusDistance) async {
|
||||
var mainCamera = await getMainCamera() as ThermionFFICamera;
|
||||
var mainCamera = await getMainCamera() as FFICamera;
|
||||
set_camera_focus_distance(mainCamera.camera, focusDistance);
|
||||
}
|
||||
|
||||
@@ -1307,7 +1307,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
@override
|
||||
Future setCameraExposure(
|
||||
double aperture, double shutterSpeed, double sensitivity) async {
|
||||
var mainCamera = await getMainCamera() as ThermionFFICamera;
|
||||
var mainCamera = await getMainCamera() as FFICamera;
|
||||
set_camera_exposure(mainCamera.camera, aperture, shutterSpeed, sensitivity);
|
||||
}
|
||||
|
||||
@@ -1336,7 +1336,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
///
|
||||
@override
|
||||
Future setCameraModelMatrix4(Matrix4 modelMatrix) async {
|
||||
var mainCamera = await getMainCamera() as ThermionFFICamera;
|
||||
var mainCamera = await getMainCamera() as FFICamera;
|
||||
final out = matrix4ToDouble4x4(modelMatrix);
|
||||
set_camera_model_matrix(mainCamera.camera, out);
|
||||
}
|
||||
@@ -1546,7 +1546,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available");
|
||||
}
|
||||
var mainCamera = await getMainCamera() as ThermionFFICamera;
|
||||
var mainCamera = await getMainCamera() as FFICamera;
|
||||
var matrixStruct = get_camera_view_matrix(mainCamera.camera);
|
||||
return double4x4ToMatrix4(matrixStruct);
|
||||
}
|
||||
@@ -1559,7 +1559,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available");
|
||||
}
|
||||
var mainCamera = await getMainCamera() as ThermionFFICamera;
|
||||
var mainCamera = await getMainCamera() as FFICamera;
|
||||
var matrixStruct = get_camera_model_matrix(mainCamera.camera);
|
||||
return double4x4ToMatrix4(matrixStruct);
|
||||
}
|
||||
@@ -1572,7 +1572,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available");
|
||||
}
|
||||
var mainCamera = await getMainCamera() as ThermionFFICamera;
|
||||
var mainCamera = await getMainCamera() as FFICamera;
|
||||
var matrixStruct = get_camera_projection_matrix(mainCamera.camera);
|
||||
return double4x4ToMatrix4(matrixStruct);
|
||||
}
|
||||
@@ -1585,7 +1585,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available");
|
||||
}
|
||||
var mainCamera = await getMainCamera() as ThermionFFICamera;
|
||||
var mainCamera = await getMainCamera() as FFICamera;
|
||||
var matrixStruct = get_camera_culling_projection_matrix(mainCamera.camera);
|
||||
return double4x4ToMatrix4(matrixStruct);
|
||||
}
|
||||
@@ -1624,7 +1624,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available");
|
||||
}
|
||||
var mainCamera = await getMainCamera() as ThermionFFICamera;
|
||||
var mainCamera = await getMainCamera() as FFICamera;
|
||||
var arrayPtr = get_camera_frustum(mainCamera.camera);
|
||||
var doubleList = arrayPtr.asTypedList(24);
|
||||
|
||||
@@ -2096,18 +2096,18 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
Future<Camera> createCamera() async {
|
||||
var cameraPtr = SceneManager_createCamera(_sceneManager!);
|
||||
var engine = Viewer_getEngine(_viewer!);
|
||||
var camera = ThermionFFICamera(cameraPtr, engine);
|
||||
var camera = FFICamera(cameraPtr, engine);
|
||||
return camera;
|
||||
}
|
||||
|
||||
Future destroyCamera(ThermionFFICamera camera) async {
|
||||
Future destroyCamera(FFICamera camera) async {
|
||||
SceneManager_destroyCamera(_sceneManager!, camera.camera);
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
Future setActiveCamera(ThermionFFICamera camera) async {
|
||||
Future setActiveCamera(FFICamera camera) async {
|
||||
final view = (await getViewAt(0)) as FFIView;
|
||||
View_setCamera(view.view, camera.camera);
|
||||
}
|
||||
@@ -2118,7 +2118,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
Future<Camera> getActiveCamera() async {
|
||||
final view = (await getViewAt(0)) as FFIView;
|
||||
final ptr = View_getCamera(view.view);
|
||||
return ThermionFFICamera(ptr, Viewer_getEngine(_viewer!));
|
||||
return FFICamera(ptr, Viewer_getEngine(_viewer!));
|
||||
}
|
||||
|
||||
final _hooks = <Future Function()>[];
|
||||
@@ -2153,7 +2153,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
if (camera == nullptr) {
|
||||
throw Exception("No camera at index $index");
|
||||
}
|
||||
return ThermionFFICamera(camera, Viewer_getEngine(_viewer!));
|
||||
return FFICamera(camera, Viewer_getEngine(_viewer!));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -2234,4 +2234,16 @@ class FFIView extends View {
|
||||
Future setRenderTarget(covariant FFIRenderTarget renderTarget) async {
|
||||
View_setRenderTarget(view, renderTarget.renderTarget);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setCamera(FFICamera camera) async {
|
||||
View_setCamera(view, camera.camera);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Viewport> getViewport() async {
|
||||
TViewport vp = View_getViewport(view);
|
||||
return Viewport(vp.left, vp.bottom, vp.width, vp.height);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
|
||||
class Viewport {
|
||||
final int left;
|
||||
final int bottom;
|
||||
final int width;
|
||||
final int height;
|
||||
|
||||
Viewport(this.left, this.bottom, this.width, this.height);
|
||||
}
|
||||
|
||||
abstract class View {
|
||||
Future<Viewport> getViewport();
|
||||
Future updateViewport(int width, int height);
|
||||
Future setRenderTarget(covariant RenderTarget renderTarget);
|
||||
Future setCamera(covariant Camera camera);
|
||||
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ abstract class ThermionViewer {
|
||||
/// Render a single frame and copy the pixel buffer to [out].
|
||||
///
|
||||
Future<Uint8List> capture(covariant SwapChain swapChain,
|
||||
{covariant RenderTarget? renderTarget});
|
||||
{covariant View? view, covariant RenderTarget? renderTarget});
|
||||
|
||||
///
|
||||
///
|
||||
|
||||
@@ -45,13 +45,6 @@ namespace thermion_filament
|
||||
using namespace gltfio;
|
||||
using namespace camutils;
|
||||
|
||||
enum ToneMapping
|
||||
{
|
||||
ACES,
|
||||
FILMIC,
|
||||
LINEAR
|
||||
};
|
||||
|
||||
class FilamentViewer
|
||||
{
|
||||
|
||||
|
||||
@@ -321,6 +321,7 @@ namespace thermion_filament
|
||||
gltfio::TextureProvider *_ktxDecoder = nullptr;
|
||||
std::mutex _mutex;
|
||||
std::mutex _stencilMutex;
|
||||
std::vector<MaterialInstance*> _materialInstances;
|
||||
|
||||
utils::NameComponentManager *_ncm;
|
||||
|
||||
|
||||
@@ -1,60 +1,30 @@
|
||||
#ifndef _FLUTTER_FILAMENT_API_H
|
||||
#define _FLUTTER_FILAMENT_API_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef IS_DLL
|
||||
#define EMSCRIPTEN_KEEPALIVE __declspec(dllimport)
|
||||
#else
|
||||
#define EMSCRIPTEN_KEEPALIVE __declspec(dllexport)
|
||||
#endif
|
||||
#else
|
||||
#ifndef EMSCRIPTEN_KEEPALIVE
|
||||
#define EMSCRIPTEN_KEEPALIVE __attribute__((visibility("default")))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// we copy the LLVM <stdbool.h> here rather than including,
|
||||
// because on Windows it's difficult to pin the exact location which confuses dart ffigen
|
||||
|
||||
#ifndef __STDBOOL_H
|
||||
#define __STDBOOL_H
|
||||
|
||||
#define __bool_true_false_are_defined 1
|
||||
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ > 201710L
|
||||
/* FIXME: We should be issuing a deprecation warning here, but cannot yet due
|
||||
* to system headers which include this header file unconditionally.
|
||||
*/
|
||||
#elif !defined(__cplusplus)
|
||||
#define bool _Bool
|
||||
#define true 1
|
||||
#define false 0
|
||||
#elif defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
/* Define _Bool as a GNU extension. */
|
||||
#define _Bool bool
|
||||
#if defined(__cplusplus) && __cplusplus < 201103L
|
||||
/* For C++98, define bool, false, true as a GNU extension. */
|
||||
#define bool bool
|
||||
#define false false
|
||||
#define true true
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* __STDBOOL_H */
|
||||
|
||||
#if defined(__APPLE__) || defined(__EMSCRIPTEN__)
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
#include "APIBoundaryTypes.h"
|
||||
#include "ResourceBuffer.hpp"
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace thermion {
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "ThermionDartApi.h"
|
||||
|
||||
struct TViewport {
|
||||
int32_t left;
|
||||
int32_t bottom;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
};
|
||||
typedef struct TViewport TViewport;
|
||||
|
||||
enum ToneMapping
|
||||
{
|
||||
ACES,
|
||||
FILMIC,
|
||||
LINEAR
|
||||
};
|
||||
|
||||
// View
|
||||
EMSCRIPTEN_KEEPALIVE TViewport View_getViewport(TView *view);
|
||||
EMSCRIPTEN_KEEPALIVE void View_updateViewport(TView *view, uint32_t width, uint32_t height);
|
||||
EMSCRIPTEN_KEEPALIVE void View_setRenderTarget(TView *view, TRenderTarget *renderTarget);
|
||||
EMSCRIPTEN_KEEPALIVE void View_setFrustumCullingEnabled(TView *view, bool enabled);
|
||||
@@ -66,14 +36,13 @@ EMSCRIPTEN_KEEPALIVE void View_setShadowsEnabled(TView* tView, bool enabled);
|
||||
EMSCRIPTEN_KEEPALIVE void View_setShadowType(TView* tView, int shadowType);
|
||||
EMSCRIPTEN_KEEPALIVE void View_setSoftShadowOptions(TView* tView, float penumbraScale, float penumbraRatioScale);
|
||||
EMSCRIPTEN_KEEPALIVE void View_setBloom(TView* tView, float strength);
|
||||
EMSCRIPTEN_KEEPALIVE void View_setToneMapping(TView* tView, TEngine* tEngine, int toneMapping);
|
||||
EMSCRIPTEN_KEEPALIVE void View_setToneMapping(TView* tView, TEngine* tEngine, ToneMapping toneMapping);
|
||||
EMSCRIPTEN_KEEPALIVE void View_setAntiAliasing(TView *tView, bool msaa, bool fxaa, bool taa);
|
||||
EMSCRIPTEN_KEEPALIVE void View_setLayerEnabled(TView *tView, int layer, bool visible);
|
||||
EMSCRIPTEN_KEEPALIVE void View_setCamera(TView *tView, TCamera *tCamera);
|
||||
EMSCRIPTEN_KEEPALIVE TCamera* View_getCamera(TView *tView);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -677,7 +677,7 @@ namespace thermion_filament
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("Created headless swapchain.");
|
||||
Log("Created headless swapchain %dx%d.", width, height);
|
||||
swapChain = _engine->createSwapChain(width, height, filament::backend::SWAP_CHAIN_CONFIG_TRANSPARENT | filament::backend::SWAP_CHAIN_CONFIG_READABLE | filament::SwapChain::CONFIG_HAS_STENCIL_BUFFER);
|
||||
}
|
||||
#endif
|
||||
@@ -1135,12 +1135,24 @@ namespace thermion_filament
|
||||
void FilamentViewer::capture(View *view, uint8_t *out, bool useFence, SwapChain *swapChain, RenderTarget *renderTarget, void (*onComplete)())
|
||||
{
|
||||
|
||||
if (!renderTarget)
|
||||
{
|
||||
Log("NO SWAPCHAIN");
|
||||
if (!(renderTarget || swapChain)) {
|
||||
Log("NO RENDER TARGET OR SWAPCHAIN");
|
||||
return;
|
||||
}
|
||||
|
||||
if(swapChain && !_engine->isValid(swapChain)) {
|
||||
Log("SWAPCHAIN PROVIDED BUT NOT VALID");
|
||||
return;
|
||||
}
|
||||
|
||||
int i =0 ;
|
||||
for(auto sc : _swapChains) {
|
||||
if(sc == swapChain) {
|
||||
Log("Using swapchain at index %d", i);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
Viewport const &vp = view->getViewport();
|
||||
size_t pixelBufferSize = vp.width * vp.height * 4;
|
||||
auto *pixelBuffer = new uint8_t[pixelBufferSize];
|
||||
|
||||
@@ -528,13 +528,18 @@ namespace thermion_filament
|
||||
asset.second->getLightEntityCount());
|
||||
_assetLoader->destroyAsset(asset.second);
|
||||
}
|
||||
for(auto* texture : _textures) {
|
||||
for(auto *texture : _textures) {
|
||||
_engine->destroy(texture);
|
||||
}
|
||||
|
||||
for(auto *materialInstance : _materialInstances) {
|
||||
_engine->destroy(materialInstance);
|
||||
}
|
||||
|
||||
// TODO - free geometry?
|
||||
_textures.clear();
|
||||
_assets.clear();
|
||||
_materialInstances.clear();
|
||||
}
|
||||
|
||||
FilamentInstance *SceneManager::getInstanceByEntityId(EntityId entityId)
|
||||
@@ -2453,6 +2458,7 @@ EntityId SceneManager::createGeometry(
|
||||
}
|
||||
materialInstance->setParameter("baseColorFactor", RgbaType::sRGB, filament::math::float4{1.0f, 0.0f, 1.0f, 1.0f});
|
||||
materialInstance->setParameter("baseColorIndex", 0);
|
||||
_materialInstances.push_back(materialInstance);
|
||||
return materialInstance;
|
||||
}
|
||||
|
||||
@@ -2460,6 +2466,7 @@ EntityId SceneManager::createGeometry(
|
||||
UvMap uvmap;
|
||||
auto instance = _unlitMaterialProvider->createMaterialInstance(nullptr, &uvmap);
|
||||
instance->setParameter("uvScale", filament::math::float2 { 1.0f, 1.0f });
|
||||
_materialInstances.push_back(instance);
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,27 +1,33 @@
|
||||
#ifdef _WIN32
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
#pragma comment(lib, "opengl32.lib")
|
||||
#endif
|
||||
|
||||
#include "ResourceBuffer.hpp"
|
||||
#include "FilamentViewer.hpp"
|
||||
#include "filament/LightManager.h"
|
||||
#include "Log.hpp"
|
||||
#include "ThreadPool.hpp"
|
||||
|
||||
#include <thread>
|
||||
#include <functional>
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten/emscripten.h>
|
||||
#endif
|
||||
|
||||
using namespace thermion_filament;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <filament/View.h>
|
||||
#include <filament/Viewport.h>
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/ToneMapper.h>
|
||||
#include <filament/ColorGrading.h>
|
||||
|
||||
#include "ThermionDartApi.h"
|
||||
#include "TView.h"
|
||||
#include "Log.hpp"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace thermion {
|
||||
extern "C"
|
||||
{
|
||||
using namespace filament;
|
||||
|
||||
#endif
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TViewport View_getViewport(TView *tView)
|
||||
{
|
||||
auto view = reinterpret_cast<View *>(tView);
|
||||
auto & vp = view->getViewport();
|
||||
TViewport tvp;
|
||||
tvp.left = vp.left;
|
||||
tvp.bottom = vp.bottom;
|
||||
tvp.width = vp.width;
|
||||
tvp.height = vp.height;
|
||||
return tvp;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void View_updateViewport(TView *tView, uint32_t width, uint32_t height)
|
||||
{
|
||||
@@ -54,10 +60,10 @@ extern "C"
|
||||
view->setShadowingEnabled(enabled);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void View_setShadowType(TView *tView, ShadowType shadowType)
|
||||
EMSCRIPTEN_KEEPALIVE void View_setShadowType(TView *tView, int shadowType)
|
||||
{
|
||||
auto view = reinterpret_cast<View *>(tView);
|
||||
view->setShadowType(shadowType);
|
||||
view->setShadowType((ShadowType)shadowType);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void View_setSoftShadowOptions(TView *tView, float penumbraScale, float penumbraRatioScale)
|
||||
@@ -80,7 +86,7 @@ extern "C"
|
||||
#endif
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void View_setToneMapping(TView *tView, TEngine *tEngine, int toneMapping)
|
||||
EMSCRIPTEN_KEEPALIVE void View_setToneMapping(TView *tView, TEngine *tEngine, ToneMapping toneMapping)
|
||||
{
|
||||
auto view = reinterpret_cast<View *>(tView);
|
||||
auto engine = reinterpret_cast<Engine *>(tEngine);
|
||||
@@ -139,4 +145,8 @@ extern "C"
|
||||
view->setCamera(camera);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
181
thermion_dart/test/geometry_tests.dart
Normal file
181
thermion_dart/test/geometry_tests.dart
Normal file
@@ -0,0 +1,181 @@
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
|
||||
import 'helpers.dart';
|
||||
|
||||
void main() async {
|
||||
final testHelper = TestHelper("geometry");
|
||||
group("custom geometry", () {
|
||||
test('create cube (no uvs/normals)', () async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
await viewer.addLight(LightType.SUN, 6500, 1000000, 0, 0, 0, 0, 0, -1);
|
||||
await viewer.setCameraPosition(0, 2, 6);
|
||||
await viewer
|
||||
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8));
|
||||
await viewer.setBackgroundColor(1.0, 1.0, 1.0, 1.0);
|
||||
await viewer
|
||||
.createGeometry(GeometryHelper.cube(normals: false, uvs: false));
|
||||
|
||||
await testHelper.capture(viewer, "geometry_cube_no_uv_no_normal");
|
||||
});
|
||||
|
||||
test('create cube (no normals)', () async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
var light = await viewer.addLight(
|
||||
LightType.POINT, 6500, 10000000, 0, 2, 0, 0, 0, 0,
|
||||
falloffRadius: 100.0);
|
||||
await viewer.setCameraPosition(0, 2, 6);
|
||||
await viewer
|
||||
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8));
|
||||
await viewer.setBackgroundColor(1.0, 0.0, 1.0, 1.0);
|
||||
await viewer
|
||||
.createGeometry(GeometryHelper.cube(normals: false, uvs: false));
|
||||
await testHelper.capture(viewer, "geometry_cube_no_normals");
|
||||
});
|
||||
|
||||
test('create cube (with normals)', () async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
|
||||
var light = await viewer.addLight(
|
||||
LightType.POINT, 6500, 10000000, 0, 2, 0, 0, 0, 0,
|
||||
falloffRadius: 100.0);
|
||||
await viewer.setCameraPosition(0, 2, 6);
|
||||
await viewer
|
||||
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8));
|
||||
await viewer.setBackgroundColor(1.0, 1.0, 1.0, 1.0);
|
||||
await viewer
|
||||
.createGeometry(GeometryHelper.cube(normals: true, uvs: false));
|
||||
await testHelper.capture(viewer, "geometry_cube_with_normals");
|
||||
});
|
||||
|
||||
test('create cube with custom ubershader material instance (color)',
|
||||
() async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
await viewer.addLight(LightType.SUN, 6500, 1000000, 0, 0, 0, 0, 0, -1);
|
||||
await viewer.setCameraPosition(0, 2, 6);
|
||||
await viewer
|
||||
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8));
|
||||
await viewer.setBackgroundColor(1.0, 0.0, 1.0, 1.0);
|
||||
|
||||
var materialInstance =
|
||||
await viewer.createUbershaderMaterialInstance(unlit: true);
|
||||
final cube = await viewer.createGeometry(
|
||||
GeometryHelper.cube(uvs: false, normals: true),
|
||||
materialInstance: materialInstance);
|
||||
await viewer.setMaterialPropertyFloat4(
|
||||
cube, "baseColorFactor", 0, 0.0, 1.0, 0.0, 0.0);
|
||||
await testHelper.capture(
|
||||
viewer, "geometry_cube_with_custom_material_ubershader");
|
||||
await viewer.removeEntity(cube);
|
||||
await viewer.destroyMaterialInstance(materialInstance);
|
||||
});
|
||||
|
||||
test('create cube with custom ubershader material instance (texture)',
|
||||
() async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
await viewer.addLight(LightType.SUN, 6500, 1000000, 0, 0, 0, 0, 0, -1);
|
||||
await viewer.setCameraPosition(0, 2, 6);
|
||||
await viewer
|
||||
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8));
|
||||
await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0);
|
||||
|
||||
var materialInstance = await viewer.createUbershaderMaterialInstance();
|
||||
final cube = await viewer.createGeometry(
|
||||
GeometryHelper.cube(uvs: true, normals: true),
|
||||
materialInstance: materialInstance);
|
||||
var textureData =
|
||||
File("${testHelper.testDir}/assets/cube_texture_512x512.png")
|
||||
.readAsBytesSync();
|
||||
var texture = await viewer.createTexture(textureData);
|
||||
await viewer.applyTexture(texture as ThermionFFITexture, cube);
|
||||
await testHelper.capture(
|
||||
viewer, "geometry_cube_with_custom_material_ubershader_texture");
|
||||
await viewer.removeEntity(cube);
|
||||
await viewer.destroyMaterialInstance(materialInstance);
|
||||
await viewer.destroyTexture(texture);
|
||||
});
|
||||
|
||||
test('unlit material with color only', () async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
await viewer.setCameraPosition(0, 0, 6);
|
||||
await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0);
|
||||
await viewer.setPostProcessing(true);
|
||||
await viewer.setToneMapping(ToneMapper.LINEAR);
|
||||
|
||||
var materialInstance = await viewer.createUnlitMaterialInstance();
|
||||
var cube = await viewer.createGeometry(GeometryHelper.cube(),
|
||||
materialInstance: materialInstance);
|
||||
|
||||
await viewer.setMaterialPropertyFloat4(
|
||||
cube, "baseColorFactor", 0, 0.0, 1.0, 0.0, 1.0);
|
||||
|
||||
await testHelper.capture(viewer, "unlit_material_base_color");
|
||||
|
||||
await viewer.dispose();
|
||||
});
|
||||
|
||||
test('create cube with custom material instance (unlit)', () async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
await viewer.setCameraPosition(0, 2, 6);
|
||||
await viewer
|
||||
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8));
|
||||
await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0);
|
||||
await viewer.setPostProcessing(true);
|
||||
await viewer.setToneMapping(ToneMapper.LINEAR);
|
||||
|
||||
var materialInstance = await viewer.createUnlitMaterialInstance();
|
||||
var cube = await viewer.createGeometry(GeometryHelper.cube(),
|
||||
materialInstance: materialInstance);
|
||||
|
||||
var textureData =
|
||||
File("${testHelper.testDir}/assets/cube_texture_512x512.png")
|
||||
.readAsBytesSync();
|
||||
var texture = await viewer.createTexture(textureData);
|
||||
await viewer.applyTexture(texture, cube);
|
||||
await testHelper.capture(
|
||||
viewer, "geometry_cube_with_custom_material_unlit_texture_only");
|
||||
await viewer.removeEntity(cube);
|
||||
|
||||
cube = await viewer.createGeometry(GeometryHelper.cube(),
|
||||
materialInstance: materialInstance);
|
||||
// reusing same material instance, so set baseColorIndex to -1 to disable the texture
|
||||
await viewer.setMaterialPropertyInt(cube, "baseColorIndex", 0, -1);
|
||||
await viewer.setMaterialPropertyFloat4(
|
||||
cube, "baseColorFactor", 0, 0.0, 1.0, 0.0, 1.0);
|
||||
await testHelper.capture(
|
||||
viewer, "geometry_cube_with_custom_material_unlit_color_only");
|
||||
await viewer.removeEntity(cube);
|
||||
|
||||
cube = await viewer.createGeometry(GeometryHelper.cube(),
|
||||
materialInstance: materialInstance);
|
||||
// now set baseColorIndex to 0 to enable the texture and the base color
|
||||
await viewer.setMaterialPropertyInt(cube, "baseColorIndex", 0, 0);
|
||||
await viewer.setMaterialPropertyFloat4(
|
||||
cube, "baseColorFactor", 0, 0.0, 1.0, 0.0, 0.5);
|
||||
await viewer.applyTexture(texture, cube);
|
||||
|
||||
await testHelper.capture(
|
||||
viewer, "geometry_cube_with_custom_material_unlit_color_and_texture");
|
||||
|
||||
await viewer.removeEntity(cube);
|
||||
|
||||
await viewer.destroyTexture(texture);
|
||||
await viewer.destroyMaterialInstance(materialInstance);
|
||||
await viewer.dispose();
|
||||
});
|
||||
|
||||
test('create sphere (no normals)', () async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
await viewer.setBackgroundColor(0.0, 0.0, 1.0, 1.0);
|
||||
await viewer.setCameraPosition(0, 0, 6);
|
||||
await viewer
|
||||
.createGeometry(GeometryHelper.sphere(normals: false, uvs: false));
|
||||
await testHelper.capture(viewer, "geometry_sphere_no_normals");
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import 'package:thermion_dart/src/utils/dart_resources.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/thermion_viewer_ffi.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/shared_types/view.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
@@ -66,7 +67,6 @@ Future<Uint8List> savePixelBufferToBmp(
|
||||
|
||||
class TestHelper {
|
||||
late SwapChain swapChain;
|
||||
late RenderTarget renderTarget;
|
||||
late Directory outDir;
|
||||
late String testDir;
|
||||
|
||||
@@ -79,15 +79,18 @@ class TestHelper {
|
||||
outDir.createSync();
|
||||
}
|
||||
|
||||
Future capture(ThermionViewer viewer, String outputFilename, { SwapChain? swapChain, RenderTarget? renderTarget}) async {
|
||||
Future capture(ThermionViewer viewer, String outputFilename,
|
||||
{View? view, SwapChain? swapChain, RenderTarget? renderTarget}) async {
|
||||
await Future.delayed(Duration(milliseconds: 10));
|
||||
var outPath = p.join(outDir.path, "$outputFilename.bmp");
|
||||
var pixelBuffer =
|
||||
await viewer.capture(swapChain ?? this.swapChain, renderTarget: renderTarget);
|
||||
var pixelBuffer = await viewer.capture(
|
||||
view: view, swapChain ?? this.swapChain, renderTarget: renderTarget);
|
||||
view ??= await viewer.getViewAt(0);
|
||||
var vp = await view.getViewport();
|
||||
await savePixelBufferToBmp(
|
||||
pixelBuffer,
|
||||
viewer.viewportDimensions.$1.toInt(),
|
||||
viewer.viewportDimensions.$2.toInt(),
|
||||
vp.width,
|
||||
vp.height,
|
||||
outPath);
|
||||
return pixelBuffer;
|
||||
}
|
||||
@@ -105,8 +108,8 @@ class TestHelper {
|
||||
{img.Color? bg,
|
||||
Vector3? cameraPosition,
|
||||
viewportDimensions = (width: 500, height: 500)}) async {
|
||||
final texture =
|
||||
await createTexture(viewportDimensions.width, viewportDimensions.height);
|
||||
final texture = await createTexture(
|
||||
viewportDimensions.width, viewportDimensions.height);
|
||||
|
||||
final resourceLoader = calloc<ResourceLoaderWrapper>(1);
|
||||
var loadToOut = NativeCallable<
|
||||
@@ -123,10 +126,7 @@ class TestHelper {
|
||||
await viewer.initialized;
|
||||
swapChain = await viewer.createSwapChain(
|
||||
viewportDimensions.width, viewportDimensions.height);
|
||||
renderTarget = await viewer.createRenderTarget(viewportDimensions.width,
|
||||
viewportDimensions.height, texture);
|
||||
|
||||
// await viewer.setRenderTarget(renderTarget as FFIRenderTarget);
|
||||
await viewer.updateViewportAndCameraProjection(
|
||||
viewportDimensions.width.toDouble(),
|
||||
viewportDimensions.height.toDouble());
|
||||
|
||||
@@ -161,173 +161,7 @@ void main() async {
|
||||
});
|
||||
});
|
||||
|
||||
group("custom geometry", () {
|
||||
test('create cube (no uvs/normals)', () async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
await viewer.addLight(LightType.SUN, 6500, 1000000, 0, 0, 0, 0, 0, -1);
|
||||
await viewer.setCameraPosition(0, 2, 6);
|
||||
await viewer
|
||||
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8));
|
||||
await viewer.setBackgroundColor(1.0, 1.0, 1.0, 1.0);
|
||||
await viewer
|
||||
.createGeometry(GeometryHelper.cube(normals: false, uvs: false));
|
||||
|
||||
await testHelper.capture(viewer, "geometry_cube_no_uv_no_normal");
|
||||
});
|
||||
|
||||
test('create cube (no normals)', () async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
var light = await viewer.addLight(
|
||||
LightType.POINT, 6500, 10000000, 0, 2, 0, 0, 0, 0,
|
||||
falloffRadius: 100.0);
|
||||
await viewer.setCameraPosition(0, 2, 6);
|
||||
await viewer
|
||||
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8));
|
||||
await viewer.setBackgroundColor(1.0, 0.0, 1.0, 1.0);
|
||||
await viewer
|
||||
.createGeometry(GeometryHelper.cube(normals: false, uvs: false));
|
||||
await testHelper.capture(viewer, "geometry_cube_no_normals");
|
||||
});
|
||||
|
||||
test('create cube (with normals)', () async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
|
||||
var light = await viewer.addLight(
|
||||
LightType.POINT, 6500, 10000000, 0, 2, 0, 0, 0, 0,
|
||||
falloffRadius: 100.0);
|
||||
await viewer.setCameraPosition(0, 2, 6);
|
||||
await viewer
|
||||
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8));
|
||||
await viewer.setBackgroundColor(1.0, 1.0, 1.0, 1.0);
|
||||
await viewer
|
||||
.createGeometry(GeometryHelper.cube(normals: true, uvs: false));
|
||||
await testHelper.capture(viewer, "geometry_cube_with_normals");
|
||||
});
|
||||
|
||||
test('create cube with custom ubershader material instance (color)',
|
||||
() async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
await viewer.addLight(LightType.SUN, 6500, 1000000, 0, 0, 0, 0, 0, -1);
|
||||
await viewer.setCameraPosition(0, 2, 6);
|
||||
await viewer
|
||||
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8));
|
||||
await viewer.setBackgroundColor(1.0, 0.0, 1.0, 1.0);
|
||||
|
||||
var materialInstance =
|
||||
await viewer.createUbershaderMaterialInstance(unlit: true);
|
||||
final cube = await viewer.createGeometry(
|
||||
GeometryHelper.cube(uvs: false, normals: true),
|
||||
materialInstance: materialInstance);
|
||||
await viewer.setMaterialPropertyFloat4(
|
||||
cube, "baseColorFactor", 0, 0.0, 1.0, 0.0, 0.0);
|
||||
await testHelper.capture(
|
||||
viewer, "geometry_cube_with_custom_material_ubershader");
|
||||
await viewer.removeEntity(cube);
|
||||
await viewer.destroyMaterialInstance(materialInstance);
|
||||
});
|
||||
|
||||
test('create cube with custom ubershader material instance (texture)',
|
||||
() async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
await viewer.addLight(LightType.SUN, 6500, 1000000, 0, 0, 0, 0, 0, -1);
|
||||
await viewer.setCameraPosition(0, 2, 6);
|
||||
await viewer
|
||||
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8));
|
||||
await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0);
|
||||
|
||||
var materialInstance = await viewer.createUbershaderMaterialInstance();
|
||||
final cube = await viewer.createGeometry(
|
||||
GeometryHelper.cube(uvs: true, normals: true),
|
||||
materialInstance: materialInstance);
|
||||
var textureData =
|
||||
File("${testHelper.testDir}/assets/cube_texture_512x512.png").readAsBytesSync();
|
||||
var texture = await viewer.createTexture(textureData);
|
||||
await viewer.applyTexture(texture as ThermionFFITexture, cube);
|
||||
await testHelper.capture(
|
||||
viewer, "geometry_cube_with_custom_material_ubershader_texture");
|
||||
await viewer.removeEntity(cube);
|
||||
await viewer.destroyMaterialInstance(materialInstance);
|
||||
await viewer.destroyTexture(texture);
|
||||
});
|
||||
|
||||
test('unlit material with color only', () async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
await viewer.setCameraPosition(0, 0, 6);
|
||||
await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0);
|
||||
await viewer.setPostProcessing(true);
|
||||
await viewer.setToneMapping(ToneMapper.LINEAR);
|
||||
|
||||
var materialInstance = await viewer.createUnlitMaterialInstance();
|
||||
var cube = await viewer.createGeometry(GeometryHelper.cube(),
|
||||
materialInstance: materialInstance);
|
||||
|
||||
await viewer.setMaterialPropertyFloat4(
|
||||
cube, "baseColorFactor", 0, 0.0, 1.0, 0.0, 1.0);
|
||||
|
||||
await testHelper.capture(viewer, "unlit_material_base_color");
|
||||
|
||||
await viewer.dispose();
|
||||
});
|
||||
|
||||
test('create cube with custom material instance (unlit)', () async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
await viewer.setCameraPosition(0, 2, 6);
|
||||
await viewer
|
||||
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8));
|
||||
await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0);
|
||||
await viewer.setPostProcessing(true);
|
||||
await viewer.setToneMapping(ToneMapper.LINEAR);
|
||||
|
||||
var materialInstance = await viewer.createUnlitMaterialInstance();
|
||||
var cube = await viewer.createGeometry(GeometryHelper.cube(),
|
||||
materialInstance: materialInstance);
|
||||
|
||||
var textureData =
|
||||
File("${testHelper.testDir}/assets/cube_texture_512x512.png").readAsBytesSync();
|
||||
var texture = await viewer.createTexture(textureData);
|
||||
await viewer.applyTexture(texture, cube);
|
||||
await testHelper.capture(
|
||||
viewer, "geometry_cube_with_custom_material_unlit_texture_only");
|
||||
await viewer.removeEntity(cube);
|
||||
|
||||
cube = await viewer.createGeometry(GeometryHelper.cube(),
|
||||
materialInstance: materialInstance);
|
||||
// reusing same material instance, so set baseColorIndex to -1 to disable the texture
|
||||
await viewer.setMaterialPropertyInt(cube, "baseColorIndex", 0, -1);
|
||||
await viewer.setMaterialPropertyFloat4(
|
||||
cube, "baseColorFactor", 0, 0.0, 1.0, 0.0, 1.0);
|
||||
await testHelper.capture(
|
||||
viewer, "geometry_cube_with_custom_material_unlit_color_only");
|
||||
await viewer.removeEntity(cube);
|
||||
|
||||
cube = await viewer.createGeometry(GeometryHelper.cube(),
|
||||
materialInstance: materialInstance);
|
||||
// now set baseColorIndex to 0 to enable the texture and the base color
|
||||
await viewer.setMaterialPropertyInt(cube, "baseColorIndex", 0, 0);
|
||||
await viewer.setMaterialPropertyFloat4(
|
||||
cube, "baseColorFactor", 0, 0.0, 1.0, 0.0, 0.5);
|
||||
await viewer.applyTexture(texture, cube);
|
||||
|
||||
await testHelper.capture(
|
||||
viewer, "geometry_cube_with_custom_material_unlit_color_and_texture");
|
||||
|
||||
await viewer.removeEntity(cube);
|
||||
|
||||
await viewer.destroyTexture(texture);
|
||||
await viewer.destroyMaterialInstance(materialInstance);
|
||||
await viewer.dispose();
|
||||
});
|
||||
|
||||
test('create sphere (no normals)', () async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
await viewer.setBackgroundColor(0.0, 0.0, 1.0, 1.0);
|
||||
await viewer.setCameraPosition(0, 0, 6);
|
||||
await viewer
|
||||
.createGeometry(GeometryHelper.sphere(normals: false, uvs: false));
|
||||
await testHelper.capture(viewer, "geometry_sphere_no_normals");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
group("MaterialInstance", () {
|
||||
test('disable depth write', () async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
|
||||
@@ -1,20 +1,118 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
import 'helpers.dart';
|
||||
|
||||
void main() async {
|
||||
final testHelper = TestHelper("view");
|
||||
|
||||
group('view tests', () {
|
||||
test('create view', () async {
|
||||
test('one swapchain, render view to render target', () async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
final renderTarget = await viewer.createRenderTarget(
|
||||
200, 400, await testHelper.createTexture(200, 400));
|
||||
|
||||
final texture = await testHelper.createTexture(500, 500);
|
||||
final renderTarget = await viewer.createRenderTarget(500, 500, texture);
|
||||
viewer.setRenderTarget(renderTarget);
|
||||
|
||||
await viewer.setBackgroundColor(1.0, 0, 0, 1);
|
||||
final cube = await viewer.createGeometry(GeometryHelper.cube());
|
||||
|
||||
var mainCamera = await viewer.getMainCamera();
|
||||
mainCamera.setTransform(Matrix4.translation(Vector3(0, 0, 5)));
|
||||
await testHelper.capture(
|
||||
viewer,
|
||||
renderTarget: renderTarget,
|
||||
"default_swapchain_default_view_render_target");
|
||||
});
|
||||
|
||||
test('create secondary view, same swapchain', () async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
await viewer.setBackgroundColor(1.0, 0, 0, 1);
|
||||
final cube = await viewer.createGeometry(GeometryHelper.cube());
|
||||
|
||||
var mainCamera = await viewer.getMainCamera();
|
||||
mainCamera.setTransform(Matrix4.translation(Vector3(0, 0, 5)));
|
||||
await testHelper.capture(viewer, "default_swapchain_default_view");
|
||||
|
||||
final view = await viewer.createView();
|
||||
|
||||
await view.updateViewport(200, 400);
|
||||
view.updateViewport(500, 500);
|
||||
view.setCamera(mainCamera);
|
||||
await testHelper.capture(
|
||||
viewer,
|
||||
"default_swapchain_new_view_with_main_camera",
|
||||
view: view,
|
||||
);
|
||||
|
||||
var newCamera = await viewer.createCamera();
|
||||
newCamera.setTransform(Matrix4.translation(Vector3(0.0, 0.0, 10.0)));
|
||||
newCamera.setLensProjection();
|
||||
view.setCamera(newCamera);
|
||||
|
||||
await testHelper.capture(
|
||||
viewer,
|
||||
"default_swapchain_new_view_new_camera",
|
||||
view: view,
|
||||
);
|
||||
|
||||
await testHelper.capture(
|
||||
viewer,
|
||||
"default_swapchain_default_view_main_camera_no_change",
|
||||
);
|
||||
|
||||
await viewer.dispose();
|
||||
});
|
||||
|
||||
test('create secondary view, different swapchain', () async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
await viewer.setBackgroundColor(1.0, 0, 0, 1);
|
||||
final cube = await viewer.createGeometry(GeometryHelper.cube());
|
||||
|
||||
var mainCamera = await viewer.getMainCamera();
|
||||
mainCamera.setTransform(Matrix4.translation(Vector3(0, 0, 5)));
|
||||
final swapChain = await viewer.createSwapChain(200, 400);
|
||||
await testHelper.capture(
|
||||
viewer, "create_swapchain_default_view_default_swapchain");
|
||||
|
||||
final view = await viewer.createView();
|
||||
|
||||
final texture = await testHelper.createTexture(400, 400);
|
||||
final renderTarget = await viewer.createRenderTarget(400, 400, texture);
|
||||
await view.setRenderTarget(renderTarget);
|
||||
await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0);
|
||||
await testHelper.capture(viewer, "create_view_with_render_target", renderTarget: renderTarget);
|
||||
|
||||
await view.updateViewport(400, 400);
|
||||
view.setCamera(mainCamera);
|
||||
|
||||
await testHelper.capture(
|
||||
viewer,
|
||||
view: view,
|
||||
swapChain: swapChain,
|
||||
renderTarget: renderTarget,
|
||||
"create_swapchain_new_view_new_swapchain",
|
||||
);
|
||||
|
||||
// var newCamera = await viewer.createCamera();
|
||||
// newCamera.setTransform(Matrix4.translation(Vector3(0.0, 0.0, 10.0)));
|
||||
// newCamera.setLensProjection();
|
||||
// view.setCamera(newCamera);
|
||||
|
||||
// await testHelper.capture(
|
||||
// viewer,
|
||||
// "created_view_with_new_camera",
|
||||
// view: view,
|
||||
// );
|
||||
|
||||
// await testHelper.capture(
|
||||
// viewer,
|
||||
// "default_view_main_camera_no_change",
|
||||
// );
|
||||
|
||||
// // await view.updateViewport(200, 400);
|
||||
// // await view.setRenderTarget(renderTarget);
|
||||
// // await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0);
|
||||
// // await testHelper.capture(viewer, "create_view_with_render_target",
|
||||
// // renderTarget: renderTarget);
|
||||
await viewer.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user