feature!:
This is a breaking change needed to fully implement instancing and stencil highlighting.
Previously, users would work directly with entities (on the Dart side, ThermionEntity), e.g.
final entity = await viewer.loadGlb("some.glb");
However, Filament "entities" are a lower-level abstraction.
Loading a glTF file, for example, inserts multiple entities into the scene.
For example, each mesh, light, and camera within a glTF asset will be assigned an entity. A top-level (non-renderable) entity will also be created for the glTF asset, which can be used to transform the entire hierarchy.
"Asset" is a better representation for loading/inserting objects into the scene; think of this as a bundle of entities.
Unless you need to work directly with transforms, instancing, materials and renderables, you can work directly with ThermionAsset.
This commit is contained in:
@@ -1,21 +1,11 @@
|
||||
output: '../lib/src/viewer/src/ffi/src/thermion_dart.g.dart'
|
||||
headers:
|
||||
entry-points:
|
||||
- '../native/include/ThermionDartRenderThreadApi.h'
|
||||
- '../native/include/ThermionDartApi.h'
|
||||
- '../native/include/TView.h'
|
||||
- '../native/include/TCamera.h'
|
||||
- '../native/include/TGizmo.h'
|
||||
- '../native/include/c_api/*.h'
|
||||
- '../native/include/ResourceBuffer.h'
|
||||
include-directives:
|
||||
- '../native/include/ThermionDartRenderThreadApi.h'
|
||||
- '../native/include/ThermionDartApi.h'
|
||||
- '../native/include/TView.h'
|
||||
- '../native/include/TCamera.h'
|
||||
- '../native/include/TGizmo.h'
|
||||
- '../native/include/TMaterialInstance.h'
|
||||
- '../native/include/c_api/*.h'
|
||||
- '../native/include/ResourceBuffer.h'
|
||||
- '../native/include/APIBoundaryTypes.h'
|
||||
ffi-native:
|
||||
assetId: package:thermion_dart/thermion_dart.dart
|
||||
ignore-source-errors: true
|
||||
|
||||
@@ -4,4 +4,6 @@ export 'src/input_handler.dart';
|
||||
export 'src/delegates.dart';
|
||||
export 'src/delegate_input_handler.dart';
|
||||
export 'src/implementations/default_pick_delegate.dart';
|
||||
export 'src/implementations/gizmo_pick_delegate.dart';
|
||||
export 'src/implementations/gizmo_input_handler.dart';
|
||||
export 'src/implementations/third_person_camera_delegate.dart';
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
@@ -54,6 +53,13 @@ class DelegateInputHandler implements InputHandler {
|
||||
_actions = actions;
|
||||
}
|
||||
|
||||
if (pickDelegate != null) {
|
||||
if (_actions[InputType.LMB_DOWN] != null) {
|
||||
throw Exception();
|
||||
}
|
||||
_actions[InputType.LMB_DOWN] = InputAction.PICK;
|
||||
}
|
||||
|
||||
for (var gestureType in InputType.values) {
|
||||
_inputDeltas[gestureType] = Vector3.zero();
|
||||
}
|
||||
@@ -94,7 +100,7 @@ class DelegateInputHandler implements InputHandler {
|
||||
clampY: clampY,
|
||||
entity: entity,
|
||||
rotationSensitivity: rotateSensitivity,
|
||||
zoomSensitivity:zoomSensitivity,
|
||||
zoomSensitivity: zoomSensitivity,
|
||||
panSensitivity: panSensitivity,
|
||||
movementSensitivity: movementSensitivity),
|
||||
actions: {
|
||||
@@ -265,7 +271,8 @@ class DelegateInputHandler implements InputHandler {
|
||||
Future<void> onScaleEnd(int pointerCount, double velocity) async {}
|
||||
|
||||
@override
|
||||
Future<void> onScaleStart(Vector2 localPosition, int pointerCount, Duration? sourceTimestamp ) async {
|
||||
Future<void> onScaleStart(Vector2 localPosition, int pointerCount,
|
||||
Duration? sourceTimestamp) async {
|
||||
// noop
|
||||
}
|
||||
|
||||
|
||||
@@ -24,4 +24,5 @@ abstract class VelocityDelegate {
|
||||
abstract class PickDelegate {
|
||||
const PickDelegate();
|
||||
void pick(Vector2 location);
|
||||
Future dispose();
|
||||
}
|
||||
|
||||
@@ -1,13 +1,24 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
|
||||
class DefaultPickDelegate extends PickDelegate {
|
||||
final ThermionViewer viewer;
|
||||
|
||||
const DefaultPickDelegate(this.viewer);
|
||||
DefaultPickDelegate(this.viewer);
|
||||
|
||||
final _picked = StreamController<ThermionEntity>();
|
||||
Stream<ThermionEntity> get picked => _picked.stream;
|
||||
|
||||
Future dispose() async {
|
||||
_picked.close();
|
||||
}
|
||||
|
||||
@override
|
||||
void pick(Vector2 location) {
|
||||
viewer.pick(location.x.toInt(), location.y.toInt());
|
||||
viewer.pick(location.x.toInt(), location.y.toInt(), (result) {
|
||||
_picked.sink.add(result.entity);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,13 +86,14 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
|
||||
if (_queuedRotationDelta.length2 > 0.0) {
|
||||
double deltaX = _queuedRotationDelta.x * rotationSensitivity;
|
||||
double deltaY = _queuedRotationDelta.y * rotationSensitivity;
|
||||
relativeRotation = Quaternion.axisAngle(current.up, -deltaX) * Quaternion.axisAngle(current.right, -deltaY);
|
||||
relativeRotation = Quaternion.axisAngle(current.up, -deltaX) *
|
||||
Quaternion.axisAngle(current.right, -deltaY);
|
||||
_queuedRotationDelta = Vector2.zero();
|
||||
}
|
||||
|
||||
// Apply (mouse) pan
|
||||
if (_queuedTranslateDelta.length2 > 0.0) {
|
||||
double deltaX = _queuedTranslateDelta.x * panSensitivity;
|
||||
double deltaX = -_queuedTranslateDelta.x * panSensitivity;
|
||||
double deltaY = _queuedTranslateDelta.y * panSensitivity;
|
||||
double deltaZ = -_queuedTranslateDelta.z * panSensitivity;
|
||||
|
||||
@@ -104,8 +105,9 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
|
||||
|
||||
// Apply zoom
|
||||
if (_queuedZoomDelta != 0.0) {
|
||||
relativeTranslation += current.forward
|
||||
..scaled(_queuedZoomDelta * zoomSensitivity);
|
||||
var zoomTranslation = current.forward..scaled(zoomSensitivity);
|
||||
zoomTranslation.scale(_queuedZoomDelta);
|
||||
relativeTranslation += zoomTranslation;
|
||||
_queuedZoomDelta = 0.0;
|
||||
}
|
||||
|
||||
@@ -128,11 +130,10 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
|
||||
|
||||
await viewer.setTransform(
|
||||
await entity,
|
||||
|
||||
Matrix4.compose(
|
||||
relativeTranslation, relativeRotation, Vector3(1, 1, 1)) * current );
|
||||
Matrix4.compose(
|
||||
relativeTranslation, relativeRotation, Vector3(1, 1, 1)) *
|
||||
current);
|
||||
|
||||
_executing = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
import 'dart:async';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
|
||||
class _Gizmo {
|
||||
bool isVisible = false;
|
||||
|
||||
final ThermionViewer viewer;
|
||||
final nonPickable = <ThermionEntity>{};
|
||||
final GizmoAsset _asset;
|
||||
|
||||
_Gizmo(this._asset, this.viewer);
|
||||
|
||||
Axis? _active;
|
||||
Axis? get active => _active;
|
||||
|
||||
Vector3? _activeCords;
|
||||
|
||||
void checkHover(int x, int y) async {
|
||||
_asset.pick(x, y, handler: (result, coords) async {
|
||||
switch (result) {
|
||||
case GizmoPickResultType.None:
|
||||
await _asset.unhighlight();
|
||||
_active = null;
|
||||
break;
|
||||
case GizmoPickResultType.AxisX:
|
||||
_active = Axis.X;
|
||||
_activeCords = coords;
|
||||
|
||||
case GizmoPickResultType.AxisY:
|
||||
_active = Axis.Y;
|
||||
_activeCords = coords;
|
||||
|
||||
case GizmoPickResultType.AxisZ:
|
||||
_active = Axis.Z;
|
||||
_activeCords = coords;
|
||||
|
||||
default:
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Matrix4? gizmoTransform;
|
||||
|
||||
Future attach(ThermionEntity entity) async {
|
||||
if (_asset.nonPickableEntities.contains(entity)) {
|
||||
return;
|
||||
}
|
||||
final transform = await viewer.getWorldTransform(entity);
|
||||
transform.setRotation(Matrix3.identity());
|
||||
transform.setDiagonal(Vector4.all(1.0));
|
||||
await viewer.setTransform(_asset.entity, transform);
|
||||
await viewer.setParent(entity, _asset.entity);
|
||||
if (!isVisible) {
|
||||
await _asset.addToScene();
|
||||
isVisible = true;
|
||||
}
|
||||
gizmoTransform = await viewer.getWorldTransform(_asset.entity);
|
||||
}
|
||||
|
||||
Future detach() async {
|
||||
await _asset.removeFromScene();
|
||||
_active = null;
|
||||
isVisible = false;
|
||||
}
|
||||
|
||||
void _updateTransform(Vector2 currentPosition, Vector2 delta) async {
|
||||
if (gizmoTransform == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var view = await viewer.getViewAt(0);
|
||||
var camera = await viewer.getActiveCamera();
|
||||
|
||||
var viewport = await view.getViewport();
|
||||
|
||||
var projectionMatrix = await viewer.getCameraProjectionMatrix();
|
||||
var viewMatrix = await camera.getViewMatrix();
|
||||
var inverseViewMatrix = await camera.getModelMatrix();
|
||||
var inverseProjectionMatrix = projectionMatrix.clone()..invert();
|
||||
|
||||
// get gizmo position in screenspace
|
||||
var gizmoPositionWorldSpace = gizmoTransform!.getTranslation();
|
||||
Vector4 gizmoClipSpace = projectionMatrix *
|
||||
viewMatrix *
|
||||
Vector4(gizmoPositionWorldSpace.x, gizmoPositionWorldSpace.y,
|
||||
gizmoPositionWorldSpace.z, 1.0);
|
||||
|
||||
var gizmoNdc = gizmoClipSpace / gizmoClipSpace.w;
|
||||
|
||||
var gizmoScreenSpace = Vector2(((gizmoNdc.x / 2) + 0.5) * viewport.width,
|
||||
viewport.height - (((gizmoNdc.y / 2) + 0.5) * viewport.height));
|
||||
|
||||
gizmoScreenSpace += delta;
|
||||
|
||||
gizmoNdc = Vector4(((gizmoScreenSpace.x / viewport.width) - 0.5) * 2,
|
||||
(((gizmoScreenSpace.y / viewport.height)) - 0.5) * -2, gizmoNdc.z, 1.0);
|
||||
|
||||
var gizmoViewSpace = inverseProjectionMatrix * gizmoNdc;
|
||||
gizmoViewSpace /= gizmoViewSpace.w;
|
||||
|
||||
var newPosition = (inverseViewMatrix * gizmoViewSpace).xyz;
|
||||
|
||||
Vector3 worldSpaceDelta = newPosition - gizmoTransform!.getTranslation();
|
||||
worldSpaceDelta.multiply(_active!.asVector());
|
||||
|
||||
gizmoTransform!.setTranslation(gizmoTransform!.getTranslation() + worldSpaceDelta);
|
||||
|
||||
await viewer.setTransform(_asset.entity, gizmoTransform!);
|
||||
}
|
||||
}
|
||||
|
||||
class GizmoInputHandler extends InputHandler {
|
||||
final InputHandler wrapped;
|
||||
final ThermionViewer viewer;
|
||||
late final _Gizmo translationGizmo;
|
||||
|
||||
GizmoInputHandler({required this.wrapped, required this.viewer}) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
final _initialized = Completer<bool>();
|
||||
Future initialize() async {
|
||||
if (_initialized.isCompleted) {
|
||||
throw Exception("Already initialized");
|
||||
}
|
||||
await viewer.initialized;
|
||||
final view = await viewer.getViewAt(0);
|
||||
var translationGizmoAsset =
|
||||
await viewer.createGizmo(view, GizmoType.translation);
|
||||
this.translationGizmo = _Gizmo(translationGizmoAsset, viewer);
|
||||
_initialized.complete(true);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream get cameraUpdated => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
Future dispose() async {
|
||||
await viewer.removeEntity(translationGizmo._asset);
|
||||
}
|
||||
|
||||
@override
|
||||
InputAction? getActionForType(InputType gestureType) {
|
||||
if (gestureType == InputType.LMB_DOWN) {
|
||||
return InputAction.PICK;
|
||||
}
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> get initialized => _initialized.future;
|
||||
|
||||
@override
|
||||
void keyDown(PhysicalKey key) {
|
||||
wrapped.keyDown(key);
|
||||
}
|
||||
|
||||
@override
|
||||
void keyUp(PhysicalKey key) {
|
||||
wrapped.keyDown(key);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onPointerDown(Vector2 localPosition, bool isMiddle) async {
|
||||
if (!_initialized.isCompleted) {
|
||||
return;
|
||||
}
|
||||
await viewer.pick(localPosition.x.toInt(), localPosition.y.toInt(),
|
||||
(result) {
|
||||
translationGizmo.attach(result.entity);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onPointerHover(Vector2 localPosition, Vector2 delta) async {
|
||||
if (!_initialized.isCompleted) {
|
||||
return;
|
||||
}
|
||||
translationGizmo.checkHover(
|
||||
localPosition.x.floor(), localPosition.y.floor());
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onPointerMove(
|
||||
Vector2 localPosition, Vector2 delta, bool isMiddle) async {
|
||||
if (!isMiddle && translationGizmo._active != null) {
|
||||
final scaledDelta = Vector2(
|
||||
delta.x,
|
||||
delta.y,
|
||||
);
|
||||
translationGizmo._updateTransform(localPosition, scaledDelta);
|
||||
return;
|
||||
}
|
||||
return wrapped.onPointerMove(localPosition, delta, isMiddle);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onPointerScroll(
|
||||
Vector2 localPosition, double scrollDelta) async {
|
||||
return wrapped.onPointerScroll(localPosition, scrollDelta);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onPointerUp(bool isMiddle) async {
|
||||
await wrapped.onPointerUp(isMiddle);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onScaleEnd(int pointerCount, double velocity) {
|
||||
return wrapped.onScaleEnd(pointerCount, velocity);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onScaleStart(
|
||||
Vector2 focalPoint, int pointerCount, Duration? sourceTimestamp) {
|
||||
return wrapped.onScaleStart(focalPoint, pointerCount, sourceTimestamp);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onScaleUpdate(
|
||||
Vector2 focalPoint,
|
||||
Vector2 focalPointDelta,
|
||||
double horizontalScale,
|
||||
double verticalScale,
|
||||
double scale,
|
||||
int pointerCount,
|
||||
double rotation,
|
||||
Duration? sourceTimestamp) {
|
||||
return wrapped.onScaleUpdate(focalPoint, focalPointDelta, horizontalScale,
|
||||
verticalScale, scale, pointerCount, rotation, sourceTimestamp);
|
||||
}
|
||||
|
||||
@override
|
||||
void setActionForType(InputType gestureType, InputAction gestureAction) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// import 'dart:async';
|
||||
|
||||
// import 'package:thermion_dart/thermion_dart.dart';
|
||||
// import 'package:vector_math/vector_math_64.dart';
|
||||
|
||||
// class GizmoPickDelegate extends PickDelegate {
|
||||
// final ThermionViewer viewer;
|
||||
// late final GizmoAsset translationGizmo;
|
||||
|
||||
// GizmoPickDelegate(this.viewer) {
|
||||
// initialize();
|
||||
// }
|
||||
|
||||
// bool _initialized = false;
|
||||
// Future initialize() async {
|
||||
// if (_initialized) {
|
||||
// throw Exception("Already initialized");
|
||||
// }
|
||||
// final view = await viewer.getViewAt(0);
|
||||
// translationGizmo = await viewer.createGizmo(view, GizmoType.translation);
|
||||
// await translationGizmo.addToScene();
|
||||
// _initialized = true;
|
||||
// }
|
||||
|
||||
// final _picked = StreamController<ThermionEntity>();
|
||||
// Stream<ThermionEntity> get picked => _picked.stream;
|
||||
|
||||
// Future dispose() async {
|
||||
// _picked.close();
|
||||
// }
|
||||
|
||||
// @override
|
||||
// void pick(Vector2 location) {
|
||||
// if (!_initialized) {
|
||||
// return;
|
||||
// }
|
||||
// viewer.pick(location.x.toInt(), location.y.toInt(), (result) {
|
||||
// translationGizmo.attach(result.entity);
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
@@ -1,230 +1,329 @@
|
||||
// import 'dart:async';
|
||||
|
||||
// import 'package:flutter/gestures.dart';
|
||||
// import 'package:flutter/services.dart';
|
||||
// import 'package:logging/logging.dart';
|
||||
// import 'package:thermion_dart/thermion_dart/entities/abstract_gizmo.dart';
|
||||
// import 'package:thermion_dart/thermion_dart/thermion_viewer.dart';
|
||||
// import 'dart:ui';
|
||||
// import 'package:thermion_dart/thermion_dart/input/input_handler.dart';
|
||||
// import 'package:thermion_dart/thermion_dart.dart';
|
||||
// import 'package:vector_math/vector_math_64.dart';
|
||||
|
||||
// // Renamed implementation
|
||||
// class PickingCameraGestureHandler implements InputHandler {
|
||||
// import '../input_handler.dart';
|
||||
|
||||
// class GizmoPickingHandler implements InputHandler {
|
||||
// final ThermionViewer viewer;
|
||||
// final bool enableCamera;
|
||||
// final bool enablePicking;
|
||||
// final Logger _logger = Logger("PickingCameraGestureHandler");
|
||||
// late final GizmoAsset _translationGizmo;
|
||||
|
||||
// AbstractGizmo? _gizmo;
|
||||
// Timer? _scrollTimer;
|
||||
// ThermionEntity? _highlightedEntity;
|
||||
// StreamSubscription<FilamentPickResult>? _pickResultSubscription;
|
||||
// GizmoPickingHandler(this.viewer) {}
|
||||
|
||||
// bool _gizmoAttached = false;
|
||||
// final _initialized = Completer<bool>();
|
||||
|
||||
// PickingCameraGestureHandler({
|
||||
// required this.viewer,
|
||||
// this.enableCamera = true,
|
||||
// this.enablePicking = true,
|
||||
// }) {
|
||||
// try {
|
||||
// _gizmo = viewer.gizmo;
|
||||
// } catch (err) {
|
||||
// _logger.warning(
|
||||
// "Failed to get gizmo. If you are running on WASM, this is expected");
|
||||
// Future initialize() async {
|
||||
// if (_initialized.isCompleted) {
|
||||
// throw Exception("Already initialized");
|
||||
// }
|
||||
// final view = await viewer.getViewAt(0);
|
||||
// _translationGizmo = await viewer.createGizmo(view, GizmoType.translation);
|
||||
// _initialized.complete(true);
|
||||
// }
|
||||
|
||||
// _pickResultSubscription = viewer.pickResult.listen(_onPickResult);
|
||||
|
||||
// // Add keyboard listener
|
||||
// RawKeyboard.instance.addListener(_handleKeyEvent);
|
||||
// Future dispose() async {
|
||||
// await viewer.removeEntity(_translationGizmo);
|
||||
// }
|
||||
|
||||
// @override
|
||||
// ThermionGestureState get currentState => _currentState;
|
||||
|
||||
// void _handleKeyEvent(RawKeyEvent event) {
|
||||
// if (event is RawKeyDownEvent &&
|
||||
// event.logicalKey == LogicalKeyboardKey.escape) {
|
||||
// _resetToNullState();
|
||||
// }
|
||||
// }
|
||||
|
||||
// void _resetToNullState() async {
|
||||
// _currentState = ThermionGestureState.NULL;
|
||||
// if (_highlightedEntity != null) {
|
||||
// await viewer.removeStencilHighlight(_highlightedEntity!);
|
||||
// _highlightedEntity = null;
|
||||
// }
|
||||
// }
|
||||
|
||||
// void _onPickResult(FilamentPickResult result) async {
|
||||
// var targetEntity = await viewer.getAncestor(result.entity) ?? result.entity;
|
||||
|
||||
// if (_highlightedEntity != targetEntity) {
|
||||
// if (_highlightedEntity != null) {
|
||||
// await viewer.removeStencilHighlight(_highlightedEntity!);
|
||||
// }
|
||||
|
||||
// _highlightedEntity = targetEntity;
|
||||
// if (_highlightedEntity != null) {
|
||||
// await viewer.setStencilHighlight(_highlightedEntity!);
|
||||
// _gizmo?.attach(_highlightedEntity!);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// Stream get cameraUpdated => throw UnimplementedError();
|
||||
|
||||
// @override
|
||||
// Future<void> onPointerHover(Offset localPosition, Offset delta) async {
|
||||
// if (_gizmoAttached) {
|
||||
// _gizmo?.checkHover(localPosition.dx, localPosition.dy);
|
||||
// }
|
||||
|
||||
// if (_highlightedEntity != null) {
|
||||
// await viewer.queuePositionUpdateFromViewportCoords(
|
||||
// _highlightedEntity!,
|
||||
// localPosition.dx,
|
||||
// localPosition.dy,
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Future<void> onPointerScroll(Offset localPosition, double scrollDelta) async {
|
||||
// if (!enableCamera) {
|
||||
// return;
|
||||
// }
|
||||
// if (_currentState == ThermionGestureState.NULL ||
|
||||
// _currentState == ThermionGestureState.ZOOMING) {
|
||||
// await _zoom(localPosition, scrollDelta);
|
||||
// }
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Future<void> onPointerDown(Offset localPosition, int buttons) async {
|
||||
// if (_highlightedEntity != null) {
|
||||
// _resetToNullState();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (enablePicking && buttons != kMiddleMouseButton) {
|
||||
// viewer.pick(localPosition.dx.toInt(), localPosition.dy.toInt());
|
||||
// }
|
||||
|
||||
// if (buttons == kMiddleMouseButton && enableCamera) {
|
||||
// await viewer.rotateStart(localPosition.dx, localPosition.dy);
|
||||
// _currentState = ThermionGestureState.ROTATING;
|
||||
// } else if (buttons == kPrimaryMouseButton && enableCamera) {
|
||||
// await viewer.panStart(localPosition.dx, localPosition.dy);
|
||||
// _currentState = ThermionGestureState.PANNING;
|
||||
// }
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Future<void> onPointerMove(
|
||||
// Offset localPosition, Offset delta, int buttons) async {
|
||||
// if (_highlightedEntity != null) {
|
||||
// await _handleEntityHighlightedMove(localPosition);
|
||||
// return;
|
||||
// }
|
||||
|
||||
// switch (_currentState) {
|
||||
// case ThermionGestureState.NULL:
|
||||
// break;
|
||||
|
||||
// case ThermionGestureState.ROTATING:
|
||||
// if (enableCamera) {
|
||||
// await viewer.rotateUpdate(localPosition.dx, localPosition.dy);
|
||||
// }
|
||||
// break;
|
||||
// case ThermionGestureState.PANNING:
|
||||
// if (enableCamera) {
|
||||
// await viewer.panUpdate(localPosition.dx, localPosition.dy);
|
||||
// }
|
||||
// break;
|
||||
// case ThermionGestureState.ZOOMING:
|
||||
// // ignore
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Future<void> onPointerUp(int buttons) async {
|
||||
// switch (_currentState) {
|
||||
// case ThermionGestureState.ROTATING:
|
||||
// await viewer.rotateEnd();
|
||||
// _currentState = ThermionGestureState.NULL;
|
||||
// break;
|
||||
// case ThermionGestureState.PANNING:
|
||||
// await viewer.panEnd();
|
||||
// _currentState = ThermionGestureState.NULL;
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// Future<void> _handleEntityHighlightedMove(Offset localPosition) async {
|
||||
// if (_highlightedEntity != null) {
|
||||
// await viewer.queuePositionUpdateFromViewportCoords(
|
||||
// _highlightedEntity!,
|
||||
// localPosition.dx,
|
||||
// localPosition.dy,
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
// Future<void> _zoom(Offset localPosition, double scrollDelta) async {
|
||||
// _scrollTimer?.cancel();
|
||||
// _currentState = ThermionGestureState.ZOOMING;
|
||||
// await viewer.zoomBegin();
|
||||
// await viewer.zoomUpdate(
|
||||
// localPosition.dx, localPosition.dy, scrollDelta > 0 ? 1 : -1);
|
||||
|
||||
// _scrollTimer = Timer(const Duration(milliseconds: 100), () async {
|
||||
// await viewer.zoomEnd();
|
||||
// _currentState = ThermionGestureState.NULL;
|
||||
// });
|
||||
// }
|
||||
|
||||
// @override
|
||||
// void dispose() {
|
||||
// _pickResultSubscription?.cancel();
|
||||
// if (_highlightedEntity != null) {
|
||||
// viewer.removeStencilHighlight(_highlightedEntity!);
|
||||
// }
|
||||
// RawKeyboard.instance.removeListener(_handleKeyEvent);
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Future<bool> get initialized => viewer.initialized;
|
||||
|
||||
// @override
|
||||
// InputAction getActionForType(InputType type) {
|
||||
// // TODO: implement getActionForType
|
||||
// InputAction? getActionForType(InputType gestureType) {
|
||||
// throw UnimplementedError();
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Future<void> onScaleEnd() {
|
||||
// Future<bool> get initialized => _initialized.future;
|
||||
|
||||
// @override
|
||||
// void keyDown(PhysicalKey key) {}
|
||||
|
||||
// @override
|
||||
// void keyUp(PhysicalKey key) {}
|
||||
|
||||
// @override
|
||||
// Future<void> onPointerDown(Vector2 localPosition, bool isMiddle) {
|
||||
// viewer.pick(localPosition.x.floor(), localPosition.y.floor(), (axis) {
|
||||
|
||||
// })
|
||||
// // _translationGizmo.pick(
|
||||
// // localPosition.x.floor(), localPosition.y.floor(), (axis) {});
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Future<void> onPointerHover(Vector2 localPosition, Vector2 delta) {
|
||||
// // TODO: implement onPointerHover
|
||||
// throw UnimplementedError();
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Future<void> onPointerMove(
|
||||
// Vector2 localPosition, Vector2 delta, bool isMiddle) {
|
||||
// // TODO: implement onPointerMove
|
||||
// throw UnimplementedError();
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Future<void> onPointerScroll(Vector2 localPosition, double scrollDelta) {
|
||||
// // TODO: implement onPointerScroll
|
||||
// throw UnimplementedError();
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Future<void> onPointerUp(bool isMiddle) {
|
||||
// // TODO: implement onPointerUp
|
||||
// throw UnimplementedError();
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Future<void> onScaleEnd(int pointerCount, double velocity) {
|
||||
// // TODO: implement onScaleEnd
|
||||
// throw UnimplementedError();
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Future<void> onScaleStart() {
|
||||
// Future<void> onScaleStart(
|
||||
// Vector2 focalPoint, int pointerCount, Duration? sourceTimestamp) {
|
||||
// // TODO: implement onScaleStart
|
||||
// throw UnimplementedError();
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Future<void> onScaleUpdate() {
|
||||
// Future<void> onScaleUpdate(
|
||||
// Vector2 focalPoint,
|
||||
// Vector2 focalPointDelta,
|
||||
// double horizontalScale,
|
||||
// double verticalScale,
|
||||
// double scale,
|
||||
// int pointerCount,
|
||||
// double rotation,
|
||||
// Duration? sourceTimestamp) {
|
||||
// // TODO: implement onScaleUpdate
|
||||
// throw UnimplementedError();
|
||||
// }
|
||||
|
||||
// @override
|
||||
// void setActionForType(InputType type, InputAction action) {
|
||||
// void setActionForType(InputType gestureType, InputAction gestureAction) {
|
||||
// // TODO: implement setActionForType
|
||||
// }
|
||||
// }
|
||||
// // final ThermionViewer viewer;
|
||||
// // final bool enableCamera;
|
||||
// // final bool enablePicking;
|
||||
// // final Logger _logger = Logger("PickingCameraGestureHandler");
|
||||
|
||||
// // AbstractGizmo? _gizmo;
|
||||
// // Timer? _scrollTimer;
|
||||
// // ThermionEntity? _highlightedEntity;
|
||||
// // StreamSubscription<FilamentPickResult>? _pickResultSubscription;
|
||||
|
||||
// // bool _gizmoAttached = false;
|
||||
|
||||
// // PickingCameraGestureHandler({
|
||||
// // required this.viewer,
|
||||
// // this.enableCamera = true,
|
||||
// // this.enablePicking = true,
|
||||
// // }) {
|
||||
// // try {
|
||||
// // _gizmo = viewer.gizmo;
|
||||
// // } catch (err) {
|
||||
// // _logger.warning(
|
||||
// // "Failed to get gizmo. If you are running on WASM, this is expected");
|
||||
// // }
|
||||
|
||||
// // _pickResultSubscription = viewer.pickResult.listen(_onPickResult);
|
||||
|
||||
// // // Add keyboard listener
|
||||
// // RawKeyboard.instance.addListener(_handleKeyEvent);
|
||||
// // }
|
||||
|
||||
// // @override
|
||||
// // ThermionGestureState get currentState => _currentState;
|
||||
|
||||
// // void _handleKeyEvent(RawKeyEvent event) {
|
||||
// // if (event is RawKeyDownEvent &&
|
||||
// // event.logicalKey == LogicalKeyboardKey.escape) {
|
||||
// // _resetToNullState();
|
||||
// // }
|
||||
// // }
|
||||
|
||||
// // void _resetToNullState() async {
|
||||
// // _currentState = ThermionGestureState.NULL;
|
||||
// // if (_highlightedEntity != null) {
|
||||
// // await viewer.removeStencilHighlight(_highlightedEntity!);
|
||||
// // _highlightedEntity = null;
|
||||
// // }
|
||||
// // }
|
||||
|
||||
// // void _onPickResult(FilamentPickResult result) async {
|
||||
// // var targetEntity = await viewer.getAncestor(result.entity) ?? result.entity;
|
||||
|
||||
// // if (_highlightedEntity != targetEntity) {
|
||||
// // if (_highlightedEntity != null) {
|
||||
// // await viewer.removeStencilHighlight(_highlightedEntity!);
|
||||
// // }
|
||||
|
||||
// // _highlightedEntity = targetEntity;
|
||||
// // if (_highlightedEntity != null) {
|
||||
// // await viewer.setStencilHighlight(_highlightedEntity!);
|
||||
// // _gizmo?.attach(_highlightedEntity!);
|
||||
// // }
|
||||
// // }
|
||||
// // }
|
||||
|
||||
// // @override
|
||||
// // Future<void> onPointerHover(Offset localPosition, Offset delta) async {
|
||||
// // if (_gizmoAttached) {
|
||||
// // _gizmo?.checkHover(localPosition.dx, localPosition.dy);
|
||||
// // }
|
||||
|
||||
// // if (_highlightedEntity != null) {
|
||||
// // await viewer.queuePositionUpdateFromViewportCoords(
|
||||
// // _highlightedEntity!,
|
||||
// // localPosition.dx,
|
||||
// // localPosition.dy,
|
||||
// // );
|
||||
// // }
|
||||
// // }
|
||||
|
||||
// // @override
|
||||
// // Future<void> onPointerScroll(Offset localPosition, double scrollDelta) async {
|
||||
// // if (!enableCamera) {
|
||||
// // return;
|
||||
// // }
|
||||
// // if (_currentState == ThermionGestureState.NULL ||
|
||||
// // _currentState == ThermionGestureState.ZOOMING) {
|
||||
// // await _zoom(localPosition, scrollDelta);
|
||||
// // }
|
||||
// // }
|
||||
|
||||
// // @override
|
||||
// // Future<void> onPointerDown(Offset localPosition, int buttons) async {
|
||||
// // if (_highlightedEntity != null) {
|
||||
// // _resetToNullState();
|
||||
// // return;
|
||||
// // }
|
||||
|
||||
// // if (enablePicking && buttons != kMiddleMouseButton) {
|
||||
// // viewer.pick(localPosition.dx.toInt(), localPosition.dy.toInt());
|
||||
// // }
|
||||
|
||||
// // if (buttons == kMiddleMouseButton && enableCamera) {
|
||||
// // await viewer.rotateStart(localPosition.dx, localPosition.dy);
|
||||
// // _currentState = ThermionGestureState.ROTATING;
|
||||
// // } else if (buttons == kPrimaryMouseButton && enableCamera) {
|
||||
// // await viewer.panStart(localPosition.dx, localPosition.dy);
|
||||
// // _currentState = ThermionGestureState.PANNING;
|
||||
// // }
|
||||
// // }
|
||||
|
||||
// // @override
|
||||
// // Future<void> onPointerMove(
|
||||
// // Offset localPosition, Offset delta, int buttons) async {
|
||||
// // if (_highlightedEntity != null) {
|
||||
// // await _handleEntityHighlightedMove(localPosition);
|
||||
// // return;
|
||||
// // }
|
||||
|
||||
// // switch (_currentState) {
|
||||
// // case ThermionGestureState.NULL:
|
||||
// // break;
|
||||
|
||||
// // case ThermionGestureState.ROTATING:
|
||||
// // if (enableCamera) {
|
||||
// // await viewer.rotateUpdate(localPosition.dx, localPosition.dy);
|
||||
// // }
|
||||
// // break;
|
||||
// // case ThermionGestureState.PANNING:
|
||||
// // if (enableCamera) {
|
||||
// // await viewer.panUpdate(localPosition.dx, localPosition.dy);
|
||||
// // }
|
||||
// // break;
|
||||
// // case ThermionGestureState.ZOOMING:
|
||||
// // // ignore
|
||||
// // break;
|
||||
// // }
|
||||
// // }
|
||||
|
||||
// // @override
|
||||
// // Future<void> onPointerUp(int buttons) async {
|
||||
// // switch (_currentState) {
|
||||
// // case ThermionGestureState.ROTATING:
|
||||
// // await viewer.rotateEnd();
|
||||
// // _currentState = ThermionGestureState.NULL;
|
||||
// // break;
|
||||
// // case ThermionGestureState.PANNING:
|
||||
// // await viewer.panEnd();
|
||||
// // _currentState = ThermionGestureState.NULL;
|
||||
// // break;
|
||||
// // default:
|
||||
// // break;
|
||||
// // }
|
||||
// // }
|
||||
|
||||
// // Future<void> _handleEntityHighlightedMove(Offset localPosition) async {
|
||||
// // if (_highlightedEntity != null) {
|
||||
// // await viewer.queuePositionUpdateFromViewportCoords(
|
||||
// // _highlightedEntity!,
|
||||
// // localPosition.dx,
|
||||
// // localPosition.dy,
|
||||
// // );
|
||||
// // }
|
||||
// // }
|
||||
|
||||
// // Future<void> _zoom(Offset localPosition, double scrollDelta) async {
|
||||
// // _scrollTimer?.cancel();
|
||||
// // _currentState = ThermionGestureState.ZOOMING;
|
||||
// // await viewer.zoomBegin();
|
||||
// // await viewer.zoomUpdate(
|
||||
// // localPosition.dx, localPosition.dy, scrollDelta > 0 ? 1 : -1);
|
||||
|
||||
// // _scrollTimer = Timer(const Duration(milliseconds: 100), () async {
|
||||
// // await viewer.zoomEnd();
|
||||
// // _currentState = ThermionGestureState.NULL;
|
||||
// // });
|
||||
// // }
|
||||
|
||||
// // @override
|
||||
// // void dispose() {
|
||||
// // _pickResultSubscription?.cancel();
|
||||
// // if (_highlightedEntity != null) {
|
||||
// // viewer.removeStencilHighlight(_highlightedEntity!);
|
||||
// // }
|
||||
// // RawKeyboard.instance.removeListener(_handleKeyEvent);
|
||||
// // }
|
||||
|
||||
// // @override
|
||||
// // Future<bool> get initialized => viewer.initialized;
|
||||
|
||||
// // @override
|
||||
// // InputAction getActionForType(InputType type) {
|
||||
// // // TODO: implement getActionForType
|
||||
// // throw UnimplementedError();
|
||||
// // }
|
||||
|
||||
// // @override
|
||||
// // Future<void> onScaleEnd() {
|
||||
// // // TODO: implement onScaleEnd
|
||||
// // throw UnimplementedError();
|
||||
// // }
|
||||
|
||||
// // @override
|
||||
// // Future<void> onScaleStart() {
|
||||
// // // TODO: implement onScaleStart
|
||||
// // throw UnimplementedError();
|
||||
// // }
|
||||
|
||||
// // @override
|
||||
// // Future<void> onScaleUpdate() {
|
||||
// // // TODO: implement onScaleUpdate
|
||||
// // throw UnimplementedError();
|
||||
// // }
|
||||
|
||||
// // @override
|
||||
// // void setActionForType(InputType type, InputAction action) {
|
||||
// // // TODO: implement setActionForType
|
||||
// // }
|
||||
// // }
|
||||
|
||||
@@ -4,41 +4,40 @@ import 'package:vector_math/vector_math_64.dart';
|
||||
|
||||
import '../../viewer/viewer.dart';
|
||||
|
||||
class Axis {
|
||||
class AxisWidget {
|
||||
final ThermionViewer _viewer;
|
||||
final ThermionEntity xAxis;
|
||||
final ThermionEntity yAxis;
|
||||
final ThermionEntity zAxis;
|
||||
|
||||
Axis._(this.xAxis, this.yAxis, this.zAxis, this._viewer);
|
||||
AxisWidget._(this.xAxis, this.yAxis, this.zAxis, this._viewer);
|
||||
|
||||
static Future<Axis> create(ThermionViewer viewer) async {
|
||||
final xAxis = await viewer!.createGeometry(
|
||||
final xAxis = await viewer.createGeometry(
|
||||
Geometry(Float32List.fromList([0, 0, 0, 10, 0, 0]), [0, 1],
|
||||
primitiveType: PrimitiveType.LINES),
|
||||
materialInstance: await viewer!.createUnlitMaterialInstance());
|
||||
final yAxis = await viewer!.createGeometry(
|
||||
materialInstances: [await viewer.createUnlitMaterialInstance()]);
|
||||
final yAxis = await viewer.createGeometry(
|
||||
Geometry(Float32List.fromList([0, 0, 0, 0, 10, 0]), [0, 1],
|
||||
primitiveType: PrimitiveType.LINES),
|
||||
materialInstance: await viewer!.createUnlitMaterialInstance());
|
||||
final zAxis = await viewer!.createGeometry(
|
||||
materialInstances: [await viewer.createUnlitMaterialInstance()]);
|
||||
final zAxis = await viewer.createGeometry(
|
||||
Geometry(Float32List.fromList([0, 0, 0, 0, 0, 10]), [0, 1],
|
||||
primitiveType: PrimitiveType.LINES),
|
||||
materialInstance: await viewer!.createUnlitMaterialInstance());
|
||||
|
||||
await viewer!.setMaterialPropertyFloat4(
|
||||
xAxis, "baseColorFactor", 0, 1.0, 0.0, 0.0, 1.0);
|
||||
await viewer!.setMaterialPropertyFloat4(
|
||||
yAxis, "baseColorFactor", 0, 0.0, 1.0, 0.0, 1.0);
|
||||
await viewer!.setMaterialPropertyFloat4(
|
||||
zAxis, "baseColorFactor", 0, 0.0, 0.0, 1.0, 1.0);
|
||||
return Axis._(xAxis, yAxis, zAxis, viewer);
|
||||
materialInstances: [await viewer.createUnlitMaterialInstance()]);
|
||||
throw Exception("TODO");
|
||||
// await viewer!.setMaterialPropertyFloat4(
|
||||
// xAxis, "baseColorFactor", 0, 1.0, 0.0, 0.0, 1.0);
|
||||
// await viewer!.setMaterialPropertyFloat4(
|
||||
// yAxis, "baseColorFactor", 0, 0.0, 1.0, 0.0, 1.0);
|
||||
// await viewer!.setMaterialPropertyFloat4(
|
||||
// zAxis, "baseColorFactor", 0, 0.0, 0.0, 1.0, 1.0);
|
||||
// return Axis._(xAxis, yAxis, zAxis, viewer);
|
||||
}
|
||||
|
||||
Future setTransform(Matrix4 transform) async {
|
||||
await _viewer.setTransform(xAxis, transform);
|
||||
await _viewer.setTransform(yAxis, transform);
|
||||
await _viewer.setTransform(zAxis, transform);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,127 +1,120 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:thermion_dart/src/viewer/viewer.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
|
||||
abstract class Gizmo {
|
||||
bool get isVisible;
|
||||
bool get isHovered;
|
||||
|
||||
void reset();
|
||||
|
||||
Future attach(ThermionEntity entity);
|
||||
Future detach();
|
||||
// abstract class BaseGizmo extends Gizmo {
|
||||
// final ThermionEntity x;
|
||||
// final ThermionEntity y;
|
||||
// final ThermionEntity z;
|
||||
// final ThermionEntity center;
|
||||
|
||||
Stream<Aabb2> get boundingBox;
|
||||
// ThermionEntity? _activeAxis;
|
||||
// ThermionEntity? _activeEntity;
|
||||
// ThermionViewer viewer;
|
||||
|
||||
void checkHover(int x, int y);
|
||||
}
|
||||
// bool _visible = false;
|
||||
// bool get isVisible => _visible;
|
||||
|
||||
abstract class BaseGizmo extends Gizmo {
|
||||
final ThermionEntity x;
|
||||
final ThermionEntity y;
|
||||
final ThermionEntity z;
|
||||
final ThermionEntity center;
|
||||
// bool _isHovered = false;
|
||||
// bool get isHovered => _isHovered;
|
||||
|
||||
ThermionEntity? _activeAxis;
|
||||
ThermionEntity? _activeEntity;
|
||||
ThermionViewer viewer;
|
||||
// final Set<ThermionEntity> ignore;
|
||||
|
||||
bool _visible = false;
|
||||
bool get isVisible => _visible;
|
||||
// Stream<Aabb2> get boundingBox => _boundingBoxController.stream;
|
||||
// final _boundingBoxController = StreamController<Aabb2>.broadcast();
|
||||
|
||||
bool _isHovered = false;
|
||||
bool get isHovered => _isHovered;
|
||||
// ThermionEntity get entity => center;
|
||||
|
||||
final Set<ThermionEntity> ignore;
|
||||
// BaseGizmo(
|
||||
// {required this.x,
|
||||
// required this.y,
|
||||
// required this.z,
|
||||
// required this.center,
|
||||
// required this.viewer,
|
||||
// this.ignore = const <ThermionEntity>{}}) {
|
||||
// onPick(_onGizmoPickResult);
|
||||
// }
|
||||
|
||||
Stream<Aabb2> get boundingBox => _boundingBoxController.stream;
|
||||
final _boundingBoxController = StreamController<Aabb2>.broadcast();
|
||||
// final _stopwatch = Stopwatch();
|
||||
|
||||
BaseGizmo({required this.x, required this.y, required this.z, required this.center, required this.viewer,
|
||||
this.ignore = const <ThermionEntity>{}}) {
|
||||
onPick(_onGizmoPickResult);
|
||||
}
|
||||
// double _transX = 0.0;
|
||||
// double _transY = 0.0;
|
||||
|
||||
final _stopwatch = Stopwatch();
|
||||
// Future translate(double transX, double transY) async {
|
||||
// if (!_stopwatch.isRunning) {
|
||||
// _stopwatch.start();
|
||||
// }
|
||||
|
||||
double _transX = 0.0;
|
||||
double _transY = 0.0;
|
||||
// _transX += transX;
|
||||
// _transY += transY;
|
||||
|
||||
Future translate(double transX, double transY) async {
|
||||
if (!_stopwatch.isRunning) {
|
||||
_stopwatch.start();
|
||||
}
|
||||
// if (_stopwatch.elapsedMilliseconds < 16) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
_transX += transX;
|
||||
_transY += transY;
|
||||
// final axis = Vector3(_activeAxis == x ? 1.0 : 0.0,
|
||||
// _activeAxis == y ? 1.0 : 0.0, _activeAxis == z ? 1.0 : 0.0);
|
||||
|
||||
if (_stopwatch.elapsedMilliseconds < 16) {
|
||||
return;
|
||||
}
|
||||
// await viewer.queueRelativePositionUpdateWorldAxis(
|
||||
// _activeEntity!,
|
||||
// _transX,
|
||||
// -_transY, // flip the sign because "up" in NDC Y axis is positive, but negative in Flutter
|
||||
// axis.x,
|
||||
// axis.y,
|
||||
// axis.z);
|
||||
// _transX = 0;
|
||||
// _transY = 0;
|
||||
// _stopwatch.reset();
|
||||
// }
|
||||
|
||||
final axis = Vector3(_activeAxis == x ? 1.0 : 0.0,
|
||||
_activeAxis == y ? 1.0 : 0.0, _activeAxis == z ? 1.0 : 0.0);
|
||||
// void reset() {
|
||||
// _activeAxis = null;
|
||||
// }
|
||||
|
||||
await viewer.queueRelativePositionUpdateWorldAxis(
|
||||
_activeEntity!,
|
||||
_transX,
|
||||
-_transY, // flip the sign because "up" in NDC Y axis is positive, but negative in Flutter
|
||||
axis.x,
|
||||
axis.y,
|
||||
axis.z);
|
||||
_transX = 0;
|
||||
_transY = 0;
|
||||
_stopwatch.reset();
|
||||
}
|
||||
// void _onGizmoPickResult(FilamentPickResult result) async {
|
||||
// if (result.entity == x || result.entity == y || result.entity == z) {
|
||||
// _activeAxis = result.entity;
|
||||
// _isHovered = true;
|
||||
// } else if (result.entity == 0) {
|
||||
// _activeAxis = null;
|
||||
// _isHovered = false;
|
||||
// } else {
|
||||
// throw Exception("Unexpected gizmo pick result");
|
||||
// }
|
||||
// }
|
||||
|
||||
void reset() {
|
||||
_activeAxis = null;
|
||||
}
|
||||
// Future attach(ThermionEntity entity) async {
|
||||
// _activeAxis = null;
|
||||
// if (entity == _activeEntity) {
|
||||
// return;
|
||||
// }
|
||||
// if (entity == center) {
|
||||
// _activeEntity = null;
|
||||
// return;
|
||||
// }
|
||||
// _visible = true;
|
||||
|
||||
void _onGizmoPickResult(FilamentPickResult result) async {
|
||||
if (result.entity == x || result.entity == y || result.entity == z) {
|
||||
_activeAxis = result.entity;
|
||||
_isHovered = true;
|
||||
} else if (result.entity == 0) {
|
||||
_activeAxis = null;
|
||||
_isHovered = false;
|
||||
} else {
|
||||
throw Exception("Unexpected gizmo pick result");
|
||||
}
|
||||
}
|
||||
// if (_activeEntity != null) {
|
||||
// // await viewer.removeStencilHighlight(_activeEntity!);
|
||||
// }
|
||||
// _activeEntity = entity;
|
||||
|
||||
Future attach(ThermionEntity entity) async {
|
||||
_activeAxis = null;
|
||||
if (entity == _activeEntity) {
|
||||
return;
|
||||
}
|
||||
if (entity == center) {
|
||||
_activeEntity = null;
|
||||
return;
|
||||
}
|
||||
_visible = true;
|
||||
// await viewer.setParent(center, entity, preserveScaling: false);
|
||||
// _boundingBoxController.sink.add(await viewer.getViewportBoundingBox(x));
|
||||
// }
|
||||
|
||||
if (_activeEntity != null) {
|
||||
await viewer.removeStencilHighlight(_activeEntity!);
|
||||
}
|
||||
_activeEntity = entity;
|
||||
// Future detach() async {
|
||||
// await setVisibility(false);
|
||||
// }
|
||||
|
||||
await viewer.setParent(center, entity, preserveScaling: false);
|
||||
_boundingBoxController.sink.add(await viewer.getViewportBoundingBox(x));
|
||||
}
|
||||
// @override
|
||||
// void checkHover(int x, int y) {
|
||||
// pick(x, y);
|
||||
// }
|
||||
|
||||
Future detach() async {
|
||||
await setVisibility(false);
|
||||
}
|
||||
// Future pick(int x, int y);
|
||||
|
||||
@override
|
||||
void checkHover(int x, int y) {
|
||||
pick(x, y);
|
||||
}
|
||||
|
||||
Future pick(int x, int y);
|
||||
|
||||
Future setVisibility(bool visible);
|
||||
void onPick(void Function(PickResult result) callback);
|
||||
}
|
||||
// Future setVisibility(bool visible);
|
||||
// void onPick(void Function(PickResult result) callback);
|
||||
// }
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
import 'shared_types/shared_types.dart';
|
||||
|
||||
///
|
||||
/// To ensure we can easily store/recreate a particular, [ThermionViewer] will raise an event whenever an
|
||||
/// entity is added/removed.
|
||||
///
|
||||
enum EventType { EntityAdded, EntityRemoved, EntityHidden, EntityRevealed, ClearLights }
|
||||
|
||||
///
|
||||
/// An "entity added" event must provide sufficient detail to enable that asset to be reloaded in future.
|
||||
/// This requires a bit more legwork because entities may be lights (direct/indirect), geometry or gltf.
|
||||
///
|
||||
enum EntityType { Geometry, Gltf, DirectLight, IBL }
|
||||
|
||||
class SceneUpdateEvent {
|
||||
late final ThermionEntity? entity;
|
||||
late final EventType eventType;
|
||||
|
||||
EntityType get addedEntityType {
|
||||
if (_directLight != null) {
|
||||
return EntityType.DirectLight;
|
||||
} else if (_ibl != null) {
|
||||
return EntityType.IBL;
|
||||
} else if (_gltf != null) {
|
||||
return EntityType.Gltf;
|
||||
} else if (_geometry != null) {
|
||||
return EntityType.Geometry;
|
||||
} else {
|
||||
throw Exception("Unknown entity type");
|
||||
}
|
||||
}
|
||||
|
||||
DirectLight? _directLight;
|
||||
IBL? _ibl;
|
||||
GLTF? _gltf;
|
||||
Geometry? _geometry;
|
||||
|
||||
SceneUpdateEvent.remove(this.entity) {
|
||||
this.eventType = EventType.EntityRemoved;
|
||||
}
|
||||
|
||||
SceneUpdateEvent.reveal(this.entity) {
|
||||
this.eventType = EventType.EntityRevealed;
|
||||
}
|
||||
|
||||
SceneUpdateEvent.hide(this.entity) {
|
||||
this.eventType = EventType.EntityHidden;
|
||||
}
|
||||
|
||||
SceneUpdateEvent.addDirectLight(this.entity, this._directLight) {
|
||||
this.eventType = EventType.EntityAdded;
|
||||
}
|
||||
|
||||
SceneUpdateEvent.addIbl(this.entity, this._ibl) {
|
||||
this.eventType = EventType.EntityAdded;
|
||||
}
|
||||
|
||||
SceneUpdateEvent.addGltf(this.entity, this._gltf) {
|
||||
this.eventType = EventType.EntityAdded;
|
||||
}
|
||||
|
||||
SceneUpdateEvent.addGeometry(this.entity, this._geometry) {
|
||||
this.eventType = EventType.EntityAdded;
|
||||
}
|
||||
|
||||
SceneUpdateEvent.clearLights() {
|
||||
this.eventType = EventType.ClearLights;
|
||||
}
|
||||
|
||||
DirectLight getDirectLight() {
|
||||
return _directLight!;
|
||||
}
|
||||
|
||||
IBL getAsIBL() {
|
||||
return _ibl!;
|
||||
}
|
||||
|
||||
GLTF getAsGLTF() {
|
||||
return _gltf!;
|
||||
}
|
||||
|
||||
Geometry getAsGeometry() {
|
||||
return _geometry!;
|
||||
}
|
||||
}
|
||||
186
thermion_dart/lib/src/viewer/src/ffi/src/ffi_asset.dart
Normal file
186
thermion_dart/lib/src/viewer/src/ffi/src/ffi_asset.dart
Normal file
@@ -0,0 +1,186 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
|
||||
import 'ffi_material_instance.dart';
|
||||
|
||||
class FFIAsset extends ThermionAsset {
|
||||
final Pointer<TSceneAsset> pointer;
|
||||
final Pointer<TSceneManager> sceneManager;
|
||||
Pointer<TRenderableManager> get renderableManager =>
|
||||
Engine_getRenderableManager(engine);
|
||||
final Pointer<TEngine> engine;
|
||||
FFIAsset? _highlight;
|
||||
final Pointer<TMaterialProvider> _unlitMaterialProvider;
|
||||
final bool isInstance;
|
||||
|
||||
late final ThermionEntity entity;
|
||||
|
||||
FFIAsset(
|
||||
this.pointer, this.sceneManager, this.engine, this._unlitMaterialProvider,
|
||||
{this.isInstance = false}) {
|
||||
entity = SceneAsset_getEntity(pointer);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<ThermionEntity>> getChildEntities() async {
|
||||
var count = SceneAsset_getChildEntityCount(pointer);
|
||||
var children = Int32List(count);
|
||||
SceneAsset_getChildEntities(pointer, children.address);
|
||||
return children;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ThermionAsset> getInstance(int index) async {
|
||||
if (isInstance) {
|
||||
throw Exception(
|
||||
"This is itself an instance. Call getInstance on the original asset that this instance was created from");
|
||||
}
|
||||
var instance = SceneAsset_getInstance(pointer, index);
|
||||
if (instance == nullptr) {
|
||||
throw Exception("No instance available at index $index");
|
||||
}
|
||||
return FFIAsset(instance, sceneManager, engine, _unlitMaterialProvider);
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
@override
|
||||
Future<FFIAsset> createInstance(
|
||||
{covariant List<MaterialInstance>? materialInstances = null}) async {
|
||||
var created = await withPointerCallback<TSceneAsset>((cb) {
|
||||
var ptrList = Int64List(materialInstances?.length ?? 0);
|
||||
if (materialInstances != null && materialInstances.isNotEmpty) {
|
||||
ptrList.setRange(
|
||||
0,
|
||||
materialInstances.length,
|
||||
materialInstances
|
||||
.cast<ThermionFFIMaterialInstance>()
|
||||
.map((mi) => mi.pointer.address)
|
||||
.toList());
|
||||
}
|
||||
|
||||
SceneAsset_createInstanceRenderThread(
|
||||
pointer,
|
||||
ptrList.address.cast<Pointer<TMaterialInstance>>(),
|
||||
materialInstances?.length ?? 0,
|
||||
cb);
|
||||
});
|
||||
if (created == FILAMENT_ASSET_ERROR) {
|
||||
throw Exception("Failed to create instance");
|
||||
}
|
||||
return FFIAsset(created, sceneManager, engine, _unlitMaterialProvider);
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
@override
|
||||
Future<int> getInstanceCount() async {
|
||||
return SceneAsset_getInstanceCount(pointer);
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
@override
|
||||
Future<List<ThermionAsset>> getInstances() async {
|
||||
var count = await getInstanceCount();
|
||||
final result = List<ThermionAsset>.generate(count, (i) {
|
||||
return FFIAsset(SceneAsset_getInstance(pointer, i), sceneManager, engine,
|
||||
_unlitMaterialProvider);
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future removeStencilHighlight() async {
|
||||
if (_highlight != null) {
|
||||
SceneManager_removeFromScene(sceneManager, _highlight!.entity);
|
||||
final childEntities = await _highlight!.getChildEntities();
|
||||
for (final child in childEntities) {
|
||||
SceneManager_removeFromScene(sceneManager, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future setStencilHighlight(
|
||||
{double r = 1.0,
|
||||
double g = 0.0,
|
||||
double b = 0.0,
|
||||
int? entityIndex}) async {
|
||||
if (_highlight == null) {
|
||||
var targetEntity = this.entity;
|
||||
if (entityIndex != null) {
|
||||
final childEntities = await this.getChildEntities();
|
||||
targetEntity = childEntities[entityIndex!];
|
||||
}
|
||||
var sourceMaterialInstance = ThermionFFIMaterialInstance(
|
||||
RenderableManager_getMaterialInstanceAt(
|
||||
renderableManager, targetEntity, 0));
|
||||
|
||||
await sourceMaterialInstance.setStencilWriteEnabled(true);
|
||||
await sourceMaterialInstance.setDepthWriteEnabled(true);
|
||||
await sourceMaterialInstance
|
||||
.setStencilOpDepthStencilPass(StencilOperation.REPLACE);
|
||||
|
||||
await sourceMaterialInstance.setStencilReferenceValue(1);
|
||||
|
||||
final materialInstancePtr =
|
||||
await withPointerCallback<TMaterialInstance>((cb) {
|
||||
final key = Struct.create<TMaterialKey>();
|
||||
MaterialProvider_createMaterialInstanceRenderThread(
|
||||
_unlitMaterialProvider, key.address, cb);
|
||||
});
|
||||
final highlightMaterialInstance =
|
||||
ThermionFFIMaterialInstance(materialInstancePtr);
|
||||
await highlightMaterialInstance
|
||||
.setStencilCompareFunction(SamplerCompareFunction.NE);
|
||||
await highlightMaterialInstance.setStencilReferenceValue(1);
|
||||
|
||||
await highlightMaterialInstance.setDepthCullingEnabled(false);
|
||||
|
||||
await highlightMaterialInstance.setParameterFloat("vertexScale", 1.03);
|
||||
await highlightMaterialInstance.setParameterFloat4(
|
||||
"baseColorFactor", r, g, b, 1.0);
|
||||
|
||||
var highlightInstance = await this
|
||||
.createInstance(materialInstances: [highlightMaterialInstance]);
|
||||
_highlight = highlightInstance;
|
||||
|
||||
var targetHighlightEntity = _highlight!.entity;
|
||||
|
||||
if (entityIndex != null) {
|
||||
var highlightChildEntities = await _highlight!.getChildEntities();
|
||||
targetHighlightEntity = highlightChildEntities[entityIndex!];
|
||||
}
|
||||
|
||||
RenderableManager_setPriority(
|
||||
renderableManager, targetHighlightEntity, 7);
|
||||
RenderableManager_setPriority(renderableManager, targetEntity, 0);
|
||||
|
||||
await highlightMaterialInstance.setStencilReferenceValue(1);
|
||||
|
||||
SceneManager_addToScene(sceneManager, targetHighlightEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future addToScene() async {
|
||||
SceneAsset_addToScene(pointer, SceneManager_getScene(sceneManager));
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
Future removeFromScene() async {
|
||||
SceneManager_removeFromScene(sceneManager, entity);
|
||||
for (final child in await getChildEntities()) {
|
||||
SceneManager_removeFromScene(sceneManager, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,9 +9,10 @@ import 'thermion_dart.g.dart' as g;
|
||||
class FFICamera extends Camera {
|
||||
final Pointer<g.TCamera> camera;
|
||||
final Pointer<g.TEngine> engine;
|
||||
final Pointer<g.TTransformManager> transformManager;
|
||||
late ThermionEntity _entity;
|
||||
|
||||
FFICamera(this.camera, this.engine) {
|
||||
FFICamera(this.camera, this.engine, this.transformManager) {
|
||||
_entity = g.Camera_getEntity(camera);
|
||||
}
|
||||
|
||||
@@ -29,7 +30,7 @@ class FFICamera extends Camera {
|
||||
@override
|
||||
Future setTransform(Matrix4 transform) async {
|
||||
var entity = g.Camera_getEntity(camera);
|
||||
g.Engine_setTransform(engine, entity, matrix4ToDouble4x4(transform));
|
||||
g.TransformManager_setTransform(transformManager, entity, matrix4ToDouble4x4(transform));
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -1,50 +1,69 @@
|
||||
import 'dart:async';
|
||||
import 'dart:ffi';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_asset.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/shared_types/entities.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart';
|
||||
|
||||
import '../../../../utils/src/gizmo.dart';
|
||||
import '../../../viewer.dart';
|
||||
|
||||
class FFIGizmo extends BaseGizmo {
|
||||
Pointer<TGizmo> pointer;
|
||||
import 'ffi_view.dart';
|
||||
|
||||
class FFIGizmo extends FFIAsset implements GizmoAsset {
|
||||
final Set<ThermionEntity> nonPickableEntities;
|
||||
late NativeCallable<GizmoPickCallbackFunction> _nativeCallback;
|
||||
|
||||
void Function(GizmoPickResultType axis, Vector3 coords)? _callback;
|
||||
|
||||
late FFIView _view;
|
||||
|
||||
void _onPickResult(int resultType, double x, double y, double z) {
|
||||
_callback?.call(GizmoPickResultType.values[resultType], Vector3(x, y, z));
|
||||
}
|
||||
|
||||
FFIGizmo(
|
||||
this.pointer, ThermionViewer viewer) : super(x: 0, y: 0, z: 0, center: 0, viewer: viewer) {
|
||||
this._view,
|
||||
super.pointer,
|
||||
super.sceneManager,
|
||||
super.renderableManager,
|
||||
super.unlitMaterialProvider,
|
||||
this.nonPickableEntities
|
||||
) {
|
||||
_nativeCallback =
|
||||
NativeCallable<GizmoPickCallbackFunction>.listener(_onPickResult);
|
||||
}
|
||||
|
||||
///
|
||||
/// The result(s) of calling [pickGizmo] (see below).
|
||||
///
|
||||
// Stream<PickResult> get onPick => _pickResultController.stream;
|
||||
// final _pickResultController = StreamController<PickResult>.broadcast();
|
||||
|
||||
void Function(PickResult)? _callback;
|
||||
|
||||
void onPick(void Function(PickResult) callback) {
|
||||
_callback = callback;
|
||||
}
|
||||
|
||||
void _onPickResult(DartEntityId entityId, int x, int y, Pointer<TView> view) {
|
||||
_callback?.call((entity: entityId, x: x, y: y, depth: 0, fragX: 0, fragY: 0, fragZ: 0));
|
||||
}
|
||||
|
||||
///
|
||||
/// Used to test whether a Gizmo is at the given viewport coordinates.
|
||||
/// Called by `FilamentGestureDetector` on a mouse/finger down event. You probably don't want to call this yourself.
|
||||
/// This is asynchronous and will require 2-3 frames to complete - subscribe to the [gizmoPickResult] stream to receive the results of this method.
|
||||
/// [x] and [y] must be in local logical coordinates (i.e. where 0,0 is at top-left of the ThermionWidget).
|
||||
///
|
||||
@override
|
||||
Future pick(int x, int y) async {
|
||||
Gizmo_pick(pointer, x.toInt(), y, _nativeCallback.nativeFunction);
|
||||
Future removeStencilHighlight() async {
|
||||
throw Exception("Not supported for gizmo");
|
||||
}
|
||||
|
||||
@override
|
||||
Future setVisibility(bool visible) async {
|
||||
Gizmo_setVisibility(pointer, visible);
|
||||
Future setStencilHighlight(
|
||||
{double r = 1.0,
|
||||
double g = 0.0,
|
||||
double b = 0.0,
|
||||
int? entityIndex}) async {
|
||||
throw Exception("Not supported for gizmo");
|
||||
}
|
||||
|
||||
@override
|
||||
Future pick(int x, int y,
|
||||
{Future Function(GizmoPickResultType result, Vector3 coords)?
|
||||
handler}) async {
|
||||
_callback = handler;
|
||||
final viewport = await _view.getViewport();
|
||||
y = viewport.height - y;
|
||||
|
||||
Gizmo_pick(pointer.cast<TGizmo>(), x, y, _nativeCallback.nativeFunction);
|
||||
}
|
||||
|
||||
@override
|
||||
Future highlight(Axis axis) async {
|
||||
Gizmo_unhighlight(pointer.cast<TGizmo>());
|
||||
Gizmo_highlight(pointer.cast<TGizmo>(), TGizmoAxis.values[axis.index]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future unhighlight() async {
|
||||
Gizmo_unhighlight(pointer.cast<TGizmo>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
import 'dart:ffi';
|
||||
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
|
||||
class ThermionFFIMaterialInstance extends MaterialInstance {
|
||||
final Pointer<TMaterialInstance> pointer;
|
||||
|
||||
ThermionFFIMaterialInstance(this.pointer) {
|
||||
if (pointer == nullptr) {
|
||||
throw Exception("MaterialInstance not found");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future setDepthCullingEnabled(bool enabled) async {
|
||||
MaterialInstance_setDepthCulling(this.pointer, enabled);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setDepthWriteEnabled(bool enabled) async {
|
||||
MaterialInstance_setDepthWrite(this.pointer, enabled);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setParameterFloat4(
|
||||
String name, double x, double y, double z, double w) async {
|
||||
MaterialInstance_setParameterFloat4(
|
||||
pointer, name.toNativeUtf8().cast<Char>(), x, y, z, w);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setParameterFloat2(String name, double x, double y) async {
|
||||
MaterialInstance_setParameterFloat2(
|
||||
pointer, name.toNativeUtf8().cast<Char>(), x, y);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setParameterFloat(String name, double value) async {
|
||||
MaterialInstance_setParameterFloat(
|
||||
pointer, name.toNativeUtf8().cast<Char>(), value);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setParameterInt(String name, int value) async {
|
||||
MaterialInstance_setParameterInt(
|
||||
pointer, name.toNativeUtf8().cast<Char>(), value);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setDepthFunc(SamplerCompareFunction depthFunc) async {
|
||||
MaterialInstance_setDepthFunc(pointer, TSamplerCompareFunc.values[depthFunc.index]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setStencilCompareFunction(SamplerCompareFunction func,
|
||||
[StencilFace face = StencilFace.FRONT_AND_BACK]) async {
|
||||
MaterialInstance_setStencilCompareFunction(
|
||||
pointer, TSamplerCompareFunc.values[func.index], TStencilFace.values[face.index]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setStencilOpDepthFail(StencilOperation op,
|
||||
[StencilFace face = StencilFace.FRONT_AND_BACK]) async {
|
||||
MaterialInstance_setStencilOpDepthFail(pointer,
|
||||
TStencilOperation.values[op.index], TStencilFace.values[face.index]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setStencilOpDepthStencilPass(StencilOperation op,
|
||||
[StencilFace face = StencilFace.FRONT_AND_BACK]) async {
|
||||
MaterialInstance_setStencilOpDepthStencilPass(pointer,
|
||||
TStencilOperation.values[op.index], TStencilFace.values[face.index]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setStencilOpStencilFail(StencilOperation op,
|
||||
[StencilFace face = StencilFace.FRONT_AND_BACK]) async {
|
||||
MaterialInstance_setStencilOpStencilFail(pointer,
|
||||
TStencilOperation.values[op.index], TStencilFace.values[face.index]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setStencilReferenceValue(int value,
|
||||
[StencilFace face = StencilFace.FRONT_AND_BACK]) async {
|
||||
MaterialInstance_setStencilReferenceValue(
|
||||
pointer, value, TStencilFace.values[face.index]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setStencilWriteEnabled(bool enabled) async {
|
||||
MaterialInstance_setStencilWrite(pointer, enabled);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setCullingMode(CullingMode cullingMode) async {
|
||||
MaterialInstance_setCullingMode(
|
||||
pointer, TCullingMode.values[cullingMode.index]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> isStencilWriteEnabled() async {
|
||||
return MaterialInstance_isStencilWriteEnabled(pointer);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setStencilReadMask(int mask) async {
|
||||
MaterialInstance_setStencilReadMask(pointer, mask);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setStencilWriteMask(int mask) async {
|
||||
MaterialInstance_setStencilWriteMask(pointer, mask);
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ class FFIView extends View {
|
||||
|
||||
@override
|
||||
Future setRenderTarget(covariant FFIRenderTarget? renderTarget) async {
|
||||
if(renderTarget != null) {
|
||||
if (renderTarget != null) {
|
||||
View_setRenderTarget(view, renderTarget.renderTarget);
|
||||
} else {
|
||||
View_setRenderTarget(view, nullptr);
|
||||
@@ -39,8 +39,9 @@ class FFIView extends View {
|
||||
@override
|
||||
Future<Camera> getCamera() async {
|
||||
final engine = Viewer_getEngine(viewer);
|
||||
final cameraPtr = View_getCamera(view);
|
||||
return FFICamera(cameraPtr, engine);
|
||||
final transformManager = Engine_getTransformManager(engine);
|
||||
final cameraPtr = View_getCamera(view);
|
||||
return FFICamera(cameraPtr, engine, transformManager);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -72,4 +73,12 @@ class FFIView extends View {
|
||||
final engine = await Viewer_getEngine(viewer);
|
||||
View_setToneMappingRenderThread(view, engine, mapper.index);
|
||||
}
|
||||
|
||||
Future setStencilBufferEnabled(bool enabled) async {
|
||||
return View_setStencilBufferEnabled(view, enabled);
|
||||
}
|
||||
|
||||
Future<bool> isStencilBufferEnabled() async {
|
||||
return View_isStencilBufferEnabled(view);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,85 @@
|
||||
library;
|
||||
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
|
||||
export 'geometry.dart';
|
||||
export 'gltf.dart';
|
||||
|
||||
export 'light_options.dart';
|
||||
|
||||
// a handle that can be safely passed back to the rendering layer to manipulate an Entity
|
||||
// repre handle that can be safely passed back to the rendering layer to manipulate an Entity
|
||||
typedef ThermionEntity = int;
|
||||
|
||||
abstract class ThermionAsset {
|
||||
ThermionEntity get entity;
|
||||
Future<List<ThermionEntity>> getChildEntities();
|
||||
|
||||
///
|
||||
/// Renders an outline around [entity] with the given color.
|
||||
///
|
||||
Future setStencilHighlight(
|
||||
{double r = 1.0, double g = 0.0, double b = 0.0, int? entityIndex});
|
||||
|
||||
///
|
||||
/// Removes the outline around [entity]. Noop if there was no highlight.
|
||||
///
|
||||
Future removeStencilHighlight();
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
Future<ThermionAsset> getInstance(int index);
|
||||
|
||||
///
|
||||
/// Create a new instance of [entity].
|
||||
/// Instances are not automatically added to the scene; you must
|
||||
/// call [addToScene].
|
||||
///
|
||||
Future<ThermionAsset> createInstance(
|
||||
{covariant List<MaterialInstance>? materialInstances = null});
|
||||
|
||||
///
|
||||
/// Returns the number of instances associated with this asset.
|
||||
///
|
||||
Future<int> getInstanceCount();
|
||||
|
||||
///
|
||||
/// Returns all instances of associated with this asset.
|
||||
///
|
||||
Future<List<ThermionAsset>> getInstances();
|
||||
|
||||
///
|
||||
/// Adds all entities (renderable, lights and cameras) under [asset] to the scene.
|
||||
///
|
||||
Future addToScene();
|
||||
|
||||
///
|
||||
/// Removes all entities (renderable, lights and cameras) under [asset] from the scene.
|
||||
///
|
||||
Future removeFromScene();
|
||||
}
|
||||
|
||||
enum Axis {
|
||||
X(const [1.0, 0.0, 0.0]),
|
||||
Y(const [0.0, 1.0, 0.0]),
|
||||
Z(const [0.0, 0.0, 1.0]);
|
||||
|
||||
const Axis(this.vector);
|
||||
|
||||
final List<double> vector;
|
||||
|
||||
Vector3 asVector() => Vector3(vector[0], vector[1], vector[2]);
|
||||
}
|
||||
|
||||
enum GizmoPickResultType { AxisX, AxisY, AxisZ, Parent, None }
|
||||
|
||||
enum GizmoType { translation, rotation }
|
||||
|
||||
abstract class GizmoAsset extends ThermionAsset {
|
||||
Future pick(int x, int y,
|
||||
{Future Function(GizmoPickResultType axis, Vector3 coords)? handler});
|
||||
Future highlight(Axis axis);
|
||||
Future unhighlight();
|
||||
Set<ThermionEntity> get nonPickableEntities;
|
||||
}
|
||||
|
||||
@@ -1,32 +1,112 @@
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart';
|
||||
|
||||
enum SamplerCompareFunction {
|
||||
enum SamplerCompareFunction {
|
||||
/// !< Less or equal
|
||||
LE,
|
||||
|
||||
/// !< Greater or equal
|
||||
GE,
|
||||
|
||||
/// !< Strictly less than
|
||||
L,
|
||||
|
||||
/// !< Strictly greater than
|
||||
G,
|
||||
|
||||
/// !< Equal
|
||||
E,
|
||||
|
||||
/// !< Not equal
|
||||
NE,
|
||||
|
||||
/// !< Always. Depth / stencil testing is deactivated.
|
||||
A,
|
||||
|
||||
/// !< Never. The depth / stencil test always fails.
|
||||
N;
|
||||
}
|
||||
abstract class MaterialInstance {
|
||||
Future setDepthWriteEnabled(bool enabled);
|
||||
Future setDepthFunc(SamplerCompareFunction depthFunc);
|
||||
|
||||
Future setDepthCullingEnabled(bool enabled);
|
||||
Future setParameterFloat4(String name, double x, double y, double z, double w);
|
||||
Future setParameterFloat2(String name, double x, double y);
|
||||
Future setParameterFloat(String name, double x);
|
||||
Future setParameterInt(String name, int value);
|
||||
|
||||
/// Defines stencil operations
|
||||
enum StencilOperation {
|
||||
/// Keep the current value
|
||||
KEEP,
|
||||
|
||||
/// Set the value to zero
|
||||
ZERO,
|
||||
|
||||
/// Set the value to reference value
|
||||
REPLACE,
|
||||
|
||||
/// Increment the current value with saturation
|
||||
INCR,
|
||||
|
||||
/// Increment the current value without saturation
|
||||
INCR_WRAP,
|
||||
|
||||
/// Decrement the current value with saturation
|
||||
DECR,
|
||||
|
||||
/// Decrement the current value without saturation
|
||||
DECR_WRAP,
|
||||
|
||||
/// Invert the current value
|
||||
INVERT
|
||||
}
|
||||
|
||||
enum CullingMode {
|
||||
NONE, // No culling
|
||||
FRONT, // Cull front faces
|
||||
BACK, // Cull back faces
|
||||
FRONT_AND_BACK // Cull both front and back faces
|
||||
}
|
||||
|
||||
/// Defines which face(s) the stencil operation affects
|
||||
enum StencilFace {
|
||||
/// Front face only
|
||||
FRONT,
|
||||
|
||||
/// Back face only
|
||||
BACK,
|
||||
|
||||
/// Both front and back faces
|
||||
FRONT_AND_BACK
|
||||
}
|
||||
|
||||
enum AlphaMode { OPAQUE, MASK, BLEND }
|
||||
|
||||
abstract class MaterialInstance {
|
||||
Future<bool> isStencilWriteEnabled();
|
||||
Future setDepthWriteEnabled(bool enabled);
|
||||
Future setDepthFunc(SamplerCompareFunction depthFunc);
|
||||
Future setDepthCullingEnabled(bool enabled);
|
||||
Future setParameterFloat4(
|
||||
String name, double x, double y, double z, double w);
|
||||
Future setParameterFloat2(String name, double x, double y);
|
||||
Future setParameterFloat(String name, double x);
|
||||
Future setParameterInt(String name, int value);
|
||||
|
||||
/// Sets the stencil operation to be performed when the stencil test fails
|
||||
Future setStencilOpStencilFail(StencilOperation op,
|
||||
[StencilFace face = StencilFace.FRONT_AND_BACK]);
|
||||
|
||||
/// Sets the stencil operation to be performed when the depth test fails
|
||||
Future setStencilOpDepthFail(StencilOperation op,
|
||||
[StencilFace face = StencilFace.FRONT_AND_BACK]);
|
||||
|
||||
/// Sets the stencil operation to be performed when both depth and stencil tests pass
|
||||
Future setStencilOpDepthStencilPass(StencilOperation op,
|
||||
[StencilFace face = StencilFace.FRONT_AND_BACK]);
|
||||
|
||||
/// Sets the stencil test comparison function
|
||||
Future setStencilCompareFunction(SamplerCompareFunction func,
|
||||
[StencilFace face = StencilFace.FRONT_AND_BACK]);
|
||||
|
||||
/// Sets the reference value used for stencil testing
|
||||
Future setStencilReferenceValue(int value,
|
||||
[StencilFace face = StencilFace.FRONT_AND_BACK]);
|
||||
|
||||
Future setStencilWriteEnabled(bool enabled);
|
||||
|
||||
Future setCullingMode(CullingMode cullingMode);
|
||||
|
||||
Future setStencilReadMask(int mask);
|
||||
Future setStencilWriteMask(int mask);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'swap_chain.dart';
|
||||
|
||||
|
||||
///
|
||||
/// The viewport currently attached to a [View].
|
||||
@@ -27,4 +27,6 @@ abstract class View {
|
||||
Future setFrustumCullingEnabled(bool enabled);
|
||||
Future setToneMapper(ToneMapper mapper);
|
||||
Future setBloom(double strength);
|
||||
Future setStencilBufferEnabled(bool enabled);
|
||||
Future<bool> isStencilBufferEnabled();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'package:thermion_dart/src/viewer/src/events.dart';
|
||||
import '../../utils/src/gizmo.dart';
|
||||
import 'shared_types/shared_types.dart';
|
||||
export 'shared_types/shared_types.dart';
|
||||
@@ -9,30 +8,30 @@ import 'package:vector_math/vector_math_64.dart';
|
||||
import 'dart:async';
|
||||
import 'package:animation_tools_dart/animation_tools_dart.dart';
|
||||
|
||||
import 'shared_types/view.dart';
|
||||
|
||||
const double kNear = 0.05;
|
||||
const double kFar = 1000.0;
|
||||
const double kFocalLength = 28.0;
|
||||
|
||||
enum VisibilityLayers {
|
||||
DEFAULT_ASSET(0),
|
||||
LAYER_1(1),
|
||||
LAYER_2(2),
|
||||
LAYER_3(3),
|
||||
LAYER_4(4),
|
||||
LAYER_5(5),
|
||||
BACKGROUND(6),
|
||||
OVERLAY(7);
|
||||
|
||||
final int value;
|
||||
const VisibilityLayers(this.value);
|
||||
}
|
||||
|
||||
abstract class ThermionViewer {
|
||||
///
|
||||
/// A Future that resolves when the underlying rendering context has been successfully created.
|
||||
///
|
||||
Future<bool> get initialized;
|
||||
|
||||
///
|
||||
/// The result(s) of calling [pick] (see below).
|
||||
/// This may be a broadcast stream, so you should ensure you have subscribed to this stream before calling [pick].
|
||||
/// If [pick] is called without an active subscription to this stream, the results will be silently discarded.
|
||||
///
|
||||
Stream<FilamentPickResult> get pickResult;
|
||||
|
||||
///
|
||||
/// A Stream containing entities added/removed to/from to the scene.
|
||||
///
|
||||
Stream<SceneUpdateEvent> get sceneUpdated;
|
||||
|
||||
///
|
||||
/// Whether the controller is currently rendering at [framerate].
|
||||
///
|
||||
@@ -74,8 +73,7 @@ abstract class ThermionViewer {
|
||||
///
|
||||
///
|
||||
///
|
||||
Future destroySwapChain(
|
||||
covariant SwapChain swapChain);
|
||||
Future destroySwapChain(covariant SwapChain swapChain);
|
||||
|
||||
///
|
||||
///
|
||||
@@ -86,8 +84,7 @@ abstract class ThermionViewer {
|
||||
///
|
||||
///
|
||||
///
|
||||
Future destroyRenderTarget(
|
||||
covariant RenderTarget renderTarget);
|
||||
Future destroyRenderTarget(covariant RenderTarget renderTarget);
|
||||
|
||||
///
|
||||
///
|
||||
@@ -215,24 +212,24 @@ abstract class ThermionViewer {
|
||||
Future clearLights();
|
||||
|
||||
///
|
||||
/// Load the .glb asset at the given path and insert into the scene.
|
||||
/// Load the .glb asset at the given path, adding all entities to the scene.
|
||||
/// Specify [numInstances] to create multiple instances (this is more efficient than dynamically instantating at a later time). You can then retrieve the created instances with [getInstances].
|
||||
/// If you want to be able to call [createInstance] at a later time, you must pass true for [keepData].
|
||||
/// If [keepData] is false, the source glTF data will be released and [createInstance] will throw an exception.
|
||||
///
|
||||
Future<ThermionEntity> loadGlb(String path,
|
||||
Future<ThermionAsset> loadGlb(String path,
|
||||
{int numInstances = 1, bool keepData = false});
|
||||
|
||||
///
|
||||
/// Load the .glb asset from the specified buffer and insert into the scene.
|
||||
/// Load the .glb asset from the specified buffer, adding all entities to the scene.
|
||||
/// Specify [numInstances] to create multiple instances (this is more efficient than dynamically instantating at a later time). You can then retrieve the created instances with [getInstances].
|
||||
/// If you want to be able to call [createInstance] at a later time, you must pass true for [keepData].
|
||||
/// If [keepData] is false, the source glTF data will be released and [createInstance] will throw an exception.
|
||||
/// If [loadResourcesAsync] is true, resources (textures, materials, etc) will
|
||||
/// If [loadResourcesAsync] is true, resources (textures, materials, etc) will
|
||||
/// be loaded asynchronously (so expect some material/texture pop-in);
|
||||
///
|
||||
///
|
||||
Future<ThermionEntity> loadGlbFromBuffer(Uint8List data,
|
||||
Future<ThermionAsset> loadGlbFromBuffer(Uint8List data,
|
||||
{int numInstances = 1,
|
||||
bool keepData = false,
|
||||
int priority = 4,
|
||||
@@ -240,28 +237,13 @@ abstract class ThermionViewer {
|
||||
bool loadResourcesAsync});
|
||||
|
||||
///
|
||||
/// Create a new instance of [entity].
|
||||
///
|
||||
Future<ThermionEntity> createInstance(ThermionEntity entity);
|
||||
|
||||
///
|
||||
/// Returns the number of instances of the asset associated with [entity].
|
||||
///
|
||||
Future<int> getInstanceCount(ThermionEntity entity);
|
||||
|
||||
///
|
||||
/// Returns all instances of [entity].
|
||||
///
|
||||
Future<List<ThermionEntity>> getInstances(ThermionEntity entity);
|
||||
|
||||
///
|
||||
/// Load the .gltf asset at the given path and insert into the scene.
|
||||
/// Load the .gltf asset at the given path, adding all entities to the scene.
|
||||
/// [relativeResourcePath] is the folder path where the glTF resources are stored;
|
||||
/// this is usually the parent directory of the .gltf file itself.
|
||||
///
|
||||
/// See [loadGlb] for an explanation of [keepData].
|
||||
///
|
||||
Future<ThermionEntity> loadGltf(String path, String relativeResourcePath,
|
||||
Future<ThermionAsset> loadGltf(String path, String relativeResourcePath,
|
||||
{bool keepData = false});
|
||||
|
||||
///
|
||||
@@ -277,32 +259,34 @@ abstract class ThermionViewer {
|
||||
/// Gets the names of all morph targets for the child renderable [childEntity] under [entity].
|
||||
///
|
||||
Future<List<String>> getMorphTargetNames(
|
||||
ThermionEntity entity, ThermionEntity childEntity);
|
||||
covariant ThermionAsset asset, ThermionEntity childEntity);
|
||||
|
||||
///
|
||||
/// Gets the names of all bones for the armature at [skinIndex] under the specified [entity].
|
||||
///
|
||||
Future<List<String>> getBoneNames(ThermionEntity entity, {int skinIndex = 0});
|
||||
Future<List<String>> getBoneNames(covariant ThermionAsset asset,
|
||||
{int skinIndex = 0});
|
||||
|
||||
///
|
||||
/// Gets the names of all glTF animations embedded in the specified entity.
|
||||
///
|
||||
Future<List<String>> getAnimationNames(ThermionEntity entity);
|
||||
Future<List<String>> getAnimationNames(covariant ThermionAsset asset);
|
||||
|
||||
///
|
||||
/// Returns the length (in seconds) of the animation at the given index.
|
||||
///
|
||||
Future<double> getAnimationDuration(
|
||||
ThermionEntity entity, int animationIndex);
|
||||
covariant ThermionAsset asset, int animationIndex);
|
||||
|
||||
///
|
||||
/// Animate the morph targets in [entity]. See [MorphTargetAnimation] for an explanation as to how to construct the animation frame data.
|
||||
/// Construct animation(s) for every entity under [asset]. If [targetMeshNames] is provided, only entities with matching names will be animated.
|
||||
/// [MorphTargetAnimation] for an explanation as to how to construct the animation frame data.
|
||||
/// This method will check the morph target names specified in [animation] against the morph target names that actually exist exist under [meshName] in [entity],
|
||||
/// throwing an exception if any cannot be found.
|
||||
/// It is permissible for [animation] to omit any targets that do exist under [meshName]; these simply won't be animated.
|
||||
///
|
||||
Future setMorphAnimationData(
|
||||
ThermionEntity entity, MorphAnimationData animation,
|
||||
covariant ThermionAsset asset, MorphAnimationData animation,
|
||||
{List<String>? targetMeshNames});
|
||||
|
||||
///
|
||||
@@ -314,7 +298,7 @@ abstract class ThermionViewer {
|
||||
/// Resets all bones in the given entity to their rest pose.
|
||||
/// This should be done before every call to addBoneAnimation.
|
||||
///
|
||||
Future resetBones(ThermionEntity entity);
|
||||
Future resetBones(ThermionAsset asset);
|
||||
|
||||
///
|
||||
/// Enqueues and plays the [animation] for the specified bone(s).
|
||||
@@ -334,7 +318,7 @@ abstract class ThermionViewer {
|
||||
/// This will be applied in reverse after [fadeOutInSecs].
|
||||
///
|
||||
///
|
||||
Future addBoneAnimation(ThermionEntity entity, BoneAnimationData animation,
|
||||
Future addBoneAnimation(ThermionAsset asset, BoneAnimationData animation,
|
||||
{int skinIndex = 0,
|
||||
double fadeInInSecs = 0.0,
|
||||
double fadeOutInSecs = 0.0,
|
||||
@@ -344,7 +328,7 @@ abstract class ThermionViewer {
|
||||
/// Gets the entity representing the bone at [boneIndex]/[skinIndex].
|
||||
/// The returned entity is only intended for use with [getWorldTransform].
|
||||
///
|
||||
Future<ThermionEntity> getBone(ThermionEntity parent, int boneIndex,
|
||||
Future<ThermionEntity> getBone(covariant ThermionAsset asset, int boneIndex,
|
||||
{int skinIndex = 0});
|
||||
|
||||
///
|
||||
@@ -362,7 +346,8 @@ abstract class ThermionViewer {
|
||||
/// Note that [parent] must be the ThermionEntity returned by [loadGlb/loadGltf], not any other method ([getChildEntity] etc).
|
||||
/// This is because all joint information is internally stored with the parent entity.
|
||||
///
|
||||
Future<Matrix4> getInverseBindMatrix(ThermionEntity parent, int boneIndex,
|
||||
Future<Matrix4> getInverseBindMatrix(
|
||||
covariant ThermionAsset asset, int boneIndex,
|
||||
{int skinIndex = 0});
|
||||
|
||||
///
|
||||
@@ -398,7 +383,7 @@ abstract class ThermionViewer {
|
||||
/// Removes/destroys the specified entity from the scene.
|
||||
/// [entity] will no longer be a valid handle after this method is called; ensure you immediately discard all references once this method is complete.
|
||||
///
|
||||
Future removeEntity(ThermionEntity entity);
|
||||
Future removeEntity(ThermionAsset asset);
|
||||
|
||||
///
|
||||
/// Removes/destroys all renderable entities from the scene (including cameras).
|
||||
@@ -407,9 +392,9 @@ abstract class ThermionViewer {
|
||||
Future clearEntities();
|
||||
|
||||
///
|
||||
/// Schedules the glTF animation at [index] in [entity] to start playing on the next frame.
|
||||
/// Schedules the glTF animation at [index] in [asset] to start playing on the next frame.
|
||||
///
|
||||
Future playAnimation(ThermionEntity entity, int index,
|
||||
Future playAnimation(ThermionAsset asset, int index,
|
||||
{bool loop = false,
|
||||
bool reverse = false,
|
||||
bool replaceActive = true,
|
||||
@@ -419,17 +404,27 @@ abstract class ThermionViewer {
|
||||
///
|
||||
/// Schedules the glTF animation at [index] in [entity] to start playing on the next frame.
|
||||
///
|
||||
Future playAnimationByName(ThermionEntity entity, String name,
|
||||
Future playAnimationByName(covariant ThermionAsset asset, String name,
|
||||
{bool loop = false,
|
||||
bool reverse = false,
|
||||
bool replaceActive = true,
|
||||
double crossfade = 0.0});
|
||||
|
||||
Future setAnimationFrame(
|
||||
ThermionEntity entity, int index, int animationFrame);
|
||||
///
|
||||
///
|
||||
///
|
||||
Future setGltfAnimationFrame(
|
||||
covariant ThermionAsset asset, int index, int animationFrame);
|
||||
|
||||
Future stopAnimation(ThermionEntity entity, int animationIndex);
|
||||
Future stopAnimationByName(ThermionEntity entity, String name);
|
||||
///
|
||||
///
|
||||
///
|
||||
Future stopAnimation(covariant ThermionAsset asset, int animationIndex);
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
Future stopAnimationByName(covariant ThermionAsset asset, String name);
|
||||
|
||||
///
|
||||
/// Sets the current scene camera to the glTF camera under [name] in [entity].
|
||||
@@ -576,44 +571,11 @@ abstract class ThermionViewer {
|
||||
///
|
||||
Future setCameraModelMatrix4(Matrix4 matrix);
|
||||
|
||||
///
|
||||
/// Sets the `baseColorFactor` property for the material at index [materialIndex] in [entity] under node [meshName] to [color].
|
||||
///
|
||||
@Deprecated("Use setMaterialPropertyFloat4 instead")
|
||||
Future setMaterialColor(ThermionEntity entity, String meshName,
|
||||
int materialIndex, double r, double g, double b, double a);
|
||||
|
||||
///
|
||||
/// Sets the material property [propertyName] under material [materialIndex] for [entity] to [value].
|
||||
/// [entity] must have a Renderable attached.
|
||||
///
|
||||
Future setMaterialPropertyFloat4(ThermionEntity entity, String propertyName,
|
||||
int materialIndex, double f1, double f2, double f3, double f4);
|
||||
|
||||
///
|
||||
/// Sets the material property [propertyName] under material [materialIndex] for [entity] to [value].
|
||||
/// [entity] must have a Renderable attached.
|
||||
///
|
||||
Future setMaterialPropertyFloat(ThermionEntity entity, String propertyName,
|
||||
int materialIndex, double value);
|
||||
|
||||
///
|
||||
/// Sets the material property [propertyName] under material [materialIndex] for [entity] to [value].
|
||||
/// [entity] must have a Renderable attached.
|
||||
///
|
||||
Future setMaterialPropertyInt(
|
||||
ThermionEntity entity, String propertyName, int materialIndex, int value);
|
||||
|
||||
///
|
||||
/// Scale [entity] to fit within the unit cube.
|
||||
///
|
||||
Future transformToUnitCube(ThermionEntity entity);
|
||||
|
||||
///
|
||||
/// Directly sets the world space position for [entity] to the given coordinates.
|
||||
///
|
||||
Future setPosition(ThermionEntity entity, double x, double y, double z);
|
||||
|
||||
///
|
||||
/// Set the world space position for [lightEntity] to the given coordinates.
|
||||
///
|
||||
@@ -625,17 +587,6 @@ abstract class ThermionViewer {
|
||||
///
|
||||
Future setLightDirection(ThermionEntity lightEntity, Vector3 direction);
|
||||
|
||||
///
|
||||
/// Directly sets the scale for [entity], skipping all collision detection.
|
||||
///
|
||||
Future setScale(ThermionEntity entity, double scale);
|
||||
|
||||
///
|
||||
/// Directly sets the rotation for [entity] to [rads] around the axis {x,y,z}, skipping all collision detection.
|
||||
///
|
||||
Future setRotation(
|
||||
ThermionEntity entity, double rads, double x, double y, double z);
|
||||
|
||||
///
|
||||
/// TODO
|
||||
///
|
||||
@@ -674,28 +625,22 @@ abstract class ThermionViewer {
|
||||
Future setAntiAliasing(bool msaa, bool fxaa, bool taa);
|
||||
|
||||
///
|
||||
/// Sets the rotation for [entity] to the specified quaternion.
|
||||
/// Adds a single [entity] to the scene.
|
||||
///
|
||||
Future setRotationQuat(ThermionEntity entity, Quaternion rotation);
|
||||
Future addEntityToScene(ThermionEntity entity);
|
||||
|
||||
///
|
||||
/// Reveal the node [meshName] under [entity]. Only applicable if [hide] had previously been called; this is a no-op otherwise.
|
||||
/// Removes a single [entity] from the scene.
|
||||
///
|
||||
Future reveal(ThermionEntity entity, String? meshName);
|
||||
Future removeEntityFromScene(ThermionEntity entity);
|
||||
|
||||
///
|
||||
/// If [meshName] is provided, hide the node [meshName] under [entity], otherwise hide the root node for [entity].
|
||||
/// The entity still exists in memory, but is no longer being rendered into the scene. Call [reveal] to re-commence rendering.
|
||||
///
|
||||
Future hide(ThermionEntity entity, String? meshName);
|
||||
|
||||
///
|
||||
/// Used to select the entity in the scene at the given viewport coordinates.
|
||||
/// Called by `FilamentGestureDetector` on a mouse/finger down event. You probably don't want to call this yourself.
|
||||
/// This is asynchronous and will require 2-3 frames to complete - subscribe to the [pickResult] stream to receive the results of this method.
|
||||
/// Hit test the viewport at the given coordinates. If the coordinates intersect
|
||||
/// with a renderable entity, [resultHandler] will be called.
|
||||
/// This is asynchronous and will require 2-3 frames to complete (so ensure you are calling render())
|
||||
/// [x] and [y] must be in local logical coordinates (i.e. where 0,0 is at top-left of the ThermionWidget).
|
||||
///
|
||||
Future pick(int x, int y);
|
||||
Future pick(int x, int y, void Function(PickResult) resultHandler);
|
||||
|
||||
///
|
||||
/// Retrieves the name assigned to the given ThermionEntity (usually corresponds to the glTF mesh name).
|
||||
@@ -703,23 +648,16 @@ abstract class ThermionViewer {
|
||||
String? getNameForEntity(ThermionEntity entity);
|
||||
|
||||
///
|
||||
/// Returns all child entities under [parent].
|
||||
/// Returns all child entities under [asset].
|
||||
///
|
||||
Future<List<ThermionEntity>> getChildEntities(
|
||||
ThermionEntity parent, bool renderableOnly);
|
||||
Future<List<ThermionEntity>> getChildEntities(covariant ThermionAsset asset);
|
||||
|
||||
///
|
||||
/// Finds the child entity named [childName] associated with the given parent.
|
||||
/// Usually, [parent] will be the return value from [loadGlb]/[loadGltf] and [childName] will be the name of a node/mesh.
|
||||
///
|
||||
Future<ThermionEntity> getChildEntity(
|
||||
ThermionEntity parent, String childName);
|
||||
|
||||
///
|
||||
/// List the name of all child entities under the given entity.
|
||||
///
|
||||
Future<List<String>> getChildEntityNames(ThermionEntity entity,
|
||||
{bool renderableOnly = true});
|
||||
Future<ThermionEntity?> getChildEntity(
|
||||
covariant ThermionAsset asset, String childName);
|
||||
|
||||
///
|
||||
/// An [entity] will only be animatable after an animation component is attached.
|
||||
@@ -750,8 +688,9 @@ abstract class ThermionViewer {
|
||||
/// Creates a (renderable) entity with the specified geometry and adds to the scene.
|
||||
/// If [keepData] is true, the source data will not be released.
|
||||
///
|
||||
Future createGeometry(Geometry geometry,
|
||||
{MaterialInstance? materialInstance, bool keepData = false});
|
||||
Future<ThermionAsset> createGeometry(Geometry geometry,
|
||||
{covariant List<MaterialInstance>? materialInstances,
|
||||
bool keepData = false});
|
||||
|
||||
///
|
||||
/// Gets the parent entity of [entity]. Returns null if the entity has no parent.
|
||||
@@ -783,7 +722,8 @@ abstract class ThermionViewer {
|
||||
///
|
||||
/// The gizmo for translating/rotating objects. Only one gizmo can be active for a given view.
|
||||
///
|
||||
Future<Gizmo> createGizmo(covariant View view);
|
||||
Future<GizmoAsset> createGizmo(covariant View view,
|
||||
GizmoType type);
|
||||
|
||||
///
|
||||
/// Register a callback to be invoked when this viewer is disposed.
|
||||
@@ -803,34 +743,23 @@ abstract class ThermionViewer {
|
||||
///
|
||||
/// Toggles the visibility of the respective layer.
|
||||
///
|
||||
Future setLayerVisibility(int layer, bool visible);
|
||||
Future setLayerVisibility(VisibilityLayers layer, bool visible);
|
||||
|
||||
///
|
||||
/// All renderable entities are assigned a layer mask.
|
||||
///
|
||||
/// By calling [setLayerVisibility], all renderable entities allocated to
|
||||
/// the given layer can be efficiently hidden/revealed.
|
||||
///
|
||||
/// By default, all renderable entities are assigned to layer 0 (and this
|
||||
/// layer is enabled by default). Call [setVisibilityLayer] to change the
|
||||
/// All renderable entities are assigned a layer mask.
|
||||
///
|
||||
/// By calling [setLayerVisibility], all renderable entities allocated to
|
||||
/// the given layer can be efficiently hidden/revealed.
|
||||
///
|
||||
/// By default, all renderable entities are assigned to layer 0 (and this
|
||||
/// layer is enabled by default). Call [setVisibilityLayer] to change the
|
||||
/// layer for the specified entity.
|
||||
///
|
||||
/// Note that we currently also assign gizmos to layer 1 (enabled by default)
|
||||
/// and the world grid to layer 2 (disabled by default). We suggest you avoid
|
||||
///
|
||||
/// Note that we currently also assign gizmos to layer 1 (enabled by default)
|
||||
/// and the world grid to layer 2 (disabled by default). We suggest you avoid
|
||||
/// using these layers.
|
||||
///
|
||||
Future setVisibilityLayer(ThermionEntity entity, int layer);
|
||||
|
||||
///
|
||||
/// Renders an outline around [entity] with the given color.
|
||||
///
|
||||
Future setStencilHighlight(ThermionEntity entity,
|
||||
{double r = 1.0, double g = 0.0, double b = 0.0});
|
||||
|
||||
///
|
||||
/// Removes the outline around [entity]. Noop if there was no highlight.
|
||||
///
|
||||
Future removeStencilHighlight(ThermionEntity entity);
|
||||
Future setVisibilityLayer(ThermionEntity entity, VisibilityLayers layer);
|
||||
|
||||
///
|
||||
/// Decodes the specified image data and creates a texture.
|
||||
@@ -908,7 +837,7 @@ abstract class ThermionViewer {
|
||||
///
|
||||
///
|
||||
///
|
||||
Future<MaterialInstance?> getMaterialInstanceAt(
|
||||
Future<MaterialInstance> getMaterialInstanceAt(
|
||||
ThermionEntity entity, int index);
|
||||
|
||||
///
|
||||
|
||||
@@ -8,7 +8,7 @@ import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
import 'dart:async';
|
||||
import 'package:animation_tools_dart/animation_tools_dart.dart';
|
||||
import 'events.dart';
|
||||
|
||||
import 'shared_types/camera.dart';
|
||||
|
||||
class ThermionViewerStub extends ThermionViewer {
|
||||
@@ -18,16 +18,6 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future addBoneAnimation(ThermionEntity entity, BoneAnimationData animation,
|
||||
{int skinIndex = 0,
|
||||
double fadeInInSecs = 0.0,
|
||||
double fadeOutInSecs = 0.0,
|
||||
double maxDelta = 1.0}) {
|
||||
// TODO: implement addBoneAnimation
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future addCollisionComponent(ThermionEntity entity,
|
||||
{void Function(int entityId1, int entityId2)? callback,
|
||||
@@ -77,44 +67,12 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Future<ThermionEntity> createInstance(ThermionEntity entity) {
|
||||
// TODO: implement createInstance
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future dispose() {
|
||||
// TODO: implement dispose
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<double> getAnimationDuration(
|
||||
ThermionEntity entity, int animationIndex) {
|
||||
// TODO: implement getAnimationDuration
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<String>> getAnimationNames(ThermionEntity entity) {
|
||||
// TODO: implement getAnimationNames
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ThermionEntity> getBone(ThermionEntity parent, int boneIndex,
|
||||
{int skinIndex = 0}) {
|
||||
// TODO: implement getBone
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<String>> getBoneNames(ThermionEntity entity,
|
||||
{int skinIndex = 0}) {
|
||||
// TODO: implement getBoneNames
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<double> getCameraCullingFar() {
|
||||
@@ -170,58 +128,12 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<ThermionEntity>> getChildEntities(
|
||||
ThermionEntity parent, bool renderableOnly) {
|
||||
// TODO: implement getChildEntities
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ThermionEntity> getChildEntity(
|
||||
ThermionEntity parent, String childName) {
|
||||
// TODO: implement getChildEntity
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<String>> getChildEntityNames(ThermionEntity entity,
|
||||
{bool renderableOnly = true}) {
|
||||
// TODO: implement getChildEntityNames
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> getInstanceCount(ThermionEntity entity) {
|
||||
// TODO: implement getInstanceCount
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<ThermionEntity>> getInstances(ThermionEntity entity) {
|
||||
// TODO: implement getInstances
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Matrix4> getInverseBindMatrix(ThermionEntity parent, int boneIndex,
|
||||
{int skinIndex = 0}) {
|
||||
// TODO: implement getInverseBindMatrix
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Matrix4> getLocalTransform(ThermionEntity entity) {
|
||||
// TODO: implement getLocalTransform
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<String>> getMorphTargetNames(
|
||||
ThermionEntity entity, ThermionEntity childEntity) {
|
||||
// TODO: implement getMorphTargetNames
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
String? getNameForEntity(ThermionEntity entity) {
|
||||
@@ -241,11 +153,6 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future hide(ThermionEntity entity, String? meshName) {
|
||||
// TODO: implement hide
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
// TODO: implement initialized
|
||||
@@ -296,27 +203,6 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
// TODO: implement pickResult
|
||||
Stream<FilamentPickResult> get pickResult => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
Future playAnimation(ThermionEntity entity, int index,
|
||||
{bool loop = false,
|
||||
bool reverse = false,
|
||||
bool replaceActive = true,
|
||||
double crossfade = 0.0,
|
||||
double startOffset=0.0}) {
|
||||
// TODO: implement playAnimation
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future playAnimationByName(ThermionEntity entity, String name,
|
||||
{bool loop = false,
|
||||
bool reverse = false,
|
||||
bool replaceActive = true,
|
||||
double crossfade = 0.0}) {
|
||||
// TODO: implement playAnimationByName
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future queuePositionUpdate(
|
||||
ThermionEntity entity, double x, double y, double z,
|
||||
@@ -352,12 +238,6 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future removeEntity(ThermionEntity entity) {
|
||||
// TODO: implement removeEntity
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future removeIbl() {
|
||||
// TODO: implement removeIbl
|
||||
@@ -381,17 +261,6 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
// TODO: implement rendering
|
||||
bool get rendering => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
Future resetBones(ThermionEntity entity) {
|
||||
// TODO: implement resetBones
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future reveal(ThermionEntity entity, String? meshName) {
|
||||
// TODO: implement reveal
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future rotateEnd() {
|
||||
@@ -417,12 +286,7 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setAnimationFrame(
|
||||
ThermionEntity entity, int index, int animationFrame) {
|
||||
// TODO: implement setAnimationFrame
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Future setAntiAliasing(bool msaa, bool fxaa, bool taa) {
|
||||
@@ -546,24 +410,6 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future clearMorphAnimationData(ThermionEntity entity) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setMorphAnimationData(
|
||||
ThermionEntity entity, MorphAnimationData animation,
|
||||
{List<String>? targetMeshNames}) {
|
||||
// TODO: implement setMorphAnimationData
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setMorphTargetWeights(ThermionEntity entity, List<double> weights) {
|
||||
// TODO: implement setMorphTargetWeights
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setParent(ThermionEntity child, ThermionEntity parent, { bool preserveScaling = false}) {
|
||||
@@ -644,17 +490,6 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future stopAnimation(ThermionEntity entity, int animationIndex) {
|
||||
// TODO: implement stopAnimation
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future stopAnimationByName(ThermionEntity entity, String name) {
|
||||
// TODO: implement stopAnimationByName
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future testCollisions(ThermionEntity entity) {
|
||||
@@ -811,18 +646,7 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Future<ThermionEntity> loadGlb(String path, {int numInstances = 1, bool keepData = false}) {
|
||||
// TODO: implement loadGlb
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ThermionEntity> loadGltf(String path, String relativeResourcePath, {bool keepData = false}) {
|
||||
// TODO: implement loadGltf
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setMaterialPropertyFloat(ThermionEntity entity, String propertyName, int materialIndex, double value) {
|
||||
@@ -836,9 +660,6 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
// TODO: implement sceneUpdated
|
||||
Stream<SceneUpdateEvent> get sceneUpdated => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
Future<ThermionEntity> addDirectLight(DirectLight light) {
|
||||
@@ -882,14 +703,6 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future createGeometry(Geometry geometry, {MaterialInstance? materialInstance, bool keepData = false}) {
|
||||
// TODO: implement createGeometry
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@override
|
||||
Future setMaterialPropertyInt(ThermionEntity entity, String propertyName, int materialIndex, int value) {
|
||||
// TODO: implement setMaterialPropertyInt
|
||||
@@ -1052,12 +865,6 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ThermionEntity> loadGlbFromBuffer(Uint8List data, {int numInstances = 1, bool keepData = false, int priority = 4, int layer = 0, bool loadResourcesAsync= false}) {
|
||||
// TODO: implement loadGlbFromBuffer
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future destroyRenderTarget(covariant RenderTarget renderTarget) {
|
||||
// TODO: implement destroyRenderTarget
|
||||
@@ -1081,6 +888,189 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
// TODO: implement getRenderableBoundingBox
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future pick(int x, int y) {
|
||||
// TODO: implement pick
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Future<ThermionAsset> createInstance(covariant ThermionAsset asset, {covariant List<MaterialInstance>? materialInstances = null}) {
|
||||
// TODO: implement createInstance
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> getInstanceCount(covariant ThermionAsset entity) {
|
||||
// TODO: implement getInstanceCount
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<ThermionEntity>> getInstances(covariant ThermionAsset entity) {
|
||||
// TODO: implement getInstances
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future hide(ThermionEntity entity) {
|
||||
// TODO: implement hide
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ThermionAsset> loadGlb(String path, {int numInstances = 1, bool keepData = false}) {
|
||||
// TODO: implement loadGlb
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Future<ThermionAsset> loadGltf(String path, String relativeResourcePath, {bool keepData = false}) {
|
||||
// TODO: implement loadGltf
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future reveal(ThermionEntity entity) {
|
||||
// TODO: implement reveal
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ThermionAsset> loadGlbFromBuffer(Uint8List data, {int numInstances = 1, bool keepData = false, int priority = 4, int layer = 0, bool loadResourcesAsync=false}) {
|
||||
// TODO: implement loadGlbFromBuffer
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future addBoneAnimation(ThermionAsset asset, BoneAnimationData animation, {int skinIndex = 0, double fadeInInSecs = 0.0, double fadeOutInSecs = 0.0, double maxDelta = 1.0}) {
|
||||
// TODO: implement addBoneAnimation
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<double> getAnimationDuration(covariant ThermionAsset asset, int animationIndex) {
|
||||
// TODO: implement getAnimationDuration
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<String>> getAnimationNames(covariant ThermionAsset asset) {
|
||||
// TODO: implement getAnimationNames
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ThermionEntity> getBone(covariant ThermionAsset asset, int boneIndex, {int skinIndex = 0}) {
|
||||
// TODO: implement getBone
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<String>> getBoneNames(covariant ThermionAsset asset, {int skinIndex = 0}) {
|
||||
// TODO: implement getBoneNames
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<ThermionEntity>> getChildEntities(covariant ThermionAsset asset) {
|
||||
// TODO: implement getChildEntities
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ThermionEntity?> getChildEntity(covariant ThermionAsset asset, String childName) {
|
||||
// TODO: implement getChildEntity
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Matrix4> getInverseBindMatrix(covariant ThermionAsset asset, int boneIndex, {int skinIndex = 0}) {
|
||||
// TODO: implement getInverseBindMatrix
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<String>> getMorphTargetNames(covariant ThermionAsset asset, ThermionEntity childEntity) {
|
||||
// TODO: implement getMorphTargetNames
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future playAnimationByName(covariant ThermionAsset asset, String name, {bool loop = false, bool reverse = false, bool replaceActive = true, double crossfade = 0.0}) {
|
||||
// TODO: implement playAnimationByName
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setAnimationFrame(covariant ThermionAsset asset, int index, int animationFrame) {
|
||||
// TODO: implement setAnimationFrame
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setMorphAnimationData(ThermionAsset asset, MorphAnimationData animation, {List<String>? targetMeshNames}) {
|
||||
// TODO: implement setMorphAnimationData
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Future stopAnimation(covariant ThermionAsset asset, int animationIndex) {
|
||||
// TODO: implement stopAnimation
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future stopAnimationByName(covariant ThermionAsset asset, String name) {
|
||||
// TODO: implement stopAnimationByName
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future playAnimation(ThermionAsset asset, int index, {bool loop = false, bool reverse = false, bool replaceActive = true, double crossfade = 0.0, double startOffset = 0.0}) {
|
||||
// TODO: implement playAnimation
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future removeEntity(ThermionAsset asset) {
|
||||
// TODO: implement removeEntity
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future resetBones(ThermionAsset asset) {
|
||||
// TODO: implement resetBones
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future clearMorphAnimationData(ThermionEntity entity) {
|
||||
// TODO: implement clearMorphAnimationData
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ThermionAsset> createGeometry(Geometry geometry, {covariant List<MaterialInstance>? materialInstances, bool keepData = false}) {
|
||||
// TODO: implement createGeometry
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setGltfAnimationFrame(covariant ThermionAsset asset, int index, int animationFrame) {
|
||||
// TODO: implement setGltfAnimationFrame
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setMorphTargetWeights(ThermionEntity entity, List<double> weights) {
|
||||
// TODO: implement setMorphTargetWeights
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -4,17 +4,6 @@ class ThermionWasmMaterialInstance extends MaterialInstance {
|
||||
final int pointer;
|
||||
|
||||
ThermionWasmMaterialInstance(this.pointer);
|
||||
@override
|
||||
Future setDepthCullingEnabled(bool enabled) {
|
||||
// TODO: implement setDepthCullingEnabled
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setDepthWriteEnabled(bool enabled) {
|
||||
// TODO: implement setDepthWriteEnabled
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setParameterFloat2(String name, double x, double y) {
|
||||
@@ -45,4 +34,64 @@ class ThermionWasmMaterialInstance extends MaterialInstance {
|
||||
// TODO: implement setParameterInt
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setDepthCullingEnabled(enabled) {
|
||||
// TODO: implement setDepthCullingEnabled
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setDepthWriteEnabled(enabled) {
|
||||
// TODO: implement setDepthWriteEnabled
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setStencilCompareFunction(SamplerCompareFunction func, [StencilFace face = StencilFace.FRONT_AND_BACK]) {
|
||||
// TODO: implement setStencilCompareFunction
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setStencilOpDepthFail(StencilOperation op, [StencilFace face = StencilFace.FRONT_AND_BACK]) {
|
||||
// TODO: implement setStencilOpDepthFail
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setStencilOpDepthStencilPass(StencilOperation op, [StencilFace face = StencilFace.FRONT_AND_BACK]) {
|
||||
// TODO: implement setStencilOpDepthStencilPass
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setStencilOpStencilFail(StencilOperation op, [StencilFace face = StencilFace.FRONT_AND_BACK]) {
|
||||
// TODO: implement setStencilOpStencilFail
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setStencilReferenceValue(int value, [StencilFace face = StencilFace.FRONT_AND_BACK]) {
|
||||
// TODO: implement setStencilReferenceValue
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> isStencilWriteEnabled() {
|
||||
// TODO: implement isStencilWriteEnabled
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setCullingMode(CullingMode cullingMode) {
|
||||
// TODO: implement setCullingMode
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setStencilWriteEnabled(bool enabled) {
|
||||
// TODO: implement setStencilWriteEnabled
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include <chrono>
|
||||
|
||||
#include "ResourceBuffer.hpp"
|
||||
#include "SceneManager.hpp"
|
||||
#include "scene/SceneManager.hpp"
|
||||
#include "ThreadPool.hpp"
|
||||
|
||||
namespace thermion
|
||||
@@ -65,9 +65,6 @@ namespace thermion
|
||||
void rotateIbl(const math::mat3f &matrix);
|
||||
void createIbl(float r, float g, float b, float intensity);
|
||||
|
||||
void removeEntity(EntityId asset);
|
||||
void clearEntities();
|
||||
|
||||
void render(
|
||||
uint64_t frameTimeInNanos
|
||||
);
|
||||
@@ -98,15 +95,6 @@ namespace thermion
|
||||
void clearBackgroundImage();
|
||||
void setBackgroundImagePosition(float x, float y, bool clamp, uint32_t width, uint32_t height);
|
||||
|
||||
typedef void (*PickCallback)(EntityId entityId, int x, int y, View *view, float depth, float fragX, float fragY, float fragZ);
|
||||
|
||||
///
|
||||
/// Returns true if the specified entity is a gizmo, grid or background image entity.
|
||||
///
|
||||
bool isNonPickableEntity(EntityId entityId);
|
||||
|
||||
void pick(View *view, uint32_t x, uint32_t y, PickCallback callback);
|
||||
|
||||
Engine* getEngine() {
|
||||
return _engine;
|
||||
}
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <utils/Entity.h>
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/Material.h>
|
||||
#include <filament/MaterialInstance.h>
|
||||
#include <filament/Scene.h>
|
||||
#include <filament/Camera.h>
|
||||
#include <filament/View.h>
|
||||
#include <filament/Viewport.h>
|
||||
|
||||
#include <gltfio/AssetLoader.h>
|
||||
#include <gltfio/FilamentAsset.h>
|
||||
#include <gltfio/FilamentInstance.h>
|
||||
#include <gltfio/ResourceLoader.h>
|
||||
|
||||
#include <filament/IndexBuffer.h>
|
||||
#include <filament/InstanceBuffer.h>
|
||||
|
||||
#include "ThermionDartApi.h"
|
||||
|
||||
namespace thermion {
|
||||
|
||||
using namespace filament;
|
||||
using namespace utils;
|
||||
|
||||
class Gizmo {
|
||||
|
||||
enum Axis { X, Y, Z};
|
||||
|
||||
public:
|
||||
Gizmo(Engine *engine, View *view, Scene *scene, Material* material);
|
||||
~Gizmo();
|
||||
|
||||
typedef void (*PickCallback)(EntityId entityId, uint32_t x, uint32_t y, View *view);
|
||||
|
||||
Entity x() {
|
||||
return _entities[0];
|
||||
};
|
||||
Entity y() {
|
||||
return _entities[1];
|
||||
};
|
||||
Entity z() {
|
||||
return _entities[2];
|
||||
};
|
||||
Entity center() {
|
||||
return _entities[3];
|
||||
};
|
||||
|
||||
bool isActive() {
|
||||
return _isActive;
|
||||
}
|
||||
|
||||
void pick(uint32_t x, uint32_t y, PickCallback callback);
|
||||
bool isGizmoEntity(Entity entity);
|
||||
void setVisibility(bool visible);
|
||||
|
||||
private:
|
||||
|
||||
class PickCallbackHandler {
|
||||
public:
|
||||
PickCallbackHandler(Gizmo* gizmo, PickCallback callback) : _gizmo(gizmo), _callback(callback) {};
|
||||
void handle(filament::View::PickingQueryResult const &result) {
|
||||
auto x = static_cast<int32_t>(result.fragCoords.x);
|
||||
auto y= static_cast<int32_t>(result.fragCoords.y);
|
||||
for(int i = 0; i < 7; i++) {
|
||||
if(_gizmo->_entities[i] == result.renderable) {
|
||||
if(i < 4) {
|
||||
return;
|
||||
}
|
||||
_gizmo->highlight(_gizmo->_entities[i - 4]);
|
||||
_callback(Entity::smuggle(_gizmo->_entities[i - 4]), x, y, _gizmo->_view);
|
||||
return;
|
||||
}
|
||||
}
|
||||
_gizmo->unhighlight();
|
||||
_callback(0, x, y, _gizmo->_view);
|
||||
delete(this);
|
||||
}
|
||||
|
||||
private:
|
||||
Gizmo* _gizmo;
|
||||
PickCallback _callback;
|
||||
|
||||
};
|
||||
void createTransparentRectangles();
|
||||
void highlight(Entity entity);
|
||||
void unhighlight();
|
||||
Engine *_engine;
|
||||
Scene *_scene;
|
||||
View *_view;
|
||||
Material* _material;
|
||||
|
||||
utils::Entity _entities[7] = { utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity() };
|
||||
|
||||
MaterialInstance* _materialInstances[7];
|
||||
math::float4 inactiveColors[3] {
|
||||
math::float4 { 1.0f, 0.0f, 0.0f, 0.5f },
|
||||
math::float4 { 0.0f, 1.0f, 0.0f, 0.5f },
|
||||
math::float4 { 0.0f, 0.0f, 1.0f, 0.5f },
|
||||
};
|
||||
math::float4 activeColors[3] {
|
||||
math::float4 { 1.0f, 0.0f, 0.0f, 1.0f },
|
||||
math::float4 { 0.0f, 1.0f, 0.0f, 1.0f },
|
||||
math::float4 { 0.0f, 0.0f, 1.0f, 1.0f },
|
||||
};
|
||||
bool _isActive = true;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include <math/mat4.h>
|
||||
#include "APIBoundaryTypes.h"
|
||||
#include "c_api/APIBoundaryTypes.h"
|
||||
|
||||
namespace thermion {
|
||||
|
||||
@@ -1,365 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include <filament/Scene.h>
|
||||
#include <filament/Camera.h>
|
||||
#include <filament/View.h>
|
||||
|
||||
#include <gltfio/AssetLoader.h>
|
||||
#include <gltfio/FilamentAsset.h>
|
||||
#include <gltfio/FilamentInstance.h>
|
||||
#include <gltfio/ResourceLoader.h>
|
||||
|
||||
#include <filament/IndexBuffer.h>
|
||||
#include <filament/InstanceBuffer.h>
|
||||
#include <utils/NameComponentManager.h>
|
||||
|
||||
#include "tsl/robin_map.h"
|
||||
|
||||
|
||||
#include "APIBoundaryTypes.h"
|
||||
#include "CustomGeometry.hpp"
|
||||
#include "Gizmo.hpp"
|
||||
#include "GridOverlay.hpp"
|
||||
#include "ResourceBuffer.hpp"
|
||||
#include "components/CollisionComponentManager.hpp"
|
||||
#include "components/AnimationComponentManager.hpp"
|
||||
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
typedef int32_t EntityId;
|
||||
|
||||
using namespace filament;
|
||||
using namespace filament::gltfio;
|
||||
using namespace utils;
|
||||
using std::string;
|
||||
using std::unique_ptr;
|
||||
using std::vector;
|
||||
|
||||
class SceneManager
|
||||
{
|
||||
public:
|
||||
SceneManager(
|
||||
const ResourceLoaderWrapperImpl *const loader,
|
||||
Engine *engine,
|
||||
Scene *scene,
|
||||
const char *uberArchivePath,
|
||||
Camera* mainCamera);
|
||||
~SceneManager();
|
||||
|
||||
enum LAYERS {
|
||||
DEFAULT_ASSETS = 0,
|
||||
BACKGROUND = 6,
|
||||
OVERLAY = 7,
|
||||
};
|
||||
|
||||
class HighlightOverlay {
|
||||
public:
|
||||
HighlightOverlay(EntityId id, SceneManager* const sceneManager, Engine* const engine, float r, float g, float b);
|
||||
~HighlightOverlay();
|
||||
|
||||
bool isValid() {
|
||||
return !_entity.isNull();
|
||||
}
|
||||
|
||||
private:
|
||||
MaterialInstance* _highlightMaterialInstance = nullptr;
|
||||
bool _isGeometryEntity = false;
|
||||
bool _isGltfAsset = false;
|
||||
FilamentInstance* _newInstance = nullptr;
|
||||
Entity _entity;
|
||||
Engine* const _engine;
|
||||
SceneManager* const _sceneManager;
|
||||
};
|
||||
|
||||
////
|
||||
/// @brief Load the glTF file from the specified path and adds all entities to the scene.
|
||||
/// @param uri the path to the asset. Should be either asset:// (representing a Flutter asset), or file:// (representing a filesystem file).
|
||||
/// @param relativeResourcePath the (relative) path to the asset's resources.
|
||||
/// @return the glTF entity.
|
||||
///
|
||||
EntityId loadGltf(const char *uri, const char *relativeResourcePath, bool keepData = false);
|
||||
|
||||
////
|
||||
/// @brief Load the GLB from the specified path, optionally creating multiple instances.
|
||||
/// @param uri the path to the asset. Should be either asset:// (representing a Flutter asset), or file:// (representing a filesystem file).
|
||||
/// @param numInstances the number of instances to create.
|
||||
/// @return an Entity representing the FilamentAsset associated with the loaded FilamentAsset.
|
||||
///
|
||||
EntityId loadGlb(const char *uri, int numInstances, bool keepData);
|
||||
EntityId loadGlbFromBuffer(const uint8_t *data, size_t length, int numInstances = 1, bool keepData = false, int priority = 4, int layer = 0, bool loadResourcesAsync = false);
|
||||
EntityId createInstance(EntityId entityId);
|
||||
|
||||
void remove(EntityId entity);
|
||||
void destroyAll();
|
||||
unique_ptr<vector<string>> getAnimationNames(EntityId entity);
|
||||
float getAnimationDuration(EntityId entity, int animationIndex);
|
||||
|
||||
unique_ptr<vector<string>> getMorphTargetNames(EntityId assetEntityId, EntityId childEntity);
|
||||
unique_ptr<vector<string>> getBoneNames(EntityId assetEntityId, EntityId childEntity);
|
||||
void transformToUnitCube(EntityId e);
|
||||
inline void updateTransform(EntityId e);
|
||||
void setScale(EntityId e, float scale);
|
||||
void setPosition(EntityId e, float x, float y, float z);
|
||||
void setRotation(EntityId e, float rads, float x, float y, float z, float w);
|
||||
|
||||
void queueTransformUpdates(EntityId* entities, math::mat4* transforms, int numEntities);
|
||||
void queueRelativePositionUpdateWorldAxis(EntityId entity, float viewportCoordX, float viewportCoordY, float x, float y, float z);
|
||||
void queueRelativePositionUpdateFromViewportVector(View* view, EntityId entityId, float viewportCoordX, float viewportCoordY);
|
||||
|
||||
const utils::Entity *getCameraEntities(EntityId e);
|
||||
size_t getCameraEntityCount(EntityId e);
|
||||
const utils::Entity *getLightEntities(EntityId e) noexcept;
|
||||
size_t getLightEntityCount(EntityId e) noexcept;
|
||||
|
||||
void updateAnimations();
|
||||
void updateTransforms();
|
||||
void testCollisions(EntityId entity);
|
||||
bool setMaterialColor(EntityId e, const char *meshName, int materialInstance, const float r, const float g, const float b, const float a);
|
||||
|
||||
bool setMorphAnimationBuffer(
|
||||
EntityId entityId,
|
||||
const float *const morphData,
|
||||
const uint32_t *const morphIndices,
|
||||
int numMorphTargets,
|
||||
int numFrames,
|
||||
float frameLengthInMs);
|
||||
|
||||
void clearMorphAnimationBuffer(
|
||||
EntityId entityId);
|
||||
|
||||
bool setMorphTargetWeights(EntityId entityId, const float *const weights, int count);
|
||||
|
||||
math::mat4f getLocalTransform(EntityId entityId);
|
||||
math::mat4f getWorldTransform(EntityId entityId);
|
||||
EntityId getBone(EntityId entityId, int skinIndex, int boneIndex);
|
||||
math::mat4f getInverseBindMatrix(EntityId entityId, int skinIndex, int boneIndex);
|
||||
|
||||
/// @brief Set the local transform for the bone at boneIndex/skinIndex in the given entity.
|
||||
/// @param entityId the parent entity
|
||||
/// @param entityName the name of the mesh under entityId for which the bone will be set.
|
||||
/// @param skinIndex the index of the joint skin. Currently only 0 is supported.
|
||||
/// @param boneName the name of the bone
|
||||
/// @param transform the 4x4 matrix representing the local transform for the bone
|
||||
/// @return true if the transform was successfully set, false otherwise
|
||||
bool setBoneTransform(EntityId entityId, int skinIndex, int boneIndex, math::mat4f transform);
|
||||
|
||||
/// @brief Immediately start animating the bone at [boneIndex] under the parent instance [entity] at skin [skinIndex].
|
||||
/// @param entity the mesh entity to animate
|
||||
/// @param frameData frame data as quaternions
|
||||
/// @param numFrames the number of frames
|
||||
/// @param boneName the name of the bone to animate
|
||||
/// @param frameLengthInMs the length of each frame in ms
|
||||
/// @return true if the bone animation was successfully enqueued
|
||||
bool addBoneAnimation(
|
||||
EntityId parent,
|
||||
int skinIndex,
|
||||
int boneIndex,
|
||||
const float *const frameData,
|
||||
int numFrames,
|
||||
float frameLengthInMs,
|
||||
float fadeOutInSecs,
|
||||
float fadeInInSecs,
|
||||
float maxDelta
|
||||
);
|
||||
|
||||
std::unique_ptr<std::vector<math::mat4f>> getBoneRestTranforms(EntityId entityId, int skinIndex);
|
||||
void resetBones(EntityId entityId);
|
||||
|
||||
bool setTransform(EntityId entityId, math::mat4f transform);
|
||||
bool setTransform(EntityId entityId, math::mat4 transform);
|
||||
|
||||
bool updateBoneMatrices(EntityId entityId);
|
||||
void playAnimation(EntityId e, int index, bool loop, bool reverse, bool replaceActive, float crossfade = 0.3f, float startOffset = 0.0f);
|
||||
void stopAnimation(EntityId e, int index);
|
||||
void setMorphTargetWeights(const char *const entityName, float *weights, int count);
|
||||
|
||||
Texture* createTexture(const uint8_t* data, size_t length, const char* name);
|
||||
bool applyTexture(EntityId entityId, Texture *texture, const char* slotName, int materialIndex);
|
||||
void destroyTexture(Texture* texture);
|
||||
|
||||
void setAnimationFrame(EntityId entity, int animationIndex, int animationFrame);
|
||||
bool hide(EntityId entity, const char *meshName);
|
||||
bool reveal(EntityId entity, const char *meshName);
|
||||
const char *getNameForEntity(EntityId entityId);
|
||||
utils::Entity findChildEntityByName(
|
||||
EntityId entityId,
|
||||
const char *entityName);
|
||||
int getEntityCount(EntityId entity, bool renderableOnly);
|
||||
void getEntities(EntityId entity, bool renderableOnly, EntityId *out);
|
||||
const char *getEntityNameAt(EntityId entity, int index, bool renderableOnly);
|
||||
void addCollisionComponent(EntityId entity, void (*onCollisionCallback)(const EntityId entityId1, const EntityId entityId2), bool affectsCollidingTransform);
|
||||
void removeCollisionComponent(EntityId entityId);
|
||||
EntityId getParent(EntityId child);
|
||||
EntityId getAncestor(EntityId child);
|
||||
void setParent(EntityId child, EntityId parent, bool preserveScaling);
|
||||
bool addAnimationComponent(EntityId entity);
|
||||
void removeAnimationComponent(EntityId entity);
|
||||
|
||||
/// @brief renders an outline around the specified entity.
|
||||
///
|
||||
///
|
||||
void setStencilHighlight(EntityId entity, float r, float g, float b);
|
||||
|
||||
/// @brief removes the outline around the specified entity.
|
||||
///
|
||||
///
|
||||
void removeStencilHighlight(EntityId entity);
|
||||
|
||||
/// @brief returns the number of instances of the FilamentAsset represented by the given entity.
|
||||
/// @param entityId
|
||||
/// @return the number of instances
|
||||
int getInstanceCount(EntityId entityId);
|
||||
|
||||
/// @brief returns an array containing all instances of the FilamentAsset represented by the given entity.
|
||||
/// @param entityId
|
||||
void getInstances(EntityId entityId, EntityId *out);
|
||||
|
||||
///
|
||||
/// Sets the draw priority for the given entity. See RenderableManager.h for more details.
|
||||
///
|
||||
void setPriority(EntityId entity, int priority);
|
||||
|
||||
/// @brief returns the 2D min/max viewport coordinates of the bounding box for the specified enitty;
|
||||
/// @param out a pointer large enough to store four floats (the min/max coordinates of the bounding box)
|
||||
/// @return
|
||||
///
|
||||
Aabb2 getScreenSpaceBoundingBox(View* view, EntityId entity);
|
||||
|
||||
/// @brief returns the 3D bounding box of the renderable instance for the given entity.
|
||||
/// @return the bounding box
|
||||
///
|
||||
Aabb3 getRenderableBoundingBox(EntityId entity);
|
||||
|
||||
///
|
||||
/// Creates an entity with the specified geometry/material/normals and adds to the scene.
|
||||
/// If [keepData] is true, stores
|
||||
///
|
||||
EntityId createGeometry(
|
||||
float *vertices,
|
||||
uint32_t numVertices,
|
||||
float *normals,
|
||||
uint32_t numNormals,
|
||||
float *uvs,
|
||||
uint32_t numUvs,
|
||||
uint16_t *indices,
|
||||
uint32_t numIndices,
|
||||
filament::RenderableManager::PrimitiveType primitiveType = RenderableManager::PrimitiveType::TRIANGLES,
|
||||
MaterialInstance* materialInstance = nullptr,
|
||||
bool keepData = false
|
||||
);
|
||||
|
||||
friend class FilamentViewer;
|
||||
|
||||
gltfio::MaterialProvider * const unlitMaterialProvider() {
|
||||
return _unlitMaterialProvider;
|
||||
}
|
||||
|
||||
bool isGeometryInstance(EntityId entity) {
|
||||
return std::find(_geometryInstances.begin(), _geometryInstances.end(), entity) != _geometryInstances.end();
|
||||
}
|
||||
|
||||
bool isGeometryEntity(EntityId entity) {
|
||||
return _geometry.find(entity) != _geometry.end();
|
||||
}
|
||||
|
||||
CustomGeometry* const getGeometry(EntityId entityId) {
|
||||
return _geometry[entityId].get();
|
||||
}
|
||||
|
||||
bool isGltfAsset(EntityId entity) {
|
||||
return getAssetByEntityId(entity) != nullptr;
|
||||
}
|
||||
|
||||
gltfio::FilamentInstance *getInstanceByEntityId(EntityId entityId);
|
||||
gltfio::FilamentAsset *getAssetByEntityId(EntityId entityId);
|
||||
|
||||
gltfio::FilamentInstance *createGltfAssetInstance(FilamentAsset* asset) {
|
||||
return _assetLoader->createInstance(asset);
|
||||
}
|
||||
|
||||
MaterialInstance* getMaterialInstanceAt(EntityId entityId, int materialIndex);
|
||||
|
||||
void setMaterialProperty(EntityId entity, int materialIndex, const char* property, float value);
|
||||
void setMaterialProperty(EntityId entity, int materialIndex, const char* property, int32_t value);
|
||||
void setMaterialProperty(EntityId entityId, int materialIndex, const char* property, filament::math::float4& value);
|
||||
|
||||
MaterialInstance* createUbershaderMaterialInstance(MaterialKey key);
|
||||
void destroy(MaterialInstance* materialInstance);
|
||||
|
||||
gltfio::MaterialProvider* getUbershaderProvider() {
|
||||
return _ubershaderProvider;
|
||||
}
|
||||
|
||||
MaterialInstance* createUnlitFixedSizeMaterialInstance();
|
||||
|
||||
MaterialInstance* createUnlitMaterialInstance();
|
||||
|
||||
void setVisibilityLayer(EntityId entityId, int layer);
|
||||
|
||||
Camera* createCamera();
|
||||
|
||||
void destroyCamera(Camera* camera);
|
||||
|
||||
size_t getCameraCount();
|
||||
|
||||
Camera* getCameraAt(size_t index);
|
||||
|
||||
Gizmo *createGizmo(View *view, Scene *scene);
|
||||
|
||||
bool isGizmoEntity(utils::Entity entity);
|
||||
|
||||
Scene* getScene() {
|
||||
return _scene;
|
||||
}
|
||||
|
||||
private:
|
||||
gltfio::AssetLoader *_assetLoader = nullptr;
|
||||
const ResourceLoaderWrapperImpl *const _resourceLoaderWrapper;
|
||||
Engine *_engine = nullptr;
|
||||
Scene *_scene = nullptr;
|
||||
Camera* _mainCamera;
|
||||
|
||||
gltfio::MaterialProvider *_ubershaderProvider = nullptr;
|
||||
gltfio::MaterialProvider *_unlitMaterialProvider = nullptr;
|
||||
gltfio::ResourceLoader *_gltfResourceLoader = nullptr;
|
||||
gltfio::TextureProvider *_stbDecoder = nullptr;
|
||||
gltfio::TextureProvider *_ktxDecoder = nullptr;
|
||||
std::mutex _mutex;
|
||||
std::mutex _stencilMutex;
|
||||
std::vector<MaterialInstance*> _materialInstances;
|
||||
|
||||
Material* _gizmoMaterial = nullptr;
|
||||
|
||||
utils::NameComponentManager *_ncm;
|
||||
|
||||
tsl::robin_map<
|
||||
EntityId,
|
||||
gltfio::FilamentInstance *>
|
||||
_instances;
|
||||
tsl::robin_map<EntityId, gltfio::FilamentAsset *> _assets;
|
||||
tsl::robin_map<EntityId, unique_ptr<CustomGeometry>> _geometry;
|
||||
std::vector<EntityId> _geometryInstances;
|
||||
tsl::robin_map<EntityId, unique_ptr<HighlightOverlay>> _highlighted;
|
||||
tsl::robin_map<EntityId, math::mat4> _transformUpdates;
|
||||
std::set<Texture*> _textures;
|
||||
std::vector<Camera*> _cameras;
|
||||
|
||||
AnimationComponentManager *_animationComponentManager = nullptr;
|
||||
CollisionComponentManager *_collisionComponentManager = nullptr;
|
||||
|
||||
utils::Entity findEntityByName(
|
||||
const gltfio::FilamentInstance *instance,
|
||||
const char *entityName);
|
||||
|
||||
GridOverlay* _gridOverlay = nullptr;
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "ThermionDartApi.h"
|
||||
#include "TGizmo.h"
|
||||
|
||||
typedef void (*GizmoPickCallback)(EntityId entityId, uint32_t x, uint32_t y, TView* view);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Gizmo_pick(TGizmo *tGizmo, uint32_t x, uint32_t y, GizmoPickCallback callback);
|
||||
EMSCRIPTEN_KEEPALIVE void Gizmo_setVisibility(TGizmo *tGizmo, bool visible);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,78 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#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
|
||||
|
||||
typedef struct TMaterialInstance TMaterialInstance;
|
||||
|
||||
// copied from SamplerCompareFunc in DriverEnums.h
|
||||
enum TDepthFunc {
|
||||
// don't change the enums values
|
||||
LE = 0, //!< Less or equal
|
||||
GE, //!< Greater or equal
|
||||
L, //!< Strictly less than
|
||||
G, //!< Strictly greater than
|
||||
E, //!< Equal
|
||||
NE, //!< Not equal
|
||||
A, //!< Always. Depth / stencil testing is deactivated.
|
||||
N //!< Never. The depth / stencil test always fails.
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthWrite(TMaterialInstance* materialInstance, bool enabled);
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthCulling(TMaterialInstance* materialInstance, bool enabled);
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat4(TMaterialInstance* materialInstance, const char* name, double x, double y, double w, double z);
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat2(TMaterialInstance* materialInstance, const char* name, double x, double y);
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat(TMaterialInstance* materialInstance, const char* name, double value);
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterInt(TMaterialInstance* materialInstance, const char* name, int value);
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthFunc(TMaterialInstance* materialInstance, TDepthFunc depthFunc);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "APIBoundaryTypes.h"
|
||||
#include "ResourceBuffer.hpp"
|
||||
#include "ThermionDartAPIUtils.h"
|
||||
#include "TCamera.h"
|
||||
#include "TMaterialInstance.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TGizmo* SceneManager_createGizmo(TSceneManager *tSceneManager, TView *tView, TScene *tScene);
|
||||
EMSCRIPTEN_KEEPALIVE EntityId SceneManager_createGeometry(
|
||||
TSceneManager *sceneManager,
|
||||
float *vertices,
|
||||
int numVertices,
|
||||
float *normals,
|
||||
int numNormals,
|
||||
float *uvs,
|
||||
int numUvs,
|
||||
uint16_t *indices,
|
||||
int numIndices,
|
||||
int primitiveType,
|
||||
TMaterialInstance *materialInstance,
|
||||
bool keepData);
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialInstance *SceneManager_createUnlitMaterialInstance(TSceneManager *sceneManager);
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialInstance *SceneManager_createUnlitFixedSizeMaterialInstance(TSceneManager *sceneManager);
|
||||
EMSCRIPTEN_KEEPALIVE bool SceneManager_setTransform(TSceneManager *sceneManager, EntityId entityId, const double *const transform);
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_queueTransformUpdates(TSceneManager *sceneManager, EntityId* entities, const double* const transforms, int numEntities);
|
||||
EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_findCameraByName(TSceneManager* tSceneManager, EntityId entity, const char* name);
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_setVisibilityLayer(TSceneManager *tSceneManager, EntityId entity, int layer);
|
||||
EMSCRIPTEN_KEEPALIVE TScene* SceneManager_getScene(TSceneManager *tSceneManager);
|
||||
EMSCRIPTEN_KEEPALIVE EntityId SceneManager_loadGlbFromBuffer(TSceneManager *sceneManager, const uint8_t *const, size_t length, bool keepData, int priority, int layer, bool loadResourcesAsync);
|
||||
EMSCRIPTEN_KEEPALIVE bool SceneManager_setMorphAnimation(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId entity,
|
||||
const float *const morphData,
|
||||
const uint32_t *const morphIndices,
|
||||
int numMorphTargets,
|
||||
int numFrames,
|
||||
float frameLengthInMs);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_createCamera(TSceneManager *sceneManager);
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_destroyCamera(TSceneManager *sceneManager, TCamera* camera);
|
||||
EMSCRIPTEN_KEEPALIVE size_t SceneManager_getCameraCount(TSceneManager *sceneManager);
|
||||
EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_getCameraAt(TSceneManager *sceneManager, size_t index);
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_destroyMaterialInstance(TSceneManager *sceneManager, TMaterialInstance *instance);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,216 +0,0 @@
|
||||
#ifndef _FLUTTER_FILAMENT_API_H
|
||||
#define _FLUTTER_FILAMENT_API_H
|
||||
|
||||
#include "APIExport.h"
|
||||
#include "APIBoundaryTypes.h"
|
||||
#include "ResourceBuffer.hpp"
|
||||
#include "ThermionDartAPIUtils.h"
|
||||
#include "TMaterialInstance.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TViewer *Viewer_create(const void *const context, const void *const loader, void *const platform, const char *uberArchivePath);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_destroy(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE TSceneManager *Viewer_getSceneManager(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE TRenderTarget* Viewer_createRenderTarget(TViewer *viewer, intptr_t texture, uint32_t width, uint32_t height);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_destroyRenderTarget(TViewer *viewer, TRenderTarget* tRenderTarget);
|
||||
EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createSwapChain(TViewer *viewer, const void *const window);
|
||||
EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createHeadlessSwapChain(TViewer *viewer, uint32_t width, uint32_t height);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_destroySwapChain(TViewer *viewer, TSwapChain* swapChain);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_render(
|
||||
TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_capture(
|
||||
TViewer *viewer,
|
||||
TView *view,
|
||||
TSwapChain *swapChain,
|
||||
uint8_t *pixelBuffer,
|
||||
void (*callback)(void));
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTarget(
|
||||
TViewer *viewer,
|
||||
TView *view,
|
||||
TSwapChain *swapChain,
|
||||
TRenderTarget *renderTarget,
|
||||
uint8_t *pixelBuffer,
|
||||
void (*callback)(void));
|
||||
EMSCRIPTEN_KEEPALIVE TView* Viewer_createView(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE TView* Viewer_getViewAt(TViewer *viewer, int index);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_setMainCamera(TViewer *tViewer, TView *tView);
|
||||
EMSCRIPTEN_KEEPALIVE TSwapChain* Viewer_getSwapChainAt(TViewer *tViewer, int index);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_setViewRenderable(TViewer *viewer, TSwapChain *swapChain, TView* view, bool renderable);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_pick(TViewer *viewer, TView* tView, int x, int y, void (*callback)(EntityId entityId, int x, int y, TView *tView, float depth, float fragX, float fragY, float fragZ));
|
||||
EMSCRIPTEN_KEEPALIVE bool Viewer_isNonPickableEntity(TViewer *viewer, EntityId entityId);
|
||||
|
||||
// Engine
|
||||
EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer* viewer);
|
||||
EMSCRIPTEN_KEEPALIVE TCamera *Engine_getCameraComponent(TEngine* tEngine, EntityId entityId);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_setTransform(TEngine* tEngine, EntityId entity, double4x4 transform);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void clear_background_image(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_image(TViewer *viewer, const char *path, bool fillHeight);
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_image_position(TViewer *viewer, float x, float y, bool clamp);
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_color(TViewer *viewer, const float r, const float g, const float b, const float a);
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void load_skybox(TViewer *viewer, const char *skyboxPath);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_loadIbl(TViewer *viewer, const char *iblPath, float intensity);
|
||||
EMSCRIPTEN_KEEPALIVE void create_ibl(TViewer *viewer, float r, float g, float b, float intensity);
|
||||
EMSCRIPTEN_KEEPALIVE void rotate_ibl(TViewer *viewer, float *rotationMatrix);
|
||||
EMSCRIPTEN_KEEPALIVE void remove_skybox(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE void remove_ibl(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE EntityId add_light(
|
||||
TViewer *viewer,
|
||||
uint8_t type,
|
||||
float colour,
|
||||
float intensity,
|
||||
float posX,
|
||||
float posY,
|
||||
float posZ,
|
||||
float dirX,
|
||||
float dirY,
|
||||
float dirZ,
|
||||
float falloffRadius,
|
||||
float spotLightConeInner,
|
||||
float spotLightConeOuter,
|
||||
float sunAngularRadius,
|
||||
float sunHaloSize,
|
||||
float sunHaloFallof,
|
||||
bool shadows);
|
||||
EMSCRIPTEN_KEEPALIVE void remove_light(TViewer *viewer, EntityId entityId);
|
||||
EMSCRIPTEN_KEEPALIVE void clear_lights(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE void set_light_position(TViewer *viewer, EntityId light, float x, float y, float z);
|
||||
EMSCRIPTEN_KEEPALIVE void set_light_direction(TViewer *viewer, EntityId light, float x, float y, float z);
|
||||
EMSCRIPTEN_KEEPALIVE EntityId load_glb(TSceneManager *sceneManager, const char *assetPath, int numInstances, bool keepData);
|
||||
EMSCRIPTEN_KEEPALIVE EntityId load_gltf(TSceneManager *sceneManager, const char *assetPath, const char *relativePath, bool keepData);
|
||||
EMSCRIPTEN_KEEPALIVE EntityId create_instance(TSceneManager *sceneManager, EntityId id);
|
||||
EMSCRIPTEN_KEEPALIVE int get_instance_count(TSceneManager *sceneManager, EntityId entityId);
|
||||
EMSCRIPTEN_KEEPALIVE void get_instances(TSceneManager *sceneManager, EntityId entityId, EntityId *out);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId get_main_camera(TViewer *viewer);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_frame_interval(TViewer *viewer, float interval);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void apply_weights(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId entity,
|
||||
const char *const entityName,
|
||||
float *const weights,
|
||||
int count);
|
||||
EMSCRIPTEN_KEEPALIVE bool set_morph_target_weights(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId entity,
|
||||
const float *const morphData,
|
||||
int numWeights);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialInstance *create_material_instance(TSceneManager *sceneManager, TMaterialKey materialConfig);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void clear_morph_animation(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId entity);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void reset_to_rest_pose(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId asset);
|
||||
EMSCRIPTEN_KEEPALIVE void add_bone_animation(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId entity,
|
||||
int skinIndex,
|
||||
int boneIndex,
|
||||
const float *const frameData,
|
||||
int numFrames,
|
||||
float frameLengthInMs,
|
||||
float fadeOutInSecs,
|
||||
float fadeInInSecs,
|
||||
float maxDelta);
|
||||
EMSCRIPTEN_KEEPALIVE void get_local_transform(TSceneManager *sceneManager,
|
||||
EntityId entityId, float *const);
|
||||
EMSCRIPTEN_KEEPALIVE void get_rest_local_transforms(TSceneManager *sceneManager,
|
||||
EntityId entityId, int skinIndex, float *const out, int numBones);
|
||||
EMSCRIPTEN_KEEPALIVE void get_world_transform(TSceneManager *sceneManager,
|
||||
EntityId entityId, float *const);
|
||||
EMSCRIPTEN_KEEPALIVE void get_inverse_bind_matrix(TSceneManager *sceneManager,
|
||||
EntityId entityId, int skinIndex, int boneIndex, float *const);
|
||||
EMSCRIPTEN_KEEPALIVE bool set_bone_transform(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId entity,
|
||||
int skinIndex,
|
||||
int boneIndex,
|
||||
const float *const transform);
|
||||
EMSCRIPTEN_KEEPALIVE void play_animation(TSceneManager *sceneManager, EntityId entity, int index, bool loop, bool reverse, bool replaceActive, float crossfade, float startOffset);
|
||||
EMSCRIPTEN_KEEPALIVE void set_animation_frame(TSceneManager *sceneManager, EntityId entity, int animationIndex, int animationFrame);
|
||||
EMSCRIPTEN_KEEPALIVE void stop_animation(TSceneManager *sceneManager, EntityId entity, int index);
|
||||
EMSCRIPTEN_KEEPALIVE int get_animation_count(TSceneManager *sceneManager, EntityId asset);
|
||||
EMSCRIPTEN_KEEPALIVE void get_animation_name(TSceneManager *sceneManager, EntityId entity, char *const outPtr, int index);
|
||||
EMSCRIPTEN_KEEPALIVE float get_animation_duration(TSceneManager *sceneManager, EntityId entity, int index);
|
||||
EMSCRIPTEN_KEEPALIVE int get_bone_count(TSceneManager *sceneManager, EntityId assetEntity, int skinIndex);
|
||||
EMSCRIPTEN_KEEPALIVE void get_bone_names(TSceneManager *sceneManager, EntityId assetEntity, const char **outPtr, int skinIndex);
|
||||
EMSCRIPTEN_KEEPALIVE EntityId get_bone(TSceneManager *sceneManager,
|
||||
EntityId entityId,
|
||||
int skinIndex,
|
||||
int boneIndex);
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool update_bone_matrices(TSceneManager *sceneManager, EntityId entityId);
|
||||
EMSCRIPTEN_KEEPALIVE void get_morph_target_name(TSceneManager *sceneManager, EntityId assetEntity, EntityId childEntity, char *const outPtr, int index);
|
||||
EMSCRIPTEN_KEEPALIVE int get_morph_target_name_count(TSceneManager *sceneManager, EntityId assetEntity, EntityId childEntity);
|
||||
EMSCRIPTEN_KEEPALIVE void remove_entity(TViewer *viewer, EntityId asset);
|
||||
EMSCRIPTEN_KEEPALIVE void clear_entities(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE bool set_material_color(TSceneManager *sceneManager, EntityId entity, const char *meshName, int materialIndex, const float r, const float g, const float b, const float a);
|
||||
EMSCRIPTEN_KEEPALIVE void transform_to_unit_cube(TSceneManager *sceneManager, EntityId asset);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void queue_relative_position_update_world_axis(TSceneManager *sceneManager, EntityId entity, float viewportX, float viewportY, float x, float y, float z);
|
||||
EMSCRIPTEN_KEEPALIVE void queue_position_update_from_viewport_coords(TSceneManager *sceneManager, TView *view, EntityId entity, float viewportX, float viewportY);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_position(TSceneManager *sceneManager, EntityId entity, float x, float y, float z);
|
||||
EMSCRIPTEN_KEEPALIVE void set_rotation(TSceneManager *sceneManager, EntityId entity, float rads, float x, float y, float z, float w);
|
||||
EMSCRIPTEN_KEEPALIVE void set_scale(TSceneManager *sceneManager, EntityId entity, float scale);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TCamera *Engine_getCameraComponent(TEngine *engine, EntityId entity);
|
||||
EMSCRIPTEN_KEEPALIVE TEntityManager *Engine_getEntityManager(TEngine *engine);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int hide_mesh(TSceneManager *sceneManager, EntityId entity, const char *meshName);
|
||||
EMSCRIPTEN_KEEPALIVE int reveal_mesh(TSceneManager *sceneManager, EntityId entity, const char *meshName);
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE const char *get_name_for_entity(TSceneManager *sceneManager, const EntityId entityId);
|
||||
EMSCRIPTEN_KEEPALIVE EntityId find_child_entity_by_name(TSceneManager *sceneManager, const EntityId parent, const char *name);
|
||||
EMSCRIPTEN_KEEPALIVE int get_entity_count(TSceneManager *sceneManager, const EntityId target, bool renderableOnly);
|
||||
EMSCRIPTEN_KEEPALIVE void get_entities(TSceneManager *sceneManager, const EntityId target, bool renderableOnly, EntityId *out);
|
||||
EMSCRIPTEN_KEEPALIVE const char *get_entity_name_at(TSceneManager *sceneManager, const EntityId target, int index, bool renderableOnly);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void ios_dummy();
|
||||
EMSCRIPTEN_KEEPALIVE void thermion_flutter_free(void *ptr);
|
||||
EMSCRIPTEN_KEEPALIVE void add_collision_component(TSceneManager *sceneManager, EntityId entityId, void (*callback)(const EntityId entityId1, const EntityId entityId2), bool affectsCollidingTransform);
|
||||
EMSCRIPTEN_KEEPALIVE void remove_collision_component(TSceneManager *sceneManager, EntityId entityId);
|
||||
EMSCRIPTEN_KEEPALIVE bool add_animation_component(TSceneManager *sceneManager, EntityId entityId);
|
||||
EMSCRIPTEN_KEEPALIVE void remove_animation_component(TSceneManager *sceneManager, EntityId entityId);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId get_parent(TSceneManager *sceneManager, EntityId child);
|
||||
EMSCRIPTEN_KEEPALIVE EntityId get_ancestor(TSceneManager *sceneManager, EntityId child);
|
||||
EMSCRIPTEN_KEEPALIVE void set_parent(TSceneManager *sceneManager, EntityId child, EntityId parent, bool preserveScaling);
|
||||
EMSCRIPTEN_KEEPALIVE void test_collisions(TSceneManager *sceneManager, EntityId entity);
|
||||
EMSCRIPTEN_KEEPALIVE void set_priority(TSceneManager *sceneManager, EntityId entityId, int priority);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE Aabb2 get_bounding_box(TSceneManager *sceneManager, TView *view, EntityId entity);
|
||||
EMSCRIPTEN_KEEPALIVE void get_bounding_box_to_out(TSceneManager *sceneManager, TView *view, EntityId entity, float *minX, float *minY, float *maxX, float *maxY);
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_stencil_highlight(TSceneManager *sceneManager, EntityId entity, float r, float g, float b);
|
||||
EMSCRIPTEN_KEEPALIVE void remove_stencil_highlight(TSceneManager *sceneManager, EntityId entity);
|
||||
EMSCRIPTEN_KEEPALIVE void set_material_property_float(TSceneManager *sceneManager, EntityId entity, int materialIndex, const char *property, float value);
|
||||
EMSCRIPTEN_KEEPALIVE void set_material_property_int(TSceneManager *sceneManager, EntityId entity, int materialIndex, const char *property, int value);
|
||||
EMSCRIPTEN_KEEPALIVE void set_material_property_float4(TSceneManager *sceneManager, EntityId entity, int materialIndex, const char *property, double4 value);
|
||||
EMSCRIPTEN_KEEPALIVE void set_material_depth_write(TSceneManager *sceneManager, EntityId entity, int materialIndex, bool enabled);
|
||||
EMSCRIPTEN_KEEPALIVE void unproject_texture(TViewer* viewer, EntityId entity,uint8_t* input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight);
|
||||
EMSCRIPTEN_KEEPALIVE void *const create_texture(TSceneManager *sceneManager, uint8_t *data, size_t length);
|
||||
EMSCRIPTEN_KEEPALIVE void destroy_texture(TSceneManager *sceneManager, void *const texture);
|
||||
EMSCRIPTEN_KEEPALIVE void apply_texture_to_material(TSceneManager *sceneManager, EntityId entity, void *const texture, const char *parameterName, int materialIndex);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialInstance* get_material_instance_at(TSceneManager *sceneManager, EntityId entity, int materialIndex);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,116 +0,0 @@
|
||||
#ifndef _DART_FILAMENT_FFI_API_H
|
||||
#define _DART_FILAMENT_FFI_API_H
|
||||
|
||||
#include "ThermionDartApi.h"
|
||||
#include "TView.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace thermion {
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
///
|
||||
/// This header replicates most of the methods in ThermionDartApi.h.
|
||||
/// It represents the interface for:
|
||||
/// - invoking those methods that must be called on the main Filament engine thread
|
||||
/// - setting up a render loop
|
||||
///
|
||||
typedef int32_t EntityId;
|
||||
typedef void (*FilamentRenderCallback)(void *const owner);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createOnRenderThread(
|
||||
void *const context,
|
||||
void *const platform,
|
||||
const char *uberArchivePath,
|
||||
const void *const loader,
|
||||
void (*renderCallback)(void *const renderCallbackOwner),
|
||||
void *const renderCallbackOwner,
|
||||
void (*callback)(TViewer *viewer));
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_destroyOnRenderThread(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createSwapChainRenderThread(TViewer *viewer, void *const surface, void (*onComplete)(TSwapChain*));
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createHeadlessSwapChainRenderThread(TViewer *viewer, uint32_t width, uint32_t height, void (*onComplete)(TSwapChain*));
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_destroySwapChainRenderThread(TViewer *viewer, TSwapChain* swapChain, void (*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_renderRenderThread(TViewer *viewer, TView* view, TSwapChain* swapChain);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderThread(TViewer *viewer, TView* view, TSwapChain* swapChain, uint8_t* out, void (*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTargetRenderThread(TViewer *viewer, TView* view, TSwapChain* swapChain, TRenderTarget* renderTarget, uint8_t* out, void (*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_requestFrameRenderThread(TViewer *viewer, void(*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_loadIblRenderThread(TViewer *viewer, const char *iblPath, float intensity, void(*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createRenderTargetRenderThread(TViewer *viewer, intptr_t texture, uint32_t width, uint32_t height, void(*onComplete)(TRenderTarget*));
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void View_setToneMappingRenderThread(TView *tView, TEngine *tEngine, thermion::ToneMapping toneMapping);
|
||||
EMSCRIPTEN_KEEPALIVE void View_setBloomRenderThread(TView *tView, double bloom);
|
||||
|
||||
FilamentRenderCallback make_render_callback_fn_pointer(FilamentRenderCallback);
|
||||
EMSCRIPTEN_KEEPALIVE void set_rendering_render_thread(TViewer *viewer, bool rendering, void(*onComplete)());
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_frame_interval_render_thread(TViewer *viewer, float frameInterval);
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_color_render_thread(TViewer *viewer, const float r, const float g, const float b, const float a);
|
||||
EMSCRIPTEN_KEEPALIVE void clear_background_image_render_thread(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_image_render_thread(TViewer *viewer, const char *path, bool fillHeight, void (*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_image_position_render_thread(TViewer *viewer, float x, float y, bool clamp);
|
||||
EMSCRIPTEN_KEEPALIVE void load_skybox_render_thread(TViewer *viewer, const char *skyboxPath, void (*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void remove_skybox_render_thread(TViewer *viewer);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_createGeometryRenderThread(
|
||||
TSceneManager *sceneManager,
|
||||
float *vertices,
|
||||
int numVertices,
|
||||
float *normals,
|
||||
int numNormals,
|
||||
float *uvs,
|
||||
int numUvs,
|
||||
uint16_t *indices,
|
||||
int numIndices,
|
||||
int primitiveType,
|
||||
TMaterialInstance *materialInstance,
|
||||
bool keepData,
|
||||
void (*callback)(EntityId));
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_loadGlbFromBufferRenderThread(TSceneManager *sceneManager, const uint8_t *const data, size_t length, int numInstances, bool keepData, int priority, int layer, bool loadResourcesAsync, void (*callback)(EntityId));
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_createUnlitMaterialInstanceRenderThread(TSceneManager *sceneManager, void (*callback)(TMaterialInstance*));
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_createUnlitFixedSizeMaterialInstanceRenderThread(TSceneManager *sceneManager, void (*callback)(TMaterialInstance*));
|
||||
EMSCRIPTEN_KEEPALIVE void load_glb_render_thread(TSceneManager *sceneManager, const char *assetPath, int numInstances, bool keepData, void (*callback)(EntityId));
|
||||
EMSCRIPTEN_KEEPALIVE void load_gltf_render_thread(TSceneManager *sceneManager, const char *assetPath, const char *relativePath, bool keepData, void (*callback)(EntityId));
|
||||
EMSCRIPTEN_KEEPALIVE void create_instance_render_thread(TSceneManager *sceneManager, EntityId entityId, void (*callback)(EntityId));
|
||||
EMSCRIPTEN_KEEPALIVE void remove_entity_render_thread(TViewer *viewer, EntityId asset, void (*callback)());
|
||||
EMSCRIPTEN_KEEPALIVE void clear_entities_render_thread(TViewer *viewer, void (*callback)());
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void apply_weights_render_thread(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
const char *const entityName,
|
||||
float *const weights,
|
||||
int count);
|
||||
EMSCRIPTEN_KEEPALIVE void set_animation_frame_render_thread(TSceneManager *sceneManager, EntityId asset, int animationIndex, int animationFrame);
|
||||
EMSCRIPTEN_KEEPALIVE void stop_animation_render_thread(TSceneManager *sceneManager, EntityId asset, int index);
|
||||
EMSCRIPTEN_KEEPALIVE void get_animation_count_render_thread(TSceneManager *sceneManager, EntityId asset, void (*callback)(int));
|
||||
EMSCRIPTEN_KEEPALIVE void get_animation_name_render_thread(TSceneManager *sceneManager, EntityId asset, char *const outPtr, int index, void (*callback)());
|
||||
EMSCRIPTEN_KEEPALIVE void get_morph_target_name_render_thread(TSceneManager *sceneManager, EntityId assetEntity, EntityId childEntity, char *const outPtr, int index, void (*callback)());
|
||||
EMSCRIPTEN_KEEPALIVE void get_morph_target_name_count_render_thread(TSceneManager *sceneManager, EntityId asset, EntityId childEntity, void (*callback)(int32_t));
|
||||
EMSCRIPTEN_KEEPALIVE void set_morph_target_weights_render_thread(TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
const float *const morphData,
|
||||
int numWeights,
|
||||
void (*callback)(bool));
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void update_bone_matrices_render_thread(TSceneManager *sceneManager,
|
||||
EntityId asset, void(*callback)(bool));
|
||||
EMSCRIPTEN_KEEPALIVE void set_bone_transform_render_thread(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
int skinIndex,
|
||||
int boneIndex,
|
||||
const float *const transform,
|
||||
void (*callback)(bool));
|
||||
EMSCRIPTEN_KEEPALIVE void set_post_processing_render_thread(TViewer *viewer, bool enabled);
|
||||
EMSCRIPTEN_KEEPALIVE void reset_to_rest_pose_render_thread(TSceneManager *sceneManager, EntityId entityId, void(*callback)());
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void unproject_texture_render_thread(TViewer* viewer, EntityId entity, uint8_t* input, uint32_t inputWidth, uint32_t inputHeight, uint8_t* out, uint32_t outWidth, uint32_t outHeight, void(*callback)());
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _DART_FILAMENT_FFI_API_H
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "CustomGeometry.hpp"
|
||||
#include "scene/CustomGeometry.hpp"
|
||||
|
||||
namespace thermion {
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ extern "C"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "TMaterialInstance.h"
|
||||
|
||||
typedef int32_t EntityId;
|
||||
typedef struct TCamera TCamera;
|
||||
@@ -19,6 +18,15 @@ extern "C"
|
||||
typedef struct TView TView;
|
||||
typedef struct TGizmo TGizmo;
|
||||
typedef struct TScene TScene;
|
||||
typedef struct TTransformManager TTransformManager;
|
||||
typedef struct TAnimationManager TAnimationManager;
|
||||
typedef struct TCollisionComponentManager TCollisionComponentManager;
|
||||
typedef struct TSceneAsset TSceneAsset;
|
||||
typedef struct TNameComponentManager TNameComponentManager;
|
||||
typedef struct TMaterialInstance TMaterialInstance;
|
||||
typedef struct TMaterialProvider TMaterialProvider;
|
||||
typedef struct TRenderableManager TRenderableManager;
|
||||
typedef struct TRenderableInstance TRenderableInstance;
|
||||
|
||||
struct TMaterialKey {
|
||||
bool doubleSided;
|
||||
136
thermion_dart/native/include/c_api/TAnimationManager.h
Normal file
136
thermion_dart/native/include/c_api/TAnimationManager.h
Normal file
@@ -0,0 +1,136 @@
|
||||
#pragma once
|
||||
|
||||
#include "APIExport.h"
|
||||
#include "APIBoundaryTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_addAnimationComponent(TAnimationManager *tAnimationManager, EntityId entityId);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_removeAnimationComponent(TAnimationManager *tAnimationManager, EntityId entityId);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool AnimationManager_setMorphAnimation(
|
||||
TAnimationManager *tAnimationManager,
|
||||
EntityId entityId,
|
||||
const float *const morphData,
|
||||
const uint32_t *const morphIndices,
|
||||
int numMorphTargets,
|
||||
int numFrames,
|
||||
float frameLengthInMs);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool AnimationManager_clearMorphAnimation(TAnimationManager *tAnimationManager, EntityId entityId);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_resetToRestPose(TAnimationManager *tAnimationManager, TSceneAsset *sceneAsset);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_addBoneAnimation(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *tSceneAsset,
|
||||
int skinIndex,
|
||||
int boneIndex,
|
||||
const float *const frameData,
|
||||
int numFrames,
|
||||
float frameLengthInMs,
|
||||
float fadeOutInSecs,
|
||||
float fadeInInSecs,
|
||||
float maxDelta);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId AnimationManager_getBone(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
int skinIndex,
|
||||
int boneIndex);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_getRestLocalTransforms(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
int skinIndex,
|
||||
float *const out,
|
||||
int numBones);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_getInverseBindMatrix(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
int skinIndex,
|
||||
int boneIndex,
|
||||
float *const out);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_playAnimation(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
int index,
|
||||
bool loop,
|
||||
bool reverse,
|
||||
bool replaceActive,
|
||||
float crossfade,
|
||||
float startOffset);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_stopAnimation(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
int index);
|
||||
|
||||
// Additional methods found in implementation
|
||||
EMSCRIPTEN_KEEPALIVE float AnimationManager_getAnimationDuration(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
int animationIndex);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int AnimationManager_getAnimationCount(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_getAnimationName(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
char *const outPtr,
|
||||
int index);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int AnimationManager_getBoneCount(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
int skinIndex);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_getBoneNames(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
const char **out,
|
||||
int skinIndex);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int AnimationManager_getMorphTargetNameCount(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
EntityId childEntity);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_getMorphTargetName(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
EntityId childEntity,
|
||||
char *const outPtr,
|
||||
int index);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool AnimationManager_updateBoneMatrices(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset);
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool AnimationManager_setMorphTargetWeights(
|
||||
TAnimationManager *tAnimationManager,
|
||||
EntityId entityId,
|
||||
const float *const morphData,
|
||||
int numWeights);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_setGltfAnimationFrame(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *tSceneAsset,
|
||||
int animationIndex,
|
||||
int frame
|
||||
);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
25
thermion_dart/native/include/c_api/TGizmo.h
Normal file
25
thermion_dart/native/include/c_api/TGizmo.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "APIBoundaryTypes.h"
|
||||
#include "APIExport.h"
|
||||
#include "TView.h"
|
||||
|
||||
enum TGizmoAxis { X, Y, Z };
|
||||
enum TGizmoPickResultType { AxisX, AxisY, AxisZ, Parent, None };
|
||||
|
||||
typedef void (*GizmoPickCallback)(TGizmoPickResultType resultType, float x, float y, float z);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Gizmo_pick(TGizmo *tGizmo, uint32_t x, uint32_t y, GizmoPickCallback callback);
|
||||
EMSCRIPTEN_KEEPALIVE void Gizmo_highlight(TGizmo *tGizmo, TGizmoAxis axis);
|
||||
EMSCRIPTEN_KEEPALIVE void Gizmo_unhighlight(TGizmo *tGizmo);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
103
thermion_dart/native/include/c_api/TMaterialInstance.h
Normal file
103
thermion_dart/native/include/c_api/TMaterialInstance.h
Normal file
@@ -0,0 +1,103 @@
|
||||
#pragma once
|
||||
|
||||
#include "APIBoundaryTypes.h"
|
||||
#include "APIExport.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
// copied from SamplerCompareFunc in DriverEnums.h
|
||||
enum TSamplerCompareFunc
|
||||
{
|
||||
// don't change the enums values
|
||||
LE = 0, //!< Less or equal
|
||||
GE, //!< Greater or equal
|
||||
L, //!< Strictly less than
|
||||
G, //!< Strictly greater than
|
||||
E, //!< Equal
|
||||
NE, //!< Not equal
|
||||
A, //!< Always. Depth / stencil testing is deactivated.
|
||||
N //!< Never. The depth / stencil test always fails.
|
||||
};
|
||||
|
||||
// StencilOperation equivalent
|
||||
enum TStencilOperation
|
||||
{
|
||||
KEEP = 0, // Keep the current value
|
||||
ZERO, // Set the value to zero
|
||||
REPLACE, // Set the value to reference value
|
||||
INCR, // Increment the current value with saturation
|
||||
INCR_WRAP, // Increment the current value without saturation
|
||||
DECR, // Decrement the current value with saturation
|
||||
DECR_WRAP, // Decrement the current value without saturation
|
||||
INVERT // Invert the current value
|
||||
};
|
||||
|
||||
// StencilFace equivalent
|
||||
enum TStencilFace
|
||||
{
|
||||
STENCIL_FACE_FRONT = 1,
|
||||
STENCIL_FACE_BACK = 2,
|
||||
STENCIL_FACE_FRONT_AND_BACK = 3
|
||||
};
|
||||
|
||||
// Add these enum definitions at the top with the other enums
|
||||
enum TCullingMode
|
||||
{
|
||||
CULLING_MODE_NONE = 0,
|
||||
CULLING_MODE_FRONT,
|
||||
CULLING_MODE_BACK,
|
||||
CULLING_MODE_FRONT_AND_BACK
|
||||
};
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool MaterialInstance_isStencilWriteEnabled(TMaterialInstance *materialInstance);
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setStencilWrite(TMaterialInstance *materialInstance, bool enabled);
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setCullingMode(TMaterialInstance *materialInstance, TCullingMode culling);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthWrite(TMaterialInstance *materialInstance, bool enabled);
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthCulling(TMaterialInstance *materialInstance, bool enabled);
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat4(TMaterialInstance *materialInstance, const char *name, double x, double y, double w, double z);
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat2(TMaterialInstance *materialInstance, const char *name, double x, double y);
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat(TMaterialInstance *materialInstance, const char *name, double value);
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterInt(TMaterialInstance *materialInstance, const char *name, int value);
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthFunc(TMaterialInstance *materialInstance, TSamplerCompareFunc depthFunc);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setStencilOpStencilFail(
|
||||
TMaterialInstance *materialInstance,
|
||||
TStencilOperation op,
|
||||
TStencilFace face);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setStencilOpDepthFail(
|
||||
TMaterialInstance *materialInstance,
|
||||
TStencilOperation op,
|
||||
TStencilFace face);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setStencilOpDepthStencilPass(
|
||||
TMaterialInstance *materialInstance,
|
||||
TStencilOperation op,
|
||||
TStencilFace face);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setStencilCompareFunction(
|
||||
TMaterialInstance *materialInstance,
|
||||
TSamplerCompareFunc func,
|
||||
TStencilFace face);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setStencilReferenceValue(
|
||||
TMaterialInstance *materialInstance,
|
||||
uint8_t value,
|
||||
TStencilFace face);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setStencilReadMask(
|
||||
TMaterialInstance *materialInstance,
|
||||
uint8_t mask);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setStencilWriteMask(
|
||||
TMaterialInstance *materialInstance,
|
||||
uint8_t mask);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
14
thermion_dart/native/include/c_api/TMaterialProvider.h
Normal file
14
thermion_dart/native/include/c_api/TMaterialProvider.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "APIBoundaryTypes.h"
|
||||
#include "APIExport.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialInstance *MaterialProvider_createMaterialInstance(TMaterialProvider *provider, TMaterialKey *key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
16
thermion_dart/native/include/c_api/TNameComponentManager.h
Normal file
16
thermion_dart/native/include/c_api/TNameComponentManager.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "APIBoundaryTypes.h"
|
||||
#include "APIExport.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE const char *NameComponentManager_getName(TNameComponentManager *tNameComponentManager, EntityId entity);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
17
thermion_dart/native/include/c_api/TRenderableManager.h
Normal file
17
thermion_dart/native/include/c_api/TRenderableManager.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "APIExport.h"
|
||||
#include "APIBoundaryTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void RenderableManager_setMaterialInstanceAt(TRenderableManager *tRenderableManager, EntityId entityId, int primitiveIndex, TMaterialInstance *tMaterialInstance);
|
||||
EMSCRIPTEN_KEEPALIVE void RenderableManager_setPriority(TRenderableManager *tRenderableManager, EntityId entityId, int priority);
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialInstance *RenderableManager_getMaterialInstanceAt(TRenderableManager *tRenderableManager, EntityId entityId, int primitiveIndex);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
27
thermion_dart/native/include/c_api/TSceneAsset.h
Normal file
27
thermion_dart/native/include/c_api/TSceneAsset.h
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <utils/Entity.h>
|
||||
#include "APIExport.h"
|
||||
#include "APIBoundaryTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
EMSCRIPTEN_KEEPALIVE void SceneAsset_addToScene(TSceneAsset *tSceneAsset, TScene *tScene);
|
||||
EMSCRIPTEN_KEEPALIVE EntityId SceneAsset_getEntity(TSceneAsset *tSceneAsset);
|
||||
EMSCRIPTEN_KEEPALIVE int SceneAsset_getChildEntityCount(TSceneAsset* tSceneAsset);
|
||||
EMSCRIPTEN_KEEPALIVE void SceneAsset_getChildEntities(TSceneAsset* tSceneAsset, EntityId *out);
|
||||
EMSCRIPTEN_KEEPALIVE const utils::Entity *SceneAsset_getCameraEntities(TSceneAsset* tSceneAsset);
|
||||
EMSCRIPTEN_KEEPALIVE size_t SceneAsset_getCameraEntityCount(TSceneAsset *tSceneAsset);
|
||||
EMSCRIPTEN_KEEPALIVE const utils::Entity *SceneAsset_getLightEntities(TSceneAsset* tSceneAsset);
|
||||
EMSCRIPTEN_KEEPALIVE size_t SceneAsset_getLightEntityCount(TSceneAsset *tSceneAsset);
|
||||
EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneAsset_getInstance(TSceneAsset *tSceneAsset, int index);
|
||||
EMSCRIPTEN_KEEPALIVE size_t SceneAsset_getInstanceCount(TSceneAsset *tSceneAsset);
|
||||
EMSCRIPTEN_KEEPALIVE TSceneAsset * SceneAsset_createInstance(TSceneAsset *asset, TMaterialInstance **materialInstances, int materialInstanceCount);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
66
thermion_dart/native/include/c_api/TSceneManager.h
Normal file
66
thermion_dart/native/include/c_api/TSceneManager.h
Normal file
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include "APIBoundaryTypes.h"
|
||||
#include "ResourceBuffer.hpp"
|
||||
#include "MathUtils.hpp"
|
||||
#include "TCamera.h"
|
||||
#include "TMaterialInstance.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TGizmo *SceneManager_createGizmo(TSceneManager *tSceneManager, TView *tView, TScene *tScene);
|
||||
EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneManager_createGeometry(
|
||||
TSceneManager *sceneManager,
|
||||
float *vertices,
|
||||
int numVertices,
|
||||
float *normals,
|
||||
int numNormals,
|
||||
float *uvs,
|
||||
int numUvs,
|
||||
uint16_t *indices,
|
||||
int numIndices,
|
||||
int primitiveType,
|
||||
TMaterialInstance **materialInstances,
|
||||
int materialInstanceCount,
|
||||
bool keepData);
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialProvider *SceneManager_getUbershaderMaterialProvider(TSceneManager *sceneManager);
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialProvider *SceneManager_getUnlitMaterialProvider(TSceneManager *sceneManager);
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialInstance *SceneManager_createUnlitMaterialInstance(TSceneManager *sceneManager);
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialInstance *SceneManager_createUnlitFixedSizeMaterialInstance(TSceneManager *sceneManager);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_queueTransformUpdates(TSceneManager *sceneManager, EntityId *entities, const double *const transforms, int numEntities);
|
||||
EMSCRIPTEN_KEEPALIVE TCamera *SceneManager_findCameraByName(TSceneManager *tSceneManager, EntityId entity, const char *name);
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_setVisibilityLayer(TSceneManager *tSceneManager, EntityId entity, int layer);
|
||||
EMSCRIPTEN_KEEPALIVE TScene *SceneManager_getScene(TSceneManager *tSceneManager);
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TCamera *SceneManager_createCamera(TSceneManager *sceneManager);
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_destroyCamera(TSceneManager *sceneManager, TCamera *camera);
|
||||
EMSCRIPTEN_KEEPALIVE size_t SceneManager_getCameraCount(TSceneManager *sceneManager);
|
||||
EMSCRIPTEN_KEEPALIVE TCamera *SceneManager_getCameraAt(TSceneManager *sceneManager, size_t index);
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_destroyMaterialInstance(TSceneManager *sceneManager, TMaterialInstance *instance);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE Aabb3 SceneManager_getRenderableBoundingBox(TSceneManager *tSceneManager, EntityId entity);
|
||||
EMSCRIPTEN_KEEPALIVE int SceneManager_addToScene(TSceneManager *tSceneManager, EntityId entity);
|
||||
EMSCRIPTEN_KEEPALIVE int SceneManager_removeFromScene(TSceneManager *tSceneManager, EntityId entity);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_transformToUnitCube(TSceneManager *sceneManager, EntityId asset);
|
||||
EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneManager_loadGlbFromBuffer(TSceneManager *tSceneManager, const uint8_t *const, size_t length, bool keepData, int priority, int layer, bool loadResourcesAsync);
|
||||
EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneManager_loadGlb(TSceneManager *sceneManager, const char *assetPath, int numInstances, bool keepData);
|
||||
EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneManager_loadGltf(TSceneManager *sceneManager, const char *assetPath, const char *relativePath, bool keepData);
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TAnimationManager *SceneManager_getAnimationManager(TSceneManager *tSceneManager);
|
||||
EMSCRIPTEN_KEEPALIVE void *SceneManager_destroyAll(TSceneManager *tSceneManager);
|
||||
EMSCRIPTEN_KEEPALIVE void *SceneManager_destroyAsset(TSceneManager *tSceneManager, TSceneAsset *sceneAsset);
|
||||
EMSCRIPTEN_KEEPALIVE TNameComponentManager *SceneManager_getNameComponentManager(TSceneManager *tSceneManager);
|
||||
EMSCRIPTEN_KEEPALIVE size_t SceneManager_getOverlayEntityCount(TSceneManager *tSceneManager);
|
||||
EMSCRIPTEN_KEEPALIVE EntityId SceneManager_getOverlayEntityAt(TSceneManager *tSceneManager, size_t index);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
23
thermion_dart/native/include/c_api/TTransformManager.h
Normal file
23
thermion_dart/native/include/c_api/TTransformManager.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "APIExport.h"
|
||||
#include "APIBoundaryTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 TransformManager_getLocalTransform(TTransformManager *tTransformManager, EntityId entityId);
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 TransformManager_getWorldTransform(TTransformManager *tTransformManager, EntityId entityId);
|
||||
EMSCRIPTEN_KEEPALIVE void TransformManager_setTransform(TTransformManager *tTransformManager, EntityId entityId, double4x4 transform);
|
||||
EMSCRIPTEN_KEEPALIVE void TransformManager_transformToUnitCube(TTransformManager *tTransformManager, EntityId entityId);
|
||||
EMSCRIPTEN_KEEPALIVE void TransformManager_setParent(TTransformManager *tTransformManager, EntityId child, EntityId parent, bool preserveScaling);
|
||||
EMSCRIPTEN_KEEPALIVE EntityId TransformManager_getParent(TTransformManager *tTransformManager, EntityId child);
|
||||
EMSCRIPTEN_KEEPALIVE EntityId TransformManager_getAncestor(TTransformManager *tTransformManager, EntityId childEntityId);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -6,7 +6,8 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "ThermionDartApi.h"
|
||||
#include "APIBoundaryTypes.h"
|
||||
#include "APIExport.h"
|
||||
|
||||
struct TViewport {
|
||||
int32_t left;
|
||||
@@ -42,6 +43,11 @@ EMSCRIPTEN_KEEPALIVE void View_setLayerEnabled(TView *tView, int layer, bool vis
|
||||
EMSCRIPTEN_KEEPALIVE void View_setCamera(TView *tView, TCamera *tCamera);
|
||||
EMSCRIPTEN_KEEPALIVE TScene* View_getScene(TView *tView);
|
||||
EMSCRIPTEN_KEEPALIVE TCamera* View_getCamera(TView *tView);
|
||||
EMSCRIPTEN_KEEPALIVE void View_setStencilBufferEnabled(TView *tView, bool enabled);
|
||||
EMSCRIPTEN_KEEPALIVE bool View_isStencilBufferEnabled(TView *tView);
|
||||
|
||||
typedef void (*PickCallback)(uint32_t requestId, EntityId entityId, float depth, float fragX, float fragY, float fragZ);
|
||||
EMSCRIPTEN_KEEPALIVE void View_pick(TView* tView, uint32_t requestId, uint32_t x, uint32_t y, PickCallback callback);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
115
thermion_dart/native/include/c_api/ThermionDartApi.h
Normal file
115
thermion_dart/native/include/c_api/ThermionDartApi.h
Normal file
@@ -0,0 +1,115 @@
|
||||
#ifndef _FLUTTER_FILAMENT_API_H
|
||||
#define _FLUTTER_FILAMENT_API_H
|
||||
|
||||
#include "APIExport.h"
|
||||
#include "APIBoundaryTypes.h"
|
||||
#include "TMaterialInstance.h"
|
||||
|
||||
#include "ResourceBuffer.hpp"
|
||||
#include "MathUtils.hpp"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TViewer *Viewer_create(const void *const context, const void *const loader, void *const platform, const char *uberArchivePath);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_destroy(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE TSceneManager *Viewer_getSceneManager(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE TRenderTarget* Viewer_createRenderTarget(TViewer *viewer, intptr_t texture, uint32_t width, uint32_t height);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_destroyRenderTarget(TViewer *viewer, TRenderTarget* tRenderTarget);
|
||||
EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createSwapChain(TViewer *viewer, const void *const window);
|
||||
EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createHeadlessSwapChain(TViewer *viewer, uint32_t width, uint32_t height);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_destroySwapChain(TViewer *viewer, TSwapChain* swapChain);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_render(
|
||||
TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_capture(
|
||||
TViewer *viewer,
|
||||
TView *view,
|
||||
TSwapChain *swapChain,
|
||||
uint8_t *pixelBuffer,
|
||||
void (*callback)(void));
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTarget(
|
||||
TViewer *viewer,
|
||||
TView *view,
|
||||
TSwapChain *swapChain,
|
||||
TRenderTarget *renderTarget,
|
||||
uint8_t *pixelBuffer,
|
||||
void (*callback)(void));
|
||||
EMSCRIPTEN_KEEPALIVE TView* Viewer_createView(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE TView* Viewer_getViewAt(TViewer *viewer, int index);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_setMainCamera(TViewer *tViewer, TView *tView);
|
||||
EMSCRIPTEN_KEEPALIVE TSwapChain* Viewer_getSwapChainAt(TViewer *tViewer, int index);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_setViewRenderable(TViewer *viewer, TSwapChain *swapChain, TView* view, bool renderable);
|
||||
|
||||
|
||||
// Engine
|
||||
EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer* viewer);
|
||||
EMSCRIPTEN_KEEPALIVE TCamera *Engine_getCameraComponent(TEngine* tEngine, EntityId entityId);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void clear_background_image(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_image(TViewer *viewer, const char *path, bool fillHeight);
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_image_position(TViewer *viewer, float x, float y, bool clamp);
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_color(TViewer *viewer, const float r, const float g, const float b, const float a);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void load_skybox(TViewer *viewer, const char *skyboxPath);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_loadIbl(TViewer *viewer, const char *iblPath, float intensity);
|
||||
EMSCRIPTEN_KEEPALIVE void create_ibl(TViewer *viewer, float r, float g, float b, float intensity);
|
||||
EMSCRIPTEN_KEEPALIVE void rotate_ibl(TViewer *viewer, float *rotationMatrix);
|
||||
EMSCRIPTEN_KEEPALIVE void remove_skybox(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE void remove_ibl(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE EntityId add_light(
|
||||
TViewer *viewer,
|
||||
uint8_t type,
|
||||
float colour,
|
||||
float intensity,
|
||||
float posX,
|
||||
float posY,
|
||||
float posZ,
|
||||
float dirX,
|
||||
float dirY,
|
||||
float dirZ,
|
||||
float falloffRadius,
|
||||
float spotLightConeInner,
|
||||
float spotLightConeOuter,
|
||||
float sunAngularRadius,
|
||||
float sunHaloSize,
|
||||
float sunHaloFallof,
|
||||
bool shadows);
|
||||
EMSCRIPTEN_KEEPALIVE void remove_light(TViewer *viewer, EntityId entityId);
|
||||
EMSCRIPTEN_KEEPALIVE void clear_lights(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE void set_light_position(TViewer *viewer, EntityId light, float x, float y, float z);
|
||||
EMSCRIPTEN_KEEPALIVE void set_light_direction(TViewer *viewer, EntityId light, float x, float y, float z);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId get_main_camera(TViewer *viewer);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_frame_interval(TViewer *viewer, float interval);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void queue_relative_position_update_world_axis(TSceneManager *sceneManager, EntityId entity, float viewportX, float viewportY, float x, float y, float z);
|
||||
EMSCRIPTEN_KEEPALIVE void queue_position_update_from_viewport_coords(TSceneManager *sceneManager, TView *view, EntityId entity, float viewportX, float viewportY);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TTransformManager *Engine_getTransformManager(TEngine *engine);
|
||||
EMSCRIPTEN_KEEPALIVE TRenderableManager *Engine_getRenderableManager(TEngine *engine);
|
||||
EMSCRIPTEN_KEEPALIVE TCamera *Engine_getCameraComponent(TEngine *engine, EntityId entity);
|
||||
EMSCRIPTEN_KEEPALIVE TEntityManager *Engine_getEntityManager(TEngine *engine);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void ios_dummy();
|
||||
EMSCRIPTEN_KEEPALIVE void thermion_flutter_free(void *ptr);
|
||||
EMSCRIPTEN_KEEPALIVE void add_collision_component(TSceneManager *sceneManager, EntityId entityId, void (*callback)(const EntityId entityId1, const EntityId entityId2), bool affectsCollidingTransform);
|
||||
EMSCRIPTEN_KEEPALIVE void remove_collision_component(TSceneManager *sceneManager, EntityId entityId);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void test_collisions(TSceneManager *sceneManager, EntityId entity);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE Aabb2 get_bounding_box(TSceneManager *sceneManager, TView *view, EntityId entity);
|
||||
EMSCRIPTEN_KEEPALIVE void get_bounding_box_to_out(TSceneManager *sceneManager, TView *view, EntityId entity, float *minX, float *minY, float *maxX, float *maxY);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void unproject_texture(TViewer* viewer, EntityId entity,uint8_t* input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight);
|
||||
EMSCRIPTEN_KEEPALIVE void *const create_texture(TSceneManager *sceneManager, uint8_t *data, size_t length);
|
||||
EMSCRIPTEN_KEEPALIVE void destroy_texture(TSceneManager *sceneManager, void *const texture);
|
||||
EMSCRIPTEN_KEEPALIVE void apply_texture_to_material(TSceneManager *sceneManager, EntityId entity, void *const texture, const char *parameterName, int materialIndex);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
115
thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h
Normal file
115
thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h
Normal file
@@ -0,0 +1,115 @@
|
||||
#ifndef _DART_FILAMENT_FFI_API_H
|
||||
#define _DART_FILAMENT_FFI_API_H
|
||||
|
||||
#include "ThermionDartApi.h"
|
||||
#include "TView.h"
|
||||
#include "TMaterialProvider.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace thermion
|
||||
{
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
///
|
||||
/// This header replicates most of the methods in ThermionDartApi.h.
|
||||
/// It represents the interface for:
|
||||
/// - invoking those methods that must be called on the main Filament engine thread
|
||||
/// - setting up a render loop
|
||||
///
|
||||
typedef int32_t EntityId;
|
||||
typedef void (*FilamentRenderCallback)(void *const owner);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createOnRenderThread(
|
||||
void *const context,
|
||||
void *const platform,
|
||||
const char *uberArchivePath,
|
||||
const void *const loader,
|
||||
void (*renderCallback)(void *const renderCallbackOwner),
|
||||
void *const renderCallbackOwner,
|
||||
void (*callback)(TViewer *viewer));
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_destroyOnRenderThread(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createSwapChainRenderThread(TViewer *viewer, void *const surface, void (*onComplete)(TSwapChain *));
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createHeadlessSwapChainRenderThread(TViewer *viewer, uint32_t width, uint32_t height, void (*onComplete)(TSwapChain *));
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_destroySwapChainRenderThread(TViewer *viewer, TSwapChain *swapChain, void (*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_renderRenderThread(TViewer *viewer, TView *view, TSwapChain *swapChain);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderThread(TViewer *viewer, TView *view, TSwapChain *swapChain, uint8_t *out, void (*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTargetRenderThread(TViewer *viewer, TView *view, TSwapChain *swapChain, TRenderTarget *renderTarget, uint8_t *out, void (*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_requestFrameRenderThread(TViewer *viewer, void (*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_loadIblRenderThread(TViewer *viewer, const char *iblPath, float intensity, void (*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createRenderTargetRenderThread(TViewer *viewer, intptr_t texture, uint32_t width, uint32_t height, void (*onComplete)(TRenderTarget *));
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void View_setToneMappingRenderThread(TView *tView, TEngine *tEngine, thermion::ToneMapping toneMapping);
|
||||
EMSCRIPTEN_KEEPALIVE void View_setBloomRenderThread(TView *tView, double bloom);
|
||||
|
||||
FilamentRenderCallback make_render_callback_fn_pointer(FilamentRenderCallback);
|
||||
EMSCRIPTEN_KEEPALIVE void set_rendering_render_thread(TViewer *viewer, bool rendering, void (*onComplete)());
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_frame_interval_render_thread(TViewer *viewer, float frameInterval);
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_color_render_thread(TViewer *viewer, const float r, const float g, const float b, const float a);
|
||||
EMSCRIPTEN_KEEPALIVE void clear_background_image_render_thread(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_image_render_thread(TViewer *viewer, const char *path, bool fillHeight, void (*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_image_position_render_thread(TViewer *viewer, float x, float y, bool clamp);
|
||||
EMSCRIPTEN_KEEPALIVE void load_skybox_render_thread(TViewer *viewer, const char *skyboxPath, void (*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void remove_skybox_render_thread(TViewer *viewer);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_createGeometryRenderThread(
|
||||
TSceneManager *sceneManager,
|
||||
float *vertices,
|
||||
int numVertices,
|
||||
float *normals,
|
||||
int numNormals,
|
||||
float *uvs,
|
||||
int numUvs,
|
||||
uint16_t *indices,
|
||||
int numIndices,
|
||||
int primitiveType,
|
||||
TMaterialInstance **materialInstances,
|
||||
int materialInstanceCount,
|
||||
bool keepData,
|
||||
void (*callback)(TSceneAsset *));
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_loadGlbFromBufferRenderThread(TSceneManager *sceneManager, const uint8_t *const data, size_t length, int numInstances, bool keepData, int priority, int layer, bool loadResourcesAsync, void (*callback)(TSceneAsset *));
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_createUnlitMaterialInstanceRenderThread(TSceneManager *sceneManager, void (*callback)(TMaterialInstance *));
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_createUnlitFixedSizeMaterialInstanceRenderThread(TSceneManager *sceneManager, void (*callback)(TMaterialInstance *));
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_loadGlbRenderThread(TSceneManager *sceneManager, const char *assetPath, int numInstances, bool keepData, void (*callback)(TSceneAsset *));
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_loadGltfRenderThread(TSceneManager *sceneManager, const char *assetPath, const char *relativePath, bool keepData, void (*callback)(TSceneAsset *));
|
||||
EMSCRIPTEN_KEEPALIVE void *SceneManager_destroyAllRenderThread(TSceneManager *tSceneManager, void (*callback)());
|
||||
EMSCRIPTEN_KEEPALIVE void *SceneManager_destroyAssetRenderThread(TSceneManager *tSceneManager, TSceneAsset *sceneAsset, void (*callback)());
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void SceneAsset_createInstanceRenderThread(TSceneAsset *asset, TMaterialInstance **tMaterialInstances, int materialInstanceCount, void (*callback)(TSceneAsset *));
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialProvider_createMaterialInstanceRenderThread(TMaterialProvider *tMaterialProvider, TMaterialKey *tKey, void (*callback)(TMaterialInstance*));
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_updateBoneMatricesRenderThread(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
void (*callback)(bool));
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_setMorphTargetWeightsRenderThread(
|
||||
TAnimationManager *tAnimationManager,
|
||||
EntityId entityId,
|
||||
const float *const morphData,
|
||||
int numWeights,
|
||||
void (*callback)(bool));
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void update_bone_matrices_render_thread(TSceneManager *sceneManager,
|
||||
EntityId asset, void (*callback)(bool));
|
||||
EMSCRIPTEN_KEEPALIVE void set_bone_transform_render_thread(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
int skinIndex,
|
||||
int boneIndex,
|
||||
const float *const transform,
|
||||
void (*callback)(bool));
|
||||
EMSCRIPTEN_KEEPALIVE void set_post_processing_render_thread(TViewer *viewer, bool enabled);
|
||||
EMSCRIPTEN_KEEPALIVE void reset_to_rest_pose_render_thread(TSceneManager *sceneManager, EntityId entityId, void (*callback)());
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void unproject_texture_render_thread(TViewer *viewer, EntityId entity, uint8_t *input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight, void (*callback)());
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _DART_FILAMENT_FFI_API_H
|
||||
@@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "Log.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <variant>
|
||||
|
||||
@@ -18,10 +16,11 @@
|
||||
#include <math/norm.h>
|
||||
|
||||
#include <gltfio/Animator.h>
|
||||
#include <gltfio/AssetLoader.h>
|
||||
#include <gltfio/ResourceLoader.h>
|
||||
#include <gltfio/math.h>
|
||||
#include <utils/NameComponentManager.h>
|
||||
|
||||
#include <utils/SingleInstanceComponentManager.h>
|
||||
|
||||
#include "Log.hpp"
|
||||
|
||||
template class std::vector<float>;
|
||||
namespace thermion
|
||||
@@ -170,7 +169,6 @@ namespace thermion
|
||||
|
||||
if (std::holds_alternative<FilamentInstance *>(animationComponent.target))
|
||||
{
|
||||
|
||||
auto target = std::get<FilamentInstance *>(animationComponent.target);
|
||||
auto animator = target->getAnimator();
|
||||
auto &gltfAnimations = animationComponent.gltfAnimations;
|
||||
@@ -225,7 +223,6 @@ namespace thermion
|
||||
if (elapsedInSecs >= (animationStatus.durationInSecs + animationStatus.fadeInInSecs + animationStatus.fadeOutInSecs))
|
||||
{
|
||||
if(!animationStatus.loop) {
|
||||
Log("Bone animation %d finished", i);
|
||||
boneAnimations.erase(boneAnimations.begin() + i);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -8,5 +8,5 @@ GRID_PACKAGE:
|
||||
GRID_GRID_OFFSET:
|
||||
.int 0
|
||||
GRID_GRID_SIZE:
|
||||
.int 43432
|
||||
.int 44564
|
||||
|
||||
|
||||
@@ -8,5 +8,5 @@ _GRID_PACKAGE:
|
||||
_GRID_GRID_OFFSET:
|
||||
.int 0
|
||||
_GRID_GRID_SIZE:
|
||||
.int 43432
|
||||
.int 44564
|
||||
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -8,5 +8,5 @@ UNLIT_FIXED_SIZE_PACKAGE:
|
||||
UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_OFFSET:
|
||||
.int 0
|
||||
UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE:
|
||||
.int 39924
|
||||
.int 41110
|
||||
|
||||
|
||||
@@ -8,5 +8,5 @@ _UNLIT_FIXED_SIZE_PACKAGE:
|
||||
_UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_OFFSET:
|
||||
.int 0
|
||||
_UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE:
|
||||
.int 39924
|
||||
.int 41110
|
||||
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
172
thermion_dart/native/include/scene/AnimationManager.hpp
Normal file
172
thermion_dart/native/include/scene/AnimationManager.hpp
Normal file
@@ -0,0 +1,172 @@
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/Scene.h>
|
||||
|
||||
#include "c_api/APIBoundaryTypes.h"
|
||||
|
||||
#include "components/CollisionComponentManager.hpp"
|
||||
#include "components/AnimationComponentManager.hpp"
|
||||
#include "GltfSceneAssetInstance.hpp"
|
||||
#include "GltfSceneAsset.hpp"
|
||||
#include "SceneAsset.hpp"
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
using namespace filament;
|
||||
using namespace filament::gltfio;
|
||||
using namespace utils;
|
||||
using std::string;
|
||||
using std::unique_ptr;
|
||||
using std::vector;
|
||||
|
||||
/// @brief
|
||||
class AnimationManager
|
||||
{
|
||||
public:
|
||||
AnimationManager(
|
||||
Engine *engine,
|
||||
Scene *scene);
|
||||
~AnimationManager();
|
||||
|
||||
void update();
|
||||
|
||||
/// @brief
|
||||
/// @param asset
|
||||
/// @param childEntity
|
||||
/// @return
|
||||
vector<string> getMorphTargetNames(GltfSceneAsset *asset, EntityId childEntity);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
/// @param skinIndex
|
||||
/// @return
|
||||
vector<Entity> getBoneEntities(GltfSceneAssetInstance *instance, int skinIndex);
|
||||
|
||||
/// @brief
|
||||
/// @param sceneAsset
|
||||
/// @param morphData
|
||||
/// @param morphIndices
|
||||
/// @param numMorphTargets
|
||||
/// @param numFrames
|
||||
/// @param frameLengthInMs
|
||||
/// @return
|
||||
bool setMorphAnimationBuffer(
|
||||
utils::Entity entity,
|
||||
const float *const morphData,
|
||||
const uint32_t *const morphIndices,
|
||||
int numMorphTargets,
|
||||
int numFrames,
|
||||
float frameLengthInMs);
|
||||
|
||||
/// @brief
|
||||
/// @param entityId
|
||||
void clearMorphAnimationBuffer(
|
||||
utils::Entity entity);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
/// @param skinIndex
|
||||
/// @param boneIndex
|
||||
/// @return
|
||||
math::mat4f getInverseBindMatrix(GltfSceneAssetInstance *instance, int skinIndex, int boneIndex);
|
||||
|
||||
/// @brief Set the local transform for the bone at boneIndex/skinIndex in the given entity.
|
||||
/// @param entityId the parent entity
|
||||
/// @param entityName the name of the mesh under entityId for which the bone will be set.
|
||||
/// @param skinIndex the index of the joint skin. Currently only 0 is supported.
|
||||
/// @param boneName the name of the bone
|
||||
/// @param transform the 4x4 matrix representing the local transform for the bone
|
||||
/// @return true if the transform was successfully set, false otherwise
|
||||
bool setBoneTransform(GltfSceneAssetInstance *instance, int skinIndex, int boneIndex, math::mat4f transform);
|
||||
|
||||
/// @brief Immediately start animating the bone at [boneIndex] under the parent instance [entity] at skin [skinIndex].
|
||||
/// @param entity the mesh entity to animate
|
||||
/// @param frameData frame data as quaternions
|
||||
/// @param numFrames the number of frames
|
||||
/// @param boneName the name of the bone to animate
|
||||
/// @param frameLengthInMs the length of each frame in ms
|
||||
/// @return true if the bone animation was successfully enqueued
|
||||
bool addBoneAnimation(
|
||||
GltfSceneAssetInstance *instance,
|
||||
int skinIndex,
|
||||
int boneIndex,
|
||||
const float *const frameData,
|
||||
int numFrames,
|
||||
float frameLengthInMs,
|
||||
float fadeOutInSecs,
|
||||
float fadeInInSecs,
|
||||
float maxDelta);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
/// @param skinIndex
|
||||
/// @return
|
||||
std::vector<math::mat4f> getBoneRestTranforms(GltfSceneAssetInstance *instance, int skinIndex);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
void resetToRestPose(GltfSceneAssetInstance *instance);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
void updateBoneMatrices(GltfSceneAssetInstance *instance);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
/// @param animationIndex
|
||||
/// @param loop
|
||||
/// @param reverse
|
||||
/// @param replaceActive
|
||||
/// @param crossfade
|
||||
/// @param startOffset
|
||||
void playGltfAnimation(GltfSceneAssetInstance *instance, int animationIndex, bool loop, bool reverse, bool replaceActive, float crossfade = 0.3f, float startOffset = 0.0f);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
/// @param animationIndex
|
||||
void stopGltfAnimation(GltfSceneAssetInstance *instance, int animationIndex);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
/// @param weights
|
||||
/// @param count
|
||||
void setMorphTargetWeights(utils::Entity entity, const float *const weights, int count);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
/// @param animationIndex
|
||||
/// @param animationFrame
|
||||
void setGltfAnimationFrame(GltfSceneAssetInstance *instance, int animationIndex, int animationFrame);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
/// @return
|
||||
vector<string> getGltfAnimationNames(GltfSceneAssetInstance *instance);
|
||||
|
||||
/// @brief
|
||||
/// @param instance
|
||||
/// @param animationIndex
|
||||
/// @return
|
||||
float getGltfAnimationDuration(GltfSceneAssetInstance *instance, int animationIndex);
|
||||
|
||||
/// @brief
|
||||
/// @param entity
|
||||
/// @return
|
||||
bool addAnimationComponent(EntityId entity);
|
||||
|
||||
/// @brief
|
||||
/// @param entity
|
||||
void removeAnimationComponent(EntityId entity);
|
||||
|
||||
private:
|
||||
Engine *_engine = nullptr;
|
||||
Scene *_scene = nullptr;
|
||||
std::mutex _mutex;
|
||||
std::unique_ptr<AnimationComponentManager> _animationComponentManager = std::nullptr_t();
|
||||
};
|
||||
}
|
||||
@@ -17,9 +17,8 @@
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
using namespace filament;
|
||||
using namespace filament;
|
||||
|
||||
// CustomGeometry.h
|
||||
class CustomGeometry {
|
||||
public:
|
||||
CustomGeometry(
|
||||
@@ -31,6 +30,7 @@ public:
|
||||
uint32_t numUvs,
|
||||
uint16_t* indices,
|
||||
uint32_t numIndices,
|
||||
MaterialInstance* materialInstance,
|
||||
RenderableManager::PrimitiveType primitiveType,
|
||||
Engine* engine);
|
||||
~CustomGeometry();
|
||||
@@ -40,6 +40,8 @@ public:
|
||||
private:
|
||||
Engine* _engine;
|
||||
|
||||
MaterialInstance* _materialInstance = nullptr;
|
||||
|
||||
VertexBuffer* vertexBuffer;
|
||||
IndexBuffer* indexBuffer;
|
||||
|
||||
143
thermion_dart/native/include/scene/GeometrySceneAsset.hpp
Normal file
143
thermion_dart/native/include/scene/GeometrySceneAsset.hpp
Normal file
@@ -0,0 +1,143 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/RenderableManager.h>
|
||||
#include <filament/VertexBuffer.h>
|
||||
#include <filament/IndexBuffer.h>
|
||||
#include <gltfio/MaterialProvider.h>
|
||||
#include "scene/SceneAsset.hpp"
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
using namespace filament;
|
||||
|
||||
class GeometrySceneAsset : public SceneAsset
|
||||
{
|
||||
public:
|
||||
GeometrySceneAsset(bool isInstance,
|
||||
Engine *engine,
|
||||
VertexBuffer *vertexBuffer,
|
||||
IndexBuffer *indexBuffer,
|
||||
MaterialInstance **materialInstances,
|
||||
size_t materialInstanceCount,
|
||||
RenderableManager::PrimitiveType primitiveType,
|
||||
Box boundingBox);
|
||||
~GeometrySceneAsset();
|
||||
|
||||
SceneAsset *createInstance(MaterialInstance **materialInstances = nullptr, size_t materialInstanceCount = 0) override;
|
||||
|
||||
SceneAssetType getType() override
|
||||
{
|
||||
return SceneAsset::SceneAssetType::Geometry;
|
||||
}
|
||||
|
||||
bool isInstance() override
|
||||
{
|
||||
return _isInstance;
|
||||
}
|
||||
|
||||
utils::Entity getEntity() override
|
||||
{
|
||||
return _entity;
|
||||
}
|
||||
|
||||
MaterialInstance **getMaterialInstances() override
|
||||
{
|
||||
return _materialInstances;
|
||||
}
|
||||
|
||||
size_t getMaterialInstanceCount() override
|
||||
{
|
||||
return _materialInstanceCount;
|
||||
}
|
||||
|
||||
const Box &getBoundingBox() const { return _boundingBox; }
|
||||
VertexBuffer *getVertexBuffer() const { return _vertexBuffer; }
|
||||
IndexBuffer *getIndexBuffer() const { return _indexBuffer; }
|
||||
|
||||
void addAllEntities(Scene *scene) override
|
||||
{
|
||||
scene->addEntity(_entity);
|
||||
}
|
||||
|
||||
void removeAllEntities(Scene *scene) override
|
||||
{
|
||||
scene->remove(_entity);
|
||||
}
|
||||
|
||||
void setPriority(RenderableManager &rm, int priority) override
|
||||
{
|
||||
auto renderableInstance = rm.getInstance(_entity);
|
||||
rm.setPriority(renderableInstance, priority);
|
||||
}
|
||||
|
||||
void setLayer(RenderableManager &rm, int layer) override
|
||||
{
|
||||
auto renderableInstance = rm.getInstance(_entity);
|
||||
rm.setLayerMask(renderableInstance, 0xFF, 1u << (uint8_t)layer);
|
||||
}
|
||||
|
||||
SceneAsset *getInstanceByEntity(utils::Entity entity) override
|
||||
{
|
||||
for (auto &instance : _instances)
|
||||
{
|
||||
if (instance->getEntity() == entity)
|
||||
{
|
||||
return instance.get();
|
||||
}
|
||||
}
|
||||
return std::nullptr_t();
|
||||
}
|
||||
|
||||
SceneAsset *getInstanceAt(size_t index) override
|
||||
{
|
||||
auto &asset = _instances[index];
|
||||
return asset.get();
|
||||
}
|
||||
|
||||
size_t getInstanceCount() override
|
||||
{
|
||||
return _instances.size();
|
||||
}
|
||||
|
||||
size_t getChildEntityCount() override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Entity *getChildEntities() override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Entity findEntityByName(const char *name) override
|
||||
{
|
||||
return Entity(); // not currently implemented
|
||||
}
|
||||
|
||||
static std::unique_ptr<GeometrySceneAsset> create(
|
||||
float *vertices, uint32_t numVertices,
|
||||
float *normals, uint32_t numNormals,
|
||||
float *uvs, uint32_t numUvs,
|
||||
uint16_t *indices, uint32_t numIndices,
|
||||
MaterialInstance *materialInstance,
|
||||
RenderableManager::PrimitiveType primitiveType,
|
||||
Engine *engine);
|
||||
|
||||
private:
|
||||
Engine *_engine = nullptr;
|
||||
VertexBuffer *_vertexBuffer = nullptr;
|
||||
IndexBuffer *_indexBuffer = nullptr;
|
||||
MaterialInstance **_materialInstances = nullptr;
|
||||
size_t _materialInstanceCount = 0;
|
||||
Box _boundingBox;
|
||||
bool _isInstance = false;
|
||||
utils::Entity _entity;
|
||||
RenderableManager::PrimitiveType _primitiveType;
|
||||
std::vector<std::unique_ptr<GeometrySceneAsset>> _instances;
|
||||
|
||||
};
|
||||
|
||||
} // namespace thermion
|
||||
308
thermion_dart/native/include/scene/GeometrySceneAssetBuilder.hpp
Normal file
308
thermion_dart/native/include/scene/GeometrySceneAssetBuilder.hpp
Normal file
@@ -0,0 +1,308 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/RenderableManager.h>
|
||||
#include <filament/VertexBuffer.h>
|
||||
#include <filament/IndexBuffer.h>
|
||||
#include <filament/geometry/SurfaceOrientation.h>
|
||||
#include <filament/Box.h>
|
||||
#include <gltfio/MaterialProvider.h>
|
||||
#include "GeometrySceneAsset.hpp"
|
||||
#include "Log.hpp"
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
class GeometrySceneAssetBuilder
|
||||
{
|
||||
public:
|
||||
GeometrySceneAssetBuilder(filament::Engine *engine) : mEngine(engine) {}
|
||||
|
||||
GeometrySceneAssetBuilder &vertices(const float *vertices, uint32_t count)
|
||||
{
|
||||
mVertices->resize(count);
|
||||
std::copy(vertices, vertices + count, mVertices->data());
|
||||
mNumVertices = count;
|
||||
return *this;
|
||||
}
|
||||
|
||||
GeometrySceneAssetBuilder &normals(const float *normals, uint32_t count)
|
||||
{
|
||||
if (normals)
|
||||
{
|
||||
mNormals->resize(count);
|
||||
std::copy(normals, normals + count, mNormals->data());
|
||||
}
|
||||
else
|
||||
{
|
||||
mNormals->clear();
|
||||
}
|
||||
mNumNormals = count;
|
||||
return *this;
|
||||
}
|
||||
|
||||
GeometrySceneAssetBuilder &uvs(const float *uvs, uint32_t count)
|
||||
{
|
||||
if (uvs)
|
||||
{
|
||||
mUVs->resize(count);
|
||||
std::copy(uvs, uvs + count, mUVs->data());
|
||||
}
|
||||
else
|
||||
{
|
||||
mUVs->clear();
|
||||
}
|
||||
mNumUVs = count;
|
||||
return *this;
|
||||
}
|
||||
|
||||
GeometrySceneAssetBuilder &indices(const uint16_t *indices, uint32_t count)
|
||||
{
|
||||
mIndices->resize(count);
|
||||
std::copy(indices, indices + count, mIndices->data());
|
||||
mNumIndices = count;
|
||||
return *this;
|
||||
}
|
||||
|
||||
GeometrySceneAssetBuilder &materials(filament::MaterialInstance **materials, size_t materialInstanceCount)
|
||||
{
|
||||
mMaterialInstances = materials;
|
||||
mMaterialInstanceCount = materialInstanceCount;
|
||||
return *this;
|
||||
}
|
||||
|
||||
GeometrySceneAssetBuilder &primitiveType(filament::RenderableManager::PrimitiveType type)
|
||||
{
|
||||
mPrimitiveType = type;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::unique_ptr<GeometrySceneAsset> build()
|
||||
{
|
||||
Log("Starting build. Validating inputs...");
|
||||
if (!validate())
|
||||
{
|
||||
Log("Validation failed!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Log("Creating buffers...");
|
||||
auto [vertexBuffer, indexBuffer] = createBuffers();
|
||||
if (!vertexBuffer || !indexBuffer)
|
||||
{
|
||||
Log("Failed to create buffers: VB=%p, IB=%p", vertexBuffer, indexBuffer);
|
||||
return nullptr;
|
||||
}
|
||||
Log("Buffers created successfully: VB=%p, IB=%p", vertexBuffer, indexBuffer);
|
||||
|
||||
Log("Creating entity...");
|
||||
auto entity = utils::EntityManager::get().create();
|
||||
Log("Entity created: %d", entity.getId());
|
||||
|
||||
Box boundingBox = computeBoundingBox();
|
||||
Log("Computed bounding box: min={%f,%f,%f}, max={%f,%f,%f}",
|
||||
boundingBox.getMin().x, boundingBox.getMin().y, boundingBox.getMin().z,
|
||||
boundingBox.getMax().x, boundingBox.getMax().y, boundingBox.getMax().z);
|
||||
|
||||
auto asset = std::make_unique<GeometrySceneAsset>(
|
||||
false,
|
||||
mEngine,
|
||||
vertexBuffer,
|
||||
indexBuffer,
|
||||
mMaterialInstances,
|
||||
mMaterialInstanceCount,
|
||||
mPrimitiveType,
|
||||
boundingBox);
|
||||
|
||||
Log("Asset created: %p", asset.get());
|
||||
return asset;
|
||||
}
|
||||
|
||||
private:
|
||||
Box computeBoundingBox()
|
||||
{
|
||||
float minX = FLT_MAX, minY = FLT_MAX, minZ = FLT_MAX;
|
||||
float maxX = -FLT_MAX, maxY = -FLT_MAX, maxZ = -FLT_MAX;
|
||||
Box box;
|
||||
for (uint32_t i = 0; i < mNumVertices; i += 3)
|
||||
{
|
||||
minX = std::min(mVertices->at(i), minX);
|
||||
minY = std::min(mVertices->at(i + 1), minY);
|
||||
minZ = std::min(mVertices->at(i + 2), minZ);
|
||||
maxX = std::max(mVertices->at(i), maxX);
|
||||
maxY = std::max(mVertices->at(i + 1), maxY);
|
||||
maxZ = std::max(mVertices->at(i + 2), maxZ);
|
||||
}
|
||||
const filament::math::float3 min {minX, minY, minZ};
|
||||
const filament::math::float3 max {maxX, maxY, maxZ};
|
||||
box.set(min, max);
|
||||
return box;
|
||||
}
|
||||
|
||||
std::pair<filament::VertexBuffer *, filament::IndexBuffer *> createBuffers()
|
||||
{
|
||||
auto indexBuffer = IndexBuffer::Builder()
|
||||
.indexCount(mNumIndices)
|
||||
.bufferType(IndexBuffer::IndexType::USHORT)
|
||||
.build(*mEngine);
|
||||
|
||||
indexBuffer->setBuffer(*mEngine,
|
||||
IndexBuffer::BufferDescriptor(
|
||||
mIndices->data(),
|
||||
mNumIndices * sizeof(uint16_t),
|
||||
[](void *, size_t, void *data)
|
||||
{
|
||||
delete static_cast<std::vector<float> *>(data);
|
||||
},
|
||||
mIndices));
|
||||
|
||||
if (mUVs->empty())
|
||||
{
|
||||
mUVs->resize(mNumVertices);
|
||||
std::fill(mUVs->begin(), mUVs->end(), 0.0f);
|
||||
}
|
||||
|
||||
auto dummyColors = new std::vector<filament::math::float4>(
|
||||
mNumVertices, filament::math::float4{1.0f, 1.0f, 1.0f, 1.0f});
|
||||
|
||||
auto vertexBufferBuilder =
|
||||
VertexBuffer::Builder()
|
||||
.vertexCount(mNumVertices)
|
||||
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3)
|
||||
.attribute(VertexAttribute::UV0, 1, VertexBuffer::AttributeType::FLOAT2)
|
||||
.attribute(VertexAttribute::UV1, 2, VertexBuffer::AttributeType::FLOAT2)
|
||||
.attribute(VertexAttribute::COLOR, 3, VertexBuffer::AttributeType::FLOAT4);
|
||||
|
||||
if (!mNormals->empty())
|
||||
{
|
||||
vertexBufferBuilder.bufferCount(5)
|
||||
.attribute(VertexAttribute::TANGENTS, 4, VertexBuffer::AttributeType::FLOAT4);
|
||||
}
|
||||
else
|
||||
{
|
||||
vertexBufferBuilder = vertexBufferBuilder.bufferCount(4);
|
||||
}
|
||||
|
||||
auto vertexBuffer = vertexBufferBuilder.build(*mEngine);
|
||||
|
||||
vertexBuffer->setBufferAt(*mEngine, 0,
|
||||
VertexBuffer::BufferDescriptor(
|
||||
mVertices->data(), mNumVertices * sizeof(float),
|
||||
[](void *, size_t, void *) {}));
|
||||
|
||||
vertexBuffer->setBufferAt(*mEngine, 1,
|
||||
VertexBuffer::BufferDescriptor(
|
||||
mUVs->data(), mUVs->size() * sizeof(float),
|
||||
[](void *, size_t, void *data)
|
||||
{
|
||||
},
|
||||
mUVs));
|
||||
|
||||
vertexBuffer->setBufferAt(*mEngine, 2,
|
||||
VertexBuffer::BufferDescriptor(
|
||||
mUVs->data(), mUVs->size() * sizeof(float),
|
||||
[](void *, size_t, void *data) {
|
||||
delete static_cast<std::vector<float> *>(data);
|
||||
|
||||
},
|
||||
mUVs));
|
||||
|
||||
vertexBuffer->setBufferAt(*mEngine, 3,
|
||||
VertexBuffer::BufferDescriptor(
|
||||
dummyColors->data(), dummyColors->size() * sizeof(math::float4),
|
||||
[](void *, size_t, void *data)
|
||||
{
|
||||
delete static_cast<std::vector<math::float4> *>(data);
|
||||
},
|
||||
dummyColors));
|
||||
|
||||
if (!mNormals->empty())
|
||||
{
|
||||
assert(mPrimitiveType == RenderableManager::PrimitiveType::TRIANGLES);
|
||||
|
||||
std::vector<filament::math::ushort3> triangles;
|
||||
for (uint32_t i = 0; i < mNumIndices; i += 3)
|
||||
{
|
||||
triangles.push_back({mIndices->at(i),
|
||||
mIndices->at(i + 1),
|
||||
mIndices->at(i + 2)});
|
||||
}
|
||||
|
||||
auto &builder = geometry::SurfaceOrientation::Builder()
|
||||
.vertexCount(mNumVertices)
|
||||
.normals((filament::math::float3 *)mNormals->data())
|
||||
.positions((filament::math::float3 *)mVertices->data())
|
||||
.triangleCount(triangles.size())
|
||||
.triangles(triangles.data());
|
||||
|
||||
auto orientation = builder.build();
|
||||
auto quats = new std::vector<filament::math::quatf>(mNumVertices);
|
||||
orientation->getQuats(quats->data(), mNumVertices);
|
||||
|
||||
vertexBuffer->setBufferAt(*mEngine, 4,
|
||||
VertexBuffer::BufferDescriptor(
|
||||
quats->data(), quats->size() * sizeof(math::quatf),
|
||||
[](void *, size_t, void *data)
|
||||
{
|
||||
delete static_cast<std::vector<math::quatf> *>(data);
|
||||
},
|
||||
quats));
|
||||
}
|
||||
|
||||
return {vertexBuffer, indexBuffer};
|
||||
}
|
||||
|
||||
bool validate() const
|
||||
{
|
||||
if (!mEngine)
|
||||
{
|
||||
Log("Validation failed: No engine");
|
||||
return false;
|
||||
}
|
||||
if (mVertices->empty() || mNumVertices == 0)
|
||||
{
|
||||
Log("Validation failed: No vertices (empty=%d, count=%d)", mVertices->empty(), mNumVertices);
|
||||
return false;
|
||||
}
|
||||
if (mNumNormals > 0 && !mNormals->empty() && mNumNormals != mNumVertices)
|
||||
{
|
||||
Log("Validation failed: Normal count mismatch (normals=%d, vertices=%d)", mNumNormals, mNumVertices);
|
||||
return false;
|
||||
}
|
||||
if (mNumUVs > 0 && !mUVs->empty() && mNumUVs != mNumVertices)
|
||||
{
|
||||
Log("Validation failed: UV count mismatch (uvs=%d, vertices=%d)", mNumUVs, mNumVertices);
|
||||
return false;
|
||||
}
|
||||
if (mIndices->empty() || mNumIndices == 0)
|
||||
{
|
||||
Log("Validation failed: No indices (empty=%d, count=%d)", mIndices->empty(), mNumIndices);
|
||||
return false;
|
||||
}
|
||||
|
||||
Log("Validation passed: vertices=%d, normals=%s, uvs=%d, indices=%d",
|
||||
mNumVertices,
|
||||
(!mNormals->empty() ? "yes" : "no"),
|
||||
mNumUVs,
|
||||
mNumIndices);
|
||||
return true;
|
||||
}
|
||||
|
||||
filament::Engine *mEngine = nullptr;
|
||||
std::vector<float> *mVertices = new std::vector<float>();
|
||||
std::vector<float> *mNormals = new std::vector<float>();
|
||||
std::vector<float> *mUVs = new std::vector<float>();
|
||||
std::vector<uint16_t> *mIndices = new std::vector<uint16_t>;
|
||||
uint32_t mNumVertices = 0;
|
||||
uint32_t mNumNormals = 0;
|
||||
uint32_t mNumUVs = 0;
|
||||
uint32_t mNumIndices = 0;
|
||||
filament::MaterialInstance **mMaterialInstances = nullptr;
|
||||
size_t mMaterialInstanceCount = 0;
|
||||
filament::gltfio::MaterialProvider *mMaterialProvider = nullptr;
|
||||
filament::RenderableManager::PrimitiveType mPrimitiveType =
|
||||
filament::RenderableManager::PrimitiveType::TRIANGLES;
|
||||
};
|
||||
|
||||
} // namespace thermion
|
||||
201
thermion_dart/native/include/scene/Gizmo.hpp
Normal file
201
thermion_dart/native/include/scene/Gizmo.hpp
Normal file
@@ -0,0 +1,201 @@
|
||||
#pragma once
|
||||
|
||||
#include <utils/Entity.h>
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/Material.h>
|
||||
#include <filament/MaterialInstance.h>
|
||||
#include <filament/Scene.h>
|
||||
#include <filament/Camera.h>
|
||||
#include <filament/View.h>
|
||||
#include <filament/Viewport.h>
|
||||
#include <filament/RenderableManager.h>
|
||||
|
||||
#include <gltfio/AssetLoader.h>
|
||||
#include <gltfio/FilamentAsset.h>
|
||||
#include <gltfio/FilamentInstance.h>
|
||||
#include <gltfio/ResourceLoader.h>
|
||||
|
||||
#include <filament/IndexBuffer.h>
|
||||
#include <filament/InstanceBuffer.h>
|
||||
|
||||
#include "c_api/ThermionDartApi.h"
|
||||
#include "scene/SceneAsset.hpp"
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
using namespace filament;
|
||||
using namespace utils;
|
||||
|
||||
class Gizmo : public SceneAsset
|
||||
{
|
||||
|
||||
public:
|
||||
Gizmo(Engine *engine, View *view, Scene *scene, Material *material);
|
||||
~Gizmo() override;
|
||||
|
||||
enum Axis
|
||||
{
|
||||
X,
|
||||
Y,
|
||||
Z
|
||||
};
|
||||
|
||||
enum GizmoPickResultType {
|
||||
AxisX,
|
||||
AxisY,
|
||||
AxisZ,
|
||||
Parent,
|
||||
None
|
||||
};
|
||||
|
||||
typedef void (*GizmoPickCallback)(Gizmo::GizmoPickResultType result, float x, float y, float z);
|
||||
|
||||
|
||||
void pick(uint32_t x, uint32_t y, GizmoPickCallback callback);
|
||||
bool isGizmoEntity(Entity entity);
|
||||
|
||||
SceneAssetType getType() override { return SceneAssetType::Gizmo; }
|
||||
utils::Entity getEntity() override { return _entities[0]; }
|
||||
bool isInstance() override { return false; }
|
||||
SceneAsset *createInstance(MaterialInstance **materialInstances, size_t materialInstanceCount) override { return nullptr; }
|
||||
MaterialInstance **getMaterialInstances() override { return _materialInstances.data(); }
|
||||
size_t getMaterialInstanceCount() override { return _materialInstances.size(); }
|
||||
|
||||
void addAllEntities(Scene *scene) override
|
||||
{
|
||||
for (const auto &entity : _entities)
|
||||
{
|
||||
if (entity.isNull())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
scene->addEntity(entity);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void removeAllEntities(Scene *scene) override
|
||||
{
|
||||
for (const auto &entity : _entities)
|
||||
{
|
||||
scene->remove(entity);
|
||||
}
|
||||
}
|
||||
|
||||
size_t getInstanceCount() override { return 0; }
|
||||
SceneAsset *getInstanceByEntity(utils::Entity entity) override { return nullptr; }
|
||||
SceneAsset *getInstanceAt(size_t index) override { return nullptr; }
|
||||
|
||||
size_t getChildEntityCount() override { return _entities.size() - 1; }
|
||||
const Entity *getChildEntities() override { return _entities.data() + 1; }
|
||||
|
||||
Entity findEntityByName(const char *name) override
|
||||
{
|
||||
return utils::Entity::import(0);
|
||||
}
|
||||
|
||||
void setPriority(RenderableManager &rm, int mask) override
|
||||
{
|
||||
}
|
||||
|
||||
void setLayer(RenderableManager &rm, int layer) override
|
||||
{
|
||||
}
|
||||
|
||||
void highlight(Gizmo::Axis axis);
|
||||
void unhighlight(Gizmo::Axis axis);
|
||||
|
||||
private:
|
||||
class PickCallbackHandler
|
||||
{
|
||||
public:
|
||||
PickCallbackHandler(Gizmo *gizmo, GizmoPickCallback callback)
|
||||
: _gizmo(gizmo), _callback(callback) {}
|
||||
|
||||
void handle(filament::View::PickingQueryResult const &result)
|
||||
{
|
||||
|
||||
_gizmo->unhighlight(Gizmo::Axis::X);
|
||||
_gizmo->unhighlight(Gizmo::Axis::Y);
|
||||
_gizmo->unhighlight(Gizmo::Axis::Z);
|
||||
|
||||
Gizmo::GizmoPickResultType resultType;
|
||||
|
||||
if (result.renderable == _gizmo->_parent)
|
||||
{
|
||||
resultType = Gizmo::GizmoPickResultType::Parent;
|
||||
}
|
||||
else if (result.renderable == _gizmo->_x || result.renderable == _gizmo->_xHitTest)
|
||||
{
|
||||
resultType = Gizmo::GizmoPickResultType::AxisX;
|
||||
_gizmo->highlight(Gizmo::Axis::X);
|
||||
}
|
||||
else if (result.renderable == _gizmo->_y || result.renderable == _gizmo->_yHitTest)
|
||||
{
|
||||
_gizmo->highlight(Gizmo::Axis::Y);
|
||||
resultType = Gizmo::GizmoPickResultType::AxisY;
|
||||
}
|
||||
else if (result.renderable == _gizmo->_z || result.renderable == _gizmo->_zHitTest)
|
||||
{
|
||||
_gizmo->highlight(Gizmo::Axis::Z);
|
||||
resultType = Gizmo::GizmoPickResultType::AxisZ;
|
||||
} else {
|
||||
resultType = Gizmo::GizmoPickResultType::None;
|
||||
}
|
||||
|
||||
_callback(resultType, result.fragCoords.x, result.fragCoords.y, result.fragCoords.z);
|
||||
}
|
||||
|
||||
private:
|
||||
Gizmo *_gizmo;
|
||||
GizmoPickCallback _callback;
|
||||
};
|
||||
|
||||
Entity createParentEntity();
|
||||
Entity createHitTestEntity(Gizmo::Axis axis, Entity parent);
|
||||
Entity createAxisEntity(Gizmo::Axis axis, Entity parent);
|
||||
|
||||
math::mat4f getRotationForAxis(Gizmo::Axis axis);
|
||||
Entity getEntityForAxis(Gizmo::Axis axis)
|
||||
{
|
||||
switch (axis)
|
||||
{
|
||||
case Gizmo::Axis::X:
|
||||
return _x;
|
||||
case Gizmo::Axis::Y:
|
||||
return _y;
|
||||
case Gizmo::Axis::Z:
|
||||
return _z;
|
||||
}
|
||||
}
|
||||
|
||||
Engine *_engine;
|
||||
Scene *_scene;
|
||||
View *_view;
|
||||
Material *_material;
|
||||
|
||||
utils::Entity _parent;
|
||||
utils::Entity _x;
|
||||
utils::Entity _y;
|
||||
utils::Entity _z;
|
||||
utils::Entity _xHitTest;
|
||||
utils::Entity _yHitTest;
|
||||
utils::Entity _zHitTest;
|
||||
|
||||
std::vector<utils::Entity> _entities;
|
||||
std::vector<MaterialInstance *> _materialInstances;
|
||||
|
||||
math::float4 activeColors[3]{
|
||||
math::float4{1.0f, 1.0f, 0.0f, 0.5f},
|
||||
math::float4{1.0f, 1.0f, 0.0f, 0.5f},
|
||||
math::float4{1.0f, 1.0f, 0.0f, 0.5f},
|
||||
};
|
||||
math::float4 inactiveColors[3]{
|
||||
math::float4{1.0f, 0.0f, 0.0f, 1.0f},
|
||||
math::float4{0.0f, 1.0f, 0.0f, 1.0f},
|
||||
math::float4{0.0f, 0.0f, 1.0f, 1.0f},
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
163
thermion_dart/native/include/scene/GltfSceneAsset.hpp
Normal file
163
thermion_dart/native/include/scene/GltfSceneAsset.hpp
Normal file
@@ -0,0 +1,163 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/RenderableManager.h>
|
||||
#include <filament/VertexBuffer.h>
|
||||
#include <filament/IndexBuffer.h>
|
||||
#include <gltfio/AssetLoader.h>
|
||||
#include <gltfio/FilamentAsset.h>
|
||||
#include <gltfio/MaterialProvider.h>
|
||||
|
||||
#include "scene/GltfSceneAssetInstance.hpp"
|
||||
#include "components/AnimationComponentManager.hpp"
|
||||
#include "components/CollisionComponentManager.hpp"
|
||||
|
||||
#include "scene/SceneAsset.hpp"
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
using namespace filament;
|
||||
|
||||
class GltfSceneAsset : public SceneAsset
|
||||
{
|
||||
public:
|
||||
GltfSceneAsset(
|
||||
gltfio::FilamentAsset *asset,
|
||||
gltfio::AssetLoader *assetLoader,
|
||||
Engine *engine,
|
||||
MaterialInstance **materialInstances = nullptr,
|
||||
size_t materialInstanceCount = 0,
|
||||
int instanceIndex = -1) : _asset(asset),
|
||||
_assetLoader(assetLoader),
|
||||
_engine(engine),
|
||||
_materialInstances(materialInstances),
|
||||
_materialInstanceCount(materialInstanceCount)
|
||||
{
|
||||
}
|
||||
|
||||
~GltfSceneAsset();
|
||||
|
||||
SceneAsset *createInstance(MaterialInstance **materialInstances = nullptr, size_t materialInstanceCount = 0) override;
|
||||
|
||||
SceneAssetType getType() override
|
||||
{
|
||||
return SceneAsset::SceneAssetType::Gltf;
|
||||
}
|
||||
|
||||
bool isInstance() override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
utils::Entity getEntity() override
|
||||
{
|
||||
return _asset->getRoot();
|
||||
}
|
||||
|
||||
MaterialInstance **getMaterialInstances() override
|
||||
{
|
||||
return _materialInstances;
|
||||
}
|
||||
|
||||
size_t getMaterialInstanceCount() override
|
||||
{
|
||||
return _materialInstanceCount;
|
||||
}
|
||||
|
||||
gltfio::FilamentAsset *getAsset()
|
||||
{
|
||||
return _asset;
|
||||
}
|
||||
|
||||
void addAllEntities(Scene *scene) override
|
||||
{
|
||||
scene->addEntities(_asset->getEntities(), _asset->getEntityCount());
|
||||
scene->addEntities(_asset->getLightEntities(), _asset->getLightEntityCount());
|
||||
scene->addEntities(_asset->getCameraEntities(), _asset->getCameraEntityCount());
|
||||
}
|
||||
|
||||
void removeAllEntities(Scene *scene) override
|
||||
{
|
||||
scene->removeEntities(_asset->getEntities(), _asset->getEntityCount());
|
||||
scene->removeEntities(_asset->getLightEntities(), _asset->getLightEntityCount());
|
||||
scene->removeEntities(_asset->getCameraEntities(), _asset->getCameraEntityCount());
|
||||
}
|
||||
|
||||
void setPriority(RenderableManager &rm, int priority) override
|
||||
{
|
||||
const Entity *entities = _asset->getEntities();
|
||||
for (int i = 0; i < _asset->getEntityCount(); i++)
|
||||
{
|
||||
if (rm.hasComponent(entities[i]))
|
||||
{
|
||||
auto renderableInstance = rm.getInstance(entities[i]);
|
||||
rm.setPriority(renderableInstance, priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setLayer(RenderableManager &rm, int layer) override
|
||||
{
|
||||
const Entity *entities = _asset->getEntities();
|
||||
for (int i = 0; i < _asset->getEntityCount(); i++)
|
||||
{
|
||||
if (rm.hasComponent(entities[i]))
|
||||
{
|
||||
auto renderableInstance = rm.getInstance(entities[i]);
|
||||
rm.setLayerMask(renderableInstance, 0xFF, 1u << (uint8_t)layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SceneAsset *getInstanceByEntity(utils::Entity entity) override
|
||||
{
|
||||
for (auto &instance : _instances)
|
||||
{
|
||||
if (instance->getEntity() == entity)
|
||||
{
|
||||
return instance.get();
|
||||
}
|
||||
}
|
||||
return std::nullptr_t();
|
||||
}
|
||||
|
||||
SceneAsset *getInstanceAt(size_t index) override
|
||||
{
|
||||
auto &asset = _instances[index];
|
||||
return asset.get();
|
||||
}
|
||||
|
||||
size_t getInstanceCount() override
|
||||
{
|
||||
return _instances.size();
|
||||
}
|
||||
|
||||
size_t getChildEntityCount() override
|
||||
{
|
||||
return _asset->getEntityCount();
|
||||
}
|
||||
|
||||
const Entity* getChildEntities() override {
|
||||
return _asset->getEntities();
|
||||
}
|
||||
|
||||
Entity findEntityByName(const char* name) override {
|
||||
Entity entities[1];
|
||||
auto found = _asset->getEntitiesByName(name, entities, 1);
|
||||
return entities[0];
|
||||
}
|
||||
|
||||
private:
|
||||
gltfio::FilamentAsset *_asset;
|
||||
gltfio::AssetLoader *_assetLoader;
|
||||
Engine *_engine;
|
||||
MaterialInstance **_materialInstances = nullptr;
|
||||
size_t _materialInstanceCount = 0;
|
||||
std::vector<std::unique_ptr<GltfSceneAssetInstance>> _instances;
|
||||
};
|
||||
|
||||
} // namespace thermion
|
||||
143
thermion_dart/native/include/scene/GltfSceneAssetInstance.hpp
Normal file
143
thermion_dart/native/include/scene/GltfSceneAssetInstance.hpp
Normal file
@@ -0,0 +1,143 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/RenderableManager.h>
|
||||
#include <filament/VertexBuffer.h>
|
||||
#include <filament/IndexBuffer.h>
|
||||
#include <gltfio/FilamentAsset.h>
|
||||
#include <gltfio/FilamentInstance.h>
|
||||
#include <gltfio/MaterialProvider.h>
|
||||
|
||||
#include "scene/SceneAsset.hpp"
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
using namespace filament;
|
||||
|
||||
class GltfSceneAssetInstance : public SceneAsset
|
||||
{
|
||||
public:
|
||||
GltfSceneAssetInstance(
|
||||
gltfio::FilamentInstance *instance,
|
||||
Engine *engine,
|
||||
MaterialInstance **materialInstances = nullptr,
|
||||
size_t materialInstanceCount = 0,
|
||||
int instanceIndex = -1) : _instance(instance),
|
||||
_materialInstances(materialInstances),
|
||||
_materialInstanceCount(materialInstanceCount)
|
||||
{
|
||||
}
|
||||
|
||||
~GltfSceneAssetInstance();
|
||||
|
||||
SceneAsset *createInstance(MaterialInstance **materialInstances = nullptr, size_t materialInstanceCount = 0) override
|
||||
{
|
||||
return std::nullptr_t();
|
||||
};
|
||||
|
||||
SceneAssetType getType() override
|
||||
{
|
||||
return SceneAsset::SceneAssetType::Gltf;
|
||||
}
|
||||
|
||||
bool isInstance() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
utils::Entity getEntity() override
|
||||
{
|
||||
return _instance->getRoot();
|
||||
}
|
||||
|
||||
MaterialInstance **getMaterialInstances() override
|
||||
{
|
||||
return _materialInstances;
|
||||
}
|
||||
|
||||
size_t getMaterialInstanceCount() override
|
||||
{
|
||||
return _materialInstanceCount;
|
||||
}
|
||||
|
||||
gltfio::FilamentInstance *getInstance()
|
||||
{
|
||||
return _instance;
|
||||
}
|
||||
|
||||
void addAllEntities(Scene *scene) override
|
||||
{
|
||||
scene->addEntities(_instance->getEntities(), _instance->getEntityCount());
|
||||
}
|
||||
|
||||
void removeAllEntities(Scene *scene) override {
|
||||
scene->removeEntities(_instance->getEntities(), _instance->getEntityCount());
|
||||
}
|
||||
|
||||
size_t getInstanceCount() override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SceneAsset *getInstanceAt(size_t index) override
|
||||
{
|
||||
return std::nullptr_t();
|
||||
}
|
||||
|
||||
size_t getChildEntityCount() override
|
||||
{
|
||||
return _instance->getEntityCount();
|
||||
}
|
||||
|
||||
const Entity* getChildEntities() override {
|
||||
return _instance->getEntities();
|
||||
}
|
||||
|
||||
Entity findEntityByName(const char* name) override {
|
||||
return Entity(); // not currently implemented
|
||||
}
|
||||
|
||||
SceneAsset *getInstanceByEntity(utils::Entity entity) override {
|
||||
return std::nullptr_t();
|
||||
}
|
||||
|
||||
void setPriority(RenderableManager &rm, int priority) override
|
||||
{
|
||||
const Entity *entities = _instance->getEntities();
|
||||
for (int i = 0; i < _instance->getEntityCount(); i++)
|
||||
{
|
||||
if (rm.hasComponent(entities[i]))
|
||||
{
|
||||
auto renderableInstance = rm.getInstance(entities[i]);
|
||||
rm.setPriority(renderableInstance, priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setLayer(RenderableManager &rm, int layer) override
|
||||
{
|
||||
const Entity *entities = _instance->getEntities();
|
||||
for (int i = 0; i < _instance->getEntityCount(); i++)
|
||||
{
|
||||
if (rm.hasComponent(entities[i]))
|
||||
{
|
||||
auto renderableInstance = rm.getInstance(entities[i]);
|
||||
rm.setLayerMask(renderableInstance, 0xFF, 1u << (uint8_t)layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
filament::Engine *_engine;
|
||||
gltfio::FilamentInstance *_instance;
|
||||
MaterialInstance **_materialInstances = nullptr;
|
||||
size_t _materialInstanceCount = 0;
|
||||
};
|
||||
|
||||
} // namespace thermion
|
||||
53
thermion_dart/native/include/scene/SceneAsset.hpp
Normal file
53
thermion_dart/native/include/scene/SceneAsset.hpp
Normal file
@@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <utils/Entity.h>
|
||||
#include <gltfio/FilamentAsset.h>
|
||||
#include <filament/Scene.h>
|
||||
|
||||
#include "CustomGeometry.hpp"
|
||||
#include "Log.hpp"
|
||||
|
||||
namespace thermion {
|
||||
|
||||
using namespace filament;
|
||||
using namespace utils;
|
||||
|
||||
class SceneAsset {
|
||||
|
||||
public:
|
||||
enum SceneAssetType { Gltf, Geometry, Light, Skybox, Ibl, Image, Gizmo };
|
||||
|
||||
virtual ~SceneAsset() {
|
||||
|
||||
}
|
||||
virtual SceneAssetType getType() = 0;
|
||||
|
||||
virtual utils::Entity getEntity() {
|
||||
return utils::Entity::import(0);
|
||||
}
|
||||
|
||||
virtual bool isInstance() = 0;
|
||||
|
||||
virtual SceneAsset* createInstance(MaterialInstance **materialInstances, size_t materialInstanceCount) = 0;
|
||||
|
||||
virtual MaterialInstance **getMaterialInstances() = 0;
|
||||
virtual size_t getMaterialInstanceCount() = 0;
|
||||
virtual void addAllEntities(Scene *scene) = 0;
|
||||
virtual void removeAllEntities(Scene *scene) = 0;
|
||||
|
||||
virtual size_t getInstanceCount() = 0;
|
||||
virtual SceneAsset *getInstanceByEntity(utils::Entity entity) = 0;
|
||||
virtual SceneAsset *getInstanceAt(size_t index) = 0;
|
||||
virtual size_t getChildEntityCount() = 0;
|
||||
virtual const Entity* getChildEntities() = 0;
|
||||
virtual Entity findEntityByName(const char* name) = 0;
|
||||
|
||||
virtual void setPriority(RenderableManager& rm, int mask) = 0;
|
||||
virtual void setLayer(RenderableManager& rm, int layer) = 0;
|
||||
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
350
thermion_dart/native/include/scene/SceneManager.hpp
Normal file
350
thermion_dart/native/include/scene/SceneManager.hpp
Normal file
@@ -0,0 +1,350 @@
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include <filament/Scene.h>
|
||||
#include <filament/Camera.h>
|
||||
#include <filament/View.h>
|
||||
|
||||
#include <gltfio/AssetLoader.h>
|
||||
#include <gltfio/FilamentAsset.h>
|
||||
#include <gltfio/FilamentInstance.h>
|
||||
#include <gltfio/ResourceLoader.h>
|
||||
|
||||
#include <filament/IndexBuffer.h>
|
||||
#include <filament/InstanceBuffer.h>
|
||||
#include <utils/NameComponentManager.h>
|
||||
|
||||
#include "tsl/robin_map.h"
|
||||
|
||||
#include "AnimationManager.hpp"
|
||||
#include "CustomGeometry.hpp"
|
||||
#include "Gizmo.hpp"
|
||||
#include "GridOverlay.hpp"
|
||||
#include "ResourceBuffer.hpp"
|
||||
#include "SceneAsset.hpp"
|
||||
|
||||
#include "components/CollisionComponentManager.hpp"
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
typedef int32_t EntityId;
|
||||
|
||||
using namespace filament;
|
||||
using namespace filament::gltfio;
|
||||
using namespace utils;
|
||||
using std::string;
|
||||
using std::unique_ptr;
|
||||
using std::vector;
|
||||
|
||||
class SceneManager
|
||||
{
|
||||
public:
|
||||
SceneManager(
|
||||
const ResourceLoaderWrapperImpl *const loader,
|
||||
Engine *engine,
|
||||
Scene *scene,
|
||||
const char *uberArchivePath,
|
||||
Camera *mainCamera);
|
||||
~SceneManager();
|
||||
|
||||
enum LAYERS
|
||||
{
|
||||
DEFAULT_ASSETS = 0,
|
||||
BACKGROUND = 6,
|
||||
OVERLAY = 7,
|
||||
};
|
||||
|
||||
////
|
||||
/// @brief Load the glTF file from the specified path and adds all entities to the scene.
|
||||
/// @param uri the path to the asset. Should be either asset:// (representing a Flutter asset), or file:// (representing a filesystem file).
|
||||
/// @param relativeResourcePath the (relative) path to the asset's resources.
|
||||
/// @return the glTF entity.
|
||||
///
|
||||
SceneAsset* loadGltf(const char *uri, const char *relativeResourcePath, int numInstances = 1, bool keepData = false);
|
||||
|
||||
////
|
||||
/// @brief Load the GLB from the specified path, optionally creating multiple instances.
|
||||
/// @param uri the path to the asset. Should be either asset:// (representing a Flutter asset), or file:// (representing a filesystem file).
|
||||
/// @param numInstances the number of instances to create. Must be at least 1.
|
||||
/// @return an Entity representing the FilamentAsset associated with the loaded FilamentAsset.
|
||||
///
|
||||
SceneAsset* loadGlb(const char *uri, int numInstances, bool keepData);
|
||||
|
||||
/// @brief
|
||||
/// @param data
|
||||
/// @param length
|
||||
/// @param numInstances
|
||||
/// @param keepData
|
||||
/// @param priority
|
||||
/// @param layer
|
||||
/// @param loadResourcesAsync
|
||||
/// @return
|
||||
SceneAsset* loadGlbFromBuffer(const uint8_t *data, size_t length, int numInstances = 1, bool keepData = false, int priority = 4, int layer = 0, bool loadResourcesAsync = false);
|
||||
|
||||
///
|
||||
/// Creates an instance of the given entity.
|
||||
/// This may return an instance from a pool of inactive instances; see [remove] for more information.
|
||||
/// If [materialInstances] is provided, these wil
|
||||
///
|
||||
SceneAsset* createInstance(SceneAsset* asset, MaterialInstance **materialInstances = nullptr, size_t materialInstanceCount = 0);
|
||||
|
||||
/// @brief Removes the asset (and all its child entities) from the scene and "destroys" all resources.
|
||||
/// If the asset is not an instance, the asset will be deleted.
|
||||
/// If the asset is an instance, [remove] is not guaranted to delete the asset. It may be returned to a pool of inactive instances.
|
||||
/// From the user's perspective, this can be considered as destroyed.
|
||||
/// @param entity
|
||||
void destroy(SceneAsset* entity);
|
||||
|
||||
/// @brief Destroys all assets, scenes, materials, etc.
|
||||
///
|
||||
void destroyAll();
|
||||
|
||||
/// @brief
|
||||
/// @param entityId
|
||||
void transformToUnitCube(EntityId entityId);
|
||||
|
||||
/// @brief
|
||||
/// @param entities
|
||||
/// @param transforms
|
||||
/// @param numEntities
|
||||
void queueTransformUpdates(EntityId *entities, math::mat4 *transforms, int numEntities);
|
||||
|
||||
/// @brief
|
||||
/// @param entity
|
||||
/// @param viewportCoordX
|
||||
/// @param viewportCoordY
|
||||
/// @param x
|
||||
/// @param y
|
||||
/// @param z
|
||||
void queueRelativePositionUpdateWorldAxis(EntityId entity, float viewportCoordX, float viewportCoordY, float x, float y, float z);
|
||||
|
||||
/// @brief
|
||||
/// @param view
|
||||
/// @param entityId
|
||||
/// @param viewportCoordX
|
||||
/// @param viewportCoordY
|
||||
void queueRelativePositionUpdateFromViewportVector(View *view, EntityId entityId, float viewportCoordX, float viewportCoordY);
|
||||
|
||||
const utils::Entity *getCameraEntities(EntityId e);
|
||||
size_t getCameraEntityCount(EntityId e);
|
||||
const utils::Entity *getLightEntities(EntityId e) noexcept;
|
||||
size_t getLightEntityCount(EntityId e) noexcept;
|
||||
|
||||
/// @brief
|
||||
void update();
|
||||
|
||||
|
||||
/// @brief
|
||||
/// @param data
|
||||
/// @param length
|
||||
/// @param name
|
||||
/// @return
|
||||
Texture *createTexture(const uint8_t *data, size_t length, const char *name);
|
||||
|
||||
/// @brief
|
||||
/// @param entityId
|
||||
/// @param texture
|
||||
/// @param slotName
|
||||
/// @param materialIndex
|
||||
/// @return
|
||||
bool applyTexture(EntityId entityId, Texture *texture, const char *slotName, int materialIndex);
|
||||
|
||||
/// @brief
|
||||
/// @param texture
|
||||
void destroyTexture(Texture *texture);
|
||||
|
||||
/// @brief
|
||||
/// @param entity
|
||||
/// @return
|
||||
bool removeFromScene(EntityId entity);
|
||||
|
||||
/// @brief
|
||||
/// @param entity
|
||||
/// @return
|
||||
bool addToScene(EntityId entity);
|
||||
|
||||
/// @brief
|
||||
/// @param entity
|
||||
/// @param onCollisionCallback
|
||||
/// @param affectsCollidingTransform
|
||||
void addCollisionComponent(EntityId entity, void (*onCollisionCallback)(const EntityId entityId1, const EntityId entityId2), bool affectsCollidingTransform);
|
||||
|
||||
/// @brief
|
||||
/// @param entityId
|
||||
///
|
||||
///
|
||||
void removeCollisionComponent(EntityId entityId);
|
||||
|
||||
/// @brief
|
||||
/// @param entity
|
||||
void testCollisions(EntityId entity);
|
||||
|
||||
/// @brief returns the number of instances of the FilamentAsset represented by the given entity.
|
||||
/// @param entityId
|
||||
/// @return the number of instances
|
||||
int getInstanceCount(EntityId entityId);
|
||||
|
||||
/// @brief returns an array containing all instances of the FilamentAsset represented by the given entity.
|
||||
/// @param entityId
|
||||
void getInstances(EntityId entityId, EntityId *out);
|
||||
|
||||
///
|
||||
/// Sets the draw priority for the given entity. See RenderableManager.h for more details.
|
||||
///
|
||||
void setPriority(EntityId entity, int priority);
|
||||
|
||||
/// @brief returns the 2D min/max viewport coordinates of the bounding box for the specified enitty;
|
||||
/// @param out a pointer large enough to store four floats (the min/max coordinates of the bounding box)
|
||||
/// @return
|
||||
///
|
||||
Aabb2 getScreenSpaceBoundingBox(View *view, EntityId entity);
|
||||
|
||||
/// @brief returns the 3D bounding box of the renderable instance for the given entity.
|
||||
/// @return the bounding box
|
||||
///
|
||||
Aabb3 getRenderableBoundingBox(EntityId entity);
|
||||
|
||||
///
|
||||
/// Creates an entity with the specified geometry/material/normals and adds to the scene.
|
||||
/// If [keepData] is true, stores
|
||||
///
|
||||
SceneAsset *createGeometry(
|
||||
float *vertices,
|
||||
uint32_t numVertices,
|
||||
float *normals,
|
||||
uint32_t numNormals,
|
||||
float *uvs,
|
||||
uint32_t numUvs,
|
||||
uint16_t *indices,
|
||||
uint32_t numIndices,
|
||||
filament::RenderableManager::PrimitiveType primitiveType = RenderableManager::PrimitiveType::TRIANGLES,
|
||||
MaterialInstance **materialInstances = nullptr,
|
||||
size_t materialInstanceCount = 0,
|
||||
bool keepData = false);
|
||||
|
||||
|
||||
gltfio::MaterialProvider *const getUnlitMaterialProvider()
|
||||
{
|
||||
return _unlitMaterialProvider;
|
||||
}
|
||||
|
||||
gltfio::MaterialProvider *const getUbershaderMaterialProvider()
|
||||
{
|
||||
return _ubershaderProvider;
|
||||
}
|
||||
|
||||
/// @brief
|
||||
/// @param materialInstance
|
||||
void destroy(MaterialInstance *materialInstance);
|
||||
|
||||
/// @brief
|
||||
/// @return
|
||||
MaterialInstance *createUnlitFixedSizeMaterialInstance();
|
||||
|
||||
/// @brief
|
||||
/// @return
|
||||
MaterialInstance *createUnlitMaterialInstance();
|
||||
|
||||
/// @brief
|
||||
/// @param entityId
|
||||
/// @param layer
|
||||
void setVisibilityLayer(EntityId entityId, int layer);
|
||||
|
||||
/// @brief
|
||||
/// @return
|
||||
Camera *createCamera();
|
||||
|
||||
/// @brief
|
||||
/// @param camera
|
||||
void destroyCamera(Camera *camera);
|
||||
|
||||
/// @brief
|
||||
/// @return
|
||||
size_t getCameraCount();
|
||||
|
||||
/// @brief
|
||||
/// @param index
|
||||
/// @return
|
||||
Camera *getCameraAt(size_t index);
|
||||
|
||||
/// @brief
|
||||
/// @param view
|
||||
/// @param scene
|
||||
/// @return
|
||||
Gizmo *createGizmo(View *view, Scene *scene);
|
||||
|
||||
|
||||
/// @brief
|
||||
/// @return
|
||||
Scene *getScene()
|
||||
{
|
||||
return _scene;
|
||||
}
|
||||
|
||||
/// @brief
|
||||
/// @return
|
||||
AnimationManager *getAnimationManager() {
|
||||
return _animationManager.get();
|
||||
}
|
||||
|
||||
/// @brief
|
||||
/// @return
|
||||
NameComponentManager *getNameComponentManager() {
|
||||
return _ncm;
|
||||
}
|
||||
|
||||
Entity getOverlayEntity(size_t index) {
|
||||
if(index == 0) {
|
||||
return _gridOverlay->grid();
|
||||
} else if(index == 1) {
|
||||
return _gridOverlay->sphere();
|
||||
}
|
||||
}
|
||||
|
||||
size_t getOverlayEntityCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
gltfio::AssetLoader *_assetLoader = nullptr;
|
||||
const ResourceLoaderWrapperImpl *const _resourceLoaderWrapper;
|
||||
Engine *_engine = nullptr;
|
||||
Scene *_scene = nullptr;
|
||||
Camera *_mainCamera;
|
||||
|
||||
gltfio::MaterialKey _defaultUnlitConfig;
|
||||
|
||||
gltfio::MaterialProvider *_ubershaderProvider = nullptr;
|
||||
gltfio::MaterialProvider *_unlitMaterialProvider = nullptr;
|
||||
gltfio::ResourceLoader *_gltfResourceLoader = nullptr;
|
||||
gltfio::TextureProvider *_stbDecoder = nullptr;
|
||||
gltfio::TextureProvider *_ktxDecoder = nullptr;
|
||||
std::mutex _mutex;
|
||||
std::vector<MaterialInstance *> _materialInstances;
|
||||
|
||||
Material *_unlitFixedSizeMaterial = nullptr;
|
||||
|
||||
utils::NameComponentManager *_ncm;
|
||||
|
||||
tsl::robin_map<EntityId, math::mat4> _transformUpdates;
|
||||
std::set<Texture *> _textures;
|
||||
std::vector<Camera *> _cameras;
|
||||
std::vector<std::unique_ptr<SceneAsset>> _sceneAssets;
|
||||
std::vector<std::unique_ptr<Gizmo>> _gizmos;
|
||||
|
||||
std::unique_ptr<AnimationManager> _animationManager = std::nullptr_t();
|
||||
std::unique_ptr<CollisionComponentManager> _collisionComponentManager = std::nullptr_t();
|
||||
|
||||
GridOverlay *_gridOverlay = std::nullptr_t();
|
||||
|
||||
void _updateTransforms();
|
||||
};
|
||||
}
|
||||
@@ -120,7 +120,8 @@ namespace thermion
|
||||
static constexpr filament::math::float4 sFullScreenTriangleVertices[3] = {
|
||||
{-1.0f, -1.0f, 1.0f, 1.0f},
|
||||
{3.0f, -1.0f, 1.0f, 1.0f},
|
||||
{-1.0f, 3.0f, 1.0f, 1.0f}};
|
||||
{-1.0f, 3.0f, 1.0f, 1.0f}
|
||||
};
|
||||
|
||||
static const uint16_t sFullScreenTriangleIndices[3] = {0, 1, 2};
|
||||
|
||||
@@ -705,8 +706,8 @@ namespace thermion
|
||||
.width(width)
|
||||
.height(height)
|
||||
.levels(1)
|
||||
.usage(filament::Texture::Usage::DEPTH_ATTACHMENT | filament::Texture::Usage::SAMPLEABLE)
|
||||
.format(filament::Texture::InternalFormat::DEPTH32F)
|
||||
.usage(filament::Texture::Usage::DEPTH_ATTACHMENT | filament::Texture::Usage::STENCIL_ATTACHMENT | filament::Texture::Usage::SAMPLEABLE)
|
||||
.format(filament::Texture::InternalFormat::DEPTH24_STENCIL8)
|
||||
.build(*_engine);
|
||||
auto rt = filament::RenderTarget::Builder()
|
||||
.texture(RenderTarget::AttachmentPoint::COLOR, rtColor)
|
||||
@@ -767,6 +768,9 @@ namespace thermion
|
||||
view->setStencilBufferEnabled(true);
|
||||
view->setAmbientOcclusionOptions({.enabled = false});
|
||||
view->setDynamicResolutionOptions({.enabled = false});
|
||||
ACESToneMapper tm;
|
||||
auto colorGrading = ColorGrading::Builder().toneMapper(&tm).build(*_engine);
|
||||
view->setColorGrading(colorGrading);
|
||||
#if defined(_WIN32)
|
||||
view->setStereoscopicOptions({.enabled = false});
|
||||
#endif
|
||||
@@ -797,25 +801,6 @@ namespace thermion
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// @brief
|
||||
///
|
||||
///
|
||||
void FilamentViewer::clearEntities()
|
||||
{
|
||||
_sceneManager->destroyAll();
|
||||
}
|
||||
|
||||
/// @brief
|
||||
/// @param asset
|
||||
///
|
||||
void FilamentViewer::removeEntity(EntityId asset)
|
||||
{
|
||||
_renderMutex.lock();
|
||||
// todo - what if we are using a camera from this asset?
|
||||
_sceneManager->remove(asset);
|
||||
_renderMutex.unlock();
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
@@ -1046,8 +1031,7 @@ namespace thermion
|
||||
uint64_t frameTimeInNanos)
|
||||
{
|
||||
|
||||
_sceneManager->updateTransforms();
|
||||
_sceneManager->updateAnimations();
|
||||
_sceneManager->update();
|
||||
|
||||
for(auto swapChain : _swapChains) {
|
||||
auto views = _renderable[swapChain];
|
||||
@@ -1091,7 +1075,6 @@ namespace thermion
|
||||
}
|
||||
};
|
||||
|
||||
// Create a fence
|
||||
Fence *fence = nullptr;
|
||||
if (useFence)
|
||||
{
|
||||
@@ -1127,7 +1110,7 @@ namespace thermion
|
||||
{
|
||||
|
||||
if(swapChain && !_engine->isValid(swapChain)) {
|
||||
Log("SWAPCHAIN PROVIDED BUT NOT VALID");
|
||||
Log("SwapChain exists, but is not valid");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1191,21 +1174,9 @@ namespace thermion
|
||||
return _engine->getCameraComponent(Entity::import(entity));
|
||||
}
|
||||
|
||||
bool FilamentViewer::isNonPickableEntity(EntityId entityId) {
|
||||
auto renderable = Entity::import(entityId);
|
||||
return _sceneManager->isGizmoEntity(renderable) || renderable == _imageEntity || renderable == _sceneManager->_gridOverlay->sphere() || _sceneManager->_gridOverlay->grid();
|
||||
}
|
||||
|
||||
void FilamentViewer::pick(View *view, uint32_t x, uint32_t y, PickCallback callback)
|
||||
{
|
||||
view->pick(x, y, [=](filament::View::PickingQueryResult const &result) {
|
||||
callback(Entity::smuggle(result.renderable), x, y, view, result.depth, result.fragCoords.x, result.fragCoords.y, result.fragCoords.z);
|
||||
});
|
||||
}
|
||||
|
||||
void FilamentViewer::unprojectTexture(EntityId entityId, uint8_t *input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight)
|
||||
{
|
||||
const auto *geometry = _sceneManager->getGeometry(entityId);
|
||||
// const auto *geometry = _sceneManager->getGeometry(entityId);
|
||||
// if (!geometry->uvs)
|
||||
// {
|
||||
// Log("No UVS");
|
||||
|
||||
@@ -1,345 +0,0 @@
|
||||
#include "Gizmo.hpp"
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <utils/Entity.h>
|
||||
#include <utils/EntityManager.h>
|
||||
#include <filament/RenderableManager.h>
|
||||
#include <filament/TransformManager.h>
|
||||
#include <gltfio/math.h>
|
||||
#include "SceneManager.hpp"
|
||||
#include "material/unlit_fixed_size.h"
|
||||
#include "Log.hpp"
|
||||
|
||||
namespace thermion {
|
||||
|
||||
using namespace filament::gltfio;
|
||||
|
||||
Gizmo::Gizmo(Engine *engine, View *view, Scene* scene, Material* material) : _engine(engine), _view(view), _scene(scene), _material(material)
|
||||
{
|
||||
|
||||
auto &entityManager = EntityManager::get();
|
||||
|
||||
auto &transformManager = _engine->getTransformManager();
|
||||
|
||||
// First, create the black cube at the center
|
||||
// The axes widgets will be parented to this entity
|
||||
_entities[3] = entityManager.create();
|
||||
|
||||
_materialInstances[3] = _material->createInstance();
|
||||
_materialInstances[3]->setParameter("baseColorFactor", math::float4{0.0f, 0.0f, 0.0f, 1.0f}); // Black color
|
||||
|
||||
// Create center cube vertices
|
||||
float centerCubeSize = 0.01f;
|
||||
float *centerCubeVertices = new float[8 * 3]{
|
||||
-centerCubeSize, -centerCubeSize, -centerCubeSize,
|
||||
centerCubeSize, -centerCubeSize, -centerCubeSize,
|
||||
centerCubeSize, centerCubeSize, -centerCubeSize,
|
||||
-centerCubeSize, centerCubeSize, -centerCubeSize,
|
||||
-centerCubeSize, -centerCubeSize, centerCubeSize,
|
||||
centerCubeSize, -centerCubeSize, centerCubeSize,
|
||||
centerCubeSize, centerCubeSize, centerCubeSize,
|
||||
-centerCubeSize, centerCubeSize, centerCubeSize};
|
||||
|
||||
// Create center cube indices
|
||||
uint16_t *centerCubeIndices = new uint16_t[36]{
|
||||
0, 1, 2, 2, 3, 0,
|
||||
1, 5, 6, 6, 2, 1,
|
||||
5, 4, 7, 7, 6, 5,
|
||||
4, 0, 3, 3, 7, 4,
|
||||
3, 2, 6, 6, 7, 3,
|
||||
4, 5, 1, 1, 0, 4};
|
||||
|
||||
auto centerCubeVb = VertexBuffer::Builder()
|
||||
.vertexCount(8)
|
||||
.bufferCount(1)
|
||||
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3)
|
||||
.build(*engine);
|
||||
|
||||
centerCubeVb->setBufferAt(*engine, 0, VertexBuffer::BufferDescriptor(centerCubeVertices, 8 * sizeof(filament::math::float3), [](void *buffer, size_t size, void *)
|
||||
{ delete[] static_cast<float *>(buffer); }));
|
||||
|
||||
auto centerCubeIb = IndexBuffer::Builder().indexCount(36).bufferType(IndexBuffer::IndexType::USHORT).build(*engine);
|
||||
centerCubeIb->setBuffer(*engine, IndexBuffer::BufferDescriptor(
|
||||
centerCubeIndices, 36 * sizeof(uint16_t),
|
||||
[](void *buffer, size_t size, void *)
|
||||
{ delete[] static_cast<uint16_t *>(buffer); }));
|
||||
|
||||
RenderableManager::Builder(1)
|
||||
.boundingBox({{-centerCubeSize, -centerCubeSize, -centerCubeSize},
|
||||
{centerCubeSize, centerCubeSize, centerCubeSize}})
|
||||
.material(0, _materialInstances[3])
|
||||
.layerMask(0xFF, 1u << SceneManager::LAYERS::OVERLAY)
|
||||
.priority(7)
|
||||
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, centerCubeVb, centerCubeIb, 0, 36)
|
||||
.culling(false)
|
||||
.build(*engine, _entities[3]);
|
||||
|
||||
auto cubeTransformInstance = transformManager.getInstance(_entities[3]);
|
||||
math::mat4f cubeTransform;
|
||||
transformManager.setTransform(cubeTransformInstance, cubeTransform);
|
||||
|
||||
// Line and arrow vertices
|
||||
float lineLength = 0.6f;
|
||||
float lineWidth = 0.004f;
|
||||
float arrowLength = 0.06f;
|
||||
float arrowWidth = 0.02f;
|
||||
float *vertices = new float[13 * 3]{
|
||||
// Line vertices (8 vertices)
|
||||
-lineWidth, -lineWidth, 0.0f,
|
||||
lineWidth, -lineWidth, 0.0f,
|
||||
lineWidth, lineWidth, 0.0f,
|
||||
-lineWidth, lineWidth, 0.0f,
|
||||
-lineWidth, -lineWidth, lineLength,
|
||||
lineWidth, -lineWidth, lineLength,
|
||||
lineWidth, lineWidth, lineLength,
|
||||
-lineWidth, lineWidth, lineLength,
|
||||
// Arrow vertices (5 vertices)
|
||||
0.0f, 0.0f, lineLength + arrowLength, // Tip of the arrow
|
||||
-arrowWidth, -arrowWidth, lineLength, // Base of the arrow
|
||||
arrowWidth, -arrowWidth, lineLength,
|
||||
arrowWidth, arrowWidth, lineLength,
|
||||
-arrowWidth, arrowWidth, lineLength};
|
||||
|
||||
// Line and arrow indices
|
||||
uint16_t *indices = new uint16_t[54]{
|
||||
// Line indices (24 indices)
|
||||
0, 1, 5, 5, 4, 0,
|
||||
1, 2, 6, 6, 5, 1,
|
||||
2, 3, 7, 7, 6, 2,
|
||||
3, 0, 4, 4, 7, 3,
|
||||
// Arrow indices (30 indices)
|
||||
8, 9, 10, // Front face
|
||||
8, 10, 11, // Right face
|
||||
8, 11, 12, // Back face
|
||||
8, 12, 9, // Left face
|
||||
9, 12, 11, 11, 10, 9 // Base of the arrow
|
||||
};
|
||||
|
||||
auto vb = VertexBuffer::Builder()
|
||||
.vertexCount(13)
|
||||
.bufferCount(1)
|
||||
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3)
|
||||
.build(*engine);
|
||||
|
||||
vb->setBufferAt(*engine, 0, VertexBuffer::BufferDescriptor(vertices, 13 * sizeof(filament::math::float3), [](void *buffer, size_t size, void *)
|
||||
{ delete[] static_cast<float *>(buffer); }));
|
||||
|
||||
auto ib = IndexBuffer::Builder().indexCount(54).bufferType(IndexBuffer::IndexType::USHORT).build(*engine);
|
||||
ib->setBuffer(*engine, IndexBuffer::BufferDescriptor(
|
||||
indices, 54 * sizeof(uint16_t),
|
||||
[](void *buffer, size_t size, void *)
|
||||
{ delete[] static_cast<uint16_t *>(buffer); }));
|
||||
|
||||
// Create the three axes
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
_entities[i] = entityManager.create();
|
||||
_materialInstances[i] = _material->createInstance();
|
||||
|
||||
auto baseColor = inactiveColors[i];
|
||||
|
||||
math::mat4f transform;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case Axis::X:
|
||||
// _materialInstances[i]->setParameter("axisDirection", math::float3 { 1.0f, 0.0f, 0.0f});
|
||||
transform = math::mat4f::rotation(math::F_PI_2, math::float3{0, 1, 0});
|
||||
break;
|
||||
case 1:
|
||||
// _materialInstances[i]->setParameter("axisDirection", math::float3 { 0.0f, 1.0f, 0.0f});
|
||||
transform = math::mat4f::rotation(-math::F_PI_2, math::float3{1, 0, 0});
|
||||
break;
|
||||
case 2:
|
||||
// _materialInstances[i]->setParameter("axisDirection", math::float3 { 0.0f, 0.0f, 1.0f});
|
||||
break;
|
||||
}
|
||||
|
||||
_materialInstances[i]->setParameter("baseColorFactor", baseColor);
|
||||
|
||||
RenderableManager::Builder(1)
|
||||
.boundingBox({{-arrowWidth, -arrowWidth, 0},
|
||||
{arrowWidth, arrowWidth, lineLength + arrowLength}})
|
||||
.material(0, _materialInstances[i])
|
||||
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, vb, ib, 0, 54)
|
||||
.priority(6)
|
||||
.layerMask(0xFF, 1u << SceneManager::LAYERS::OVERLAY)
|
||||
.culling(false)
|
||||
.receiveShadows(false)
|
||||
.castShadows(false)
|
||||
.build(*engine, _entities[i]);
|
||||
|
||||
|
||||
auto instance = transformManager.getInstance(_entities[i]);
|
||||
transformManager.setTransform(instance, transform);
|
||||
|
||||
// parent the axis to the center cube
|
||||
transformManager.setParent(instance, cubeTransformInstance);
|
||||
|
||||
}
|
||||
|
||||
createTransparentRectangles();
|
||||
}
|
||||
|
||||
Gizmo::~Gizmo() {
|
||||
_scene->removeEntities(_entities, 7);
|
||||
|
||||
for(int i = 0; i < 7; i++) {
|
||||
_engine->destroy(_entities[i]);
|
||||
}
|
||||
|
||||
for(int i = 0; i < 7; i++) {
|
||||
_engine->destroy(_materialInstances[i]);
|
||||
}
|
||||
|
||||
_engine->destroy(_material);
|
||||
|
||||
}
|
||||
|
||||
void Gizmo::createTransparentRectangles()
|
||||
{
|
||||
auto &entityManager = EntityManager::get();
|
||||
auto &transformManager = _engine->getTransformManager();
|
||||
|
||||
float volumeWidth = 0.2f;
|
||||
float volumeLength = 1.2f;
|
||||
float volumeDepth = 0.2f;
|
||||
|
||||
float *volumeVertices = new float[8 * 3]{
|
||||
-volumeWidth / 2, -volumeDepth / 2, 0,
|
||||
volumeWidth / 2, -volumeDepth / 2, 0,
|
||||
volumeWidth / 2, -volumeDepth / 2, volumeLength,
|
||||
-volumeWidth / 2, -volumeDepth / 2, volumeLength,
|
||||
-volumeWidth / 2, volumeDepth / 2, 0,
|
||||
volumeWidth / 2, volumeDepth / 2, 0,
|
||||
volumeWidth / 2, volumeDepth / 2, volumeLength,
|
||||
-volumeWidth / 2, volumeDepth / 2, volumeLength
|
||||
};
|
||||
|
||||
uint16_t *volumeIndices = new uint16_t[36]{
|
||||
0, 1, 2, 2, 3, 0, // Bottom face
|
||||
4, 5, 6, 6, 7, 4, // Top face
|
||||
0, 4, 7, 7, 3, 0, // Left face
|
||||
1, 5, 6, 6, 2, 1, // Right face
|
||||
0, 1, 5, 5, 4, 0, // Front face
|
||||
3, 2, 6, 6, 7, 3 // Back face
|
||||
};
|
||||
|
||||
auto volumeVb = VertexBuffer::Builder()
|
||||
.vertexCount(8)
|
||||
.bufferCount(1)
|
||||
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3)
|
||||
.build(*_engine);
|
||||
|
||||
volumeVb->setBufferAt(*_engine, 0, VertexBuffer::BufferDescriptor(
|
||||
volumeVertices, 8 * sizeof(filament::math::float3),
|
||||
[](void *buffer, size_t size, void *) { delete[] static_cast<float *>(buffer); }
|
||||
));
|
||||
|
||||
auto volumeIb = IndexBuffer::Builder()
|
||||
.indexCount(36)
|
||||
.bufferType(IndexBuffer::IndexType::USHORT)
|
||||
.build(*_engine);
|
||||
|
||||
volumeIb->setBuffer(*_engine, IndexBuffer::BufferDescriptor(
|
||||
volumeIndices, 36 * sizeof(uint16_t),
|
||||
[](void *buffer, size_t size, void *) { delete[] static_cast<uint16_t *>(buffer); }
|
||||
));
|
||||
|
||||
for (int i = 4; i < 7; i++)
|
||||
{
|
||||
_entities[i] = entityManager.create();
|
||||
_materialInstances[i] = _material->createInstance();
|
||||
|
||||
_materialInstances[i]->setParameter("color", math::float4{0.0f, 0.0f, 0.0f, 0.0f});
|
||||
|
||||
math::mat4f transform;
|
||||
switch (i-4)
|
||||
{
|
||||
case Axis::X:
|
||||
transform = math::mat4f::rotation(math::F_PI_2, math::float3{0, 1, 0});
|
||||
break;
|
||||
case Axis::Y:
|
||||
transform = math::mat4f::rotation(-math::F_PI_2, math::float3{1, 0, 0});
|
||||
break;
|
||||
case Axis::Z:
|
||||
break;
|
||||
}
|
||||
|
||||
RenderableManager::Builder(1)
|
||||
.boundingBox({{-volumeWidth / 2, -volumeDepth / 2, 0}, {volumeWidth / 2, volumeDepth / 2, volumeLength}})
|
||||
.material(0, _materialInstances[i])
|
||||
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, volumeVb, volumeIb, 0, 36)
|
||||
.priority(7)
|
||||
.layerMask(0xFF, 1u << SceneManager::LAYERS::OVERLAY)
|
||||
.culling(false)
|
||||
.receiveShadows(false)
|
||||
.castShadows(false)
|
||||
.build(*_engine, _entities[i]);
|
||||
|
||||
auto instance = transformManager.getInstance(_entities[i]);
|
||||
transformManager.setTransform(instance, transform);
|
||||
|
||||
// Parent the picking volume to the center cube
|
||||
transformManager.setParent(instance, transformManager.getInstance(_entities[3]));
|
||||
}
|
||||
}
|
||||
|
||||
void Gizmo::highlight(Entity entity) {
|
||||
auto &rm = _engine->getRenderableManager();
|
||||
auto renderableInstance = rm.getInstance(entity);
|
||||
auto materialInstance = rm.getMaterialInstanceAt(renderableInstance, 0);
|
||||
|
||||
math::float4 baseColor;
|
||||
if(entity == x()) {
|
||||
baseColor = activeColors[Axis::X];
|
||||
} else if(entity == y()) {
|
||||
baseColor = activeColors[Axis::Y];
|
||||
} else if(entity == z()) {
|
||||
baseColor = activeColors[Axis::Z];
|
||||
} else {
|
||||
baseColor = math::float4 { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
}
|
||||
|
||||
materialInstance->setParameter("color", baseColor);
|
||||
|
||||
}
|
||||
|
||||
void Gizmo::unhighlight() {
|
||||
auto &rm = _engine->getRenderableManager();
|
||||
|
||||
for(int i = 0; i < 3; i++) {
|
||||
auto renderableInstance = rm.getInstance(_entities[i]);
|
||||
auto materialInstance = rm.getMaterialInstanceAt(renderableInstance, 0);
|
||||
|
||||
math::float4 baseColor = inactiveColors[i];
|
||||
materialInstance->setParameter("color", baseColor);
|
||||
}
|
||||
}
|
||||
|
||||
void Gizmo::pick(uint32_t x, uint32_t y, PickCallback callback)
|
||||
{
|
||||
auto handler = new Gizmo::PickCallbackHandler(this, callback);
|
||||
_view->pick(x, y, [=](filament::View::PickingQueryResult const &result) {
|
||||
handler->handle(result);
|
||||
});
|
||||
}
|
||||
|
||||
bool Gizmo::isGizmoEntity(Entity e) {
|
||||
for(int i = 0; i < 7; i++) {
|
||||
if(e == _entities[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Gizmo::setVisibility(bool visible) {
|
||||
if(visible) {
|
||||
_scene->addEntities(_entities, 7);
|
||||
} else {
|
||||
_scene->removeEntities(_entities, 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <cmath>
|
||||
#endif
|
||||
|
||||
#include "GridOverlay.hpp"
|
||||
#include "scene/GridOverlay.hpp"
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <utils/Entity.h>
|
||||
@@ -13,190 +13,190 @@
|
||||
#include <gltfio/math.h>
|
||||
|
||||
#include "material/grid.h"
|
||||
#include "SceneManager.hpp"
|
||||
#include "scene/SceneManager.hpp"
|
||||
#include "Log.hpp"
|
||||
|
||||
namespace thermion {
|
||||
|
||||
using namespace filament::gltfio;
|
||||
|
||||
GridOverlay::GridOverlay(Engine &engine) : _engine(engine)
|
||||
namespace thermion
|
||||
{
|
||||
auto &entityManager = EntityManager::get();
|
||||
auto &transformManager = engine.getTransformManager();
|
||||
|
||||
const int gridSize = 100;
|
||||
const float gridSpacing = 1.0f;
|
||||
int vertexCount = (gridSize + 1) * 4; // 2 axes, 2 vertices per line
|
||||
using namespace filament::gltfio;
|
||||
|
||||
float* gridVertices = new float[vertexCount * 3];
|
||||
int index = 0;
|
||||
GridOverlay::GridOverlay(Engine &engine) : _engine(engine)
|
||||
{
|
||||
auto &entityManager = EntityManager::get();
|
||||
auto &transformManager = engine.getTransformManager();
|
||||
|
||||
// Create grid lines
|
||||
for (int i = 0; i <= gridSize; ++i) {
|
||||
float pos = i * gridSpacing - (gridSize * gridSpacing / 2);
|
||||
const int gridSize = 100;
|
||||
const float gridSpacing = 1.0f;
|
||||
int vertexCount = (gridSize + 1) * 4; // 2 axes, 2 vertices per line
|
||||
|
||||
// X-axis lines
|
||||
gridVertices[index++] = pos;
|
||||
gridVertices[index++] = 0;
|
||||
gridVertices[index++] = -(gridSize * gridSpacing / 2);
|
||||
float *gridVertices = new float[vertexCount * 3];
|
||||
int index = 0;
|
||||
|
||||
gridVertices[index++] = pos;
|
||||
gridVertices[index++] = 0;
|
||||
gridVertices[index++] = (gridSize * gridSpacing / 2);
|
||||
// Create grid lines
|
||||
for (int i = 0; i <= gridSize; ++i)
|
||||
{
|
||||
float pos = i * gridSpacing - (gridSize * gridSpacing / 2);
|
||||
|
||||
// Z-axis lines
|
||||
gridVertices[index++] = -(gridSize * gridSpacing / 2);
|
||||
gridVertices[index++] = 0;
|
||||
gridVertices[index++] = pos;
|
||||
// X-axis lines
|
||||
gridVertices[index++] = pos;
|
||||
gridVertices[index++] = 0;
|
||||
gridVertices[index++] = -(gridSize * gridSpacing / 2);
|
||||
|
||||
gridVertices[index++] = (gridSize * gridSpacing / 2);
|
||||
gridVertices[index++] = 0;
|
||||
gridVertices[index++] = pos;
|
||||
gridVertices[index++] = pos;
|
||||
gridVertices[index++] = 0;
|
||||
gridVertices[index++] = (gridSize * gridSpacing / 2);
|
||||
|
||||
// Z-axis lines
|
||||
gridVertices[index++] = -(gridSize * gridSpacing / 2);
|
||||
gridVertices[index++] = 0;
|
||||
gridVertices[index++] = pos;
|
||||
|
||||
gridVertices[index++] = (gridSize * gridSpacing / 2);
|
||||
gridVertices[index++] = 0;
|
||||
gridVertices[index++] = pos;
|
||||
}
|
||||
|
||||
auto vb = VertexBuffer::Builder()
|
||||
.vertexCount(vertexCount)
|
||||
.bufferCount(1)
|
||||
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3)
|
||||
.build(engine);
|
||||
|
||||
vb->setBufferAt(engine, 0, VertexBuffer::BufferDescriptor(gridVertices, vertexCount * sizeof(filament::math::float3), [](void *buffer, size_t size, void *)
|
||||
{ delete[] static_cast<float *>(buffer); }));
|
||||
|
||||
uint32_t *gridIndices = new uint32_t[vertexCount];
|
||||
for (uint32_t i = 0; i < vertexCount; ++i)
|
||||
{
|
||||
gridIndices[i] = i;
|
||||
}
|
||||
|
||||
auto ib = IndexBuffer::Builder()
|
||||
.indexCount(vertexCount)
|
||||
.bufferType(IndexBuffer::IndexType::UINT)
|
||||
.build(engine);
|
||||
|
||||
ib->setBuffer(engine, IndexBuffer::BufferDescriptor(
|
||||
gridIndices, vertexCount * sizeof(uint32_t),
|
||||
[](void *buffer, size_t size, void *)
|
||||
{ delete[] static_cast<uint32_t *>(buffer); }));
|
||||
|
||||
_gridEntity = entityManager.create();
|
||||
_material = Material::Builder()
|
||||
.package(GRID_PACKAGE, GRID_GRID_SIZE)
|
||||
.build(engine);
|
||||
|
||||
_materialInstance = _material->createInstance();
|
||||
|
||||
_materialInstance->setParameter("maxDistance", 50.0f); // Adjust as needed
|
||||
_materialInstance->setParameter("color", math::float3{0.5f, 0.5f, 0.5f}); // Gray color for the grid
|
||||
|
||||
RenderableManager::Builder(1)
|
||||
.boundingBox({{-gridSize * gridSpacing / 2, 0, -gridSize * gridSpacing / 2},
|
||||
{gridSize * gridSpacing / 2, 0, gridSize * gridSpacing / 2}})
|
||||
.material(0, _materialInstance)
|
||||
.geometry(0, RenderableManager::PrimitiveType::LINES, vb, ib, 0, vertexCount)
|
||||
.priority(0)
|
||||
.layerMask(0xFF, 1u << SceneManager::LAYERS::OVERLAY)
|
||||
.culling(true)
|
||||
.receiveShadows(false)
|
||||
.castShadows(false)
|
||||
.build(engine, _gridEntity);
|
||||
const float sphereRadius = 0.05f;
|
||||
const int sphereSegments = 16;
|
||||
const int sphereRings = 16;
|
||||
|
||||
vertexCount = (sphereRings + 1) * (sphereSegments + 1);
|
||||
int indexCount = sphereRings * sphereSegments * 6;
|
||||
|
||||
math::float3 *vertices = new math::float3[vertexCount];
|
||||
uint32_t *indices = new uint32_t[indexCount];
|
||||
|
||||
int vertexIndex = 0;
|
||||
// Generate sphere vertices
|
||||
for (int ring = 0; ring <= sphereRings; ++ring)
|
||||
{
|
||||
float theta = ring * M_PI / sphereRings;
|
||||
float sinTheta = std::sin(theta);
|
||||
float cosTheta = std::cos(theta);
|
||||
|
||||
for (int segment = 0; segment <= sphereSegments; ++segment)
|
||||
{
|
||||
float phi = segment * 2 * M_PI / sphereSegments;
|
||||
float sinPhi = std::sin(phi);
|
||||
float cosPhi = std::cos(phi);
|
||||
|
||||
float x = cosPhi * sinTheta;
|
||||
float y = cosTheta;
|
||||
float z = sinPhi * sinTheta;
|
||||
|
||||
vertices[vertexIndex++] = {x * sphereRadius, y * sphereRadius, z * sphereRadius};
|
||||
}
|
||||
}
|
||||
|
||||
int indexIndex = 0;
|
||||
// Generate sphere indices
|
||||
for (int ring = 0; ring < sphereRings; ++ring)
|
||||
{
|
||||
for (int segment = 0; segment < sphereSegments; ++segment)
|
||||
{
|
||||
uint32_t current = ring * (sphereSegments + 1) + segment;
|
||||
uint32_t next = current + sphereSegments + 1;
|
||||
|
||||
indices[indexIndex++] = current;
|
||||
indices[indexIndex++] = next;
|
||||
indices[indexIndex++] = current + 1;
|
||||
|
||||
indices[indexIndex++] = current + 1;
|
||||
indices[indexIndex++] = next;
|
||||
indices[indexIndex++] = next + 1;
|
||||
}
|
||||
}
|
||||
|
||||
auto sphereVb = VertexBuffer::Builder()
|
||||
.vertexCount(vertexCount)
|
||||
.bufferCount(1)
|
||||
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3)
|
||||
.build(engine);
|
||||
|
||||
sphereVb->setBufferAt(engine, 0, VertexBuffer::BufferDescriptor(vertices, vertexCount * sizeof(math::float3), [](void *buffer, size_t size, void *)
|
||||
{ delete[] static_cast<math::float3 *>(buffer); }));
|
||||
|
||||
auto sphereIb = IndexBuffer::Builder()
|
||||
.indexCount(indexCount)
|
||||
.bufferType(IndexBuffer::IndexType::UINT)
|
||||
.build(engine);
|
||||
|
||||
sphereIb->setBuffer(engine, IndexBuffer::BufferDescriptor(
|
||||
indices, indexCount * sizeof(uint32_t),
|
||||
[](void *buffer, size_t size, void *)
|
||||
{ delete[] static_cast<uint32_t *>(buffer); }));
|
||||
|
||||
_sphereEntity = entityManager.create();
|
||||
|
||||
RenderableManager::Builder(1)
|
||||
.boundingBox({{-sphereRadius, -sphereRadius, -sphereRadius},
|
||||
{sphereRadius, sphereRadius, sphereRadius}})
|
||||
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, sphereVb, sphereIb, 0, indexCount)
|
||||
.priority(0)
|
||||
.layerMask(0xFF, 1u << SceneManager::LAYERS::OVERLAY)
|
||||
.culling(true)
|
||||
.receiveShadows(false)
|
||||
.castShadows(false)
|
||||
.build(engine, _sphereEntity);
|
||||
}
|
||||
|
||||
auto vb = VertexBuffer::Builder()
|
||||
.vertexCount(vertexCount)
|
||||
.bufferCount(1)
|
||||
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3)
|
||||
.build(engine);
|
||||
|
||||
vb->setBufferAt(engine, 0, VertexBuffer::BufferDescriptor(
|
||||
gridVertices, vertexCount * sizeof(filament::math::float3),
|
||||
[](void* buffer, size_t size, void*) { delete[] static_cast<float*>(buffer); }
|
||||
));
|
||||
|
||||
uint32_t* gridIndices = new uint32_t[vertexCount];
|
||||
for (uint32_t i = 0; i < vertexCount; ++i) {
|
||||
gridIndices[i] = i;
|
||||
void GridOverlay::destroy()
|
||||
{
|
||||
auto &rm = _engine.getRenderableManager();
|
||||
auto &tm = _engine.getTransformManager();
|
||||
rm.destroy(_sphereEntity);
|
||||
rm.destroy(_gridEntity);
|
||||
tm.destroy(_sphereEntity);
|
||||
tm.destroy(_gridEntity);
|
||||
_engine.destroy(_sphereEntity);
|
||||
_engine.destroy(_gridEntity);
|
||||
}
|
||||
|
||||
auto ib = IndexBuffer::Builder()
|
||||
.indexCount(vertexCount)
|
||||
.bufferType(IndexBuffer::IndexType::UINT)
|
||||
.build(engine);
|
||||
|
||||
ib->setBuffer(engine, IndexBuffer::BufferDescriptor(
|
||||
gridIndices, vertexCount * sizeof(uint32_t),
|
||||
[](void* buffer, size_t size, void*) { delete[] static_cast<uint32_t*>(buffer); }
|
||||
));
|
||||
|
||||
_gridEntity = entityManager.create();
|
||||
_material = Material::Builder()
|
||||
.package(GRID_PACKAGE, GRID_GRID_SIZE)
|
||||
.build(engine);
|
||||
|
||||
_materialInstance = _material->createInstance();
|
||||
|
||||
_materialInstance->setParameter("maxDistance", 50.0f); // Adjust as needed
|
||||
_materialInstance->setParameter("color", math::float3{0.5f, 0.5f, 0.5f}); // Gray color for the grid
|
||||
|
||||
|
||||
RenderableManager::Builder(1)
|
||||
.boundingBox({{-gridSize * gridSpacing / 2, 0, -gridSize * gridSpacing / 2},
|
||||
{gridSize * gridSpacing / 2, 0, gridSize * gridSpacing / 2}})
|
||||
.material(0, _materialInstance)
|
||||
.geometry(0, RenderableManager::PrimitiveType::LINES, vb, ib, 0, vertexCount)
|
||||
.priority(6)
|
||||
.layerMask(0xFF, 1u << SceneManager::LAYERS::OVERLAY)
|
||||
.culling(false)
|
||||
.receiveShadows(false)
|
||||
.castShadows(false)
|
||||
.build(engine, _gridEntity);
|
||||
const float sphereRadius = 0.05f;
|
||||
const int sphereSegments = 16;
|
||||
const int sphereRings = 16;
|
||||
|
||||
vertexCount = (sphereRings + 1) * (sphereSegments + 1);
|
||||
int indexCount = sphereRings * sphereSegments * 6;
|
||||
|
||||
math::float3* vertices = new math::float3[vertexCount];
|
||||
uint32_t* indices = new uint32_t[indexCount];
|
||||
|
||||
int vertexIndex = 0;
|
||||
// Generate sphere vertices
|
||||
for (int ring = 0; ring <= sphereRings; ++ring) {
|
||||
float theta = ring * M_PI / sphereRings;
|
||||
float sinTheta = std::sin(theta);
|
||||
float cosTheta = std::cos(theta);
|
||||
|
||||
for (int segment = 0; segment <= sphereSegments; ++segment) {
|
||||
float phi = segment * 2 * M_PI / sphereSegments;
|
||||
float sinPhi = std::sin(phi);
|
||||
float cosPhi = std::cos(phi);
|
||||
|
||||
float x = cosPhi * sinTheta;
|
||||
float y = cosTheta;
|
||||
float z = sinPhi * sinTheta;
|
||||
|
||||
vertices[vertexIndex++] = {x * sphereRadius, y * sphereRadius, z * sphereRadius};
|
||||
}
|
||||
}
|
||||
|
||||
int indexIndex = 0;
|
||||
// Generate sphere indices
|
||||
for (int ring = 0; ring < sphereRings; ++ring) {
|
||||
for (int segment = 0; segment < sphereSegments; ++segment) {
|
||||
uint32_t current = ring * (sphereSegments + 1) + segment;
|
||||
uint32_t next = current + sphereSegments + 1;
|
||||
|
||||
indices[indexIndex++] = current;
|
||||
indices[indexIndex++] = next;
|
||||
indices[indexIndex++] = current + 1;
|
||||
|
||||
indices[indexIndex++] = current + 1;
|
||||
indices[indexIndex++] = next;
|
||||
indices[indexIndex++] = next + 1;
|
||||
}
|
||||
}
|
||||
|
||||
auto sphereVb = VertexBuffer::Builder()
|
||||
.vertexCount(vertexCount)
|
||||
.bufferCount(1)
|
||||
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3)
|
||||
.build(engine);
|
||||
|
||||
sphereVb->setBufferAt(engine, 0, VertexBuffer::BufferDescriptor(
|
||||
vertices, vertexCount * sizeof(math::float3),
|
||||
[](void* buffer, size_t size, void*) { delete[] static_cast<math::float3*>(buffer); }
|
||||
));
|
||||
|
||||
auto sphereIb = IndexBuffer::Builder()
|
||||
.indexCount(indexCount)
|
||||
.bufferType(IndexBuffer::IndexType::UINT)
|
||||
.build(engine);
|
||||
|
||||
sphereIb->setBuffer(engine, IndexBuffer::BufferDescriptor(
|
||||
indices, indexCount * sizeof(uint32_t),
|
||||
[](void* buffer, size_t size, void*) { delete[] static_cast<uint32_t*>(buffer); }
|
||||
));
|
||||
|
||||
_sphereEntity = entityManager.create();
|
||||
|
||||
RenderableManager::Builder(1)
|
||||
.boundingBox({{-sphereRadius, -sphereRadius, -sphereRadius},
|
||||
{sphereRadius, sphereRadius, sphereRadius}})
|
||||
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, sphereVb, sphereIb, 0, indexCount)
|
||||
.priority(6)
|
||||
.layerMask(0xFF, 1u << SceneManager::LAYERS::OVERLAY)
|
||||
.culling(false)
|
||||
.receiveShadows(false)
|
||||
.castShadows(false)
|
||||
.build(engine, _sphereEntity);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GridOverlay::destroy()
|
||||
{
|
||||
auto &rm = _engine.getRenderableManager();
|
||||
auto &tm = _engine.getTransformManager();
|
||||
rm.destroy(_sphereEntity);
|
||||
rm.destroy(_gridEntity);
|
||||
tm.destroy(_sphereEntity);
|
||||
tm.destroy(_gridEntity);
|
||||
_engine.destroy(_sphereEntity);
|
||||
_engine.destroy(_gridEntity);
|
||||
}
|
||||
|
||||
} // namespace thermion
|
||||
@@ -1,172 +1,178 @@
|
||||
#include <filament/Material.h>
|
||||
#include <filament/MaterialInstance.h>
|
||||
#include <utils/EntityManager.h>
|
||||
// #include <filament/Material.h>
|
||||
// #include <filament/MaterialInstance.h>
|
||||
// #include <utils/EntityManager.h>
|
||||
|
||||
#include "SceneManager.hpp"
|
||||
// #include "scene/SceneManager.hpp"
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
// namespace thermion
|
||||
// {
|
||||
|
||||
SceneManager::HighlightOverlay::HighlightOverlay(
|
||||
EntityId entityId,
|
||||
SceneManager *const sceneManager,
|
||||
Engine *engine,
|
||||
float r,
|
||||
float g,
|
||||
float b) : _sceneManager(sceneManager), _engine(engine)
|
||||
{
|
||||
// SceneManager::HighlightOverlay::HighlightOverlay(
|
||||
// EntityId entityId,
|
||||
// SceneManager *const sceneManager,
|
||||
// Engine *engine,
|
||||
// float r,
|
||||
// float g,
|
||||
// float b) : _sceneManager(sceneManager), _engine(engine)
|
||||
// {
|
||||
|
||||
auto &rm = engine->getRenderableManager();
|
||||
// auto &rm = engine->getRenderableManager();
|
||||
|
||||
auto &tm = engine->getTransformManager();
|
||||
// auto &tm = engine->getTransformManager();
|
||||
|
||||
// Create the outline/highlight material instance
|
||||
filament::gltfio::MaterialKey dummyKey; // We're not using the key for this simple material
|
||||
filament::gltfio::UvMap dummyUvMap; // We're not using UV mapping for this simple material
|
||||
// // Create the outline/highlight material instance
|
||||
// filament::gltfio::MaterialKey dummyKey; // We're not using the key for this simple material
|
||||
// filament::gltfio::UvMap dummyUvMap; // We're not using UV mapping for this simple material
|
||||
|
||||
auto materialProvider = sceneManager->unlitMaterialProvider();
|
||||
// auto materialProvider = sceneManager->unlitMaterialProvider();
|
||||
|
||||
_highlightMaterialInstance = materialProvider->createMaterialInstance(&dummyKey, &dummyUvMap);
|
||||
_highlightMaterialInstance->setStencilOpStencilFail(filament::backend::StencilOperation::KEEP);
|
||||
_highlightMaterialInstance->setStencilOpDepthFail(filament::backend::StencilOperation::KEEP);
|
||||
_highlightMaterialInstance->setStencilOpDepthStencilPass(filament::backend::StencilOperation::REPLACE);
|
||||
_highlightMaterialInstance->setStencilCompareFunction(filament::backend::SamplerCompareFunc::NE);
|
||||
_highlightMaterialInstance->setStencilReferenceValue(1);
|
||||
// _highlightMaterialInstance = materialProvider->createMaterialInstance(&dummyKey, &dummyUvMap);
|
||||
// _highlightMaterialInstance->setStencilOpStencilFail(filament::backend::StencilOperation::KEEP);
|
||||
// _highlightMaterialInstance->setStencilOpDepthFail(filament::backend::StencilOperation::KEEP);
|
||||
// _highlightMaterialInstance->setStencilOpDepthStencilPass(filament::backend::StencilOperation::REPLACE);
|
||||
// _highlightMaterialInstance->setStencilCompareFunction(filament::backend::SamplerCompareFunc::NE);
|
||||
// _highlightMaterialInstance->setStencilReferenceValue(1);
|
||||
|
||||
_highlightMaterialInstance->setParameter("baseColorFactor", filament::math::float3{r, g, b});
|
||||
_highlightMaterialInstance->setParameter("vertexScale", 1.04f);
|
||||
_highlightMaterialInstance->setCullingMode(filament::backend::CullingMode::FRONT);
|
||||
// _highlightMaterialInstance->setParameter("baseColorFactor", filament::math::float3{r, g, b});
|
||||
// _highlightMaterialInstance->setParameter("vertexScale", 1.04f);
|
||||
// _highlightMaterialInstance->setCullingMode(filament::backend::CullingMode::FRONT);
|
||||
|
||||
// auto scene = sceneManager->getScene();
|
||||
|
||||
auto scene = sceneManager->getScene();
|
||||
// // _isGeometryEntity = sceneManager->isGeometryEntity(entityId);
|
||||
// // _isGltfAsset = sceneManager->isGltfAsset(entityId);
|
||||
|
||||
_isGeometryEntity = sceneManager->isGeometryEntity(entityId);
|
||||
_isGltfAsset = sceneManager->isGltfAsset(entityId);
|
||||
// if (!(_isGeometryEntity || _isGltfAsset))
|
||||
// {
|
||||
// Log("Failed to set stencil outline for entity %d: the entity is a child of another entity. "
|
||||
// "Currently, we only support outlining top-level entities."
|
||||
// "Call getAncestor() to get the ancestor of this entity, then set on that",
|
||||
// entityId);
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (!(_isGeometryEntity || _isGltfAsset))
|
||||
{
|
||||
Log("Failed to set stencil outline for entity %d: the entity is a child of another entity. "
|
||||
"Currently, we only support outlining top-level entities."
|
||||
"Call getAncestor() to get the ancestor of this entity, then set on that",
|
||||
entityId);
|
||||
return;
|
||||
}
|
||||
// if (_isGeometryEntity)
|
||||
// {
|
||||
|
||||
if (_isGeometryEntity)
|
||||
{
|
||||
// auto geometryEntity = Entity::import(entityId);
|
||||
// auto renderable = rm.getInstance(geometryEntity);
|
||||
|
||||
auto geometryEntity = Entity::import(entityId);
|
||||
auto renderable = rm.getInstance(geometryEntity);
|
||||
// auto materialInstance = rm.getMaterialInstanceAt(renderable, 0);
|
||||
|
||||
auto materialInstance = rm.getMaterialInstanceAt(renderable, 0);
|
||||
// // set stencil write on the existing material
|
||||
// materialInstance->setStencilWrite(true);
|
||||
// materialInstance->setDepthWrite(true);
|
||||
// materialInstance->setStencilReferenceValue(1);
|
||||
// materialInstance->setStencilOpStencilFail(filament::backend::StencilOperation::KEEP);
|
||||
// materialInstance->setStencilOpDepthFail(filament::backend::StencilOperation::KEEP);
|
||||
// materialInstance->setStencilOpDepthStencilPass(filament::backend::StencilOperation::KEEP);
|
||||
// materialInstance->setStencilCompareFunction(filament::backend::SamplerCompareFunc::A);
|
||||
// // materialInstance->setCullingMode(filament::MaterialInstance::CullingMode::BACK);
|
||||
|
||||
// set stencil write on the existing material
|
||||
materialInstance->setStencilWrite(true);
|
||||
materialInstance->setDepthWrite(true);
|
||||
materialInstance->setStencilReferenceValue(1);
|
||||
materialInstance->setStencilOpStencilFail(filament::backend::StencilOperation::KEEP);
|
||||
materialInstance->setStencilOpDepthFail(filament::backend::StencilOperation::KEEP);
|
||||
materialInstance->setStencilOpDepthStencilPass(filament::backend::StencilOperation::KEEP);
|
||||
materialInstance->setStencilCompareFunction(filament::backend::SamplerCompareFunc::A);
|
||||
// materialInstance->setCullingMode(filament::MaterialInstance::CullingMode::BACK);
|
||||
// // auto geometry = sceneManager->getGeometry(entityId);
|
||||
|
||||
auto geometry = sceneManager->getGeometry(entityId);
|
||||
// // _entity = geometry->createInstance(materialInstance);
|
||||
|
||||
_entity = geometry->createInstance(materialInstance);
|
||||
// scene->addEntity(_entity);
|
||||
// auto outlineTransformInstance = tm.getInstance(_entity);
|
||||
// auto entityTransformInstance = tm.getInstance(geometryEntity);
|
||||
// tm.setParent(outlineTransformInstance, entityTransformInstance);
|
||||
// }
|
||||
// else if (_isGltfAsset)
|
||||
// {
|
||||
// Log("Entity %d is gltf", entityId);
|
||||
// // auto *asset = sceneManager->getAssetByEntityId(entityId);
|
||||
|
||||
scene->addEntity(_entity);
|
||||
auto outlineTransformInstance = tm.getInstance(_entity);
|
||||
auto entityTransformInstance = tm.getInstance(geometryEntity);
|
||||
tm.setParent(outlineTransformInstance, entityTransformInstance);
|
||||
}
|
||||
else if (_isGltfAsset)
|
||||
{
|
||||
Log("Entity %d is gltf", entityId);
|
||||
auto *asset = sceneManager->getAssetByEntityId(entityId);
|
||||
// // if (asset)
|
||||
// // {
|
||||
|
||||
if (asset)
|
||||
{
|
||||
// // Log("Found glTF FilamentAsset with %d material instances", asset->getInstance()->getMaterialInstanceCount());
|
||||
|
||||
Log("Found glTF FilamentAsset with %d material instances", asset->getInstance()->getMaterialInstanceCount());
|
||||
// // auto materialInstance = asset->getInstance()->getMaterialInstances()[0];
|
||||
|
||||
auto materialInstance = asset->getInstance()->getMaterialInstances()[0];
|
||||
// // // set stencil write on the existing material
|
||||
// // materialInstance->setStencilWrite(true);
|
||||
// // materialInstance->setDepthWrite(true);
|
||||
// // materialInstance->setStencilReferenceValue(1);
|
||||
// // materialInstance->setStencilOpStencilFail(filament::backend::StencilOperation::KEEP);
|
||||
// // materialInstance->setStencilOpDepthFail(filament::backend::StencilOperation::REPLACE);
|
||||
// // materialInstance->setStencilOpDepthStencilPass(filament::backend::StencilOperation::REPLACE);
|
||||
// // materialInstance->setStencilCompareFunction(filament::backend::SamplerCompareFunc::A);
|
||||
|
||||
// set stencil write on the existing material
|
||||
materialInstance->setStencilWrite(true);
|
||||
materialInstance->setDepthWrite(true);
|
||||
materialInstance->setStencilReferenceValue(1);
|
||||
materialInstance->setStencilOpStencilFail(filament::backend::StencilOperation::KEEP);
|
||||
materialInstance->setStencilOpDepthFail(filament::backend::StencilOperation::REPLACE);
|
||||
materialInstance->setStencilOpDepthStencilPass(filament::backend::StencilOperation::REPLACE);
|
||||
materialInstance->setStencilCompareFunction(filament::backend::SamplerCompareFunc::A);
|
||||
// // _newInstance = sceneManager->createGltfAssetInstance(asset);
|
||||
|
||||
_newInstance = sceneManager->createGltfAssetInstance(asset);
|
||||
// // _entity = _newInstance->getRoot();
|
||||
|
||||
_entity = _newInstance->getRoot();
|
||||
// // auto newTransformInstance = tm.getInstance(_entity);
|
||||
|
||||
auto newTransformInstance = tm.getInstance(_entity);
|
||||
// // auto entityTransformInstance = tm.getInstance(asset->getRoot());
|
||||
// // tm.setParent(newTransformInstance, entityTransformInstance);
|
||||
// // if (!_newInstance)
|
||||
// // {
|
||||
// // Log("Couldn't create new instance");
|
||||
// // }
|
||||
// // else
|
||||
// // {
|
||||
// // for (int i = 0; i < _newInstance->getEntityCount(); i++)
|
||||
// // {
|
||||
// // auto entity = _newInstance->getEntities()[i];
|
||||
// // auto renderableInstance = rm.getInstance(entity);
|
||||
// // rm.setPriority(renderableInstance, 7);
|
||||
// // if (renderableInstance.isValid())
|
||||
// // {
|
||||
// // for (int primitiveIndex = 0; primitiveIndex < rm.getPrimitiveCount(renderableInstance); primitiveIndex++)
|
||||
// // {
|
||||
// // rm.setMaterialInstanceAt(renderableInstance, primitiveIndex, _highlightMaterialInstance);
|
||||
// // }
|
||||
// // }
|
||||
// // else
|
||||
// // {
|
||||
// // Log("Not renderable, ignoring");
|
||||
// // }
|
||||
// // }
|
||||
// // scene->addEntities(_newInstance->getEntities(), _newInstance->getEntityCount());
|
||||
// // }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Log("Not FilamentAsset");
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
auto entityTransformInstance = tm.getInstance(asset->getRoot());
|
||||
tm.setParent(newTransformInstance, entityTransformInstance);
|
||||
if (!_newInstance)
|
||||
{
|
||||
Log("Couldn't create new instance");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < _newInstance->getEntityCount(); i++)
|
||||
{
|
||||
auto entity = _newInstance->getEntities()[i];
|
||||
auto renderableInstance = rm.getInstance(entity);
|
||||
rm.setPriority(renderableInstance, 7);
|
||||
if (renderableInstance.isValid())
|
||||
{
|
||||
for (int primitiveIndex = 0; primitiveIndex < rm.getPrimitiveCount(renderableInstance); primitiveIndex++)
|
||||
{
|
||||
rm.setMaterialInstanceAt(renderableInstance, primitiveIndex, _highlightMaterialInstance);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("Not renderable, ignoring");
|
||||
}
|
||||
}
|
||||
scene->addEntities(_newInstance->getEntities(), _newInstance->getEntityCount());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("Not FilamentAsset");
|
||||
}
|
||||
}
|
||||
}
|
||||
// SceneManager::HighlightOverlay::~HighlightOverlay()
|
||||
// {
|
||||
// if (_entity.isNull())
|
||||
// {
|
||||
// Log("Null entity");
|
||||
// return;
|
||||
// }
|
||||
|
||||
SceneManager::HighlightOverlay::~HighlightOverlay()
|
||||
{
|
||||
if (_entity.isNull())
|
||||
{
|
||||
Log("Null entity");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_isGltfAsset)
|
||||
{
|
||||
_sceneManager->getScene()->removeEntities(_newInstance->getEntities(), _newInstance->getEntityCount());
|
||||
_newInstance->detachMaterialInstances();
|
||||
_engine->destroy(_highlightMaterialInstance);
|
||||
}
|
||||
else if (_isGeometryEntity)
|
||||
{
|
||||
auto &tm = _engine->getTransformManager();
|
||||
auto transformInstance = tm.getInstance(_entity);
|
||||
_sceneManager->getScene()->remove(_entity);
|
||||
utils::EntityManager::get().destroy(_entity);
|
||||
_engine->destroy(_entity);
|
||||
_engine->destroy(_highlightMaterialInstance);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("FATAL: Unknown highlight overlay entity type");
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (_isGltfAsset)
|
||||
// {
|
||||
// Log("Destroyed gltf asset highlight overlay");
|
||||
// _sceneManager->getScene()->removeEntities(_newInstance->getEntities(), _newInstance->getEntityCount());
|
||||
// // _sceneManager->destroyGltfAssetInstance(_newInstance);
|
||||
// // auto materialInstances = _newInstance->getMaterialInstances();
|
||||
// // auto numMaterialInstances = _newInstance->getMaterialInstanceCount();
|
||||
// // _newInstance->detachMaterialInstances();
|
||||
// // for(int i = 0; i < numMaterialInstances; i++) {
|
||||
// // _engine->destroy(_highlightMaterialInstance);
|
||||
// // }
|
||||
// // _engine->destroy(_newInstance);
|
||||
// }
|
||||
// else if (_isGeometryEntity)
|
||||
// {
|
||||
// auto &tm = _engine->getTransformManager();
|
||||
// auto transformInstance = tm.getInstance(_entity);
|
||||
// _sceneManager->getScene()->remove(_entity);
|
||||
// utils::EntityManager::get().destroy(_entity);
|
||||
// _engine->destroy(_entity);
|
||||
// _engine->destroy(_highlightMaterialInstance);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Log("FATAL: Unknown highlight overlay entity type");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,31 +0,0 @@
|
||||
#include <filament/View.h>
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/Scene.h>
|
||||
|
||||
#include "ThermionDartApi.h"
|
||||
#include "TGizmo.h"
|
||||
#include "Gizmo.hpp"
|
||||
#include "Log.hpp"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace thermion {
|
||||
extern "C"
|
||||
{
|
||||
using namespace filament;
|
||||
#endif
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Gizmo_pick(TGizmo *tGizmo, uint32_t x, uint32_t y, GizmoPickCallback callback)
|
||||
{
|
||||
auto *gizmo = reinterpret_cast<Gizmo*>(tGizmo);
|
||||
gizmo->pick(x, y, reinterpret_cast<Gizmo::PickCallback>(callback));
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Gizmo_setVisibility(TGizmo *tGizmo, bool visible) {
|
||||
auto *gizmo = reinterpret_cast<Gizmo*>(tGizmo);
|
||||
gizmo->setVisibility(visible);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,57 +0,0 @@
|
||||
#include <filament/MaterialInstance.h>
|
||||
#include <math/mat4.h>
|
||||
#include <math/vec4.h>
|
||||
#include <math/vec2.h>
|
||||
|
||||
#include "Log.hpp"
|
||||
#include "TMaterialInstance.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace thermion
|
||||
{
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthWrite(TMaterialInstance *materialInstance, bool enabled)
|
||||
{
|
||||
reinterpret_cast<::filament::MaterialInstance *>(materialInstance)->setDepthWrite(enabled);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthCulling(TMaterialInstance *materialInstance, bool enabled)
|
||||
{
|
||||
reinterpret_cast<::filament::MaterialInstance *>(materialInstance)->setDepthCulling(enabled);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat4(TMaterialInstance *tMaterialInstance, const char *propertyName, double x, double y, double z, double w)
|
||||
{
|
||||
auto *materialInstance = reinterpret_cast<::filament::MaterialInstance *>(tMaterialInstance);
|
||||
filament::math::float4 data{static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(w)};
|
||||
materialInstance->setParameter(propertyName, data);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat2(TMaterialInstance *materialInstance, const char *propertyName, double x, double y)
|
||||
{
|
||||
filament::math::float2 data{static_cast<float>(x), static_cast<float>(y)};
|
||||
reinterpret_cast<::filament::MaterialInstance *>(materialInstance)->setParameter(propertyName, data);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat(TMaterialInstance *materialInstance, const char *propertyName, double value)
|
||||
{
|
||||
reinterpret_cast<::filament::MaterialInstance *>(materialInstance)->setParameter(propertyName, static_cast<float>(value));
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterInt(TMaterialInstance *materialInstance, const char *propertyName, int value)
|
||||
{
|
||||
reinterpret_cast<::filament::MaterialInstance *>(materialInstance)->setParameter(propertyName, value);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthFunc(TMaterialInstance *tMaterialInstance, TDepthFunc tDepthFunc) {
|
||||
auto *materialInstance = reinterpret_cast<::filament::MaterialInstance *>(tMaterialInstance);
|
||||
auto depthFunc = static_cast<filament::MaterialInstance::DepthFunc>(tDepthFunc);
|
||||
materialInstance->setDepthFunc(depthFunc);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,140 +0,0 @@
|
||||
#include "filament/LightManager.h"
|
||||
#include "ResourceBuffer.hpp"
|
||||
#include "FilamentViewer.hpp"
|
||||
#include "Log.hpp"
|
||||
#include "APIExport.h"
|
||||
|
||||
using namespace thermion;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
#include "TSceneManager.h"
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TGizmo *SceneManager_createGizmo(TSceneManager *tSceneManager, TView *tView, TScene *tScene)
|
||||
{
|
||||
auto sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
auto *scene = reinterpret_cast<Scene *>(tScene);
|
||||
auto *view = reinterpret_cast<View *>(tView);
|
||||
auto gizmo = sceneManager->createGizmo(view, scene);
|
||||
return reinterpret_cast<TGizmo *>(gizmo);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId SceneManager_loadGlbFromBuffer(TSceneManager *sceneManager, const uint8_t *const data, size_t length, bool keepData, int priority, int layer, bool loadResourcesAsync)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->loadGlbFromBuffer((const uint8_t *)data, length, 1, keepData, priority, layer, loadResourcesAsync);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool SceneManager_setMorphAnimation(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
const float *const morphData,
|
||||
const uint32_t *const morphIndices,
|
||||
int numMorphTargets,
|
||||
int numFrames,
|
||||
float frameLengthInMs)
|
||||
{
|
||||
auto result = ((SceneManager *)sceneManager)->setMorphAnimationBuffer(asset, morphData, morphIndices, numMorphTargets, numFrames, frameLengthInMs);
|
||||
return result;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TCamera *SceneManager_getCameraByName(TSceneManager *tSceneManager, EntityId entityId, const char *name)
|
||||
{
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool SceneManager_setTransform(TSceneManager *sceneManager, EntityId entityId, const double *const transform)
|
||||
{
|
||||
auto matrix = math::mat4(
|
||||
transform[0], transform[1], transform[2],
|
||||
transform[3],
|
||||
transform[4],
|
||||
transform[5],
|
||||
transform[6],
|
||||
transform[7],
|
||||
transform[8],
|
||||
transform[9],
|
||||
transform[10],
|
||||
transform[11],
|
||||
transform[12],
|
||||
transform[13],
|
||||
transform[14],
|
||||
transform[15]);
|
||||
return ((SceneManager *)sceneManager)->setTransform(entityId, matrix);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE Aabb3 SceneManager_getRenderableBoundingBox(TSceneManager *tSceneManager, EntityId entity)
|
||||
{
|
||||
auto sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
return sceneManager->getRenderableBoundingBox(entity);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_setVisibilityLayer(TSceneManager *tSceneManager, EntityId entity, int layer)
|
||||
{
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
sceneManager->setVisibilityLayer(entity, layer);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialInstance *SceneManager_createUnlitMaterialInstance(TSceneManager *sceneManager)
|
||||
{
|
||||
auto *instance = ((SceneManager *)sceneManager)->createUnlitMaterialInstance();
|
||||
return reinterpret_cast<TMaterialInstance *>(instance);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialInstance *SceneManager_createUnlitFixedSizeMaterialInstance(TSceneManager *sceneManager)
|
||||
{
|
||||
auto *instance = ((SceneManager *)sceneManager)->createUnlitFixedSizeMaterialInstance();
|
||||
return reinterpret_cast<TMaterialInstance *>(instance);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TCamera *SceneManager_createCamera(TSceneManager *tSceneManager)
|
||||
{
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
return reinterpret_cast<TCamera *>(sceneManager->createCamera());
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_destroyCamera(TSceneManager *tSceneManager, TCamera *tCamera)
|
||||
{
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
auto *camera = reinterpret_cast<Camera *>(tCamera);
|
||||
sceneManager->destroyCamera(camera);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE size_t SceneManager_getCameraCount(TSceneManager *tSceneManager)
|
||||
{
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
return sceneManager->getCameraCount();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TCamera *SceneManager_getCameraAt(TSceneManager *tSceneManager, size_t index)
|
||||
{
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
auto *camera = sceneManager->getCameraAt(index);
|
||||
return reinterpret_cast<TCamera *>(camera);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId SceneManager_createGeometry(
|
||||
TSceneManager *sceneManager,
|
||||
float *vertices,
|
||||
int numVertices,
|
||||
float *normals,
|
||||
int numNormals,
|
||||
float *uvs,
|
||||
int numUvs,
|
||||
uint16_t *indices,
|
||||
int numIndices,
|
||||
int primitiveType,
|
||||
TMaterialInstance *materialInstance,
|
||||
bool keepData)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->createGeometry(vertices, static_cast<uint32_t>(numVertices), normals, static_cast<uint32_t>(numNormals), uvs, static_cast<uint32_t>(numUvs), indices, static_cast<uint32_t>(numIndices), (filament::RenderableManager::PrimitiveType)primitiveType, reinterpret_cast<MaterialInstance *>(materialInstance), keepData);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_destroyMaterialInstance(TSceneManager *sceneManager, TMaterialInstance *instance)
|
||||
{
|
||||
((SceneManager *)sceneManager)->destroy(reinterpret_cast<MaterialInstance *>(instance));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,952 +0,0 @@
|
||||
#ifdef _WIN32
|
||||
#include "ThermionWin32.h"
|
||||
#endif
|
||||
|
||||
#include <thread>
|
||||
#include <functional>
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten/emscripten.h>
|
||||
#endif
|
||||
|
||||
#include "filament/LightManager.h"
|
||||
#include "ResourceBuffer.hpp"
|
||||
#include "FilamentViewer.hpp"
|
||||
#include "Log.hpp"
|
||||
#include "ThreadPool.hpp"
|
||||
|
||||
using namespace thermion;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
#include "ThermionDartApi.h"
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TViewer *Viewer_create(const void *context, const void *const loader, void *const platform, const char *uberArchivePath)
|
||||
{
|
||||
const auto *loaderImpl = new ResourceLoaderWrapperImpl((ResourceLoaderWrapper *)loader);
|
||||
auto viewer = new FilamentViewer(context, loaderImpl, platform, uberArchivePath);
|
||||
return reinterpret_cast<TViewer *>(viewer);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer *viewer)
|
||||
{
|
||||
auto *engine = reinterpret_cast<FilamentViewer *>(viewer)->getEngine();
|
||||
return reinterpret_cast<TEngine *>(engine);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TRenderTarget *Viewer_createRenderTarget(TViewer *tViewer, intptr_t texture, uint32_t width, uint32_t height)
|
||||
{
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto renderTarget = viewer->createRenderTarget(texture, width, height);
|
||||
return reinterpret_cast<TRenderTarget *>(renderTarget);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_destroyRenderTarget(TViewer *tViewer, TRenderTarget *tRenderTarget)
|
||||
{
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto renderTarget = reinterpret_cast<RenderTarget *>(tRenderTarget);
|
||||
viewer->destroyRenderTarget(renderTarget);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_pick(TViewer *tViewer, TView* tView, int x, int y, void (*callback)(EntityId entityId, int x, int y, TView *tView, float depth, float fragX, float fragY, float fragZ))
|
||||
{
|
||||
auto *viewer = reinterpret_cast<FilamentViewer*>(tViewer);
|
||||
auto *view = reinterpret_cast<View*>(tView);
|
||||
((FilamentViewer *)viewer)->pick(view, static_cast<uint32_t>(x), static_cast<uint32_t>(y), reinterpret_cast<FilamentViewer::PickCallback>(callback));
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool Viewer_isNonPickableEntity(TViewer *tViewer, EntityId entityId) {
|
||||
auto *viewer = reinterpret_cast<FilamentViewer*>(tViewer);
|
||||
return viewer->isNonPickableEntity(entityId);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_destroy(TViewer *viewer)
|
||||
{
|
||||
delete ((FilamentViewer *)viewer);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_color(TViewer *viewer, const float r, const float g, const float b, const float a)
|
||||
{
|
||||
((FilamentViewer *)viewer)->setBackgroundColor(r, g, b, a);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void clear_background_image(TViewer *viewer)
|
||||
{
|
||||
((FilamentViewer *)viewer)->clearBackgroundImage();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_image(TViewer *viewer, const char *path, bool fillHeight)
|
||||
{
|
||||
((FilamentViewer *)viewer)->setBackgroundImage(path, fillHeight, 100, 100);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_image_position(TViewer *viewer, float x, float y, bool clamp)
|
||||
{
|
||||
((FilamentViewer *)viewer)->setBackgroundImagePosition(x, y, clamp, 100, 100);
|
||||
}
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void load_skybox(TViewer *viewer, const char *skyboxPath)
|
||||
{
|
||||
((FilamentViewer *)viewer)->loadSkybox(skyboxPath);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void create_ibl(TViewer *viewer, float r, float g, float b, float intensity)
|
||||
{
|
||||
((FilamentViewer *)viewer)->createIbl(r, g, b, intensity);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_loadIbl(TViewer *viewer, const char *iblPath, float intensity)
|
||||
{
|
||||
((FilamentViewer *)viewer)->loadIbl(iblPath, intensity);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void rotate_ibl(TViewer *viewer, float *rotationMatrix)
|
||||
{
|
||||
math::mat3f matrix(rotationMatrix[0], rotationMatrix[1],
|
||||
rotationMatrix[2],
|
||||
rotationMatrix[3],
|
||||
rotationMatrix[4],
|
||||
rotationMatrix[5],
|
||||
rotationMatrix[6],
|
||||
rotationMatrix[7],
|
||||
rotationMatrix[8]);
|
||||
|
||||
((FilamentViewer *)viewer)->rotateIbl(matrix);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void remove_skybox(TViewer *viewer)
|
||||
{
|
||||
((FilamentViewer *)viewer)->removeSkybox();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void remove_ibl(TViewer *viewer)
|
||||
{
|
||||
((FilamentViewer *)viewer)->removeIbl();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId add_light(
|
||||
TViewer *viewer,
|
||||
uint8_t type,
|
||||
float colour,
|
||||
float intensity,
|
||||
float posX,
|
||||
float posY,
|
||||
float posZ,
|
||||
float dirX,
|
||||
float dirY,
|
||||
float dirZ,
|
||||
float falloffRadius,
|
||||
float spotLightConeInner,
|
||||
float spotLightConeOuter,
|
||||
float sunAngularRadius,
|
||||
float sunHaloSize,
|
||||
float sunHaloFallof,
|
||||
bool shadows)
|
||||
{
|
||||
return ((FilamentViewer *)viewer)->addLight((LightManager::Type)type, colour, intensity, posX, posY, posZ, dirX, dirY, dirZ, falloffRadius, spotLightConeInner, spotLightConeOuter, sunAngularRadius, sunHaloSize, sunHaloFallof, shadows);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_light_position(TViewer *viewer, int32_t entityId, float x, float y, float z)
|
||||
{
|
||||
((FilamentViewer *)viewer)->setLightPosition(entityId, x, y, z);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_light_direction(TViewer *viewer, int32_t entityId, float x, float y, float z)
|
||||
{
|
||||
((FilamentViewer *)viewer)->setLightDirection(entityId, x, y, z);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void remove_light(TViewer *viewer, int32_t entityId)
|
||||
{
|
||||
((FilamentViewer *)viewer)->removeLight(entityId);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void clear_lights(TViewer *viewer)
|
||||
{
|
||||
((FilamentViewer *)viewer)->clearLights();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId load_glb(TSceneManager *sceneManager, const char *assetPath, int numInstances, bool keepData)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->loadGlb(assetPath, numInstances, keepData);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId create_instance(TSceneManager *sceneManager, EntityId entityId)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->createInstance(entityId);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int get_instance_count(TSceneManager *sceneManager, EntityId entityId)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->getInstanceCount(entityId);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void get_instances(TSceneManager *sceneManager, EntityId entityId, EntityId *out)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->getInstances(entityId, out);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId load_gltf(TSceneManager *sceneManager, const char *assetPath, const char *relativePath, bool keepData)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->loadGltf(assetPath, relativePath, keepData);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_setMainCamera(TViewer *tViewer, TView *tView)
|
||||
{
|
||||
auto *viewer = reinterpret_cast<FilamentViewer*>(tViewer);
|
||||
auto *view = reinterpret_cast<View*>(tView);
|
||||
viewer->setMainCamera(view);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId get_main_camera(TViewer *viewer)
|
||||
{
|
||||
return ((FilamentViewer *)viewer)->getMainCamera();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE float get_camera_fov(TCamera *camera, bool horizontal)
|
||||
{
|
||||
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
return cam->getFieldOfViewInDegrees(horizontal ? Camera::Fov::HORIZONTAL : Camera::Fov::VERTICAL);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE double get_camera_focal_length(TCamera *const camera)
|
||||
{
|
||||
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
return cam->getFocalLength();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_camera_projection_from_fov(TCamera *camera, double fovInDegrees, double aspect, double near, double far, bool horizontal)
|
||||
{
|
||||
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
cam->setProjection(fovInDegrees, aspect, near, far, horizontal ? Camera::Fov::HORIZONTAL : Camera::Fov::VERTICAL);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TCamera *get_camera(TViewer *viewer, EntityId entity)
|
||||
{
|
||||
auto filamentCamera = ((FilamentViewer *)viewer)->getCamera(entity);
|
||||
return reinterpret_cast<TCamera *>(filamentCamera);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 get_camera_model_matrix(TCamera *camera)
|
||||
{
|
||||
const auto &mat = reinterpret_cast<filament::Camera *>(camera)->getModelMatrix();
|
||||
return convert_mat4_to_double4x4(mat);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 get_camera_view_matrix(TCamera *camera)
|
||||
{
|
||||
const auto &mat = reinterpret_cast<filament::Camera *>(camera)->getViewMatrix();
|
||||
return convert_mat4_to_double4x4(mat);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 get_camera_projection_matrix(TCamera *camera)
|
||||
{
|
||||
const auto &mat = reinterpret_cast<filament::Camera *>(camera)->getProjectionMatrix();
|
||||
return convert_mat4_to_double4x4(mat);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 get_camera_culling_projection_matrix(TCamera *camera)
|
||||
{
|
||||
const auto &mat = reinterpret_cast<filament::Camera *>(camera)->getCullingProjectionMatrix();
|
||||
return convert_mat4_to_double4x4(mat);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_camera_projection_matrix(TCamera *camera, double4x4 matrix, double near, double far)
|
||||
{
|
||||
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
const auto &mat = convert_double4x4_to_mat4(matrix);
|
||||
cam->setCustomProjection(mat, near, far);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setLensProjection(TCamera *camera, double near, double far, double aspect, double focalLength)
|
||||
{
|
||||
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
cam->setLensProjection(focalLength, aspect, near, far);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setModelMatrix(TCamera *camera, double4x4 matrix)
|
||||
{
|
||||
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
cam->setModelMatrix(convert_double4x4_to_mat4(matrix));
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE double get_camera_near(TCamera *camera)
|
||||
{
|
||||
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
return cam->getNear();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE double get_camera_culling_far(TCamera *camera)
|
||||
{
|
||||
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
return cam->getCullingFar();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE const double *const get_camera_frustum(TCamera *camera)
|
||||
{
|
||||
|
||||
const auto frustum = reinterpret_cast<filament::Camera *>(camera)->getFrustum();
|
||||
|
||||
const math::float4 *planes = frustum.getNormalizedPlanes();
|
||||
double *array = (double *)calloc(24, sizeof(double));
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
auto plane = planes[i];
|
||||
array[i * 4] = double(plane.x);
|
||||
array[i * 4 + 1] = double(plane.y);
|
||||
array[i * 4 + 2] = double(plane.z);
|
||||
array[i * 4 + 3] = double(plane.w);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_camera_focus_distance(TCamera *camera, float distance)
|
||||
{
|
||||
auto *cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
cam->setFocusDistance(distance);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_camera_exposure(TCamera *camera, float aperture, float shutterSpeed, float sensitivity)
|
||||
{
|
||||
auto *cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
cam->setExposure(aperture, shutterSpeed, sensitivity);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_camera_model_matrix(TCamera *camera, double4x4 matrix)
|
||||
{
|
||||
auto *cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
const filament::math::mat4 &mat = convert_double4x4_to_mat4(matrix);
|
||||
cam->setModelMatrix(mat);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_render(
|
||||
TViewer *tViewer)
|
||||
{
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
viewer->render(0);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_setViewRenderable(TViewer *tViewer, TSwapChain *tSwapChain, TView *tView, bool renderable) {
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto swapChain = reinterpret_cast<SwapChain*>(tSwapChain);
|
||||
auto *view = reinterpret_cast<View*>(tView);
|
||||
viewer->setRenderable(view, swapChain, renderable);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_capture(
|
||||
TViewer *tViewer,
|
||||
TView *tView,
|
||||
TSwapChain *tSwapChain,
|
||||
uint8_t *pixelBuffer,
|
||||
void (*callback)(void))
|
||||
{
|
||||
#ifdef __EMSCRIPTEN__
|
||||
bool useFence = true;
|
||||
#else
|
||||
bool useFence = false;
|
||||
#endif
|
||||
auto swapChain = reinterpret_cast<SwapChain *>(tSwapChain);
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto *view = reinterpret_cast<View*>(tView);
|
||||
viewer->capture(view, pixelBuffer, useFence, swapChain, callback);
|
||||
};
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTarget(
|
||||
TViewer *tViewer,
|
||||
TView *tView,
|
||||
TSwapChain *tSwapChain,
|
||||
TRenderTarget *tRenderTarget,
|
||||
uint8_t *pixelBuffer,
|
||||
void (*callback)(void))
|
||||
{
|
||||
#ifdef __EMSCRIPTEN__
|
||||
bool useFence = true;
|
||||
#else
|
||||
bool useFence = false;
|
||||
#endif
|
||||
auto swapChain = reinterpret_cast<SwapChain *>(tSwapChain);
|
||||
auto renderTarget = reinterpret_cast<RenderTarget *>(tRenderTarget);
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto *view = reinterpret_cast<View*>(tView);
|
||||
viewer->capture(view, pixelBuffer, useFence, swapChain, renderTarget, callback);
|
||||
};
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_frame_interval(
|
||||
TViewer *viewer,
|
||||
float frameInterval)
|
||||
{
|
||||
((FilamentViewer *)viewer)->setFrameInterval(frameInterval);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_destroySwapChain(TViewer *tViewer, TSwapChain *tSwapChain)
|
||||
{
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto swapChain = reinterpret_cast<SwapChain *>(tSwapChain);
|
||||
viewer->destroySwapChain(swapChain);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createHeadlessSwapChain(TViewer *tViewer, uint32_t width, uint32_t height)
|
||||
{
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto swapChain = viewer->createSwapChain(width, height);
|
||||
return reinterpret_cast<TSwapChain *>(swapChain);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createSwapChain(TViewer *tViewer, const void *const window)
|
||||
{
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto swapChain = viewer->createSwapChain(window);
|
||||
return reinterpret_cast<TSwapChain *>(swapChain);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TSwapChain* Viewer_getSwapChainAt(TViewer *tViewer, int index) {
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto swapChain = viewer->getSwapChainAt(index);
|
||||
return reinterpret_cast<TSwapChain *>(swapChain);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TView *Viewer_createView(TViewer *tViewer)
|
||||
{
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto view = viewer->createView();
|
||||
return reinterpret_cast<TView *>(view);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TView *Viewer_getViewAt(TViewer *tViewer, int32_t index)
|
||||
{
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto view = viewer->getViewAt(index);
|
||||
return reinterpret_cast<TView *>(view);
|
||||
}
|
||||
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TSceneManager *Viewer_getSceneManager(TViewer *tViewer)
|
||||
{
|
||||
auto *viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto *sceneManager = viewer->getSceneManager();
|
||||
return reinterpret_cast<TSceneManager *>(sceneManager);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void apply_weights(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
const char *const entityName,
|
||||
float *const weights,
|
||||
int count)
|
||||
{
|
||||
// ((SceneManager*)sceneManager)->setMorphTargetWeights(asset, entityName, weights, count);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool set_morph_target_weights(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
const float *const weights,
|
||||
const int numWeights)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->setMorphTargetWeights(asset, weights, numWeights);
|
||||
}
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void clear_morph_animation(TSceneManager *sceneManager, EntityId asset)
|
||||
{
|
||||
((SceneManager *)sceneManager)->clearMorphAnimationBuffer(asset);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void reset_to_rest_pose(TSceneManager *sceneManager, EntityId entityId)
|
||||
{
|
||||
((SceneManager *)sceneManager)->resetBones(entityId);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void add_bone_animation(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
int skinIndex,
|
||||
int boneIndex,
|
||||
const float *const frameData,
|
||||
int numFrames,
|
||||
float frameLengthInMs,
|
||||
float fadeOutInSecs,
|
||||
float fadeInInSecs,
|
||||
float maxDelta)
|
||||
{
|
||||
((SceneManager *)sceneManager)->addBoneAnimation(asset, skinIndex, boneIndex, frameData, numFrames, frameLengthInMs, fadeOutInSecs, fadeInInSecs, maxDelta);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId get_bone(TSceneManager *sceneManager,
|
||||
EntityId entityId,
|
||||
int skinIndex,
|
||||
int boneIndex)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->getBone(entityId, skinIndex, boneIndex);
|
||||
}
|
||||
EMSCRIPTEN_KEEPALIVE void get_world_transform(TSceneManager *sceneManager,
|
||||
EntityId entityId, float *const out)
|
||||
{
|
||||
auto transform = ((SceneManager *)sceneManager)->getWorldTransform(entityId);
|
||||
out[0] = transform[0][0];
|
||||
out[1] = transform[0][1];
|
||||
out[2] = transform[0][2];
|
||||
out[3] = transform[0][3];
|
||||
out[4] = transform[1][0];
|
||||
out[5] = transform[1][1];
|
||||
out[6] = transform[1][2];
|
||||
out[7] = transform[1][3];
|
||||
out[8] = transform[2][0];
|
||||
out[9] = transform[2][1];
|
||||
out[10] = transform[2][2];
|
||||
out[11] = transform[2][3];
|
||||
out[12] = transform[3][0];
|
||||
out[13] = transform[3][1];
|
||||
out[14] = transform[3][2];
|
||||
out[15] = transform[3][3];
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void get_local_transform(TSceneManager *sceneManager,
|
||||
EntityId entityId, float *const out)
|
||||
{
|
||||
auto transform = ((SceneManager *)sceneManager)->getLocalTransform(entityId);
|
||||
out[0] = transform[0][0];
|
||||
out[1] = transform[0][1];
|
||||
out[2] = transform[0][2];
|
||||
out[3] = transform[0][3];
|
||||
out[4] = transform[1][0];
|
||||
out[5] = transform[1][1];
|
||||
out[6] = transform[1][2];
|
||||
out[7] = transform[1][3];
|
||||
out[8] = transform[2][0];
|
||||
out[9] = transform[2][1];
|
||||
out[10] = transform[2][2];
|
||||
out[11] = transform[2][3];
|
||||
out[12] = transform[3][0];
|
||||
out[13] = transform[3][1];
|
||||
out[14] = transform[3][2];
|
||||
out[15] = transform[3][3];
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void get_rest_local_transforms(TSceneManager *sceneManager,
|
||||
EntityId entityId, int skinIndex, float *const out, int numBones)
|
||||
{
|
||||
const auto transforms = ((SceneManager *)sceneManager)->getBoneRestTranforms(entityId, skinIndex);
|
||||
auto numTransforms = transforms->size();
|
||||
if (numTransforms != numBones)
|
||||
{
|
||||
Log("Error - %d bone transforms available but you only specified %d.", numTransforms, numBones);
|
||||
return;
|
||||
}
|
||||
for (int boneIndex = 0; boneIndex < numTransforms; boneIndex++)
|
||||
{
|
||||
const auto transform = transforms->at(boneIndex);
|
||||
for (int colNum = 0; colNum < 4; colNum++)
|
||||
{
|
||||
for (int rowNum = 0; rowNum < 4; rowNum++)
|
||||
{
|
||||
out[(boneIndex * 16) + (colNum * 4) + rowNum] = transform[colNum][rowNum];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void get_inverse_bind_matrix(TSceneManager *sceneManager,
|
||||
EntityId entityId, int skinIndex, int boneIndex, float *const out)
|
||||
{
|
||||
auto transform = ((SceneManager *)sceneManager)->getInverseBindMatrix(entityId, skinIndex, boneIndex);
|
||||
out[0] = transform[0][0];
|
||||
out[1] = transform[0][1];
|
||||
out[2] = transform[0][2];
|
||||
out[3] = transform[0][3];
|
||||
out[4] = transform[1][0];
|
||||
out[5] = transform[1][1];
|
||||
out[6] = transform[1][2];
|
||||
out[7] = transform[1][3];
|
||||
out[8] = transform[2][0];
|
||||
out[9] = transform[2][1];
|
||||
out[10] = transform[2][2];
|
||||
out[11] = transform[2][3];
|
||||
out[12] = transform[3][0];
|
||||
out[13] = transform[3][1];
|
||||
out[14] = transform[3][2];
|
||||
out[15] = transform[3][3];
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool set_bone_transform(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId entityId,
|
||||
int skinIndex,
|
||||
int boneIndex,
|
||||
const float *const transform)
|
||||
{
|
||||
auto matrix = math::mat4f(
|
||||
transform[0], transform[1], transform[2],
|
||||
transform[3],
|
||||
transform[4],
|
||||
transform[5],
|
||||
transform[6],
|
||||
transform[7],
|
||||
transform[8],
|
||||
transform[9],
|
||||
transform[10],
|
||||
transform[11],
|
||||
transform[12],
|
||||
transform[13],
|
||||
transform[14],
|
||||
transform[15]);
|
||||
return ((SceneManager *)sceneManager)->setBoneTransform(entityId, skinIndex, boneIndex, matrix);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void play_animation(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
int index,
|
||||
bool loop,
|
||||
bool reverse,
|
||||
bool replaceActive,
|
||||
float crossfade,
|
||||
float startOffset)
|
||||
{
|
||||
((SceneManager *)sceneManager)->playAnimation(asset, index, loop, reverse, replaceActive, crossfade, startOffset);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_animation_frame(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
int animationIndex,
|
||||
int animationFrame)
|
||||
{
|
||||
// ((SceneManager*)sceneManager)->setAnimationFrame(asset, animationIndex, animationFrame);
|
||||
}
|
||||
|
||||
float get_animation_duration(TSceneManager *sceneManager, EntityId asset, int animationIndex)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->getAnimationDuration(asset, animationIndex);
|
||||
}
|
||||
|
||||
int get_animation_count(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId asset)
|
||||
{
|
||||
auto names = ((SceneManager *)sceneManager)->getAnimationNames(asset);
|
||||
return (int)names->size();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void get_animation_name(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
char *const outPtr,
|
||||
int index)
|
||||
{
|
||||
auto names = ((SceneManager *)sceneManager)->getAnimationNames(asset);
|
||||
std::string name = names->at(index);
|
||||
strcpy(outPtr, name.c_str());
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int get_bone_count(TSceneManager *sceneManager, EntityId assetEntity, int skinIndex)
|
||||
{
|
||||
auto names = ((SceneManager *)sceneManager)->getBoneNames(assetEntity, skinIndex);
|
||||
return names->size();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void get_bone_names(TSceneManager *sceneManager, EntityId assetEntity, const char **out, int skinIndex)
|
||||
{
|
||||
auto names = ((SceneManager *)sceneManager)->getBoneNames(assetEntity, skinIndex);
|
||||
for (int i = 0; i < names->size(); i++)
|
||||
{
|
||||
auto name_c = names->at(i).c_str();
|
||||
memcpy((void *)out[i], name_c, strlen(name_c) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool update_bone_matrices(TSceneManager *sceneManager, EntityId entityId)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->updateBoneMatrices(entityId);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int get_morph_target_name_count(TSceneManager *sceneManager, EntityId assetEntity, EntityId childEntity)
|
||||
{
|
||||
auto names = ((SceneManager *)sceneManager)->getMorphTargetNames(assetEntity, childEntity);
|
||||
return (int)names->size();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void get_morph_target_name(TSceneManager *sceneManager, EntityId assetEntity, EntityId childEntity, char *const outPtr, int index)
|
||||
{
|
||||
auto names = ((SceneManager *)sceneManager)->getMorphTargetNames(assetEntity, childEntity);
|
||||
std::string name = names->at(index);
|
||||
strcpy(outPtr, name.c_str());
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void remove_entity(TViewer *viewer, EntityId asset)
|
||||
{
|
||||
((FilamentViewer *)viewer)->removeEntity(asset);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void clear_entities(TViewer *viewer)
|
||||
{
|
||||
((FilamentViewer *)viewer)->clearEntities();
|
||||
}
|
||||
|
||||
bool set_material_color(TSceneManager *sceneManager, EntityId asset, const char *meshName, int materialIndex, const float r, const float g, const float b, const float a)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->setMaterialColor(asset, meshName, materialIndex, r, g, b, a);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void transform_to_unit_cube(TSceneManager *sceneManager, EntityId asset)
|
||||
{
|
||||
((SceneManager *)sceneManager)->transformToUnitCube(asset);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_position(TSceneManager *sceneManager, EntityId asset, float x, float y, float z)
|
||||
{
|
||||
((SceneManager *)sceneManager)->setPosition(asset, x, y, z);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_rotation(TSceneManager *sceneManager, EntityId asset, float rads, float x, float y, float z, float w)
|
||||
{
|
||||
((SceneManager *)sceneManager)->setRotation(asset, rads, x, y, z, w);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_scale(TSceneManager *sceneManager, EntityId asset, float scale)
|
||||
{
|
||||
((SceneManager *)sceneManager)->setScale(asset, scale);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void queue_position_update_from_viewport_coords(TSceneManager *sceneManager, TView *tView, EntityId entity, float viewportX, float viewportY)
|
||||
{
|
||||
auto *view = reinterpret_cast<View*>(tView);
|
||||
((SceneManager *)sceneManager)->queueRelativePositionUpdateFromViewportVector(view, entity, viewportX, viewportY);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void stop_animation(TSceneManager *sceneManager, EntityId asset, int index)
|
||||
{
|
||||
((SceneManager *)sceneManager)->stopAnimation(asset, index);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int hide_mesh(TSceneManager *sceneManager, EntityId asset, const char *meshName)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->hide(asset, meshName);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int reveal_mesh(TSceneManager *sceneManager, EntityId asset, const char *meshName)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->reveal(asset, meshName);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE const char *get_name_for_entity(TSceneManager *sceneManager, const EntityId entityId)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->getNameForEntity(entityId);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int get_entity_count(TSceneManager *sceneManager, const EntityId target, bool renderableOnly)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->getEntityCount(target, renderableOnly);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void get_entities(TSceneManager *sceneManager, const EntityId target, bool renderableOnly, EntityId *out)
|
||||
{
|
||||
((SceneManager *)sceneManager)->getEntities(target, renderableOnly, out);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE const char *get_entity_name_at(TSceneManager *sceneManager, const EntityId target, int index, bool renderableOnly)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->getEntityNameAt(target, index, renderableOnly);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void ios_dummy()
|
||||
{
|
||||
Log("Dummy called");
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void thermion_filament_free(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void add_collision_component(TSceneManager *sceneManager, EntityId entityId, void (*onCollisionCallback)(const EntityId entityId1, const EntityId entityId2), bool affectsCollidingTransform)
|
||||
{
|
||||
((SceneManager *)sceneManager)->addCollisionComponent(entityId, onCollisionCallback, affectsCollidingTransform);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void remove_collision_component(TSceneManager *sceneManager, EntityId entityId)
|
||||
{
|
||||
((SceneManager *)sceneManager)->removeCollisionComponent(entityId);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool add_animation_component(TSceneManager *sceneManager, EntityId entityId)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->addAnimationComponent(entityId);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void remove_animation_component(TSceneManager *sceneManager, EntityId entityId)
|
||||
{
|
||||
((SceneManager *)sceneManager)->removeAnimationComponent(entityId);
|
||||
}
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId find_child_entity_by_name(TSceneManager *sceneManager, const EntityId parent, const char *name)
|
||||
{
|
||||
auto entity = ((SceneManager *)sceneManager)->findChildEntityByName(parent, name);
|
||||
return utils::Entity::smuggle(entity);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId get_parent(TSceneManager *sceneManager, EntityId child)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->getParent(child);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId get_ancestor(TSceneManager *sceneManager, EntityId child)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->getAncestor(child);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_parent(TSceneManager *sceneManager, EntityId child, EntityId parent, bool preserveScaling)
|
||||
{
|
||||
((SceneManager *)sceneManager)->setParent(child, parent, preserveScaling);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void test_collisions(TSceneManager *sceneManager, EntityId entity)
|
||||
{
|
||||
((SceneManager *)sceneManager)->testCollisions(entity);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_priority(TSceneManager *sceneManager, EntityId entity, int priority)
|
||||
{
|
||||
((SceneManager *)sceneManager)->setPriority(entity, priority);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE Aabb2 get_bounding_box(TSceneManager *sceneManager, TView *tView, EntityId entity)
|
||||
{
|
||||
auto view = reinterpret_cast<View*>(tView);
|
||||
return ((SceneManager *)sceneManager)->getScreenSpaceBoundingBox(view, entity);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void get_bounding_box_to_out(TSceneManager *sceneManager, TView *tView, EntityId entity, float *minX, float *minY, float *maxX, float *maxY)
|
||||
{
|
||||
auto view = reinterpret_cast<View*>(tView);
|
||||
auto box = ((SceneManager *)sceneManager)->getScreenSpaceBoundingBox(view, entity);
|
||||
*minX = box.minX;
|
||||
*minY = box.minY;
|
||||
*maxX = box.maxX;
|
||||
*maxY = box.maxY;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void thermion_flutter_free(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_stencil_highlight(TSceneManager *sceneManager, EntityId entityId, float r, float g, float b)
|
||||
{
|
||||
((SceneManager *)sceneManager)->setStencilHighlight(entityId, r, g, b);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void remove_stencil_highlight(TSceneManager *sceneManager, EntityId entityId)
|
||||
{
|
||||
((SceneManager *)sceneManager)->removeStencilHighlight(entityId);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_material_property_float(TSceneManager *sceneManager, EntityId entity, int materialIndex, const char *property, float value)
|
||||
{
|
||||
((SceneManager *)sceneManager)->setMaterialProperty(entity, materialIndex, property, value);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialInstance *get_material_instance_at(TSceneManager *sceneManager, EntityId entity, int materialIndex)
|
||||
{
|
||||
auto instance = ((SceneManager *)sceneManager)->getMaterialInstanceAt(entity, materialIndex);
|
||||
return reinterpret_cast<TMaterialInstance *>(instance);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_material_property_int(TSceneManager *sceneManager, EntityId entity, int materialIndex, const char *property, int32_t value)
|
||||
{
|
||||
((SceneManager *)sceneManager)->setMaterialProperty(entity, materialIndex, property, value);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_material_property_float4(TSceneManager *sceneManager, EntityId entity, int materialIndex, const char *property, double4 value)
|
||||
{
|
||||
filament::math::float4 filamentValue;
|
||||
filamentValue.x = static_cast<float>(value.x);
|
||||
filamentValue.y = static_cast<float>(value.y);
|
||||
filamentValue.z = static_cast<float>(value.z);
|
||||
filamentValue.w = static_cast<float>(value.w);
|
||||
((SceneManager *)sceneManager)->setMaterialProperty(entity, materialIndex, property, filamentValue);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void unproject_texture(TViewer *viewer, EntityId entity, uint8_t *input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight)
|
||||
{
|
||||
((FilamentViewer *)viewer)->unprojectTexture(entity, input, inputWidth, inputHeight, out, outWidth, outHeight);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void *const create_texture(TSceneManager *sceneManager, uint8_t *data, size_t length)
|
||||
{
|
||||
return (void *const)((SceneManager *)sceneManager)->createTexture(data, length, "SOMETEXTURE");
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void apply_texture_to_material(TSceneManager *sceneManager, EntityId entity, void *const texture, const char *parameterName, int materialIndex)
|
||||
{
|
||||
((SceneManager *)sceneManager)->applyTexture(entity, reinterpret_cast<Texture *>(texture), parameterName, materialIndex);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void destroy_texture(TSceneManager *sceneManager, void *const texture)
|
||||
{
|
||||
((SceneManager *)sceneManager)->destroyTexture(reinterpret_cast<Texture *>(texture));
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialInstance *create_material_instance(TSceneManager *sceneManager, TMaterialKey materialConfig)
|
||||
{
|
||||
|
||||
filament::gltfio::MaterialKey config;
|
||||
memset(&config, 0, sizeof(MaterialKey));
|
||||
|
||||
// Set and log each field
|
||||
config.unlit = materialConfig.unlit;
|
||||
config.doubleSided = materialConfig.doubleSided;
|
||||
config.useSpecularGlossiness = materialConfig.useSpecularGlossiness;
|
||||
config.alphaMode = static_cast<filament::gltfio::AlphaMode>(materialConfig.alphaMode);
|
||||
config.hasBaseColorTexture = materialConfig.hasBaseColorTexture;
|
||||
config.hasClearCoat = materialConfig.hasClearCoat;
|
||||
config.hasClearCoatNormalTexture = materialConfig.hasClearCoatNormalTexture;
|
||||
config.hasClearCoatRoughnessTexture = materialConfig.hasClearCoatRoughnessTexture;
|
||||
config.hasEmissiveTexture = materialConfig.hasEmissiveTexture;
|
||||
config.hasIOR = materialConfig.hasIOR;
|
||||
config.hasMetallicRoughnessTexture = materialConfig.hasMetallicRoughnessTexture;
|
||||
config.hasNormalTexture = materialConfig.hasNormalTexture;
|
||||
config.hasOcclusionTexture = materialConfig.hasOcclusionTexture;
|
||||
config.hasSheen = materialConfig.hasSheen;
|
||||
config.hasSheenColorTexture = materialConfig.hasSheenColorTexture;
|
||||
config.hasSheenRoughnessTexture = materialConfig.hasSheenRoughnessTexture;
|
||||
config.hasTextureTransforms = materialConfig.hasTextureTransforms;
|
||||
config.hasTransmission = materialConfig.hasTransmission;
|
||||
config.hasTransmissionTexture = materialConfig.hasTransmissionTexture;
|
||||
config.hasVolume = materialConfig.hasVolume;
|
||||
config.hasVolumeThicknessTexture = materialConfig.hasVolumeThicknessTexture;
|
||||
config.baseColorUV = materialConfig.baseColorUV;
|
||||
config.hasVertexColors = materialConfig.hasVertexColors;
|
||||
auto materialInstance = ((SceneManager *)sceneManager)->createUbershaderMaterialInstance(config);
|
||||
return reinterpret_cast<TMaterialInstance *>(materialInstance);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TCamera *Engine_getCameraComponent(TEngine *tEngine, EntityId entityId)
|
||||
{
|
||||
auto *engine = reinterpret_cast<Engine *>(tEngine);
|
||||
auto *camera = engine->getCameraComponent(utils::Entity::import(entityId));
|
||||
return reinterpret_cast<TCamera *>(camera);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_setTransform(TEngine *tEngine, EntityId entity, double4x4 transform)
|
||||
{
|
||||
auto *engine = reinterpret_cast<Engine *>(tEngine);
|
||||
auto &transformManager = engine->getTransformManager();
|
||||
|
||||
auto transformInstance = transformManager.getInstance(utils::Entity::import(entity));
|
||||
if (!transformInstance.isValid())
|
||||
{
|
||||
Log("Transform instance not valid");
|
||||
}
|
||||
transformManager.setTransform(transformInstance, convert_double4x4_to_mat4(transform));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "CustomGeometry.hpp"
|
||||
#include "scene/CustomGeometry.hpp"
|
||||
#include "UnprojectTexture.hpp"
|
||||
|
||||
namespace thermion
|
||||
|
||||
300
thermion_dart/native/src/c_api/TAnimationManager.cpp
Normal file
300
thermion_dart/native/src/c_api/TAnimationManager.cpp
Normal file
@@ -0,0 +1,300 @@
|
||||
#include "Log.hpp"
|
||||
|
||||
#include "c_api/APIExport.h"
|
||||
#include "scene/AnimationManager.hpp"
|
||||
|
||||
using namespace thermion;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
#include "c_api/TAnimationManager.h"
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_addAnimationComponent(TAnimationManager *tAnimationManager, EntityId entityId)
|
||||
{
|
||||
auto animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
animationManager->addAnimationComponent(entityId);
|
||||
}
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_removeAnimationComponent(TAnimationManager *tAnimationManager, EntityId entityId)
|
||||
{
|
||||
auto animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
animationManager->removeAnimationComponent(entityId);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool AnimationManager_setMorphAnimation(
|
||||
TAnimationManager *tAnimationManager,
|
||||
EntityId entityId,
|
||||
const float *const morphData,
|
||||
const uint32_t *const morphIndices,
|
||||
int numMorphTargets,
|
||||
int numFrames,
|
||||
float frameLengthInMs)
|
||||
{
|
||||
auto entity = utils::Entity::import(entityId);
|
||||
auto *animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto result = animationManager->setMorphAnimationBuffer(entity, morphData, morphIndices, numMorphTargets, numFrames, frameLengthInMs);
|
||||
return result;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool AnimationManager_setMorphTargetWeights(
|
||||
TAnimationManager *tAnimationManager,
|
||||
EntityId entityId,
|
||||
const float *const morphData,
|
||||
int numWeights)
|
||||
{
|
||||
auto entity = utils::Entity::import(entityId);
|
||||
auto *animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
animationManager->setMorphTargetWeights(entity, morphData, numWeights);
|
||||
return true;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool AnimationManager_clearMorphAnimation(TAnimationManager *tAnimationManager, EntityId entityId)
|
||||
{
|
||||
auto *animManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto entity = utils::Entity::import(entityId);
|
||||
animManager->clearMorphAnimationBuffer(entity);
|
||||
return true;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_resetToRestPose(TAnimationManager *tAnimationManager, TSceneAsset *sceneAsset)
|
||||
{
|
||||
auto *animManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto asset = reinterpret_cast<SceneAsset *>(sceneAsset);
|
||||
if (asset->getType() == SceneAsset::SceneAssetType::Gltf && asset->isInstance())
|
||||
{
|
||||
auto *instance = reinterpret_cast<GltfSceneAssetInstance *>(asset);
|
||||
animManager->resetToRestPose(instance);
|
||||
}
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_addBoneAnimation(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
int skinIndex,
|
||||
int boneIndex,
|
||||
const float *const frameData,
|
||||
int numFrames,
|
||||
float frameLengthInMs,
|
||||
float fadeOutInSecs,
|
||||
float fadeInInSecs,
|
||||
float maxDelta)
|
||||
{
|
||||
auto *animManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto asset = reinterpret_cast<SceneAsset *>(sceneAsset);
|
||||
if (asset->getType() == SceneAsset::SceneAssetType::Gltf && asset->isInstance())
|
||||
{
|
||||
animManager->addBoneAnimation(reinterpret_cast<GltfSceneAssetInstance *>(asset), skinIndex, boneIndex, frameData, numFrames, frameLengthInMs,
|
||||
fadeOutInSecs, fadeInInSecs, maxDelta);
|
||||
}
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId AnimationManager_getBone(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
int skinIndex,
|
||||
int boneIndex)
|
||||
{
|
||||
auto *animManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto asset = reinterpret_cast<SceneAsset *>(sceneAsset);
|
||||
if (asset->getType() == SceneAsset::SceneAssetType::Gltf && asset->isInstance())
|
||||
{
|
||||
auto entities = animManager->getBoneEntities(reinterpret_cast<GltfSceneAssetInstance *>(asset), skinIndex);
|
||||
if (boneIndex < entities.size())
|
||||
{
|
||||
return utils::Entity::smuggle(entities[boneIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_getRestLocalTransforms(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
int skinIndex,
|
||||
float *const out,
|
||||
int numBones)
|
||||
{
|
||||
auto *animManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto asset = reinterpret_cast<SceneAsset *>(sceneAsset);
|
||||
if (asset->getType() == SceneAsset::SceneAssetType::Gltf && asset->isInstance())
|
||||
{
|
||||
auto *instance = reinterpret_cast<GltfSceneAssetInstance *>(asset);
|
||||
const auto transforms = animManager->getBoneRestTranforms(instance, skinIndex);
|
||||
auto numTransforms = transforms.size();
|
||||
if (numTransforms != numBones)
|
||||
{
|
||||
Log("Error - %d bone transforms available but you only specified %d.", numTransforms, numBones);
|
||||
return;
|
||||
}
|
||||
for (int boneIndex = 0; boneIndex < numTransforms; boneIndex++)
|
||||
{
|
||||
const auto transform = transforms[boneIndex];
|
||||
for (int colNum = 0; colNum < 4; colNum++)
|
||||
{
|
||||
for (int rowNum = 0; rowNum < 4; rowNum++)
|
||||
{
|
||||
out[(boneIndex * 16) + (colNum * 4) + rowNum] = transform[colNum][rowNum];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_getInverseBindMatrix(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
int skinIndex,
|
||||
int boneIndex,
|
||||
float *const out)
|
||||
{
|
||||
auto *animManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto asset = reinterpret_cast<SceneAsset *>(sceneAsset);
|
||||
if (asset->getType() == SceneAsset::SceneAssetType::Gltf && asset->isInstance())
|
||||
{
|
||||
auto *instance = reinterpret_cast<GltfSceneAssetInstance *>(asset);
|
||||
auto transform = animManager->getInverseBindMatrix(instance, skinIndex, boneIndex);
|
||||
for (int colNum = 0; colNum < 4; colNum++)
|
||||
{
|
||||
for (int rowNum = 0; rowNum < 4; rowNum++)
|
||||
{
|
||||
out[(colNum * 4) + rowNum] = transform[colNum][rowNum];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_playAnimation(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
int index,
|
||||
bool loop,
|
||||
bool reverse,
|
||||
bool replaceActive,
|
||||
float crossfade,
|
||||
float startOffset)
|
||||
{
|
||||
auto *animManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto asset = reinterpret_cast<SceneAsset *>(sceneAsset);
|
||||
if (asset->getType() == SceneAsset::SceneAssetType::Gltf && asset->isInstance())
|
||||
{
|
||||
auto *instance = reinterpret_cast<GltfSceneAssetInstance *>(asset);
|
||||
|
||||
animManager->playGltfAnimation(instance, index, loop, reverse, replaceActive, crossfade, startOffset);
|
||||
}
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_stopAnimation(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
int index)
|
||||
{
|
||||
auto *animManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto asset = reinterpret_cast<SceneAsset *>(sceneAsset);
|
||||
if (asset->getType() == SceneAsset::SceneAssetType::Gltf && asset->isInstance())
|
||||
{
|
||||
auto *instance = reinterpret_cast<GltfSceneAssetInstance *>(asset);
|
||||
|
||||
animManager->stopGltfAnimation(instance, index);
|
||||
}
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_setGltfAnimationFrame(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *tSceneAsset,
|
||||
int animationIndex,
|
||||
int frame)
|
||||
{
|
||||
auto *animManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto asset = reinterpret_cast<SceneAsset *>(tSceneAsset);
|
||||
if (asset->getType() == SceneAsset::SceneAssetType::Gltf && asset->isInstance())
|
||||
{
|
||||
auto *instance = reinterpret_cast<GltfSceneAssetInstance *>(asset);
|
||||
animManager->setGltfAnimationFrame(instance, animationIndex, frame);
|
||||
}
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE float AnimationManager_getAnimationDuration(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
int animationIndex)
|
||||
{
|
||||
auto instance = ((GltfSceneAssetInstance *)sceneAsset);
|
||||
return ((AnimationManager *)tAnimationManager)->getGltfAnimationDuration(instance, animationIndex);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int AnimationManager_getAnimationCount(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset)
|
||||
{
|
||||
auto instance = ((GltfSceneAssetInstance *)sceneAsset);
|
||||
auto names = ((AnimationManager *)tAnimationManager)->getGltfAnimationNames(instance);
|
||||
return (int)names.size();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_getAnimationName(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
char *const outPtr,
|
||||
int index)
|
||||
{
|
||||
auto instance = ((GltfSceneAssetInstance *)sceneAsset);
|
||||
auto names = ((AnimationManager *)tAnimationManager)->getGltfAnimationNames(instance);
|
||||
std::string name = names[index];
|
||||
strcpy(outPtr, name.c_str());
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int AnimationManager_getBoneCount(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
int skinIndex)
|
||||
{
|
||||
auto instance = ((GltfSceneAssetInstance *)sceneAsset);
|
||||
auto entities = ((AnimationManager *)tAnimationManager)->getBoneEntities(instance, skinIndex);
|
||||
return (int)entities.size();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_getBoneNames(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
const char **out,
|
||||
int skinIndex)
|
||||
{
|
||||
auto instance = ((GltfSceneAssetInstance *)sceneAsset);
|
||||
auto entities = ((AnimationManager *)tAnimationManager)->getBoneEntities(instance, skinIndex);
|
||||
// Note: This needs implementation of a method to get bone names from entities
|
||||
// Current source doesn't show how bone names are retrieved
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool AnimationManager_updateBoneMatrices(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset)
|
||||
{
|
||||
auto instance = ((GltfSceneAssetInstance *)sceneAsset);
|
||||
((AnimationManager *)tAnimationManager)->updateBoneMatrices(instance);
|
||||
return true;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int AnimationManager_getMorphTargetNameCount(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
EntityId childEntity)
|
||||
{
|
||||
auto asset = ((GltfSceneAsset *)sceneAsset);
|
||||
auto names = ((AnimationManager *)tAnimationManager)->getMorphTargetNames(asset, childEntity);
|
||||
return (int)names.size();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_getMorphTargetName(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
EntityId childEntity,
|
||||
char *const outPtr,
|
||||
int index)
|
||||
{
|
||||
auto asset = ((GltfSceneAsset *)sceneAsset);
|
||||
auto names = ((AnimationManager *)tAnimationManager)->getMorphTargetNames(asset, childEntity);
|
||||
std::string name = names[index];
|
||||
strcpy(outPtr, name.c_str());
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,11 @@
|
||||
#include <filament/Camera.h>
|
||||
#include <utils/Entity.h>
|
||||
|
||||
#include "ThermionDartApi.h"
|
||||
#include "TCamera.h"
|
||||
#include "ThermionDartAPIUtils.h"
|
||||
|
||||
#include "c_api/ThermionDartApi.h"
|
||||
#include "c_api/TCamera.h"
|
||||
#include "Log.hpp"
|
||||
#include "MathUtils.hpp"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace thermion
|
||||
41
thermion_dart/native/src/c_api/TGizmo.cpp
Normal file
41
thermion_dart/native/src/c_api/TGizmo.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#include <filament/View.h>
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/Scene.h>
|
||||
|
||||
#include "c_api/TGizmo.h"
|
||||
#include "scene/Gizmo.hpp"
|
||||
#include "Log.hpp"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace thermion
|
||||
{
|
||||
extern "C"
|
||||
{
|
||||
using namespace filament;
|
||||
#endif
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Gizmo_pick(TGizmo *tGizmo, uint32_t x, uint32_t y, GizmoPickCallback callback)
|
||||
{
|
||||
auto *gizmo = reinterpret_cast<Gizmo *>(tGizmo);
|
||||
gizmo->pick(x, y, reinterpret_cast<Gizmo::GizmoPickCallback>(callback));
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Gizmo_highlight(TGizmo *tGizmo, TGizmoAxis tAxis)
|
||||
{
|
||||
auto *gizmo = reinterpret_cast<Gizmo *>(tGizmo);
|
||||
auto axis = static_cast<Gizmo::Axis>(tAxis);
|
||||
gizmo->highlight(axis);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Gizmo_unhighlight(TGizmo *tGizmo)
|
||||
{
|
||||
auto *gizmo = reinterpret_cast<Gizmo *>(tGizmo);
|
||||
gizmo->unhighlight(Gizmo::Axis::X);
|
||||
gizmo->unhighlight(Gizmo::Axis::Y);
|
||||
gizmo->unhighlight(Gizmo::Axis::Z);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
#endif
|
||||
136
thermion_dart/native/src/c_api/TMaterialInstance.cpp
Normal file
136
thermion_dart/native/src/c_api/TMaterialInstance.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
#include <filament/MaterialInstance.h>
|
||||
#include <math/mat4.h>
|
||||
#include <math/vec4.h>
|
||||
#include <math/vec2.h>
|
||||
|
||||
#include "Log.hpp"
|
||||
#include "c_api/TMaterialInstance.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace thermion
|
||||
{
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool MaterialInstance_isStencilWriteEnabled(TMaterialInstance *tMaterialInstance)
|
||||
{
|
||||
return reinterpret_cast<::filament::MaterialInstance *>(tMaterialInstance)->isStencilWriteEnabled();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthWrite(TMaterialInstance *materialInstance, bool enabled)
|
||||
{
|
||||
reinterpret_cast<::filament::MaterialInstance *>(materialInstance)->setDepthWrite(enabled);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthCulling(TMaterialInstance *materialInstance, bool enabled)
|
||||
{
|
||||
reinterpret_cast<::filament::MaterialInstance *>(materialInstance)->setDepthCulling(enabled);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat4(TMaterialInstance *tMaterialInstance, const char *propertyName, double x, double y, double z, double w)
|
||||
{
|
||||
auto *materialInstance = reinterpret_cast<::filament::MaterialInstance *>(tMaterialInstance);
|
||||
filament::math::float4 data{static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(w)};
|
||||
materialInstance->setParameter(propertyName, data);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat2(TMaterialInstance *materialInstance, const char *propertyName, double x, double y)
|
||||
{
|
||||
filament::math::float2 data{static_cast<float>(x), static_cast<float>(y)};
|
||||
reinterpret_cast<::filament::MaterialInstance *>(materialInstance)->setParameter(propertyName, data);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat(TMaterialInstance *materialInstance, const char *propertyName, double value)
|
||||
{
|
||||
reinterpret_cast<::filament::MaterialInstance *>(materialInstance)->setParameter(propertyName, static_cast<float>(value));
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterInt(TMaterialInstance *materialInstance, const char *propertyName, int value)
|
||||
{
|
||||
reinterpret_cast<::filament::MaterialInstance *>(materialInstance)->setParameter(propertyName, value);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthFunc(TMaterialInstance *tMaterialInstance, TSamplerCompareFunc tDepthFunc)
|
||||
{
|
||||
auto *materialInstance = reinterpret_cast<::filament::MaterialInstance *>(tMaterialInstance);
|
||||
auto depthFunc = static_cast<filament::MaterialInstance::DepthFunc>(tDepthFunc);
|
||||
materialInstance->setDepthFunc(depthFunc);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setStencilOpStencilFail(TMaterialInstance *tMaterialInstance,
|
||||
TStencilOperation tOp, TStencilFace tFace)
|
||||
{
|
||||
auto *materialInstance = reinterpret_cast<::filament::MaterialInstance *>(tMaterialInstance);
|
||||
auto op = static_cast<filament::MaterialInstance::StencilOperation>(tOp);
|
||||
auto face = static_cast<filament::MaterialInstance::StencilFace>(tFace);
|
||||
materialInstance->setStencilOpStencilFail(op, face);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setStencilOpDepthFail(TMaterialInstance *tMaterialInstance,
|
||||
TStencilOperation tOp, TStencilFace tFace)
|
||||
{
|
||||
auto *materialInstance = reinterpret_cast<::filament::MaterialInstance *>(tMaterialInstance);
|
||||
auto op = static_cast<filament::MaterialInstance::StencilOperation>(tOp);
|
||||
auto face = static_cast<filament::MaterialInstance::StencilFace>(tFace);
|
||||
materialInstance->setStencilOpDepthFail(op, face);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setStencilOpDepthStencilPass(TMaterialInstance *tMaterialInstance,
|
||||
TStencilOperation tOp, TStencilFace tFace)
|
||||
{
|
||||
auto *materialInstance = reinterpret_cast<::filament::MaterialInstance *>(tMaterialInstance);
|
||||
auto op = static_cast<filament::MaterialInstance::StencilOperation>(tOp);
|
||||
auto face = static_cast<filament::MaterialInstance::StencilFace>(tFace);
|
||||
materialInstance->setStencilOpDepthStencilPass(op, face);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setStencilCompareFunction(TMaterialInstance *tMaterialInstance,
|
||||
TSamplerCompareFunc tFunc, TStencilFace tFace)
|
||||
{
|
||||
auto *materialInstance = reinterpret_cast<::filament::MaterialInstance *>(tMaterialInstance);
|
||||
auto func = static_cast<filament::MaterialInstance::StencilCompareFunc>(tFunc);
|
||||
auto face = static_cast<filament::MaterialInstance::StencilFace>(tFace);
|
||||
materialInstance->setStencilCompareFunction(func, face);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setStencilReferenceValue(TMaterialInstance *tMaterialInstance,
|
||||
uint8_t value, TStencilFace tFace)
|
||||
{
|
||||
auto *materialInstance = reinterpret_cast<::filament::MaterialInstance *>(tMaterialInstance);
|
||||
auto face = static_cast<filament::MaterialInstance::StencilFace>(tFace);
|
||||
materialInstance->setStencilReferenceValue(value, face);
|
||||
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setStencilWrite(TMaterialInstance *materialInstance, bool enabled)
|
||||
{
|
||||
reinterpret_cast<::filament::MaterialInstance *>(materialInstance)->setStencilWrite(enabled);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setCullingMode(TMaterialInstance *materialInstance, TCullingMode culling)
|
||||
{
|
||||
auto *instance = reinterpret_cast<::filament::MaterialInstance *>(materialInstance);
|
||||
auto cullingMode = static_cast<filament::MaterialInstance::CullingMode>(culling);
|
||||
instance->setCullingMode(cullingMode);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setStencilReadMask(
|
||||
TMaterialInstance *materialInstance,
|
||||
uint8_t mask)
|
||||
{
|
||||
auto *instance = reinterpret_cast<::filament::MaterialInstance *>(materialInstance);
|
||||
instance->setStencilReadMask(mask);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setStencilWriteMask(
|
||||
TMaterialInstance *materialInstance,
|
||||
uint8_t mask)
|
||||
{
|
||||
auto *instance = reinterpret_cast<::filament::MaterialInstance *>(materialInstance);
|
||||
instance->setStencilWriteMask(mask);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
#endif
|
||||
57
thermion_dart/native/src/c_api/TMaterialProvider.cpp
Normal file
57
thermion_dart/native/src/c_api/TMaterialProvider.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#include <filament/MaterialInstance.h>
|
||||
#include <gltfio/MaterialProvider.h>
|
||||
#include <math/mat4.h>
|
||||
#include <math/vec4.h>
|
||||
#include <math/vec2.h>
|
||||
|
||||
#include "Log.hpp"
|
||||
#include "c_api/TMaterialProvider.h"
|
||||
#include "c_api/TMaterialInstance.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace thermion
|
||||
{
|
||||
using namespace filament;
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialInstance *MaterialProvider_createMaterialInstance(TMaterialProvider *tMaterialProvider, TMaterialKey *materialConfig)
|
||||
{
|
||||
gltfio::MaterialKey config;
|
||||
gltfio::UvMap uvMap;
|
||||
memset(&config, 0, sizeof(gltfio::MaterialKey));
|
||||
|
||||
// Set and log each field
|
||||
config.unlit = materialConfig->unlit;
|
||||
config.doubleSided = materialConfig->doubleSided;
|
||||
config.useSpecularGlossiness = materialConfig->useSpecularGlossiness;
|
||||
config.alphaMode = static_cast<filament::gltfio::AlphaMode>(materialConfig->alphaMode);
|
||||
config.hasBaseColorTexture = materialConfig->hasBaseColorTexture;
|
||||
config.hasClearCoat = materialConfig->hasClearCoat;
|
||||
config.hasClearCoatNormalTexture = materialConfig->hasClearCoatNormalTexture;
|
||||
config.hasClearCoatRoughnessTexture = materialConfig->hasClearCoatRoughnessTexture;
|
||||
config.hasEmissiveTexture = materialConfig->hasEmissiveTexture;
|
||||
config.hasIOR = materialConfig->hasIOR;
|
||||
config.hasMetallicRoughnessTexture = materialConfig->hasMetallicRoughnessTexture;
|
||||
config.hasNormalTexture = materialConfig->hasNormalTexture;
|
||||
config.hasOcclusionTexture = materialConfig->hasOcclusionTexture;
|
||||
config.hasSheen = materialConfig->hasSheen;
|
||||
config.hasSheenColorTexture = materialConfig->hasSheenColorTexture;
|
||||
config.hasSheenRoughnessTexture = materialConfig->hasSheenRoughnessTexture;
|
||||
config.hasTextureTransforms = materialConfig->hasTextureTransforms;
|
||||
config.hasTransmission = materialConfig->hasTransmission;
|
||||
config.hasTransmissionTexture = materialConfig->hasTransmissionTexture;
|
||||
config.hasVolume = materialConfig->hasVolume;
|
||||
config.hasVolumeThicknessTexture = materialConfig->hasVolumeThicknessTexture;
|
||||
config.baseColorUV = materialConfig->baseColorUV;
|
||||
config.hasVertexColors = materialConfig->hasVertexColors;
|
||||
|
||||
auto *materialProvider = reinterpret_cast<gltfio::MaterialProvider *>(tMaterialProvider);
|
||||
auto materialInstance = materialProvider->createMaterialInstance(&config, &uvMap);
|
||||
return reinterpret_cast<TMaterialInstance *>(materialInstance);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
#endif
|
||||
20
thermion_dart/native/src/c_api/TNameComponentManager.cpp
Normal file
20
thermion_dart/native/src/c_api/TNameComponentManager.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <utils/NameComponentManager.h>
|
||||
|
||||
#include "c_api/APIExport.h"
|
||||
#include "c_api/APIBoundaryTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE const char *NameComponentManager_getName(TNameComponentManager *tNameComponentManager, EntityId entity)
|
||||
{
|
||||
auto ncm = reinterpret_cast<utils::NameComponentManager *>(tNameComponentManager);
|
||||
auto instance = ncm->getInstance(utils::Entity::import(entity));
|
||||
return ncm->getName(instance);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
44
thermion_dart/native/src/c_api/TRenderableManager.cpp
Normal file
44
thermion_dart/native/src/c_api/TRenderableManager.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
#include <filament/MaterialInstance.h>
|
||||
#include <filament/RenderableManager.h>
|
||||
#include <utils/Entity.h>
|
||||
|
||||
#include "Log.hpp"
|
||||
#include "c_api/TRenderableManager.h"
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
extern "C"
|
||||
{
|
||||
using namespace filament;
|
||||
using namespace utils;
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void RenderableManager_setMaterialInstanceAt(TRenderableManager *tRenderableManager, EntityId entityId, int primitiveIndex, TMaterialInstance *tMaterialInstance)
|
||||
{
|
||||
auto *renderableManager = reinterpret_cast<filament::RenderableManager *>(tRenderableManager);
|
||||
const auto &entity = utils::Entity::import(entityId);
|
||||
auto renderableInstance = renderableManager->getInstance(entity);
|
||||
auto materialInstance = reinterpret_cast<MaterialInstance *>(tMaterialInstance);
|
||||
renderableManager->setMaterialInstanceAt(renderableInstance, primitiveIndex, materialInstance);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialInstance *RenderableManager_getMaterialInstanceAt(TRenderableManager *tRenderableManager, EntityId entityId, int primitiveIndex) {
|
||||
auto *renderableManager = reinterpret_cast<filament::RenderableManager *>(tRenderableManager);
|
||||
const auto &entity = utils::Entity::import(entityId);
|
||||
auto renderableInstance = renderableManager->getInstance(entity);
|
||||
if(!renderableInstance.isValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
auto materialInstance = renderableManager->getMaterialInstanceAt(renderableInstance, primitiveIndex);
|
||||
return reinterpret_cast<TMaterialInstance*>(materialInstance);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void RenderableManager_setPriority(TRenderableManager *tRenderableManager, EntityId entityId, int priority) {
|
||||
auto *renderableManager = reinterpret_cast<filament::RenderableManager *>(tRenderableManager);
|
||||
const auto &entity = utils::Entity::import(entityId);
|
||||
auto renderableInstance = renderableManager->getInstance(entity);
|
||||
renderableManager->setPriority(renderableInstance, priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
108
thermion_dart/native/src/c_api/TSceneAsset.cpp
Normal file
108
thermion_dart/native/src/c_api/TSceneAsset.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
#include "c_api/TSceneAsset.h"
|
||||
#include "scene/SceneAsset.hpp"
|
||||
#include "scene/GltfSceneAsset.hpp"
|
||||
|
||||
using namespace thermion;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void SceneAsset_addToScene(TSceneAsset *tSceneAsset, TScene *tScene) {
|
||||
auto *asset = reinterpret_cast<SceneAsset*>(tSceneAsset);
|
||||
auto *scene = reinterpret_cast<Scene*>(tScene);
|
||||
asset->addAllEntities(scene);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId SceneAsset_getEntity(TSceneAsset *tSceneAsset) {
|
||||
auto *asset = reinterpret_cast<SceneAsset*>(tSceneAsset);
|
||||
return utils::Entity::smuggle(asset->getEntity());
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int SceneAsset_getChildEntityCount(TSceneAsset* tSceneAsset) {
|
||||
auto *asset = reinterpret_cast<SceneAsset*>(tSceneAsset);
|
||||
return asset->getChildEntityCount();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void SceneAsset_getChildEntities(TSceneAsset* tSceneAsset, EntityId *out)
|
||||
{
|
||||
auto *asset = reinterpret_cast<SceneAsset*>(tSceneAsset);
|
||||
auto entities = asset->getChildEntities();
|
||||
for(int i = 0; i < asset->getChildEntityCount(); i++) {
|
||||
out[i] = utils::Entity::smuggle(entities[i]);
|
||||
}
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE const utils::Entity *SceneAsset_getCameraEntities(TSceneAsset* tSceneAsset)
|
||||
{
|
||||
auto *asset = reinterpret_cast<SceneAsset*>(tSceneAsset);
|
||||
if (asset->getType() == SceneAsset::SceneAssetType::Gltf && !asset->isInstance())
|
||||
{
|
||||
auto gltfSceneAsset = reinterpret_cast<GltfSceneAsset *>(asset);
|
||||
return gltfSceneAsset->getAsset()->getCameraEntities();
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::nullptr_t();
|
||||
}
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE size_t SceneAsset_getCameraEntityCount(TSceneAsset* tSceneAsset)
|
||||
{
|
||||
auto *asset = reinterpret_cast<SceneAsset*>(tSceneAsset);
|
||||
if (asset->getType() == SceneAsset::SceneAssetType::Gltf && !asset->isInstance())
|
||||
{
|
||||
auto gltfSceneAsset = reinterpret_cast<GltfSceneAsset *>(asset);
|
||||
return gltfSceneAsset->getAsset()->getCameraEntityCount();
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE const utils::Entity *SceneAsset_getLightEntities(TSceneAsset* tSceneAsset)
|
||||
{
|
||||
auto *asset = reinterpret_cast<SceneAsset*>(tSceneAsset);
|
||||
if (asset->getType() == SceneAsset::SceneAssetType::Gltf && !asset->isInstance())
|
||||
{
|
||||
auto gltfSceneAsset = reinterpret_cast<GltfSceneAsset *>(asset);
|
||||
return gltfSceneAsset->getAsset()->getLightEntities();
|
||||
}
|
||||
|
||||
return std::nullptr_t();
|
||||
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE size_t SceneAsset_getLightEntityCount(TSceneAsset* tSceneAsset)
|
||||
{
|
||||
auto *asset = reinterpret_cast<SceneAsset*>(tSceneAsset);
|
||||
if (asset->getType() == SceneAsset::SceneAssetType::Gltf && !asset->isInstance())
|
||||
{
|
||||
auto gltfSceneAsset = reinterpret_cast<GltfSceneAsset *>(asset);
|
||||
return gltfSceneAsset->getAsset()->getLightEntityCount();
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneAsset_getInstance(TSceneAsset *tSceneAsset, int index) {
|
||||
auto *asset = reinterpret_cast<SceneAsset*>(tSceneAsset);
|
||||
auto *instance = asset->getInstanceAt(index);
|
||||
return reinterpret_cast<TSceneAsset*>(instance);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneAsset_createInstance(TSceneAsset *tSceneAsset, TMaterialInstance **tMaterialInstances, int materialInstanceCount)
|
||||
{
|
||||
auto *materialInstances = reinterpret_cast<MaterialInstance **>(tMaterialInstances);
|
||||
auto *sceneAsset = reinterpret_cast<SceneAsset*>(tSceneAsset);
|
||||
auto *instance = sceneAsset->createInstance(materialInstances, materialInstanceCount);
|
||||
return reinterpret_cast<TSceneAsset *>(instance);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
219
thermion_dart/native/src/c_api/TSceneManager.cpp
Normal file
219
thermion_dart/native/src/c_api/TSceneManager.cpp
Normal file
@@ -0,0 +1,219 @@
|
||||
#include <filament/LightManager.h>
|
||||
|
||||
#include "c_api/APIExport.h"
|
||||
#include "ResourceBuffer.hpp"
|
||||
#include "FilamentViewer.hpp"
|
||||
#include "Log.hpp"
|
||||
|
||||
using namespace thermion;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
#include "c_api/TSceneManager.h"
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TScene *SceneManager_getScene(TSceneManager *tSceneManager) {
|
||||
auto sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
return reinterpret_cast<TScene*>(sceneManager->getScene());
|
||||
}
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialProvider *SceneManager_getUnlitMaterialProvider(TSceneManager *tSceneManager) {
|
||||
auto sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
auto provider = sceneManager->getUnlitMaterialProvider();
|
||||
return reinterpret_cast<TMaterialProvider*>(provider);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialProvider *SceneManager_getUbershaderMaterialProvider(TSceneManager *tSceneManager) {
|
||||
auto sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
auto provider = sceneManager->getUbershaderMaterialProvider();
|
||||
return reinterpret_cast<TMaterialProvider*>(provider);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TGizmo *SceneManager_createGizmo(TSceneManager *tSceneManager, TView *tView, TScene *tScene)
|
||||
{
|
||||
auto sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
auto *scene = reinterpret_cast<Scene *>(tScene);
|
||||
auto *view = reinterpret_cast<View *>(tView);
|
||||
auto gizmo = sceneManager->createGizmo(view, scene);
|
||||
return reinterpret_cast<TGizmo *>(gizmo);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneManager_loadGlb(TSceneManager *tSceneManager, const char *assetPath, int numInstances, bool keepData)
|
||||
{
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
auto *asset = sceneManager->loadGlb(assetPath, numInstances, keepData);
|
||||
return reinterpret_cast<TSceneAsset *>(asset);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneManager_loadGltf(TSceneManager *tSceneManager,
|
||||
const char *assetPath,
|
||||
const char *relativeResourcePath,
|
||||
bool keepData)
|
||||
{
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
auto *asset = sceneManager->loadGltf(assetPath, relativeResourcePath, 1, keepData);
|
||||
return reinterpret_cast<TSceneAsset *>(asset);
|
||||
}
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneManager_loadGlbFromBuffer(TSceneManager *tSceneManager, const uint8_t *const data, size_t length, bool keepData, int priority, int layer, bool loadResourcesAsync)
|
||||
{
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
auto *asset = sceneManager->loadGlbFromBuffer((const uint8_t *)data, length, 1, keepData, priority, layer, loadResourcesAsync);
|
||||
return reinterpret_cast<TSceneAsset *>(asset);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TCamera *SceneManager_getCameraByName(TSceneManager *tSceneManager, EntityId entityId, const char *name)
|
||||
{
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE Aabb3 SceneManager_getRenderableBoundingBox(TSceneManager *tSceneManager, EntityId entity)
|
||||
{
|
||||
auto sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
return sceneManager->getRenderableBoundingBox(entity);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_setVisibilityLayer(TSceneManager *tSceneManager, EntityId entity, int layer)
|
||||
{
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
sceneManager->setVisibilityLayer(entity, layer);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialInstance *SceneManager_createUnlitMaterialInstance(TSceneManager *sceneManager)
|
||||
{
|
||||
auto *instance = ((SceneManager *)sceneManager)->createUnlitMaterialInstance();
|
||||
return reinterpret_cast<TMaterialInstance *>(instance);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialInstance *SceneManager_createUnlitFixedSizeMaterialInstance(TSceneManager *sceneManager)
|
||||
{
|
||||
auto *instance = ((SceneManager *)sceneManager)->createUnlitFixedSizeMaterialInstance();
|
||||
return reinterpret_cast<TMaterialInstance *>(instance);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TCamera *SceneManager_createCamera(TSceneManager *tSceneManager)
|
||||
{
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
return reinterpret_cast<TCamera *>(sceneManager->createCamera());
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_destroyCamera(TSceneManager *tSceneManager, TCamera *tCamera)
|
||||
{
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
auto *camera = reinterpret_cast<Camera *>(tCamera);
|
||||
sceneManager->destroyCamera(camera);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE size_t SceneManager_getCameraCount(TSceneManager *tSceneManager)
|
||||
{
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
return sceneManager->getCameraCount();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TCamera *SceneManager_getCameraAt(TSceneManager *tSceneManager, size_t index)
|
||||
{
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
auto *camera = sceneManager->getCameraAt(index);
|
||||
return reinterpret_cast<TCamera *>(camera);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneManager_createGeometry(
|
||||
TSceneManager *tSceneManager,
|
||||
float *vertices,
|
||||
int numVertices,
|
||||
float *normals,
|
||||
int numNormals,
|
||||
float *uvs,
|
||||
int numUvs,
|
||||
uint16_t *indices,
|
||||
int numIndices,
|
||||
int primitiveType,
|
||||
TMaterialInstance **tMaterialInstances,
|
||||
int materialInstanceCount,
|
||||
bool keepData)
|
||||
{
|
||||
auto sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
auto castedNumVertices = static_cast<uint32_t>(numVertices);
|
||||
auto castedNumNormals = static_cast<uint32_t>(numNormals);
|
||||
auto castedNumUvs = static_cast<uint32_t>(numUvs);
|
||||
auto castedNumIndices = static_cast<uint32_t>(numIndices);
|
||||
auto castedPrimitiveType = static_cast<filament::RenderableManager::PrimitiveType>(primitiveType);
|
||||
auto materialInstances = reinterpret_cast<MaterialInstance **>(tMaterialInstances);
|
||||
|
||||
auto *asset = sceneManager->createGeometry(
|
||||
vertices,
|
||||
castedNumVertices,
|
||||
normals,
|
||||
castedNumNormals,
|
||||
uvs,
|
||||
castedNumUvs,
|
||||
indices,
|
||||
castedNumIndices,
|
||||
castedPrimitiveType,
|
||||
materialInstances,
|
||||
materialInstanceCount,
|
||||
keepData);
|
||||
return reinterpret_cast<TSceneAsset *>(asset);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_destroyMaterialInstance(TSceneManager *sceneManager, TMaterialInstance *instance)
|
||||
{
|
||||
((SceneManager *)sceneManager)->destroy(reinterpret_cast<MaterialInstance *>(instance));
|
||||
}
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int SceneManager_removeFromScene(TSceneManager *sceneManager, EntityId entityId)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->removeFromScene(entityId);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int SceneManager_addToScene(TSceneManager *sceneManager, EntityId entityId)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->addToScene(entityId);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_transformToUnitCube(TSceneManager *sceneManager, EntityId entityId)
|
||||
{
|
||||
((SceneManager *)sceneManager)->transformToUnitCube(entityId);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TAnimationManager *SceneManager_getAnimationManager(TSceneManager *tSceneManager)
|
||||
{
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
auto *animationManager = sceneManager->getAnimationManager();
|
||||
return reinterpret_cast<TAnimationManager *>(animationManager);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void *SceneManager_destroyAll(TSceneManager *tSceneManager)
|
||||
{
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
sceneManager->destroyAll();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void *SceneManager_destroyAsset(TSceneManager *tSceneManager, TSceneAsset *tSceneAsset)
|
||||
{
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
auto *sceneAsset = reinterpret_cast<SceneAsset *>(tSceneAsset);
|
||||
sceneManager->destroy(sceneAsset);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TNameComponentManager *SceneManager_getNameComponentManager(TSceneManager *tSceneManager) {
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
return reinterpret_cast<TNameComponentManager*>(sceneManager->getNameComponentManager());
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE size_t SceneManager_getOverlayEntityCount(TSceneManager *tSceneManager) {
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
return sceneManager->getOverlayEntityCount();
|
||||
}
|
||||
EMSCRIPTEN_KEEPALIVE EntityId SceneManager_getOverlayEntityAt(TSceneManager *tSceneManager, size_t index) {
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
auto entity = sceneManager->getOverlayEntity(index);
|
||||
return utils::Entity::smuggle(entity);
|
||||
}
|
||||
}
|
||||
155
thermion_dart/native/src/c_api/TTransformManager.cpp
Normal file
155
thermion_dart/native/src/c_api/TTransformManager.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
#include <utils/Entity.h>
|
||||
#include <filament/TransformManager.h>
|
||||
#include <filament/math/mat4.h>
|
||||
#include <gltfio/math.h>
|
||||
|
||||
#include "c_api/APIExport.h"
|
||||
#include "MathUtils.hpp"
|
||||
#include "Log.hpp"
|
||||
|
||||
using namespace thermion;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
using namespace filament;
|
||||
using namespace utils;
|
||||
using namespace filament::gltfio;
|
||||
|
||||
#include "c_api/TTransformManager.h"
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 TransformManager_getLocalTransform(TTransformManager *tTransformManager, EntityId entityId)
|
||||
{
|
||||
auto *transformManager = reinterpret_cast<filament::TransformManager *>(tTransformManager);
|
||||
const auto &entity = utils::Entity::import(entityId);
|
||||
auto transformInstance = transformManager->getInstance(entity);
|
||||
if (!transformInstance)
|
||||
{
|
||||
Log("Failed to find transform instance");
|
||||
return double4x4();
|
||||
}
|
||||
auto transform = transformManager->getTransformAccurate(transformInstance);
|
||||
return convert_mat4_to_double4x4(transform);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 TransformManager_getWorldTransform(TTransformManager *tTransformManager, EntityId entityId)
|
||||
{
|
||||
auto *transformManager = reinterpret_cast<filament::TransformManager *>(tTransformManager);
|
||||
const auto &entity = utils::Entity::import(entityId);
|
||||
auto transformInstance = transformManager->getInstance(entity);
|
||||
if (!transformInstance)
|
||||
{
|
||||
Log("Failed to find transform instance");
|
||||
return double4x4();
|
||||
}
|
||||
auto transform = transformManager->getWorldTransformAccurate(transformInstance);
|
||||
return convert_mat4_to_double4x4(transform);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void TransformManager_setTransform(TTransformManager *tTransformManager, EntityId entityId, double4x4 transform)
|
||||
{
|
||||
auto *transformManager = reinterpret_cast<filament::TransformManager *>(tTransformManager);
|
||||
const auto &entity = utils::Entity::import(entityId);
|
||||
auto transformInstance = transformManager->getInstance(entity);
|
||||
if (!transformInstance)
|
||||
{
|
||||
return;
|
||||
}
|
||||
transformManager->setTransform(transformInstance, convert_double4x4_to_mat4(transform));
|
||||
}
|
||||
|
||||
// EMSCRIPTEN_KEEPALIVE void TransformManager_transformToUnitCube(TTransformManager *tTransformManager, EntityId entityId) {
|
||||
// auto *transformManager = reinterpret_cast<filament::TransformManager*>(tTransformManager);
|
||||
// const auto &entity = utils::Entity::import(entityId);
|
||||
// auto transformInstance = transformManager->getInstance(entity);
|
||||
// if (!transformInstance)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// auto aabb = instance->getBoundingBox();
|
||||
// auto center = aabb.center();
|
||||
// auto halfExtent = aabb.extent();
|
||||
// auto maxExtent = max(halfExtent) * 2;
|
||||
// auto scaleFactor = 2.0f / maxExtent;
|
||||
// auto transform = math::mat4f::scaling(scaleFactor) * math::mat4f::translation(-center);
|
||||
// tm.setTransform(tm.getInstance(instance->getRoot()), transform);
|
||||
// }
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void TransformManager_setParent(TTransformManager *tTransformManager, EntityId childId, EntityId parentId, bool preserveScaling)
|
||||
{
|
||||
auto tm = reinterpret_cast<TransformManager *>(tTransformManager);
|
||||
const auto child = Entity::import(childId);
|
||||
const auto parent = Entity::import(parentId);
|
||||
|
||||
const auto &parentInstance = tm->getInstance(parent);
|
||||
const auto &childInstance = tm->getInstance(child);
|
||||
|
||||
if (!parentInstance.isValid())
|
||||
{
|
||||
Log("Parent instance is not valid");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!childInstance.isValid())
|
||||
{
|
||||
Log("Child instance is not valid");
|
||||
return;
|
||||
}
|
||||
|
||||
if (preserveScaling)
|
||||
{
|
||||
auto parentTransform = tm->getWorldTransform(parentInstance);
|
||||
math::float3 parentTranslation;
|
||||
math::quatf parentRotation;
|
||||
math::float3 parentScale;
|
||||
|
||||
decomposeMatrix(parentTransform, &parentTranslation, &parentRotation, &parentScale);
|
||||
|
||||
auto childTransform = tm->getTransform(childInstance);
|
||||
math::float3 childTranslation;
|
||||
math::quatf childRotation;
|
||||
math::float3 childScale;
|
||||
|
||||
decomposeMatrix(childTransform, &childTranslation, &childRotation, &childScale);
|
||||
|
||||
childScale = childScale * (1 / parentScale);
|
||||
|
||||
childTransform = composeMatrix(childTranslation, childRotation, childScale);
|
||||
|
||||
tm->setTransform(childInstance, childTransform);
|
||||
}
|
||||
|
||||
tm->setParent(childInstance, parentInstance);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId TransformManager_getParent(TTransformManager *tTransformManager, EntityId childId)
|
||||
{
|
||||
auto tm = reinterpret_cast<TransformManager *>(tTransformManager);
|
||||
const auto child = Entity::import(childId);
|
||||
const auto &childInstance = tm->getInstance(child);
|
||||
|
||||
return Entity::smuggle(tm->getParent(childInstance));
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId TransformManager_getAncestor(TTransformManager *tTransformManager, EntityId childEntityId)
|
||||
{
|
||||
auto tm = reinterpret_cast<TransformManager *>(tTransformManager);
|
||||
|
||||
const auto child = Entity::import(childEntityId);
|
||||
auto transformInstance = tm->getInstance(child);
|
||||
Entity parent;
|
||||
|
||||
while (true)
|
||||
{
|
||||
auto newParent = tm->getParent(transformInstance);
|
||||
if (newParent.isNull())
|
||||
{
|
||||
break;
|
||||
}
|
||||
parent = newParent;
|
||||
transformInstance = tm->getInstance(parent);
|
||||
}
|
||||
|
||||
return Entity::smuggle(parent);
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,8 @@
|
||||
#include <filament/ColorGrading.h>
|
||||
#include <filament/Camera.h>
|
||||
|
||||
#include "ThermionDartApi.h"
|
||||
#include "TView.h"
|
||||
#include "c_api/ThermionDartApi.h"
|
||||
#include "c_api/TView.h"
|
||||
#include "Log.hpp"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -155,6 +155,25 @@ using namespace filament;
|
||||
return reinterpret_cast<TCamera*>(&(view->getCamera()));
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void View_setStencilBufferEnabled(TView *tView, bool enabled) {
|
||||
auto view = reinterpret_cast<View *>(tView);
|
||||
view->setStencilBufferEnabled(enabled);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool View_isStencilBufferEnabled(TView *tView) {
|
||||
auto view = reinterpret_cast<View *>(tView);
|
||||
return view->isStencilBufferEnabled();
|
||||
}
|
||||
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void View_pick(TView *tView, uint32_t requestId, uint32_t x, uint32_t y, PickCallback callback)
|
||||
{
|
||||
auto *view = reinterpret_cast<View *>(tView);
|
||||
view->pick(x, y, [=](filament::View::PickingQueryResult const &result) {
|
||||
callback(requestId, utils::Entity::smuggle(result.renderable), result.depth, result.fragCoords.x, result.fragCoords.y, result.fragCoords.z);
|
||||
});
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
511
thermion_dart/native/src/c_api/ThermionDartApi.cpp
Normal file
511
thermion_dart/native/src/c_api/ThermionDartApi.cpp
Normal file
@@ -0,0 +1,511 @@
|
||||
#ifdef _WIN32
|
||||
#include "ThermionWin32.h"
|
||||
#endif
|
||||
|
||||
#include <thread>
|
||||
#include <functional>
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten/emscripten.h>
|
||||
#endif
|
||||
|
||||
#include "filament/LightManager.h"
|
||||
#include "ResourceBuffer.hpp"
|
||||
#include "FilamentViewer.hpp"
|
||||
#include "Log.hpp"
|
||||
#include "ThreadPool.hpp"
|
||||
|
||||
using namespace thermion;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
#include "c_api/ThermionDartApi.h"
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TViewer *Viewer_create(const void *context, const void *const loader, void *const platform, const char *uberArchivePath)
|
||||
{
|
||||
const auto *loaderImpl = new ResourceLoaderWrapperImpl((ResourceLoaderWrapper *)loader);
|
||||
auto viewer = new FilamentViewer(context, loaderImpl, platform, uberArchivePath);
|
||||
return reinterpret_cast<TViewer *>(viewer);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer *viewer)
|
||||
{
|
||||
auto *engine = reinterpret_cast<FilamentViewer *>(viewer)->getEngine();
|
||||
return reinterpret_cast<TEngine *>(engine);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TRenderTarget *Viewer_createRenderTarget(TViewer *tViewer, intptr_t texture, uint32_t width, uint32_t height)
|
||||
{
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto renderTarget = viewer->createRenderTarget(texture, width, height);
|
||||
return reinterpret_cast<TRenderTarget *>(renderTarget);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_destroyRenderTarget(TViewer *tViewer, TRenderTarget *tRenderTarget)
|
||||
{
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto renderTarget = reinterpret_cast<RenderTarget *>(tRenderTarget);
|
||||
viewer->destroyRenderTarget(renderTarget);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_destroy(TViewer *viewer)
|
||||
{
|
||||
delete ((FilamentViewer *)viewer);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_color(TViewer *viewer, const float r, const float g, const float b, const float a)
|
||||
{
|
||||
((FilamentViewer *)viewer)->setBackgroundColor(r, g, b, a);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void clear_background_image(TViewer *viewer)
|
||||
{
|
||||
((FilamentViewer *)viewer)->clearBackgroundImage();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_image(TViewer *viewer, const char *path, bool fillHeight)
|
||||
{
|
||||
((FilamentViewer *)viewer)->setBackgroundImage(path, fillHeight, 100, 100);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_image_position(TViewer *viewer, float x, float y, bool clamp)
|
||||
{
|
||||
((FilamentViewer *)viewer)->setBackgroundImagePosition(x, y, clamp, 100, 100);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void load_skybox(TViewer *viewer, const char *skyboxPath)
|
||||
{
|
||||
((FilamentViewer *)viewer)->loadSkybox(skyboxPath);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void create_ibl(TViewer *viewer, float r, float g, float b, float intensity)
|
||||
{
|
||||
((FilamentViewer *)viewer)->createIbl(r, g, b, intensity);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_loadIbl(TViewer *viewer, const char *iblPath, float intensity)
|
||||
{
|
||||
((FilamentViewer *)viewer)->loadIbl(iblPath, intensity);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void rotate_ibl(TViewer *viewer, float *rotationMatrix)
|
||||
{
|
||||
math::mat3f matrix(rotationMatrix[0], rotationMatrix[1],
|
||||
rotationMatrix[2],
|
||||
rotationMatrix[3],
|
||||
rotationMatrix[4],
|
||||
rotationMatrix[5],
|
||||
rotationMatrix[6],
|
||||
rotationMatrix[7],
|
||||
rotationMatrix[8]);
|
||||
|
||||
((FilamentViewer *)viewer)->rotateIbl(matrix);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void remove_skybox(TViewer *viewer)
|
||||
{
|
||||
((FilamentViewer *)viewer)->removeSkybox();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void remove_ibl(TViewer *viewer)
|
||||
{
|
||||
((FilamentViewer *)viewer)->removeIbl();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId add_light(
|
||||
TViewer *viewer,
|
||||
uint8_t type,
|
||||
float colour,
|
||||
float intensity,
|
||||
float posX,
|
||||
float posY,
|
||||
float posZ,
|
||||
float dirX,
|
||||
float dirY,
|
||||
float dirZ,
|
||||
float falloffRadius,
|
||||
float spotLightConeInner,
|
||||
float spotLightConeOuter,
|
||||
float sunAngularRadius,
|
||||
float sunHaloSize,
|
||||
float sunHaloFallof,
|
||||
bool shadows)
|
||||
{
|
||||
return ((FilamentViewer *)viewer)->addLight((LightManager::Type)type, colour, intensity, posX, posY, posZ, dirX, dirY, dirZ, falloffRadius, spotLightConeInner, spotLightConeOuter, sunAngularRadius, sunHaloSize, sunHaloFallof, shadows);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_light_position(TViewer *viewer, int32_t entityId, float x, float y, float z)
|
||||
{
|
||||
((FilamentViewer *)viewer)->setLightPosition(entityId, x, y, z);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_light_direction(TViewer *viewer, int32_t entityId, float x, float y, float z)
|
||||
{
|
||||
((FilamentViewer *)viewer)->setLightDirection(entityId, x, y, z);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void remove_light(TViewer *viewer, int32_t entityId)
|
||||
{
|
||||
((FilamentViewer *)viewer)->removeLight(entityId);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void clear_lights(TViewer *viewer)
|
||||
{
|
||||
((FilamentViewer *)viewer)->clearLights();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int get_instance_count(TSceneManager *sceneManager, EntityId entityId)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->getInstanceCount(entityId);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void get_instances(TSceneManager *sceneManager, EntityId entityId, EntityId *out)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->getInstances(entityId, out);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_setMainCamera(TViewer *tViewer, TView *tView)
|
||||
{
|
||||
auto *viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto *view = reinterpret_cast<View *>(tView);
|
||||
viewer->setMainCamera(view);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId get_main_camera(TViewer *viewer)
|
||||
{
|
||||
return ((FilamentViewer *)viewer)->getMainCamera();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE float get_camera_fov(TCamera *camera, bool horizontal)
|
||||
{
|
||||
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
return cam->getFieldOfViewInDegrees(horizontal ? Camera::Fov::HORIZONTAL : Camera::Fov::VERTICAL);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE double get_camera_focal_length(TCamera *const camera)
|
||||
{
|
||||
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
return cam->getFocalLength();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_camera_projection_from_fov(TCamera *camera, double fovInDegrees, double aspect, double near, double far, bool horizontal)
|
||||
{
|
||||
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
cam->setProjection(fovInDegrees, aspect, near, far, horizontal ? Camera::Fov::HORIZONTAL : Camera::Fov::VERTICAL);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TCamera *get_camera(TViewer *viewer, EntityId entity)
|
||||
{
|
||||
auto filamentCamera = ((FilamentViewer *)viewer)->getCamera(entity);
|
||||
return reinterpret_cast<TCamera *>(filamentCamera);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 get_camera_model_matrix(TCamera *camera)
|
||||
{
|
||||
const auto &mat = reinterpret_cast<filament::Camera *>(camera)->getModelMatrix();
|
||||
return convert_mat4_to_double4x4(mat);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 get_camera_view_matrix(TCamera *camera)
|
||||
{
|
||||
const auto &mat = reinterpret_cast<filament::Camera *>(camera)->getViewMatrix();
|
||||
return convert_mat4_to_double4x4(mat);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 get_camera_projection_matrix(TCamera *camera)
|
||||
{
|
||||
const auto &mat = reinterpret_cast<filament::Camera *>(camera)->getProjectionMatrix();
|
||||
return convert_mat4_to_double4x4(mat);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 get_camera_culling_projection_matrix(TCamera *camera)
|
||||
{
|
||||
const auto &mat = reinterpret_cast<filament::Camera *>(camera)->getCullingProjectionMatrix();
|
||||
return convert_mat4_to_double4x4(mat);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_camera_projection_matrix(TCamera *camera, double4x4 matrix, double near, double far)
|
||||
{
|
||||
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
const auto &mat = convert_double4x4_to_mat4(matrix);
|
||||
cam->setCustomProjection(mat, near, far);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setLensProjection(TCamera *camera, double near, double far, double aspect, double focalLength)
|
||||
{
|
||||
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
cam->setLensProjection(focalLength, aspect, near, far);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setModelMatrix(TCamera *camera, double4x4 matrix)
|
||||
{
|
||||
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
cam->setModelMatrix(convert_double4x4_to_mat4(matrix));
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE double get_camera_near(TCamera *camera)
|
||||
{
|
||||
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
return cam->getNear();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE double get_camera_culling_far(TCamera *camera)
|
||||
{
|
||||
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
return cam->getCullingFar();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE const double *const get_camera_frustum(TCamera *camera)
|
||||
{
|
||||
|
||||
const auto frustum = reinterpret_cast<filament::Camera *>(camera)->getFrustum();
|
||||
|
||||
const math::float4 *planes = frustum.getNormalizedPlanes();
|
||||
double *array = (double *)calloc(24, sizeof(double));
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
auto plane = planes[i];
|
||||
array[i * 4] = double(plane.x);
|
||||
array[i * 4 + 1] = double(plane.y);
|
||||
array[i * 4 + 2] = double(plane.z);
|
||||
array[i * 4 + 3] = double(plane.w);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_camera_focus_distance(TCamera *camera, float distance)
|
||||
{
|
||||
auto *cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
cam->setFocusDistance(distance);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_camera_exposure(TCamera *camera, float aperture, float shutterSpeed, float sensitivity)
|
||||
{
|
||||
auto *cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
cam->setExposure(aperture, shutterSpeed, sensitivity);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_camera_model_matrix(TCamera *camera, double4x4 matrix)
|
||||
{
|
||||
auto *cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
const filament::math::mat4 &mat = convert_double4x4_to_mat4(matrix);
|
||||
cam->setModelMatrix(mat);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_render(
|
||||
TViewer *tViewer)
|
||||
{
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
viewer->render(0);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_setViewRenderable(TViewer *tViewer, TSwapChain *tSwapChain, TView *tView, bool renderable)
|
||||
{
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto swapChain = reinterpret_cast<SwapChain *>(tSwapChain);
|
||||
auto *view = reinterpret_cast<View *>(tView);
|
||||
viewer->setRenderable(view, swapChain, renderable);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_capture(
|
||||
TViewer *tViewer,
|
||||
TView *tView,
|
||||
TSwapChain *tSwapChain,
|
||||
uint8_t *pixelBuffer,
|
||||
void (*callback)(void))
|
||||
{
|
||||
#ifdef __EMSCRIPTEN__
|
||||
bool useFence = true;
|
||||
#else
|
||||
bool useFence = false;
|
||||
#endif
|
||||
auto swapChain = reinterpret_cast<SwapChain *>(tSwapChain);
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto *view = reinterpret_cast<View *>(tView);
|
||||
viewer->capture(view, pixelBuffer, useFence, swapChain, callback);
|
||||
};
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTarget(
|
||||
TViewer *tViewer,
|
||||
TView *tView,
|
||||
TSwapChain *tSwapChain,
|
||||
TRenderTarget *tRenderTarget,
|
||||
uint8_t *pixelBuffer,
|
||||
void (*callback)(void))
|
||||
{
|
||||
#ifdef __EMSCRIPTEN__
|
||||
bool useFence = true;
|
||||
#else
|
||||
bool useFence = false;
|
||||
#endif
|
||||
auto swapChain = reinterpret_cast<SwapChain *>(tSwapChain);
|
||||
auto renderTarget = reinterpret_cast<RenderTarget *>(tRenderTarget);
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto *view = reinterpret_cast<View *>(tView);
|
||||
viewer->capture(view, pixelBuffer, useFence, swapChain, renderTarget, callback);
|
||||
};
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_frame_interval(
|
||||
TViewer *viewer,
|
||||
float frameInterval)
|
||||
{
|
||||
((FilamentViewer *)viewer)->setFrameInterval(frameInterval);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_destroySwapChain(TViewer *tViewer, TSwapChain *tSwapChain)
|
||||
{
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto swapChain = reinterpret_cast<SwapChain *>(tSwapChain);
|
||||
viewer->destroySwapChain(swapChain);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createHeadlessSwapChain(TViewer *tViewer, uint32_t width, uint32_t height)
|
||||
{
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto swapChain = viewer->createSwapChain(width, height);
|
||||
return reinterpret_cast<TSwapChain *>(swapChain);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createSwapChain(TViewer *tViewer, const void *const window)
|
||||
{
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto swapChain = viewer->createSwapChain(window);
|
||||
return reinterpret_cast<TSwapChain *>(swapChain);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_getSwapChainAt(TViewer *tViewer, int index)
|
||||
{
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto swapChain = viewer->getSwapChainAt(index);
|
||||
return reinterpret_cast<TSwapChain *>(swapChain);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TView *Viewer_createView(TViewer *tViewer)
|
||||
{
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto view = viewer->createView();
|
||||
return reinterpret_cast<TView *>(view);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TView *Viewer_getViewAt(TViewer *tViewer, int32_t index)
|
||||
{
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto view = viewer->getViewAt(index);
|
||||
return reinterpret_cast<TView *>(view);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TSceneManager *Viewer_getSceneManager(TViewer *tViewer)
|
||||
{
|
||||
auto *viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto *sceneManager = viewer->getSceneManager();
|
||||
return reinterpret_cast<TSceneManager *>(sceneManager);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void queue_position_update_from_viewport_coords(TSceneManager *sceneManager, TView *tView, EntityId entity, float viewportX, float viewportY)
|
||||
{
|
||||
auto *view = reinterpret_cast<View *>(tView);
|
||||
((SceneManager *)sceneManager)->queueRelativePositionUpdateFromViewportVector(view, entity, viewportX, viewportY);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void ios_dummy()
|
||||
{
|
||||
Log("Dummy called");
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void thermion_filament_free(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void add_collision_component(TSceneManager *sceneManager, EntityId entityId, void (*onCollisionCallback)(const EntityId entityId1, const EntityId entityId2), bool affectsCollidingTransform)
|
||||
{
|
||||
((SceneManager *)sceneManager)->addCollisionComponent(entityId, onCollisionCallback, affectsCollidingTransform);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void remove_collision_component(TSceneManager *sceneManager, EntityId entityId)
|
||||
{
|
||||
((SceneManager *)sceneManager)->removeCollisionComponent(entityId);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void test_collisions(TSceneManager *sceneManager, EntityId entity)
|
||||
{
|
||||
((SceneManager *)sceneManager)->testCollisions(entity);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE Aabb2 get_bounding_box(TSceneManager *sceneManager, TView *tView, EntityId entity)
|
||||
{
|
||||
auto view = reinterpret_cast<View *>(tView);
|
||||
return ((SceneManager *)sceneManager)->getScreenSpaceBoundingBox(view, entity);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void get_bounding_box_to_out(TSceneManager *sceneManager, TView *tView, EntityId entity, float *minX, float *minY, float *maxX, float *maxY)
|
||||
{
|
||||
auto view = reinterpret_cast<View *>(tView);
|
||||
auto box = ((SceneManager *)sceneManager)->getScreenSpaceBoundingBox(view, entity);
|
||||
*minX = box.minX;
|
||||
*minY = box.minY;
|
||||
*maxX = box.maxX;
|
||||
*maxY = box.maxY;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void thermion_flutter_free(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void unproject_texture(TViewer *viewer, EntityId entity, uint8_t *input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight)
|
||||
{
|
||||
((FilamentViewer *)viewer)->unprojectTexture(entity, input, inputWidth, inputHeight, out, outWidth, outHeight);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void *const create_texture(TSceneManager *sceneManager, uint8_t *data, size_t length)
|
||||
{
|
||||
return (void *const)((SceneManager *)sceneManager)->createTexture(data, length, "SOMETEXTURE");
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void apply_texture_to_material(TSceneManager *sceneManager, EntityId entity, void *const texture, const char *parameterName, int materialIndex)
|
||||
{
|
||||
((SceneManager *)sceneManager)->applyTexture(entity, reinterpret_cast<Texture *>(texture), parameterName, materialIndex);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void destroy_texture(TSceneManager *sceneManager, void *const texture)
|
||||
{
|
||||
((SceneManager *)sceneManager)->destroyTexture(reinterpret_cast<Texture *>(texture));
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TTransformManager *Engine_getTransformManager(TEngine *tEngine)
|
||||
{
|
||||
auto *engine = reinterpret_cast<Engine *>(tEngine);
|
||||
auto &transformManager = engine->getTransformManager();
|
||||
return reinterpret_cast<TTransformManager *>(&transformManager);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TRenderableManager *Engine_getRenderableManager(TEngine *tEngine)
|
||||
{
|
||||
auto *engine = reinterpret_cast<Engine *>(tEngine);
|
||||
auto &renderableManager = engine->getRenderableManager();
|
||||
return reinterpret_cast<TRenderableManager *>(&renderableManager);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TCamera *Engine_getCameraComponent(TEngine *tEngine, EntityId entityId)
|
||||
{
|
||||
auto *engine = reinterpret_cast<Engine *>(tEngine);
|
||||
auto *camera = engine->getCameraComponent(utils::Entity::import(entityId));
|
||||
return reinterpret_cast<TCamera *>(camera);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_setTransform(TEngine *tEngine, EntityId entity, double4x4 transform)
|
||||
{
|
||||
auto *engine = reinterpret_cast<Engine *>(tEngine);
|
||||
auto &transformManager = engine->getTransformManager();
|
||||
|
||||
auto transformInstance = transformManager.getInstance(utils::Entity::import(entity));
|
||||
if (!transformInstance.isValid())
|
||||
{
|
||||
Log("Transform instance not valid");
|
||||
}
|
||||
transformManager.setTransform(transformInstance, convert_double4x4_to_mat4(transform));
|
||||
}
|
||||
}
|
||||
@@ -3,14 +3,20 @@
|
||||
#include <thread>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ThermionDartRenderThreadApi.h"
|
||||
#include "FilamentViewer.hpp"
|
||||
#include "TView.h"
|
||||
#include "Log.hpp"
|
||||
#include "ThreadPool.hpp"
|
||||
#include "TSceneManager.h"
|
||||
#include <filament/LightManager.h>
|
||||
|
||||
#include "c_api/APIBoundaryTypes.h"
|
||||
#include "c_api/TView.h"
|
||||
#include "c_api/TSceneAsset.h"
|
||||
#include "c_api/TSceneManager.h"
|
||||
#include "c_api/TAnimationManager.h"
|
||||
#include "c_api/ThermionDartRenderThreadApi.h"
|
||||
|
||||
#include "FilamentViewer.hpp"
|
||||
#include "Log.hpp"
|
||||
|
||||
#include "ThreadPool.hpp"
|
||||
|
||||
#include "filament/LightManager.h"
|
||||
|
||||
using namespace thermion;
|
||||
using namespace std::chrono_literals;
|
||||
@@ -99,8 +105,7 @@ public:
|
||||
}
|
||||
|
||||
_cv.wait_for(taskLock, std::chrono::microseconds(2000), [this]
|
||||
{ return !_tasks.empty() || _stop; });
|
||||
|
||||
{ return !_tasks.empty() || _stop; });
|
||||
}
|
||||
|
||||
void createViewer(void *const context,
|
||||
@@ -109,7 +114,7 @@ public:
|
||||
const ResourceLoaderWrapper *const loader,
|
||||
void (*renderCallback)(void *),
|
||||
void *const owner,
|
||||
void (*callback)(TViewer*))
|
||||
void (*callback)(TViewer *))
|
||||
{
|
||||
_renderCallback = renderCallback;
|
||||
_renderCallbackOwner = owner;
|
||||
@@ -117,8 +122,7 @@ public:
|
||||
{
|
||||
auto viewer = (FilamentViewer *)Viewer_create(context, loader, platform, uberArchivePath);
|
||||
_viewer = reinterpret_cast<TViewer*>(viewer);
|
||||
callback(_viewer);
|
||||
});
|
||||
callback(_viewer); });
|
||||
auto fut = add_task(lambda);
|
||||
}
|
||||
|
||||
@@ -159,7 +163,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void(*_requestFrameRenderCallback)() = nullptr;
|
||||
void (*_requestFrameRenderCallback)() = nullptr;
|
||||
bool _stop = false;
|
||||
int _frameIntervalInMicroseconds = 1000000 / 60;
|
||||
std::mutex _mutex;
|
||||
@@ -205,9 +209,9 @@ extern "C"
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createHeadlessSwapChainRenderThread(TViewer *viewer,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
void (*onComplete)(TSwapChain*))
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
void (*onComplete)(TSwapChain *))
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]() mutable
|
||||
@@ -219,8 +223,8 @@ extern "C"
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createSwapChainRenderThread(TViewer *viewer,
|
||||
void *const surface,
|
||||
void (*onComplete)(TSwapChain*))
|
||||
void *const surface,
|
||||
void (*onComplete)(TSwapChain *))
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]() mutable
|
||||
@@ -242,8 +246,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_requestFrameRenderThread(TViewer *viewer, void(*onComplete)())
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_requestFrameRenderThread(TViewer *viewer, void (*onComplete)())
|
||||
{
|
||||
if (!_rl)
|
||||
{
|
||||
@@ -255,24 +258,26 @@ extern "C"
|
||||
}
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_loadIblRenderThread(TViewer *viewer, const char *iblPath, float intensity, void(*onComplete)()) {
|
||||
std::packaged_task<void()> lambda(
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_loadIblRenderThread(TViewer *viewer, const char *iblPath, float intensity, void (*onComplete)())
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]() mutable
|
||||
{
|
||||
Viewer_loadIbl(viewer, iblPath, intensity);
|
||||
onComplete();
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createRenderTargetRenderThread(TViewer *viewer, intptr_t texture, uint32_t width, uint32_t height, void(*onComplete)(TRenderTarget*)) {
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createRenderTargetRenderThread(TViewer *viewer, intptr_t texture, uint32_t width, uint32_t height, void (*onComplete)(TRenderTarget *))
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]() mutable
|
||||
{
|
||||
auto renderTarget = Viewer_createRenderTarget(viewer, texture, width, height);
|
||||
onComplete(renderTarget);
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void
|
||||
@@ -287,9 +292,7 @@ extern "C"
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_renderRenderThread(TViewer *viewer, TView *tView, TSwapChain *tSwapChain)
|
||||
{
|
||||
std::packaged_task<void()> lambda([=]() mutable
|
||||
{
|
||||
_rl->doRender();
|
||||
});
|
||||
{ _rl->doRender(); });
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
@@ -300,7 +303,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTargetRenderThread(TViewer *viewer, TView *view, TSwapChain *tSwapChain, TRenderTarget* tRenderTarget, uint8_t *pixelBuffer, void (*onComplete)())
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTargetRenderThread(TViewer *viewer, TView *view, TSwapChain *tSwapChain, TRenderTarget *tRenderTarget, uint8_t *pixelBuffer, void (*onComplete)())
|
||||
{
|
||||
std::packaged_task<void()> lambda([=]() mutable
|
||||
{ Viewer_captureRenderTarget(viewer, view, tSwapChain, tRenderTarget, pixelBuffer, onComplete); });
|
||||
@@ -317,32 +320,30 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void load_gltf_render_thread(TSceneManager *sceneManager,
|
||||
const char *path,
|
||||
const char *relativeResourcePath,
|
||||
bool keepData,
|
||||
void (*callback)(EntityId))
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_loadGltfRenderThread(TSceneManager *sceneManager,
|
||||
const char *path,
|
||||
const char *relativeResourcePath,
|
||||
bool keepData,
|
||||
void (*callback)(TSceneAsset *))
|
||||
{
|
||||
std::packaged_task<EntityId()> lambda([=]() mutable
|
||||
{
|
||||
auto entity = load_gltf(sceneManager, path, relativeResourcePath, keepData);
|
||||
callback(entity);
|
||||
return entity; });
|
||||
std::packaged_task<void()> lambda([=]() mutable
|
||||
{
|
||||
auto entity = SceneManager_loadGltf(sceneManager, path, relativeResourcePath, keepData);
|
||||
callback(entity); });
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void load_glb_render_thread(TSceneManager *sceneManager,
|
||||
const char *path,
|
||||
int numInstances,
|
||||
bool keepData,
|
||||
void (*callback)(EntityId))
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_loadGlbRenderThread(TSceneManager *sceneManager,
|
||||
const char *path,
|
||||
int numInstances,
|
||||
bool keepData,
|
||||
void (*callback)(TSceneAsset *))
|
||||
{
|
||||
std::packaged_task<EntityId()> lambda(
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]() mutable
|
||||
{
|
||||
auto entity = load_glb(sceneManager, path, numInstances, keepData);
|
||||
callback(entity);
|
||||
return entity;
|
||||
auto asset = SceneManager_loadGlb(sceneManager, path, numInstances, keepData);
|
||||
callback(asset);
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
@@ -358,22 +359,47 @@ extern "C"
|
||||
uint16_t *indices,
|
||||
int numIndices,
|
||||
int primitiveType,
|
||||
TMaterialInstance *materialInstance,
|
||||
TMaterialInstance **materialInstances,
|
||||
int materialInstanceCount,
|
||||
bool keepData,
|
||||
void (*callback)(EntityId))
|
||||
void (*callback)(TSceneAsset *))
|
||||
{
|
||||
std::packaged_task<EntityId()> lambda(
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]
|
||||
{
|
||||
auto entity = SceneManager_createGeometry(sceneManager, vertices, numVertices, normals, numNormals, uvs, numUvs, indices, numIndices, primitiveType, materialInstance, keepData);
|
||||
callback(entity);
|
||||
return entity;
|
||||
auto *asset = SceneManager_createGeometry(sceneManager, vertices, numVertices, normals, numNormals, uvs, numUvs, indices, numIndices, primitiveType, materialInstances, materialInstanceCount, keepData);
|
||||
callback(asset);
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void SceneAsset_createInstanceRenderThread(
|
||||
TSceneAsset *asset, TMaterialInstance **tMaterialInstances,
|
||||
int materialInstanceCount,
|
||||
void (*callback)(TSceneAsset *))
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]
|
||||
{
|
||||
auto instanceAsset = SceneAsset_createInstance(asset, tMaterialInstances, materialInstanceCount);
|
||||
callback(instanceAsset);
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_createUnlitMaterialInstanceRenderThread(TSceneManager *sceneManager, void (*callback)(TMaterialInstance*)) {
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialProvider_createMaterialInstanceRenderThread(TMaterialProvider *tMaterialProvider, TMaterialKey *tKey, void (*callback)(TMaterialInstance *))
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]
|
||||
{
|
||||
auto materialInstance = MaterialProvider_createMaterialInstance(tMaterialProvider, tKey);
|
||||
callback(materialInstance);
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_createUnlitMaterialInstanceRenderThread(TSceneManager *sceneManager, void (*callback)(TMaterialInstance *))
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]() mutable
|
||||
{
|
||||
@@ -383,7 +409,8 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_createUnlitFixedSizeMaterialInstanceRenderThread(TSceneManager *sceneManager, void (*callback)(TMaterialInstance*)) {
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_createUnlitFixedSizeMaterialInstanceRenderThread(TSceneManager *sceneManager, void (*callback)(TMaterialInstance *))
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]() mutable
|
||||
{
|
||||
@@ -394,21 +421,20 @@ extern "C"
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_loadGlbFromBufferRenderThread(TSceneManager *sceneManager,
|
||||
const uint8_t *const data,
|
||||
size_t length,
|
||||
int numInstances,
|
||||
bool keepData,
|
||||
int priority,
|
||||
int layer,
|
||||
bool loadResourcesAsync,
|
||||
void (*callback)(EntityId))
|
||||
const uint8_t *const data,
|
||||
size_t length,
|
||||
int numInstances,
|
||||
bool keepData,
|
||||
int priority,
|
||||
int layer,
|
||||
bool loadResourcesAsync,
|
||||
void (*callback)(TSceneAsset *))
|
||||
{
|
||||
std::packaged_task<EntityId()> lambda(
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]() mutable
|
||||
{
|
||||
auto entity = SceneManager_loadGlbFromBuffer(sceneManager, data, length, keepData, priority, layer, loadResourcesAsync);
|
||||
callback(entity);
|
||||
return entity;
|
||||
auto *asset = SceneManager_loadGlbFromBuffer(sceneManager, data, length, keepData, priority, layer, loadResourcesAsync);
|
||||
callback(asset);
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
@@ -432,7 +458,7 @@ extern "C"
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_image_position_render_thread(TViewer *viewer,
|
||||
float x, float y,
|
||||
bool clamp)
|
||||
@@ -442,7 +468,7 @@ extern "C"
|
||||
{ set_background_image_position(viewer, x, y, clamp); });
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void load_skybox_render_thread(TViewer *viewer,
|
||||
const char *skyboxPath,
|
||||
void (*onComplete)())
|
||||
@@ -450,11 +476,10 @@ extern "C"
|
||||
std::packaged_task<void()> lambda([=]
|
||||
{
|
||||
load_skybox(viewer, skyboxPath);
|
||||
onComplete();
|
||||
});
|
||||
onComplete(); });
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void remove_skybox_render_thread(TViewer *viewer)
|
||||
{
|
||||
std::packaged_task<void()> lambda([=]
|
||||
@@ -469,159 +494,8 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void remove_entity_render_thread(TViewer *viewer,
|
||||
EntityId asset, void (*callback)())
|
||||
EMSCRIPTEN_KEEPALIVE void View_setToneMappingRenderThread(TView *tView, TEngine *tEngine, thermion::ToneMapping toneMapping)
|
||||
{
|
||||
std::packaged_task<void()> lambda([=]
|
||||
{
|
||||
remove_entity(viewer, asset);
|
||||
callback();
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void clear_entities_render_thread(TViewer *viewer, void (*callback)())
|
||||
{
|
||||
std::packaged_task<void()> lambda([=]
|
||||
{
|
||||
clear_entities(viewer);
|
||||
callback();
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void
|
||||
get_morph_target_name_render_thread(TSceneManager *sceneManager, EntityId assetEntity,
|
||||
EntityId childEntity, char *const outPtr, int index, void (*callback)())
|
||||
{
|
||||
std::packaged_task<void()> lambda([=]
|
||||
{
|
||||
get_morph_target_name(sceneManager, assetEntity, childEntity, outPtr, index);
|
||||
callback();
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void
|
||||
get_morph_target_name_count_render_thread(TSceneManager *sceneManager, EntityId assetEntity,
|
||||
EntityId childEntity, void (*callback)(int))
|
||||
{
|
||||
std::packaged_task<int()> lambda([=]
|
||||
{
|
||||
auto count = get_morph_target_name_count(sceneManager, assetEntity, childEntity);
|
||||
callback(count);
|
||||
return count; });
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_animation_frame_render_thread(TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
int animationIndex,
|
||||
int animationFrame)
|
||||
{
|
||||
std::packaged_task<void()> lambda([=]
|
||||
{ set_animation_frame(sceneManager, asset, animationIndex, animationFrame); });
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void stop_animation_render_thread(TSceneManager *sceneManager,
|
||||
EntityId asset, int index)
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]
|
||||
{ stop_animation(sceneManager, asset, index); });
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void get_animation_count_render_thread(TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
void (*callback)(int))
|
||||
{
|
||||
std::packaged_task<int()> lambda(
|
||||
[=]
|
||||
{
|
||||
auto count = get_animation_count(sceneManager, asset);
|
||||
callback(count);
|
||||
return count;
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void get_animation_name_render_thread(TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
char *const outPtr,
|
||||
int index,
|
||||
void (*callback)())
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]
|
||||
{
|
||||
get_animation_name(sceneManager, asset, outPtr, index);
|
||||
callback();
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void
|
||||
get_name_for_entity_render_thread(TSceneManager *sceneManager, const EntityId entityId, void (*callback)(const char *))
|
||||
{
|
||||
std::packaged_task<const char *()> lambda(
|
||||
[=]
|
||||
{
|
||||
auto name = get_name_for_entity(sceneManager, entityId);
|
||||
callback(name);
|
||||
return name;
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_morph_target_weights_render_thread(TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
const float *const morphData,
|
||||
int numWeights,
|
||||
void (*callback)(bool))
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]
|
||||
{
|
||||
auto result = set_morph_target_weights(sceneManager, asset, morphData, numWeights);
|
||||
callback(result);
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_bone_transform_render_thread(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
int skinIndex,
|
||||
int boneIndex,
|
||||
const float *const transform,
|
||||
void (*callback)(bool))
|
||||
{
|
||||
std::packaged_task<bool()> lambda(
|
||||
[=]
|
||||
{
|
||||
auto success = set_bone_transform(sceneManager, asset, skinIndex, boneIndex, transform);
|
||||
callback(success);
|
||||
return success;
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void update_bone_matrices_render_thread(TSceneManager *sceneManager,
|
||||
EntityId entity, void (*callback)(bool))
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]
|
||||
{
|
||||
auto success = update_bone_matrices(sceneManager, entity);
|
||||
callback(success);
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void View_setToneMappingRenderThread(TView *tView, TEngine *tEngine, thermion::ToneMapping toneMapping) {
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]
|
||||
{
|
||||
@@ -629,8 +503,9 @@ extern "C"
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void View_setBloomRenderThread(TView *tView, double bloom) {
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void View_setBloomRenderThread(TView *tView, double bloom)
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]
|
||||
{
|
||||
@@ -639,20 +514,31 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void reset_to_rest_pose_render_thread(TSceneManager *sceneManager, EntityId entityId, void (*callback)())
|
||||
EMSCRIPTEN_KEEPALIVE void *SceneManager_destroyAllRenderThread(TSceneManager *tSceneManager, void (*callback)())
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]
|
||||
[=]() mutable
|
||||
{
|
||||
reset_to_rest_pose(sceneManager, entityId);
|
||||
SceneManager_destroyAll(tSceneManager);
|
||||
callback();
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void *SceneManager_destroyAssetRenderThread(TSceneManager *tSceneManager, TSceneAsset *tSceneAsset, void (*callback)())
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]() mutable
|
||||
{
|
||||
SceneManager_destroyAsset(tSceneManager, tSceneAsset);
|
||||
callback();
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void unproject_texture_render_thread(TViewer* viewer, EntityId entity, uint8_t *input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight, void (*callback)())
|
||||
EMSCRIPTEN_KEEPALIVE void unproject_texture_render_thread(TViewer *viewer, EntityId entity, uint8_t *input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight, void (*callback)())
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]
|
||||
@@ -662,4 +548,34 @@ extern "C"
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_updateBoneMatricesRenderThread(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
void (*callback)(bool))
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]() mutable
|
||||
{
|
||||
bool result = AnimationManager_updateBoneMatrices(tAnimationManager, sceneAsset);
|
||||
callback(result);
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_setMorphTargetWeightsRenderThread(
|
||||
TAnimationManager *tAnimationManager,
|
||||
EntityId entityId,
|
||||
const float *const morphData,
|
||||
int numWeights,
|
||||
void (*callback)(bool))
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]() mutable
|
||||
{
|
||||
bool result = AnimationManager_setMorphTargetWeights(tAnimationManager, entityId, morphData, numWeights);
|
||||
callback(result);
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
}
|
||||
521
thermion_dart/native/src/scene/AnimationManager.cpp
Normal file
521
thermion_dart/native/src/scene/AnimationManager.cpp
Normal file
@@ -0,0 +1,521 @@
|
||||
#include <memory>
|
||||
#include <stack>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/TransformManager.h>
|
||||
#include <filament/RenderableManager.h>
|
||||
|
||||
#include <gltfio/Animator.h>
|
||||
|
||||
#include "Log.hpp"
|
||||
|
||||
#include "scene/AnimationManager.hpp"
|
||||
#include "scene/SceneAsset.hpp"
|
||||
#include "scene/GltfSceneAssetInstance.hpp"
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
using namespace filament;
|
||||
using namespace utils;
|
||||
|
||||
AnimationManager::AnimationManager(Engine *engine, Scene *scene) : _engine(engine), _scene(scene)
|
||||
{
|
||||
auto &transformManager = _engine->getTransformManager();
|
||||
auto &renderableManager = _engine->getRenderableManager();
|
||||
_animationComponentManager = std::make_unique<AnimationComponentManager>(transformManager, renderableManager);
|
||||
}
|
||||
|
||||
AnimationManager::~AnimationManager()
|
||||
{
|
||||
_animationComponentManager = std::nullptr_t();
|
||||
}
|
||||
|
||||
bool AnimationManager::setMorphAnimationBuffer(
|
||||
utils::Entity entity,
|
||||
const float *const morphData,
|
||||
const uint32_t *const morphIndices,
|
||||
int numMorphTargets,
|
||||
int numFrames,
|
||||
float frameLengthInMs)
|
||||
{
|
||||
std::lock_guard lock(_mutex);
|
||||
|
||||
if (!_animationComponentManager->hasComponent(entity))
|
||||
{
|
||||
_animationComponentManager->addAnimationComponent(entity);
|
||||
}
|
||||
|
||||
MorphAnimation morphAnimation;
|
||||
|
||||
morphAnimation.meshTarget = entity;
|
||||
morphAnimation.frameData.clear();
|
||||
morphAnimation.frameData.insert(
|
||||
morphAnimation.frameData.begin(),
|
||||
morphData,
|
||||
morphData + (numFrames * numMorphTargets));
|
||||
morphAnimation.frameLengthInMs = frameLengthInMs;
|
||||
morphAnimation.morphIndices.resize(numMorphTargets);
|
||||
for (int i = 0; i < numMorphTargets; i++)
|
||||
{
|
||||
morphAnimation.morphIndices[i] = morphIndices[i];
|
||||
}
|
||||
morphAnimation.durationInSecs = (frameLengthInMs * numFrames) / 1000.0f;
|
||||
|
||||
morphAnimation.start = high_resolution_clock::now();
|
||||
morphAnimation.lengthInFrames = static_cast<int>(
|
||||
morphAnimation.durationInSecs * 1000.0f /
|
||||
frameLengthInMs);
|
||||
|
||||
auto animationComponentInstance = _animationComponentManager->getInstance(entity);
|
||||
auto &animationComponent = _animationComponentManager->elementAt<0>(animationComponentInstance);
|
||||
auto &morphAnimations = animationComponent.morphAnimations;
|
||||
|
||||
morphAnimations.emplace_back(morphAnimation);
|
||||
return true;
|
||||
}
|
||||
|
||||
void AnimationManager::clearMorphAnimationBuffer(
|
||||
utils::Entity entity)
|
||||
{
|
||||
std::lock_guard lock(_mutex);
|
||||
|
||||
auto animationComponentInstance = _animationComponentManager->getInstance(entity);
|
||||
auto &animationComponent = _animationComponentManager->elementAt<0>(animationComponentInstance);
|
||||
auto &morphAnimations = animationComponent.morphAnimations;
|
||||
morphAnimations.clear();
|
||||
}
|
||||
|
||||
void AnimationManager::resetToRestPose(GltfSceneAssetInstance *instance)
|
||||
{
|
||||
std::lock_guard lock(_mutex);
|
||||
|
||||
auto filamentInstance = instance->getInstance();
|
||||
auto skinCount = filamentInstance->getSkinCount();
|
||||
|
||||
TransformManager &transformManager = _engine->getTransformManager();
|
||||
|
||||
//
|
||||
// To reset the skeleton to its rest pose, we could just call animator->resetBoneMatrices(),
|
||||
// which sets all bone matrices to the identity matrix. However, any subsequent calls to animator->updateBoneMatrices()
|
||||
// may result in unexpected poses, because that method uses each bone's transform to calculate
|
||||
// the bone matrices (and resetBoneMatrices does not affect this transform).
|
||||
// To "fully" reset the bone, we need to set its local transform (i.e. relative to its parent)
|
||||
// to its original orientation in rest pose.
|
||||
//
|
||||
// This can be calculated as:
|
||||
//
|
||||
// auto rest = inverse(parentTransformInModelSpace) * bindMatrix
|
||||
//
|
||||
// (where bindMatrix is the inverse of the inverseBindMatrix).
|
||||
//
|
||||
// The only requirement is that parent bone transforms are reset before child bone transforms.
|
||||
// glTF/Filament does not guarantee that parent bones are listed before child bones under a FilamentInstance.
|
||||
// We ensure that parents are reset before children by:
|
||||
// - pushing all bones onto a stack
|
||||
// - iterate over the stack
|
||||
// - look at the bone at the top of the stack
|
||||
// - if the bone already been reset, pop and continue iterating over the stack
|
||||
// - otherwise
|
||||
// - if the bone has a parent that has not been reset, push the parent to the top of the stack and continue iterating
|
||||
// - otherwise
|
||||
// - pop the bone, reset its transform and mark it as completed
|
||||
for (int skinIndex = 0; skinIndex < skinCount; skinIndex++)
|
||||
{
|
||||
std::unordered_set<Entity, Entity::Hasher> joints;
|
||||
std::unordered_set<Entity, Entity::Hasher> completed;
|
||||
std::stack<Entity> stack;
|
||||
|
||||
auto transforms = getBoneRestTranforms(instance, skinIndex);
|
||||
|
||||
for (int i = 0; i < filamentInstance->getJointCountAt(skinIndex); i++)
|
||||
{
|
||||
auto restTransform = transforms[i];
|
||||
const auto &joint = filamentInstance->getJointsAt(skinIndex)[i];
|
||||
auto transformInstance = transformManager.getInstance(joint);
|
||||
transformManager.setTransform(transformInstance, restTransform);
|
||||
}
|
||||
}
|
||||
filamentInstance->getAnimator()->updateBoneMatrices();
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<math::mat4f> AnimationManager::getBoneRestTranforms(GltfSceneAssetInstance *instance, int skinIndex)
|
||||
{
|
||||
|
||||
std::vector<math::mat4f> transforms;
|
||||
|
||||
auto filamentInstance = instance->getInstance();
|
||||
auto skinCount = filamentInstance->getSkinCount();
|
||||
|
||||
TransformManager &transformManager = _engine->getTransformManager();
|
||||
|
||||
transforms.resize(filamentInstance->getJointCountAt(skinIndex));
|
||||
|
||||
//
|
||||
// To reset the skeleton to its rest pose, we could just call animator->resetBoneMatrices(),
|
||||
// which sets all bone matrices to the identity matrix. However, any subsequent calls to animator->updateBoneMatrices()
|
||||
// may result in unexpected poses, because that method uses each bone's transform to calculate
|
||||
// the bone matrices (and resetBoneMatrices does not affect this transform).
|
||||
// To "fully" reset the bone, we need to set its local transform (i.e. relative to its parent)
|
||||
// to its original orientation in rest pose.
|
||||
//
|
||||
// This can be calculated as:
|
||||
//
|
||||
// auto rest = inverse(parentTransformInModelSpace) * bindMatrix
|
||||
//
|
||||
// (where bindMatrix is the inverse of the inverseBindMatrix).
|
||||
//
|
||||
// The only requirement is that parent bone transforms are reset before child bone transforms.
|
||||
// glTF/Filament does not guarantee that parent bones are listed before child bones under a FilamentInstance.
|
||||
// We ensure that parents are reset before children by:
|
||||
// - pushing all bones onto a stack
|
||||
// - iterate over the stack
|
||||
// - look at the bone at the top of the stack
|
||||
// - if the bone already been reset, pop and continue iterating over the stack
|
||||
// - otherwise
|
||||
// - if the bone has a parent that has not been reset, push the parent to the top of the stack and continue iterating
|
||||
// - otherwise
|
||||
// - pop the bone, reset its transform and mark it as completed
|
||||
std::vector<Entity> joints;
|
||||
std::unordered_set<Entity, Entity::Hasher> completed;
|
||||
std::stack<Entity> stack;
|
||||
|
||||
for (int i = 0; i < filamentInstance->getJointCountAt(skinIndex); i++)
|
||||
{
|
||||
const auto &joint = filamentInstance->getJointsAt(skinIndex)[i];
|
||||
joints.push_back(joint);
|
||||
stack.push(joint);
|
||||
}
|
||||
|
||||
while (!stack.empty())
|
||||
{
|
||||
const auto &joint = stack.top();
|
||||
|
||||
// if we've already handled this node previously (e.g. when we encountered it as a parent), then skip
|
||||
if (completed.find(joint) != completed.end())
|
||||
{
|
||||
stack.pop();
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto transformInstance = transformManager.getInstance(joint);
|
||||
auto parent = transformManager.getParent(transformInstance);
|
||||
|
||||
// we need to handle parent joints before handling their children
|
||||
// therefore, if this joint has a parent that hasn't been handled yet,
|
||||
// push the parent to the top of the stack and start the loop again
|
||||
const auto &jointIter = std::find(joints.begin(), joints.end(), joint);
|
||||
auto parentIter = std::find(joints.begin(), joints.end(), parent);
|
||||
|
||||
if (parentIter != joints.end() && completed.find(parent) == completed.end())
|
||||
{
|
||||
stack.push(parent);
|
||||
continue;
|
||||
}
|
||||
|
||||
// otherwise let's get the inverse bind matrix for the joint
|
||||
math::mat4f inverseBindMatrix;
|
||||
bool found = false;
|
||||
for (int i = 0; i < filamentInstance->getJointCountAt(skinIndex); i++)
|
||||
{
|
||||
if (filamentInstance->getJointsAt(skinIndex)[i] == joint)
|
||||
{
|
||||
inverseBindMatrix = filamentInstance->getInverseBindMatricesAt(skinIndex)[i];
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT_PRECONDITION(found, "Failed to find inverse bind matrix for joint %d", joint);
|
||||
|
||||
// now we need to ascend back up the hierarchy to calculate the modelSpaceTransform
|
||||
math::mat4f modelSpaceTransform;
|
||||
while (parentIter != joints.end())
|
||||
{
|
||||
const auto transformInstance = transformManager.getInstance(parent);
|
||||
const auto parentIndex = distance(joints.begin(), parentIter);
|
||||
const auto transform = transforms[parentIndex];
|
||||
modelSpaceTransform = transform * modelSpaceTransform;
|
||||
parent = transformManager.getParent(transformInstance);
|
||||
parentIter = std::find(joints.begin(), joints.end(), parent);
|
||||
}
|
||||
|
||||
const auto bindMatrix = inverse(inverseBindMatrix);
|
||||
|
||||
const auto inverseModelSpaceTransform = inverse(modelSpaceTransform);
|
||||
|
||||
const auto jointIndex = distance(joints.begin(), jointIter);
|
||||
transforms[jointIndex] = inverseModelSpaceTransform * bindMatrix;
|
||||
completed.insert(joint);
|
||||
stack.pop();
|
||||
}
|
||||
return transforms;
|
||||
}
|
||||
|
||||
void AnimationManager::updateBoneMatrices(GltfSceneAssetInstance *instance)
|
||||
{
|
||||
instance->getInstance()->getAnimator()->updateBoneMatrices();
|
||||
}
|
||||
|
||||
bool AnimationManager::addBoneAnimation(GltfSceneAssetInstance *instance,
|
||||
int skinIndex,
|
||||
int boneIndex,
|
||||
const float *const frameData,
|
||||
int numFrames,
|
||||
float frameLengthInMs,
|
||||
float fadeOutInSecs,
|
||||
float fadeInInSecs,
|
||||
float maxDelta)
|
||||
{
|
||||
std::lock_guard lock(_mutex);
|
||||
|
||||
BoneAnimation animation;
|
||||
animation.boneIndex = boneIndex;
|
||||
animation.frameData.clear();
|
||||
|
||||
const auto &inverseBindMatrix = instance->getInstance()->getInverseBindMatricesAt(skinIndex)[boneIndex];
|
||||
for (int i = 0; i < numFrames; i++)
|
||||
{
|
||||
math::mat4f frame(
|
||||
frameData[i * 16],
|
||||
frameData[(i * 16) + 1],
|
||||
frameData[(i * 16) + 2],
|
||||
frameData[(i * 16) + 3],
|
||||
frameData[(i * 16) + 4],
|
||||
frameData[(i * 16) + 5],
|
||||
frameData[(i * 16) + 6],
|
||||
frameData[(i * 16) + 7],
|
||||
frameData[(i * 16) + 8],
|
||||
frameData[(i * 16) + 9],
|
||||
frameData[(i * 16) + 10],
|
||||
frameData[(i * 16) + 11],
|
||||
frameData[(i * 16) + 12],
|
||||
frameData[(i * 16) + 13],
|
||||
frameData[(i * 16) + 14],
|
||||
frameData[(i * 16) + 15]);
|
||||
|
||||
animation.frameData.push_back(frame);
|
||||
}
|
||||
|
||||
animation.frameLengthInMs = frameLengthInMs;
|
||||
animation.start = std::chrono::high_resolution_clock::now();
|
||||
animation.reverse = false;
|
||||
animation.durationInSecs = (frameLengthInMs * numFrames) / 1000.0f;
|
||||
animation.lengthInFrames = numFrames;
|
||||
animation.frameLengthInMs = frameLengthInMs;
|
||||
animation.fadeOutInSecs = fadeOutInSecs;
|
||||
animation.fadeInInSecs = fadeInInSecs;
|
||||
animation.maxDelta = maxDelta;
|
||||
animation.skinIndex = skinIndex;
|
||||
if (!_animationComponentManager->hasComponent(instance->getInstance()->getRoot()))
|
||||
{
|
||||
Log("ERROR: specified entity is not animatable (has no animation component attached).");
|
||||
return false;
|
||||
}
|
||||
auto animationComponentInstance = _animationComponentManager->getInstance(instance->getInstance()->getRoot());
|
||||
|
||||
auto &animationComponent = _animationComponentManager->elementAt<0>(animationComponentInstance);
|
||||
auto &boneAnimations = animationComponent.boneAnimations;
|
||||
|
||||
boneAnimations.emplace_back(animation);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AnimationManager::playGltfAnimation(GltfSceneAssetInstance *instance, int index, bool loop, bool reverse, bool replaceActive, float crossfade, float startOffset)
|
||||
{
|
||||
std::lock_guard lock(_mutex);
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
Log("ERROR: glTF animation index must be greater than zero.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_animationComponentManager->hasComponent(instance->getEntity()))
|
||||
{
|
||||
Log("ERROR: specified entity is not animatable (has no animation component attached).");
|
||||
return;
|
||||
}
|
||||
|
||||
auto animationComponentInstance = _animationComponentManager->getInstance(instance->getEntity());
|
||||
|
||||
auto &animationComponent = _animationComponentManager->elementAt<0>(animationComponentInstance);
|
||||
|
||||
if (replaceActive)
|
||||
{
|
||||
if (animationComponent.gltfAnimations.size() > 0)
|
||||
{
|
||||
auto &last = animationComponent.gltfAnimations.back();
|
||||
animationComponent.fadeGltfAnimationIndex = last.index;
|
||||
animationComponent.fadeDuration = crossfade;
|
||||
auto now = high_resolution_clock::now();
|
||||
auto elapsedInSecs = float(std::chrono::duration_cast<std::chrono::milliseconds>(now - last.start).count()) / 1000.0f;
|
||||
animationComponent.fadeOutAnimationStart = elapsedInSecs;
|
||||
animationComponent.gltfAnimations.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
animationComponent.fadeGltfAnimationIndex = -1;
|
||||
animationComponent.fadeDuration = 0.0f;
|
||||
}
|
||||
}
|
||||
else if (crossfade > 0)
|
||||
{
|
||||
Log("ERROR: crossfade only supported when replaceActive is true.");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
animationComponent.fadeGltfAnimationIndex = -1;
|
||||
animationComponent.fadeDuration = 0.0f;
|
||||
}
|
||||
|
||||
GltfAnimation animation;
|
||||
animation.startOffset = startOffset;
|
||||
animation.index = index;
|
||||
animation.start = std::chrono::high_resolution_clock::now();
|
||||
animation.loop = loop;
|
||||
animation.reverse = reverse;
|
||||
animation.durationInSecs = instance->getInstance()->getAnimator()->getAnimationDuration(index);
|
||||
|
||||
bool found = false;
|
||||
|
||||
// don't play the animation if it's already running
|
||||
for (int i = 0; i < animationComponent.gltfAnimations.size(); i++)
|
||||
{
|
||||
if (animationComponent.gltfAnimations[i].index == index)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
animationComponent.gltfAnimations.push_back(animation);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationManager::stopGltfAnimation(GltfSceneAssetInstance *instance, int index)
|
||||
{
|
||||
|
||||
auto animationComponentInstance = _animationComponentManager->getInstance(instance->getEntity());
|
||||
auto &animationComponent = _animationComponentManager->elementAt<0>(animationComponentInstance);
|
||||
|
||||
auto erased = std::remove_if(animationComponent.gltfAnimations.begin(),
|
||||
animationComponent.gltfAnimations.end(),
|
||||
[=](GltfAnimation &anim)
|
||||
{ return anim.index == index; });
|
||||
animationComponent.gltfAnimations.erase(erased,
|
||||
animationComponent.gltfAnimations.end());
|
||||
return;
|
||||
}
|
||||
|
||||
void AnimationManager::setMorphTargetWeights(utils::Entity entity, const float *const weights, const int count)
|
||||
{
|
||||
RenderableManager &rm = _engine->getRenderableManager();
|
||||
auto renderableInstance = rm.getInstance(entity);
|
||||
rm.setMorphWeights(
|
||||
renderableInstance,
|
||||
weights,
|
||||
count);
|
||||
}
|
||||
|
||||
void AnimationManager::setGltfAnimationFrame(GltfSceneAssetInstance *instance, int animationIndex, int animationFrame)
|
||||
{
|
||||
auto offset = 60 * animationFrame * 1000; // TODO - don't hardcore 60fps framerate
|
||||
instance->getInstance()->getAnimator()->applyAnimation(animationIndex, offset);
|
||||
instance->getInstance()->getAnimator()->updateBoneMatrices();
|
||||
return;
|
||||
}
|
||||
|
||||
float AnimationManager::getGltfAnimationDuration(GltfSceneAssetInstance *instance, int animationIndex)
|
||||
{
|
||||
return instance->getInstance()->getAnimator()->getAnimationDuration(animationIndex);
|
||||
}
|
||||
|
||||
std::vector<std::string> AnimationManager::getGltfAnimationNames(GltfSceneAssetInstance *instance)
|
||||
{
|
||||
std::vector<std::string> names;
|
||||
|
||||
size_t count = instance->getInstance()->getAnimator()->getAnimationCount();
|
||||
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
names.push_back(instance->getInstance()->getAnimator()->getAnimationName(i));
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
std::vector<std::string> AnimationManager::getMorphTargetNames(GltfSceneAsset *asset, EntityId childEntity)
|
||||
{
|
||||
std::vector<std::string> names;
|
||||
|
||||
auto filamentAsset = asset->getAsset();
|
||||
|
||||
const utils::Entity targetEntity = utils::Entity::import(childEntity);
|
||||
|
||||
size_t count = filamentAsset->getMorphTargetCountAt(targetEntity);
|
||||
for (int j = 0; j < count; j++)
|
||||
{
|
||||
const char *morphName = filamentAsset->getMorphTargetNameAt(targetEntity, j);
|
||||
names.push_back(morphName);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
vector<Entity> AnimationManager::getBoneEntities(GltfSceneAssetInstance *instance, int skinIndex)
|
||||
{
|
||||
auto *joints = instance->getInstance()->getJointsAt(skinIndex);
|
||||
auto jointCount = instance->getInstance()->getJointCountAt(skinIndex);
|
||||
std::vector<Entity> boneEntities(joints, joints + jointCount);
|
||||
return boneEntities;
|
||||
}
|
||||
|
||||
void AnimationManager::update()
|
||||
{
|
||||
std::lock_guard lock(_mutex);
|
||||
_animationComponentManager->update();
|
||||
}
|
||||
|
||||
math::mat4f AnimationManager::getInverseBindMatrix(GltfSceneAssetInstance *instance, int skinIndex, int boneIndex)
|
||||
{
|
||||
return instance->getInstance()->getInverseBindMatricesAt(skinIndex)[boneIndex];
|
||||
}
|
||||
|
||||
bool AnimationManager::setBoneTransform(GltfSceneAssetInstance *instance, int32_t skinIndex, int boneIndex, math::mat4f transform)
|
||||
{
|
||||
std::lock_guard lock(_mutex);
|
||||
|
||||
RenderableManager &rm = _engine->getRenderableManager();
|
||||
|
||||
const auto &renderableInstance = rm.getInstance(instance->getEntity());
|
||||
|
||||
if (!renderableInstance.isValid())
|
||||
{
|
||||
Log("Specified entity is not a renderable. You probably provided the ultimate parent entity of a glTF asset, which is non-renderable. ");
|
||||
return false;
|
||||
}
|
||||
|
||||
rm.setBones(
|
||||
renderableInstance,
|
||||
&transform,
|
||||
1,
|
||||
boneIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AnimationManager::addAnimationComponent(EntityId entity)
|
||||
{
|
||||
_animationComponentManager->addAnimationComponent(utils::Entity::import(entity));
|
||||
return true;
|
||||
}
|
||||
|
||||
void AnimationManager::removeAnimationComponent(EntityId entity)
|
||||
{
|
||||
_animationComponentManager->removeComponent(utils::Entity::import(entity));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <filament/Viewport.h>
|
||||
#include <filament/geometry/SurfaceOrientation.h>
|
||||
|
||||
#include "CustomGeometry.hpp"
|
||||
#include "scene/CustomGeometry.hpp"
|
||||
#include "Log.hpp"
|
||||
|
||||
namespace thermion
|
||||
@@ -22,9 +22,10 @@ namespace thermion
|
||||
float *normals, uint32_t numNormals, float *uvs,
|
||||
uint32_t numUvs, uint16_t *indices,
|
||||
uint32_t numIndices,
|
||||
MaterialInstance* materialInstance,
|
||||
RenderableManager::PrimitiveType primitiveType,
|
||||
Engine *engine)
|
||||
: numVertices(numVertices), numIndices(numIndices), _engine(engine)
|
||||
: numVertices(numVertices), numIndices(numIndices), _materialInstance(materialInstance), _engine(engine)
|
||||
{
|
||||
|
||||
this->primitiveType = primitiveType;
|
||||
@@ -214,7 +215,6 @@ namespace thermion
|
||||
|
||||
CustomGeometry::~CustomGeometry()
|
||||
{
|
||||
Log("GEOMETRY DESTRUCTOR");
|
||||
_engine->destroy(vertexBuffer);
|
||||
_engine->destroy(indexBuffer);
|
||||
}
|
||||
125
thermion_dart/native/src/scene/GeometrySceneAsset.cpp
Normal file
125
thermion_dart/native/src/scene/GeometrySceneAsset.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
#include <vector>
|
||||
|
||||
#include <gltfio/MaterialProvider.h>
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/Frustum.h>
|
||||
#include <filament/RenderableManager.h>
|
||||
#include <filament/Texture.h>
|
||||
#include <filament/TransformManager.h>
|
||||
#include <filament/Viewport.h>
|
||||
#include <filament/geometry/SurfaceOrientation.h>
|
||||
|
||||
#include "Log.hpp"
|
||||
#include "scene/GeometrySceneAsset.hpp"
|
||||
#include "scene/GeometrySceneAssetBuilder.hpp"
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
using namespace filament;
|
||||
|
||||
GeometrySceneAsset::GeometrySceneAsset(
|
||||
bool isInstance,
|
||||
Engine *engine,
|
||||
VertexBuffer *vertexBuffer,
|
||||
IndexBuffer *indexBuffer,
|
||||
MaterialInstance **materialInstances,
|
||||
size_t materialInstanceCount,
|
||||
RenderableManager::PrimitiveType primitiveType,
|
||||
Box boundingBox)
|
||||
: _isInstance(isInstance),
|
||||
_engine(engine), _vertexBuffer(vertexBuffer), _indexBuffer(indexBuffer), _materialInstances(materialInstances), _materialInstanceCount(materialInstanceCount), _primitiveType(primitiveType), _boundingBox(boundingBox)
|
||||
{
|
||||
_entity = utils::EntityManager::get().create();
|
||||
|
||||
RenderableManager::Builder builder(1);
|
||||
builder.boundingBox(_boundingBox)
|
||||
.geometry(0, _primitiveType, _vertexBuffer, _indexBuffer)
|
||||
.culling(true)
|
||||
.receiveShadows(true)
|
||||
.castShadows(true);
|
||||
for (int i = 0; i < materialInstanceCount; i++)
|
||||
{
|
||||
builder.material(i, materialInstances[i]);
|
||||
}
|
||||
builder.build(*_engine, _entity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GeometrySceneAsset::~GeometrySceneAsset()
|
||||
{
|
||||
if (_engine)
|
||||
{
|
||||
if (_vertexBuffer && !_isInstance)
|
||||
_engine->destroy(_vertexBuffer);
|
||||
if (_indexBuffer && !_isInstance)
|
||||
_engine->destroy(_indexBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
SceneAsset *GeometrySceneAsset::createInstance(MaterialInstance **materialInstances, size_t materialInstanceCount)
|
||||
{
|
||||
if (_isInstance)
|
||||
{
|
||||
Log("Cannot create an instance from another instance. Ensure you are calling createInstance with the original asset.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<GeometrySceneAsset> instance = std::make_unique<GeometrySceneAsset>(
|
||||
true,
|
||||
_engine,
|
||||
_vertexBuffer,
|
||||
_indexBuffer,
|
||||
materialInstances,
|
||||
materialInstanceCount,
|
||||
_primitiveType,
|
||||
_boundingBox);
|
||||
auto *raw = instance.get();
|
||||
_instances.push_back(std::move(instance));
|
||||
return raw;
|
||||
}
|
||||
|
||||
// std::unique_ptr<GeometrySceneAsset> GeometrySceneAsset::create(
|
||||
// float *vertices, uint32_t numVertices,
|
||||
// float *normals, uint32_t numNormals,
|
||||
// float *uvs, uint32_t numUvs,
|
||||
// uint16_t *indices, uint32_t numIndices,
|
||||
// MaterialInstance **materialInstances,
|
||||
// size_t materialInstanceCount,
|
||||
// RenderableManager::PrimitiveType primitiveType,
|
||||
// Engine *engine)
|
||||
// {
|
||||
|
||||
// // Setup texture if needed
|
||||
// if (asset && uvs && numUvs > 0 &&
|
||||
// asset->getMaterialInstance() &&
|
||||
// asset->getMaterialInstance()->getMaterial()->hasParameter("baseColorMap"))
|
||||
// {
|
||||
// static constexpr uint32_t textureSize = 1;
|
||||
// static constexpr uint32_t white = 0x00ffffff;
|
||||
|
||||
// auto texture = Texture::Builder()
|
||||
// .width(textureSize)
|
||||
// .height(textureSize)
|
||||
// .levels(1)
|
||||
// .format(Texture::InternalFormat::RGBA8)
|
||||
// .build(*engine);
|
||||
|
||||
// filament::backend::PixelBufferDescriptor pbd(
|
||||
// &white, 4, Texture::Format::RGBA, Texture::Type::UBYTE);
|
||||
// texture->setImage(*engine, 0, std::move(pbd));
|
||||
|
||||
// TextureSampler sampler(
|
||||
// TextureSampler::MinFilter::NEAREST,
|
||||
// TextureSampler::MagFilter::NEAREST);
|
||||
// sampler.setWrapModeS(TextureSampler::WrapMode::REPEAT);
|
||||
// sampler.setWrapModeT(TextureSampler::WrapMode::REPEAT);
|
||||
|
||||
// asset->getMaterialInstance()->setParameter("baseColorMap", texture, sampler);
|
||||
// }
|
||||
|
||||
// return asset;
|
||||
// }
|
||||
|
||||
} // namespace thermion
|
||||
367
thermion_dart/native/src/scene/Gizmo.cpp
Normal file
367
thermion_dart/native/src/scene/Gizmo.cpp
Normal file
@@ -0,0 +1,367 @@
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/RenderableManager.h>
|
||||
#include <filament/TransformManager.h>
|
||||
|
||||
#include <utils/Entity.h>
|
||||
#include <utils/EntityManager.h>
|
||||
|
||||
#include <gltfio/math.h>
|
||||
|
||||
#include "scene/Gizmo.hpp"
|
||||
#include "scene/SceneManager.hpp"
|
||||
|
||||
#include "material/unlit_fixed_size.h"
|
||||
|
||||
#include "Log.hpp"
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
using namespace filament::gltfio;
|
||||
|
||||
// First, create the black cube at the center
|
||||
// The axes widgets will be parented to this entity
|
||||
Entity Gizmo::createParentEntity()
|
||||
{
|
||||
auto &transformManager = _engine->getTransformManager();
|
||||
auto &entityManager = _engine->getEntityManager();
|
||||
|
||||
auto parent = entityManager.create();
|
||||
|
||||
auto *parentMaterialInstance = _material->createInstance();
|
||||
parentMaterialInstance->setParameter("baseColorFactor", math::float4{0.0f, 1.0f, 1.0f, 1.0f});
|
||||
parentMaterialInstance->setParameter("scale", 4.0f);
|
||||
|
||||
_materialInstances.push_back(parentMaterialInstance);
|
||||
|
||||
// Create center cube vertices
|
||||
float centerCubeSize = 0.1f;
|
||||
float *centerCubeVertices = new float[8 * 3]{
|
||||
-centerCubeSize, -centerCubeSize, -centerCubeSize,
|
||||
centerCubeSize, -centerCubeSize, -centerCubeSize,
|
||||
centerCubeSize, centerCubeSize, -centerCubeSize,
|
||||
-centerCubeSize, centerCubeSize, -centerCubeSize,
|
||||
-centerCubeSize, -centerCubeSize, centerCubeSize,
|
||||
centerCubeSize, -centerCubeSize, centerCubeSize,
|
||||
centerCubeSize, centerCubeSize, centerCubeSize,
|
||||
-centerCubeSize, centerCubeSize, centerCubeSize};
|
||||
|
||||
// Create center cube indices
|
||||
uint16_t *centerCubeIndices = new uint16_t[36]{
|
||||
0, 1, 2, 2, 3, 0,
|
||||
1, 5, 6, 6, 2, 1,
|
||||
5, 4, 7, 7, 6, 5,
|
||||
4, 0, 3, 3, 7, 4,
|
||||
3, 2, 6, 6, 7, 3,
|
||||
4, 5, 1, 1, 0, 4};
|
||||
|
||||
auto centerCubeVb = VertexBuffer::Builder()
|
||||
.vertexCount(8)
|
||||
.bufferCount(1)
|
||||
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3)
|
||||
.build(*_engine);
|
||||
|
||||
centerCubeVb->setBufferAt(*_engine, 0, VertexBuffer::BufferDescriptor(centerCubeVertices, 8 * sizeof(filament::math::float3), [](void *buffer, size_t size, void *)
|
||||
{ delete[] static_cast<float *>(buffer); }));
|
||||
|
||||
auto centerCubeIb = IndexBuffer::Builder().indexCount(36).bufferType(IndexBuffer::IndexType::USHORT).build(*_engine);
|
||||
centerCubeIb->setBuffer(*_engine, IndexBuffer::BufferDescriptor(
|
||||
centerCubeIndices, 36 * sizeof(uint16_t),
|
||||
[](void *buffer, size_t size, void *)
|
||||
{ delete[] static_cast<uint16_t *>(buffer); }));
|
||||
|
||||
RenderableManager::Builder(1)
|
||||
.boundingBox({{-centerCubeSize, -centerCubeSize, -centerCubeSize},
|
||||
{centerCubeSize, centerCubeSize, centerCubeSize}})
|
||||
.material(0, parentMaterialInstance)
|
||||
.layerMask(0xFF, 1u << SceneManager::LAYERS::OVERLAY)
|
||||
.priority(7)
|
||||
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, centerCubeVb, centerCubeIb, 0, 36)
|
||||
.culling(false)
|
||||
.build(*_engine, parent);
|
||||
|
||||
auto parentTransformInstance = transformManager.getInstance(parent);
|
||||
math::mat4f cubeTransform;
|
||||
transformManager.setTransform(parentTransformInstance, cubeTransform);
|
||||
return parent;
|
||||
}
|
||||
|
||||
Gizmo::Gizmo(Engine *engine, View *view, Scene *scene, Material *material) : _engine(engine), _view(view), _scene(scene), _material(material)
|
||||
{
|
||||
auto parent = createParentEntity();
|
||||
auto x = createAxisEntity(Gizmo::Axis::X, parent);
|
||||
auto y = createAxisEntity(Gizmo::Axis::Y, parent);
|
||||
auto z = createAxisEntity(Gizmo::Axis::Z, parent);
|
||||
|
||||
auto xHitTest = createHitTestEntity(Gizmo::Axis::X, parent);
|
||||
auto yHitTest = createHitTestEntity(Gizmo::Axis::Y, parent);
|
||||
auto zHitTest = createHitTestEntity(Gizmo::Axis::Z, parent);
|
||||
|
||||
_entities = std::vector{parent, x, y, z, xHitTest, yHitTest, zHitTest};
|
||||
_parent = parent;
|
||||
_x = x;
|
||||
_y = y;
|
||||
_z = z;
|
||||
_xHitTest = xHitTest;
|
||||
_yHitTest = yHitTest;
|
||||
_zHitTest = zHitTest;
|
||||
}
|
||||
|
||||
Entity Gizmo::createAxisEntity(Gizmo::Axis axis, Entity parent)
|
||||
{
|
||||
auto &entityManager = _engine->getEntityManager();
|
||||
auto &transformManager = _engine->getTransformManager();
|
||||
auto *materialInstance = _material->createInstance();
|
||||
_materialInstances.push_back(materialInstance);
|
||||
auto entity = entityManager.create();
|
||||
|
||||
auto baseColor = inactiveColors[axis];
|
||||
|
||||
// Line and arrow vertices
|
||||
float lineLength = 0.6f;
|
||||
float lineWidth = 0.008f;
|
||||
float arrowLength = 0.06f;
|
||||
float arrowWidth = 0.02f;
|
||||
float *vertices = new float[13 * 3]{
|
||||
// Line vertices (8 vertices)
|
||||
-lineWidth, -lineWidth, 0.0f,
|
||||
lineWidth, -lineWidth, 0.0f,
|
||||
lineWidth, lineWidth, 0.0f,
|
||||
-lineWidth, lineWidth, 0.0f,
|
||||
-lineWidth, -lineWidth, lineLength,
|
||||
lineWidth, -lineWidth, lineLength,
|
||||
lineWidth, lineWidth, lineLength,
|
||||
-lineWidth, lineWidth, lineLength,
|
||||
// Arrow vertices (5 vertices)
|
||||
0.0f, 0.0f, lineLength + arrowLength, // Tip of the arrow
|
||||
-arrowWidth, -arrowWidth, lineLength, // Base of the arrow
|
||||
arrowWidth, -arrowWidth, lineLength,
|
||||
arrowWidth, arrowWidth, lineLength,
|
||||
-arrowWidth, arrowWidth, lineLength};
|
||||
|
||||
// Line and arrow indices
|
||||
uint16_t *indices = new uint16_t[24 + 18]{
|
||||
// Line indices (24 indices)
|
||||
0, 1, 5, 5, 4, 0,
|
||||
1, 2, 6, 6, 5, 1,
|
||||
2, 3, 7, 7, 6, 2,
|
||||
3, 0, 4, 4, 7, 3,
|
||||
// // Arrow indices (18 indices)
|
||||
8, 9, 10, // Front face
|
||||
8, 10, 11, // Right face
|
||||
8, 11, 12, // Back face
|
||||
8, 12, 9, // Left face
|
||||
9, 12, 11, 11, 10, 9 // Base of the arrow
|
||||
};
|
||||
|
||||
auto vb = VertexBuffer::Builder()
|
||||
.vertexCount(13)
|
||||
.bufferCount(1)
|
||||
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3)
|
||||
.build(*_engine);
|
||||
|
||||
vb->setBufferAt(*_engine, 0, VertexBuffer::BufferDescriptor(vertices, 13 * sizeof(filament::math::float3), [](void *buffer, size_t size, void *)
|
||||
{ delete[] static_cast<float *>(buffer); }));
|
||||
|
||||
auto ib = IndexBuffer::Builder().indexCount(42).bufferType(IndexBuffer::IndexType::USHORT).build(*_engine);
|
||||
ib->setBuffer(*_engine, IndexBuffer::BufferDescriptor(
|
||||
indices, 42 * sizeof(uint16_t),
|
||||
[](void *buffer, size_t size, void *)
|
||||
{ delete[] static_cast<uint16_t *>(buffer); }));
|
||||
|
||||
materialInstance->setParameter("baseColorFactor", baseColor);
|
||||
materialInstance->setParameter("scale", 4.0f);
|
||||
materialInstance->setDepthCulling(false);
|
||||
materialInstance->setDepthFunc(MaterialInstance::DepthFunc::A);
|
||||
|
||||
RenderableManager::Builder(1)
|
||||
.boundingBox({{-arrowWidth, -arrowWidth, 0},
|
||||
{arrowWidth, arrowWidth, lineLength + arrowLength}})
|
||||
.material(0, materialInstance)
|
||||
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, vb, ib, 0, 42)
|
||||
.priority(6)
|
||||
.layerMask(0xFF, 1u << SceneManager::LAYERS::OVERLAY)
|
||||
.culling(false)
|
||||
.receiveShadows(false)
|
||||
.castShadows(false)
|
||||
.build(*_engine, entity);
|
||||
|
||||
auto transformInstance = transformManager.getInstance(entity);
|
||||
|
||||
transformManager.setTransform(transformInstance, getRotationForAxis(axis));
|
||||
|
||||
// parent the axis to the center cube
|
||||
auto parentTransformInstance = transformManager.getInstance(parent);
|
||||
transformManager.setParent(transformInstance, parentTransformInstance);
|
||||
return entity;
|
||||
}
|
||||
|
||||
Gizmo::~Gizmo()
|
||||
{
|
||||
_scene->removeEntities(_entities.data(), _entities.size());
|
||||
|
||||
for (auto entity : _entities)
|
||||
{
|
||||
_engine->destroy(entity);
|
||||
}
|
||||
|
||||
for (auto *materialInstance : _materialInstances)
|
||||
{
|
||||
_engine->destroy(materialInstance);
|
||||
}
|
||||
}
|
||||
|
||||
Entity Gizmo::createHitTestEntity(Gizmo::Axis axis, Entity parent)
|
||||
{
|
||||
auto &entityManager = EntityManager::get();
|
||||
auto &transformManager = _engine->getTransformManager();
|
||||
|
||||
auto parentTransformInstance = transformManager.getInstance(parent);
|
||||
|
||||
float volumeWidth = 0.2f;
|
||||
float volumeLength = 1.2f;
|
||||
float volumeDepth = 0.2f;
|
||||
|
||||
float *volumeVertices = new float[8 * 3]{
|
||||
-volumeWidth / 2, -volumeDepth / 2, 0,
|
||||
volumeWidth / 2, -volumeDepth / 2, 0,
|
||||
volumeWidth / 2, -volumeDepth / 2, volumeLength,
|
||||
-volumeWidth / 2, -volumeDepth / 2, volumeLength,
|
||||
-volumeWidth / 2, volumeDepth / 2, 0,
|
||||
volumeWidth / 2, volumeDepth / 2, 0,
|
||||
volumeWidth / 2, volumeDepth / 2, volumeLength,
|
||||
-volumeWidth / 2, volumeDepth / 2, volumeLength};
|
||||
|
||||
uint16_t *volumeIndices = new uint16_t[36]{
|
||||
0, 1, 2, 2, 3, 0, // Bottom face
|
||||
4, 5, 6, 6, 7, 4, // Top face
|
||||
0, 4, 7, 7, 3, 0, // Left face
|
||||
1, 5, 6, 6, 2, 1, // Right face
|
||||
0, 1, 5, 5, 4, 0, // Front face
|
||||
3, 2, 6, 6, 7, 3 // Back face
|
||||
};
|
||||
|
||||
auto volumeVb = VertexBuffer::Builder()
|
||||
.vertexCount(8)
|
||||
.bufferCount(1)
|
||||
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3)
|
||||
.build(*_engine);
|
||||
|
||||
volumeVb->setBufferAt(*_engine, 0, VertexBuffer::BufferDescriptor(volumeVertices, 8 * sizeof(filament::math::float3), [](void *buffer, size_t size, void *)
|
||||
{ delete[] static_cast<float *>(buffer); }));
|
||||
|
||||
auto volumeIb = IndexBuffer::Builder()
|
||||
.indexCount(36)
|
||||
.bufferType(IndexBuffer::IndexType::USHORT)
|
||||
.build(*_engine);
|
||||
|
||||
volumeIb->setBuffer(*_engine, IndexBuffer::BufferDescriptor(
|
||||
volumeIndices, 36 * sizeof(uint16_t),
|
||||
[](void *buffer, size_t size, void *)
|
||||
{ delete[] static_cast<uint16_t *>(buffer); }));
|
||||
|
||||
auto entity = entityManager.create();
|
||||
auto *materialInstance = _material->createInstance();
|
||||
_materialInstances.push_back(materialInstance);
|
||||
materialInstance->setParameter("baseColorFactor", math::float4{0.0f, 0.0f, 0.0f, 0.0f});
|
||||
materialInstance->setParameter("scale", 4.0f);
|
||||
|
||||
RenderableManager::Builder(1)
|
||||
.boundingBox({{-volumeWidth / 2, -volumeDepth / 2, 0}, {volumeWidth / 2, volumeDepth / 2, volumeLength}})
|
||||
.material(0, materialInstance)
|
||||
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, volumeVb, volumeIb, 0, 36)
|
||||
.priority(7)
|
||||
.layerMask(0xFF, 1u << SceneManager::LAYERS::OVERLAY)
|
||||
.culling(false)
|
||||
.receiveShadows(false)
|
||||
.castShadows(false)
|
||||
.build(*_engine, entity);
|
||||
|
||||
auto transformInstance = transformManager.getInstance(entity);
|
||||
transformManager.setTransform(transformInstance, getRotationForAxis(axis));
|
||||
// Parent the picking volume to the center cube
|
||||
transformManager.setParent(transformInstance, parentTransformInstance);
|
||||
return entity;
|
||||
}
|
||||
|
||||
void Gizmo::highlight(Gizmo::Axis axis)
|
||||
{
|
||||
auto &rm = _engine->getRenderableManager();
|
||||
auto entity = getEntityForAxis(axis);
|
||||
if (entity.isNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto renderableInstance = rm.getInstance(entity);
|
||||
|
||||
if (!renderableInstance.isValid())
|
||||
{
|
||||
Log("Invalid renderable for axis");
|
||||
return;
|
||||
}
|
||||
auto *materialInstance = rm.getMaterialInstanceAt(renderableInstance, 0);
|
||||
math::float4 baseColor = activeColors[axis];
|
||||
materialInstance->setParameter("baseColorFactor", baseColor);
|
||||
}
|
||||
|
||||
void Gizmo::unhighlight(Gizmo::Axis axis)
|
||||
{
|
||||
auto &rm = _engine->getRenderableManager();
|
||||
auto entity = getEntityForAxis(axis);
|
||||
if (entity.isNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto renderableInstance = rm.getInstance(entity);
|
||||
if (!renderableInstance.isValid())
|
||||
{
|
||||
Log("Invalid renderable for axis");
|
||||
return;
|
||||
}
|
||||
auto *materialInstance = rm.getMaterialInstanceAt(renderableInstance, 0);
|
||||
math::float4 baseColor = inactiveColors[axis];
|
||||
materialInstance->setParameter("baseColorFactor", baseColor);
|
||||
}
|
||||
|
||||
void Gizmo::pick(uint32_t x, uint32_t y, GizmoPickCallback callback)
|
||||
{
|
||||
|
||||
auto handler = new Gizmo::PickCallbackHandler(this, callback);
|
||||
_view->pick(x, y, [=](filament::View::PickingQueryResult const &result)
|
||||
{
|
||||
handler->handle(result);
|
||||
delete handler; });
|
||||
}
|
||||
|
||||
bool Gizmo::isGizmoEntity(Entity e)
|
||||
{
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
if (e == _entities[i])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
math::mat4f Gizmo::getRotationForAxis(Gizmo::Axis axis)
|
||||
{
|
||||
|
||||
math::mat4f transform;
|
||||
|
||||
switch (axis)
|
||||
{
|
||||
case Axis::X:
|
||||
transform = math::mat4f::rotation(math::F_PI_2, math::float3{0, 1, 0});
|
||||
break;
|
||||
case Axis::Y:
|
||||
transform = math::mat4f::rotation(-math::F_PI_2, math::float3{1, 0, 0});
|
||||
break;
|
||||
case Axis::Z:
|
||||
break;
|
||||
}
|
||||
return transform;
|
||||
}
|
||||
|
||||
}
|
||||
61
thermion_dart/native/src/scene/GltfSceneAsset.cpp
Normal file
61
thermion_dart/native/src/scene/GltfSceneAsset.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
|
||||
#include "scene/GltfSceneAsset.hpp"
|
||||
#include "scene/GltfSceneAssetInstance.hpp"
|
||||
#include "gltfio/FilamentInstance.h"
|
||||
#include "Log.hpp"
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
GltfSceneAsset::~GltfSceneAsset()
|
||||
{
|
||||
_instances.clear();
|
||||
_asset->releaseSourceData();
|
||||
_assetLoader->destroyAsset(_asset);
|
||||
}
|
||||
|
||||
SceneAsset *GltfSceneAsset::createInstance(MaterialInstance **materialInstances, size_t materialInstanceCount)
|
||||
{
|
||||
auto instanceNumber = _instances.size();
|
||||
|
||||
if (instanceNumber > _asset->getAssetInstanceCount() - 1)
|
||||
{
|
||||
Log("No instances available for reuse. When loading the asset, you must pre-allocate the number of instances you wish to make available for use. Try increasing this number.");
|
||||
return std::nullptr_t();
|
||||
}
|
||||
Log("Creating instance %d", instanceNumber);
|
||||
auto instance = _asset->getAssetInstances()[instanceNumber];
|
||||
instance->recomputeBoundingBoxes();
|
||||
instance->getAnimator()->updateBoneMatrices();
|
||||
|
||||
auto& rm = _engine->getRenderableManager();
|
||||
|
||||
if(materialInstanceCount > 0) {
|
||||
for(int i = 0; i < instance->getEntityCount(); i++) {
|
||||
auto renderableInstance = rm.getInstance(instance->getEntities()[i]);
|
||||
if(!renderableInstance.isValid()) {
|
||||
Log("Instance is not renderable");
|
||||
} else {
|
||||
for(int i = 0; i < materialInstanceCount; i++) {
|
||||
rm.setMaterialInstanceAt(renderableInstance, i, materialInstances[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<GltfSceneAssetInstance> sceneAssetInstance = std::make_unique<GltfSceneAssetInstance>(
|
||||
instance,
|
||||
_engine,
|
||||
materialInstances,
|
||||
materialInstanceCount
|
||||
);
|
||||
|
||||
auto *raw = sceneAssetInstance.get();
|
||||
|
||||
_instances.push_back(std::move(sceneAssetInstance));
|
||||
return raw;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
14
thermion_dart/native/src/scene/GltfSceneAssetInstance.cpp
Normal file
14
thermion_dart/native/src/scene/GltfSceneAssetInstance.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
#include "scene/GltfSceneAssetInstance.hpp"
|
||||
#include "gltfio/FilamentInstance.h"
|
||||
#include "Log.hpp"
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
GltfSceneAssetInstance::~GltfSceneAssetInstance()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
349
thermion_dart/native/src/scene/RotationGizmo.cpp
Normal file
349
thermion_dart/native/src/scene/RotationGizmo.cpp
Normal file
@@ -0,0 +1,349 @@
|
||||
// #include <filament/Engine.h>
|
||||
// #include <filament/RenderableManager.h>
|
||||
// #include <filament/TransformManager.h>
|
||||
|
||||
// #include <gltfio/math.h>
|
||||
|
||||
// #include <utils/Entity.h>
|
||||
// #include <utils/EntityManager.h>
|
||||
|
||||
// #include <math.h>
|
||||
|
||||
// #include "scene/SceneManager.hpp"
|
||||
|
||||
// namespace thermion {
|
||||
|
||||
// using namespace filament::gltfio;
|
||||
|
||||
// RotationGizmo::RotationGizmo(Engine* engine, View* view, Scene* scene, Material* material)
|
||||
// : _engine(engine), _view(view), _scene(scene), _material(material) {
|
||||
|
||||
// auto& entityManager = EntityManager::get();
|
||||
// auto& transformManager = _engine->getTransformManager();
|
||||
|
||||
// // Create center cube
|
||||
// auto parentEntity = entityManager.create();
|
||||
// auto* parentMaterialInstance = _material->createInstance();
|
||||
// parentMaterialInstance->setParameter("baseColorFactor", math::float4{0.0f, 0.0f, 0.0f, 1.0f});
|
||||
// parentMaterialInstance->setParameter("scale", 4.0f);
|
||||
|
||||
// _entities[0] = parentEntity;
|
||||
// _materialInstances[0] = parentMaterialInstance;
|
||||
|
||||
// // Create center cube geometry
|
||||
// float centerCubeSize = 0.01f;
|
||||
// float* centerCubeVertices = new float[8 * 3]{
|
||||
// -centerCubeSize, -centerCubeSize, -centerCubeSize,
|
||||
// centerCubeSize, -centerCubeSize, -centerCubeSize,
|
||||
// centerCubeSize, centerCubeSize, -centerCubeSize,
|
||||
// -centerCubeSize, centerCubeSize, -centerCubeSize,
|
||||
// -centerCubeSize, -centerCubeSize, centerCubeSize,
|
||||
// centerCubeSize, -centerCubeSize, centerCubeSize,
|
||||
// centerCubeSize, centerCubeSize, centerCubeSize,
|
||||
// -centerCubeSize, centerCubeSize, centerCubeSize
|
||||
// };
|
||||
|
||||
// uint16_t* centerCubeIndices = new uint16_t[36]{
|
||||
// 0, 1, 2, 2, 3, 0,
|
||||
// 1, 5, 6, 6, 2, 1,
|
||||
// 5, 4, 7, 7, 6, 5,
|
||||
// 4, 0, 3, 3, 7, 4,
|
||||
// 3, 2, 6, 6, 7, 3,
|
||||
// 4, 5, 1, 1, 0, 4
|
||||
// };
|
||||
|
||||
// auto centerCubeVb = VertexBuffer::Builder()
|
||||
// .vertexCount(8)
|
||||
// .bufferCount(1)
|
||||
// .attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3)
|
||||
// .build(*engine);
|
||||
|
||||
// centerCubeVb->setBufferAt(*engine, 0,
|
||||
// VertexBuffer::BufferDescriptor(centerCubeVertices, 8 * sizeof(filament::math::float3),
|
||||
// [](void* buffer, size_t size, void*) { delete[] static_cast<float*>(buffer); }));
|
||||
|
||||
// auto centerCubeIb = IndexBuffer::Builder()
|
||||
// .indexCount(36)
|
||||
// .bufferType(IndexBuffer::IndexType::USHORT)
|
||||
// .build(*engine);
|
||||
|
||||
// centerCubeIb->setBuffer(*engine,
|
||||
// IndexBuffer::BufferDescriptor(centerCubeIndices, 36 * sizeof(uint16_t),
|
||||
// [](void* buffer, size_t size, void*) { delete[] static_cast<uint16_t*>(buffer); }));
|
||||
|
||||
// RenderableManager::Builder(1)
|
||||
// .boundingBox({{-centerCubeSize, -centerCubeSize, -centerCubeSize},
|
||||
// {centerCubeSize, centerCubeSize, centerCubeSize}})
|
||||
// .material(0, parentMaterialInstance)
|
||||
// .layerMask(0xFF, 1u << SceneManager::LAYERS::OVERLAY)
|
||||
// .priority(7)
|
||||
// .geometry(0, RenderableManager::PrimitiveType::TRIANGLES, centerCubeVb, centerCubeIb, 0, 36)
|
||||
// .culling(false)
|
||||
// .build(*engine, parentEntity);
|
||||
|
||||
// // Create rotation circles
|
||||
// constexpr int segments = 32;
|
||||
// float radius = 0.5f;
|
||||
// float* vertices;
|
||||
// uint16_t* indices;
|
||||
// int vertexCount, indexCount;
|
||||
|
||||
// createCircle(radius, segments, vertices, indices, vertexCount, indexCount);
|
||||
|
||||
// auto vb = VertexBuffer::Builder()
|
||||
// .vertexCount(vertexCount)
|
||||
// .bufferCount(1)
|
||||
// .attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3)
|
||||
// .build(*engine);
|
||||
|
||||
// vb->setBufferAt(*engine, 0,
|
||||
// VertexBuffer::BufferDescriptor(vertices, vertexCount * sizeof(filament::math::float3),
|
||||
// [](void* buffer, size_t size, void*) { delete[] static_cast<float*>(buffer); }));
|
||||
|
||||
// auto ib = IndexBuffer::Builder()
|
||||
// .indexCount(indexCount)
|
||||
// .bufferType(IndexBuffer::IndexType::USHORT)
|
||||
// .build(*engine);
|
||||
|
||||
// ib->setBuffer(*engine,
|
||||
// IndexBuffer::BufferDescriptor(indices, indexCount * sizeof(uint16_t),
|
||||
// [](void* buffer, size_t size, void*) { delete[] static_cast<uint16_t*>(buffer); }));
|
||||
|
||||
// // Create the three circular rotation handles
|
||||
// for (int i = 0; i < 3; i++) {
|
||||
// auto* materialInstance = _material->createInstance();
|
||||
// auto entity = entityManager.create();
|
||||
// _entities[i + 1] = entity;
|
||||
// _materialInstances[i + 1] = materialInstance;
|
||||
|
||||
// auto baseColor = inactiveColors[i];
|
||||
// math::mat4f transform;
|
||||
|
||||
// switch (i) {
|
||||
// case Axis::X:
|
||||
// transform = math::mat4f::rotation(math::F_PI_2, math::float3{0, 1, 0});
|
||||
// break;
|
||||
// case Axis::Y:
|
||||
// transform = math::mat4f::rotation(math::F_PI_2, math::float3{1, 0, 0});
|
||||
// break;
|
||||
// case Axis::Z:
|
||||
// break;
|
||||
// }
|
||||
|
||||
// materialInstance->setParameter("baseColorFactor", baseColor);
|
||||
// materialInstance->setParameter("scale", 4.0f);
|
||||
|
||||
// RenderableManager::Builder(1)
|
||||
// .boundingBox({{-radius, -radius, -0.01f}, {radius, radius, 0.01f}})
|
||||
// .material(0, materialInstance)
|
||||
// .geometry(0, RenderableManager::PrimitiveType::TRIANGLES, vb, ib, 0, indexCount)
|
||||
// .priority(6)
|
||||
// .layerMask(0xFF, 1u << SceneManager::LAYERS::OVERLAY)
|
||||
// .culling(false)
|
||||
// .receiveShadows(false)
|
||||
// .castShadows(false)
|
||||
// .build(*engine, entity);
|
||||
|
||||
// auto transformInstance = transformManager.getInstance(entity);
|
||||
// transformManager.setTransform(transformInstance, transform);
|
||||
// transformManager.setParent(transformInstance, transformManager.getInstance(parentEntity));
|
||||
// }
|
||||
|
||||
// createHitTestEntities();
|
||||
// setVisibility(true);
|
||||
// }
|
||||
|
||||
// void RotationGizmo::createCircle(float radius, int segments, float*& vertices, uint16_t*& indices, int& vertexCount, int& indexCount) {
|
||||
// vertexCount = segments * 2;
|
||||
// indexCount = segments * 6;
|
||||
|
||||
// vertices = new float[vertexCount * 3];
|
||||
// indices = new uint16_t[indexCount];
|
||||
|
||||
// float thickness = 0.01f;
|
||||
|
||||
// // Generate vertices for inner and outer circles
|
||||
// for (int i = 0; i < segments; i++) {
|
||||
// float angle = (2.0f * M_PI * i) / segments;
|
||||
// float x = cosf(angle);
|
||||
// float y = sinf(angle);
|
||||
|
||||
// // Inner circle vertex
|
||||
// vertices[i * 6] = x * (radius - thickness);
|
||||
// vertices[i * 6 + 1] = y * (radius - thickness);
|
||||
// vertices[i * 6 + 2] = 0.0f;
|
||||
|
||||
// // Outer circle vertex
|
||||
// vertices[i * 6 + 3] = x * (radius + thickness);
|
||||
// vertices[i * 6 + 4] = y * (radius + thickness);
|
||||
// vertices[i * 6 + 5] = 0.0f;
|
||||
// }
|
||||
|
||||
// // Generate indices for triangles
|
||||
// for (int i = 0; i < segments; i++) {
|
||||
// int next = (i + 1) % segments;
|
||||
|
||||
// // First triangle
|
||||
// indices[i * 6] = i * 2;
|
||||
// indices[i * 6 + 1] = i * 2 + 1;
|
||||
// indices[i * 6 + 2] = next * 2 + 1;
|
||||
|
||||
// // Second triangle
|
||||
// indices[i * 6 + 3] = i * 2;
|
||||
// indices[i * 6 + 4] = next * 2 + 1;
|
||||
// indices[i * 6 + 5] = next * 2;
|
||||
// }
|
||||
// }
|
||||
|
||||
// void RotationGizmo::createHitTestEntities() {
|
||||
// auto& entityManager = EntityManager::get();
|
||||
// auto& transformManager = _engine->getTransformManager();
|
||||
|
||||
// float radius = 0.5f;
|
||||
// float thickness = 0.1f;
|
||||
|
||||
// // Create hit test volumes for each rotation circle
|
||||
// for (int i = 4; i < 7; i++) {
|
||||
// _entities[i] = entityManager.create();
|
||||
// _materialInstances[i] = _material->createInstance();
|
||||
|
||||
// _materialInstances[i]->setParameter("baseColorFactor", math::float4{0.0f, 0.0f, 0.0f, 0.0f});
|
||||
// _materialInstances[i]->setParameter("scale", 4.0f);
|
||||
|
||||
// math::mat4f transform;
|
||||
// switch (i - 4) {
|
||||
// case Axis::X:
|
||||
// transform = math::mat4f::rotation(math::F_PI_2, math::float3{0, 1, 0});
|
||||
// break;
|
||||
// case Axis::Y:
|
||||
// transform = math::mat4f::rotation(math::F_PI_2, math::float3{1, 0, 0});
|
||||
// break;
|
||||
// case Axis::Z:
|
||||
// break;
|
||||
// }
|
||||
|
||||
// // Create a thicker invisible volume aroun
|
||||
|
||||
// // Create a thicker invisible volume around each rotation circle for hit testing
|
||||
// float* volumeVertices;
|
||||
// uint16_t* volumeIndices;
|
||||
// int volumeVertexCount, volumeIndexCount;
|
||||
// createCircle(radius, 32, volumeVertices, volumeIndices, volumeVertexCount, volumeIndexCount);
|
||||
|
||||
// auto volumeVb = VertexBuffer::Builder()
|
||||
// .vertexCount(volumeVertexCount)
|
||||
// .bufferCount(1)
|
||||
// .attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3)
|
||||
// .build(*_engine);
|
||||
|
||||
// volumeVb->setBufferAt(*_engine, 0,
|
||||
// VertexBuffer::BufferDescriptor(volumeVertices, volumeVertexCount * sizeof(filament::math::float3),
|
||||
// [](void* buffer, size_t size, void*) { delete[] static_cast<float*>(buffer); }));
|
||||
|
||||
// auto volumeIb = IndexBuffer::Builder()
|
||||
// .indexCount(volumeIndexCount)
|
||||
// .bufferType(IndexBuffer::IndexType::USHORT)
|
||||
// .build(*_engine);
|
||||
|
||||
// volumeIb->setBuffer(*_engine,
|
||||
// IndexBuffer::BufferDescriptor(volumeIndices, volumeIndexCount * sizeof(uint16_t),
|
||||
// [](void* buffer, size_t size, void*) { delete[] static_cast<uint16_t*>(buffer); }));
|
||||
|
||||
// RenderableManager::Builder(1)
|
||||
// .boundingBox({{-radius, -radius, -thickness/2}, {radius, radius, thickness/2}})
|
||||
// .material(0, _materialInstances[i])
|
||||
// .geometry(0, RenderableManager::PrimitiveType::TRIANGLES, volumeVb, volumeIb, 0, volumeIndexCount)
|
||||
// .priority(7)
|
||||
// .layerMask(0xFF, 1u << SceneManager::LAYERS::OVERLAY)
|
||||
// .culling(false)
|
||||
// .receiveShadows(false)
|
||||
// .castShadows(false)
|
||||
// .build(*_engine, _entities[i]);
|
||||
|
||||
// auto instance = transformManager.getInstance(_entities[i]);
|
||||
// transformManager.setTransform(instance, transform);
|
||||
// transformManager.setParent(instance, transformManager.getInstance(_entities[0]));
|
||||
// }
|
||||
// }
|
||||
|
||||
// RotationGizmo::~RotationGizmo() {
|
||||
// _scene->removeEntities(_entities, 7);
|
||||
|
||||
// for (int i = 0; i < 7; i++) {
|
||||
// _engine->destroy(_entities[i]);
|
||||
// _engine->destroy(_materialInstances[i]);
|
||||
// }
|
||||
// }
|
||||
|
||||
// void RotationGizmo::highlight(Entity entity) {
|
||||
// auto& rm = _engine->getRenderableManager();
|
||||
// auto renderableInstance = rm.getInstance(entity);
|
||||
// auto materialInstance = rm.getMaterialInstanceAt(renderableInstance, 0);
|
||||
|
||||
// math::float4 baseColor;
|
||||
// if (entity == x()) {
|
||||
// baseColor = activeColors[Axis::X];
|
||||
// } else if (entity == y()) {
|
||||
// baseColor = activeColors[Axis::Y];
|
||||
// } else if (entity == z()) {
|
||||
// baseColor = activeColors[Axis::Z];
|
||||
// } else {
|
||||
// baseColor = math::float4{1.0f, 1.0f, 1.0f, 1.0f};
|
||||
// }
|
||||
|
||||
// materialInstance->setParameter("baseColorFactor", baseColor);
|
||||
// }
|
||||
|
||||
// void RotationGizmo::unhighlight() {
|
||||
// auto& rm = _engine->getRenderableManager();
|
||||
|
||||
// for (int i = 0; i < 3; i++) {
|
||||
// auto renderableInstance = rm.getInstance(_entities[i + 1]);
|
||||
// auto materialInstance = rm.getMaterialInstanceAt(renderableInstance, 0);
|
||||
// materialInstance->setParameter("baseColorFactor", inactiveColors[i]);
|
||||
// }
|
||||
// }
|
||||
|
||||
// void RotationGizmo::pick(uint32_t x, uint32_t y, PickCallback callback) {
|
||||
// auto handler = new RotationGizmo::PickCallbackHandler(this, callback);
|
||||
// _view->pick(x, y, [=](filament::View::PickingQueryResult const& result) {
|
||||
// handler->handle(result);
|
||||
// delete handler;
|
||||
// });
|
||||
// }
|
||||
|
||||
// void RotationGizmo::PickCallbackHandler::handle(filament::View::PickingQueryResult const& result) {
|
||||
// auto x = static_cast<int32_t>(result.fragCoords.x);
|
||||
// auto y = static_cast<int32_t>(result.fragCoords.y);
|
||||
|
||||
// for (int i = 0; i < 7; i++) {
|
||||
// if (_gizmo->_entities[i] == result.renderable) {
|
||||
// if (i < 4) {
|
||||
// return;
|
||||
// }
|
||||
// _gizmo->highlight(_gizmo->_entities[i - 4]);
|
||||
// _callback(static_cast<Axis>(i - 4), x, y, _gizmo->_view);
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// _gizmo->unhighlight();
|
||||
// }
|
||||
|
||||
// bool RotationGizmo::isGizmoEntity(Entity e) {
|
||||
// for (int i = 0; i < 7; i++) {
|
||||
// if (e == _entities[i]) {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// void RotationGizmo::setVisibility(bool visible) {
|
||||
// if (visible) {
|
||||
// _scene->addEntities(_entities, 7);
|
||||
// } else {
|
||||
// _scene->removeEntities(_entities, 7);
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user