more refactoring

This commit is contained in:
Nick Fisher
2025-03-18 18:06:17 +08:00
parent 77fe40848b
commit 951f5daa2d
54 changed files with 19065 additions and 16751 deletions
+309 -203
View File
@@ -32,7 +32,8 @@ class GeometryHelper {
verticesList.addAll([x, y, z]); verticesList.addAll([x, y, z]);
normalsList.addAll([x, y, z]); normalsList.addAll([x, y, z]);
uvsList.addAll([longNumber / longitudeBands, latNumber / latitudeBands]); uvsList
.addAll([longNumber / longitudeBands, latNumber / latitudeBands]);
} }
} }
@@ -41,7 +42,8 @@ class GeometryHelper {
int first = (latNumber * (longitudeBands + 1)) + longNumber; int first = (latNumber * (longitudeBands + 1)) + longNumber;
int second = first + longitudeBands + 1; int second = first + longitudeBands + 1;
indices.addAll([first, second, first + 1, second, second + 1, first + 1]); indices
.addAll([first, second, first + 1, second, second + 1, first + 1]);
} }
} }
@@ -52,139 +54,184 @@ class GeometryHelper {
return Geometry(vertices, indices, normals: _normals, uvs: _uvs); return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
} }
static Geometry cube({bool normals = true, bool uvs = true}) { static Geometry cube({bool normals = true, bool uvs = true}) {
final vertices = Float32List.fromList([ final vertices = Float32List.fromList([
// Front face // Front face
-1, -1, 1, -1, -1, 1, // 0
1, -1, 1, 1, -1, 1, // 1
1, 1, 1, 1, 1, 1, // 2
-1, 1, 1, -1, 1, 1, // 3
// Back face // Back face
-1, -1, -1, -1, -1, -1, // 4
-1, 1, -1, 1, -1, -1, // 5
1, 1, -1, 1, 1, -1, // 6
1, -1, -1, -1, 1, -1, // 7
// Top face // Top face
-1, 1, -1, -1, 1, 1, // 3 (8)
-1, 1, 1, 1, 1, 1, //2 (9)
1, 1, 1, 1, 1, -1, //6 (10)
1, 1, -1, -1, 1, -1, // 7 (11)
// Bottom face // Bottom
-1, -1, -1, -1, -1, -1, // 4 (12)
1, -1, -1, 1, -1, -1, // 5 (13)
1, -1, 1, 1, -1, 1, // 1 (14)
-1, -1, 1, -1, -1, 1, // 0 (15)
// Right face // Right
1, -1, -1, 1, -1, 1, // 1 (16)
1, 1, -1, 1, -1, -1, // 5 (17)
1, 1, 1, 1, 1, -1, // 6 (18)
1, -1, 1, 1, 1, 1, // 2 (19)
// Left face // Left
-1, -1, -1, -1, -1, -1, // 4 (20)
-1, -1, 1, -1, -1, 1, // 0 (21)
-1, 1, 1, -1, 1, 1, // 3 (22)
-1, 1, -1, -1, 1, -1 // 7 (23)
]); ]);
final _normals = normals ? Float32List.fromList([ final _normals = normals
// Front face ? Float32List.fromList([
0, 0, 1, 0,
0, 0, 1, 0,
0, 0, 1, 1,
0, 0, 1, 0,
0,
1,
0,
0,
1,
0,
0,
1,
0,
0,
-1,
0,
0,
-1,
0,
0,
-1,
0,
0,
-1,
0,
1,
0,
0,
1,
0,
0,
1,
0,
0,
1,
0,
0,
-1,
0,
0,
-1,
0,
0,
-1,
0,
0,
-1,
0,
1,
0,
0,
1,
0,
0,
1,
0,
0,
1,
0,
0,
-1,
0,
0,
-1,
0,
0,
-1,
0,
0,
-1,
0,
0,
])
: null;
// Back face final _uvs = uvs
0, 0, -1, ? Float32List.fromList([
0, 0, -1, // front
0, 0, -1, 1 / 3, 3 / 4, // 0
0, 0, -1, 2 / 3, 3 / 4, // 1
2 / 3, 1, // 2
1 / 3, 1, // 3
// Top face // back
0, 1, 0, 1 / 3, 1 / 4, // 4
0, 1, 0, 2 / 3, 1 / 4, // 5
0, 1, 0, 2 / 3, 1 / 2, // 6
0, 1, 0, 1 / 3, 1 / 2, // 7
// Bottom face // top
0, -1, 0, 2 / 3, 1 / 2, // 8
0, -1, 0, 1, 1 / 2, // 9
0, -1, 0, 1, 3 / 4, // 10
0, -1, 0, 2 / 3, 3 / 4, // 11
// Right face // bottom
1, 0, 0, 0, 1 / 2, // 12
1, 0, 0, 1 / 3, 1 / 2, // 13
1, 0, 0, 1 / 3, 3 / 4, // 14
1, 0, 0, 0, 3 / 4, // 15
// Left face // right
-1, 0, 0, 1 / 3, 1 / 2, // 16
-1, 0, 0, 2 / 3, 1 / 2, // 17
-1, 0, 0, 2 / 3, 3 / 4, // 18
-1, 0, 0, 1 / 3, 3 / 4, // 19
]) : null;
final _uvs = uvs ? Float32List.fromList([ // left
// Front face 1 / 3, 0, // 20
1/3, 1/3, 2 / 3, 0, // 21
2/3, 1/3, 2 / 3, 1 / 4, // 22
2/3, 2/3, 1 / 3, 1 / 4 // 23
1/3, 2/3, ])
: null;
// Back face
2/3, 2/3,
2/3, 1,
1, 1,
1, 2/3,
// Top face
1/3, 0,
1/3, 1/3,
2/3, 1/3,
2/3, 0,
// Bottom face
1/3, 2/3,
2/3, 2/3,
2/3, 1,
1/3, 1,
// Right face
2/3, 1/3,
2/3, 2/3,
1, 2/3,
1, 1/3,
// Left face
0, 1/3,
1/3, 1/3,
1/3, 2/3,
0, 2/3,
]) : null;
final indices = [ final indices = [
// Front face // Front face
0, 1, 2, 0, 2, 3, 0, 1, 2, 0, 2, 3,
// Back face // Back face
4, 5, 6, 4, 6, 7, 5, 4, 7, 5, 7, 6,
// Top face // Top face
8, 9, 10, 8, 10, 11, 8, 9, 10, 8, 10, 11, // 3,2,6,3,6,7, //
// Bottom face // Bottom face
12, 13, 14, 12, 14, 15, 12, 13, 14, 12, 14, 15, // 4,5,1,4,1,0,
// Right face // Right face
16, 17, 18, 16, 18, 19, 16, 17, 18, 16, 18, 19, //1,5,6,1,6,2,
// Left face // Left face
20, 21, 22, 20, 22, 23 20, 21, 22, 20, 22, 23 // 4,0,3,4,3,7
]; ];
return Geometry(vertices, indices, normals: _normals, uvs: _uvs); return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
} }
static Geometry cylinder({double radius = 1.0, double length = 1.0, bool normals = true, bool uvs = true }) { static Geometry cylinder(
{double radius = 1.0,
double length = 1.0,
bool normals = true,
bool uvs = true}) {
int segments = 32; int segments = 32;
List<double> verticesList = []; List<double> verticesList = [];
List<double> normalsList = []; List<double> normalsList = [];
@@ -251,7 +298,11 @@ static Geometry cube({bool normals = true, bool uvs = true}) {
return Geometry(vertices, indices, normals: _normals, uvs: _uvs); return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
} }
static Geometry conic({double radius = 1.0, double length = 1.0, bool normals = true, bool uvs = true}) { static Geometry conic(
{double radius = 1.0,
double length = 1.0,
bool normals = true,
bool uvs = true}) {
int segments = 32; int segments = 32;
List<double> verticesList = []; List<double> verticesList = [];
List<double> normalsList = []; List<double> normalsList = [];
@@ -369,24 +420,47 @@ static Geometry conic({double radius = 1.0, double length = 1.0, bool normals =
Float32List? _uvs = uvs ? Float32List.fromList(uvsList) : null; Float32List? _uvs = uvs ? Float32List.fromList(uvsList) : null;
return Geometry(vertices, indices, normals: _normals, uvs: _uvs); return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
} }
static Geometry plane({double width = 1.0, double height = 1.0, bool normals = true, bool uvs = true}) { static Geometry plane(
{double width = 1.0,
double height = 1.0,
bool normals = true,
bool uvs = true}) {
Float32List vertices = Float32List.fromList([ Float32List vertices = Float32List.fromList([
-width / 2, 0, -height / 2, -width / 2,
width / 2, 0, -height / 2, 0,
width / 2, 0, height / 2, -height / 2,
-width / 2, 0, height / 2, width / 2,
0,
-height / 2,
width / 2,
0,
height / 2,
-width / 2,
0,
height / 2,
]); ]);
Float32List? _normals = normals ? Float32List.fromList([ Float32List? _normals = normals
0, 1, 0, ? Float32List.fromList([
0, 1, 0, 0,
0, 1, 0, 1,
0, 1, 0, 0,
]) : null; 0,
1,
0,
0,
1,
0,
0,
1,
0,
])
: null;
Float32List? _uvs = uvs ? Float32List.fromList([ Float32List? _uvs =
uvs ? Float32List.fromList([
0, 0, 0, 0,
1, 0, 1, 0,
1, 1, 1, 1,
@@ -394,8 +468,12 @@ static Geometry conic({double radius = 1.0, double length = 1.0, bool normals =
]) : null; ]) : null;
List<int> indices = [ List<int> indices = [
0, 2, 1, 0,
0, 3, 2, 1,
2,
0,
2,
3,
]; ];
return Geometry(vertices, indices, normals: _normals, uvs: _uvs); return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
@@ -409,7 +487,7 @@ static Geometry conic({double radius = 1.0, double length = 1.0, bool normals =
double fov = pi / 3, double fov = pi / 3,
bool normals = true, bool normals = true,
bool uvs = true, bool uvs = true,
}) { }) {
List<double> verticesList = []; List<double> verticesList = [];
List<double> normalsList = []; List<double> normalsList = [];
List<double> uvsList = []; List<double> uvsList = [];
@@ -435,8 +513,10 @@ static Geometry conic({double radius = 1.0, double length = 1.0, bool normals =
double z = sphereRadius * sinPhi * sinTheta; double z = sphereRadius * sinPhi * sinTheta;
verticesList.addAll([x, y, z]); verticesList.addAll([x, y, z]);
normalsList.addAll([x / sphereRadius, y / sphereRadius, z / sphereRadius]); normalsList
uvsList.addAll([longNumber / longitudeBands, latNumber / latitudeBands]); .addAll([x / sphereRadius, y / sphereRadius, z / sphereRadius]);
uvsList
.addAll([longNumber / longitudeBands, latNumber / latitudeBands]);
} }
} }
@@ -477,19 +557,19 @@ static Geometry conic({double radius = 1.0, double length = 1.0, bool normals =
// Add near rectangle vertices (negative z) // Add near rectangle vertices (negative z)
verticesList.addAll([ verticesList.addAll([
-nearWidth/2, -nearHeight/2, -frustumNear, // Bottom-left -nearWidth / 2, -nearHeight / 2, -frustumNear, // Bottom-left
nearWidth/2, -nearHeight/2, -frustumNear, // Bottom-right nearWidth / 2, -nearHeight / 2, -frustumNear, // Bottom-right
nearWidth/2, nearHeight/2, -frustumNear, // Top-right nearWidth / 2, nearHeight / 2, -frustumNear, // Top-right
-nearWidth/2, nearHeight/2, -frustumNear, // Top-left -nearWidth / 2, nearHeight / 2, -frustumNear, // Top-left
]); ]);
// Add far rectangle vertices (negative z) // Add far rectangle vertices (negative z)
int farBaseIndex = verticesList.length ~/ 3; int farBaseIndex = verticesList.length ~/ 3;
verticesList.addAll([ verticesList.addAll([
-farWidth/2, -farHeight/2, -frustumFar, // Bottom-left -farWidth / 2, -farHeight / 2, -frustumFar, // Bottom-left
farWidth/2, -farHeight/2, -frustumFar, // Bottom-right farWidth / 2, -farHeight / 2, -frustumFar, // Bottom-right
farWidth/2, farHeight/2, -frustumFar, // Top-right farWidth / 2, farHeight / 2, -frustumFar, // Top-right
-farWidth/2, farHeight/2, -frustumFar, // Top-left -farWidth / 2, farHeight / 2, -frustumFar, // Top-left
]); ]);
// Add normals and UVs for frustum vertices // Add normals and UVs for frustum vertices
@@ -534,16 +614,12 @@ static Geometry conic({double radius = 1.0, double length = 1.0, bool normals =
Float32List? _normals = normals ? Float32List.fromList(normalsList) : null; Float32List? _normals = normals ? Float32List.fromList(normalsList) : null;
Float32List? _uvs = uvs ? Float32List.fromList(uvsList) : null; Float32List? _uvs = uvs ? Float32List.fromList(uvsList) : null;
return Geometry( return Geometry(vertices, indices,
vertices, normals: _normals, uvs: _uvs, primitiveType: PrimitiveType.LINES);
indices, }
normals: _normals,
uvs: _uvs,
primitiveType: PrimitiveType.LINES
);
}
static Geometry fromAabb3(Aabb3 aabb, {bool normals = true, bool uvs = true}) { static Geometry fromAabb3(Aabb3 aabb,
{bool normals = true, bool uvs = true}) {
// Get the center and half extents from the AABB // Get the center and half extents from the AABB
final center = aabb.center; final center = aabb.center;
final halfExtents = Vector3.zero(); final halfExtents = Vector3.zero();
@@ -552,43 +628,68 @@ static Geometry fromAabb3(Aabb3 aabb, {bool normals = true, bool uvs = true}) {
// Create vertices list with transformed coordinates // Create vertices list with transformed coordinates
final vertices = Float32List.fromList([ final vertices = Float32List.fromList([
// Front face // Front face
center.x - halfExtents.x, center.y - halfExtents.y, center.z + halfExtents.z, center.x - halfExtents.x, center.y - halfExtents.y,
center.x + halfExtents.x, center.y - halfExtents.y, center.z + halfExtents.z, center.z + halfExtents.z,
center.x + halfExtents.x, center.y + halfExtents.y, center.z + halfExtents.z, center.x + halfExtents.x, center.y - halfExtents.y,
center.x - halfExtents.x, center.y + halfExtents.y, center.z + halfExtents.z, center.z + halfExtents.z,
center.x + halfExtents.x, center.y + halfExtents.y,
center.z + halfExtents.z,
center.x - halfExtents.x, center.y + halfExtents.y,
center.z + halfExtents.z,
// Back face // Back face
center.x - halfExtents.x, center.y - halfExtents.y, center.z - halfExtents.z, center.x - halfExtents.x, center.y - halfExtents.y,
center.x - halfExtents.x, center.y + halfExtents.y, center.z - halfExtents.z, center.z - halfExtents.z,
center.x + halfExtents.x, center.y + halfExtents.y, center.z - halfExtents.z, center.x - halfExtents.x, center.y + halfExtents.y,
center.x + halfExtents.x, center.y - halfExtents.y, center.z - halfExtents.z, center.z - halfExtents.z,
center.x + halfExtents.x, center.y + halfExtents.y,
center.z - halfExtents.z,
center.x + halfExtents.x, center.y - halfExtents.y,
center.z - halfExtents.z,
// Top face // Top face
center.x - halfExtents.x, center.y + halfExtents.y, center.z - halfExtents.z, center.x - halfExtents.x, center.y + halfExtents.y,
center.x - halfExtents.x, center.y + halfExtents.y, center.z + halfExtents.z, center.z - halfExtents.z,
center.x + halfExtents.x, center.y + halfExtents.y, center.z + halfExtents.z, center.x - halfExtents.x, center.y + halfExtents.y,
center.x + halfExtents.x, center.y + halfExtents.y, center.z - halfExtents.z, center.z + halfExtents.z,
center.x + halfExtents.x, center.y + halfExtents.y,
center.z + halfExtents.z,
center.x + halfExtents.x, center.y + halfExtents.y,
center.z - halfExtents.z,
// Bottom face // Bottom face
center.x - halfExtents.x, center.y - halfExtents.y, center.z - halfExtents.z, center.x - halfExtents.x, center.y - halfExtents.y,
center.x + halfExtents.x, center.y - halfExtents.y, center.z - halfExtents.z, center.z - halfExtents.z,
center.x + halfExtents.x, center.y - halfExtents.y, center.z + halfExtents.z, center.x + halfExtents.x, center.y - halfExtents.y,
center.x - halfExtents.x, center.y - halfExtents.y, center.z + halfExtents.z, center.z - halfExtents.z,
center.x + halfExtents.x, center.y - halfExtents.y,
center.z + halfExtents.z,
center.x - halfExtents.x, center.y - halfExtents.y,
center.z + halfExtents.z,
// Right face // Right face
center.x + halfExtents.x, center.y - halfExtents.y, center.z - halfExtents.z, center.x + halfExtents.x, center.y - halfExtents.y,
center.x + halfExtents.x, center.y + halfExtents.y, center.z - halfExtents.z, center.z - halfExtents.z,
center.x + halfExtents.x, center.y + halfExtents.y, center.z + halfExtents.z, center.x + halfExtents.x, center.y + halfExtents.y,
center.x + halfExtents.x, center.y - halfExtents.y, center.z + halfExtents.z, center.z - halfExtents.z,
center.x + halfExtents.x, center.y + halfExtents.y,
center.z + halfExtents.z,
center.x + halfExtents.x, center.y - halfExtents.y,
center.z + halfExtents.z,
// Left face // Left face
center.x - halfExtents.x, center.y - halfExtents.y, center.z - halfExtents.z, center.x - halfExtents.x, center.y - halfExtents.y,
center.x - halfExtents.x, center.y - halfExtents.y, center.z + halfExtents.z, center.z - halfExtents.z,
center.x - halfExtents.x, center.y + halfExtents.y, center.z + halfExtents.z, center.x - halfExtents.x, center.y - halfExtents.y,
center.x - halfExtents.x, center.y + halfExtents.y, center.z - halfExtents.z, center.z + halfExtents.z,
center.x - halfExtents.x, center.y + halfExtents.y,
center.z + halfExtents.z,
center.x - halfExtents.x, center.y + halfExtents.y,
center.z - halfExtents.z,
]); ]);
final _normals = normals ? Float32List.fromList([ final _normals = normals
? Float32List.fromList([
// Front face // Front face
0, 0, 1, 0, 0, 1,
0, 0, 1, 0, 0, 1,
@@ -624,45 +725,48 @@ static Geometry fromAabb3(Aabb3 aabb, {bool normals = true, bool uvs = true}) {
-1, 0, 0, -1, 0, 0,
-1, 0, 0, -1, 0, 0,
-1, 0, 0, -1, 0, 0,
]) : null; ])
: null;
final _uvs = uvs ? Float32List.fromList([ final _uvs = uvs
? Float32List.fromList([
// Front face // Front face
1/3, 1/3, 1 / 3, 1 / 3,
2/3, 1/3, 2 / 3, 1 / 3,
2/3, 2/3, 2 / 3, 2 / 3,
1/3, 2/3, 1 / 3, 2 / 3,
// Back face // Back face
2/3, 2/3, 2 / 3, 2 / 3,
2/3, 1, 2 / 3, 1,
1, 1, 1, 1,
1, 2/3, 1, 2 / 3,
// Top face // Top face
1/3, 0, 1 / 3, 0,
1/3, 1/3, 1 / 3, 1 / 3,
2/3, 1/3, 2 / 3, 1 / 3,
2/3, 0, 2 / 3, 0,
// Bottom face // Bottom face
1/3, 2/3, 1 / 3, 2 / 3,
2/3, 2/3, 2 / 3, 2 / 3,
2/3, 1, 2 / 3, 1,
1/3, 1, 1 / 3, 1,
// Right face // Right face
2/3, 1/3, 2 / 3, 1 / 3,
2/3, 2/3, 2 / 3, 2 / 3,
1, 2/3, 1, 2 / 3,
1, 1/3, 1, 1 / 3,
// Left face // Left face
0, 1/3, 0, 1 / 3,
1/3, 1/3, 1 / 3, 1 / 3,
1/3, 2/3, 1 / 3, 2 / 3,
0, 2/3, 0, 2 / 3,
]) : null; ])
: null;
final indices = [ final indices = [
// Front face // Front face
@@ -682,15 +786,14 @@ static Geometry fromAabb3(Aabb3 aabb, {bool normals = true, bool uvs = true}) {
return Geometry(vertices, indices, normals: _normals, uvs: _uvs); return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
} }
static Geometry halfPyramid({ static Geometry halfPyramid(
double startX = 0.25, {double startX = 0.25,
double startY = 0.25, double startY = 0.25,
double width = 1.0, double width = 1.0,
double height = 1.0, double height = 1.0,
double depth = 1.0, double depth = 1.0,
bool normals = true, bool normals = true,
bool uvs = true bool uvs = true}) {
}) {
// Define vertices for a half pyramid (triangular prism) // Define vertices for a half pyramid (triangular prism)
// Starting at (startX, startY, 0) // Starting at (startX, startY, 0)
Float32List vertices = Float32List.fromList([ Float32List vertices = Float32List.fromList([
@@ -706,7 +809,8 @@ static Geometry fromAabb3(Aabb3 aabb, {bool normals = true, bool uvs = true}) {
]); ]);
// Define normals if needed // Define normals if needed
Float32List? _normals = normals ? Float32List.fromList([ Float32List? _normals = normals
? Float32List.fromList([
// Base rectangle // Base rectangle
0, 0, -1, // Bottom face 0, 0, -1, // Bottom face
0, 0, -1, 0, 0, -1,
@@ -716,10 +820,12 @@ static Geometry fromAabb3(Aabb3 aabb, {bool normals = true, bool uvs = true}) {
// Ridge normals (approximate) // Ridge normals (approximate)
0, 0.7071, 0.7071, // Angled toward ridge 0, 0.7071, 0.7071, // Angled toward ridge
0, 0.7071, 0.7071, 0, 0.7071, 0.7071,
]) : null; ])
: null;
// Define UVs if needed // Define UVs if needed
Float32List? _uvs = uvs ? Float32List.fromList([ Float32List? _uvs = uvs
? Float32List.fromList([
// Base rectangle UVs // Base rectangle UVs
0, 0, // Bottom-left 0, 0, // Bottom-left
1, 0, // Bottom-right 1, 0, // Bottom-right
@@ -729,7 +835,8 @@ static Geometry fromAabb3(Aabb3 aabb, {bool normals = true, bool uvs = true}) {
// Ridge UVs // Ridge UVs
0, 0.5, 0, 0.5,
1, 0.5, 1, 0.5,
]) : null; ])
: null;
// Define indices for triangular faces // Define indices for triangular faces
List<int> indices = [ List<int> indices = [
@@ -753,6 +860,5 @@ static Geometry fromAabb3(Aabb3 aabb, {bool normals = true, bool uvs = true}) {
]; ];
return Geometry(vertices, indices, normals: _normals, uvs: _uvs); return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
} }
} }
@@ -1,6 +1,7 @@
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_material.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_material.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart';
import 'package:thermion_dart/thermion_dart.dart'; import 'package:thermion_dart/thermion_dart.dart';
@@ -10,34 +11,18 @@ class FFIAsset extends ThermionAsset {
/// ///
/// ///
/// ///
final Pointer<TSceneAsset> pointer; final Pointer<TSceneAsset> asset;
/// ///
/// ///
/// ///
final Pointer<TSceneManager> sceneManager; final FFIFilamentApp app;
///
///
///
Pointer<TRenderableManager> get renderableManager =>
Engine_getRenderableManager(engine);
///
///
///
final Pointer<TEngine> engine;
/// ///
/// ///
/// ///
FFIAsset? _highlight; FFIAsset? _highlight;
///
///
///
final Pointer<TMaterialProvider> _unlitMaterialProvider;
/// ///
/// ///
/// ///
@@ -48,22 +33,15 @@ class FFIAsset extends ThermionAsset {
/// ///
late final ThermionEntity entity; late final ThermionEntity entity;
/// FFIAsset(this.asset, this.app, {this.isInstance = false}) {
/// entity = SceneAsset_getEntity(asset);
///
final ThermionViewer viewer;
FFIAsset(this.pointer, this.sceneManager, this.engine,
this._unlitMaterialProvider, this.viewer,
{this.isInstance = false}) {
entity = SceneAsset_getEntity(pointer);
} }
@override @override
Future<List<ThermionEntity>> getChildEntities() async { Future<List<ThermionEntity>> getChildEntities() async {
var count = SceneAsset_getChildEntityCount(pointer); var count = SceneAsset_getChildEntityCount(asset);
var children = Int32List(count); var children = Int32List(count);
SceneAsset_getChildEntities(pointer, children.address); SceneAsset_getChildEntities(asset, children.address);
return children; return children;
} }
@@ -73,12 +51,11 @@ class FFIAsset extends ThermionAsset {
throw Exception( throw Exception(
"This is itself an instance. Call getInstance on the original asset that this instance was created from"); "This is itself an instance. Call getInstance on the original asset that this instance was created from");
} }
var instance = SceneAsset_getInstance(pointer, index); var instance = SceneAsset_getInstance(asset, index);
if (instance == nullptr) { if (instance == nullptr) {
throw Exception("No instance available at index $index"); throw Exception("No instance available at index $index");
} }
return FFIAsset( return FFIAsset(instance, app);
instance, sceneManager, engine, _unlitMaterialProvider, viewer);
} }
/// ///
@@ -100,7 +77,7 @@ class FFIAsset extends ThermionAsset {
} }
SceneAsset_createInstanceRenderThread( SceneAsset_createInstanceRenderThread(
pointer, asset,
ptrList.address.cast<Pointer<TMaterialInstance>>(), ptrList.address.cast<Pointer<TMaterialInstance>>(),
materialInstances?.length ?? 0, materialInstances?.length ?? 0,
cb); cb);
@@ -108,8 +85,7 @@ class FFIAsset extends ThermionAsset {
if (created == FILAMENT_ASSET_ERROR) { if (created == FILAMENT_ASSET_ERROR) {
throw Exception("Failed to create instance"); throw Exception("Failed to create instance");
} }
return FFIAsset( return FFIAsset(created, app);
created, sceneManager, engine, _unlitMaterialProvider, viewer);
} }
/// ///
@@ -117,7 +93,7 @@ class FFIAsset extends ThermionAsset {
/// ///
@override @override
Future<int> getInstanceCount() async { Future<int> getInstanceCount() async {
return SceneAsset_getInstanceCount(pointer); return SceneAsset_getInstanceCount(asset);
} }
/// ///
@@ -127,8 +103,7 @@ class FFIAsset extends ThermionAsset {
Future<List<ThermionAsset>> getInstances() async { Future<List<ThermionAsset>> getInstances() async {
var count = await getInstanceCount(); var count = await getInstanceCount();
final result = List<ThermionAsset>.generate(count, (i) { final result = List<ThermionAsset>.generate(count, (i) {
return FFIAsset(SceneAsset_getInstance(pointer, i), sceneManager, engine, return FFIAsset(SceneAsset_getInstance(asset, i), app);
_unlitMaterialProvider, viewer);
}); });
return result; return result;
@@ -139,13 +114,14 @@ class FFIAsset extends ThermionAsset {
/// ///
@override @override
Future removeStencilHighlight() async { Future removeStencilHighlight() async {
if (_highlight != null) { throw UnimplementedError();
SceneManager_removeFromScene(sceneManager, _highlight!.entity); // if (_highlight != null) {
final childEntities = await _highlight!.getChildEntities(); // SceneManager_removeFromScene(sceneManager, _highlight!.entity);
for (final child in childEntities) { // final childEntities = await _highlight!.getChildEntities();
SceneManager_removeFromScene(sceneManager, child); // for (final child in childEntities) {
} // SceneManager_removeFromScene(sceneManager, child);
} // }
// }
} }
/// ///
@@ -165,8 +141,7 @@ class FFIAsset extends ThermionAsset {
} }
var sourceMaterialInstance = FFIMaterialInstance( var sourceMaterialInstance = FFIMaterialInstance(
RenderableManager_getMaterialInstanceAt( RenderableManager_getMaterialInstanceAt(
renderableManager, targetEntity, 0), app.renderableManager, targetEntity, 0), app);
sceneManager);
await sourceMaterialInstance.setStencilWriteEnabled(true); await sourceMaterialInstance.setStencilWriteEnabled(true);
await sourceMaterialInstance.setDepthWriteEnabled(true); await sourceMaterialInstance.setDepthWriteEnabled(true);
@@ -179,10 +154,10 @@ class FFIAsset extends ThermionAsset {
await withPointerCallback<TMaterialInstance>((cb) { await withPointerCallback<TMaterialInstance>((cb) {
final key = Struct.create<TMaterialKey>(); final key = Struct.create<TMaterialKey>();
MaterialProvider_createMaterialInstanceRenderThread( MaterialProvider_createMaterialInstanceRenderThread(
_unlitMaterialProvider, key.address, cb); app.ubershaderMaterialProvider, key.address, cb);
}); });
final highlightMaterialInstance = final highlightMaterialInstance =
FFIMaterialInstance(materialInstancePtr, sceneManager); FFIMaterialInstance(materialInstancePtr, app);
await highlightMaterialInstance await highlightMaterialInstance
.setStencilCompareFunction(SamplerCompareFunction.NE); .setStencilCompareFunction(SamplerCompareFunction.NE);
await highlightMaterialInstance.setStencilReferenceValue(1); await highlightMaterialInstance.setStencilReferenceValue(1);
@@ -197,10 +172,10 @@ class FFIAsset extends ThermionAsset {
_highlight = highlightInstance; _highlight = highlightInstance;
await highlightMaterialInstance.setStencilReferenceValue(1); await highlightMaterialInstance.setStencilReferenceValue(1);
RenderableManager_setPriority(renderableManager, targetEntity, 0); RenderableManager_setPriority(app.renderableManager, targetEntity, 0);
final transformManager = Engine_getTransformManager(engine);
TransformManager_setParent( TransformManager_setParent(
transformManager, _highlight!.entity, entity, false); app.transformManager, _highlight!.entity, entity, false);
} }
var targetHighlightEntity = _highlight!.entity; var targetHighlightEntity = _highlight!.entity;
@@ -210,35 +185,17 @@ class FFIAsset extends ThermionAsset {
targetHighlightEntity = highlightChildEntities[entityIndex!]; targetHighlightEntity = highlightChildEntities[entityIndex!];
} }
RenderableManager_setPriority(renderableManager, targetHighlightEntity, 7); RenderableManager_setPriority(
app.renderableManager, targetHighlightEntity, 7);
SceneManager_addToScene(sceneManager, targetHighlightEntity); throw UnimplementedError();
}
///
///
///
@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);
}
} }
FFIAsset? boundingBoxAsset; FFIAsset? boundingBoxAsset;
Future<v64.Aabb3> getBoundingBox() async { Future<v64.Aabb3> getBoundingBox() async {
final entities = <ThermionEntity>[]; final entities = <ThermionEntity>[];
if (RenderableManager_isRenderable(renderableManager, entity)) { if (RenderableManager_isRenderable(app.renderableManager, entity)) {
entities.add(entity); entities.add(entity);
} else { } else {
entities.addAll(await getChildEntities()); entities.addAll(await getChildEntities());
@@ -247,7 +204,7 @@ class FFIAsset extends ThermionAsset {
var boundingBox = v64.Aabb3(); var boundingBox = v64.Aabb3();
for (final entity in entities) { for (final entity in entities) {
final aabb3 = SceneManager_getRenderableBoundingBox(sceneManager, entity); final aabb3 = RenderableManager_getAabb(app.renderableManager, entity);
final entityBB = v64.Aabb3.centerAndHalfExtents( final entityBB = v64.Aabb3.centerAndHalfExtents(
v64.Vector3(aabb3.centerX, aabb3.centerY, aabb3.centerZ), v64.Vector3(aabb3.centerX, aabb3.centerY, aabb3.centerZ),
v64.Vector3(aabb3.halfExtentX, aabb3.halfExtentY, aabb3.halfExtentZ), v64.Vector3(aabb3.halfExtentX, aabb3.halfExtentY, aabb3.halfExtentZ),
@@ -263,7 +220,7 @@ class FFIAsset extends ThermionAsset {
@override @override
Future<void> setBoundingBoxVisibility(bool visible) async { Future<void> setBoundingBoxVisibility(bool visible) async {
if (boundingBoxAsset == null) { if (boundingBoxAsset == null) {
final boundingBox = await SceneAsset_getBoundingBox(pointer); final boundingBox = await SceneAsset_getBoundingBox(asset);
final min = [ final min = [
boundingBox.centerX - boundingBox.halfExtentX, boundingBox.centerX - boundingBox.halfExtentX,
@@ -323,10 +280,10 @@ class FFIAsset extends ThermionAsset {
await withPointerCallback<TMaterialInstance>((cb) { await withPointerCallback<TMaterialInstance>((cb) {
final key = Struct.create<TMaterialKey>(); final key = Struct.create<TMaterialKey>();
MaterialProvider_createMaterialInstanceRenderThread( MaterialProvider_createMaterialInstanceRenderThread(
_unlitMaterialProvider, key.address, cb); app.ubershaderMaterialProvider, key.address, cb);
}); });
final material = FFIMaterialInstance(materialInstancePtr, sceneManager); final material = FFIMaterialInstance(materialInstancePtr, app);
await material.setParameterFloat4( await material.setParameterFloat4(
"baseColorFactor", 1.0, 1.0, 0.0, 1.0); // Yellow wireframe "baseColorFactor", 1.0, 1.0, 0.0, 1.0); // Yellow wireframe
@@ -337,23 +294,25 @@ class FFIAsset extends ThermionAsset {
primitiveType: PrimitiveType.LINES, primitiveType: PrimitiveType.LINES,
); );
boundingBoxAsset = await viewer.createGeometry( throw UnimplementedError();
geometry,
materialInstances: [material],
keepData: false,
) as FFIAsset;
await viewer.setCastShadows(boundingBoxAsset!.entity, false); // boundingBoxAsset = await viewer.createGeometry(
await viewer.setReceiveShadows(boundingBoxAsset!.entity, false); // geometry,
// materialInstances: [material],
// keepData: false,
// ) as FFIAsset;
TransformManager_setParent(Engine_getTransformManager(engine), await boundingBoxAsset!.setCastShadows(false);
await boundingBoxAsset!.setReceiveShadows(false);
TransformManager_setParent(Engine_getTransformManager(app.engine),
boundingBoxAsset!.entity, entity, false); boundingBoxAsset!.entity, entity, false);
} }
if (visible) { // if (visible) {
await boundingBoxAsset!.addToScene(); // await boundingBoxAsset!.addToScene();
} else { // } else {
await boundingBoxAsset!.removeFromScene(); // await boundingBoxAsset!.removeFromScene();
} // }
} }
/// ///
@@ -365,7 +324,25 @@ class FFIAsset extends ThermionAsset {
final entities = <ThermionEntity>[entity, ...childEntities]; final entities = <ThermionEntity>[entity, ...childEntities];
for (final entity in entities) { for (final entity in entities) {
RenderableManager_setMaterialInstanceAt( RenderableManager_setMaterialInstanceAt(
Engine_getRenderableManager(engine), entity, 0, instance.pointer); Engine_getRenderableManager(app.engine), entity, 0, instance.pointer);
}
}
Future setCastShadows(bool castShadows) async {
RenderableManager_setCastShadows(
app.renderableManager, this.entity, castShadows);
for (final entity in await this.getChildEntities()) {
RenderableManager_setCastShadows(
app.renderableManager, entity, castShadows);
}
}
Future setReceiveShadows(bool receiveShadows) async {
RenderableManager_setReceiveShadows(
app.renderableManager, this.entity, receiveShadows);
for (final entity in await this.getChildEntities()) {
RenderableManager_setReceiveShadows(
app.renderableManager, entity, receiveShadows);
} }
} }
} }
@@ -26,6 +26,7 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
final Pointer<TRenderableManager> renderableManager; final Pointer<TRenderableManager> renderableManager;
final Pointer<TMaterialProvider> ubershaderMaterialProvider; final Pointer<TMaterialProvider> ubershaderMaterialProvider;
final Pointer<TRenderTicker> renderTicker; final Pointer<TRenderTicker> renderTicker;
final Pointer<TNameComponentManager> nameComponentManager;
FFIFilamentApp( FFIFilamentApp(
this.engine, this.engine,
@@ -36,7 +37,8 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
this.lightManager, this.lightManager,
this.renderableManager, this.renderableManager,
this.ubershaderMaterialProvider, this.ubershaderMaterialProvider,
this.renderTicker) this.renderTicker,
this.nameComponentManager)
: super( : super(
engine: engine, engine: engine,
gltfAssetLoader: gltfAssetLoader, gltfAssetLoader: gltfAssetLoader,
@@ -76,7 +78,9 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
final renderableManager = Engine_getRenderableManager(engine); final renderableManager = Engine_getRenderableManager(engine);
final renderTicker = await withPointerCallback<TRenderTicker>( final renderTicker = await withPointerCallback<TRenderTicker>(
(cb) => RenderTicker_create()); (cb) => RenderTicker_create(renderer));
final nameComponentManager = NameComponentManager_create();
_instance = FFIFilamentApp( _instance = FFIFilamentApp(
engine, engine,
@@ -86,7 +90,8 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
transformManager, transformManager,
lightManager, lightManager,
renderableManager, renderableManager,
ubershaderMaterialProvider); ubershaderMaterialProvider,
renderTicker, nameComponentManager);
} }
return _instance!; return _instance!;
} }
@@ -1,28 +1,28 @@
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_texture.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_texture.dart';
import 'package:thermion_dart/thermion_dart.dart'; import 'package:thermion_dart/thermion_dart.dart';
import 'package:vector_math/vector_math_64.dart'; import 'package:vector_math/vector_math_64.dart';
class FFIMaterial extends Material { class FFIMaterial extends Material {
final Pointer<TEngine> engine; final FFIFilamentApp app;
final Pointer<TSceneManager> sceneManager;
final Pointer<TMaterial> pointer; final Pointer<TMaterial> pointer;
FFIMaterial(this.pointer, this.engine, this.sceneManager); FFIMaterial(this.pointer, this.app);
@override @override
Future<MaterialInstance> createInstance() async { Future<MaterialInstance> createInstance() async {
var ptr = await withPointerCallback<TMaterialInstance>((cb) { var ptr = await withPointerCallback<TMaterialInstance>((cb) {
Material_createInstanceRenderThread(pointer, cb); Material_createInstanceRenderThread(pointer, cb);
}); });
return FFIMaterialInstance(ptr, sceneManager); return FFIMaterialInstance(ptr, this.app);
} }
Future dispose() async { Future destroy() async {
await withVoidCallback((cb) { await withVoidCallback((cb) {
Engine_destroyMaterialRenderThread(engine, pointer, cb); Engine_destroyMaterialRenderThread(app.engine, pointer, cb);
}); });
} }
@@ -35,9 +35,9 @@ class FFIMaterial extends Material {
class FFIMaterialInstance extends MaterialInstance { class FFIMaterialInstance extends MaterialInstance {
final Pointer<TMaterialInstance> pointer; final Pointer<TMaterialInstance> pointer;
final Pointer<TSceneManager> sceneManager; final FFIFilamentApp app;
FFIMaterialInstance(this.pointer, this.sceneManager) { FFIMaterialInstance(this.pointer, this.app) {
if (pointer == nullptr) { if (pointer == nullptr) {
throw Exception("MaterialInstance not found"); throw Exception("MaterialInstance not found");
} }
@@ -169,10 +169,9 @@ class FFIMaterialInstance extends MaterialInstance {
MaterialInstance_setStencilWriteMask(pointer, mask); MaterialInstance_setStencilWriteMask(pointer, mask);
} }
Future dispose() async { Future destroy() async {
await withVoidCallback((cb) { await withVoidCallback((cb) {
SceneManager_destroyMaterialInstanceRenderThread( Engine_destroyMaterialInstanceRenderThread(app.engine, this.pointer, cb);
sceneManager, pointer, cb);
}); });
} }
@@ -1,10 +1,9 @@
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_asset.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_render_target.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_render_target.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_swapchain.dart';
import 'package:thermion_dart/src/viewer/src/shared_types/scene.dart'; import 'package:thermion_dart/src/viewer/src/shared_types/scene.dart';
import 'package:thermion_dart/src/viewer/src/shared_types/shared_types.dart';
import 'callbacks.dart'; import 'callbacks.dart';
import 'ffi_camera.dart';
class FFIScene extends Scene { class FFIScene extends Scene {
final Pointer<TScene> scene; final Pointer<TScene> scene;
@@ -12,8 +11,15 @@ class FFIScene extends Scene {
FFIRenderTarget? renderTarget; FFIRenderTarget? renderTarget;
FFIScene(this.scene, this.app) { FFIScene(this.scene, this.app) {}
@override
Future add(covariant FFIAsset asset) async {
SceneAsset_addToScene(asset.asset, scene);
} }
@override
Future remove(covariant FFIAsset asset) async {
SceneAsset_removeFromScene(asset.asset, scene);
}
} }
@@ -327,14 +327,22 @@ external void LightManager_setDirection(
double z, double z,
); );
@ffi.Native<ffi.Int Function(ffi.Pointer<TLightManager>, EntityId, ffi.Int)>( @ffi.Native<ffi.Int Function(ffi.Pointer<TLightManager>, ffi.UnsignedInt)>(
isLeaf: true) symbol: "LightManager_createLight", isLeaf: true)
external int LightManager_createLight( external int _LightManager_createLight(
ffi.Pointer<TLightManager> tLightManager, ffi.Pointer<TLightManager> tLightManager,
int entity, int tLightTtype,
int type,
); );
int LightManager_createLight(
ffi.Pointer<TLightManager> tLightManager,
TLightType tLightTtype,
) =>
_LightManager_createLight(
tLightManager,
tLightTtype.value,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TLightManager>, EntityId)>( @ffi.Native<ffi.Void Function(ffi.Pointer<TLightManager>, EntityId)>(
isLeaf: true) isLeaf: true)
external void LightManager_destroyLight( external void LightManager_destroyLight(
@@ -342,15 +350,12 @@ external void LightManager_destroyLight(
int entity, int entity,
); );
@ffi.Native< @ffi.Native<ffi.Void Function(ffi.Pointer<TLightManager>, EntityId, ffi.Float)>(
ffi.Void Function(ffi.Pointer<TLightManager>, EntityId, ffi.Double, isLeaf: true)
ffi.Double, ffi.Double)>(isLeaf: true)
external void LightManager_setColor( external void LightManager_setColor(
ffi.Pointer<TLightManager> tLightManager, ffi.Pointer<TLightManager> tLightManager,
int entity, int entity,
double r, double colorTemperature,
double g,
double b,
); );
@ffi.Native< @ffi.Native<
@@ -995,6 +1000,9 @@ external void View_pick(
PickCallback callback, PickCallback callback,
); );
@ffi.Native<ffi.Pointer<TNameComponentManager> Function()>(isLeaf: true)
external ffi.Pointer<TNameComponentManager> NameComponentManager_create();
@ffi.Native< @ffi.Native<
ffi.Pointer<ffi.Char> Function( ffi.Pointer<ffi.Char> Function(
ffi.Pointer<TNameComponentManager>, EntityId)>(isLeaf: true) ffi.Pointer<TNameComponentManager>, EntityId)>(isLeaf: true)
@@ -1003,6 +1011,14 @@ external ffi.Pointer<ffi.Char> NameComponentManager_getName(
int entity, int entity,
); );
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TIndirectLight>, ffi.Pointer<ffi.Double>)>(isLeaf: true)
external void IndirectLight_setRotation(
ffi.Pointer<TIndirectLight> tIndirectLight,
ffi.Pointer<ffi.Double> rotation,
);
@ffi.Native< @ffi.Native<
ffi.Void Function(ffi.Pointer<TGizmo>, ffi.Uint32, ffi.Uint32, ffi.Void Function(ffi.Pointer<TGizmo>, ffi.Uint32, ffi.Uint32,
GizmoPickCallback)>(isLeaf: true) GizmoPickCallback)>(isLeaf: true)
@@ -1067,6 +1083,12 @@ external void Scene_addEntity(
int entityId, int entityId,
); );
@ffi.Native<ffi.Void Function(ffi.Pointer<TScene>, EntityId)>(isLeaf: true)
external void Scene_removeEntity(
ffi.Pointer<TScene> tScene,
int entityId,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TScene>, ffi.Pointer<TSkybox>)>( @ffi.Native<ffi.Void Function(ffi.Pointer<TScene>, ffi.Pointer<TSkybox>)>(
isLeaf: true) isLeaf: true)
external void Scene_setSkybox( external void Scene_setSkybox(
@@ -1383,12 +1405,26 @@ external void Renderer_setFrameInterval(
int interval, int interval,
); );
@ffi.Native< @ffi.Native<ffi.Pointer<TRenderTicker> Function(ffi.Pointer<TRenderer>)>(
ffi.Pointer<TRenderTicker> Function( isLeaf: true)
ffi.Pointer<TRenderer>, ffi.Pointer<TSceneManager>)>(isLeaf: true)
external ffi.Pointer<TRenderTicker> RenderTicker_create( external ffi.Pointer<TRenderTicker> RenderTicker_create(
ffi.Pointer<TRenderer> tRenderer, ffi.Pointer<TRenderer> tRenderer,
ffi.Pointer<TSceneManager> tSceneManager, );
@ffi.Native<
ffi.Void Function(ffi.Pointer<TRenderTicker>,
ffi.Pointer<TAnimationManager>)>(isLeaf: true)
external void RenderTicker_addAnimationManager(
ffi.Pointer<TRenderTicker> tRenderTicker,
ffi.Pointer<TAnimationManager> tAnimationManager,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TRenderTicker>,
ffi.Pointer<TAnimationManager>)>(isLeaf: true)
external void RenderTicker_removeAnimationManager(
ffi.Pointer<TRenderTicker> tRenderTicker,
ffi.Pointer<TAnimationManager> tAnimationManager,
); );
@ffi.Native<ffi.Void Function(ffi.Pointer<TRenderTicker>, ffi.Uint64)>( @ffi.Native<ffi.Void Function(ffi.Pointer<TRenderTicker>, ffi.Uint64)>(
@@ -1421,6 +1457,22 @@ external void RenderTicker_renderRenderThread(
int frameTimeInNanos, int frameTimeInNanos,
); );
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TEngine>,
ffi.Pointer<TScene>,
ffi.Pointer<
ffi.NativeFunction<
ffi.Void Function(
ffi.Pointer<TAnimationManager>)>>)>(isLeaf: true)
external void AnimationManager_createRenderThread(
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TScene> tScene,
ffi.Pointer<
ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TAnimationManager>)>>
onComplete,
);
@ffi.Native< @ffi.Native<
ffi.Void Function( ffi.Void Function(
ffi.Int, ffi.Int,
@@ -1549,6 +1601,15 @@ external void Engine_destroyMaterialRenderThread(
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete, ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
); );
@ffi.Native<
ffi.Void Function(ffi.Pointer<TEngine>, ffi.Pointer<TMaterialInstance>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void Engine_destroyMaterialInstanceRenderThread(
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TMaterialInstance> tMaterialInstance,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
@ffi.Native< @ffi.Native<
ffi.Void Function(ffi.Pointer<TEngine>, ffi.Pointer<TSkybox>, ffi.Void Function(ffi.Pointer<TEngine>, ffi.Pointer<TSkybox>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true) ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
@@ -3182,6 +3243,13 @@ external bool RenderableManager_getFogEnabled(
int entityId, int entityId,
); );
@ffi.Native<Aabb3 Function(ffi.Pointer<TRenderableManager>, EntityId)>(
isLeaf: true)
external Aabb3 RenderableManager_getAabb(
ffi.Pointer<TRenderableManager> tRenderableManager,
int entityId,
);
@ffi.Native< @ffi.Native<
ffi.Pointer<TEngine> Function( ffi.Pointer<TEngine> Function(
ffi.UnsignedInt, ffi.UnsignedInt,
@@ -3324,6 +3392,14 @@ external void Engine_destroyMaterial(
ffi.Pointer<TMaterial> tMaterial, ffi.Pointer<TMaterial> tMaterial,
); );
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TEngine>, ffi.Pointer<TMaterialInstance>)>(isLeaf: true)
external void Engine_destroyMaterialInstance(
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TMaterialInstance> tMaterialInstance,
);
@ffi.Native<ffi.Pointer<TScene> Function(ffi.Pointer<TEngine>)>(isLeaf: true) @ffi.Native<ffi.Pointer<TScene> Function(ffi.Pointer<TEngine>)>(isLeaf: true)
external ffi.Pointer<TScene> Engine_createScene( external ffi.Pointer<TScene> Engine_createScene(
ffi.Pointer<TEngine> tEngine, ffi.Pointer<TEngine> tEngine,
@@ -3401,6 +3477,44 @@ external ffi.Pointer<TSceneAsset> SceneAsset_createGeometry(
int materialInstanceCount, int materialInstanceCount,
); );
@ffi.Native<
ffi.Pointer<TSceneAsset> Function(
ffi.Pointer<TGltfAssetLoader>,
ffi.Pointer<TGltfResourceLoader>,
ffi.Pointer<TEngine>,
ffi.Pointer<TNameComponentManager>,
ffi.Pointer<ffi.Uint8>,
ffi.Size,
ffi.Size)>(isLeaf: true)
external ffi.Pointer<TSceneAsset> SceneAsset_loadGlb(
ffi.Pointer<TGltfAssetLoader> tAssetLoader,
ffi.Pointer<TGltfResourceLoader> tResourceLoader,
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TNameComponentManager> tNameComponentManager,
ffi.Pointer<ffi.Uint8> data,
int length,
int numInstances,
);
@ffi.Native<
ffi.Pointer<TSceneAsset> Function(
ffi.Pointer<TGltfAssetLoader>,
ffi.Pointer<TGltfResourceLoader>,
ffi.Pointer<TEngine>,
ffi.Pointer<TNameComponentManager>,
ffi.Pointer<ffi.Uint8>,
ffi.Size,
ffi.Size)>(isLeaf: true)
external ffi.Pointer<TSceneAsset> SceneAsset_loadGltf(
ffi.Pointer<TGltfAssetLoader> tAssetLoader,
ffi.Pointer<TGltfResourceLoader> tResourceLoader,
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TNameComponentManager> tNameComponentManager,
ffi.Pointer<ffi.Uint8> data,
int length,
int numInstances,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TSceneAsset>, ffi.Pointer<TScene>)>( @ffi.Native<ffi.Void Function(ffi.Pointer<TSceneAsset>, ffi.Pointer<TScene>)>(
isLeaf: true) isLeaf: true)
external void SceneAsset_addToScene( external void SceneAsset_addToScene(
@@ -3408,6 +3522,13 @@ external void SceneAsset_addToScene(
ffi.Pointer<TScene> tScene, ffi.Pointer<TScene> tScene,
); );
@ffi.Native<ffi.Void Function(ffi.Pointer<TSceneAsset>, ffi.Pointer<TScene>)>(
isLeaf: true)
external void SceneAsset_removeFromScene(
ffi.Pointer<TSceneAsset> tSceneAsset,
ffi.Pointer<TScene> tScene,
);
@ffi.Native<EntityId Function(ffi.Pointer<TSceneAsset>)>(isLeaf: true) @ffi.Native<EntityId Function(ffi.Pointer<TSceneAsset>)>(isLeaf: true)
external int SceneAsset_getEntity( external int SceneAsset_getEntity(
ffi.Pointer<TSceneAsset> tSceneAsset, ffi.Pointer<TSceneAsset> tSceneAsset,
@@ -3465,6 +3586,12 @@ external Aabb3 SceneAsset_getBoundingBox(
ffi.Pointer<TSceneAsset> asset, ffi.Pointer<TSceneAsset> asset,
); );
@ffi.Native<ffi.Pointer<TAnimationManager> Function(ffi.Pointer<TEngine>)>(
isLeaf: true)
external ffi.Pointer<TAnimationManager> AnimationManager_create(
ffi.Pointer<TEngine> tEngine,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TAnimationManager>, EntityId)>( @ffi.Native<ffi.Void Function(ffi.Pointer<TAnimationManager>, EntityId)>(
isLeaf: true) isLeaf: true)
external void AnimationManager_addAnimationComponent( external void AnimationManager_addAnimationComponent(
@@ -4131,6 +4258,26 @@ enum TTransparencyMode {
}; };
} }
enum TLightType {
LIGHT_TYPE_SUN(0),
LIGHT_TYPE_DIRECTIONAL(1),
LIGHT_TYPE_POINT(2),
LIGHT_TYPE_FOCUSED_SPOT(3),
LIGHT_TYPE_SPOT(4);
final int value;
const TLightType(this.value);
static TLightType fromValue(int value) => switch (value) {
0 => LIGHT_TYPE_SUN,
1 => LIGHT_TYPE_DIRECTIONAL,
2 => LIGHT_TYPE_POINT,
3 => LIGHT_TYPE_FOCUSED_SPOT,
4 => LIGHT_TYPE_SPOT,
_ => throw ArgumentError("Unknown value for TLightType: $value"),
};
}
typedef EntityId = ffi.Int32; typedef EntityId = ffi.Int32;
typedef DartEntityId = int; typedef DartEntityId = int;
@@ -24,6 +24,8 @@ import 'callbacks.dart';
import 'ffi_camera.dart'; import 'ffi_camera.dart';
import 'ffi_view.dart'; import 'ffi_view.dart';
const FILAMENT_ASSET_ERROR = 0;
/// ///
/// ///
/// ///
@@ -37,29 +39,30 @@ class ThermionViewerFFI extends ThermionViewer {
late final FFIFilamentApp app; late final FFIFilamentApp app;
late final FFIRenderTarget? renderTarget; late final FFIRenderTarget? renderTarget;
late final Future<Uint8List> Function(String path) assetLoader;
/// ///
/// ///
/// ///
ThermionViewerFFI(this.app, {this.renderTarget}) { ThermionViewerFFI(this.assetLoader, this.app, {this.renderTarget}) {
_onPickResultCallable = _onPickResultCallable =
NativeCallable<PickCallbackFunction>.listener(_onPickResult); NativeCallable<PickCallbackFunction>.listener(_onPickResult);
_initialize(); _initialize();
} }
/// // ///
/// // ///
/// // ///
Future<RenderTarget> createRenderTarget(int width, int height, // Future<RenderTarget> createRenderTarget(int width, int height,
{covariant FFITexture? color, covariant FFITexture? depth}) async { // {covariant FFITexture? color, covariant FFITexture? depth}) async {
final renderTarget = await withPointerCallback<TRenderTarget>((cb) { // final renderTarget = await withPointerCallback<TRenderTarget>((cb) {
RenderTarget_createRenderThread(app.engine, width, height, // RenderTarget_createRenderThread(app.engine, width, height,
color?.pointer ?? nullptr, depth?.pointer ?? nullptr, cb); // color?.pointer ?? nullptr, depth?.pointer ?? nullptr, cb);
}); // });
return FFIRenderTarget(renderTarget, app); // return FFIRenderTarget(renderTarget, app);
} // }
/// ///
/// ///
@@ -95,6 +98,7 @@ class ThermionViewerFFI extends ThermionViewer {
late final FFIView view; late final FFIView view;
late final FFIScene scene; late final FFIScene scene;
late final FFICamera camera; late final FFICamera camera;
late final Pointer<TAnimationManager> animationManager;
Future _initialize() async { Future _initialize() async {
_logger.info("Initializing ThermionViewerFFI"); _logger.info("Initializing ThermionViewerFFI");
@@ -111,6 +115,10 @@ class ThermionViewerFFI extends ThermionViewer {
if (renderTarget != null) { if (renderTarget != null) {
await view.setRenderTarget(renderTarget); await view.setRenderTarget(renderTarget);
} }
animationManager = await withPointerCallback<TAnimationManager>((cb) =>
AnimationManager_createRenderThread(app.engine, scene.scene, cb));
RenderTicker_addAnimationManager(app.renderTicker, animationManager);
this._initialized.complete(true); this._initialized.complete(true);
} }
@@ -136,79 +144,78 @@ class ThermionViewerFFI extends ThermionViewer {
@override @override
Future render() async { Future render() async {
RenderTicker_renderRenderThread(app.renderTicker, 0); RenderTicker_renderRenderThread(app.renderTicker, 0);
// Viewer_renderRenderThread(_viewer!, view.view, swapChain.swapChain);
} }
/// // ///
/// // ///
/// // ///
@override // @override
Future<Uint8List> capture() async { // Future<Uint8List> capture() async {
final fence = await withPointerCallback<TFence>((cb) { // final fence = await withPointerCallback<TFence>((cb) {
Engine_createFenceRenderThread(app.engine!, cb); // Engine_createFenceRenderThread(app.engine!, cb);
}); // });
var pixelBuffers = <Uint8List>[]; // var pixelBuffers = <Uint8List>[];
for (final entry in targets) { // for (final entry in targets) {
final view = entry.view as FFIView; // final view = entry.view as FFIView;
var swapChain = entry.swapChain as FFISwapChain?; // var swapChain = entry.swapChain as FFISwapChain?;
final renderTarget = entry.renderTarget as FFIRenderTarget?; // final renderTarget = entry.renderTarget as FFIRenderTarget?;
final vp = await view.getViewport(); // final vp = await view.getViewport();
final length = vp.width * vp.height * 4; // final length = vp.width * vp.height * 4;
await withBoolCallback((cb) { // await withBoolCallback((cb) {
Renderer_beginFrameRenderThread(renderer, // Renderer_beginFrameRenderThread(renderer,
swapChain?.swapChain ?? Viewer_getSwapChainAt(_viewer!, 0), 0, cb); // swapChain?.swapChain ?? Viewer_getSwapChainAt(_viewer!, 0), 0, cb);
}); // });
await withVoidCallback((cb) {
Renderer_renderRenderThread(renderer, view.view, cb);
});
final out = Uint8List(length);
await withVoidCallback((cb) {
Renderer_readPixelsRenderThread(
renderer,
view.view,
renderTarget!.renderTarget,
TPixelDataFormat.PIXELDATAFORMAT_RGBA,
TPixelDataType.PIXELDATATYPE_UBYTE,
out.address,
cb);
});
pixelBuffers.add(out);
}
await withVoidCallback((cb) {
Renderer_endFrameRenderThread(renderer, cb);
});
await withVoidCallback((cb) {
Engine_flushAndWaitRenderThead(app.engine!, cb);
});
await withVoidCallback((cb) {
Engine_destroyFenceRenderThread(app.engine!, fence, cb);
});
// await withVoidCallback((cb) { // await withVoidCallback((cb) {
// if (renderTarget != null) { // Renderer_renderRenderThread(renderer, view.view, cb);
// Viewer_captureRenderTargetRenderThread(
// _viewer!,
// view!.view,
// swapChain!.swapChain,
// renderTarget.renderTarget,
// out.address,
// useFence,
// cb);
// } else {
// Viewer_captureRenderThread(_viewer!, view!.view, swapChain!.swapChain,
// out.address, useFence, cb);
// }
// }); // });
return pixelBuffers; // final out = Uint8List(length);
} // await withVoidCallback((cb) {
// Renderer_readPixelsRenderThread(
// renderer,
// view.view,
// renderTarget!.renderTarget,
// TPixelDataFormat.PIXELDATAFORMAT_RGBA,
// TPixelDataType.PIXELDATATYPE_UBYTE,
// out.address,
// cb);
// });
// pixelBuffers.add(out);
// }
// await withVoidCallback((cb) {
// Renderer_endFrameRenderThread(renderer, cb);
// });
// await withVoidCallback((cb) {
// Engine_flushAndWaitRenderThead(app.engine!, cb);
// });
// await withVoidCallback((cb) {
// Engine_destroyFenceRenderThread(app.engine!, fence, cb);
// });
// // await withVoidCallback((cb) {
// // if (renderTarget != null) {
// // Viewer_captureRenderTargetRenderThread(
// // _viewer!,
// // view!.view,
// // swapChain!.swapChain,
// // renderTarget.renderTarget,
// // out.address,
// // useFence,
// // cb);
// // } else {
// // Viewer_captureRenderThread(_viewer!, view!.view, swapChain!.swapChain,
// // out.address, useFence, cb);
// // }
// // });
// return pixelBuffers;
// }
double _msPerFrame = 1000.0 / 60.0; double _msPerFrame = 1000.0 / 60.0;
@@ -225,7 +232,6 @@ class ThermionViewerFFI extends ThermionViewer {
@override @override
Future setFrameRate(int framerate) async { Future setFrameRate(int framerate) async {
_msPerFrame = 1000.0 / framerate; _msPerFrame = 1000.0 / framerate;
set_frame_interval_render_thread(_viewer!, _msPerFrame);
} }
final _onDispose = <Future Function()>[]; final _onDispose = <Future Function()>[];
@@ -238,20 +244,14 @@ class ThermionViewerFFI extends ThermionViewer {
/// ///
@override @override
Future dispose() async { Future dispose() async {
if (_viewer == null) {
throw Exception("Viewer has already been disposed.");
}
_disposing = true; _disposing = true;
await setRendering(false); await setRendering(false);
await destroyAssets(); await destroyAssets();
for (final mInstance in _materialInstances) { for (final mInstance in _materialInstances) {
await mInstance.dispose(); await mInstance.destroy();
} }
await destroyLights(); await destroyLights();
_sceneManager = null;
_viewer = null;
for (final callback in _onDispose) { for (final callback in _onDispose) {
await callback.call(); await callback.call();
} }
@@ -310,34 +310,39 @@ class ThermionViewerFFI extends ThermionViewer {
/// ///
@override @override
Future loadSkybox(String skyboxPath) async { Future loadSkybox(String skyboxPath) async {
final pathPtr = skyboxPath.toNativeUtf8(allocator: allocator).cast<Char>(); var data = await _loadAsset(skyboxPath);
await withVoidCallback((cb) { skybox = await withPointerCallback<TSkybox>((cb) {
Viewer_loadSkyboxRenderThread(_viewer!, pathPtr, cb); Engine_buildSkyboxRenderThread(
app.engine, data.address, data.length, cb, nullptr);
}); });
Scene_setSkybox(scene.scene, skybox!);
allocator.free(pathPtr);
} }
/// Future<Uint8List> _loadAsset(String path) async {
/// if (path.startsWith("file://")) {
/// return File(path.replaceAll("file://", "")).readAsBytesSync();
@override
Future createIbl(double r, double g, double b, double intensity) async {
create_ibl(_viewer!, r, g, b, intensity);
} }
if (path.startsWith("asset://")) {
throw UnimplementedError();
}
throw UnimplementedError();
}
Pointer<TIndirectLight>? indirectLight;
Pointer<TSkybox>? skybox;
/// ///
/// ///
/// ///
@override @override
Future loadIbl(String lightingPath, {double intensity = 30000}) async { Future loadIbl(String lightingPath, {double intensity = 30000}) async {
final pathPtr = var data = await _loadAsset(lightingPath);
lightingPath.toNativeUtf8(allocator: allocator).cast<Char>(); indirectLight = await withPointerCallback<TIndirectLight>((cb) {
Engine_buildIndirectLightRenderThread(
await withVoidCallback((cb) { app.engine, data.address, data.length, intensity, cb, nullptr);
Viewer_loadIblRenderThread(_viewer!, pathPtr, intensity, cb);
}); });
Scene_setIndirectLight(scene.scene, indirectLight!);
} }
/// ///
@@ -345,12 +350,10 @@ class ThermionViewerFFI extends ThermionViewer {
/// ///
@override @override
Future rotateIbl(Matrix3 rotationMatrix) async { Future rotateIbl(Matrix3 rotationMatrix) async {
var floatPtr = allocator<Float>(9); if (indirectLight == null) {
for (int i = 0; i < 9; i++) { throw Exception("No IBL loaded");
floatPtr[i] = rotationMatrix.storage[i];
} }
rotate_ibl(_viewer!, floatPtr); IndirectLight_setRotation(indirectLight!, rotationMatrix.storage.address);
allocator.free(floatPtr);
} }
/// ///
@@ -358,9 +361,11 @@ class ThermionViewerFFI extends ThermionViewer {
/// ///
@override @override
Future removeSkybox() async { Future removeSkybox() async {
await withVoidCallback((cb) { if (skybox != null) {
Viewer_removeSkyboxRenderThread(_viewer!, cb); await withVoidCallback(
}); (cb) => Engine_destroySkyboxRenderThread(app.engine, skybox!, cb));
skybox = null;
}
} }
/// ///
@@ -368,9 +373,11 @@ class ThermionViewerFFI extends ThermionViewer {
/// ///
@override @override
Future removeIbl() async { Future removeIbl() async {
await withVoidCallback((cb) { if (indirectLight != null) {
Viewer_removeIblRenderThread(_viewer!, cb); await withVoidCallback((cb) => Engine_destroyIndirectLightRenderThread(
}); app.engine, indirectLight!, cb));
indirectLight = null;
}
} }
@override @override
@@ -408,35 +415,38 @@ class ThermionViewerFFI extends ThermionViewer {
return addDirectLight(directLight); return addDirectLight(directLight);
} }
final _lights = <ThermionEntity>{};
/// ///
/// ///
/// ///
@override @override
Future<ThermionEntity> addDirectLight(DirectLight directLight) async { Future<ThermionEntity> addDirectLight(DirectLight directLight) async {
var entity = await withIntCallback((cb) { var entity = LightManager_createLight(
SceneManager_addLightRenderThread( app.lightManager, TLightType.values[directLight.type.index]);
_sceneManager!,
directLight.type.index,
directLight.color,
directLight.intensity,
directLight.position.x,
directLight.position.y,
directLight.position.z,
directLight.direction.x,
directLight.direction.y,
directLight.direction.z,
directLight.falloffRadius,
directLight.spotLightConeInner,
directLight.spotLightConeOuter,
directLight.sunAngularRadius,
directLight.sunHaloSize,
directLight.sunHaloFallof,
directLight.castShadows,
cb);
});
if (entity == FILAMENT_ASSET_ERROR) { if (entity == FILAMENT_ASSET_ERROR) {
throw Exception("Failed to add light to scene"); throw Exception("Failed to add light to scene");
} }
LightManager_setColor(app.lightManager, entity, directLight.color);
LightManager_setIntensity(app.lightManager, entity, directLight.intensity);
LightManager_setPosition(app.lightManager, entity, directLight.position.x,
directLight.position.y, directLight.position.z);
LightManager_setDirection(app.lightManager, entity, directLight.direction.x,
directLight.direction.y, directLight.direction.z);
LightManager_setFalloff(
app.lightManager, entity, directLight.falloffRadius);
LightManager_setSpotLightCone(app.lightManager, entity,
directLight.spotLightConeInner, directLight.spotLightConeOuter);
// LightManager_setSunAngularRadius(app.lightManager, entity, directLight.spotLightConeInner, directLight.spotLightConeOuter);
// LightManager_setSunHaloSize(app.lightManager, entity, directLight.spotLightConeInner, directLight.spotLightConeOuter);
// LightManager_setSunHaloFalloff(app.lightManager, entity, directLight.spotLightConeInner, directLight.spotLightConeOuter);
LightManager_setShadowCaster(
app.lightManager, entity, directLight.castShadows);
Scene_addEntity(scene.scene, entity);
_lights.add(entity);
return entity; return entity;
} }
@@ -445,9 +455,9 @@ class ThermionViewerFFI extends ThermionViewer {
/// ///
@override @override
Future removeLight(ThermionEntity entity) async { Future removeLight(ThermionEntity entity) async {
await withVoidCallback((cb) { Scene_removeEntity(scene.scene, entity);
SceneManager_removeLightRenderThread(_sceneManager!, entity, cb); LightManager_destroyLight(app.lightManager, entity);
}); _lights.remove(entity);
} }
/// ///
@@ -455,34 +465,23 @@ class ThermionViewerFFI extends ThermionViewer {
/// ///
@override @override
Future destroyLights() async { Future destroyLights() async {
await withVoidCallback((cb) { for (final light in _lights) {
SceneManager_destroyLightsRenderThread(_sceneManager!, cb); await removeLight(light);
});
} }
}
final _assets = <ThermionAsset>{};
/// ///
/// ///
/// ///
@override @override
Future<ThermionAsset> loadGlb(String path, Future<ThermionAsset> loadGlb(String path,
{bool unlit = false, int numInstances = 1, bool keepData = false}) async { {int numInstances = 1, bool keepData = false}) async {
if (unlit) { final data = await assetLoader(path);
throw Exception("Not yet implemented");
}
final pathPtr = path.toNativeUtf8(allocator: allocator).cast<Char>();
var asset = await withPointerCallback<TSceneAsset>((callback) =>
SceneManager_loadGlbRenderThread(
_sceneManager!, pathPtr, numInstances, keepData, callback));
allocator.free(pathPtr); return loadGlbFromBuffer(data,
if (asset == nullptr) { numInstances: numInstances, keepData: keepData);
throw Exception("An error occurred loading the asset at $path");
}
var thermionAsset = FFIAsset(
asset, _sceneManager!, app.engine!, _unlitMaterialProvider!, this);
return thermionAsset;
} }
/// ///
@@ -490,37 +489,29 @@ class ThermionViewerFFI extends ThermionViewer {
/// ///
@override @override
Future<ThermionAsset> loadGlbFromBuffer(Uint8List data, Future<ThermionAsset> loadGlbFromBuffer(Uint8List data,
{bool unlit = false, {int numInstances = 1,
int numInstances = 1,
bool keepData = false, bool keepData = false,
int priority = 4, int priority = 4,
int layer = 0, int layer = 0,
bool loadResourcesAsync = false}) async { bool loadResourcesAsync = false}) async {
if (unlit) { var asset = SceneAsset_loadGlb(
throw Exception("Not yet implemented"); app.gltfAssetLoader,
} app.gltfResourceLoader,
app.engine,
if (layer < 0 || layer > 6) { app.nameComponentManager,
throw Exception("Layer must be between 0 and 6");
}
var assetPtr = await withPointerCallback<TSceneAsset>((callback) =>
SceneManager_loadGlbFromBufferRenderThread(
_sceneManager!,
data.address, data.address,
data.length, data.length,
numInstances, numInstances);
keepData,
priority,
layer,
loadResourcesAsync,
callback));
if (assetPtr == nullptr) { if (asset == nullptr) {
throw Exception("An error occurred loading GLB from buffer"); throw Exception("An error occurred loading the asset");
} }
return FFIAsset(
assetPtr, _sceneManager!, app.engine!, _unlitMaterialProvider!, this); var thermionAsset = FFIAsset(asset, app);
_assets.add(thermionAsset);
return thermionAsset;
} }
/// ///
@@ -1694,8 +1685,7 @@ class ThermionViewerFFI extends ThermionViewer {
/// ///
@override @override
Future<v64.Aabb3> getRenderableBoundingBox(ThermionEntity entityId) async { Future<v64.Aabb3> getRenderableBoundingBox(ThermionEntity entityId) async {
final result = final result = RenderableManager_getAabb(app.renderableManager, entityId);
SceneManager_getRenderableBoundingBox(_sceneManager!, entityId);
return v64.Aabb3.centerAndHalfExtents( return v64.Aabb3.centerAndHalfExtents(
Vector3(result.centerX, result.centerY, result.centerZ), Vector3(result.centerX, result.centerY, result.centerZ),
Vector3(result.halfExtentX, result.halfExtentY, result.halfExtentZ)); Vector3(result.halfExtentX, result.halfExtentY, result.halfExtentZ));
@@ -1706,10 +1696,11 @@ class ThermionViewerFFI extends ThermionViewer {
/// ///
@override @override
Future<v64.Aabb2> getViewportBoundingBox(ThermionEntity entityId) async { Future<v64.Aabb2> getViewportBoundingBox(ThermionEntity entityId) async {
final view = (await getViewAt(0)) as FFIView; throw UnimplementedError();
final result = get_bounding_box(_sceneManager!, view.view, entityId); // final view = (await getViewAt(0)) as FFIView;
return v64.Aabb2.minMax(v64.Vector2(result.minX, result.minY), // final result = get_bounding_box(_sceneManager!, view.view, entityId);
v64.Vector2(result.maxX, result.maxY)); // return v64.Aabb2.minMax(v64.Vector2(result.minX, result.minY),
// v64.Vector2(result.maxX, result.maxY));
} }
/// ///
@@ -8,7 +8,7 @@ export 'gltf.dart';
export 'light_options.dart'; export 'light_options.dart';
// repre handle that can be safely passed back to the rendering layer to manipulate an Entity // handle manipulate an Entity
typedef ThermionEntity = int; typedef ThermionEntity = int;
abstract class ThermionAsset { abstract class ThermionAsset {
@@ -66,15 +66,8 @@ abstract class ThermionAsset {
/// ///
Future<List<ThermionAsset>> getInstances(); Future<List<ThermionAsset>> getInstances();
/// Future setCastShadows(bool castShadows);
/// Adds all entities (renderable, lights and cameras) under [asset] to the scene. Future setReceiveShadows(bool castShadows);
///
Future addToScene();
///
/// Removes all entities (renderable, lights and cameras) under [asset] from the scene.
///
Future removeFromScene();
} }
enum Axis { enum Axis {
@@ -97,7 +97,7 @@ enum TransparencyMode {
abstract class Material { abstract class Material {
Future<MaterialInstance> createInstance(); Future<MaterialInstance> createInstance();
Future<bool> hasParameter(String propertyName); Future<bool> hasParameter(String propertyName);
Future dispose(); Future destroy();
} }
abstract class MaterialInstance { abstract class MaterialInstance {
@@ -146,5 +146,5 @@ abstract class MaterialInstance {
Future setTransparencyMode(TransparencyMode mode); Future setTransparencyMode(TransparencyMode mode);
Future dispose(); Future destroy();
} }
@@ -1,4 +1,6 @@
import 'package:thermion_dart/src/viewer/src/thermion_viewer_base.dart';
abstract class Scene { abstract class Scene {
Future add(covariant ThermionAsset asset);
Future remove(covariant ThermionAsset asset);
} }
@@ -40,8 +40,9 @@ abstract class ThermionViewer {
/// Render a single frame and return the captured image as a pixel buffer. /// Render a single frame and return the captured image as a pixel buffer.
/// ///
Future<List<Uint8List>> capture( Future<List<Uint8List>> capture(
covariant List<({View view, SwapChain? swapChain, RenderTarget? renderTarget})> targets); covariant List<
({View view, SwapChain? swapChain, RenderTarget? renderTarget})>
targets);
/// ///
/// ///
@@ -108,12 +109,6 @@ abstract class ThermionViewer {
/// ///
Future loadIbl(String lightingPath, {double intensity = 30000}); Future loadIbl(String lightingPath, {double intensity = 30000});
///
/// Creates a indirect light with the given color.
/// Only one indirect light can be active at any given time; if an indirect light has already been loaded, it will be replaced.
///
Future createIbl(double r, double g, double b, double intensity);
/// ///
/// Rotates the IBL & skybox. /// Rotates the IBL & skybox.
/// ///
+30 -20
View File
@@ -1,25 +1,31 @@
#pragma once #pragma once
#include <filament/Engine.h>
#include <filament/Renderer.h>
#include <filament/View.h>
#include <math/vec3.h>
#include <math/vec4.h>
#include <math/mat3.h>
#include <math/norm.h>
#include <fstream>
#include <iostream>
#include <string>
#include <chrono> #include <chrono>
#include <mutex>
#include <vector>
#include <map>
#include "scene/SceneManager.hpp" #include <filament/Renderer.h>
#include <filament/SwapChain.h>
#include <filament/View.h>
#include <filament/Viewport.h>
#include <filament/Camera.h>
#include <filament/Engine.h>
#include <filament/IndexBuffer.h>
#include <filament/Material.h>
#include <filament/MaterialInstance.h>
#include <filament/RenderableManager.h>
#include <filament/Scene.h>
#include <filament/TransformManager.h>
#include <filament/VertexBuffer.h>
#include "scene/AnimationManager.hpp"
namespace thermion namespace thermion
{ {
typedef std::chrono::time_point<std::chrono::high_resolution_clock> time_point_t; typedef std::chrono::time_point time_point_t;
using namespace std::chrono; using namespace std::chrono;
@@ -27,20 +33,24 @@ namespace thermion
{ {
public: public:
RenderTicker(filament::Renderer renderer, thermion::SceneManager sceneManager) : mRenderer(renderer), mSceneManager(sceneManager) { } RenderTicker(filament::Renderer *renderer) : mRenderer(renderer) { }
~RenderTicker(); ~RenderTicker();
void render( void render(
uint64_t frameTimeInNanos uint64_t frameTimeInNanos
); );
void setRenderable(SwapChain *swapChain, View **view, uint8_t numViews); void setRenderable(filament::SwapChain *swapChain, filament::View **view, uint8_t numViews);
void addAnimationManager(AnimationManager* animationManager);
void removeAnimationManager(AnimationManager* animationManager);
private: private:
std::mutex mMutex; std::mutex mMutex;
Renderer *mRenderer = nullptr; filament::Renderer *mRenderer = nullptr;
SceneManager *mSceneManager = nullptr; std::vector<AnimationManager*> mAnimationManagers;
std::vector<SwapChain*> mSwapChains; std::vector<filament::SwapChain*> mSwapChains;
std::map<SwapChain*, std::vector<View*>> mRenderable; std::map<filament::SwapChain*, std::vector<filament::View*>> mRenderable;
}; };
@@ -8,6 +8,8 @@ extern "C"
{ {
#endif #endif
EMSCRIPTEN_KEEPALIVE TAnimationManager *AnimationManager_create(TEngine *tEngine);
EMSCRIPTEN_KEEPALIVE void AnimationManager_addAnimationComponent(TAnimationManager *tAnimationManager, EntityId entityId); EMSCRIPTEN_KEEPALIVE void AnimationManager_addAnimationComponent(TAnimationManager *tAnimationManager, EntityId entityId);
EMSCRIPTEN_KEEPALIVE void AnimationManager_removeAnimationComponent(TAnimationManager *tAnimationManager, EntityId entityId); EMSCRIPTEN_KEEPALIVE void AnimationManager_removeAnimationComponent(TAnimationManager *tAnimationManager, EntityId entityId);
@@ -43,6 +43,7 @@ EMSCRIPTEN_KEEPALIVE void Engine_flushAndWait(TEngine *tEngine);
EMSCRIPTEN_KEEPALIVE TMaterial *Engine_buildMaterial(TEngine *tEngine, const uint8_t* materialData, size_t length); EMSCRIPTEN_KEEPALIVE TMaterial *Engine_buildMaterial(TEngine *tEngine, const uint8_t* materialData, size_t length);
EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterial(TEngine *tEngine, TMaterial *tMaterial); EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterial(TEngine *tEngine, TMaterial *tMaterial);
EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterialInstance(TEngine *tEngine, TMaterialInstance *tMaterialInstance);
EMSCRIPTEN_KEEPALIVE TScene *Engine_createScene(TEngine *tEngine); EMSCRIPTEN_KEEPALIVE TScene *Engine_createScene(TEngine *tEngine);
EMSCRIPTEN_KEEPALIVE TSkybox *Engine_buildSkybox(TEngine *tEngine, uint8_t* ktxData, size_t length, void(*onTextureUploadComplete)()); EMSCRIPTEN_KEEPALIVE TSkybox *Engine_buildSkybox(TEngine *tEngine, uint8_t* ktxData, size_t length, void(*onTextureUploadComplete)());
EMSCRIPTEN_KEEPALIVE TIndirectLight *Engine_buildIndirectLight(TEngine *tEngine, uint8_t* ktxData, size_t length, float intensity, void(*onTextureUploadComplete)()); EMSCRIPTEN_KEEPALIVE TIndirectLight *Engine_buildIndirectLight(TEngine *tEngine, uint8_t* ktxData, size_t length, float intensity, void(*onTextureUploadComplete)());
@@ -12,7 +12,7 @@ extern "C"
{ {
#endif #endif
EMSCRIPTEN_KEEPALIVE void IndirectLight_setRotation(TIndirectLight TIndirectLight, double3x3 rotation); EMSCRIPTEN_KEEPALIVE void IndirectLight_setRotation(TIndirectLight *tIndirectLight, double *rotation);
#ifdef __cplusplus #ifdef __cplusplus
} }
@@ -9,11 +9,19 @@ extern "C"
{ {
#endif #endif
enum TLightType {
LIGHT_TYPE_SUN,
LIGHT_TYPE_DIRECTIONAL,
LIGHT_TYPE_POINT,
LIGHT_TYPE_FOCUSED_SPOT,
LIGHT_TYPE_SPOT
};
EMSCRIPTEN_KEEPALIVE void LightManager_setPosition(TLightManager *tLightManager, EntityId light, double x, double y, double z); EMSCRIPTEN_KEEPALIVE void LightManager_setPosition(TLightManager *tLightManager, EntityId light, double x, double y, double z);
EMSCRIPTEN_KEEPALIVE void LightManager_setDirection(TLightManager *tLightManager, EntityId light, double x, double y, double z); EMSCRIPTEN_KEEPALIVE void LightManager_setDirection(TLightManager *tLightManager, EntityId light, double x, double y, double z);
EMSCRIPTEN_KEEPALIVE int LightManager_createLight(TLightManager *tLightManager, EntityId entity, int type); EMSCRIPTEN_KEEPALIVE int LightManager_createLight(TLightManager *tLightManager, TLightType tLightTtype);
EMSCRIPTEN_KEEPALIVE void LightManager_destroyLight(TLightManager *tLightManager, EntityId entity); EMSCRIPTEN_KEEPALIVE void LightManager_destroyLight(TLightManager *tLightManager, EntityId entity);
EMSCRIPTEN_KEEPALIVE void LightManager_setColor(TLightManager *tLightManager, EntityId entity, double r, double g, double b); EMSCRIPTEN_KEEPALIVE void LightManager_setColor(TLightManager *tLightManager, EntityId entity, float colorTemperature);
EMSCRIPTEN_KEEPALIVE void LightManager_setIntensity(TLightManager *tLightManager, EntityId entity, double intensity); EMSCRIPTEN_KEEPALIVE void LightManager_setIntensity(TLightManager *tLightManager, EntityId entity, double intensity);
EMSCRIPTEN_KEEPALIVE void LightManager_setFalloff(TLightManager *tLightManager, EntityId entity, double falloff); EMSCRIPTEN_KEEPALIVE void LightManager_setFalloff(TLightManager *tLightManager, EntityId entity, double falloff);
EMSCRIPTEN_KEEPALIVE void LightManager_setSpotLightCone(TLightManager *tLightManager, EntityId entity, double inner, double outer); EMSCRIPTEN_KEEPALIVE void LightManager_setSpotLightCone(TLightManager *tLightManager, EntityId entity, double inner, double outer);
@@ -7,7 +7,7 @@
extern "C" extern "C"
{ {
#endif #endif
EMSCRIPTEN_KEEPALIVE TNameComponentManager *NameComponentManager_create();
EMSCRIPTEN_KEEPALIVE const char *NameComponentManager_getName(TNameComponentManager *tNameComponentManager, EntityId entity); EMSCRIPTEN_KEEPALIVE const char *NameComponentManager_getName(TNameComponentManager *tNameComponentManager, EntityId entity);
@@ -8,7 +8,10 @@ extern "C"
{ {
#endif #endif
EMSCRIPTEN_KEEPALIVE TRenderTicker *RenderTicker_create(TRenderer *tRenderer, TSceneManager *tSceneManager); EMSCRIPTEN_KEEPALIVE TRenderTicker *RenderTicker_create(TRenderer *tRenderer);
EMSCRIPTEN_KEEPALIVE void RenderTicker_addAnimationManager(TRenderTicker *tRenderTicker, TAnimationManager *tAnimationManager);
EMSCRIPTEN_KEEPALIVE void RenderTicker_removeAnimationManager(TRenderTicker *tRenderTicker, TAnimationManager *tAnimationManager);
EMSCRIPTEN_KEEPALIVE void RenderTicker_render(TRenderTicker *tRenderTicker, uint64_t frameTimeInNanos); EMSCRIPTEN_KEEPALIVE void RenderTicker_render(TRenderTicker *tRenderTicker, uint64_t frameTimeInNanos);
EMSCRIPTEN_KEEPALIVE void RenderTicker_setRenderable(TRenderTicker *tFilamentRender, TSwapChain *swapChain, TView **views, uint8_t numViews); EMSCRIPTEN_KEEPALIVE void RenderTicker_setRenderable(TRenderTicker *tFilamentRender, TSwapChain *swapChain, TView **views, uint8_t numViews);
@@ -20,6 +20,7 @@ extern "C"
EMSCRIPTEN_KEEPALIVE void RenderableManager_setReceiveShadows(TRenderableManager *tRenderableManager, EntityId entityId, bool receiveShadows); EMSCRIPTEN_KEEPALIVE void RenderableManager_setReceiveShadows(TRenderableManager *tRenderableManager, EntityId entityId, bool receiveShadows);
EMSCRIPTEN_KEEPALIVE bool RenderableManager_isShadowReceiver(TRenderableManager *tRenderableManager, EntityId entityId); EMSCRIPTEN_KEEPALIVE bool RenderableManager_isShadowReceiver(TRenderableManager *tRenderableManager, EntityId entityId);
EMSCRIPTEN_KEEPALIVE bool RenderableManager_getFogEnabled(TRenderableManager *tRenderableManager, EntityId entityId); EMSCRIPTEN_KEEPALIVE bool RenderableManager_getFogEnabled(TRenderableManager *tRenderableManager, EntityId entityId);
EMSCRIPTEN_KEEPALIVE Aabb3 RenderableManager_getAabb(TRenderableManager *tRenderableManager, EntityId entityId);
#ifdef __cplusplus #ifdef __cplusplus
} }
@@ -16,6 +16,7 @@ extern "C"
EMSCRIPTEN_KEEPALIVE void Scene_addEntity(TScene* tScene, EntityId entityId); EMSCRIPTEN_KEEPALIVE void Scene_addEntity(TScene* tScene, EntityId entityId);
EMSCRIPTEN_KEEPALIVE void Scene_removeEntity(TScene* tScene, EntityId entityId);
EMSCRIPTEN_KEEPALIVE void Scene_setSkybox(TScene* tScene, TSkybox *skybox); EMSCRIPTEN_KEEPALIVE void Scene_setSkybox(TScene* tScene, TSkybox *skybox);
EMSCRIPTEN_KEEPALIVE void Scene_setIndirectLight(TScene* tScene, TIndirectLight *tIndirectLight); EMSCRIPTEN_KEEPALIVE void Scene_setIndirectLight(TScene* tScene, TIndirectLight *tIndirectLight);
EMSCRIPTEN_KEEPALIVE void Scene_addFilamentAsset(TScene* tScene, TFilamentAsset *asset); EMSCRIPTEN_KEEPALIVE void Scene_addFilamentAsset(TScene* tScene, TFilamentAsset *asset);
@@ -24,7 +24,29 @@ extern "C"
TMaterialInstance **materialInstances, TMaterialInstance **materialInstances,
int materialInstanceCount int materialInstanceCount
); );
EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneAsset_loadGlb(
TGltfAssetLoader *tAssetLoader,
TGltfResourceLoader *tResourceLoader,
TEngine *tEngine,
TNameComponentManager *tNameComponentManager,
uint8_t *data,
size_t length,
size_t numInstances
);
EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneAsset_loadGltf(
TGltfAssetLoader *tAssetLoader,
TGltfResourceLoader *tResourceLoader,
TEngine *tEngine,
TNameComponentManager *tNameComponentManager,
uint8_t *data,
size_t length,
size_t numInstances
);
EMSCRIPTEN_KEEPALIVE void SceneAsset_addToScene(TSceneAsset *tSceneAsset, TScene *tScene); EMSCRIPTEN_KEEPALIVE void SceneAsset_addToScene(TSceneAsset *tSceneAsset, TScene *tScene);
EMSCRIPTEN_KEEPALIVE void SceneAsset_removeFromScene(TSceneAsset *tSceneAsset, TScene *tScene);
EMSCRIPTEN_KEEPALIVE EntityId SceneAsset_getEntity(TSceneAsset *tSceneAsset); EMSCRIPTEN_KEEPALIVE EntityId SceneAsset_getEntity(TSceneAsset *tSceneAsset);
EMSCRIPTEN_KEEPALIVE int SceneAsset_getChildEntityCount(TSceneAsset* tSceneAsset); EMSCRIPTEN_KEEPALIVE int SceneAsset_getChildEntityCount(TSceneAsset* tSceneAsset);
EMSCRIPTEN_KEEPALIVE void SceneAsset_getChildEntities(TSceneAsset* tSceneAsset, EntityId *out); EMSCRIPTEN_KEEPALIVE void SceneAsset_getChildEntities(TSceneAsset* tSceneAsset, EntityId *out);
@@ -20,6 +20,8 @@ namespace thermion
EMSCRIPTEN_KEEPALIVE void RenderTicker_renderRenderThread(TRenderTicker *tRenderTicker, uint64_t frameTimeInNanos,); EMSCRIPTEN_KEEPALIVE void RenderTicker_renderRenderThread(TRenderTicker *tRenderTicker, uint64_t frameTimeInNanos,);
// EMSCRIPTEN_KEEPALIVE void RenderLoop_addTask(TRenderLoop* tRenderLoop, void (*task)()); // EMSCRIPTEN_KEEPALIVE void RenderLoop_addTask(TRenderLoop* tRenderLoop, void (*task)());
EMSCRIPTEN_KEEPALIVE void AnimationManager_createRenderThread(TEngine *tEngine, TScene *tScene, void (*onComplete)(TAnimationManager *));
EMSCRIPTEN_KEEPALIVE void Engine_createRenderThread( EMSCRIPTEN_KEEPALIVE void Engine_createRenderThread(
TBackend backend, TBackend backend,
void* platform, void* platform,
@@ -36,6 +38,7 @@ namespace thermion
EMSCRIPTEN_KEEPALIVE void Engine_buildMaterialRenderThread(TEngine *tEngine, const uint8_t *materialData, size_t length, void (*onComplete)(TMaterial *)); EMSCRIPTEN_KEEPALIVE void Engine_buildMaterialRenderThread(TEngine *tEngine, const uint8_t *materialData, size_t length, void (*onComplete)(TMaterial *));
EMSCRIPTEN_KEEPALIVE void Engine_destroySwapChainRenderThread(TEngine *tEngine, TSwapChain *tSwapChain, void (*onComplete)()); EMSCRIPTEN_KEEPALIVE void Engine_destroySwapChainRenderThread(TEngine *tEngine, TSwapChain *tSwapChain, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterialRenderThread(TEngine *tEngine, TMaterial *tMaterial, void (*onComplete)()); EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterialRenderThread(TEngine *tEngine, TMaterial *tMaterial, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterialInstanceRenderThread(TEngine *tEngine, TMaterialInstance *tMaterialInstance, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void Engine_destroySkyboxRenderThread(TEngine *tEngine, TSkybox *tSkybox, void (*onComplete)()); EMSCRIPTEN_KEEPALIVE void Engine_destroySkyboxRenderThread(TEngine *tEngine, TSkybox *tSkybox, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void Engine_destroyIndirectLightRenderThread(TEngine *tEngine, TIndirectLight *tIndirectLight, void (*onComplete)()); EMSCRIPTEN_KEEPALIVE void Engine_destroyIndirectLightRenderThread(TEngine *tEngine, TIndirectLight *tIndirectLight, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void Texture_buildRenderThread(TEngine *engine, EMSCRIPTEN_KEEPALIVE void Texture_buildRenderThread(TEngine *engine,
@@ -8,5 +8,5 @@ GIZMO_PACKAGE:
GIZMO_GIZMO_OFFSET: GIZMO_GIZMO_OFFSET:
.int 0 .int 0
GIZMO_GIZMO_SIZE: GIZMO_GIZMO_SIZE:
.int 45584 .int 45867
@@ -8,5 +8,5 @@ _GIZMO_PACKAGE:
_GIZMO_GIZMO_OFFSET: _GIZMO_GIZMO_OFFSET:
.int 0 .int 0
_GIZMO_GIZMO_SIZE: _GIZMO_GIZMO_SIZE:
.int 45584 .int 45867
Binary file not shown.
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -8,5 +8,5 @@ GRID_PACKAGE:
GRID_GRID_OFFSET: GRID_GRID_OFFSET:
.int 0 .int 0
GRID_GRID_SIZE: GRID_GRID_SIZE:
.int 52130 .int 52018
@@ -8,5 +8,5 @@ _GRID_PACKAGE:
_GRID_GRID_OFFSET: _GRID_GRID_OFFSET:
.int 0 .int 0
_GRID_GRID_SIZE: _GRID_GRID_SIZE:
.int 52130 .int 52018
Binary file not shown.
File diff suppressed because it is too large Load Diff
@@ -8,5 +8,5 @@ IMAGE_PACKAGE:
IMAGE_IMAGE_OFFSET: IMAGE_IMAGE_OFFSET:
.int 0 .int 0
IMAGE_IMAGE_SIZE: IMAGE_IMAGE_SIZE:
.int 56612 .int 63850
@@ -8,5 +8,5 @@ _IMAGE_PACKAGE:
_IMAGE_IMAGE_OFFSET: _IMAGE_IMAGE_OFFSET:
.int 0 .int 0
_IMAGE_IMAGE_SIZE: _IMAGE_IMAGE_SIZE:
.int 56612 .int 63850
Binary file not shown.
File diff suppressed because it is too large Load Diff
@@ -8,5 +8,5 @@ UNLIT_PACKAGE:
UNLIT_UNLIT_OFFSET: UNLIT_UNLIT_OFFSET:
.int 0 .int 0
UNLIT_UNLIT_SIZE: UNLIT_UNLIT_SIZE:
.int 106370 .int 157994
@@ -8,5 +8,5 @@ _UNLIT_PACKAGE:
_UNLIT_UNLIT_OFFSET: _UNLIT_UNLIT_OFFSET:
.int 0 .int 0
_UNLIT_UNLIT_SIZE: _UNLIT_UNLIT_SIZE:
.int 106370 .int 157994
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: UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_OFFSET:
.int 0 .int 0
UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE: UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE:
.int 45632 .int 45907
@@ -8,5 +8,5 @@ _UNLIT_FIXED_SIZE_PACKAGE:
_UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_OFFSET: _UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_OFFSET:
.int 0 .int 0
_UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE: _UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE:
.int 45632 .int 45907
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+55 -24
View File
@@ -1,3 +1,5 @@
#if __APPLE__ #if __APPLE__
#include "TargetConditionals.h" #include "TargetConditionals.h"
#endif #endif
@@ -6,35 +8,31 @@
#pragma comment(lib, "Ws2_32.lib") #pragma comment(lib, "Ws2_32.lib")
#endif #endif
#include <filament/Camera.h> #include <math/mat4.h>
#include <filament/SwapChain.h> #include <utils/EntityManager.h>
#include <backend/DriverEnums.h> #include <utils/Panic.h>
#include <backend/platforms/OpenGLPlatform.h> #include <utils/Systrace.h>
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
#include <backend/platforms/PlatformWebGL.h> #include <emscripten.h>
#include <emscripten/emscripten.h>
#include <emscripten/bind.h>
#include <emscripten/html5.h> #include <emscripten/html5.h>
#include <emscripten/threading.h> #include <emscripten/threading.h>
#include <emscripten/val.h> #include <filament/webgl/WebEngine.h>
#include <sys/types.h>
#endif #endif
#include <filament/Box.h>
#include <filament/Camera.h>
#include <filament/ColorGrading.h>
#include <filament/Engine.h> #include <filament/Engine.h>
#include <filament/IndexBuffer.h>
#include <filament/Options.h> #include <filament/IndirectLight.h>
#include <filament/Renderer.h> #include <filament/LightManager.h>
#include <filament/View.h> #include <filament/Material.h>
#include <filament/MaterialInstance.h>
#include <filament/RenderableManager.h> #include <filament/RenderableManager.h>
#include <filament/Scene.h>
#include <iostream> #include <filament/Skybox.h>
#include <streambuf> #include <filament/TransformManager.h>
#include <sstream> #include <filament/VertexBuffer.h>
#include <istream>
#include <fstream>
#include <filesystem>
#include <mutex>
#include <iomanip>
#include <unordered_set>
#include "Log.hpp" #include "Log.hpp"
@@ -70,13 +68,32 @@ namespace thermion
} }
mRenderable[swapChain] = swapChainViews; mRenderable[swapChain] = swapChainViews;
// Keep track of the swapchains, so we can iterate them in the render method.
bool found = false;
for (auto existingSwapChain : mSwapChains) {
if (existingSwapChain == swapChain) {
found = true;
break;
} }
}
if (!found) {
mSwapChains.push_back(swapChain);
}
}
}
void RenderTicker::render(uint64_t frameTimeInNanos) void RenderTicker::render(uint64_t frameTimeInNanos)
{ {
std::lock_guard lock(mMutex); std::lock_guard lock(mMutex);
mSceneManager->update(); // Update all animation managers
for (auto animationManager : mAnimationManagers) {
if (animationManager) { // Check for nullptr just in case
animationManager->update(frameTimeInNanos * 1e-9);
}
}
for (auto swapChain : mSwapChains) for (auto swapChain : mSwapChains)
{ {
@@ -99,5 +116,19 @@ namespace thermion
#endif #endif
} }
void RenderTicker::addAnimationManager(AnimationManager* animationManager) {
std::lock_guard<std::mutex> lock(mMutex);
mAnimationManagers.push_back(animationManager);
}
void RenderTicker::removeAnimationManager(AnimationManager* animationManager) {
std::lock_guard<std::mutex> lock(mMutex);
auto it = std::find(mAnimationManagers.begin(), mAnimationManagers.end(), animationManager);
if (it != mAnimationManagers.end()) {
mAnimationManagers.erase(it);
}
}
RenderTicker::~RenderTicker() {}
} // namespace thermion } // namespace thermion
@@ -10,6 +10,13 @@ extern "C"
#include "c_api/TAnimationManager.h" #include "c_api/TAnimationManager.h"
EMSCRIPTEN_KEEPALIVE TAnimationManager *AnimationManager_create(TEngine *tEngine, TScene *tScene) {
auto *engine = reinterpret_cast<filament::Engine *>(tEngine);
auto *scene = reinterpret_cast<filament::Scene *>(tScene);
auto animationManager = new AnimationManager(engine, scene);
return reinterpret_cast<TAnimationManager *>(animationManager);
}
EMSCRIPTEN_KEEPALIVE void AnimationManager_addAnimationComponent(TAnimationManager *tAnimationManager, EntityId entityId) EMSCRIPTEN_KEEPALIVE void AnimationManager_addAnimationComponent(TAnimationManager *tAnimationManager, EntityId entityId)
{ {
auto animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager); auto animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
@@ -162,6 +162,12 @@ namespace thermion
engine->destroy(material); engine->destroy(material);
} }
EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterialInstance(TEngine *tEngine, TMaterialInstance *tMaterialInstance) {
auto *engine = reinterpret_cast<Engine *>(tEngine);
auto *mi = reinterpret_cast<MaterialInstance *>(tMaterialInstance);
engine->destroy(mi);
}
EMSCRIPTEN_KEEPALIVE void Engine_destroyTexture(TEngine *tEngine, TTexture *tTexture) EMSCRIPTEN_KEEPALIVE void Engine_destroyTexture(TEngine *tEngine, TTexture *tTexture)
{ {
auto *engine = reinterpret_cast<Engine *>(tEngine); auto *engine = reinterpret_cast<Engine *>(tEngine);
@@ -24,13 +24,13 @@ namespace thermion
using namespace filament; using namespace filament;
#endif #endif
EMSCRIPTEN_KEEPALIVE void IndirectLight_setRotation(TIndirectLight *tIndirectLight, double3x3 rotation) EMSCRIPTEN_KEEPALIVE void IndirectLight_setRotation(TIndirectLight *tIndirectLight, double *rotation)
{ {
auto *indirectLight = reinterpret_cast<filament::IndirectLight *>(tIndirectLight); auto *indirectLight = reinterpret_cast<filament::IndirectLight *>(tIndirectLight);
const filament::math::mat3f fRotation { const filament::math::mat3f fRotation {
filament::math::float3 { rotation.col1.x, rotation.col1.y, rotation.col1.z }, filament::math::float3 { static_cast<float>(rotation[0]), static_cast<float>(rotation[1]), static_cast<float>(rotation[2]) },
filament::math::float3 { rotation.col2.x, rotation.col2.y, rotation.col2.z }, filament::math::float3 { static_cast<float>(rotation[3]), static_cast<float>(rotation[4]), static_cast<float>(rotation[5]) },
filament::math::float3 { rotation.col3.x, rotation.col3.y, rotation.col3.z }, filament::math::float3 { static_cast<float>(rotation[6]), static_cast<float>(rotation[7]), static_cast<float>(rotation[8]) },
}; };
indirectLight->setRotation(fRotation); indirectLight->setRotation(fRotation);
} }
@@ -1,10 +1,14 @@
#include <filament/LightManager.h> #include <filament/LightManager.h>
#include <utils/Entity.h> #include <utils/Entity.h>
#include <utils/EntityManager.h>
#include "c_api/APIExport.h" #include "c_api/APIExport.h"
#include "Log.hpp"
#include "c_api/TLightManager.h" #include "c_api/TLightManager.h"
#include "Log.hpp"
extern "C" { extern "C" {
EMSCRIPTEN_KEEPALIVE void LightManager_setPosition(TLightManager *tLightManager, EntityId light, double x, double y, double z) { EMSCRIPTEN_KEEPALIVE void LightManager_setPosition(TLightManager *tLightManager, EntityId light, double x, double y, double z) {
@@ -27,8 +31,9 @@ EMSCRIPTEN_KEEPALIVE void LightManager_setDirection(TLightManager *tLightManager
lightManager->setDirection(instance, filament::math::float3 { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z) }); lightManager->setDirection(instance, filament::math::float3 { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z) });
} }
EMSCRIPTEN_KEEPALIVE int LightManager_createLight(TLightManager *tLightManager, EntityId entity, int type) { EMSCRIPTEN_KEEPALIVE int LightManager_createLight(TEngine *tEngine, TLightManager *tLightManager, TLightType type) {
auto* lm = reinterpret_cast<filament::LightManager*>(tLightManager); auto *engine = reinterpret_cast<filament::Engine *>(tEngine);
auto *lightManager = reinterpret_cast<filament::LightManager*>(tLightManager);
filament::LightManager::Type lightType; filament::LightManager::Type lightType;
switch (type) { switch (type) {
@@ -41,9 +46,12 @@ EMSCRIPTEN_KEEPALIVE int LightManager_createLight(TLightManager *tLightManager,
} }
filament::LightManager::Builder builder(lightType); filament::LightManager::Builder builder(lightType);
return false; auto entity = utils::EntityManager::create();
// auto result = builder.build(*lm->getEngine(), utils::Entity::import(entity)); auto result = builder.build(*engine, utils::Entity::import(entity));
// return result == filament::LightManager::Result::Success ? 0 : -1; if(result != filament::LightManager::Result::Success) {
Log("Failed to create light");
}
return entity;
} }
EMSCRIPTEN_KEEPALIVE void LightManager_destroyLight(TLightManager *tLightManager, EntityId entity) { EMSCRIPTEN_KEEPALIVE void LightManager_destroyLight(TLightManager *tLightManager, EntityId entity) {
@@ -51,11 +59,13 @@ EMSCRIPTEN_KEEPALIVE void LightManager_destroyLight(TLightManager *tLightManager
lm->destroy(utils::Entity::import(entity)); lm->destroy(utils::Entity::import(entity));
} }
EMSCRIPTEN_KEEPALIVE void LightManager_setColor(TLightManager *tLightManager, EntityId entity, double r, double g, double b) { EMSCRIPTEN_KEEPALIVE void LightManager_setColor(TLightManager *tLightManager, EntityId entity, float colorTemperature) {
auto* lm = reinterpret_cast<filament::LightManager*>(tLightManager); auto* lm = reinterpret_cast<filament::LightManager*>(tLightManager);
auto color = filament::Color::cct(colorTemperature);
auto instance = lm->getInstance(utils::Entity::import(entity)); auto instance = lm->getInstance(utils::Entity::import(entity));
if (instance.isValid()) { if (instance.isValid()) {
lm->setColor(instance, {static_cast<float>(r), static_cast<float>(g), static_cast<float>(b)}); lm->setColor(instance, color);
} }
} }
@@ -8,6 +8,12 @@ extern "C"
{ {
#endif #endif
EMSCRIPTEN_KEEPALIVE TNameComponentManager *NameComponentManager_create()
{
auto *ncm = new utils::NameComponentManager(utils::EntityManager::get());
return reinterpret_cast<TNameComponentManager *>(ncm);
}
EMSCRIPTEN_KEEPALIVE const char *NameComponentManager_getName(TNameComponentManager *tNameComponentManager, EntityId entity) EMSCRIPTEN_KEEPALIVE const char *NameComponentManager_getName(TNameComponentManager *tNameComponentManager, EntityId entity)
{ {
auto ncm = reinterpret_cast<utils::NameComponentManager *>(tNameComponentManager); auto ncm = reinterpret_cast<utils::NameComponentManager *>(tNameComponentManager);
@@ -18,13 +18,24 @@ extern "C"
{ {
#include "c_api/TRenderTicker.hpp" #include "c_api/TRenderTicker.hpp"
EMSCRIPTEN_KEEPALIVE TRenderTicker *RenderTicker_create(TRenderer *tRenderer, TSceneManager *tSceneManager) { EMSCRIPTEN_KEEPALIVE TRenderTicker *RenderTicker_create(TRenderer *tRenderer) {
auto *renderer = reinterpret_cast<filament::Renderer *>(tRenderer); auto *renderer = reinterpret_cast<filament::Renderer *>(tRenderer);
auto *sceneManager = reinterpret_cast<thermion::SceneManager *>(tSceneManager); auto *renderTicker = new RenderTicker(renderer);
auto *renderTicker = new RenderTicker(renderer, sceneManager);
return reinterpret_cast<TRenderTicker *>(renderTicker); return reinterpret_cast<TRenderTicker *>(renderTicker);
} }
EMSCRIPTEN_KEEPALIVE void RenderTicker_addAnimationManager(TRenderTicker *tRenderTicker, TAnimationManager *tAnimationManager) {
auto *renderTicker = reinterpret_cast<RenderTicker *>(tRenderTicker);
auto *animationManager = reinterpret_cast<thermion::AnimationManager *>(tAnimationManager);
renderTicker->addAnimationManager(animationManager);
}
EMSCRIPTEN_KEEPALIVE void RenderTicker_removeAnimationManager(TRenderTicker *tRenderTicker, TAnimationManager *tAnimationManager) {
auto *renderTicker = reinterpret_cast<RenderTicker *>(tRenderTicker);
auto *animationManager = reinterpret_cast<thermion::AnimationManager *>(tAnimationManager);
renderTicker->removeAnimationManager(animationManager);
}
EMSCRIPTEN_KEEPALIVE void RenderTicker_render(TRenderTicker *tRenderTicker, uint64_t frameTimeInNanos) { EMSCRIPTEN_KEEPALIVE void RenderTicker_render(TRenderTicker *tRenderTicker, uint64_t frameTimeInNanos) {
auto *renderTicker = reinterpret_cast<RenderTicker *> auto *renderTicker = reinterpret_cast<RenderTicker *>
renderTicker->render(frameTimeInNanos); renderTicker->render(frameTimeInNanos);
@@ -120,5 +120,16 @@ namespace thermion
} }
return renderableManager->getFogEnabled(renderableInstance); return renderableManager->getFogEnabled(renderableInstance);
} }
EMSCRIPTEN_KEEPALIVE Aabb3 RenderableManager_getAabb(TRenderableManager *tRenderableManager, EntityId entityId) {
auto *renderableManager = reinterpret_cast<filament::RenderableManager *>(tRenderableManager);
const auto &entity = utils::Entity::import(entityId);
auto renderableInstance = renderableManager->getInstance(entity);
if (!renderableInstance.isValid()) {
return false;
}
auto box = rm.getAxisAlignedBoundingBox(instance);
return Aabb3{box.center.x, box.center.y, box.center.z, box.halfExtent.x, box.halfExtent.y, box.halfExtent.z};
}
} }
} }
@@ -30,6 +30,11 @@ namespace thermion
scene->addEntity(utils::Entity::import(entityId)); scene->addEntity(utils::Entity::import(entityId));
} }
EMSCRIPTEN_KEEPALIVE void Scene_removeEntity(TScene* tScene, EntityId entityId) {
auto *scene = reinterpret_cast<Scene *>(tScene);
scene->removeEntity(utils::Entity::import(entityId));
}
EMSCRIPTEN_KEEPALIVE void Scene_setSkybox(TScene* tScene, TSkybox *tSkybox) { EMSCRIPTEN_KEEPALIVE void Scene_setSkybox(TScene* tScene, TSkybox *tSkybox) {
auto *scene = reinterpret_cast<Scene *>(tScene); auto *scene = reinterpret_cast<Scene *>(tScene);
auto *skybox = reinterpret_cast<Skybox *>(tSkybox); auto *skybox = reinterpret_cast<Skybox *>(tSkybox);
@@ -1,4 +1,10 @@
#include <gltfio/AssetLoader.h>
#include <gltfio/ResourceLoader.h>
#include <utils/NameComponentManager.h>
#include "c_api/TGltfAssetLoader.h"
#include "c_api/TSceneAsset.h" #include "c_api/TSceneAsset.h"
#include "scene/SceneAsset.hpp" #include "scene/SceneAsset.hpp"
#include "scene/GltfSceneAsset.hpp" #include "scene/GltfSceneAsset.hpp"
@@ -59,12 +65,43 @@ extern "C"
} }
EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneAsset_loadGlb(
TGltfAssetLoader *tAssetLoader,
TGltfResourceLoader *tResourceLoader,
TEngine *tEngine,
TNameComponentManager *tNameComponentManager,
uint8_t *data,
size_t length,
size_t numInstances
) {
auto *engine = reinterpret_cast<filament::Engine *>(tEngine);
auto *nameComponentManager = reinterpret_cast<utils::NameComponentManager *>(tNameComponentManager);
auto *tFilamentAsset = GltfAssetLoader_load(tAssetLoader, tResourceLoader, data, length, numInstances);
auto *filamentAsset = reinterpret_cast<filament::gltfio::FilamentAsset *>(tFilamentAsset);
auto *assetLoader = reinterpret_cast<filament::gltfio::AssetLoader *>(tAssetLoader);
auto *resourceLoader = reinterpret_cast<filament::gltfio::ResourceLoader *>(tResourceLoader);
auto *sceneAsset = new GltfSceneAsset(
filamentAsset,
assetLoader,
engine,
nameComponentManager
);
return reinterpret_cast<TSceneAsset *>(sceneAsset);
}
EMSCRIPTEN_KEEPALIVE void SceneAsset_addToScene(TSceneAsset *tSceneAsset, TScene *tScene) { EMSCRIPTEN_KEEPALIVE void SceneAsset_addToScene(TSceneAsset *tSceneAsset, TScene *tScene) {
auto *asset = reinterpret_cast<SceneAsset*>(tSceneAsset); auto *asset = reinterpret_cast<SceneAsset*>(tSceneAsset);
auto *scene = reinterpret_cast<Scene*>(tScene); auto *scene = reinterpret_cast<Scene*>(tScene);
asset->addAllEntities(scene); asset->addAllEntities(scene);
} }
EMSCRIPTEN_KEEPALIVE void SceneAsset_removeFromScene(TSceneAsset *tSceneAsset, TScene *tScene) {
auto *asset = reinterpret_cast<SceneAsset*>(tSceneAsset);
auto *scene = reinterpret_cast<Scene*>(tScene);
asset->removeAllEntities(scene);
}
EMSCRIPTEN_KEEPALIVE EntityId SceneAsset_getEntity(TSceneAsset *tSceneAsset) { EMSCRIPTEN_KEEPALIVE EntityId SceneAsset_getEntity(TSceneAsset *tSceneAsset) {
auto *asset = reinterpret_cast<SceneAsset*>(tSceneAsset); auto *asset = reinterpret_cast<SceneAsset*>(tSceneAsset);
return utils::Entity::smuggle(asset->getEntity()); return utils::Entity::smuggle(asset->getEntity());
@@ -683,6 +683,16 @@ extern "C"
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
} }
EMSCRIPTEN_KEEPALIVE void AnimationManager_createRenderThread(TEngine *tEngine, TScene *tScene, void (*onComplete)(TAnimationManager *)) {
std::packaged_task<void()> lambda(
[=]() mutable
{
auto *animationManager = AnimationManager_create(tEngine, tScene);
callback(animationManager);
});
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void AnimationManager_updateBoneMatricesRenderThread( EMSCRIPTEN_KEEPALIVE void AnimationManager_updateBoneMatricesRenderThread(
TAnimationManager *tAnimationManager, TAnimationManager *tAnimationManager,
TSceneAsset *sceneAsset, TSceneAsset *sceneAsset,