refactoring

This commit is contained in:
Nick Fisher
2025-03-19 12:27:13 +08:00
parent d5bffd5ad2
commit 627447f8b0
65 changed files with 2304 additions and 3005 deletions

View File

@@ -0,0 +1,2 @@
export 'src/filament_app.dart';
export 'src/engine.dart';

View File

@@ -0,0 +1,267 @@
library;
import 'package:animation_tools_dart/animation_tools_dart.dart';
import 'package:thermion_dart/src/filament/src/layers.dart';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:vector_math/vector_math_64.dart';
import 'entity.dart';
export 'geometry.dart';
export 'gltf.dart';
export 'light_options.dart';
abstract class ThermionAsset {
///
///
///
ThermionEntity get entity;
///
///
///
Future<List<ThermionEntity>> getChildEntities();
///
///
///
Future setMaterialInstanceAt(covariant MaterialInstance instance);
///
/// 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();
///
/// When visible is [true], renders the bounding box.
///
Future setBoundingBoxVisibility(bool visible);
///
///
///
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();
///
///
///
Future setCastShadows(bool castShadows);
///
///
///
Future setReceiveShadows(bool castShadows);
///
/// 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
/// using these layers.
///
Future setVisibilityLayer(ThermionEntity entity, VisibilityLayers layer);
///
/// Schedules the glTF animation at [index] in [asset] to start playing on the next frame.
///
Future playAnimation(ThermionAsset asset, int index,
{bool loop = false,
bool reverse = false,
bool replaceActive = true,
double crossfade = 0.0,
double startOffset = 0.0});
///
/// Schedules the glTF animation at [index] in [entity] to start playing on the next frame.
///
Future playAnimationByName(covariant ThermionAsset asset, String name,
{bool loop = false,
bool reverse = false,
bool replaceActive = true,
double crossfade = 0.0});
///
///
///
Future setGltfAnimationFrame(
covariant ThermionAsset asset, int index, int animationFrame);
///
///
///
Future stopAnimation(covariant ThermionAsset asset, int animationIndex);
///
///
///
Future stopAnimationByName(covariant ThermionAsset asset, String name);
///
/// Set the weights for all morph targets in [entity] to [weights].
/// Note that [weights] must contain values for ALL morph targets, but no exception will be thrown if you don't do so (you'll just get incorrect results).
/// If you only want to set one value, set all others to zero (check [getMorphTargetNames] if you need the get a list of all morph targets).
/// IMPORTANT - this accepts the actual ThermionEntity with the relevant morph targets (unlike [getMorphTargetNames], which uses the parent entity and the child mesh name).
/// Use [getChildEntityByName] if you are setting the weights for a child mesh.
///
Future setMorphTargetWeights(ThermionEntity entity, List<double> weights);
///
/// Gets the names of all morph targets for the child renderable [childEntity] under [entity].
///
Future<List<String>> getMorphTargetNames(
covariant ThermionAsset asset, ThermionEntity childEntity);
///
/// Gets the names of all bones for the armature at [skinIndex] under the specified [entity].
///
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(covariant ThermionAsset asset);
///
/// Returns the length (in seconds) of the animation at the given index.
///
Future<double> getAnimationDuration(
covariant ThermionAsset asset, int animationIndex);
///
/// 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(
covariant ThermionAsset asset, MorphAnimationData animation,
{List<String>? targetMeshNames});
///
/// Clear all current morph animations for [entity].
///
Future clearMorphAnimationData(ThermionEntity entity);
///
/// Resets all bones in the given entity to their rest pose.
/// This should be done before every call to addBoneAnimation.
///
Future resetBones(ThermionAsset asset);
///
/// Enqueues and plays the [animation] for the specified bone(s).
/// By default, frame data is interpreted as being in *parent* bone space;
/// a 45 degree around Y means the bone will rotate 45 degrees around the
/// Y axis of the parent bone *in its current orientation*.
/// (i.e NOT the parent bone's rest position!).
/// Currently, only [Space.ParentBone] and [Space.Model] are supported; if you want
/// to transform to another space, you will need to do so manually.
///
/// [fadeInInSecs]/[fadeOutInSecs]/[maxDelta] are used to cross-fade between
/// the current active glTF animation ("animation1") and the animation you
/// set via this method ("animation2"). The bone orientations will be
/// linearly interpolated between animation1 and animation2; at time 0,
/// the orientation will be 100% animation1, at time [fadeInInSecs], the
/// animation will be ((1 - maxDelta) * animation1) + (maxDelta * animation2).
/// This will be applied in reverse after [fadeOutInSecs].
///
///
Future addBoneAnimation(ThermionAsset asset, BoneAnimationData animation,
{int skinIndex = 0,
double fadeInInSecs = 0.0,
double fadeOutInSecs = 0.0,
double maxDelta = 1.0});
///
/// Gets the entity representing the bone at [boneIndex]/[skinIndex].
/// The returned entity is only intended for use with [getWorldTransform].
///
Future<ThermionEntity> getBone(covariant ThermionAsset asset, int boneIndex,
{int skinIndex = 0});
///
/// Gets the local (relative to parent) transform for [entity].
///
Future<Matrix4> getLocalTransform(ThermionEntity entity);
///
/// Gets the world transform for [entity].
///
Future<Matrix4> getWorldTransform(ThermionEntity entity);
///
/// Gets the inverse bind (pose) matrix for the bone.
/// 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(
covariant ThermionAsset asset, int boneIndex,
{int skinIndex = 0});
///
/// Sets the transform (relative to its parent) for [entity].
///
Future setTransform(ThermionEntity entity, Matrix4 transform);
///
/// Updates the bone matrices for [entity] (which must be the ThermionEntity
/// returned by [loadGlb/loadGltf]).
/// Under the hood, this just calls [updateBoneMatrices] on the Animator
/// instance of the relevant FilamentInstance (which uses the local
/// bone transform and the inverse bind matrix to set the bone matrix).
///
Future updateBoneMatrices(ThermionEntity entity);
///
/// Directly set the bone matrix for the bone at the given index.
/// Don't call this manually unless you know what you're doing.
///
Future setBoneTransform(
ThermionEntity entity, int boneIndex, Matrix4 transform,
{int skinIndex = 0});
///
/// An [entity] will only be animatable after an animation component is attached.
/// Any calls to [playAnimation]/[setBoneAnimation]/[setMorphAnimation] will have no visual effect until [addAnimationComponent] has been called on the instance.
///
Future addAnimationComponent(ThermionEntity entity);
///
/// Removes an animation component from [entity].
///
Future removeAnimationComponent(ThermionEntity entity);
}

