finalize bone transform animation
This commit is contained in:
@@ -1,44 +1,7 @@
|
||||
import 'animations.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class Animation {
|
||||
late final Float32List? morphData;
|
||||
final int numMorphWeights;
|
||||
|
||||
final int numFrames;
|
||||
final double frameLengthInMs;
|
||||
|
||||
final List<String>? boneNames;
|
||||
final List<String>? meshNames;
|
||||
|
||||
final Float32List? boneTransforms;
|
||||
|
||||
Animation(this.morphData, this.numMorphWeights, this.boneTransforms,
|
||||
this.boneNames, this.meshNames, this.numFrames, this.frameLengthInMs) {
|
||||
if (morphData != null && morphData!.length != numFrames * numMorphWeights) {
|
||||
throw Exception("Mismatched animation data with frame length");
|
||||
}
|
||||
}
|
||||
|
||||
Animation.from(
|
||||
{required List<List<double>> morphData,
|
||||
required this.numMorphWeights,
|
||||
this.boneTransforms,
|
||||
this.boneNames,
|
||||
this.meshNames,
|
||||
required this.numFrames,
|
||||
required this.frameLengthInMs}) {
|
||||
if (morphData.length != numFrames) {
|
||||
throw Exception("Mismatched animation data with frame length");
|
||||
}
|
||||
this.morphData = Float32List(numMorphWeights * numFrames);
|
||||
for (int i = 0; i < numFrames; i++) {
|
||||
this.morphData!.setRange((i * numMorphWeights),
|
||||
(i * numMorphWeights) + numMorphWeights, morphData[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
import 'package:vector_math/vector_math.dart';
|
||||
|
||||
class AnimationBuilder {
|
||||
BoneAnimation? boneAnimation;
|
||||
@@ -53,7 +16,7 @@ class AnimationBuilder {
|
||||
|
||||
final List<String> _boneNames = [];
|
||||
final List<String> _meshNames = [];
|
||||
final List<BoneTransform> _boneTransforms = [];
|
||||
final List<BoneTransformFrameData> _boneTransforms = [];
|
||||
|
||||
Animation build() {
|
||||
if (_numMorphWeights == 0 || _duration == 0 || _frameLengthInMs == 0)
|
||||
@@ -79,22 +42,31 @@ class AnimationBuilder {
|
||||
print(
|
||||
"Created morphWeights of size ${morphData.length} (${morphData.lengthInBytes} for ${numFrames} frames");
|
||||
|
||||
final boneTransforms = Float32List(numFrames * _boneTransforms.length * 7);
|
||||
print(
|
||||
"Creating bone transforms of size ${numFrames * _boneTransforms.length * 7}");
|
||||
for (int i = 0; i < numFrames; i++) {
|
||||
for (int j = 0; j < _boneTransforms.length; j++) {
|
||||
var frameData = _boneTransforms[j].getFrameData(i).toList();
|
||||
var rngStart = ((i * _boneTransforms.length) + j) * 7;
|
||||
var rngEnd = rngStart + 7;
|
||||
boneTransforms.setRange(rngStart, rngEnd, frameData);
|
||||
}
|
||||
print(
|
||||
"frameData for frame $i ${boneTransforms.sublist(i * _boneTransforms.length * 7, (i * _boneTransforms.length * 7) + 7)}");
|
||||
List<BoneAnimation>? boneAnimations;
|
||||
|
||||
if (_boneTransforms.isNotEmpty) {
|
||||
throw Exception("TODO");
|
||||
boneAnimations = <BoneAnimation>[];
|
||||
|
||||
final boneTransforms =
|
||||
Float32List(numFrames * _boneTransforms.length * 7);
|
||||
|
||||
// print(
|
||||
// "Creating bone transforms of size ${numFrames * _boneTransforms.length * 7}");
|
||||
// for (int i = 0; i < numFrames; i++) {
|
||||
// for (int j = 0; j < _boneTransforms.length; j++) {
|
||||
// var frameData = _boneTransforms[j].getFrameData(i).toList();
|
||||
// var rngStart = ((i * _boneTransforms.length) + j) * 7;
|
||||
// var rngEnd = rngStart + 7;
|
||||
// boneTransforms.setRange(rngStart, rngEnd, frameData);
|
||||
// }
|
||||
// print(
|
||||
// "frameData for frame $i ${boneTransforms.sublist(i * _boneTransforms.length * 7, (i * _boneTransforms.length * 7) + 7)}");
|
||||
// }
|
||||
}
|
||||
|
||||
return Animation(morphData, _numMorphWeights, boneTransforms, _boneNames,
|
||||
_meshNames, numFrames, _frameLengthInMs);
|
||||
return Animation(morphData, _numMorphWeights, boneAnimations, numFrames,
|
||||
_frameLengthInMs);
|
||||
}
|
||||
|
||||
AnimationBuilder setFramerate(int framerate) {
|
||||
@@ -126,11 +98,11 @@ class AnimationBuilder {
|
||||
String meshName,
|
||||
double start,
|
||||
double end,
|
||||
Vec3 transStart,
|
||||
Vec3 transEnd,
|
||||
Vector3 transStart,
|
||||
Vector3 transEnd,
|
||||
Quaternion quatStart,
|
||||
Quaternion quatEnd) {
|
||||
var translations = <Vec3>[];
|
||||
var translations = <Vector3>[];
|
||||
var quats = <Quaternion>[];
|
||||
var frameStart = (start * 1000) ~/ _frameLengthInMs;
|
||||
var frameEnd = (end * 1000) ~/ _frameLengthInMs;
|
||||
@@ -143,25 +115,25 @@ class AnimationBuilder {
|
||||
if (i >= frameStart && i < frameEnd) {
|
||||
var linear = (i - frameStart) / (frameEnd - frameStart);
|
||||
|
||||
translations.add(Vec3(
|
||||
x: ((1 - linear) * transStart.x) + (linear * transEnd.x),
|
||||
y: ((1 - linear) * transStart.y) + (linear * transEnd.y),
|
||||
z: ((1 - linear) * transStart.z) + (linear * transEnd.z),
|
||||
translations.add(Vector3(
|
||||
((1 - linear) * transStart.x) + (linear * transEnd.x),
|
||||
((1 - linear) * transStart.y) + (linear * transEnd.y),
|
||||
((1 - linear) * transStart.z) + (linear * transEnd.z),
|
||||
));
|
||||
|
||||
quats.add(Quaternion(
|
||||
x: ((1 - linear) * quatStart.x) + (linear * quatEnd.x),
|
||||
y: ((1 - linear) * quatStart.y) + (linear * quatEnd.y),
|
||||
z: ((1 - linear) * quatStart.z) + (linear * quatEnd.z),
|
||||
w: ((1 - linear) * quatStart.w) + (linear * quatEnd.w),
|
||||
((1 - linear) * quatStart.x) + (linear * quatEnd.x),
|
||||
((1 - linear) * quatStart.y) + (linear * quatEnd.y),
|
||||
((1 - linear) * quatStart.z) + (linear * quatEnd.z),
|
||||
((1 - linear) * quatStart.w) + (linear * quatEnd.w),
|
||||
));
|
||||
} else {
|
||||
translations.add(Vec3());
|
||||
quats.add(Quaternion());
|
||||
translations.add(Vector3.zero());
|
||||
quats.add(Quaternion.identity());
|
||||
}
|
||||
}
|
||||
|
||||
_boneTransforms.add(BoneTransform(translations, quats));
|
||||
_boneTransforms.add(BoneTransformFrameData(translations, quats));
|
||||
|
||||
_boneNames.add(boneName);
|
||||
_meshNames.add(meshName);
|
||||
|
||||
@@ -1,47 +1,87 @@
|
||||
class Vec3 {
|
||||
final double x;
|
||||
final double y;
|
||||
final double z;
|
||||
import 'dart:typed_data';
|
||||
|
||||
Vec3({this.x = 0, this.y = 0, this.z = 0});
|
||||
import 'package:vector_math/vector_math.dart';
|
||||
|
||||
factory Vec3.from(List<double> vals) =>
|
||||
Vec3(x: vals[0], y: vals[1], z: vals[2]);
|
||||
// class Vec3 {
|
||||
// final double x;
|
||||
// final double y;
|
||||
// final double z;
|
||||
|
||||
// Vec3({this.x = 0, this.y = 0, this.z = 0});
|
||||
|
||||
// factory Vec3.from(List<double> vals) =>
|
||||
// Vec3(x: vals[0], y: vals[1], z: vals[2]);
|
||||
// }
|
||||
|
||||
// class Quaternion {
|
||||
// double x = 0;
|
||||
// double y = 0;
|
||||
// double z = 0;
|
||||
// double w = 1;
|
||||
|
||||
// Quaternion({this.x = 0, this.y = 0, this.z = 0, this.w = 1.0});
|
||||
|
||||
// factory Quaternion.from(List<double> vals) =>
|
||||
// Quaternion(x: vals[0], y: vals[1], z: vals[2], w: vals[3]);
|
||||
// }
|
||||
|
||||
class BoneAnimation {
|
||||
final List<String> boneNames;
|
||||
final List<String> meshNames;
|
||||
final Float32List frameData;
|
||||
|
||||
BoneAnimation(this.boneNames, this.meshNames, this.frameData);
|
||||
|
||||
List<List> toList() {
|
||||
return [boneNames, meshNames, frameData];
|
||||
}
|
||||
}
|
||||
|
||||
class Quaternion {
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
double z = 0;
|
||||
double w = 1;
|
||||
class Animation {
|
||||
late final Float32List? morphData;
|
||||
final int numMorphWeights;
|
||||
|
||||
Quaternion({this.x = 0, this.y = 0, this.z = 0, this.w = 1.0});
|
||||
final int numFrames;
|
||||
final double frameLengthInMs;
|
||||
|
||||
factory Quaternion.from(List<double> vals) =>
|
||||
Quaternion(x: vals[0], y: vals[1], z: vals[2], w: vals[3]);
|
||||
final List<BoneAnimation>? boneAnimations;
|
||||
|
||||
Animation(this.morphData, this.numMorphWeights, this.boneAnimations,
|
||||
this.numFrames, this.frameLengthInMs) {
|
||||
if (morphData != null && morphData!.length != numFrames * numMorphWeights) {
|
||||
throw Exception("Mismatched animation data with frame length");
|
||||
}
|
||||
}
|
||||
|
||||
Animation.from(
|
||||
{required List<List<double>> morphData,
|
||||
required this.numMorphWeights,
|
||||
this.boneAnimations,
|
||||
required this.numFrames,
|
||||
required this.frameLengthInMs}) {
|
||||
if (morphData.length != numFrames) {
|
||||
throw Exception("Mismatched animation data with frame length");
|
||||
}
|
||||
this.morphData = Float32List(numMorphWeights * numFrames);
|
||||
for (int i = 0; i < numFrames; i++) {
|
||||
this.morphData!.setRange((i * numMorphWeights),
|
||||
(i * numMorphWeights) + numMorphWeights, morphData[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BoneTransform {
|
||||
final List<Vec3> translations;
|
||||
class BoneTransformFrameData {
|
||||
final List<Vector3> translations;
|
||||
final List<Quaternion> quaternions;
|
||||
|
||||
///
|
||||
/// The length of [translations] and [quaternions] must be the same;
|
||||
/// each entry represents the Vec3/Quaternion for the given frame.
|
||||
///
|
||||
BoneTransform(this.translations, this.quaternions) {
|
||||
BoneTransformFrameData(this.translations, this.quaternions) {
|
||||
if (translations.length != quaternions.length) {
|
||||
throw Exception("Length of translation/quaternion frames must match");
|
||||
}
|
||||
// for (int i = 0; i < quaternions.length; i++) {
|
||||
// _frameData.add(translations[i].x);
|
||||
// _frameData.add(translations[i].y);
|
||||
// _frameData.add(translations[i].z);
|
||||
// _frameData.add(quaternions[i].x);
|
||||
// _frameData.add(quaternions[i].y);
|
||||
// _frameData.add(quaternions[i].z);
|
||||
// _frameData.add(quaternions[i].w);
|
||||
// }
|
||||
}
|
||||
|
||||
Iterable<double> getFrameData(int frame) sync* {
|
||||
@@ -54,22 +94,3 @@ class BoneTransform {
|
||||
yield quaternions[frame].w;
|
||||
}
|
||||
}
|
||||
|
||||
class BoneAnimation {
|
||||
final List<BoneTransform> boneTransforms;
|
||||
final List<String> boneNames;
|
||||
final List<String> meshNames;
|
||||
|
||||
final int numFrames;
|
||||
|
||||
BoneAnimation(
|
||||
this.boneTransforms, this.boneNames, this.meshNames, this.numFrames);
|
||||
|
||||
Iterable<double> toFrameData() sync* {
|
||||
for (int i = 0; i < numFrames; i++) {
|
||||
for (int j = 0; j < boneTransforms.length; j++) {
|
||||
yield* boneTransforms[j].getFrameData(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,8 +80,8 @@ abstract class FilamentController {
|
||||
Future setPosition(FilamentAsset asset, double x, double y, double z);
|
||||
Future setRotation(
|
||||
FilamentAsset asset, double rads, double x, double y, double z);
|
||||
Future setBoneTransform(FilamentAsset asset, String boneName, String meshName,
|
||||
BoneTransform transform);
|
||||
// Future setBoneTransform(FilamentAsset asset, String boneName, String meshName,
|
||||
// BoneTransform transform);
|
||||
Future setScale(FilamentAsset asset, double scale);
|
||||
Future setCameraFocalLength(double focalLength);
|
||||
Future setCameraFocusDistance(double focusDistance);
|
||||
@@ -282,14 +282,11 @@ class PolyvoxFilamentController extends FilamentController {
|
||||
}
|
||||
|
||||
Future setAnimation(FilamentAsset asset, Animation animation) async {
|
||||
print("Frmael en ${animation.frameLengthInMs}");
|
||||
await _channel.invokeMethod("setAnimation", [
|
||||
asset,
|
||||
animation.morphData!,
|
||||
animation.numMorphWeights,
|
||||
animation.boneTransforms ?? Float32List(0),
|
||||
animation.boneNames ?? <String>[],
|
||||
animation.meshNames ?? <String>[],
|
||||
animation.boneAnimations?.map((a) => a.toList()).toList() ?? [],
|
||||
animation.numFrames,
|
||||
animation.frameLengthInMs
|
||||
]);
|
||||
@@ -367,21 +364,21 @@ class PolyvoxFilamentController extends FilamentController {
|
||||
await _channel.invokeMethod("setPosition", [asset, x, y, z]);
|
||||
}
|
||||
|
||||
Future setBoneTransform(FilamentAsset asset, String boneName, String meshName,
|
||||
BoneTransform transform) async {
|
||||
await _channel.invokeMethod("setBoneTransform", [
|
||||
asset,
|
||||
boneName,
|
||||
meshName,
|
||||
transform.translations[0].x,
|
||||
transform.translations[0].y,
|
||||
transform.translations[0].z,
|
||||
transform.quaternions[0].x,
|
||||
transform.quaternions[0].y,
|
||||
transform.quaternions[0].z,
|
||||
transform.quaternions[0].w
|
||||
]);
|
||||
}
|
||||
// Future setBoneTransform(FilamentAsset asset, String boneName, String meshName,
|
||||
// BoneTransform transform) async {
|
||||
// await _channel.invokeMethod("setBoneTransform", [
|
||||
// asset,
|
||||
// boneName,
|
||||
// meshName,
|
||||
// transform.translations[0].x,
|
||||
// transform.translations[0].y,
|
||||
// transform.translations[0].z,
|
||||
// transform.quaternions[0].x,
|
||||
// transform.quaternions[0].y,
|
||||
// transform.quaternions[0].z,
|
||||
// transform.quaternions[0].w
|
||||
// ]);
|
||||
// }
|
||||
|
||||
Future setScale(FilamentAsset asset, double scale) async {
|
||||
await _channel.invokeMethod("setScale", [asset, scale]);
|
||||
|
||||
Reference in New Issue
Block a user