zturtleman / mm3d

Maverick Model 3D is a 3D model editor and animator for games.
https://clover.moe/mm3d
GNU General Public License v2.0
114 stars 22 forks source link

Decision: Reconsider MM3D format filters by frames? #129

Open m-7761 opened 4 years ago

m-7761 commented 4 years ago

I'm introducing a MFAF_MODE_2020 (MSAF_MODE_2020) "modern" animation format flag. My sense is the historical practice of emitting the animation data in frame order is inefficient.

I'm wondering if this should be changed with the flag since MM3D converters will have to adopt the flag anyway.

For vertex-animation data to me filter by frame seems intuitive to think about as a "human" but it's not cache efficient with the way I've moved the data into the Vertex structure to solve the displayFrameAnimPrimitiveError problem, which is itself not inefficient for interpolating vertex data.

For skeletal/point animation each frame only contains at most the number of joints or bones, which is a small number. It could be filtered by joint/point/object (removing object field) or it could all be written out in no order (adding a frame field to each keyframe.) If there are more frames than objects or vice versa one strategy is more compact, but the issue with frame filtering is it makes the internal code have to pass over all of the keyframes and check them for frame equality since that's not how they're stored in Model data structure.

That's inefficient for reading/writing the MM3D files and a lot more code to maintain that's confusing and makes you do a double-take on first glance.

What it boils down to is does the MM3D format have a particular character or not? Is it a big deal to change it just because?

m-7761 commented 4 years ago

EDITED: Something I forgot (to consider) is the vertex-data probably benefits from frame filtering because I've changed it to do a kind of run-length encoding against the new interpolation mode.

If it were filtered by vertex the run-lengths would likely be very short, but by frame it could omit large groups of vertices in theory.

I've also changed the point part of frame-animation to work like the joint keyframes. That actually simplifies a lot of code because it makes the two animation data structures virtually identical. It's a little weird though because joints use local transforms and points use global transforms. It became too prohibitive to store translation rotation and scale, and it didn't make as much sense to mask them with the interpolation mode strategy in packs of three.

The applyMatrix function is a little quirky because for skeletal animations it doesn't rotate the keyframes (I think they follow the joints) and just rotates the parent joints. Whereas that doesn't work for points. It would be better to decide if points should behave like joints in this regard or not. Likewise when clamping interpolation (interpKeyframe) the two differ. I tried to factor scale into applyMatrix last night. It's complicated.

zturtleman commented 4 years ago

Smaller files would be good, yes. How animations are stored internally and in .mm3d files is a deeper fundamental change than I'm currently interested in.

I personally want .mm3d files to remain compatible with Misfit Model 3D. Otherwise I think a person might as well fork the format (change the file magic identifier and extension) with no real loss.

I would suggest adding a new data type chunks instead of an animation flag (see MDT_ enum in src/libmm3d/mm3dfilter.cc) if the animation data is represented differently causing Misfit Model 3D and Maverick to not be able to load the animations correctly. By using a new separate chunks (and not including the naive "legacy" animation data at all) Misfit Model 3D and Maverick would load the model without the animations. (How to choose new chunk ID numbers without potential conflict in the future, I don't know.)

Though then it seems like you should have an option for exporting Misfit Model 3D compatible animations or "modern 2020" animations when writing Misfit Model 3D models.

m-7761 commented 4 years ago

Though then it seems like you should have an option for exporting Misfit Model 3D compatible animations or "modern 2020" animations when writing Misfit Model 3D models.

No, if that's truly a goal then it's best to use an old version of the software. This is basic versioning. It's why formats have fields for versions.

It's a bug to load files with versions newer than the software's built version simply because they can't (by definition) represent the file fully and so will downgrade the file if they try to save it. I don't think it would be worth it to maintain the ability to write old versions. I've never seen a software offer that.

It probably doesn't make any sense to add chunks. That's hard to maintain and you get junk like the 8 bit group smoothing setting is stored as a "chunk" instead of just slipping it into the group data where it belongs. That practice has no actual value and results in indecipherable spaghetti code. The loader code needs to be simple so projects can copy it to write MM3D loaders for themselves. That's what I did before I started working on animation so I could make MM3D files from my data sets.

P.S. For the keyframe data (points use keyframes now) changing would simplify that code from the library's perspective but otherwise not make a big difference. (Edited: This can also be done with a vector to remap the data once, no big deal.) For vertex-frames frame filtering (favoring size and morph logic) seems best to me. I kept the frame-first filtering for consistency sake even though it doesn't fit the keyframe data well. So overall I'm ambivalent but feel that there will never be another time to decide. Frame filtering would be required anyway if someone truly wanted to put in an option to write old file formats, but those would be inferior files and so pretty pointless.

EDITED: Just as an update, yesterday I finished three long days of rewriting all of the animation subroutines and read/write and I'm moving on to testing and double-checking everything next.

m-7761 commented 4 years ago

For the record: I think this work will probably remain open for evaluation until the decision is made to get rid of the separation between "skeletal" and "frame" animations (https://github.com/zturtleman/mm3d/issues/127) that I see as inevitable. I don't think there should be any public releases incorporating those changes before that's decided. I don't mean "if to do it" but "how to do it".

m-7761 commented 3 years ago

Update: After working on this (https://github.com/zturtleman/mm3d/issues/127) (https://github.com/zturtleman/mm3d/issues/149) it's plain to see an easy path forward for merging my fork file-format wise. I'm not sure this is the best Issue under which to file this but just to update on progress...

Since I've merged animations what makes sense is to adopt two new blocks for MM3D format and retire some old ones. The frame order (topic of this issue) can change in making a new "MDT_Animations" block that includes all animation data in a unified format. The old animation blocks will be retired to just reading.

Other than this I'm pretty sure the only new data I've added is Scale information, and I figure that can go in a new "MDT_ScaleFactors" block or something, which makes a lot of sense to do since scale is so often 1,1,1 so it does no good to write that out alongside the Joint and Point blocks.

Unless I'm missing something this will leave all existing blocks unscathed.