View File

@@ -0,0 +1,50 @@
import 'package:thermion_dart/src/filament/src/layers.dart';
import 'package:thermion_dart/thermion_dart.dart';
enum Projection { Perspective, Orthographic }
abstract class Camera {
Future lookAt(Vector3 position, {Vector3? focus, Vector3? up}) async {
focus ??= Vector3.zero();
up ??= Vector3(0, 1, 0);
final viewMatrix = makeViewMatrix(position, focus, up);
viewMatrix.invert();
await setModelMatrix(viewMatrix);
}
///
/// Sets the camera exposure.
///
Future setCameraExposure(
double aperture, double shutterSpeed, double sensitivity);
Future setProjection(Projection projection, double left, double right,
double bottom, double top, double near, double far);
Future setProjectionMatrixWithCulling(
Matrix4 projectionMatrix, double near, double far);
Future setLensProjection(
{double near = kNear,
double far = kFar,
double aspect = 1.0,
double focalLength = kFocalLength});
Future<Matrix4> getViewMatrix();
Future<Matrix4> getModelMatrix();
Future<Matrix4> getProjectionMatrix();
Future<Matrix4> getCullingProjectionMatrix();
Future setModelMatrix(Matrix4 matrix);
ThermionEntity getEntity();
Future setTransform(Matrix4 transform);
Future<double> getNear();
Future<double> getCullingFar();
Future<double> getFocalLength();
Future<double> getFocusDistance();
Future setFocusDistance(double focusDistance);
Future destroy();
}

View File

@@ -0,0 +1,28 @@
enum Backend {
/// !< Automatically selects an appropriate driver for the platform.
DEFAULT(0),
/// !< Selects the OpenGL/ES driver (default on Android)
OPENGL(1),
/// !< Selects the Vulkan driver if the platform supports it (default on Linux/Windows)
VULKAN(2),
/// !< Selects the Metal driver if the platform supports it (default on MacOS/iOS).
METAL(3),
/// !< Selects the no-op driver for testing purposes.
NOOP(4);
final int value;
const Backend(this.value);
static Backend fromValue(int value) => switch (value) {
0 => DEFAULT,
1 => OPENGL,
2 => VULKAN,
3 => METAL,
4 => NOOP,
_ => throw ArgumentError("Unknown value for TBackend: $value"),
};
}

View File

@@ -0,0 +1,2 @@
typedef ThermionEntity = int;
final ThermionEntity FILAMENT_ENTITY_NULL = 0;

View File

