J'ai déjà commencé !
J'envisage de commencer plus tard.
Je ne participerai pas.
J'aimerais bien mais je peux pas je suis jury....
Merci à gbdivers pour les réponses.
J'ai effectué un calcul automatique des normales et voici un premier résultat (lumière ultra simpliste, vu que c'était pour tester les normales (en théorie, il faudrait les dessiner ...))
-> http://www.developpez.net/forums/d10...n/#post6060041
J'ai utilisé la méthode que j'ai expliqué sur la page précédente ... donc aucune difficulté (enfin pas pour moi du moins) et cela a même fonctionner du premier coup (donc j'ai eu de la chance sur l'ordre des vecteurs).
Pour avoir des effets de lumières moins abruptes, j'ai tout de même effectuer une opération supplémentaire que je n'avais pas expliquer sur la page précédente. C'est un truc tout simple, donc pas la peine de chercher loin (j'ai pas le niveau 1ière S en math )
Pour résumé le principe de calcul des normales, en pseudo-code, ça donne quelque chose comme ça :
Pour amélioré le rendu, il est également possible de calculer dans un second temps le vecteur normal pour chaque vertex en prenant la moyenne de chaque vecteur normal des triangle ayant le vertex comme sommet.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 pour chaque triangle ABC (chaque point A, B et C est codé dans un QVector3D) calculer le vecteur AB ("QVector3D AB = B - A;") calculer le vecteur AC ("QVector3D AC = C - A";) calculer le vecteur normal au triangle (en utilisant le produit vectoriel : "QVector3D n = QVector3D::crossProduct(AC, AB);" normaliser le vecteur ("n.normalize();")
Pour le principe de calcul des lumières, j'en ai parlé dans mon tutoriel : http://gbelz.developpez.com/remi-ach...page=opengl#L5
Pour les couleurs, voici à titre indicatif une proposition de couleurs par défaut :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 Type R G B Artery (artères) 1 0,101961 0,101961 Bladder (vessie) 0,6 1 0,6 Bone (os) 0,94902 0,94902 0,85098 Heart (cœur) 0,701961 0 0 Kidney (rein) 0,501961 0,2 0,101961 Liver (foie) 0,8 0,2 0,2 Lung (poumon) 1 0,8 0,901961 Pancreas 1 0,701961 0,4 PortalVein (veine porte) 0 0 1 Skin (peau) 1 0,701961 0,54902 Spleen (rate) 0,6 0,101961 0,301961 Stomach (estomac) 0,6 0,6 1 SurrenalGland (glande surrénale) 1 0,6 0,301961 VenaCava (veine cave) 0,2 0,4 1 VenousSystem (système veineux) 0,2 0,4 1
Et bah, gbdivers à tout dit sur le calcul des normales (et surement mieux formuler que moi )
Et j'avais fait la petite amélioration d'une normale par vertex ... (donc il a cramé mon avantage )
Je pense que mon orientation est ok en prenant v2 - v1 / v3 - v2 (sachant que v1 / v2 / v3, c'est l'ordre donné dans les lignes des indices).
Le calcul est exactement le même que dans le tuto de gbdivers, et pour la spéculaire que je n'ai pas encore ajouté, il faut voir mon tuto
Et en ayant chargé tout les fichiers ... oui, il semble que l'orientation est la même pour toute les mesh. On voit d'ailleurs un nombril, que l'on ne peut pas remarquer sans l'éclairage .
Merci pour les couleurs ... je me demande comment faire une intégration correcte de ce genre de données
Je sais bien que je suis un peu pénible, mais je trouve ça moche d'avoir un deuxième fichier pour les couleurs (notamment car l'utilisateur doit donc charger deux fichiers à la main). Après, l'identification se fait au nom du fichier, ce qui est aussi un désavantage, car si je change le nom du fichier j’obtiens quelque chose de "faux'
Donc le mieux, c'est de se faire son fichier .trian ... mais j'essaie de garder une compatibilité avec le défi
Sinon, bien sur, je savais comment charger / lire / faire mon fichier de couleur
Mais non, mais non...
En pratique, tu n'as pas 2 fichiers à ouvrir "à la main" mais beaucoup plus, puisque chaque organe est dans un fichier séparé. Et tu n'es pas obligé d'ouvrir en même temps le fichier de couleurs et les autres.
Quand à changer le nom ou le contenu des fichiers .trian, tu fais comme tu veux. Dans la "vie réelle", ces fichiers seraient fournit par le scanner ou l'irm directement au serveur. Mais ensuite, le serveur fait ce qu'il veut de ces fichiers : renommer, modifier, compacter, élaguer, laver, repeindre, etc.
Bref, débrouillez vous
Hum, je suis un peu perplexe donc.
à un moment, on nous dit, voici les fichiers trian que vous devez géré. Et après, on nous dit, vous pouvez tout casser, les gérer autrement et tout ...
Enfin, disons que les fichiers .trian viennent du scanner, donc il me faut une étape de transformation ... par le serveur. Pour répondre au mieux aux critères et au monde réel.
Sinon, ce matin, mais je n'ai pas vérifié, j'ai pensé qu'un problème similaire se posera sur les données ECG. C'est dans le sens, que nous avons des données (cool ) mais que nous ne savons pas ce que cela représente.
Pardon, j'ai un peu mal posé la question ...
C'est dans le sens si un patient à plusieurs graphismes, il faut un nom pour les axes et des échelles pour les courbes. Votre fichier ne contient pas ces informations (qui me semble nécessaires)
De plus, si vous nous donnez des fichiers, et qu'il faut juste s'en servir pour base, alors ... autant que je prenne simplement les .obj ... au lieu de faire un parseur pour .trian :p
Je commence à croire que le défi est un peu flou sur les requis, notamment dans les fichiers à supporter, ou comment les supporter. Si ce n'est qu'un exemple, je peux vraiment partir sur ce que je veux alors ... alors que si vous me dites, voilà les fichiers 3D que donne le scanner, vous devez les prendre en charge pour pouvoir avoir les infos du scanner, c'est tout autre chose (car il y au moins une obligation)
Un ECG, c'est un ECG... On ne met généralement rien sur les axes, c'est sous-tendu au type d'examen, le personnel qualifié sait très bien ce que c'est et n'a pas besoin de détails.
Ce sont des données d'exemples, libre à toi d'aller faire tout à fait autre chose ou de les utiliser !
Ce n'est pas flou, c'est libre . C'est un exemple de fichiers qui peuvent ressortir du scanner... alors qu'il pourrait produire quelque chose de tout à fait différent ! Un hôpital n'a pas forcément des milliers de scanners, un seul est déjà bien suffisant pour certains, une application pour ce type de clients ne devra pas supporter des milliards de formats ; a contrario, pour une boucherie de plus grande ampleur, tout le matériel n'a pas forcément pu être acheté en même temps, il faut donc que le logiciel puisse tous les reconnaître.
Si tu pars sur d'autres formats de fichiers, il faut garder en tête que ton application doit être rendue complète, c'est-à-dire avec suffisamment de données pour tester tous les modules.
La seule chose réellement intéressante, c'est l'axe des abscisses (le temps) et cette information est donnée (1 point = 1 ms)C'est dans le sens si un patient à plusieurs graphismes, il faut un nom pour les axes et des échelles pour les courbes. Votre fichier ne contient pas ces informations (qui me semble nécessaires)
Tu peux utiliser les formats que tu veux mais :De plus, si vous nous donnez des fichiers, et qu'il faut juste s'en servir pour base, alors ... autant que je prenne simplement les .obj ... au lieu de faire un parseur pour .trian :p
- (comme tu l'as dit toi même) les fichiers .trian sont très simples à prendre en charge
- tu n'as pas le droit d'utiliser une lib pour lire les formats 3D si ce n'est pas une lib destinée à Qt
Mais ces données ne sont là que pour vous aider et vous orienter
Nous sommes déjà approximativement à la moitié du défi (lancé le premier juin), d'où la question suivante : où en êtes-vous ?
Nous avons déjà sept participations , mais pas encore beaucoup de détails sur les différentes participations : quels sont vos choix, orientations ? Plutôt QML ou pas du tout ? Auriez-vous quelques captures d'écran de ce que vous avez déjà fait ?
Bonjour, cela risque d'être compromis pour moi, tout a été décrit sur le papier, je comptais utiliser le dernier mois afin de tout coder et mettre en place, cependant je dois partir en séjour linguistique pendant 5 semaines sans ordinateur perso sous la main.
Moi, perso je suis perplexe. Déjà la moitié du défi et déjà si peux de fait ... enfin ... cela ne m'inquiète pas trop le pire
Donc ça avance, calmement (Plus de précision sur le fil de discussion des geekologues )
C'est bien dommage, bien que, maintenant que tout est pensé, le développement pourrait aller beaucoup plus vite... et il te restera un peu de temps à la fin août pour ça !
En général, le gros du projet se fait dans les derniers instants, derniers jours, donc pas de panique ! L'idéal étant de ne plus devoir faire que du bugfixing les deux dernières semaines, mais il faut s'organiser pas mal pour y arriver, mais surtout rejeter la procrastination (tout le monde est touché ).
Bonjour,
Pour ma part, j'ai déjà bien avancé dans la réalisation du serveur et le client commence à voir apparaître son interface graphique en QML.
À la base, je comptais faire l'interface graphique en QML et laisser la partie C++ lui dire quoi afficher quand et que faire quand. Sauf que ce serait dénaturer l'idée initiale de QML, c'est-à-dire de séparer la partie graphique de la partie logique d'une application. Toutefois, si l'on réfléchit sur le concept, on va logiquement avoir besoin de quelque chose pour faire la connexion entre le C++ et QML.
On pourrait accéder directement aux données via le rootObject() du QDeclarativeView/QDeclarativeEngine et y faire du setProperty() à la va-vite et dire que l'affaire est jouée. Ce serait sortir de l'idée initiale car il vaut mieux que la partie logique n'ait pas connaissance de l'arborescence du QML de l'IU. D'autant plus que si l'on veut accéder à un enfant de l'élément en haut de l'arbre QML, la consommation en ressource ne serait pas moindre.
Alternative, définir un nouvel élément QML en créant une classe C++ héritant de QObject (et éventuellement de QDeclarativeItem si l'on veut que le résultat soit graphique) et appeler qmlRegisterType<Nom>("X", 1, 0, "Nom") puis l'utiliser dans le code avec :
Toutefois, avec ce code-ci, on va devoir passer par la première solution pour changer la valeur de l'item ancre :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 import QtQuick 1.0 import X 1.0 Nom { id: ancreEntreQMLetCPP property: value }
Ce qui revient à la solution hacky initiale.
Code : Sélectionner tout - Visualiser dans une fenêtre à part view->rootObject()->setProperty("property", xxx);
La dernière possibilité que j'ai explorée correspond à la même chose en mieux, les contextProperties. Cela correspond plus ou moins à passer l'instance d'une classe héritant directement ou non de QObject au QML pour lui permettre de s'en servir tel une variable globale.
Avec _anchor, une instance d'une classe dérivant de QObject. De là, on peut changer ses propriété dans le code C++ à notre guise sans avoir à aller titiller la partie QML, qui exploitera quant à elle l'instance par le biais de "anchor" :
Code : Sélectionner tout - Visualiser dans une fenêtre à part declarativeview->rootContext()->setContextProperty("anchor", _anchor);
Une question que les gens qui ont touché à ça se poseront peut-être ? Comment actualiser la valeur de backgroundColor côté C++ de manière à ce qu'il y ait un changement dans l'interface graphique ? Si l'on définit la propriété backgroundColor comme ceci :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 Rectangle { color: anchor.backgroundColor }
Ce ne sera pas possible. Il faut ajouter un NOTIFYier dans la propriété :
Code : Sélectionner tout - Visualiser dans une fenêtre à part Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor)
De là, le contenu de l'IU s'actualisera tout seul lors d'un changement de propriété. De même, côté QML, on pourra appeler toutes les fonctions Q_INVOKABLEs de la contextProperty anchor :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor NOTIFY backgroundColorChanged) ... QColor backgroundColor() const { return _backgroundColor; } void setBackgroundColor(const QColor &color) { _backgroundColor = color; emit backgroundColorChanged(); }
Si vous souhaitez en savoir plus sur les Q_PROPERTY, Q_INVOKABLE et compagnie, référez-vous à mon article : http://louis-du-verdier.developpez.com/qt/fondations/
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 // C++ : public: Q_INVOKABLE void doSomething(); // QML : onClicked: anchor.doSomething()
Je m'égare... où en étais-je... ici :
Ce que j'ai détaillé au-dessus est un moyen idéal de relier l'interface graphique en QML avec la partie logique en C++. C'est également un point qui va pousser n'importe qui à tenter de tirer le maximum possible de QML et de son JS, tout en "gettant" et "sendant" certaines données depuis/au C++ pour réaliser l'application.Envoyé par Amnell
Ainsi, j'ai quitté mon idée initiale de juste dessiner les élément de la GUI en QML puis de les afficher avec des QDeclarativeTruc pour choisir l'option séparation de la partie graphique de la partie logique avec lien entre les deux fait par une contextProperty. Au final, de quoi récupérer pas mal de points vu que QML aura un grand rôle dans l'affaire.
Espérant avoir donné un coup de pouce à ceux qui étaient dans le besoin,
Amnell.
Partager