horde3d / Horde3D

Horde3D is a small 3D rendering and animation engine. It is written in an effort to create an engine being as lightweight and conceptually clean as possible.
http://horde3d.org/
1.55k stars 308 forks source link

advice on per-vertext animation #225

Closed gwald closed 9 months ago

gwald commented 10 months ago

Hello again

I want to do per vertex animation, but my models (.obj's) are individual models, same model data but the verts are in different positions... anyway, I don't know how to package these into collada format to get morph targets.

Would anyone have any tips on how to do this or what to words to search? I cant seem to find anything that can do it.

Or alternatively, can H3D load my individual model data and interpolate from one to another? I had a look at the API and forum, I couldn't find anything that suggest it can.

Thanks in advance.

algts commented 10 months ago

Hello. I'll start with the second question. Horde is designed to use animation files, otherwise you would have to animate the models yourself. You can get the vertex positions of each model, animate them manually, then reupload new positions. Here is the example on how you can get vertex positions: https://github.com/algts/Horde3DPhysics/blob/master/src/Horde3DPhysics/egPhysics.cpp

Now, the first question. AFAIK morph targets will work until you have the same number of vertices. Therefore, if you have different models (like begin and end state of the animation, if I understood you correctly) you'll probably have to import both models into your DCC tool (Blender, 3d Max, Maya, etc.), make the two models on the polar ends of the animation track (for example, model 1 is on 0 keyframe, model 2 is on 100 keyframe) and create a transition effect. Basically, you would have to recreate the morph animation and then you would export the animation to Collada. You should consult the manual of your DCC tool on how to create transition/morph animation.

gwald commented 10 months ago

Thank you very much for the reply! It helped me out a lot!

My DCC is MarbleClay (http://escargot.la.coocan.jp/MCLFrm.html) a very simple 3D app, it doesn't have animation support, I just export individual poses :)

I looked at the code and saw h3dMapResStream & h3dUnmapResStream, I found someone asking the same question on the forum and this worked great: http://horde3d.org/forums/viewtopic.php?p=5337&sid=9d997d42445994769ab88f36edb90416#p5337

Thank you :+1:

gwald commented 10 months ago

Some info regarding the DCC approach.

http://horde3d.org/forums/viewtopic.php?f=11&t=2330

I recently found a face animation software package, it mentioned the "Motion designer files .mdd" format, which I've never heard of before, but it's a way of packing and process morphing animation, it's a very simple format:

http://rodolphe-vaillant.fr/entry/134/mdd-file-exporter-importer-source-code-c-c

And probably widely supported, like blender: https://blender.stackexchange.com/questions/45921/how-to-import-mdd-files

They might not even require the .mdd format, and might work with just individual files.

gwald commented 10 months ago

Sorry for reopening this, but I'm not sure how to proceed without doing a lot more trial and error and would like advice. I can morph verts on a node with a resource.

I have a static pose frame saved as .dae and converted and I want to tween out to another static pose, repeat for a few frames. But I'm not sure how to best structure this for multiple 'resources', to get an animation.

I started creating individual resources, but it felt wrong and wondered if I could use clone and found an example of cloning materials inside a resource: https://horde3d.org/forums/viewtopic.php?p=10364#p10364

Is this the correct the approach, cloning the mesh? I have 4 keyframes and I want a one tween frame in between , I know how to interpolate them.

I would normally just do it, but this is pretty big for 'trial and error', and could do with advice.

I was thinking: Load all the keyframes as normal resources Create the animation resource using the first frame, create 7 clones of the mesh. Then I "h3dMapResStream & h3dUnmapResStream" the mesh in the 7 clone meshes.

But I cant seem to set the new mesh: h3dSetNodeParamI(scene_anim_ID, H3D_ResTypes_Geometry, keyframes_cloneID ); I've step through the engine, and it doesn't like my scene_anim_ID ("Models/t1.scene.xml"), even though it's fine (non zero).

Help please :/

algts commented 10 months ago

Are you sure you want to go that way? To me it looks like you're reimplementing the whole engine animation system in your game. AFAIK, currently Horde does not support generating animation files on the fly, you should look into converter code (search for function that generates animation file in converter.cpp). If you are not using animation resources, but are changing geometry resources in models, you should probably:

Make sure that you are setting geometry file and then call h3dUpdateModel with update geometry flag. Next update would not work unless you change geometry resource again.

Horde checks the following when updating geometry in model:

if( !_skinningDirty && !_morpherDirty ) return false;

    if( _baseGeoRes == 0x0 || _baseGeoRes->getVertPosData() == 0x0 ||
        _baseGeoRes->getVertTanData() == 0x0 || _baseGeoRes->getVertStaticData() == 0x0 ) return false;
    if( _geometryRes == 0x0 || _geometryRes->getVertPosData() == 0x0 ||
        _geometryRes->getVertTanData() == 0x0 || _geometryRes->getVertStaticData() == 0x0 ) return false;

SkinningDirty is set when you set new geometry resource. If you do not set any morphers or software skinning parameter is not set (you should set it if you are not using animation files), baseGeoRes would be zero and therefore the checks would fail.

algts commented 9 months ago

@gwald Hello. Did it help you or you've encountered some issues?

gwald commented 9 months ago

Hi, Yes, it was very helpful thank you! Thanks for asking :)

I figured the best way forward with least resistance is to modify the converter to create the anim file of the static dae files as morph targets, I started looking into this and I can roughly figure out where to make it read the dae files and change the XML objects to make it think it's one dae with morph targets.

So, I left that and now I'm trying to figure out how to load a morph animation using this one: https://github.com/KhronosGroup/COLLADA2GLTF/issues/166#issuecomment-385405062

And I'm stuck getting it to morph (https://github.com/horde3d/Horde3D/issues/226)

Or it could be an issue that I'm using groupnodes to keep track of my scene and deleting all the nodes at the start of each new frame? (I dont want child nodes automatically rendering,https://github.com/horde3d/Horde3D/issues/224#issuecomment-1899231779).

algts commented 9 months ago

@gwald Is this issue still valid? Or should we close it?

gwald commented 9 months ago

I'm still looking into this, and I'll post my solution here and/or close this. I'm testing the dev branch now, thanks again for your help with morphing! :)

gwald commented 9 months ago

I made a program that takes all the collada text files in a folder and mergers them into a single one as morph frames in alphabetical order... it doesn't keep the names (maybe that would have been better), it uses the first name and adds numbers. It works with my simple collada files created with assimp.

The hacky source code and a win32 executable is included... If I change it regularly, I might maintain it on my github src.zip

Thank you @algts for your patience and guidance.