@@ -0,0 +1,209 @@
import 'dart:typed_data';
import 'package:thermion_dart/src/filament/src/engine.dart';
import 'package:thermion_dart/thermion_dart.dart';
class FilamentConfig<T, U> {
final Backend backend;
final T? renderCallback;
final U? renderCallbackOwner;
final U resourceLoader;
final U? platform;
final U? driver;
final U? sharedContext;
final String? uberArchivePath;
final int stereoscopicEyeCount;
final bool disableHandleUseAfterFreeCheck;
FilamentConfig(
{required this.backend,
required this.resourceLoader,
this.uberArchivePath,
this.renderCallback,
this.renderCallbackOwner,
this.platform,
this.driver,
this.sharedContext,
this.stereoscopicEyeCount = 1,
this.disableHandleUseAfterFreeCheck = false});
}
abstract class FilamentApp<T> {
static FilamentApp? instance;
final T engine;
final T gltfAssetLoader;
final T gltfResourceLoader;
final T renderer;
final T transformManager;
final T lightManager;
final T renderableManager;
final T ubershaderMaterialProvider;
FilamentApp(
{required this.engine,
required this.gltfAssetLoader,
required this.gltfResourceLoader,
required this.renderer,
required this.transformManager,
required this.lightManager,
required this.renderableManager,
required this.ubershaderMaterialProvider});
///
///
///
Future<SwapChain> createHeadlessSwapChain(int width, int height,
{bool hasStencilBuffer = false});
///
///
///
Future<SwapChain> createSwapChain(T handle, {bool hasStencilBuffer = false});
///
///
///
Future destroySwapChain(SwapChain swapChain);
///
///
///
Future destroy();
///
///
///
Future<RenderTarget> createRenderTarget(int width, int height,
{covariant Texture? color, covariant Texture? depth});
///
///
///
Future<Texture> createTexture(int width, int height,
{int depth = 1,
int levels = 1,
Set<TextureUsage> flags = const {TextureUsage.TEXTURE_USAGE_SAMPLEABLE},
TextureSamplerType textureSamplerType = TextureSamplerType.SAMPLER_2D,
TextureFormat textureFormat = TextureFormat.RGBA16F,
int? importedTextureHandle});
///
///
///
Future<TextureSampler> createTextureSampler(
{TextureMinFilter minFilter = TextureMinFilter.LINEAR,
TextureMagFilter magFilter = TextureMagFilter.LINEAR,
TextureWrapMode wrapS = TextureWrapMode.CLAMP_TO_EDGE,
TextureWrapMode wrapT = TextureWrapMode.CLAMP_TO_EDGE,
TextureWrapMode wrapR = TextureWrapMode.CLAMP_TO_EDGE,
double anisotropy = 0.0,
TextureCompareMode compareMode = TextureCompareMode.NONE,
TextureCompareFunc compareFunc = TextureCompareFunc.LESS_EQUAL});
///
/// Decodes the specified image data.
///
Future<LinearImage> decodeImage(Uint8List data);
///
/// Creates an (empty) imge with the given dimensions.
///
Future<LinearImage> createImage(int width, int height, int channels);
///
///
///
Future<Material> createMaterial(Uint8List data);
///
///
///
Future<MaterialInstance> createUbershaderMaterialInstance({
bool doubleSided = false,
bool unlit = false,
bool hasVertexColors = false,
bool hasBaseColorTexture = false,
bool hasNormalTexture = false,
bool hasOcclusionTexture = false,
bool hasEmissiveTexture = false,
bool useSpecularGlossiness = false,
AlphaMode alphaMode = AlphaMode.OPAQUE,
bool enableDiagnostics = false,
bool hasMetallicRoughnessTexture = false,
int metallicRoughnessUV = -1,
int baseColorUV = -1,
bool hasClearCoatTexture = false,
int clearCoatUV = -1,
bool hasClearCoatRoughnessTexture = false,
int clearCoatRoughnessUV = -1,
bool hasClearCoatNormalTexture = false,
int clearCoatNormalUV = -1,
bool hasClearCoat = false,
bool hasTransmission = false,
bool hasTextureTransforms = false,
int emissiveUV = -1,
int aoUV = -1,
int normalUV = -1,
bool hasTransmissionTexture = false,
int transmissionUV = -1,
bool hasSheenColorTexture = false,
int sheenColorUV = -1,
bool hasSheenRoughnessTexture = false,
int sheenRoughnessUV = -1,
bool hasVolumeThicknessTexture = false,
int volumeThicknessUV = -1,
bool hasSheen = false,
bool hasIOR = false,
bool hasVolume = false,
});
///
///
///
Future<MaterialInstance> createUnlitMaterialInstance();
///
///
///
Future<MaterialInstance> getMaterialInstanceAt(
ThermionEntity entity, int index);
///
///
///
@override
Future<ThermionAsset> createGeometry(Geometry geometry,
{List<MaterialInstance>? materialInstances, bool keepData = false});
///
///
///
Future setRenderable(covariant View view, bool renderable);
///
///
///
Future register(covariant SwapChain swapChain, covariant View view);
///
///
///
Future render();
///
///
///
Future requestFrame();
///
///
///
Future registerRequestFrameHook(Future Function() hook);
///
///
///
Future unregisterRequestFrameHook(Future Function() hook);
}

View File

@@ -0,0 +1,32 @@
import 'dart:typed_data';
import '../../viewer/viewer.dart';
class Geometry {
final Float32List vertices;
final Uint16List indices;
final Float32List normals;
final Float32List uvs;
final PrimitiveType primitiveType;
Geometry(
this.vertices,
List<int> indices, {
Float32List? normals,
Float32List? uvs,
this.primitiveType = PrimitiveType.TRIANGLES,
}) : indices = Uint16List.fromList(indices),
normals = normals ?? Float32List(0),
uvs = uvs ?? Float32List(0) {
assert(this.uvs.length == 0 || this.uvs.length == (vertices.length ~/ 3 * 2), "Expected either zero or ${indices.length * 2} UVs, got ${this.uvs.length}");
}
void scale(double factor) {
for (int i = 0; i < vertices.length; i++) {
vertices[i] = vertices[i] * factor;
}
}
bool get hasNormals => normals.isNotEmpty;
bool get hasUVs => uvs.isNotEmpty;
}

