expose methods for getting bone names

This commit is contained in:
Nick Fisher
2024-05-26 12:11:11 +08:00
parent 443a4ba0d4
commit 82f533e6b2
5 changed files with 115 additions and 4 deletions

View File

@@ -236,6 +236,15 @@ abstract class AbstractFilamentViewer {
Future<List<String>> getMorphTargetNames(
FilamentEntity entity, FilamentEntity childEntity);
///
/// Gets the names of all bones for the armature at [skinIndex] under the specified [entity].
///
Future<List<String>> getBoneNames(
FilamentEntity entity, { int skinIndex = 0});
///
/// Gets the names of all glTF animations embedded in the specified entity.
///
Future<List<String>> getAnimationNames(FilamentEntity entity);
///

View File

@@ -565,6 +565,27 @@ external double get_animation_duration(
int index,
);
@ffi.Native<ffi.Int Function(ffi.Pointer<ffi.Void>, EntityId, ffi.Int)>(
symbol: 'get_bone_count',
assetId: 'package:dart_filament/dart_filament.dart')
external int get_bone_count(
ffi.Pointer<ffi.Void> sceneManager,
int assetEntity,
int skinIndex,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId,
ffi.Pointer<ffi.Pointer<ffi.Char>>, ffi.Int)>(
symbol: 'get_bone_names',
assetId: 'package:dart_filament/dart_filament.dart')
external void get_bone_names(
ffi.Pointer<ffi.Void> sceneManager,
int assetEntity,
ffi.Pointer<ffi.Pointer<ffi.Char>> outPtr,
int skinIndex,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId, EntityId,
ffi.Pointer<ffi.Char>, ffi.Int)>(

View File

@@ -3,6 +3,7 @@ import 'dart:ffi';
import 'dart:io';
import 'dart:math';
import 'package:animation_tools_dart/animation_tools_dart.dart';
import 'package:dart_filament/dart_filament/compatibility/native/compatibility.dart';
import 'package:dart_filament/dart_filament/entities/filament_entity.dart';
import 'package:dart_filament/dart_filament/entities/gizmo.dart';
@@ -124,7 +125,7 @@ class FilamentViewer extends AbstractFilamentViewer {
_scene = SceneImpl(this);
await setCameraManipulatorOptions(zoomSpeed: 10.0);
final out = allocator<Int32>(3);
get_gizmo(_sceneManager!, out);
_gizmo = Gizmo(out[0], out[1], out[2], this);
@@ -422,6 +423,23 @@ class FilamentViewer extends AbstractFilamentViewer {
return names.cast<String>();
}
Future<List<String>> getBoneNames(FilamentEntity entity,
{int skinIndex = 0}) async {
var count = get_bone_count(_sceneManager!, entity, skinIndex);
var out = allocator<Pointer<Char>>(count);
for (int i = 0; i < count; i++) {
out[i] = allocator<Char>(255);
}
get_bone_names(_sceneManager!, entity, out, skinIndex);
var names = <String>[];
for (int i = 0; i < count; i++) {
var namePtr = out[i];
names.add(namePtr.cast<Utf8>().toDartString());
}
return names;
}
@override
Future<List<String>> getAnimationNames(FilamentEntity entity) async {
var animationCount = get_animation_count(_sceneManager!, entity);
@@ -461,6 +479,14 @@ class FilamentViewer extends AbstractFilamentViewer {
FilamentEntity entity, MorphAnimationData animation,
{List<String>? targetMeshNames}) async {
var meshNames = await getChildEntityNames(entity, renderableOnly: true);
if (targetMeshNames != null) {
for (final targetMeshName in targetMeshNames) {
if (!meshNames.contains(targetMeshName)) {
throw Exception(
"Error: mesh ${targetMeshName} does not exist under the specified entity. Available meshes : ${meshNames}");
}
}
}
var meshEntities = await getChildEntities(entity, true);
@@ -481,6 +507,8 @@ class FilamentViewer extends AbstractFilamentViewer {
var meshMorphTargets = await getMorphTargetNames(entity, meshEntity);
print("Got mesh morph targets ${meshMorphTargets}");
var intersection = animation.morphTargets
.toSet()
.intersection(meshMorphTargets.toSet())
@@ -488,7 +516,11 @@ class FilamentViewer extends AbstractFilamentViewer {
if (intersection.isEmpty) {
throw Exception(
"No morph targets specified in animation are present on mesh $meshName. If you weren't intending to animate every mesh, specify [targetMeshNames] when invoking this method.\nAnimation morph targets: ${animation.morphTargets}\nMesh morph targets ${meshMorphTargets}");
"""No morph targets specified in animation are present on mesh $meshName.
If you weren't intending to animate every mesh, specify [targetMeshNames] when invoking this method.
Animation morph targets: ${animation.morphTargets}\n
Mesh morph targets ${meshMorphTargets}
Child meshes: ${meshNames}""");
}
var indices =
@@ -1168,6 +1200,4 @@ class FilamentViewer extends AbstractFilamentViewer {
Future setPriority(FilamentEntity entityId, int priority) async {
set_priority(_sceneManager!, entityId, priority);
}
}

View File

@@ -510,6 +510,19 @@ extern "C"
strcpy(outPtr, name.c_str());
}
EMSCRIPTEN_KEEPALIVE int get_bone_count(void *sceneManager, EntityId assetEntity, int skinIndex) {
auto names = ((SceneManager *)sceneManager)->getBoneNames(assetEntity, skinIndex);
return names->size();
}
EMSCRIPTEN_KEEPALIVE void get_bone_names(void *sceneManager, EntityId assetEntity, const char** out, int skinIndex) {
auto names = ((SceneManager *)sceneManager)->getBoneNames(assetEntity, skinIndex);
for(int i = 0; i < names->size(); i++) {
memcpy((void*)out[i], names->at(i).c_str(), names->at(i).length());
}
}
EMSCRIPTEN_KEEPALIVE int get_morph_target_name_count(void *sceneManager, EntityId assetEntity, EntityId childEntity)
{
auto names = ((SceneManager *)sceneManager)->getMorphTargetNames(assetEntity, childEntity);

View File

@@ -1239,6 +1239,44 @@ namespace flutter_filament
return names;
}
unique_ptr<vector<string>> SceneManager::getBoneNames(EntityId assetEntityId, int skinIndex) {
unique_ptr<std::vector<std::string>> names = std::make_unique<std::vector<std::string>>();
auto *instance = getInstanceByEntityId(assetEntityId);
if (!instance)
{
auto *asset = getAssetByEntityId(assetEntityId);
if (asset)
{
instance = asset->getInstance();
}
else
{
Log("ERROR: failed to find instance for entity %d", assetEntityId);
return names;
}
}
size_t skinCount = instance->getSkinCount();
if (skinCount > 1)
{
Log("WARNING - skin count > 1 not currently implemented. This will probably not work");
}
size_t numJoints = instance->getJointCountAt(skinIndex);
auto joints = instance->getJointsAt(skinIndex);
for (int i = 0; i < numJoints; i++)
{
const char *jointName = _ncm->getName(_ncm->getInstance(joints[i]));
names->push_back(jointName);
}
return names;
}
void SceneManager::transformToUnitCube(EntityId entityId)
{
const auto *instance = getInstanceByEntityId(entityId);