Comments (13)
Hi,
Glad to hear ozz is helping you. Hope to see what you did with it some day!
Back to your question: ozz::animation::BlendingJob is by design able to blend n layer, n being dynamic. samples uses hard coded number indeed, only to allocate layers though.
ozz::Range is generalising the concept of array using internally a begin and end pointer. It allows to pass BlendingJob an array of layers, without imposing a way to allocate the array. ozz::Range can be initialised from:
- a static c array like samples are using.
- a pointer and a size, to use when the array is allocated from new[] operator for example.
- a vector.
- ...
So there should be no problem providing a dynamic number of layers. I suspect the issue is in the way you setup ozz::Range. Can you double check that? There might be a bug also, in ozzRange or BlendingJob. So if you're stuck you can send me your BlendingJob setup and array allocation code.
Hope it helps.
Cheers,
Guillaume
from ozz-animation.
Thank you so much for the quick response! Below is the code from the blend sample with a minor adjustment. When using the Dynamic Code block it cannot make it through blendingjob's validate function, when using the Sample Code block (the original code) everything runs perfectly. What code would you insert in the Dynamic Code block such that the variable layers can be created based on a dynamic value? Thank you, you're the best!
// Blends animations.
// Blends the local spaces transforms computed by sampling all animations
// (1st stage just above), and outputs the result to the local space
// transform buffer blended_locals_
//----Dynamic Code
int dynamicNumLayers = kNumLayers;
ozz::memory::Allocator* allocator = ozz::memory::default_allocator();
ozz::Range<ozz::animation::BlendingJob::Layer> layers = allocator->AllocateRange<ozz::animation::BlendingJob::Layer>(dynamicNumLayers);
//----Dynamic Code
//----Sample Code
ozz::animation::BlendingJob::Layer layers[kNumLayers];
//----Sample Code
for (int i = 0; i < kNumLayers; ++i) {
layers[i].transform = samplers_[i].locals;
layers[i].weight = samplers_[i].weight;
}
// Setups blending job.
ozz::animation::BlendingJob blend_job;
blend_job.threshold = threshold_;
blend_job.layers = layers;
blend_job.bind_pose = skeleton_.bind_pose();
blend_job.output = blended_locals_;
// Blends.
if (!blend_job.Run()) {
return false;
}
from ozz-animation.
Hi,
just found the reason: AllocateRange is a C allocator. It works with POD structures, not objects that require their constructors to be called (like ozz::animation::BlendingJob::Layer which sets some default values).
I just realised also that ozz lacks a way to allocate that sort of arrays, like new[] would do. I'll try to provide that and detect non POD structures used with Allocate* functions.
In the meantime you should be able to fix it in you code, using new[], a vector...
That wasn't obvious! Thanks for reporting the issue.
Cheers,
Guillaume
from ozz-animation.
Hi,
I now understand that ozz::memory::Allocator API is error prone, because it exposes object-like allocation functions, but doesn't call constructors/destructors (neither warn about it). It must be fixed.
Have you managed to overcome your issue and blend n layers on your side?
Cheers,
Guillaume
from ozz-animation.
@syonker if you fully init your layers, you can work around the issue until it's fixed.
for (int i = 0; i < kNumLayers; ++i) {
layers[i].transform = samplers_[i].locals;
layers[i].weight = samplers_[i].weight;
layers[i].joint_weights = ozz::Range<const ozz::math::SimdFloat4>();
}
from ozz-animation.
I guess the issue with my work around at the moment is that I'm not declaring 'layers' correctly then. @kylawl how did you declare 'layers' just before that bit of code you sent in order for it to work in the blend sample and by based on a dynamic value? Thank you so much for the help
from ozz-animation.
Hi,
What @kylawl says (thanks BTW) works without changing your allocation strategy. Just add this line to the initialization loop:
for (int i = 0; i < kNumLayers; ++i) {
layers[i].transform = samplers_[i].locals;
layers[i].weight = samplers_[i].weight;
layers[i].joint_weights = ozz::Range<const ozz::math::SimdFloat4>(); // <- Missing initialization workaround
}
BUT, it’s a workaround!
Just to be sure: you don't need to wait for a fix, ozz::animation::BlendingJob and ozz::memory::Allocator are working as expected/documented. The issue is that your allocating your array with a raw memory allocator (à la malloc). This means that ozz::animation::BlendingJob::Layer's are not properly initialized, beacuse their consructors aren't called (thus the workaround). In c++ new/new[] operators should be used to allocate objects/class; that’s one option. I pushed a modified sample to demonstrate it. Another option is using containers like vectors. There are many other options, it's up to you to choose depending on your allocation strategy.
Keep in mind that dynamically allocating is very costly though. It should be avoided during update (ozz does no allocation during update). So I'd recommend to pre-allocate this array, which doesn't prevent you from having dynamic number of layers. Nothing actually prevents you from using a dynamic number of layers...
Hope it helps,
Guillaume
from ozz-animation.
Thank you both so much! That's exactly what I needed. By allocating in my init() function with the provided method by the time update() comes around I have a dynamic based number of layers to access and it works perfectly. Ozz is the best, I'm excited to keep working with it!
from ozz-animation.
from ozz-animation.
Good to hear it's working and that you're happy!
The mix of pod and non-pod types in ozz data structure is part of the confusion. That's also why I think ozz allocation function should handle constructor calls (when needed).
@kylawl, I am curious why you don't allocate the 16 layers on the stack, like ozz sample are doing? It doesn't consume that much stack, and is thread safe by nature.
Looking forward to see what you're doing with ozz.
Cheers,
Guillaume
from ozz-animation.
I'm using ozz to service a generalized animation system so while this game limits the max layers to 16, it is a configurable maximum within our editor, not necessarily a compile time constant. Hence the heap allocation.
from ozz-animation.
Sounds like an interesting project @kylawl, hope to see it some day!
Looking at ozz Allocator, I saw that typed arrays allocations (those supposed to call constructors) were actually never used by the library, only samples. I presume most users have their own allocator anyway (or use crt). So I removed them, and used vectors in the samples which are safer and easier to read. Here is the change.
from ozz-animation.
from ozz-animation.
Related Issues (20)
- examples on how to integrate with OpenGL? HOT 2
- What CLI options did you exactly use to create the media/bin/*.ozz animations from FBX files? HOT 4
- Animation Playback HOT 25
- gltf2ozz issue HOT 2
- Trouble getting Skinning to work. HOT 3
- Make a new master release HOT 3
- glTF and FBX skeleton difference HOT 1
- The 'install' -target for make tries to change permissions on existing directories HOT 4
- The 'install' -target places some files in the installation root directory HOT 2
- Feedback/Suggestion: the exclusion of mesh data in ozz tooling makes the library less confortable to use
- Decoupling SamplingJob from file format HOT 2
- Skinning job doesn't preserve tangent handedness HOT 1
- Log adds a dependency on the standard C++ library for runtime HOT 2
- Failed to build on MSYS2 MINGW64 HOT 7
- gltf2ozz is not filtering out non joint nodes HOT 1
- How to define pole vector for two bone IK? HOT 4
- Discover projects using ozz-animation HOT 7
- AnimationOptimizer too eager to early out ? HOT 1
- Can't build samples after adding fbxsdk folder to the FindFbx.make
- 3 bones with first 2 bones not animated producing discrepancy between playback sample and Khronos GLTF reference HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ozz-animation.