View File

@@ -0,0 +1,28 @@
import 'entity.dart';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:vector_math/vector_math_64.dart';
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();
bool isNonPickable(ThermionEntity entity);
bool isGizmoEntity(ThermionEntity entity);
}

View File

@@ -0,0 +1,6 @@
class GLTF {
final String uri;
final int numInstances;
GLTF(this.uri, this.numInstances);
}

View File

@@ -0,0 +1,18 @@
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);
}

View File

@@ -0,0 +1,7 @@
enum LightType {
SUN, //!< Directional light that also draws a sun's disk in the sky.
DIRECTIONAL, //!< Directional light, emits light in a given direction.
POINT, //!< Point light, emits light from a position, in all directions.
FOCUSED_SPOT, //!< Physically correct spot light.
SPOT,
}

View File

@@ -0,0 +1,98 @@
import 'dart:math';
import 'package:vector_math/vector_math_64.dart' as v;
import 'package:vector_math/vector_math_64.dart';
import 'light.dart';
class IBL {
String? iblPath;
final double iblIntensity;
IBL(this.iblIntensity);
}
class DirectLight {
final LightType type;
final double color;
final double intensity;
final bool castShadows;
late final v.Vector3 position;
late final v.Vector3 direction;
final double falloffRadius;
final double spotLightConeInner;
final double spotLightConeOuter;
final double sunAngularRadius;
final double sunHaloSize;
final double sunHaloFallof;
DirectLight({
required this.type,
required this.color,
required this.intensity,
this.castShadows = false,
required this.direction,
required this.position,
this.falloffRadius = 1.0,
this.spotLightConeInner = pi / 8,
this.spotLightConeOuter = pi / 4,
this.sunAngularRadius = 0.545,
this.sunHaloSize = 10.0,
this.sunHaloFallof = 80.0,
});
DirectLight.point({
double color = 6500,
double intensity = 100000,
bool castShadows = false,
Vector3? position,
double falloffRadius = 1.0,
}) : this(
type: LightType.POINT,
color: color,
intensity: intensity,
castShadows: castShadows,
position: position ?? Vector3(0, 1, 0),
direction: Vector3.zero(),
falloffRadius: falloffRadius,
);
DirectLight.sun({
double color = 6500,
double intensity = 100000,
bool castShadows = true,
Vector3? direction,
double sunAngularRadius = 0.545,
double sunHaloSize = 10.0,
double sunHaloFalloff = 80.0,
}) : this(
type: LightType.DIRECTIONAL,
color: color,
intensity: intensity,
castShadows: castShadows,
position: Vector3(0, 0, 0),
direction: direction ?? Vector3(0, -1, 0),
sunAngularRadius: sunAngularRadius,
sunHaloSize: sunHaloSize,
sunHaloFallof: sunHaloFalloff,
);
DirectLight.spot({
double color = 6500,
double intensity = 100000,
bool castShadows = true,
Vector3? position,
Vector3? direction,
double falloffRadius = 1.0,
double spotLightConeInner = pi / 8,
double spotLightConeOuter = pi / 4,
}) : this(
type: LightType.SPOT,
color: color,
intensity: intensity,
castShadows: castShadows,
position: position ?? Vector3(0, 1, 0),
direction: direction ?? Vector3(0, -1, 0),
falloffRadius: falloffRadius,
spotLightConeInner: spotLightConeInner,
spotLightConeOuter: spotLightConeOuter,
);
}

View File

@@ -0,0 +1,4 @@
// see filament Manipulator.h for more details
@Deprecated(
"This is used the native pointer manipulator Prefer InputHandler instead")
enum ManipulatorMode { ORBIT, MAP, FREE_FLIGHT }

View File

@@ -0,0 +1,150 @@
import 'dart:typed_data';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:vector_math/vector_math_64.dart';
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;
}
/// 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 }
enum TransparencyMode {
//! the transparent object is drawn honoring the raster state
DEFAULT,
/**
* the transparent object is first drawn in the depth buffer,
* then in the color buffer, honoring the culling mode, but ignoring the depth test function
*/
TWO_PASSES_ONE_SIDE,
/**
* the transparent object is drawn twice in the color buffer,
* first with back faces only, then with front faces; the culling
* mode is ignored. Can be combined with two-sided lighting
*/
TWO_PASSES_TWO_SIDES
}
abstract class Material {
Future<MaterialInstance> createInstance();
Future<bool> hasParameter(String propertyName);
Future destroy();
}
abstract class MaterialInstance {
Future<bool> isStencilWriteEnabled();
Future setDepthWriteEnabled(bool enabled);
Future setDepthFunc(SamplerCompareFunction depthFunc);
Future setDepthCullingEnabled(bool enabled);
Future setParameterFloat(String name, double x);
Future setParameterFloat2(String name, double x, double y);
Future setParameterFloat3(String name, double x, double y, double z);
Future setParameterFloat3Array(String name, List<Vector3> data);
Future setParameterFloat4(
String name, double x, double y, double z, double w);
Future setParameterInt(String name, int value);
Future setParameterBool(String name, bool value);
Future setParameterTexture(
String name, covariant Texture texture, covariant TextureSampler sampler);
/// 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);
Future setTransparencyMode(TransparencyMode mode);
Future destroy();
}

