Le moteur 3d ECO
L'outil photo

Voici une visionneuse pour les fichiers obj-mtl, glft et mes mécanismes obj. Photo permet de créer des vignettes, par exemple pour faire une vue des objets dans l'inventaire d'un jeu.
09/2025
OMesh_gltf ayant été modifié pour charger les morph targets, Photo a été adapté et enrichi.
04/2025
Le fichier chargeant les GLTF a été amélioré. Les équipements des personnages sont désormais visibles (ou pas), vous pouvez désormais charger les objets animés par les axes (comme les coffres). Ceux qui possèdent des parties en morphing ne sont pas encore pris en compte.
Les morph targets
Qu’est-ce qu’un morph target ?
Plutôt qu'animer un mesh en utilisant des bones et un squelette (skin ou rig), qui déforment la forme de base (l'ensemble des vertex-vertices), on passe directement la déformation voulue (avec plusieurs tableaux des positions des vertices).
Cette méthode est coûteuse en mémoire et est généralement réservée à l'animation des tissus ou des visages.
Dans ma classe OMesh_gltf, les morph targets sont animés sans passer par des VAO-VBO dédiés et des shaders spécifiques. C'est plus lent, mais plus simple pour de simples drapeaux, par exemple. Créez une classe spécifique et ses shaders si vos besoins sont plus grands (?).
Comment ça marche dans ECO ?
Voici la méthode d'affichage :
void Tmesh_gltf::draw(OShLight& shLight, TshGlass& shGlass)
{
OMat4 model1;
shLight.enable(); // le shader d'affichage, lumière simple
glDisable(GL_CULL_FACE);
// >> ici on vérifie qu'il y a une animation « squelette » en cours
// il s'agit ici d'un fichier GLTF, géré par a classe OMesh_gltf
if (mesh.anim_running())
{
// >> récupération des axes d'animation, selon l'animation en cours et le temps
std::vector<OMat4> axis;
mesh.anim_getAxis(axis);
// >> passage du résultat au shader
shLight.setBones(true);
shLight.setJointMat(axis); // >> dans le shader, les nouveaux axes déforment le mesh
}
else if (mesh.getAnimation_size() > 0)
{
// >> pas d'animation, on utilise la pose de base (calculée automatiquement dans OMesh_gltf)
shLight.setBones(true);
shLight.setJointMat(mesh.getAxisNeutral());
}
// >> Après la déformation générale, on cherche les parties du mesh qui ont une déformation
// par morph target. La classe OMesh_gltf charge automatiquement les morph targets,
// et si la partie du mesh en contient, elle applique la transformation)
mesh.anim_morph();
// pour chaque partie du mesh, on affiche
for (size_t i_par = 0; i_par < mesh.getPart_size(); i_par++)
{
if (!mesh.getPart_visibility(i_par)) continue;
shLight.setModel(m_model);
switch(mesh.getAnimation_mode(i_par))
{
case GLTF_ANIM_NULL:
shLight.setBones(false);
break;
case GLTF_ANIM_RIG:
// >> par exemple, le perso et ses mouvements par déformations des bones
shLight.setBones(true);
break;
case GLTF_ANIM_AXE:
// >> ce sont, par exemple, les équipements d'un personnage qui suivent son mouvement
shLight.setBones(false);
model1 = m_model;
model1 *= mesh.getJointOfPart(i_par);
shLight.setModel(model1);
break;
case GLTF_ANIM_MORPH:
// >> ne pas oublier, car si setBones est en valeur TRUE,
// le shader va appliquer les transformations par bone
shLight.setBones(false);
break;
default:
shLight.setBones(false);
break;
}
// >> dessin du mesh, OMesh_gltf gère l'affichage de chaque partie
shLight.setTextures(mesh.getId_diffuseMap(i_par), mesh.getId_normalMap(i_par) );
mesh.draw(i_par);
}
mesh.end_draw_part();
shLight.setBones(false);
}