View File

@@ -0,0 +1,17 @@
import '../../viewer/viewer.dart';
/// The result of a picking operation (see [ThermionViewer.pick] for more details).
/// [x] and [y] refer to the original screen coordinates used to call [pick]; this should
/// match the values of [fragX] and [fragY]. [fragZ] is the depth value in screen coordinates,
/// [depth] is the value in the depth buffer (i.e. fragZ = 1.0 - depth).
///
typedef FilamentPickResult = ({
ThermionEntity entity,
int x,
int y,
double depth,
double fragX,
double fragY,
double fragZ
});
typedef PickResult = FilamentPickResult;

View File

@@ -0,0 +1,10 @@
// copied from filament/backened/DriverEnums.h
enum PrimitiveType {
// don't change the enums values (made to match GL)
POINTS, //!< points
LINES, //!< lines
UNUSED1,
LINE_STRIP, //!< line strip
TRIANGLES, //!< triangles
TRIANGLE_STRIP, //!< triangle strip
}

View File

@@ -0,0 +1,7 @@
import 'package:thermion_dart/thermion_dart.dart';
abstract class RenderTarget {
Future<Texture> getColorTexture();
Future<Texture> getDepthTexture();
Future destroy();
}

View File

@@ -0,0 +1,6 @@
import 'package:thermion_dart/thermion_dart.dart';
abstract class Scene {
Future add(covariant ThermionAsset asset);
Future remove(covariant ThermionAsset asset);
}

View File

@@ -0,0 +1,6 @@
enum ShadowType {
PCF, //!< percentage-closer filtered shadows (default)
VSM, //!< variance shadows
DPCF, //!< PCF with contact hardening simulation
PCSS, //!< PCF with soft shadows and contact hardening
}

View File

@@ -0,0 +1,18 @@
library shared_types;
export 'swap_chain.dart';
export 'view.dart';
export 'render_target.dart';
export 'camera.dart';
export 'material.dart';
export 'texture.dart';
export 'asset.dart';
export 'entity.dart';
export 'gizmo.dart';
export 'light.dart';
export 'shadow.dart';
export 'manipulator.dart';
export 'pick_result.dart';
export 'primitive.dart';
export 'texture_details.dart';
export 'tone_mapper.dart';

View File

@@ -0,0 +1,3 @@
abstract class SwapChain {
}

View File

@@ -0,0 +1,455 @@
import 'dart:typed_data';
/// Defines the type of sampler to use with a texture
enum TextureSamplerType {
SAMPLER_2D,
SAMPLER_2D_ARRAY,
SAMPLER_CUBEMAP,
SAMPLER_EXTERNAL,
SAMPLER_3D,
SAMPLER_CUBEMAP_ARRAY
}
/// Defines internal texture formats
enum TextureFormat {
// 8-bits per element
R8, // R 8-bits
R8_SNORM, // R 8-bits (signed normalized)
R8UI, // R 8-bits (unsigned integer)
R8I, // R 8-bits (signed integer)
STENCIL8, // Stencil 8-bits
// 16-bits per element
R16F, // R 16-bits (float)
R16UI, // R 16-bits (unsigned integer)
R16I, // R 16-bits (signed integer)
RG8, // RG 8-bits each
RG8_SNORM, // RG 8-bits each (signed normalized)
RG8UI, // RG 8-bits each (unsigned integer)
RG8I, // RG 8-bits each (signed integer)
RGB565, // RGB 5-6-5 bits
RGB9_E5, // RGB9_E5 format
RGB5_A1, // RGB 5 bits each, A 1 bit
RGBA4, // RGBA 4 bits each
DEPTH16, // Depth 16-bits
// 24-bits per element
RGB8, // RGB 8-bits each
SRGB8, // RGB 8-bits each (sRGB color space)
RGB8_SNORM, // RGB 8-bits each (signed normalized)
RGB8UI, // RGB 8-bits each (unsigned integer)
RGB8I, // RGB 8-bits each (signed integer)
DEPTH24, // Depth 24-bits
// 32-bits per element
R32F, // R 32-bits (float)
R32UI, // R 32-bits (unsigned integer)
R32I, // R 32-bits (signed integer)
RG16F, // RG 16-bits each (float)
RG16UI, // RG 16-bits each (unsigned integer)
RG16I, // RG 16-bits each (signed integer)
R11F_G11F_B10F, // R11F_G11F_B10F format
RGBA8, // RGBA 8-bits each
SRGB8_A8, // RGB 8-bits each (sRGB), A 8-bits
RGBA8_SNORM, // RGBA 8-bits each (signed normalized)
UNUSED, // used to be rgbm
RGB10_A2, // RGB 10-bits each, A 2-bits
RGBA8UI, // RGBA 8-bits each (unsigned integer)
RGBA8I, // RGBA 8-bits each (signed integer)
DEPTH32F, // Depth 32-bits (float)
DEPTH24_STENCIL8, // Depth 24-bits, Stencil 8-bits
DEPTH32F_STENCIL8, // Depth 32-bits (float), Stencil 8-bits
// 48-bits per element
RGB16F, // RGB 16-bits each (float)
RGB16UI, // RGB 16-bits each (unsigned integer)
RGB16I, // RGB 16-bits each (signed integer)
// 64-bits per element
RG32F, // RG 32-bits each (float)
RG32UI, // RG 32-bits each (unsigned integer)
RG32I, // RG 32-bits each (signed integer)
RGBA16F, // RGBA 16-bits each (float)
RGBA16UI, // RGBA 16-bits each (unsigned integer)
RGBA16I, // RGBA 16-bits each (signed integer)
// 96-bits per element
RGB32F, // RGB 32-bits each (float)
RGB32UI, // RGB 32-bits each (unsigned integer)
RGB32I, // RGB 32-bits each (signed integer)
// 128-bits per element
RGBA32F, // RGBA 32-bits each (float)
RGBA32UI, // RGBA 32-bits each (unsigned integer)
RGBA32I, // RGBA 32-bits each (signed integer)
// Compressed formats
EAC_R11, // EAC R11 (compressed)
EAC_R11_SIGNED, // EAC R11 (compressed, signed)
EAC_RG11, // EAC RG11 (compressed)
EAC_RG11_SIGNED, // EAC RG11 (compressed, signed)
ETC2_RGB8, // ETC2 RGB8 (compressed)
ETC2_SRGB8, // ETC2 RGB8 (compressed, sRGB)
ETC2_RGB8_A1, // ETC2 RGB8A1 (compressed)
ETC2_SRGB8_A1, // ETC2 RGB8A1 (compressed, sRGB)
ETC2_EAC_RGBA8, // ETC2 RGBA8 (compressed)
ETC2_EAC_SRGBA8, // ETC2 RGBA8 (compressed, sRGB)
// DXT formats
DXT1_RGB, // DXT1 RGB (compressed)
DXT1_RGBA, // DXT1 RGBA (compressed)
DXT3_RGBA, // DXT3 RGBA (compressed)
DXT5_RGBA, // DXT5 RGBA (compressed)
DXT1_SRGB, // DXT1 sRGB (compressed)
DXT1_SRGBA, // DXT1 sRGBA (compressed)
DXT3_SRGBA, // DXT3 sRGBA (compressed)
DXT5_SRGBA, // DXT5 sRGBA (compressed)
// ASTC formats
RGBA_ASTC_4x4, // ASTC 4x4 RGBA (compressed)
RGBA_ASTC_5x4, // ASTC 5x4 RGBA (compressed)
RGBA_ASTC_5x5, // ASTC 5x5 RGBA (compressed)
RGBA_ASTC_6x5, // ASTC 6x5 RGBA (compressed)
RGBA_ASTC_6x6, // ASTC 6x6 RGBA (compressed)
RGBA_ASTC_8x5, // ASTC 8x5 RGBA (compressed)
RGBA_ASTC_8x6, // ASTC 8x6 RGBA (compressed)
RGBA_ASTC_8x8, // ASTC 8x8 RGBA (compressed)
RGBA_ASTC_10x5, // ASTC 10x5 RGBA (compressed)
RGBA_ASTC_10x6, // ASTC 10x6 RGBA (compressed)
RGBA_ASTC_10x8, // ASTC 10x8 RGBA (compressed)
RGBA_ASTC_10x10, // ASTC 10x10 RGBA (compressed)
RGBA_ASTC_12x10, // ASTC 12x10 RGBA (compressed)
RGBA_ASTC_12x12, // ASTC 12x12 RGBA (compressed)
SRGB8_ALPHA8_ASTC_4x4, // ASTC 4x4 sRGBA (compressed)
SRGB8_ALPHA8_ASTC_5x4, // ASTC 5x4 sRGBA (compressed)
SRGB8_ALPHA8_ASTC_5x5, // ASTC 5x5 sRGBA (compressed)
SRGB8_ALPHA8_ASTC_6x5, // ASTC 6x5 sRGBA (compressed)
SRGB8_ALPHA8_ASTC_6x6, // ASTC 6x6 sRGBA (compressed)
SRGB8_ALPHA8_ASTC_8x5, // ASTC 8x5 sRGBA (compressed)
SRGB8_ALPHA8_ASTC_8x6, // ASTC 8x6 sRGBA (compressed)
SRGB8_ALPHA8_ASTC_8x8, // ASTC 8x8 sRGBA (compressed)
SRGB8_ALPHA8_ASTC_10x5, // ASTC 10x5 sRGBA (compressed)
SRGB8_ALPHA8_ASTC_10x6, // ASTC 10x6 sRGBA (compressed)
SRGB8_ALPHA8_ASTC_10x8, // ASTC 10x8 sRGBA (compressed)
SRGB8_ALPHA8_ASTC_10x10, // ASTC 10x10 sRGBA (compressed)
SRGB8_ALPHA8_ASTC_12x10, // ASTC 12x10 sRGBA (compressed)
SRGB8_ALPHA8_ASTC_12x12, // ASTC 12x12 sRGBA (compressed)
// RGTC formats
RED_RGTC1, // BC4 unsigned
SIGNED_RED_RGTC1, // BC4 signed
RED_GREEN_RGTC2, // BC5 unsigned
SIGNED_RED_GREEN_RGTC2, // BC5 signed
// BPTC formats
RGB_BPTC_SIGNED_FLOAT, // BC6H signed
RGB_BPTC_UNSIGNED_FLOAT, // BC6H unsigned
RGBA_BPTC_UNORM, // BC7
SRGB_ALPHA_BPTC_UNORM, // BC7 sRGB
}
enum TextureUsage {
TEXTURE_USAGE_NONE(0),
/// !< Texture can be used as a color attachment
TEXTURE_USAGE_COLOR_ATTACHMENT(1),
/// !< Texture can be used as a depth attachment
TEXTURE_USAGE_DEPTH_ATTACHMENT(2),
/// !< Texture can be used as a stencil attachment
TEXTURE_USAGE_STENCIL_ATTACHMENT(4),
/// !< Data can be uploaded into this texture (default)
TEXTURE_USAGE_UPLOADABLE(8),
/// !< Texture can be sampled (default)
TEXTURE_USAGE_SAMPLEABLE(16),
/// !< Texture can be used as a subpass input
TEXTURE_USAGE_SUBPASS_INPUT(32),
/// !< Texture can be used the source of a blit()
TEXTURE_USAGE_BLIT_SRC(64),
/// !< Texture can be used the destination of a blit()
TEXTURE_USAGE_BLIT_DST(128),
/// !< Texture can be used the destination of a blit()
TEXTURE_USAGE_PROTECTED(256),
/// !< Default texture usage
TEXTURE_USAGE_DEFAULT(24);
final int value;
const TextureUsage(this.value);
static TextureUsage fromValue(int value) => switch (value) {
0 => TEXTURE_USAGE_NONE,
1 => TEXTURE_USAGE_COLOR_ATTACHMENT,
2 => TEXTURE_USAGE_DEPTH_ATTACHMENT,
4 => TEXTURE_USAGE_STENCIL_ATTACHMENT,
8 => TEXTURE_USAGE_UPLOADABLE,
16 => TEXTURE_USAGE_SAMPLEABLE,
32 => TEXTURE_USAGE_SUBPASS_INPUT,
64 => TEXTURE_USAGE_BLIT_SRC,
128 => TEXTURE_USAGE_BLIT_DST,
256 => TEXTURE_USAGE_PROTECTED,
24 => TEXTURE_USAGE_DEFAULT,
_ => throw ArgumentError("Unknown value for TTextureUsage: $value"),
};
}
/// Defines texture wrapping modes for texture coordinates
enum TextureWrapMode {
/// Clamps texture coordinates to edge, extending edge pixels
CLAMP_TO_EDGE,
/// Repeats the texture (tiles)
REPEAT,
/// Mirrors the texture at each repeat
MIRRORED_REPEAT
}
/// Defines texture minification filter types
enum TextureMinFilter {
/// Nearest neighbor sampling (pixelated look)
NEAREST,
/// Linear interpolation between texels
LINEAR,
/// Nearest neighbor filtering with nearest mipmap
NEAREST_MIPMAP_NEAREST,
/// Linear filtering with nearest mipmap
LINEAR_MIPMAP_NEAREST,
/// Nearest filtering with linear mipmap interpolation
NEAREST_MIPMAP_LINEAR,
/// Linear filtering with linear mipmap interpolation (best quality)
LINEAR_MIPMAP_LINEAR
}
/// Defines texture magnification filter types
enum TextureMagFilter {
/// Nearest neighbor sampling (pixelated look)
NEAREST,
/// Linear interpolation between texels
LINEAR
}
/// Defines texture comparison modes
enum TextureCompareMode {
/// No comparison is performed
NONE,
/// Compare texture values to reference value
COMPARE_TO_TEXTURE
}
/// Defines texture comparison functions
enum TextureCompareFunc {
/// Less than or equal
LESS_EQUAL,
/// Greater than or equal
GREATER_EQUAL,
/// Less than
LESS,
/// Greater than
GREATER,
/// Equal
EQUAL,
/// Not equal
NOT_EQUAL,
/// Always passes
ALWAYS,
/// Never passes
NEVER
}
/// Defines swizzle operations for texture components
enum TextureSwizzle {
/// Use the component as is
CHANNEL_0,
/// Use the red channel
CHANNEL_R,
/// Use the green channel
CHANNEL_G,
/// Use the blue channel
CHANNEL_B,
/// Use the alpha channel
CHANNEL_A,
/// Use value 0
ZERO,
/// Use value 1
ONE
}
/// Defines the texture sampler configuration
abstract class TextureSampler {
/// Disposes the sampler resources
Future dispose();
}
/// Defines a texture object
abstract class Texture {
/// Returns the width of the texture at the specified mipmap level
Future<int> getWidth([int level = 0]);
/// Returns the height of the texture at the specified mipmap level
Future<int> getHeight([int level = 0]);
/// Returns the depth of the texture at the specified mipmap level (for 3D textures)
Future<int> getDepth([int level = 0]);
/// Returns the number of mipmap levels this texture has
Future<int> getLevels();
/// Returns the sampler type of this texture
Future<TextureSamplerType> getTarget();
/// Returns the internal format of this texture
Future<TextureFormat> getFormat();
Future setLinearImage(
covariant LinearImage image, PixelDataFormat format, PixelDataType type);
/// Sets the image data for a 2D texture or a texture level
Future setImage(int level, Uint8List buffer, int width, int height,
int channels, PixelDataFormat format, PixelDataType type);
/// Sets the image data for a region of a 2D texture
Future setSubImage(int level, int xOffset, int yOffset, int width, int height,
Uint8List buffer, PixelDataFormat format, PixelDataType type);
/// Sets the image data for a 3D texture or cubemap
Future setImage3D(
int level,
int xOffset,
int yOffset,
int zOffset,
int width,
int height,
int channels,
int depth,
Uint8List buffer,
PixelDataFormat format,
PixelDataType type);
/// Sets an external image (like a video or camera frame) as the texture source
Future setExternalImage(dynamic externalImage);
/// Generates mipmaps automatically for the texture
Future generateMipmaps();
/// Disposes the texture resources
Future dispose();
}
enum PixelDataFormat {
R,
/// One Red channel, float
R_INTEGER,
/// One Red channel, integer
RG,
/// Two Red and Green channels, float
RG_INTEGER,
/// Two Red and Green channels, integer
RGB,
/// Three Red, Green and Blue channels, float
RGB_INTEGER,
/// Three Red, Green and Blue channels, integer
RGBA,
/// Four Red, Green, Blue and Alpha channels, float
RGBA_INTEGER,
/// Four Red, Green, Blue and Alpha channels, integer
UNUSED,
/// Used to be rgbm
DEPTH_COMPONENT,
/// Depth, 16-bit or 24-bits usually
DEPTH_STENCIL,
/// Two Depth (24-bits) + Stencil (8-bits) channels
ALPHA
/// One Alpha channel, float
}
/// Pixel Data Type
enum PixelDataType {
UBYTE,
/// Unsigned byte
BYTE,
/// Signed byte
USHORT,
/// Unsigned short (16-bit)
SHORT,
/// Signed short (16-bit)
UINT,
/// Unsigned int (32-bit)
INT,
/// Signed int (32-bit)
HALF,
/// Half-float (16-bit float)
FLOAT,
/// Float (32-bits float)
COMPRESSED,
/// Compressed pixels, see CompressedPixelDataType
UINT_10F_11F_11F_REV,
/// Three low precision floating-point numbers
USHORT_565,
/// Unsigned int (16-bit), encodes 3 RGB channels
UINT_2_10_10_10_REV,
/// Unsigned normalized 10 bits RGB, 2 bits alpha
}
@deprecated
typedef ThermionTexture = Texture;
abstract class LinearImage {
Future destroy();
Future<Float32List> getData();
Future<int> getWidth();
Future<int> getHeight();
Future<int> getChannels();
}

View File

@@ -0,0 +1,14 @@
///
/// This represents the backing "surface" that we render into.
/// "Texture" here is a misnomer as it is only a render target texture on certain platforms.
///
class TextureDetails {
final int textureId;
// both width and height are in physical, not logical pixels
final int width;
final int height;
TextureDetails(
{required this.textureId, required this.width, required this.height});
}

View File

@@ -0,0 +1 @@
enum ToneMapper { ACES, FILMIC, LINEAR }

View File

@@ -0,0 +1,38 @@
import 'package:thermion_dart/src/filament/src/layers.dart';
import 'package:thermion_dart/thermion_dart.dart';
///
/// The viewport currently attached to a [View].
///
/// The dimensions here are guaranteed to be in physical pixels.
///
class Viewport {
final int left;
final int bottom;
final int width;
final int height;
Viewport(this.left, this.bottom, this.width, this.height);
}
enum QualityLevel { LOW, MEDIUM, HIGH, ULTRA }
abstract class View {
Future<Viewport> getViewport();
Future setViewport(int width, int height);
Future<RenderTarget?> getRenderTarget();
Future setRenderTarget(covariant RenderTarget? renderTarget);
Future setCamera(covariant Camera camera);
Future<Camera> getCamera();
Future setPostProcessing(bool enabled);
Future setAntiAliasing(bool msaa, bool fxaa, bool taa);
Future setFrustumCullingEnabled(bool enabled);
Future setToneMapper(ToneMapper mapper);
Future setStencilBufferEnabled(bool enabled);
Future<bool> isStencilBufferEnabled();
Future setDithering(bool enabled);
Future<bool> isDitheringEnabled();
Future setBloom(bool enabled, double strength);
Future setRenderQuality(QualityLevel quality);
Future setLayerVisibility(VisibilityLayers layer, bool visible);
}