Dan's Orbiter page
Orbiter Francophone => Création Orbiter Francophone => Topic started by: DanSteph on 14 May 2008, 02:23:20
-
Par requète j'ouvre un nouveau fil "posez vos questions", il servira probablement bientôt, si vous ne programmez pas des dll actuellement évitez de polluer ce fil.
Ce post sera listé dans dans la série "tutorial DLL pour Orbiter"dispo ici:
http://orbiter.dansteph.com/forum/index.php?topic=6335.msg95352#msg95352
Vos questions et nos réponses (on peut etre plusieurs à répondre) serons
donc immortalisée et peut être utile à d'autres qui auront eu les mêmes
questions/probleme que vous.
Questions sur le C++,sur la SDK orbiter ou sur VC++ bienvenue.
Rappellez vous, y a pas de questions bêtes, mais essayez d'éviter le off-topic
et les blabla pour garder le post assez informatif.
A vos claviers !
NOTE: ce fil est le deuxième de la série "posez vos question sur les dll" vous pouvez trouver le premier qui a
été fermé car très long ici: http://orbiter.dansteph.com/forum/index.php?topic=6342.msg95437#msg95437
Message modifié ( 14-05-2008 03:04 )
-
Avec Visual C++ Express Edition, lorsqu'on crée un nouveau projet, le seul modèle disponible en application WIN32
est l'application console.
Comme la structure ne correspond pas avec la création d'une DLL, j'ai cherché dans l'aide si il est possible de charger
un modèle DLL mais je n'ai pas trouvé de solution ce qui m'a imposé de partir d'un projet existant, ShuttlePB en
l'occurence.
Quelle est la meilleure solution à retenir pour un développement en partant d'un exemple ?
:sage: Papyref
-
Avec Visual C++ Express Edition, lorsqu'on crée un nouveau projet, le seul modèle disponible en application
WIN32 est l'application console.
Oui, c'est l'express edition, tellement rapide que tout est en .exe >_<
Désolé mais ma version est en anglais...
File -> New -> Project from existing code -> renseigner les champs obligatoires et dans "Project type" choisir
"Dynamically linked library (DLL) project".
Plus sérieusement ces guignoleries m'agacent, c'est aussi simple d'utiliser un ancien projet et d'éditer à la main les
fichiers .sln et .vcproj!!!
Compile en Multi-threaded (/MT), çà t'évitera d'être dépendant des "VC++2005 runtime libraries".
[ properties->C/C++->Code Generation-> Runtime librarie -> Multi-Threaded (/MT) ]
En parlant du shuttlePB, une petite remarque qui peut être importante pour la suite de l'apprentissage:
Le modèle RCS du shuttlePB n'est pas compatible avec AttitudeMFD, LandMFD, LolaMFD et la plupart des MFD
possédant un contrôle des moteurs d'attitude (IMFD fonctionne bien malgrès tout car un beau jour dans l'été 2007,
j'ai contacté Jarmonik pour remonter ce bug).
Il vaut mieux préférer le modèle present dans le code du DeltaGlider ou n'importe quel autre modéle du moment que
les thg ne possèdent pas plus de 2 th (oui, enfin bref, si il y a plus de 2 tuyères impliquées c'est pas bon).
-
Merci !
Effictivement la gestion des RCS de ShuttkePB est plutôt merdique. Je vais m'orienter sur celle du DeltaGlider
:sage: Papyref
-
Y-a-t-il un moyen de récupérer la taille d'affichage utilisée par orbiter?
Message modifié ( 17-05-2008 18:53 )
-
mhhhh...
Je récupère le handle de la window tout au début pour OrbiterSound avec ca tu peux appeller des fonctions
genre "getsize" de window ? (GetWindowRect ou "Rec" ?)
Si tu rame je te donnerais le détail...
A++
Dan
-
ok, je cerne mieux ce qu'il faut faire mais j'ai réglé le problème avec les polices et le HUD que j'avais sans avoir besoin
de la taille de la fenêtre finalement.
Il me reste par contre un truc vraiment bizarre avec un MFD.
Je compile sur mon premier pc, affichage en 1280x1024. Je teste aussi de 1024x768 à 1600x1200 pour savoir si les
résolutions classiques passent bien.
Sur ce pc, lorsque je teste le mfd en 1024x768, j'obtiens ce à quoi je m'attend:
(http://img207.imageshack.us/img207/1771/mfdgrmbl013wv7.jpg)
Sur mon vieux pc qui affiche en 1024x768 et orbiter en 1024x768 lorsque je teste le MFD, j'obtiens çà :
(http://img255.imageshack.us/img255/3084/mfdgrmbl2wb0.jpg)
:rant:
Donc, il y aurait une différence entre un affichage d'orbiter en 1024x768 sous un windows en 1280x1024 et 1024x768
sous un windows qui fonctionne en 1024x768 ???? Serait-ce du à la taille différente entre les 2 écrans (19 et 17
pouces), à la féquence différente entre les deux ecrans (85Hz contre 75Hz),
au choix de la police (HFONT hFont = (HFONT)GetStockObject(SYSTEM_FONT);...pas de quoi fouetter un chat!) ,
à une incantation mystique provenant d'un des pontes de microsoft (acheter Vista, tu dois!)???
Message modifié ( 18-05-2008 05:11 )
-
Ah, y à un gag avec les MFD et le HUD pour avoir toujours un affichage correct. Je crois que martin renvoie une
variable avec le rapport hauteur ligne bidule machin... me souviens plus désolé :sad:
Regarde peut etre dans l'exemple de MFD y a une variable "CT" ou dans le genre.
Dan
-
Oui, le hud, çà a été pénible mais vraiment pas insurmontable, j'avais choisi bêtement un police Arial avant de
m'apercevoir qu'elle devenait énorme ou trop fluette en 1024x768 suivant la taille choisie... avec system_font c'est ok.
Par contre, le coup du mfd me bluffe totalement (les deux screen sont en 1024x768 sur 2 écrans différents) mais je
crois que je viens de trouver une possible erreur plutôt interessante dans mon code...
-
mais je crois que je viens de trouver une possible erreur plutôt interessante dans mon code...
Ummmm....oui elle était pas mal celle-là d'erreur >_<
J'avais mis i au lieu de oapigetvesselCount()-i, mais evidemment dit comme çà çà ne raconte pas grand
chose...
-
Je merde pour définir une animation.
En utilisant les instructions de la doc API pour DefineAnimations, je me fait jeter avec UINT qui n'est pas je crois
accepté en C++. Il en est de même avec Static.
Quelle est la solution ?
C++ commence à me pomper car avec mes vieux yeux j'ai du mal à différencier [ et { par exemple, alors bonjour les
fautes de syntaxe !
:sage: Papyref
-
N'hesite pas à poster la partie de ton code qui pose problème. Là, la seule chose que je puisse te dire c'est
que UINT (unsigned int) ne pose pas de problème normalement en c++.
C++ commence à me pomper car avec mes vieux yeux j'ai du mal à différencier [ et { par exemple, alors bonjour les
fautes de syntaxe !
Çà ne remplace pas les yeux mais tu peux changer la police (et sa taille) utilisée par VC++:
menu tools-> Options...-> Environment-> Fonts and Colors
Message modifié ( 18-05-2008 19:54 )
-
Papyref a écrit:
Je merde pour définir une animation.
En utilisant les instructions de la doc API pour DefineAnimations, je me fait jeter avec UINT qui n'est pas je crois
accepté en C++. Il en est de même avec Static.
Quelle est la solution ?
C++ commence à me pomper car avec mes vieux yeux j'ai du mal à différencier [ et { par exemple, alors bonjour les
fautes de syntaxe !
:sage: Papyref
Tu pourrais changer la taille de police, va voir dans les options. N'oublie pas si pas déjà fait que tu peux coloriser le
code: http://orbiter.dansteph.com/forum/index.php?topic=6359.msg95780#msg95780
Pour UINT il est defini dans windef.h, un appui sur F1 en selectionnant "UINT" te donne cette information.
Par contre moi j'ai pas de #include "windef.h" dans mes codes donc il doit être defini
aussi dans un autre header. Au début du header du DGIV j'ai que ca:
#define STRICT
#include "orbitersdk.h"
#include "resource.h"
#include "..\OrbiterSoundSDK\OrbiterSoundSDK35.h"
#include <stdio.h>
A mon avis orbitersdk.h "include" lui-même "window.h" qui inclu lui même "windef.h"
NOTE SUR LES TYPES:
des types en majuscule et non colorisé (UINT, BOOL,VECTOR3) ne sont pas vraiment des types de base standard
comme:
int
float
Ce sont des types "custom" formée d'autre types de base soit fait plus ou moins en standard dans window
(BOOL, UINT) soit totalement défini par l'utilisateur (VECTOR3, MESHANDLE)
Ainsi si tu clique droit sur "UINT" tu trouve dans "windef.h" la déclaration de type:
typedef unsigned int UINT;
Donc "UINT" est un alias de "unsigned int" d'ailleur si tu utilise "unsigned int" pour ta variable ca marche aussi.
Ceci est extremement utile pour définir des type propre, ainsi le "MESHANDLE" de Martin n'est qu'un type:
void* un pointeur de type indéfini. (click droit sur une variable "voir definition" pour voir ou un type est
declaré)
Tout ca c'est très souple tu peux aussi faire en début de listing un:
typedef unsigned int PAPPY;
Et declarer une variable de type "PAPPY" qui sera égale au "UINT" ;)
Pour les anims attention il y a deux methodes. une ancienne et une nouvelle. Je continue dans un nouveau post:
....
Message modifié ( 18-05-2008 19:56 )
-
A mon avis orbitersdk.h "include" lui-même "window.h" qui inclu lui même "windef.h"
Oui, c'est idem chez moi, je n'ai jamais eu à l'inclure moi-même. En suivant le fil, on a:
windows.h qui inclus windef.h est inclus dans orbiterAPI.h qui se trouve être inclus dans Orbitersdk.h, lui-même inclus
dans la solution...faut suivre ^^
-
ANIMATION:
C'est pas la chose la plus simple à comprendre surtout du fait que c'est incroyablement souple mais le principe n'est
pas compliqué ni compliqué a mettre en oeuvre une fois qu'on à pigé. (c'est compliqué à expliquer du fait de la
souplesse)
Une animation ce défini dans clbksetclascap (ou fonction appellée par clbksetclasscap), Pour chaque animation on va
d'abord créer une animation vide avec la fonction:
CreateAnimation();
Ensuite on va définir à un endroit les caractéristiques comme no de mesh à animer, degre de liberté, axe de rotation
et puis passer ces données à une fonction:
AddAnimationComponent();
A la fin on obtient un "handle", c'est en passant de 0 a 1 à ce handle à chaque image (pour un mouvement) que
l'animation ce fera.
La lecture de la doc concernant ces deux fonctions est indispensable mais dans le principe on fait comme ca par
exemple pour une rotation:
1-Definir dans notre class vessel une variable de type MGROUP_ROTATE"
MGROUP_ROTATE *RadarTourne;
Dans clbkSetClassCap() (ou fonction appellée par clbksetclasscap) on donne d'abord quel partie du mesh va etre
concernée par cette animation, si par exemple c'est le bloc "3" du mesh:
static UINT GrpMeshRadar[1] = {3};
On peut définir plusieurs partie "bloc" du mesh par exemple si les groupes 3 et 14 forment le radar:
static UINT GrpMeshRadar[2] = {3,14};
Ensuite on défini les caracteristiques, axe, degre de rotation, no de mesh, position de départ dans le mesh etc etc
(voir doc MGROUP_ROTATE) par exemple:
RadarTourne= new MGROUP_ROTATE (0,GrpMeshRadar,1,_V(0,-1.9,-5.04),_V(1,0,0),(float)(2*PI));
En sortie on lui donne notre handle déclaré plus haut "RadarTourne"
Toutes nos données sont bonne , il nous reste plus qu'a créer l'animation dans Orbiter. Pour ce faire on utilise:
CreateAnimation et AddAnimationComponent.
En bref le code total donnerais par exemple pour une radar avec un seul groupe de mesh:
Declaration dans le header de la classe de notre vessel:
// animation radar
MGROUP_ROTATE *RadarTourne; // données animation pour fonction "AddAnimationComponent "
UINT uAnim_radar; // handle pour manipuler l'animation
Dans "clbkSetClassCap" ou fonction appellée par "clbkSetClassCap":
static UINT GrpMeshRadar[1] = {3};
RadarTourne= new MGROUP_ROTATE (0,GrpMeshRadar,1,_V(0,-1.9,-5.04),_V(1,0,0),(float)(2*PI));
uAnim_radar = CreateAnimation (1.0);
AddAnimationComponent (uAnim_radar, 0,1, RadarTourne);
Voila, ouf , terminé, nous pouvons maintenant utiliser en runtime notre animation avec la fonction:
SetAnimation();
Chaque appel positionnera le mesh , si par exemple nous aurions une mains qui s'ouvre lentement et que la position
fermée soit a 0.0 et ouverte à 1.0 nous appelerions une fois:
SetAnimation(0.0);
Et l'image suivante la main serais fermée (et le resterais jusqu'a un nouvel appel.
En pratique on va plutot l'utiliser dans "clbkPostStep" et l'appeller à chaque image avec une légere variation de la
valeur à chaque image pour que l'animation ce fasse.
Le dernier probleme est qu'il faut utiliser une compensation du temps (sinon à 200FPS l'anim durera 1 secondes et
50FPS 4 secondes) et utiliser quelques variables logiques pour savoir quand démarrer et arreter l'animation.
Encore une fois le principe est simple mais compliqué a expliquer. Voir dans les exemples avec "DOOR_CLOSING" etc
etc.
(hésite pas si tu à plus de questions ;)
OUF ! PFFFF y a pas plus compliqué a expliqué que les anims, c'est tellement souple, on peut faire des hierarchie avec
des parties qui glissent, tournent, tout ca commandé par un seul handle et "SetAnimation"... dingue !
A++
Dan
-
NOTE SUR LES GROUPES DES MESH:
Chaque partie d'une mesh (dans 3dmax groupe séparé) est aussi séparé dans les mesh de martin et sont numéroté
dans l'ordre de lecture du mesh.
Ainsi si on a un mesh de deux cubes le cubes 1 sera le numéro 0 et le cube 2 le numéro 1. (On peut lire les
fichiers ".msh" avec notepad)
Il ne reste qu'a passer ce ou ces numéros pour les animer:
exemple: static UINT GrpMeshRadar[1] = {1};
Le drame c'est que dès qu'on va tripoter le mesh dans 3dmax ou autre (supprimer un groupe par exemple) il y a de
grande chances que tout les numéros (ordre des groupes) changent. Chiant mais pas grave avec trois animations,
dramatique avec comme le DGIV plus de 60 animations (on y arrive vite croyez moi)
Il faut retrouver tout les groupes (dans un mesh de 40'000 poly et 200 groupes c'est coton), leurs numéro et éditer
tout notre code. On le fait une fois mais pas deux.
C'est pour cela que j'ai modifié le script d'export de 3dmax qui me crée maintenant aussi un fichier "header" en C++
"MeshHeader.h" a inclure dans notre projet, Il contient le nom du groupe défini avec à coté le nouveau numéro réel
du groupe.
Les première lignes de ce header ont cette gueule pour le DGIV :
#define GRP_SPSiege 0
#define GRP_ANIMcpit_exter 5
#define GRP_ANIMcpit_inter 16
#define GRP_airlock 17
#define GRP_ANIMrightmain0 21
#define GRP_ANIMrightnose0 22
#define GRP_ANIMleftnosed0 23
#define GRP_ANIMnosestrut0 24
#define GRP_ANIMleft_wheel_door 25
#define GRP_ANIMleftmaind0 26
#define GRP_ANIMright_whe0 27
Du coup à notre animation on ne lui passe plus le numéro de groupe mais le nom défini:
exemple: static UINT GrpMeshRadar[1] = {GRP_SPSiege};
Et a chaque modif du mesh il suffira de copier le nouveau header et de recompiler pour que toutes les anims soient bonne automatiquement.
Pour de petit projet ce n'est pas indispensable mais pour des truc plus consequent il est impossible de bosser tout a
la main, sachez donc qu'il existe cette possibilité (mais seulement avec 3dsmax désolé)
A++
Dan
Message modifié ( 18-05-2008 20:51 )
-
Toutes nos données sont bonne , il nous reste plus qu'a créer l'animation dans Orbiter. Pour ce faire on utilise:
CreateAnimation et AddAnimationComponent.
Il faut aussi effacer RadarTourne à la destruction, non?
MonAddon::~MonAddon ()
{
delete RadarTourne;
}
-
no matter a écrit:
Il faut aussi effacer RadarTourne à la destruction, non?
MonAddon::~MonAddon ()
{
delete RadarTourne;
}
Oui c'est mieux, me semblais pas vital pour la bonne marche et je voulais pas alourdir... ;)
(50 octets de leak à chaque lancement faudrais quelques millions de lancements pour crasher le PC)
Papy débute je pensais le laisser prendre ces marques au début avec juste l'essentiel et "pousser" dans la
complexité et les informations au fur et à mesure de ces questions et de son avancement.
Mais perso je fuis les allocations dynamique comme la peste, dans 95% des cas elle ne servent à rien à part prendre
un gros risque de leak si on oublie une désallocation. A la place de martin je n'aurais pas fait comme cela dans la SDK.
Dan
-
Merci Dan !
Comme j'ai déjà réalisé des animations un peu sophistiquées comme le DGArm en utilisant Spacecraft, je pense que
je vais arriver à m'en sortir avec tes conseils.
Pour l'instant je cherche seulement à réaliser ce que j'ai déjà fait sans chercher l'exploit pour comprendre les
principes sans chercher à traiter des interactions complexes.
Si je n'y arrive pas je me suicide :) J'ai d'ailleurs essayé il y a quelques jours en prenant un premier bain de mer pour
2008 avec une eau dans les 14°C !!! Ca raffermit les chairs....
:sage: Papyref
-
Hésite pas à poser des questions précise, voir poster des bouts de code qui ne marchent pas.
On peut être plus utile et donner des informations plus pointues sur des points précis que de faire un tuto complet
sur tout le sujet. (il serait énorme sur les anims pour traiter tout les cas malgré que le principe soit simple)
14°C pour un type habitué à ce rafraichir en ouvrant un hublot de la station papy bar c'est de la gnognotte...
aucune crainte :)
(Par contre les caisses de bière stockées à l'exterieurs... c'est moyen la kronenbourg à -270°)
Dan
-
DanSteph a écrit:
Par contre les caisses de bière stockées à l'exterieurs... c'est moyen la kronenbourg à -270°
Dan
sa se bois frais la bierre :badsmile: .
Message modifié ( 19-05-2008 13:58 )
-
Au lieu de dire des bétises,
J'ai fais un système de refuel et je voudrais savoir la technique pour rendre ce type de système fps indépendant car
comme tous ce qui est dans la fonction clbkPostStep la vitesse dépend du fps...
-
J'ai créé ce groupe d'animation pour une porte. Les paramètres initiaux restent à vérifier
void MonAddon::DefineAnimations (void)
{
static UINT GrpMeshLeftDoor[1] = {49};
PorteOuvre = new MGROUP_ROTATE (0, GrpMeshLeftDoor,1, _V(6.7,7,0), _V(0,0,1), float(0.5*PI));
uAnim_leftDoor = CreateAnimation (1.0);
AddAnimationComponent (uAnim_leftDoor,0 ,1, PorteOuvre) ;
}
J'ai définit les variables en ClassVessel
MGROUP_ROTATE *PorteOuvre;
UINT uAnim_leftDoor;
Et comme je ne me fais pas jeter en compilant je pense que c'est bon jusque là.
C'est maintenant que je pédale. Est ce qu'il faut déclarer et utiiser cette animation dans clbkPostStep ? ou
autrement ?
J'avoue être un peu découragé après un certain nombre d'essais loupés et je pense que je vais mettre un terme à
cette expérience avant de me liquéfier le peu de méninges qui me restent !
:wall: Papyref
-
Tout va bien papyref ;) pour la gestion de ta porte :
Dans ton fichier.h, tu déclares 2 variables supplémentaires:
double door_proc;
enum DoorStatus { DOOR_CLOSED, DOOR_CLOSING, DOOR_OPENING, DOOR_OPEN } door_status;
dans ton contructeur :
door_proc = 0;
door_status = DOOR_CLOSED; // si tu veux qu'elle soit fermée par défaut
dans la méthode clbkPostStep :
if (gear_status == GEAR_OPENING || gear_status == GEAR_CLOSING)
{
double dg = simdt * DOOR_OPERATING_SPEED; // double DOOR_OPERATING_SPEED = 0.5;
if (door_status == DOOR_CLOSING)
{
if (door_proc > 0.0)
door_proc = max (0.0, door_proc-dg);
else
door_status = DOOR_CLOSED;
}
else
{
if (door_proc < 1.0)
door_proc = min (1.0, door_proc+dg);
else
door_status = DOOR_OPEN;
}
}
SetAnimation (uAnim_leftDoor, door_proc);
}
[/color]
Tu crées ensuite une méthode :
void taClasse::RevertDoor()
{
if (door_status == DOOR_CLOSED|| door_status == DOOR_CLOSING)
door_status = DOOR_OPENING;
else if (door_status == DOOR_OPENING || door_status == DOOR_OPEN)
door_status = DOOR_CLOSING;
}
(déclare là dans ton .h)
et enfin, pour que ce soit effectif, dans ta méthode clbkConsumeBufferedKey :
if (!down)
{
return 0; // Seulement pression d'une touche (pas de touche enfoncée)
}
if (KEYMOD_SHIFT (kstate))
{
switch (key)
{
case OAPI_KEY_D: //Autrement si tu appuies sur SHIFT-D
RevertDoor();
return 1;
}
}
Pfiou ! Fini ;)
Message modifié ( 19-05-2008 17:48 )
-
Merci,
C'est bien ce que j'avais essayé mais j'ai dû me planter dans la syntaxe.
Je reprendrai ça demain parceque ma femme me harcèle :)
:sage: Papyref
-
Papyref a écrit:
Merci,
C'est bien ce que j'avais essayé mais j'ai dû me planter dans la syntaxe.
Je reprendrai ça demain parceque ma femme me harcèle :)
:sage: Papyref
Si tu as un soucis, envois moi le code, j'y jetterai un oeil ;)
-
Gat3rZ a écrit:
Au lieu de dire des bétises,
J'ai fais un système de refuel et je voudrais savoir la technique pour rendre ce type de système fps indépendant car
comme tous ce qui est dans la fonction clbkPostStep la vitesse dépend du fps...
Ça dépend beaucoup de ton système justement... mais quelques SetPropellantMass() conditionnés ne tueront pas
ton fps tout de même.
Evidemment, il vaut mieux sortir tout ce qu'il est possible du PostStep, j'essaie à mon niveau mais je ne pense pas
être en mesure de pouvoir vraiment t'aider là dessus...
Le PostStep du CTV est assez chargé après tout et le fps reste vraiment correct.
-
C'est pas un problème de lag, le problème c'est que la vitesse de refuel dépend des fps (et on voit bien la diférence)
je cherche un moyen pour que la vitesse de refuel soit constante malgré les fps.
Message modifié ( 19-05-2008 19:09 )
-
Tu ne peux rien y faire .... c'est ta machine qui décide ;) Et puis si tu veux du fps, ne code pas alors :) ... et puis bon,
contente toi d'optimiser le mesh de ton addon, pour ce qui est du code à proprement parler, tu optimiseras en temps
et en heure ...
-
C'est pas un problème de lag, le problème c'est que la vitesse de refuel dépend des fps (et on voit bien la
diférence) je cherche un moyen pour que la vitesse de refuel soit constante malgré les fps.
Ok, j'avais répondu à coté.
Tu peux récupérer le FPS avec oapiGetFrameRate() et peut-être compenser en fonction du résultat.
-
Ok merci je vais éssayer de bricoler quelque chose avec sa.
-
J'ai trover un truc tout bète :
SetFuelMass(GetFuelMass()+(1/oapiGetFrameRate()))
dans clbkPostStep
Le rate 1 est diviser par le nombre de fps mais au bout d'une seconde il est remultiplier par le nombre de fps par
lequel il c'est fait diviser.
Alors a moins que le fps change plusieurs fois en 1 sec sa le stabilise.
C'est corect comme moyen?
-
TIMING DES EVENEMENTS EN FONCTION DU FRAMERATE
Gat3rZ a écrit:
J'ai trover un truc tout bète :
SetFuelMass(GetFuelMass()+(1/oapiGetFrameRate()))
dans clbkPostStep
Ne prend pas le framerate qui est imprecis, ce qu'il faut c'est le temps en milliseconde ecoulé
depuis la dernière image et multiplier TOUT ce qui prend une durée (animation) par ce temps
la. (plus communément appelé "Delta time" ou DT)
Ceci va garantir l'indépendance d'événements vis à vis du framerate.
Exemple pour le fuel:
// on peut changer le facteur "*60" pour changer la vitesse de refuelling.
SetFuelMass(GetFuelMass()+(oapiGetSimStep()*60));
Même principe pour les anims.
Dan
-
Ah ok ... j'avais pas vu cette fonction oapiGetSimStep et je cherchais a faire ce qu'elle fait mais je trouvais sa trop
complexe donc je me suis resou a utiliser le calcul plus haut.
-
Il aurais fallu chercher du coté de "performance counter" qui descend
jusqu'à la microseconde mais comme martin le fait, pas besoin.
Dan
-
Pour ouvrir un MFD, j'utilise oapiOpenMFD (int mode, int id) qui ouvre le MFD mode sur le MFD
défini par id (MFD_LEFT, _RIGHT ou encore _USER1, _USER2, _USER3) .
Pour les MFD d'orbiter aucun problème:
oapiOpenMFD (MFD_COMMS, MFD_USER1); ouvre bien le MFD COM/NAV à l'emplacement USER1 que j'ai
défini.
Par contre, pour ouvrir un MFD autre que ceux d'orbiter, je n'ai pas trouvé le truc. Comme mode, on a :
MFD_NONE
MFD_ORBIT
MFD_SURFACE
MFD_MAP
MFD_HSI
MFD_LANDING
MFD_DOCKING
MFD_OPLANEALIGN
MFD_OSYNC
MFD_TRANSFER
MFD_USERTYPE
Je vois bien ce MFD_USERTYPE... mais je ne vois pas comment l'utiliser.
Est-il possible d'ouvrir un MFD autre que ceux livrés avec orbiter?
Comment?
D'avance: :wor:
-
no matter a écrit:
Est-il possible d'ouvrir un MFD autre que ceux livrés avec orbiter?
Comment?
Avec le boutton "mode" a coté de power :badlink:
Je sors ->
-
Quand je veux lancer un débogage, cette m... de Visual C++ me sort le message suivant et je ne vois pas pourquoi.
Quelqu'un peut il me dire ou est l'erreur ?
(http://img509.imageshack.us/img509/6194/yafss001aw4.jpg)
Merci
:sage: Papyref
-
c'est pas grave tu fait "oui" et sa roule.
-
Avec le boutton "mode" a coté de power
Rah, j'aurais du m'y attendre :ptdr:
Quand je veux lancer un débogage, cette m... de Visual C++ me sort le message suivant et je ne vois pas
pourquoi. Quelqu'un peut il me dire ou est l'erreur ?
Euh...oui...c'est normal (réflexion pensive....j'avais eu çà mais en anglais si mes souvenirs sont bons...), tu peux
continuer en répondant "Oui".
Vu que tu n'as pas généré Orbiter.exe en mode debug, c'est normal. Tu ne vas pas débugger Orbiter.exe mais ta dll.
Message modifié ( 20-05-2008 16:56 )
-
Même en insistant il y a des trucs qui le chagrine
(http://img241.imageshack.us/img241/7197/yafss001jc8.jpg)
Je ne vois pas ce que vient faire mon clavier Logitech dans cette affaire ?
:sage: Papyref
-
Alors la .... ya quelque chose qui a merder...
Faut demander a Dan
-
Papyref a écrit:
Quand je veux lancer un débogage, cette m... de Visual C++ me sort le message suivant et je ne vois pas pourquoi.
Quelqu'un peut il me dire ou est l'erreur ?
:sage: Papyref
Comme l'a dit No Matter c'est que l'executable Orbiter.exe ne contient aucune données de débug mais ta DLL
oui, donc c'est juste un message d'information il faut répondre "oui".
Papyref a écrit:
Je ne vois pas ce que vient faire mon clavier Logitech dans cette affaire ?
:sage: Papyref
En lancement debug VC++ te liste un peut toutes les DLL chargées par le programme ou le système. (Une DLL c'est exactement fait pour cela, être chargée quand un prog à besoin de certaines fonctions)
C'est tout à fait normal donc, tu dois en voir passer des dizaines: CRT, systèmes, clavier, souris, directX etc. etc.
"Aucun symbole chargé" ca veut dire que la DLL en question à été compilée en mode release
donc sans informations de debugging. (normal aussi)
A un moment tu peux voir passer ta DLL avec à coté "symbole de débogage chargé" ou un truc dans le genre.
Quand on compile en debug le code est parsemé d'informations et tourne dans
un cadre qui controle ce qui ce passe, ce qui permet l'execution pas a pas, la lecture
des variables etc etc. C'est pour cela que c'est un poil plus lent et qu'un prog ou
dll compilé en debug est plus gros.. (à cause des "symboles" de debug)
Moralité: tout baigne mais ne pas oublier de compiler en mode "release" avant de
publier un truc. Et (pour ceux qui ne connaissent pas encore) ne pas passer à coté
de l'importance du debugging, l'oublier c'est vouloir s'arracher pleins de cheveux
pour rien. Voir: "Comment debugger pas à pas sa DLL ?"
http://orbiter.dansteph.com/forum/index.php?topic=6336.msg95354#msg95354
Dan
Message modifié ( 20-05-2008 22:37 )
-
Je me demande quelque chose:
J'ai remarquer que l'on pouvait séparer les fonction en plusieurs ccp, mais je voudrais aller plus loin : quand j'aurais
un projet avec beaucoup de fonction et autres, au lieu de tous mètre dans un seul .cpp, .h et autres je pourrait les regrouper dans plusieurs
fichiers selon leurs catégorie mais si dans mon projet je les regroupes dans différents dossiers, il peut y avoir des problèmes
(pertes de perf, mauvaise compilations... je ne sait quoi) ? je pense que non mais je voudrait être sur.
Je pose la question car je voudrait prendre directement des habitudes d'organisation même si je ne suit pas encore a
des projets de cette ampleur.
Et sinon si il y a des petits "truc" a savoir sur ce sujet...
Message modifié ( 21-05-2008 18:14 )
-
Du moment que vc++ retrouve ses petits, que tous les fichiers ont leur chemin valide, çà ne pose pas de problème
j'imagine. D'ailleurs lorsque tu compiles, tu vas chercher des librairies ailleurs que dans ton répertoire de solution, des
.h et des .lib.
-
Gat3rZ a écrit:
fichiers selon leurs catégorie mais si dans mon projet je les regroupes dans différents dossiers, il peut y avoir des
problèmes (pertes de perf, mauvaise compilations... je ne sait quoi) ? je pense que non mais je voudrait être sur.
Je pose la question car je voudrait prendre directement des habitudes d'organisation même si je ne suit pas encore a
des projets de cette ampleur. Et sinon si il y a des petits "truc" a savoir sur ce sujet...
Si tu fait des fonctions "générique" qui peuvent servir dans de multiples projets je te conseil de les mettres dans des
librairies. Mais en général quand on débute ca ne sert à rien, on n'a pas assez de connaissances pour juger de la
pertinence d'une fonction pour d'autres projets ni pour les faire assez "générique". Donc on fait des libs qui ne
servent à rien. Pas adaptée, mal foutue, pas documentée (donc on ne retrouve plus les fonctions)
J'en ai eu fait mais évidemment elle ne m'ont jamais servie donc. Je n'en fais plus. Maintenant j'utilise le "copier/coller"
tout mes projets sont aux meme endroit et je fais des recherches comme expliqué dans ce tuto:
"Peu de mémoire beaucoup de méthode" http://orbiter.dansteph.com/forum/index.php?topic=6337.msg95356#msg95356
Sinon pour un même projet vaux mieu tout garder dans un seul répertoire. On peut spliter les h et cpp pour clarté de
lecture mais ca sert à rien de tout disperser sur le disque, au contraire.
Par contre le nom des sources et la manière de spliter sont eux très importantes pour tout retrouver rapidement.
donc pas de "essai21.cpp" mais plutôt "AnimationMesh.cpp"
Ici exemple d'organisation du projet DeltagliderIV (36387 lignes de code)
Le but est de tout avoir sous les yeux pour tout retrouver très rapidement.
(http://orbiter.dansteph.com/screenshot/dansteph/cppetheader.jpg)
A++
Dan
Message modifié ( 21-05-2008 21:50 )
-
Exactement ce que je voulait savoir, merci.
Sinon je me suis attaquer a un gros morceaux : les panels 2D.
Je me suis un peux embrouiller dans toutes les fonction nécessaires, je reprendrais sa demain soir , mais si
quelqu'un a du temps pour me bricoler un ptit exemple pour juste faire un bouton "toggle" ce serait sympa. Attention
je demande pas un truc près a compiler avec toute les ressources, juste les quelques lignes qui font que l'on peux
voir et appuyer sur un bouton ;) , pour le reste je me débrouille. l'exemple du shuttleA est un peux mélanger avec
d'autres choses et c'est pas très clair. Et le tuto sur les panels 2D ne l'explique pas (C'est marqué dedans vous allez
me dire).
Message modifié ( 21-05-2008 22:30 )
-
Correction commentée - Trucs pour tout le monde
Papy m'a envoyé sont projet, je vais faire ici une correction commentée pour souligner certains points important qui
peuvent vous bloquer ou faire que les choses ne marchent pas. Donner une "méthode" et des trucs plutot que
simplement corriger est beaucoup plus utile.
Donc papy vient de s'y mettre, il a modifié sont hercule et il vole, Bravo !
Par contre sur les animations (pas évident) ca coince, tout compile nickel mais rien, pas d'animations.
Donc je commence mon boulot de détective... Un bon programmeur n'est pas celui qui fait tout marcher du premier
coup (n'existe pas) Un bon programmeur c'est avant tout un excellent detective.
Au boulot Mr Watson.
De l'importance de l'indentation
Premier coup d'oeil, le code la partie qui m'intteresse est mal indenté, ceci pose d'énorme problème de lectures.
Si il y a une erreur de "logique" dans le code il est dur de la détecter. La présentation est importante il faut la soigner.
Code mal indenté: (par exemple on a l'impression que le premier "if" ne concerne que la premiere ligne, ce genre de
fausse "impression" peu nous faire perdre des heures)
(http://orbiter.dansteph.com/screenshot/dansteph/correctionpapy1.jpg)
Heureusement VC++ propose des utilitaires d'indentation automatique, pas besoin de s'embeter donc. Une fois le
code tapé si il est mal indenté (ou régulièrement) tapez:
CTRL+A (selectionne tout le texte du cpp présent)
ALT+F8 (indente automatiquement le code selectionné)
Et voila, beaucoup plus clair de voir la logique, le premier "if" englobe le reste etc etc:
(http://orbiter.dansteph.com/screenshot/dansteph/correctionpapy2.jpg)
Comment trouver ce qui ne marche pas ?
Votre code à l'air bon, mais ca ne marche pas. Pourquoi ?
La il faut de la méthode, en regardant "en vrac" et sans organisation des bouts de code on peut passer 50 fois sur
une erreur sans la voir. La méthode consiste à "remonter" le fil logique. Exemple avec une porte qui s'ouvre:
Pour ouvrir une porte il faut une main qui actionne la poignée, il faut donc une poignée, il faut que la poignée marche,
il faut des gonds , il faut que les gond marchent... vous voyez la logique ?
Sans organisation on peut passer des heures à controller en vrac toutes la mécanique de la porte alors qu'il nous
manquait simplement la main peut etre ?
Donc avec le code plus haut pour le problème d'animation de papy je cherche à un bout de la chaine, l'instruction
finale "SetAnimation" (La main) il peut y avoir plusieurs problemes:
SetAnimation (uAnim_PorteGauche , PorteGauche_proc);
1-Defaut de logique, elle n'est jamais declenchée (le "if" est faux)
2-Defaut de parametres, le "handle" est inccorrecte ou la valeur 0->1 qui fait l'animation ne change jamais ou hors
limite.
La méthode la plus évidente est de controller en débug (execution "pas a pas") , un point d'arret sur
l'instruction "SetAnimation ", on lance le programme et on regarde ce qui ce passe.
NOTE: sans debug pas à pas personne n'ira très loin, c'est vital, voir donc le tuto la dessus:
http://orbiter.dansteph.com/forum/index.php?topic=6336.msg95354#msg95354
Donc je lance, rien, SetAnimation n'est jamais appellé. Je met un point d'arret plus haut sur le "if" et la le programme
s'arrette et je vois ceci:
(http://orbiter.dansteph.com/screenshot/dansteph/correctionpapy3.jpg)
Horreur !, notre variable qui est sensé prendre la valeur 1 ou 0 pour passer le if contient "-842150451", aucune
chance de de declencher l'anim donc. Pourquoi quoi cette valeur ?
-Dans une classe les variables ne sont jamais initialisée par défaut ! elle prennent n'importe quel valeur. Je vais pas
rentrer dans les explications complexe mais le truc à retenir de vital !!!! c'est:
REGLE INVARIABLE: Toute variable déclarée dans votre classe ("class" dans le fichier ".h" ) doit
être initialisée avec une valeur valide dans "clbkSetClassCap()" qui est la fonction d'initialisation d'un vessel
Orbiter
Donc : chaque fois qu'on rajoute une variable dans la classe (par ici si vous ne voyez pas):
(http://orbiter.dansteph.com/screenshot/dansteph/correctionpapy4.jpg)
On l'initialise dans clbkSetClassCap à une valeur valide pour notre programme:
(http://orbiter.dansteph.com/screenshot/dansteph/correctionpapy5.jpg)
Voila, c'était les "méthodes" qu'il me semblait importante de souligner. Pour le reste j'ecris à papy en PM.
A++
Dan
Message modifié ( 22-05-2008 05:44 )
-
Merci Dan je vais essayer de corriger mais il faut d"abord que mon debug fonctionne.
:sage: Papyref
-
Mes animations marchent (pas encore toutes) et le debug fonctionne . Je ne sais pas encore de façon sûre pourquoi il
ne fonctionnait pas mais j'ai peut être une piste ?
Bon WE
:sage: Papyref
-
Cool !
Peut être spacecraft et la similarité des noms ? En tout cas une cause exogène il semble.
Mais rassure toi, les CTD "bizarre" sont assez rare. En général on a fait une bêtise dans
le code et on la trouve rapidement.
A++
Dan
-
Question probablement bête !
Pour animer une trappe faite de deux meshes par exemple j'écris:
static UINT GrpMeshTrappeDroit[2] = {72,73};
TrappeDroitOuvre = new MGROUP_ROTATE (0, GrpMeshTrappeDroit,2, _V(-7,-7,0), _V(0,0,1), float(-0.7*PI));
Pour définir ce que doit faire le GrpMesh et de quoi il est constitué.
Je pense que dans ce cas par exemple un petit tableau de données est constitué avec les deux meshes cités en
première ligne et que ces données vont être utilisées pour construire le groupe.
Dans l'initialisation des variables de classe on écrit
TrappeDroitOuvre =NULL;
qui mets le pointeur à zéro.
Que se passerait il si on ne mettait pas le pointeur à zéro ? Je ne vois pas de différence en testant l'animation !
:sage: Papyref
-
Papyref a écrit:
static UINT GrpMeshTrappeDroit[2] = {72,73};
TrappeDroitOuvre = new MGROUP_ROTATE (0, GrpMeshTrappeDroit,2, _V(-7,-7,0), _V(0,0,1), float(-0.7*PI));
Pour définir ce que doit faire le GrpMesh et de quoi il est constitué.
Je pense que dans ce cas par exemple un petit tableau de données est constitué avec les deux meshes cités en
première ligne et que ces données vont être utilisées pour construire le groupe.
Exact, ne pas oublier de mettre le nombre d'entrée du tableaux en parametres je crois que c'est celui la (que tu a
bien mis à 2): (0, GrpMeshTrappeDroit,2, _V(-7,-7,0), _V(0,0,1), float(-0.7*PI));
Le mettre faux peu faire des plantées.
Papyref a écrit:
Dans l'initialisation des variables de classe on écrit
TrappeDroitOuvre =NULL;
qui mets le pointeur à zéro.
Que se passerait il si on ne mettait pas le pointeur à zéro ? Je ne vois pas de différence en testant l'animation !
Pour autant que tu n'aie fais aucune erreurs et dans ce cas précis aucuns avantages vu que la variable est assignée
par le "TrappeDroitOuvre=new" avant utilisation. Donc qu'elle aie une valeur indéfinie (n'importe quoi) ou
0 (NULL) avant cette assignation ca ne change rien.
Mais ca ne change pas la rêgle imuable: "toutes variables de classe doivent être initialisée" et j'explique pourquoi.
1-Imagine que tu à fais une erreur au niveau du "new" tu part en débug tu controle ton pointeur quand il doit être
utilisé et comme tu ne l'a pas initialisé à zéro tu vois une valeur "0x3A45FFE" tu te dis "il est valide" et tu perd trois
heures et 1247 cheveux à chercher ailleurs le problème. Avec initialisation tu voit tout de suite qu'il est "null" au
moment de l'utilisation: tu tiens ton bug !
2-Rêgle immuable: tout pointeur invalide doit obligatoirement être à zéro (NULL)
Les pointeurs invalides sont une des premières cause de CTD, une fois le programme touffu avec pleins de
pointeurs ca devient un casse tête si on n'a pas pris dès le début cette bonne habitude.
Donc à l'initialisation= NULL et quand on les "détruit" on devrais toujours utiliser des fonctions de "delete" qui
remettent en plus le pointeur à zéro. (cf: SafeDelete() )
Ca permet en plus de mettre toutes les fonctions sensibles qui utilisent des pointeurs derrières des conditions qui
vont toutes assumer qu'un pointeur à zéro est invalide et valide sinon:
if(cMonPointeur!=NULL) // passe seulement si pointeur non null
{
ExecuteFonctionSensible(MonPointeur); // aucun risque de CTD
}
3- une variable de classe non initialisée est une cause fréquente de bug chez le débutant (et même plus tard)
4-Même si ce n'est pas absolument indispensable comme dans ton cas, le fait d'initialiser systématiquement tes
valeurs de classes va t'inculquer un véritable reflexe salutaire: "1-j'ajoute dans la classe, 2-j'initialise"
qui va te prémunir contre des oublis (on oublie déjà assez de trucs comme cela pour prendre en plus de mauvaises
habitudes)
5- Même si il n'y a pas absolument besoin dans un cas précis imagine que tu change un peu ton code et que maintenant tu aurais besoin quelle soit initialisée, comment fera tu pour gêrer le fait que tu à une moitié de variables initialisée et l'autre pas... tout recontroller ?
Donc pour toutes ces raisons, variables, pointeur, tableaux, tout ce qui est declaré dans la classe devrait être à 100% initialisé après le constructeur (clbkSetClassCap dans notre cas)
Ca répond ?
A++
Dan
Message modifié ( 28-05-2008 11:04 )
-
OK merci Dan !
Papy
-
J'ai créé une animation pour les portes avec SetAnimation (uAnim_Porte , Porte_proc);
Elle fonctionne bien avec le Keyboard en passant par un RevertPorte ().
Il me semble qu'une animation étant caractérisée par son status et sa procédure, ce sont ces paramètres que je dois
sauvegarder dans le scénario.
J'ai donc écrit ce qui suit pour sauvegarder dans le scénario puis recharger:
void Hercule::clbkSaveState(FILEHANDLE scn)
{
char cbuf [256];
VESSEL2::clbkSaveState (scn);
sprintf (cbuf," %d %0.4f",Porte_status,Porte_proc);
oapiWriteScenario_string (scn,"PORTE", cbuf);
}
void Hercule::clbkLoadStateEx(FILEHANDLE scn, void *vs)
{
char *line;
while (oapiReadScenario_nextline (scn, line))
{
if (!_strnicmp (line, "PORTE", 5))
{
sscanf (line+5, "%d %0.4f", &Porte_status,&Porte_proc);
}
else
{
ParseScenarioLineEx (line, vs);
}
}
SetAnimation (uAnim_Porte , Porte_proc);
}
Si je sauvegarde avec les portes fermées j'obtiens dans le scénario PORTE 0 0.0000 et si je sauvegarde portes
ouvertes j'obtiens 3 1.0000
Quand je relance mon scénario sauvegardé portes ouvertes, les portes sont fermées. Ca aurait été trop beau si ça
avait marché !
Ou est mon erreur d'interprétation ?
:sick: PoorPapyref
-
Si je sauvegarde avec les portes fermées j'obtiens dans le scénario PORTE 0 0.0000 et si je sauvegarde
portes ouvertes j'obtiens 3 1.0000
SetAnimation (uAnim_Porte , Porte_proc); est bien dans clbkPostCreation?
EDIT:
Il me semble qu'une animation étant caractérisée par son status et sa procédure, ce sont ces paramètres que je dois sauvegarder dans le scénario.
Absolument et il me semble que cette partie-là est ecrite correctement dans ton code, d'ailleurs le scénario sauvegardé le confirme. L'erreur vient plutôt ensuite, après la lecture au moment d'initialiser l'animation, d'où mon idée sur SetAnimation().
Message modifié ( 28-05-2008 18:14 )
-
Mon SetAnimation est en clbkPostStep et je ne vois pas trop pourquoi il ne marcherait pas ?
Le maitre aura peut être un avis. Je dois avoir oublié d'initialiser quelquechose
-
En effet, tel qu'il est écrit il est correct.
Lorsque tu recharges un scénario avec la porte ouverte, l'anim n'est pas initialisée dans l'état sauvegardé, tu te
retrouves donc avec porte fermée. Que se passe-t-il si tu lance l'anim?
La porte s'ouvre ou passe subitement de l'état fermé à l'état ouvert sans intermédiaire pour se refermer?
Sinon, effectivement, je ne vois pas d'erreur au niveau de ce que tu as posté.
J'utilise plutôt strnicmp (respect de la casse obligatoire) que _strnicmp (se fout royalement de la casse) mais ce n'est
pas le problème ici.
Message modifié ( 28-05-2008 18:53 )
-
En lançant le scénario suavegardé porte ouverte, la porte est fermée et il faut que je demande deux fois son
ouverture avec le clavier pour qu'elle fonctionne.
Son ouverture doit donc bien être demandée mais elle ne marche pas et la première demande doit réinitialiser et
permettre à la deuxième de s'éxecuter.
-
Papyref a écrit:
Mon SetAnimation est en clbkPostStep et je ne vois pas trop pourquoi il ne marcherait pas ?
Le maitre aura peut être un avis. Je dois avoir oublié d'initialiser quelquechose
Dans clbkPostStep le SetAnimation n'est executé QUE si le status de la port est "OPENING" ou "CLOSING"
donc si le status est CLOSED ou OPEN il n'est jamais executé. (ET ca DOIT rester comme cela!)
Donc le mettre en plus à la fin de "clbkLoadStateEx" EST la bonne solution.
Bon a savoir: Les callback sont appellé dans cet ordre au lancement:
1-ClbkSetClassCap
2-DefineAnimation (appellé par le précédent)
3-clbkLoadStateEX (animation valide, restore les variable, remet la porte à la position sauvegardée)
4-clbkPostStep
Par contre je te conseil fortement d'utiliser ma classe "saveRestore" plutot que la méthode par defaut d'Orbiter.
Ma methode est hyper simple une fois la classe incluse dans le projet et t'évitera beaucoup de prise de têtes avec les
saves restore des variables.
Classe SaveRestore à telecharger ici:
http://orbiter.dansteph.com/forum/index.php?topic=6381.msg96441#msg96441
Une fois installée et "loadState et "saveState" modifié exactement comme decrit dans l'instalation au début de
clbkSetClassCap inclure ceci:
void MonAddon::clbkSetClassCaps (FILEHANDLE cfg)
{
////////////////////////////////////////////////////////////
// DEFINI LES VARIABLES A SAUVER/RESTORER
// elle seront sauvées/resotrées automatiquement
// dans clbkSaveState et clbkLoadStateEx
////////////////////////////////////////////////////////////
Scn.InitClass(); // obligatoirement en premier
// Variables compressée (utilisation normale)
Scn.SavedVariable(0, &Porte_status);
Scn.SavedVariable(1, &Porte_proc);
Variante si tu veux garder des noms explicites dans le scenario:
void MonAddon::clbkSetClassCaps (FILEHANDLE cfg)
{
////////////////////////////////////////////////////////////
// DEFINI LES VARIABLES A SAUVER/RESTORER
// elle seront sauvées/resotrées automatiquement
// dans clbkSaveState et clbkLoadStateEx
////////////////////////////////////////////////////////////
Scn.InitClass(); // obligatoirement en premier
Scn.SavedVariable("DOOR_STATUS", &Porte_status);
Scn.SavedVariable("DOOR_STATE", &Porte_proc);
A la fin de "clbkLoadStateEx" rajoute en plus "SetAnimation" comme ci-dessous:
// --------------------------------------------------------------
// Read status from scenario file
// --------------------------------------------------------------
void ShuttlePB::clbkLoadStateEx (FILEHANDLE scn, void *vs)
{
char *line;
while (oapiReadScenario_nextline (scn, line))
{
if(Scn.LoadScenario(line)==TRUE)
continue;
ParseScenarioLineEx (line, vs); // unrecognised option - pass to Orbiter's generic parser
}
// ici les variables sont toutes restorées
// remet les portes à la bonne position
SetAnimation (uAnim_Porte , Porte_proc);
}
Message modifié ( 28-05-2008 20:55 )
-
Merci Maître.
Demain je revois ma copie !
:sage: Papyref
-
Classe SaveRestore à telecharger ici:
http://orbiter.dansteph.com/forum/index.php?topic=6381.msg96441#msg96441
A propos de cette classe justement, j'avais bien saisi l'intérêt mais j'avais raté ceci:
"cette classe offre en plus la possibilité de sauver des variables "non compressée" avec un nom pour garder la
possibilité d'édition"
Et dire que je l'ai pas utilisée jusqu'ici parce que je croyais que tout était compressé et non éditable dans le .scn.
Impardonnable ^^
Message modifié ( 28-05-2008 20:55 )
-
C'est clair que c'est un gain de temps et une source de prise de tête et d'erreur énormes supprimée.
Que ne l'ai je pas ecrite plus tot et utilisé dans le DGIII/IV :sad: ... j'ai perdu des heures et des milliers de cheveux avec l'ancienne methode. :pfff:
Par contre bien comprendre le principe:
Dans clbkSetClassCap on "marques" les variables comme "à sauver/restorer" mais elle ne sont pas sauvées ni restorées à cet endroit !!!!
Elle le seront automatiquement dans les fonctions "clbkLoadStateEx" et "clbkSaveState" si on doit remettre des
choses comme les animations le faire donc à la fin de "clbkLoadStateEx"
Dan
Message modifié ( 28-05-2008 21:02 )
-
Hello les gens :)
Je retrouve plus le topic qui parlait de l'édition de ressources, un peu indispensable pour refaire un projet au
propre (avant de venir pleurer pour un oui ou pour un non :badsmile: )
ps : j'ai changé de VS because la version de 97(!) marche pas avec OS3.5.
-
Hello Schimz,
Content de te voir dans le coin. :beer:
Si c'est ResEdit que tu cherches, ça en cause un peu là .... mais c'est un peu nul. :sad:
http://orbiter.dansteph.com/forum/index.php?topic=6342.msg95681#msg95681
Et là, le post de NoMatter, le troisième en partant du bas de la page
http://orbiter.dansteph.com/forum/index.php?topic=6342.msg95675#msg95675
Extrait :
Oui, la version express de VC++ ne permet pas d'éditer de fichier .rc.
Il faut passer par un autre logiciel pour les modifier, pr exemple:
http://www.resedit.net/ (doit y'en avoir d'autre...)
-
ok danke
-
Salut Schimz... content de te revoir ici également. Re-Bon-Vol parmis nous ;)
-
1 ére question
J'ai créé des animations de train droit et gauche avec parent pour des jambes de train se déplaçant en translation
entrainant un patin qui se déplace en rotation.
J'ai donc écrrit un truc comme ça:
//====================================================
//ANIMATIONS AVEC PARENT
//====================================================
ANIMATIONCOMPONENT_HANDLE parent;
//*** Jambes et patins du train
static UINT GrpMeshJambeGauche[4] = {11,12,15,16};
JambeGaucheOuvre = new MGROUP_TRANSLATE (0, GrpMeshJambeGauche,4, _V(1.5,-3.5,0));
static UINT GrpMeshPatinGauche[3] = {20,59,61};
PatinGaucheOuvre = new MGROUP_ROTATE (0, GrpMeshPatinGauche,3, _V(4.5,-4.9,0), _V(0,0,1), float(-0.166*PI));
uAnim_JambeGauche = CreateAnimation (0.0);
parent = AddAnimationComponent (uAnim_JambeGauche, 0, 1,JambeGaucheOuvre );
uAnim_PatinGauche = CreateAnimation (0.0);
AddAnimationComponent (uAnim_PatinGauche,0.2,1,PatinGaucheOuvre,parent);
static UINT GrpMeshJambeDroit[4] = {13,14,17,18};
JambeDroitOuvre = new MGROUP_TRANSLATE (0, GrpMeshJambeDroit,4, _V(-1.5,-3.5,0));
static UINT GrpMeshPatinDroit[3] = {19,58,60};
PatinDroitOuvre = new MGROUP_ROTATE (0, GrpMeshPatinDroit,3, _V(-4.5,-4.9,0), _V(0,0,1), float(0.166*PI));
uAnim_JambeDroit = CreateAnimation (0.0);
parent = AddAnimationComponent (uAnim_JambeDroit, 0, 1,JambeDroitOuvre );
uAnim_PatinDroit = CreateAnimation (0.0);
AddAnimationComponent (uAnim_PatinDroit,0.2,1,PatinDroitOuvre,parent);
} //*** FIN ANIMATION PARENT
Ca fonctionne mais j'ai un doute. Est ce que parent doit être réinitialisé pour chaque création sinon on risque des
ennuis. Si oui comment faudrait il procéder ?
Il ne me semble pas en regardant l'exemple du bras d'Atlantis mais j'aimerai en être sûr.
2ème question
Elle concerne la classe Save Load
J'ai procédé aux modifs conformément au post de Dan pour pouvoir obtenir la sauvegarde et le chargement dans le
scénario et fait l'init en clbkSetClassCaps
void Hercule::clbkSetClassCaps (FILEHANDLE cfg)
{
Scn.InitClass();
..............
Si je lance une compile j'ai le message ci dessous
1>Compilation en cours...
1>clbkSetClassCap.cpp
1>f:\orbiter\orbitersdk\samples\herculebidon\clbksetclasscap.cpp(13) : error C2065: 'Scn' : identificateur non déclaré
1>f:\orbiter\orbitersdk\samples\herculebidon\clbksetclasscap.cpp(13) : error C2228: la partie gauche de '.InitClass'
doit avoir un class/struct/union
1> le type est ''unknown-type''
1>Le journal de génération a été enregistré à
l'emplacement "file://f:\Orbiter\Orbitersdk\samples\HerculeBidon\Debug\BuildLog.htm"
1>Hercule - 2 erreur(s), 0 avertissement(s)
========== Génération : 0 a réussi, 1 a échoué, 0 mis à jour, 0 a été ignoré ==========
Quelle erreur ai je pu commettre pour obtenir ce message ésotérique ?
Merci pour tout renseignement qui sera récompensé par un pot au Papybar
:stupid: Papyref
-
Pour la 2ème question: t'as déclaré SaveRestore.h (ou quelque-chose comme ca) dans la classe?
-
Papyref a écrit:
1>f:\orbiter\orbitersdk\samples\herculebidon\clbksetclasscap.cpp(13) : error C2228: la partie gauche
de '.InitClass'
doit avoir un class/struct/union
1> le type est ''unknown-type''
1>Le journal de génération a été enregistré à
l'emplacement "file://f:\Orbiter\Orbitersdk\samples\HerculeBidon\Debug\BuildLog.htm"
il doit te manquer surtout le handle de la classe saverestore "Scn" en rouge:
#include "orbitersdk.h"
[color=blue]#include "SaveRestoreScenario.h"[/color] [color=green]// header du SDK [/color]
class Hercule:public VESSEL2
{
public:
Hercule(OBJHANDLE hVessel, int flightmodel): VESSEL2 (hVessel, flightmodel) {}
[color=red]SaveRestoreScenario Scn;[/color] [color=green]// handle de la classe[/color]
.....
}
Dan
Message modifié ( 02-06-2008 18:42 )
-
Problème réglé pour SaveRestore grâce à ton aide. Merci Dan !
Je ferai plus attention aux indentations dans les boucles...
Une question qui va paraître saugrenue : si on écrit MaFonction () est ce pareil que MaFonction (void) ?
:sage: Papyref l'édenté (pas l'indenté)
-
void veut dire... "rien"
Par defaut effectivement tu peux déclarer une fonction comme ceci:
Function()
{
}
Et le compilateur lui comprend que tu a voulu dire:
Function(void)
{
}
Donc pas de passage de parametres, "rien" en bref.
De même une fonction qui ne retourne rien comme valeur s'écrit:
void Function(void)
{
}
au contraire d'une qui retournerait une valeur int par exemple:
int Function(void)
{
return 1;
}
En bref pour répondre à ta question:
Si tu écrit: "Function()" tu peux éventuellement confondre avec un "appel" de la fonction plutôt qu'une déclaration.
Je trouve mieux d'être plus "verbeux" donc je mets des void.
IMPORTANT A propos d'être verbeux justement, voila un piège vicieux, ou comment une sois-disante
économie de lignes peut nous pourrir la vie.
Une condition qui ne contient qu'une seule ligne n'a pas besoin de crochets:
if(Tata)
CaMarche();
else
CaMarcheAussi2();
Et voila comment s'arracher les cheveux à peu de frais;
if(Tata)
CaMarche();
MaisPlusIci();
else
CaMarcheAussi2();
ET voui, sans crochets seule la ligne en dessous des if/else en dépend "MaisPlusIci()" sera exécuté à chaque fois.
C'est pour cela que JAMAIS je n'omets les crochets, même pour une condition à une seule ligne que je ne prévois pas
de modifier. (jamais jamais? ;)
// voila du rustique concu pour les intempéries
if(Tata)
{
CaMarche();
}
else
{
CaMarcheAussi2();
EtIciAussi();
}
C'est plus long (plus lisible aussi) mais aucune chance d'avoir des problèmes. Sur un gros projets ça peut faire toutes la différence entre un truc fragile voir buggé à mort et une application stable.
Les "grrrrand" théoriciens du C++ qui sévissent sur les forums spécialisés et hurlent à l'hérésie quand on prend une ligne de plus ou quand on est verbeux ne sont souvent pas ceux qui écrivent des applications. Ce sont des "poêtes" qui aiment le verbe pour le verbe, pas des techniciens.
Donc verbeux: "void" et crochets... En prenant toujours les même tics d'écriture "bourrine" on minimise les risques d'oublis. Les ciselures ca le fait pas, du rustique , du costaud !
Dan
Message modifié ( 08-06-2008 07:35 )
-
Tu as raison Dan, il vaut mieux un peu de verbiage que de se trouver plus tard comme une poule devant un cure
dents !
J'ai suivi ton conseil et fait un clbkPostStep_AnimAuto à partir du clbkPostStep pour écrire mes conditions
d'animations automatiquzs sur critères particuliers et ça clarifie bien le listing.
C'est une bonne méthode surtout pour un projet complexe !
Mon train rentre et sort seul au décollage et à l'atterrissage en l'asservissant à l'altitude et au sens de la vitesse de
montée et je suis assez content de moi. Il me reste à faire des tests plus complets pour voir qu'il n'y a pas de
blocage possible.
Les spécialistes vont me trouver un peu simpliste mais ça fait plaisir d'y arriver !
PapyC++
-
Papy, n'aurais-tu pas envie d'ouvrir un topic parallèlle à celui-ci pour que l'on puisse se faire une idée de ton projet en
cours avec photos et tout le tremblement ?
A moins que tout ceci ne soit strictement classé Secret défense ...
-
Voire Très Secret Défense .... :lol:
-
Mon train rentre et sort seul au décollage et à l'atterrissage en l'asservissant à l'altitude et au sens de la
vitesse de montée et je suis assez content de moi. Il me reste à faire des tests plus complets pour voir qu'il n'y a pas
de blocage possible.
on commence comme çà, on fini avec des réserves d'o2, l'effet plasma pour la rentrée et les boutons des mfd qui
fonctionnent dans le VC.
Ton addon a donc un train d'atterro. A l'affût des infos ^^
Message modifié ( 07-06-2008 17:19 )
-
En fait je refait Hercule que l'on trouve sur le site Mustard et que tu dois connaître.
Je l'avais créé avec Spacecraft et je le reprends en dll.
Mon but est d'apprendre à créer en C++ et ce projet comprend pas mal d'animations: portes, train; RCS et dock
mobiles, un bras animé et un astronaute embarqué.
C'est utopique mais assez complet pour se faire la main.
Le train n'en est pas un a proprement parler car il est constitué par des trappes, des jambes et des patins vu que le
bazar est a décollage vertical et ne posséde pas d'ailes.
L"animation consiste à ouvrir ou fermer les trappes en rotation et déplacer les jambes en translation en même temps
que les patins qui sont enfants par rapport aux jambes et effectuent une petite rotation.
Je profite de la reprise pour faire des asservissements qui n'étaient pas réalisables avec Spacecraft.
Ca prends forme mais j'ai encore du travail et je n'en suis pas au plasma et au VC !
Pas classé Secret !!!
:sage: Papyref
-
Bonjour! Je voudrais savoir comment on fait un add-on, j'en ai besoin, comme le disait brainstorm je crois, "oh! Jai
besoin de... et pouf! un add-on!" aidez-moi svp!
-
Bonsoir,
Pour répondre à Etudiant spatial, et comme ce n'est pas le sujet du topic, je met juste un lien vers un autre topic plus
approprié et très intéressant :
http://orbiter.dansteph.com/forum/index.php?topic=6456.msg98189#msg98189
Après lecture, et si vous vous lancez dans l'aventure, n'hésitez pas un créer un topic pour expliquer précisément les
problèmes rencontrés.
Milouse
-
Papyref a écrit:
C'est utopique mais assez complet pour se faire la main.
C'est surtout en très bonne voie... lâche pas papy ! ;)
Une grande nouveauté surtout: Spacecraft est vraiment un super outil mais tu étais en "limite haute", tu n'aurais pas pu faire beaucoup plus. Avec le C++ tu n'a pratiquement plus aucune limite à part le temps que tu peux y consacrer.
A++
Dan
Message modifié ( 08-06-2008 09:24 )
-
Je ne lache pas cher maitre !
Pour le prouver voilà deux images.
Une d'Hercule posé toutes issues ouvertes et une après début de montée ou les automatismes ont fermés la soute
si on ne l'a pas fait manuellement (j'ajouterai peut être un bip d'alarme), rentré le train, le dock, les rétros et fermé la
salle pour être prêt à affronter la montée en atmosphère.
Si il n'y a pas d'atmosphère, seuls le train et la soute sont maneuvrés.
Il est vrai qu'avec C++ on s'épanouit...
Avant décollage
(http://img266.imageshack.us/img266/2962/yafss001zk5.jpg)
Tout se ferme en montée
(http://img265.imageshack.us/img265/750/yafss002ae3.jpg)
Je vais attaquer le bras robotique et ça sera peut être un peu plus délicat !
:sage: Papyref
-
(j'ajouterai peut être un bip d'alarme)
peut-être un peu hors sujet mais on peut trouver plein de sons ici (alrme avions, gpws etc...):
http://www.simphonics.com/library/WaveFiles/
-
Papyref a écrit:
Je vais attaquer le bras robotique et ça sera peut être un peu plus délicat !
C'est sur ! Mais comme dis le proverbe: "plus on peste plus on a de... euh.. vestes" !?
...Attend non c'est pas ça ! :sick:
Je réessaie: "Plus on peste... plus on fait... la sieste ?"
Ah non je hais les proverbes !!!.... :rant:
Enfin bref ! on est super content quand ça marche quoi. :badsmile:
Bras robotique ? mhhhh dans le principe c'est pas *trop* compliqué faut bien être stricte et propre avec les
parents/enfants, plus difficile est de rendre la chose conviviale et aisée à utiliser.
De loins le plus dur/long en prog en fait c'est souvent l'interface pour que les gens utilisent nos "routines".
A++
Dan
Message modifié ( 10-06-2008 14:55 )
-
mhhh petit conseil:
Souvent il y a un moment "chaud" ou on doit trouver les principes, "comment faire" pour cela on essaie et test pas
mal de choses et ca fini en total désordre, code mal et vite fait mélangé avec des essais infructueux. Ne pas hésiter à
faire donc du code temporaire "bordelique" et une fois que ca marche et qu'on sait "comment", penser le truc avec les
nouvelles connaissances acquise et réecrire au propre.
J'utilise souvent dans ces cas des routines avec des noms "test" ou "temp" (ie: "temp_altitude") facile à enlever après coup. Sinon c'est comme une maison: à force de batir sur du fragile ça fini par s'écrouler sous le poids des bugs ou du fouilli incompréhensible.
Après chacun à son style j'imagine, certain sont hyper clean et posé depuis le début ?
Dan
Message modifié ( 09-06-2008 03:25 )
-
Exact le b... est latent avec ce genre de choses.
Je mets au point sur deux éléments pour commencer et ensuite ce sera plus facile.
J'avance pas à pas et je suis en train de me gratter la tête pour réaliser un arrêt en cours du mouvement et une
inversion.
Ensuite je cogiterai sur le graping puis l'interface.
Quand j'aurais fini je prendrai des vacances :)
:sage: Papyref
-
On peut définir la commande d'ouverture ou de fermeture d'une porte de deux façons comme par exemple:
void Hercule::RevertPorte ()
{
if (Porte_status == DOOR_CLOSED|| Porte_status == DOOR_CLOSING)
{
Porte_status = DOOR_OPENING;
}
else if (Porte_status == DOOR_OPENING|| Porte_status == DOOR_OPEN)
{
Porte_status = DOOR_CLOSING;
}
}
ou
void Hercule::RevertPorte ()
{
Porte_status = ((Porte_status == DOOR_CLOSED|| Porte_status == DOOR_CLOSING)?
DOOR_OPENING:DOOR_CLOSING);
}
L'une des définitions est elle préférable ?
Papyref
-
Ca revient strictement au même, la deuxième c'est "luxe le savon des stars", c'est une notation courte, "pro".
Si tu a des problèmes à la comprendre utilise la première. (Perso c'est celle que j'utilise, très verbeuse et visuelle
donc compréhensible en un éclair, c'est important) A la compilation ca revient au même de toute façon.
Question optimisation le C++ est incroyablement rapide, tu pourrais mettre 20'000 fois ces lignes
dans la fonction sans constater aucune différence de FPS.
C'est une question d'endroit aussi, cette fonction n'est utilisée qu'une fois tout les milliers de frames,
il faut être plus précautioneux dans clbkPostStep (je veux dire, ne pas mettre 20'000 fois ces lignes ;) )
Une chose importante c'est d'être capable "d'executer" le code dans sa tête comme le ferait l'ordi.
Il faut être capable de voir le bug dans celle la par exemple en "l'executant" avec différents cas:
void Hercule::RevertPorte ()
{
if (Porte_status == DOOR_CLOSED|| Porte_status == DOOR_OPEN)
{
Porte_status = DOOR_OPENING;
}
else if (Porte_status == DOOR_OPENING|| Porte_status == DOOR_OPEN)
{
Porte_status = DOOR_CLOSING;
}
}
Réponse du Bug: Une fois la porte ouverte elle resterais bloquée dans cette position
A++
Dan
Message modifié ( 09-06-2008 12:04 )
-
Je suis étonné de voir que j'ai compris toute ta première partie, et absolument rien à la seconde :damn:, alors que les deux
parties fond la même chose.
-
Pour le bras robotique:
Oublie pas une chose non plus, les DOOR_CLOSING et tout ca ce ne sont que des "flags" une methode qu'à "inventé"
martin pour controller la seule variable qui active l'animation la variable ***_proc qui est passée a "SetAnimation",
ces flags permettent grace au petit bloc dans clbkPostStep de faire passer la variable ***_proc de 0 a 1 et
inversement.
On aurais pu utiliser d'autre methodes mais celle à martin est élégante *dans ce cas précis*.
Par contre pour un bras ou tu veux le controle sur toute la course et pas seulement passer d'un etat a l'autre
automatiquement (ferme/ouvert) cette methode n'est plus adéquate. (les DOOR_CLOSING etc etc j'entend)
Tu va devoir controller précisement les variables ***_proc pour bouger l'animation au millimetres.
Pour garder la souplesse d'animation il va donc te falloir une variable qui contient quel position tu *demande* et dans
clbkPostStep un petit block sera en charge de faire bouger la variable ***_proc jusqu'à quelle "rejoigne" la valeur
demandée en douceur et un SetAnimation pour bouger le bras.
Exemple, variables requises: (a sauver dans le scenario)
dAvantBras_proc // de 0 a 1, variable passée à SetAnimation, position de l'avant bras
dAvantBras_request // de 0 a 1, variable qui demande une position de l'avant bras.
Le but donc c'est pas exemple si tu demande une position au millieux de l'avant bras "dAvantBras_request=0.5f;" il
existe une routine dans clbkPostStep qui fera passer automatiquement la variable "dAvantBras_proc" de sa position
actuelle à celle demandée (0.5), le tout en douceur en tenant compte de la vitesse/fps.
On peut utiliser plusieurs methodes donct certaines plus avancées qui tiendrais compte de l'amortissement (inertie
demarrage/arret, vitesse +rapide quand on est loin de la position)
Autre contrainte: une fois en bonne position la routine Setanimation ne doit plus etre activée, le block doit
etre "inerte" à ce moment. (pour éviter que martin ne declenche des calculs 3d complexe juste pour remettre le mesh
animé au meme endroit)
Pour bien comprendre le principe la methode la plus basique (pourrie) serait celle la:
// Bouge l'avant bras d'après la valeur demandée "dAvantBras_request"
if(dAvantBras_proc<dAvantBras_request)
{
dAvantBras_proc+=0.1f;
}
else
{
dAvantBras_proc-=0.1f;
}
SetAnimation(bidule,dAvantBras_proc);
La valeur effective proc va "rejoindre" toujours celle demandée par "request". Mais cette methode est inepte car on
ne tient pas compte du FPS, le bras va sauter continuellement de +-0.1 autour de la bonne valeur et Setanimation
sera appellée chaque frame même quand le bras sera quasi à la bonne position.
A vue de groins celle la est encore basique mais marche parfaitement sans les défauts précédents:
// Bouge l'avant bras d'après la valeur demandée "dAvantBras_request"
if(dAvantBras_Request!=dAvantBras_Proc)
{
double dg =simdt*0.02f; // vitesse en fonction du FPS
if(dAvantBras_Proc<dAvantBras_Request-dg)
{
dAvantBras_Proc+=dg;
}
else if(dAvantBras_Proc>dAvantBras_Request+dg)
{
dAvantBras_Proc-=dg;
}
else
{
// la valeur est très proche, met la egale donc
// désactive ce bloque d'animation la prochaine boucle
dAvantBras_Proc=dAvantBras_Request;
}
SetAnimation (uAnim_AvantBras , dAvantBras_Proc);
}
Maintenant ce qui serais sympa c'est de pouvoir faire nos demande de 0° a 360° plutot que de 0 à 1. C'est plus
parlant pour un humain. Donc on pourrait utiliser des variables "proc et request" dans ces limites la et simplement
diviser la valeur proc par 360 juste avant de la passer à SetAnimation.
Voila qui est parfaitement fonctionnel, grace aux touche clavier ou a un panel on met la valeur "dAvantBras_Request"
à une position de 0° a 360° et le bras rejoindra doucement cet angle la:
// Bouge l'avant bras d'après la valeur demandée "dAvantBras_request"
// demande de 0° a 360°
if(dAvantBras_Request!=dAvantBras_Proc)
{
// protection contre une valeur request "out of range"
// limite a 0-360 la valeur.
dAvantBras_Request=min(360,max(0,dAvantBras_Request));
double dg =simdt*5.0f; // vitesse en fonction du FPS
if(dAvantBras_Proc<dAvantBras_Request-dg)
{
dAvantBras_Proc+=dg;
}
else if(dAvantBras_Proc>dAvantBras_Request+dg)
{
dAvantBras_Proc-=dg;
}
else
{
// la valeur est très proche, met la egale donc
// désactive ce bloque d'animation la prochaine boucle
dAvantBras_Proc=dAvantBras_Request;
}
SetAnimation (uAnim_AvantBras , dAvantBras_Proc/360.0f);
}
Avec ca tu peux permettre à l'utilisateur de controller la valeur dAvantBras_Request de 5° ou 1° par les touches clavier, l'avant bras rejoindra doucement la position demandée.
Après on peut rentrer dans la complexité avec inertie demarrage/arret, gestion "intelligente" de la vitesse en millieu
de course voir "vitesse variable" définie par utilisateur (rapide/lent) mais ca sort du cadre d'un post "introduction"
La vitesse étant faible par définition ca peut marcher comme cela sans choquer vraiment. (mais avec un bras de 10m
ca pourrait donner pas mal de l'inertie)
Mais je suis pret a plancher sur un truc plus complexe dans un prochain post :badsmile:
A++
Dan
Message modifié ( 09-06-2008 15:20 )
-
Bon j'ai fais une routine "à inertie" juste par interet si jamais c'est dispo.
Remarque sur la routine "Bras Robotique":
Comme on a pleins d'éléments du bras a bouger on va ce retrouver avec des dizaines de lignes
qui vont faire la même chose juste avec des variables différentes. Ca fait un gros paquet de lignes
répétitive donc dur a modifier et à lire. Typiquement le truc à remplacer par une fonction.
Le code plus haut n'a besoin que de trois variables, deux variables anim et le numéro de l'animation
pour "SetAnimation".
Dès lors on pourrait creer une fonction "animation" dans le genre:
ProcessBrasAnimation(UINT NoAnimation,double * dProc,double *dRequest)
Avec un seul "corp" de fonction générique pour toutes les parties du bras.
Dans clbkPostStep au lieu d'une centaines de lignes indigeste on aurait un truc dans le genre:
ProcessBrasAnimation(uAnim_AvantBras,&dAvantBras_Proc,&dAvantBras_Request);
ProcessBrasAnimation(uAnim_Bras, &Bras_Proc, &Bras_Request);
ProcessBrasAnimation(uAnim_Epaule, &dEpaule_Proc, &dEpaule_Request);
ProcessBrasAnimation(uAnim_Poignet, &dPoignet_Proc, &dPoignet_Request);
Beaucoup plus lisible, en plus si on veut changer la routine d'animation elle même on a qu'un
seul bloc à modifier et c'est beaucoup plus lisible.
Mon coeur de programmeur 3d s'indigne de ces 5 calls inutiles dans la boucle principale, mais le gain en lisibilité du projet est conséquent. Pour pallier le defaut on peut "proteger" les fonction de l'execution. comme ceci:
if(dAvantBras_Request!=dAvantBras_Proc)
ProcessBrasAnimation(uAnim_AvantBras,&dAvantBras_Proc,&dAvantBras_Request);
if(Bras_Request!=Bras_Proc)
ProcessBrasAnimation(uAnim_Bras, &Bras_Proc, &Bras_Request);
if(dEpaule_Proc!=dEpaule_Request)
ProcessBrasAnimation(uAnim_Epaule, &dEpaule_Proc, &dEpaule_Request);
if(dPoignet_Request!=dPoignet_Proc)
ProcessBrasAnimation(uAnim_Poignet, &dPoignet_Proc, &dPoignet_Request);
Ou déclarer la fonction inline, (pour ceux qui connaissent).
Voila, rien que des avantages. je déteste lire la section "animation" dans le DGIV, 3km de lignes pareilles qui font la même chose avec juste des variables différentes, j'aurais du faire comme ci-dessus (mais j'était jeune ;) )
A++
Dan
Message modifié ( 09-06-2008 17:43 )
-
Merci pour ces renseignements.
Moi aussi je trouve que j'écris trop de lignes mais il faut d'abord que ça marche et ensuite on peut envisager de faire
plus sioux avec l'expérience.
Je vais 3 jours à Carnac pour me laver le citron et je ne ferai pas de robotique mais de la bouffe-balade.
Il faut s'oxygener les méninges C++sûr sinon mon vieux cerveau va perdre beaucoup trop de neurones :)
:sage::sage::sage: Papyref
-
Papyref a écrit:
Moi aussi je trouve que j'écris trop de lignes mais il faut d'abord que ça marche et ensuite on peut envisager de faire
plus sioux avec l'expérience.
Ben c'est la ou c'est malin: si ca marche pour une section ca marchera aussi pour toutes les autres
sans ecrire en plus une centaines de lignes. Suffit de trois variables et de rajouter la fonction.
En plus si t'est pas satisfait de la routine au lieu d'en modifier 5 tu modifie juste la générique.
Papyref a écrit:
Il faut s'oxygener les méninges C++sûr sinon mon vieux cerveau va perdre beaucoup trop de neurones :)
Bah il "parait" qu'on utilise 1/3 du cerveau seulement donc t'a de quoi voir venir :badsmile:
A++
Dan
PS publique: c'est une légende urbaine les 1/3, les seul qui font ca sont les cadavres de fraiche date.
-
hum moins de 10 % parait il .... ;)
-
brainstorm a écrit:
hum moins de 10 % parait il .... ;)
Après réflexion c'est certainement vrai pour ceux qui ont inventés cette légende ;)
Dan
Message modifié ( 10-06-2008 02:55 )
-
Pour déplacer la rotule de mon bras vers l'avant ou l'arrière de la soute d'Hercule, j'écris dans clbkConsumeBufferKey
pour ajuster ma dShiftZ_proc avec dShiftZ_request (voir méthode Dan):
case OAPI_KEY_LEFT: // Deplacement longitudinal avant de la rotule
if (dShiftZ_request <= 0.95) dShiftZ_request = dShiftZ_request + 0.05;
return 1;
case OAPI_KEY_RIGHT: // Deplacement longitudinal arrière de la rotule
if (dShiftZ_request >= 0.05) dShiftZ_request = dShiftZ_request - 0.05;
return 1;
Ce n'est pas terrible mais ça marche et ça permet de mouvoir le bras par incréments de 0.05 de 0 à 1 et vice versa.
L'ennui est bien sûr qu'il faut une impulsion sur flèche gauche ou droite chaque fois que l'on veut faire un petit
déplacement supplémentaire et ce n'est pas continu.
Mon idée serait de faire un déplacement dans un sens ou dans l'autre en faisant une incrémentation automatique
tant qu'on tient le bouton enfoncé (on pourrait afficher en même temps la valeur de consigne à atteindre) et en
relachant on attendrait que le déplacement soit terminé ou alors on pourrait rectifier la consigne avant la fin du
déplacement.
A ma grande honte je ne trouve pas de solution adéquate faute de savoir tester correctement l'enfoncement
temporaire de la touche et de plus si je crée une boucle pour incrémenter j'ai peur que le déplacement de la consigne
soit trop rapide.
Quelqu'un peut-il m'aider ?
Merci
:sage::sage: Pauvre vieux Papy épuisé !
-
Deux methodes à mon avis:
clbkConsumeBufferKey recoit tout les événements clavier ceux ci sont de deux natures:
1-Enfoncement de la touche: événement "down"
2-Relachement de la touche: événement "up"
Au début de la fonction "clbkConsumeBufferedKey" un petit bout de code rejette les événements "up" pour ne garder
que les enfoncements "down". (sinon chaque appui déclencherait l'action voulue deux fois, une à l'appui, une au
relachement)
// ne traite que quand la touche est enfoncée pas quand elle remonte
if (!down)
return 0;
Tout ce qui est après ne sera executé qu'après un enfoncement de la touche.
En utilisant ce savoir tu pourrais faire un flag, à l'enfoncement il déclencherais l'animation et au relachement
arreterais l'animation. Un peu compliqué mais valable.
L'autre méthode plus simple à mon avis utilise les fonctions que j'ai posté plus haut avec des variables "request" et
un callback spécial d'orbiter qui s'execute à chaque "PostStep" et permet de tester l'appui ou non d'une touche:
clbkConsumeDirectKey
Keyboard handler. Called at each simulation time step. This callback function allows
the installation of a custom keyboard interface for the vessel.
Dans cette fonction une macro "KEYDOWN" permet de tester si une touche est enfoncée ou non à chaque "image"
int Hercule::clbkConsumeDirectKey(char *kstate)
{
if(KEYDOWN(kstate,OAPI_KEY_T)
{
// si ici, touche T appuyée en ce moment
}
}
Le but serais le suivant: incrémenter la variable "Request" si la touche est enfoncée pour qu'elle soit toujours un chouia devant la valeur actuelle (carotte devant le nez), mais attention comme cette incrémentation serais faite à chaque image en une secondes tu atteindrais une valeur "request" limite. (1.0 ou 0.0) Il faut donc l'incrémenter mais que de la "valeur actuelle de position du bras" + "un petit chiffre" "0.05" par exemple. pour que la "carotte" reste bien juste "devant le nez"
Un peu dans le genre:
int Hercule::clbkConsumeDirectKey(char *kstate)
{
if(KEYDOWN(kstate,OAPI_KEY_LEFT)
{
dAvantBras_Request=dAvantBras_Proc+0.05;
dAvantBras_Request=min(1.0,max(0.0,dAvantBras_Request)); // limite
}
else if(KEYDOWN(kstate,OAPI_KEY_RIGHT)
{
dAvantBras_Request=dAvantBras_Proc-0.05;
dAvantBras_Request=min(1.0,max(0.0,dAvantBras_Request)); // limite
}
}
-Oublie pas de limiter "dAvantBras_Request" dans cette fonction pour pas qu'il n'excede 0.0 ou 1.0 (utilise min/max)
C'est bon ? (sinon je te fais plus de code) ;)
A++
Dan
Message modifié ( 14-06-2008 17:55 )
-
Merci Speedy Dan,
Je vais essayer de me débrouiller avec ces éléments.
Si je coince je referai appel à ta grande sagesse !
Papy
-
Question bête !
Je crée une variable iControle bras qui va me servir à controler la prise de commande du bras et une variable
iControlPartBras qui va désigner ensuite en cyclant par la touche fléche UP quelle partie du bras va être déplacée en
agissant sur les touches flêches LEFT et RIGHT
J'écris (probablement pas génialement mais ça marche) dans clbkConsumeBufferKey à l'endroit adéquat et avec les
initialisations iControlBras=0; iControlPartBras=1;
case OAPI_KEY_SPACE:
// Controle du bras demandé ou non par CTRL + SPACEBAR
// La variable iControlBras va servir d'inverseur
// A 1 le bras est sous controle, a 0 il ne l'est pas
iControlBras = iControlBras + 1;
if (iControlBras >1)
{
iControlBras =0 ;
}
return 1;
}
case OAPI_KEY_UP:
// On cycle avec la fléche UP pour choisir quelle partie du bras
// sera controlée par les fléches LEFT et RIGHT
if (iControlBras == 1)
{
iControlPartBras = iControlPartBras + 1;
if (iControlPartBras >7)
{
iControlPartBras =1 ;
}
}
}
et toujours dans clbkConsumeBufferKey dans le handler traitant l'appui fugitif
int Hercule::clbkConsumeDirectKey (char*kstate)
{
if (iControlBras == 1) // Le bras est sous controle pour la translation longitudinale
{
if(KEYDOWN (kstate,OAPI_KEY_LEFT) && iControlPartBras == 1) // La partie 1 est choisie
{
dShiftZ_request = dShiftZ_proc + 0.01;
dShiftZ_request = min(1.0,max(0.0,dShiftZ_request));
}
else if(KEYDOWN (kstate,OAPI_KEY_RIGHT)&& iControlPartBras == 1)
{
dShiftZ_request = dShiftZ_proc - 0.01;
dShiftZ_request = min(1.0,max(0.0,dShiftZ_request));
}
Une chose me surprend.
Les variables iControlBras et iControlPartBras sont des entiers mais je dois écrire iControlBras ==1 et
iControlPartBras ==1 pour que ça marche.
Pourquoi une équivalence et pas une égalité ?
:sage: Papyref rêveur
-
Ben je crois que dans les structures en if, il faut demander == (égal à), != (différent de), < (+ petit que), > (+ grand
que), <= (+ petit ou égal à), >= (+ grand ou égal à), || (ou), && (et).
C'est comme ça ;).
Mais ta variables iControlBras doit contenir deux valeurs, non??
Si tel est le cas, c'est mieux de prendre une variable de type "booléenes", qui peut soit être TRUE, soit FALSE.
Dans ton code, ça donnerait ça:
bool bControlBras = false;
if (bControlBras) //Si bControlBras est true
{
...
}
if (!bControlBras) //Si bControlBras est false
{
...
}
Ensuite, petit truc pour ajouter un à une variable (indentation):
Au lieu d'écrire
iControlBras = iControlBras + 1; //Très long...
On peut aussi mettre
iControlBras++;
Cela marche aussi avec les moins:
iControlBras--;
Message modifié ( 15-06-2008 19:49 )
-
Les variables iControlBras et iControlPartBras sont des entiers mais je dois écrire iControlBras ==1 et
iControlPartBras ==1 pour que ça marche.
Tu veux dire dans le "if" ? les conditions prennent toujours un double "==" c'est une convention d'écriture.
Si tu fait "if(iControlPartBras =1)" Tu assigne la valeur 1 au lieu de comparer. Depuis la version 2005 le
compilateur grogne si on ecrit comme cela mais avant ce n'était pas le cas et c'était une source d'erreur la condition
étant toujours vraie et la variable prenant la valeur au lieu de comparer.
Donc "egal" s'ecrit toujours "==" Le "non egal" s'ecrit "!=" plus grand et plus petit eux s'écrivent "<" et ">"
Par contre en lisant je me dis que ce serait logique d'augmenter la valeur iControlPartBras avec "UP" et la descendre
avec "DOWN". Si le gars controle le "poignet 7" et qu'il veut controller "l'avant bras 6" il devra presser 7 fois sur UP.
Pas très pratique.
A++
Dan
-
Je n'aurais pas du arretter mon post pour manger, doublon avec le tiens Marty :)
"iControlPartBras" est ok en integer il prend 7 valeurs. Par contre tu a raison "iControlBras" serait mieux en
boolean "bControlBras"
Ca ne change rien à l'execution mais ca différencie mieux la variable de iControlPartBras et en lisant tu verrais tout de
suite que c'est un "flag" un "verrou" qui ne prend que deux états. Important la lecture claire surtout quand on survol.
(risque de t'emmeler entre iControlPartBras et bControlBras)
A++
Dan
Message modifié ( 15-06-2008 19:51 )
-
DanSteph a écrit:
Par contre en lisant je me dis que ce serait logique d'augmenter la valeur iControlPartBras avec "UP" et la
descendre
avec "DOWN". Si le gars controle le "poignet 7" et qu'il veut controller "l'avant bras
6" il devra presser 7 fois sur UP.
Pas très pratique.
A++
Dan
Effectivement j'avais pensé décrémenter avec DOWN mais en un premier temps j'ai fait simple pour voir d'abord si
mon concept était bon
Merci
AC++
Papy
-
Je galère comme un fou avec VS2008, ça marche toujours pas :sad:
Même le projet que j'avais fait avec la version 2007 marche pas. J'ai pleins d'erreur de lien.
A priori, c'est bon en config
(http://img116.imageshack.us/img116/4286/inczy7.jpg)
(http://img116.imageshack.us/img116/6084/libjo3.jpg)
Mais j'ai pleins d'erreurs de liens, j'en réduis en copiant les .h .lib d'orbiter dans le répertoire local et en les
déclarant dans le projet, mais ça bloque toujours. Et je suis perplexe devant les explications de msdm.
(http://img228.imageshack.us/img228/9628/prozacsn0.png)
-
T'a suivi le tuto d'install de vs express ou c'est du custom ?
voir: http://orbiter.dansteph.com/forum/index.php?topic=6334.msg95341#msg95341
Tu peux poster les messages (enfin quelques un) ?
C'est des lnk 2001 ? Attention a l'ordre des lignes, la platform SDK est la bonne ?
Ca compile avec le shuttlePB par hazard ?
Dan
Message modifié ( 22-06-2008 15:50 )
-
Le SDK, c'est celui qu'il m'a inclut dans le téléchargement (si j'installe celui que tu indiques, il se passe rien).
la console de compil avec le DGex
http://akaa.free.fr/online/compil.txt
J'ai pas essayé avec la shuttlePB, mais le project que j'ai fait l'année dernière, c'est la même chose (et même message sur
la console).
-
Visiblement il manque déjà la lib orbiter.lib et orbitersdk.lib, d'habitude martin les inclus direct dans ces projets
peut etre les avais tu incluse avec des chemins absolu (pas "../lib/orbiter.lib" mais "c:\bidule\orbiter.lib"?)
Essaie de delete "orbiter.lib" et "orbitersdk.lib" de ton projet et reinclu le en browsant "add existing item"
Tu dois avoir orbiter.lib et orbitersdk.lib
A++
Dan
-
DanSteph a écrit:
Essaie de delete "orbiter.lib" et "orbitersdk.lib" de ton projet et reinclu le en browsant "add existing item"
Tu dois avoir orbiter.lib et orbitersdk.lib
Haaa ça marche mieux comme ça :)
Pourquoi VS, ne voit pas les fichiers dans les répertoires déclarés ?
http://akaa.free.fr/online/compil2.txt
Doh, 20 erreurs, le bout du tunnel :o
GDI nan ?
Message modifié ( 22-06-2008 18:14 )
-
Schimz a écrit:
Pourquoi VS, ne voit pas les fichiers dans les répertoires déclarés ?
Avec VS quand ca compile c'est déjà 87% du projet qui est fini... :badsmile:
Schimz a écrit:
GDI nan ?
Regarde du coté des libs pour le panel:
http://orbiter.dansteph.com/forum/index.php?topic=6358.msg95704#msg95704
A++
Dan
-
DanSteph a écrit:
Regarde du coté des libs pour le panel:
http://orbiter.dansteph.com/forum/index.php?topic=6358.msg95704#msg95704
Je les avait oubliées celles là :bug:
reste plus que ça -_-°
1>MSVCMRT.lib(mstartup.obj) : error LNK2001: symbole externe non résolu ___native_dllmain_reason
1>MSVCMRT.lib(mstartup.obj) : error LNK2001: symbole externe non résolu ___native_vcclrit_reason
1>MSVCMRT.lib(mstartup.obj) : error LNK2001: symbole externe non résolu ___native_startup_state
1>MSVCMRT.lib(mstartup.obj) : error LNK2001: symbole externe non résolu ___native_startup_lock
-
Si je mets une exception sur la dll, plusse d'erreurs :|
-
Ça maaarche :flower:
Mais j'ai un problème sur mes textout.
Pour qu'ils fonctionnent, j'ai rajouté le truc en gras
TextOut (hDC, 2, 0, (LPCWSTR)name, strlen(name));
Et bé maintenant, ils sont tout corrompus :sad:
(http://img66.imageshack.us/img66/8628/sanstitre1tx8.gif)
edit : c'est redeviendu bon :o
Message modifié ( 25-06-2008 20:41 )
-
Schimz a écrit:
edit : c'est redeviendu bon :o
Ah ben tant mieux :)
Dan
-
Oué bin c'est pas gagné. Je bloque toujours sur un truc depuis le début de ce panel. Je prévoyais que ce serait le plus
compliqué, 'me suis pas trompé (http://img240.imageshack.us/img240/2315/pingouinoaq5.gif)
-
Les panel c'est pas le plus simple, avec picto au cours d'une longue discussion on était arrivé a un truc semi-
automatique, une fonction pour déclarer position, image et tout et tout était automatique, affichage, détection.
C'est pas finalisé ni taillé pour être passé comme cela mais dans la discussion est ici (je sais plus ou ca démarre):
http://orbiter.dansteph.com/forum/index.php?topic=6342.msg95437#msg95437
Demande peut être à picto si il a encore le code ?
A++
Dan
-
C'est pas un bouton, c'est un redraw_always :o
Par contre, ouais, je vais avoir besoin d'un truc pour les boutons du panel hoverhead :siffle:
-
post le code qui merde si t'est bloqué, utilise les tag [ code ]
Dan
-
ouais, je vais avoir besoin d'un truc pour les boutons du panel hoverhead
Tu veux dire la fonction automatique de déclaration des boutons ?
Y'en aura donc tant que ça ? :)
Mais oui, si tu as besoin, je t'envoie tout ce qu'il faut pour cette fonction.
-
DanSteph a écrit:
post le code qui merde si t'est bloqué, utilise les tag [ code ]
Dan
C'est le même code que le DG. Mais faut le refaire. Pour que ça ressemble à autre chose.
-
J'ai un problème de transparence :sunk:
(http://img370.imageshack.us/img370/6278/sanstitre1copierow5.jpg)
J'ai 3 PanelArea qui se chevauchent, mais la transparence de chaque zones bouffe le pixels des autres zones.
En changeant l'ordre d'appel ou de couleur de transparence, c'est pareil :rant: :sad:
-
Defini qu'une zone et blit tes plusieurs truc dans la fonction redraw unique. (désolé si c'est pas clair j'ai pas dormi
depuis..bouf...)
A++
Dan
-
Arf, j'y ai pensé, mais va falloir réécrire tout le bouzin... :sad:
ed : bon, c'est plus simple qu'il n'y parait, ça fait juste grossir le code de 200% :siffle:
re ed : et puis ça a viré le bug qui faisait planter Orbiter quand j'activais le train d'atterrissage. Si je virais le blits (postés au dessus) ça revenait normal :trucdeouf:
Message modifié ( 06-07-2008 14:18 )
-
Schimz a écrit:
Arf, j'y ai pensé, mais va falloir réécrire tout le bouzin... :sad:
Ben euh, oui, désolé mais les zones qui se chevauchent ca marche pas, faut prendre le controle et la c'est a toi de
jouer.
A++
Dan
-
J'arrive au bout de mon test C++ mais j'ai un ennui avec le point de grappling du RMS
L'animation du bras fonctionne parfaitement et mon dernier groupe est le suivant:
WristRoll = new MGROUP_ROTATE (LOCALVERTEXLIST, MAKEGROUPARRAY(arm_tip), 3,
_V(-4.55,5,26), _V(0,0,1), (float)(4*PI));
uAnim_WristRoll= CreateAnimation (0.0);
hAC_arm = AddAnimationComponent (uAnim_WristRoll, 0, 1, WristRoll, parent);
il définit un triangle fictif rotatif par les trois points arm_tip
arm_tip[0] = _V(-4.55,5,26.3);
arm_tip[1] = _V(-4.55,5,27.3);
arm_tip[2] = _V(-4.55,6,26.3);
Le point de grappling peut être définit en écrivant:
AttPayload - = CreateAttachment (false, arm_tip[0], arm_tip[1]-arm_tip[0], arm_tip[2]-arm_tip[0], "G",
true);//Grap
ou arm_tip[0] donne la position du point d'attachement en fonction du déplacement du bras, arm_tip[1]-arm_tip[0] la
direction de l'axe d'attachement et arm_tip[2]-arm_tip[0] la rotation autour de cet axe
Je veux tester en un premier temps l'aptitude à déplacer le satellite sans me préoccuper de savoir si il est grapable
ou pas.
Dans mon scénario j'attache un satellite ici Octopus) au bras en écrivant dans le scénario
ATTACHED 0:0,Hercule
Il se positionne correctement en bout de bras en position d'origine repliée comme on peut le voir sur la capture
d'écran (il percute Hercule mais pour l'instant ce n'est pas grave)
(http://img368.imageshack.us/img368/3605/yafss001eg9.jpg)[/URL]
C'est à partir de là que je pédale dans la choucroute !
Si je fais bouger le bras, le satellite ne suis pas le mouvement ce qui me semble logique. Il faudrait que les vecteurs
arm_tip varient et je n'arrive pas à trouver la solution pour le faire.
Le handler hAC conditionne probablement le déplacement.
Faut-il faire une conversion de coordonées Local2Global pour que ça marche ?
Je suis preneur de toute suggestion. Merci d'avance.
:wall: Papyref
-
Autant te le dire tout de suite: je n'ai pas la réponse :)
Je n'ai jamais fait de bras amovible, mais si la navette par défaut en a un (je suis pas sur?)
tu pourrais jetter un oeil sur le code ? Il est dans la SDK.
Je ferais ca en premier, sinon en deuxieme un oeil sur la fonction attachment dans la doc. ?
En troisième une recherche sur les (ancien) forum de dev orbiter avec "CreateAttachment " ?
Si tu trouve rien j'essayerais de jetter un oeil de mon coté...
A++
Dan
-
Il y a effectivement un bras sur Atlantis, j'ai regardé le code çà à l'air compréhensible, à voir!
C'est pareil pour moi, je n'ai aucune expérience avec les bras manipulateurs (çà me parait même complexe).
Bonne chance Papy ;)
EDIT: tu peux peut-être te simplifier la vie en utilisant "Universal Remote Manipulator System" de Kulch (je n'ai pas testé l'addon, je ne sais pas ce qu'il vaut mais kulch s'en sort en général assez bien) -> sur OH.
Message modifié ( 07-07-2008 14:03 )
-
Merci les amis,
J'ai examiné déjà le code d'Atlantis mais je n'ai pas encore trouvé la solution.
Je connais le bras de Kulch mais mon but est d'animer le mien pour apprendre et je ne veux pas l'utiliser.
L'animation du bras n'est pas un problème mais c'est le grap qui en est un.
Je vais continuer à méditer.
Papyref
-
J'irais jetter un oeil cette nuit et détaillerais un peu la partie cruciale... enfin , je vais voir quoi...
Dan
-
(http://img116.imageshack.us/img116/4286/inczy7.jpg)
(http://img116.imageshack.us/img116/6084/libjo3.jpg)
HO HE.... Ca m'intéresse vraiment d'avoir ce type d'information sur VS2005.... Comment faire pour voir tous les liens pour
les include, fichiers bibliothèques
BREF: Avec ce type de panneau, peut-on voir les répertoires pour:
1-Les DLL
2-Les fichiers H de ces DLL
3-Le LIB
4-Le includes (que je comprends pas ce que fait ces choses)
5-les BIN (je ne comprend pas ce choses également et j'aimerais en savoir plus)
6-les DEF (je ne comprend pas ce choses également et j'aimerais en savoir plus)
Si vous avez un schéma ou une doc permettant de comprendre 'visuellement parlant' les différents objets qui peuvent
graviter autour d'un exécutable (DLL, H, LIB,....) et quel sont les associations indispensables commes DLL+H, LIB (qui doit être seul car il sont linker....)
MERCI....
Message modifié ( 12-08-2008 13:30 )
-
Hellooo :)
Je perd 20% de fps avec les effets sur les moteurs du DGex :badsmile:
Je veux exclure le code de chaque moteur si son level ne change pas de step en step. Je me doute que c'est une histoire de
Pre/Post Step. Mais à part le if(do==true) DoStuff();, je sèche :damn:
Message modifié ( 26-02-2009 21:41 )
-
Hello ;)
No problemo mais je vois pas ou ce situe ton prob exactement pour l'instant.
Comment implementer le callback post/pre step ou comment exclure du code tant qu'il n'y a pas de changements ?
T'a un bout de code, un contexte, plus de précisions ?
A peluche
Dan
Message modifié ( 26-02-2009 23:47 )
-
exclure du code tant qu'il n'y a pas de changements
That's it.
C'est la mise à jour de ma variable à tester et le dit test que je sais pas où mettre.
ça :
previousThrusterLevel = GetThrusterLevel(th);
et ça :
do = true;
if ( GetThrusterLevel(th) == previousThrusterLevel )
do = false;
-
ok,
Optimisation par désactivation dynamique de code redondant (wow le titre :badsmile: )
Il te faut une variable permanente dans ta classe (le h en principe) Autant de variables qu'il y a de moteurs -qui
peuvent avoir différentes valeurs- dans l'exemple je suppose trois. Par convention j'utilise toujours le prefixe "old"
(vieux) je sais qu'elle contient la valeurs de la dernière execution valide.
// dans le header de la class vessel
float fOldEngineLevel1;
float fOldEngineLevel2;
float fOldEngineLevel3;
Dans clbkSetClassCap on initialise les variables c'est très important j'insiste toujours la dessus.
void clbkSetClassCap()
{
fOldEngineLevel1=-999.0f;
fOldEngineLevel2=-999.0f;
fOldEngineLevel3=-999.0f;
pourquoi -999 ? :)
Dans ces variables faut toujours mettre une valeurs qui ne peut pas être atteinte par le truc à controller, sinon on
risque d'avoir un bug ( "même valeur ? oh ben je fais rien" si y avait besoin la premier fois!). La c'est pas si
important puisque à zéro on n'a pas d'effet, mais j'attire l'attention la dessus si tu veux appliquer cette technique
ailleurs.
Dans clbkPreStep (ou PostStep dépend ou tu applique ton effet) on fais le boulot, je ne le montre que pour l'engine1
pour plus de clarté.
void clbkPreStep()
{
[color=green]// Phase un on lis la valeur courante dans une variable locale (pas besoin ailleurs)[/color]
float fCurrentEngineLevel1=GetThrusterLevel(th);
[color=green]// Phase deux on procède à la comparaison, pour un float ou une simple
// variation de 0.0000001 est considéré comme non égal on dois le faire
// par fourchette et ajuster la fourchette pour n'avoir une activation de code
// que pour des différences significative. (le code ne tournera que quand vraiment nécessaire)
// ici une fourchette de 0.1, si ca ce voit trop on peut affiner (0.005)[/color]
if(fCurrentEngineLevel1 < fOldEngineLevel1+0.05 && fCurrentEngineLevel1 > fOldEngineLevel1-0.05)
{
[color=green]// le code qui applique l'effet.[/color]
DoEffect();
[color=green]// Et pour finir on ce souvient de la valeurs du moteur la dernière fois
// que l'effet a été appliqué. Une différence de 0.1 assurera
// un déclenchement de l'effet la prochaine fois.[/color]
fOldEngineLevel1=fCurrentEngineLevel1;
}
Résultat: ton effet ne sera executé que si le moteur à eu une variation de 0.1 avec la dernière fois.
Tout ca c'est très bien si ton Code "DoEffect() l'applique pour cette boucle seulement (défini un niveau de fumée?). Mais il faut du code en plus si c'est une fonction qui fais on/off (active désactive les particules? je sais pas ce que tu fais exactement)
J'utilise cette technique pour énormément de trucs. ca assure qu'une chose qui ne change pas ne soit pas mise à jours chaque loop. Ca permet aussi de réduire les maj pour des différences non significatives.
Exemple typique le volume d'un son, une variation de 1 sur 255 ne s'entend pas, donc j'applique cette technique avec "5" comme fourchette. (OrbiterSound l'utilise énormément que ce soit pour le volume la fréquence etc etc)
A++
Dan
Message modifié ( 27-02-2009 16:25 )
-
Super :)
:wor:
Tout ca c'est très bien si ton Code "DoEffect() l'applique pour cette boucle seulement (défini un niveau de fumée?).
Mais il faut du code en plus si c'est une fonction qui fais on/off (active désactive les particules? je sais pas ce que tu
fais exactement)
Oui, il y a plein de code à zapper. C'est pour qu'en plus de mes vars fHaeLvlPrec, j'avais préparé 4 booléens
bHaeDoFX :eek:
Aleyyy, c'est partit pour le W.E. :zzz:
-
Bon week-end alors :)
Hésite pas !
Dan
-
Ça marche :)
'tin, c'était tout con en fait :bug:
Par contre, ça marche pas si je fais pas mon if comme ça :wonder:
if (plasma_lvl < plasma_lvlPrec || plasma_lvl > plasma_lvlPrec) {
plasmaDoFX = true;
plasma_lvlPrec=plasma_lvl;
} else {
plasmaDoFX = false;
}
Pour tester, j'ai rajouté un dong windows dans mes fonctions Fx, c'était rigolo :)
edit :
Hésite pas !
Un orbiterSound pour 09β :siffle:
Message modifié ( 27-02-2009 21:04 )
-
C'est la version égalité parfaite la, tu pourrais remplacer par
if (plasma_lvl !=plasma_lvlPrec)
{
//etc etc
L'inconvénient de cette méthode c'est qu'entre 0.0455 et 0.0672 si tu incrémente lentement (cas possible de pilote
automatique) t'auras pratiquement un lancement d'effet chaque loop alors qu'avec l'autre methode tu en aura que le
stricte necessaire= meilleurs optimisation.
Pour ton projet franchement (je ne sais pas l'impact de ton effet?) ca ne fais peut-être pas une grand différence, pour
des trucs plus gros ca plus ca plus ca= framerate pourri.
Peut être mon code était mal ficelé (fais de tête) essaie juste de remplacer la première ligne:
if (plasma_lvl < plasma_lvlPrec || plasma_lvl > plasma_lvlPrec){
Par :
if (plasma_lvl < plasma_lvlPrec-0.05 || plasma_lvl > plasma_lvlPrec+0.05){
Oui en fait je crois que je me suis gouré la première fois. Mauvaise logique. Pour optimiser après tu peux essayer
de changer la valeurs par incrément de 0.05 jusqu'a trouver la valeur maximale ou tu vois pas de "saut" dans ton
effet. Le lancement sera fais juste le nombre de fois nécessaire.
A++
Dan
Message modifié ( 27-02-2009 23:19 )
-
DanSteph a écrit:
Pour ton projet franchement (je ne sais pas l'impact de ton effet?) ca ne fais peut-être pas une grand différence, pour
des trucs plus gros ca plus ca plus ca= framerate pourri.
Dan
Oué ben en fait, oué, pas de changement de FPS, c'est juste les effets en eux mêmes qui bouffent :ptdr:
-
C'est l'effet particule ?
Si oui faut optimiser l'effet lui-même (martin), de notre coté on peut juste l'afficher ou pas (il me semble), ca change
rien :)
Dan
-
DanSteph a écrit:
C'est l'effet particule ?
Non, pour ça j'utilise le truc normal. Les FX, c'est le son (j'ai pas de MAIN sound, je fais tout à la mano) et le mélange de
surface (la lumière des moteurs).
-
C'est peut être bien un probleme de fill rate, truc que orbiter gêre pas nickel. (affichage de texture transparente en
empilement)
Dans ce cas rien que tu puisse faire à part optimiser les textures ou les réduires.
Dan
-
Boaf, ça tournait correctement sur la trapanelle du boulot, je verrais mieux la différence en testant lundi.
Bon... faut que je vire les vieilles lampes... :zzz:
Je vais aussi zapper quelques trucs pas nécessaires actuellement, pour avancer la release.
-
Coussini a écrit:
(http://img116.imageshack.us/img116/4286/inczy7.jpg)
(http://img116.imageshack.us/img116/6084/libjo3.jpg)
HO HE.... Ca m'intéresse vraiment d'avoir ce type d'information sur VS2005.... Comment faire pour voir tous les liens pour
les include, fichiers bibliothèques
BREF: Avec ce type de panneau, peut-on voir les répertoires pour:
1-Les DLL
2-Les fichiers H de ces DLL
3-Le LIB
4-Le includes (que je comprends pas ce que fait ces choses)
5-les BIN (je ne comprend pas ce choses également et j'aimerais en savoir plus)
6-les DEF (je ne comprend pas ce choses également et j'aimerais en savoir plus)
Si vous avez un schéma ou une doc permettant de comprendre 'visuellement parlant' les différents objets qui peuvent
graviter autour d'un exécutable (DLL, H, LIB,....) et quel sont les associations indispensables commes DLL+H, LIB (qui doit
être seul car il sont linker....)
MERCI....
si la question peux intéresser encore du monde, demandez moi, je peux poster un ptit cours complet sur la question...
C'est vrai que ce problème est universel. Je vais essayer de poster tout ca bientot
-
Salut tout le monde.
Moi aussi, avec les vacances je me met à bricoler les DLL... ;)
Au début, pas trop de problème. Mais pour animer mon train, je veut faire tourner une tige tout en faisant une translation...
Seulement dans ce cas là, le centre de rotation bouge avec la translation...
En cherchant un peu, je pense qu'une animation avec parent pourrait être la solution. Je recopie donc les exemples de la doc
de la SDK à ma sauce. Ca me donne :
ANIMATIONCOMPONENT_HANDLE parent;
static UINT RessortARGGRP[2] = {GRP_RessortARGG, GRP_RessortARGD};
static MGROUP_ROTATE RessortRot (0, RessortARGGRP, 2, _V(3.9, 0.1, 2.05), _V(1,0,0), (float)(0.43*PI));
trans = new MGROUP_TRANSLATE (0, RessortARGGRP, 2, _V(0,0,-0.8));
parent = AddAnimationComponent (anim_Gear, 0, 0.6, &RessortRot);
AddAnimationComponent (anim_Gear, 0, 0.6, trans, parent);
Seulement, à la compilation il me dit que la variable trans n'est pas déclarée... :sunk:
Alors ma question est la suivante : où faut-il déclarer cette variable et comment ?
Merci.
-
Ca répond pas directement à ta question, mais regarde la "méthode" de Dan (
http://orbiter.dansteph.com/forum/index.php?topic=6337.msg95356#msg95356 )!!!
-> ouvre le projet de la sdk, puis clique droit sur la variable -> "atteindre la déclaration"...
-
simon50 a écrit:
Seulement, à la compilation il me dit que la variable trans n'est pas déclarée... :sunk:
Alors ma question est la suivante : où faut-il déclarer cette variable et comment ?
Merci.
Où : dans ton header
comment : en écrivant MGROUP_TRANSFORM *trans;
Et puisque new il y a, delete tu n'oubliras pas ! :prof:
Message modifié ( 17-06-2009 20:26 )
-
no matter a écrit:
Où : dans ton header
comment : en écrivant MGROUP_TRANSFORM *trans;
Et puisque new il y a, delete tu n'oubliras pas ! :prof:
OK, merci. :top:
Je teste ça demain. ;)
-
J'ai installé VC2008 pour recompilé les dll de mes stations Ceres et ESS qui semblent ne pas vouloir fonctionné sur une
installe qui comporte le XR2, et voir si c'est mieux.
Au moment de la compilation je rencontre le problème :
1>.\Ceres.rc(10) : fatal error RC1015: cannot open include file 'afxres.h'.
J'ai fait des recherches et trouvé ça sur Wiki :
cannot open include file 'afxres.h'
Error: fatal error RC1015: cannot open include file 'afxres.h'.
Solution: add the 'include\mfc\' folder of the Platform SDK (default C:\Program Files\Microsoft Platform SDK\include\mfc) to
"Configuration Properties/Resources/Additional Include Directories"
Je pense avoir compris qu'il faut inclure Program Files\Microsoft Platform SDK\include\mfc
ma question est, ou exactement ?
-
Regarde le poste 4:
"4-Regler Visual C++ express pour qu'il retrouve les ressources"
De ce fil:
http://orbiter.dansteph.com/forum/index.php?topic=6334.msg95341#msg95341
Hope it help ?
Dan
-
DanSteph a écrit:
Regarde le poste 4:
"4-Regler Visual C++ express pour qu'il retrouve les ressources"
De ce fil:
http://orbiter.dansteph.com/forum/index.php?topic=6334.msg95341#msg95341
Hope it help ?
Dan
Merci tonton Dan
(http://img115.imageshack.us/img115/9977/vc2008.jpg)
Le chemin le plus courant :
C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include\mfc
-
Bien le bonjour! ;)
Alors... Comme beaucoup de monde ici, je connais à-peu-près le langage C++, mais lorsqu'il s'agit de configurer Visual et de
farfouiller dans toutes ces librairies au nom obscure (msvcrt et autres), alors là ça se corse!!
Pour quelqu'un qui s'y connaît, c'est surement un problème easy à résoudre, mais pour moi...no comment!
Ma sortie du debug:
1>------ Début de la génération : Projet : MSLJ_Gemini, Configuration : Debug Win32 ------
1>Édition des liens en cours...
1> Création de la bibliothèque .\Debug/MSLJ_Gemini.lib et de l'objet .\Debug/MSLJ_Gemini.exp
1>Config_Stage1.obj : error LNK2001: symbole externe non résolu "public: virtual void __thiscall MFD::Update(struct HDC__ *)"
(?Update@MFD@@UAEXPAUHDC__@@@Z)
1>MSLJ_Gemini.obj : error LNK2001: symbole externe non résolu "public: virtual void __thiscall MFD::Update(struct HDC__ *)"
(?Update@MFD@@UAEXPAUHDC__@@@Z)
1>Config_Stage1.obj : error LNK2019: symbole externe non résolu "void * __cdecl operator new[](unsigned int,struct
std::_DebugHeapTag_t const &,char *,int)" (??_U@YAPAXIABU_DebugHeapTag_t@std@@PADH@Z) référencé dans la fonction "public:
char * __cdecl std::_DebugHeapAllocator<char>::allocate(unsigned int,void const *)"
(?allocate@?$_DebugHeapAllocator@D@std@@QAAPADIPBX@Z)
1>MSLJ_Gemini.obj : error LNK2001: symbole externe non résolu "void * __cdecl operator new[](unsigned int,struct
std::_DebugHeapTag_t const &,char *,int)" (??_U@YAPAXIABU_DebugHeapTag_t@std@@PADH@Z)
1>Config_Stage1.obj : error LNK2019: symbole externe non résolu "struct std::_DebugHeapTag_t const & __cdecl
std::_DebugHeapTag_func(void)" (?_DebugHeapTag_func@std@@YAABU_DebugHeapTag_t@1@XZ) référencé dans la fonction "public: char
* __cdecl std::_DebugHeapAllocator<char>::allocate(unsigned int,void const *)"
(?allocate@?$_DebugHeapAllocator@D@std@@QAAPADIPBX@Z)
1>MSLJ_Gemini.obj : error LNK2001: symbole externe non résolu "struct std::_DebugHeapTag_t const & __cdecl
std::_DebugHeapTag_func(void)" (?_DebugHeapTag_func@std@@YAABU_DebugHeapTag_t@1@XZ)
1>.\..\..\..\Modules/MSLJ_Gemini.dll : fatal error LNK1120: 3 externes non résolus
1>Le journal de génération a été enregistré à l'emplacement
"file://c:\Users\Marty\Desktop\Orbiter_Gemini\Orbitersdk\samples\GeminiSpirit\Debug\BuildLog.htm"
1>MSLJ_Gemini - 7 erreur(s), 0 avertissement(s)
========== Génération : 0 a réussi, 1 a échoué, 0 mis à jour, 0 a été ignoré ==========
Sinon, mon visual est configuré comme dans le tuto de Dan, j'ai pas mis de "dépendances supplémentaires" (j'ai essayé avec
quelques-unes: aucun résultat mais bon...c'était du tatonnage) et j'ai dû exclure msvcrt.lib et libcpmtd.lib (sinon il me
dit qu'elles font conflict...)
Merci beaucoûp à ceux qui oseront jeter un coup d'oeil là-dessus!
-
Ah damned je l'ai déjà eu celle la , c'est un truc de lib ou de paramètre of course mais me souviens plus.
Tu peux poster le zip du projet quelque part et me filer le lien en privé que je zieute ?
A++
Dan
-
je rencontre un problème similaire quand je compile le ShuttlePB SDK for VC++ 2008 Express dispo sur orbit
hangar mods mais seulement en release...
1>------ Début de la génération : Projet : ShuttlePB2008, Configuration : Release Win32 ------
1>Compilation en cours...
1>ShuttlePB.cpp
1>Édition des liens en cours...
1> Création de la bibliothèque .\..\..\..\Modules/ShuttlePB.lib et de l'objet .\..\..\..\Modules/ShuttlePB.exp
1>ShuttlePB.obj : error LNK2001: symbole externe non résolu "const type_info::`vftable'" (??_7type_info@@6B@)
1>ShuttlePB.obj : error LNK2019: symbole externe non résolu "void __cdecl operator delete(void *)" (??3@YAXPAX@Z)
référencé dans la fonction "public: virtual void * __thiscall LaunchpadItem::`scalar deleting destructor'(unsigned int)"
(??_GLaunchpadItem@@UAEPAXI@Z)
1>ShuttlePB.obj : error LNK2019: symbole externe non résolu "void __cdecl operator delete[](void *)" (??
_V@YAXPAX@Z) référencé dans la fonction "public: virtual void * __thiscall LaunchpadItem::`vector deleting
destructor'(unsigned int)" (??_ELaunchpadItem@@UAEPAXI@Z)
1>ShuttlePB.obj : error LNK2019: symbole externe non résolu "void __stdcall `eh vector destructor iterator'(void
*,unsigned int,int,void (__thiscall*)(void *))" (??_M@YGXPAXIHP6EX0@Z@Z) référencé dans la fonction "public: virtual
void * __thiscall LaunchpadItem::`vector deleting destructor'(unsigned int)" (??_ELaunchpadItem@@UAEPAXI@Z)
1>ShuttlePB.obj : error LNK2001: symbole externe non résolu __fltused
1>ShuttlePB.obj : error LNK2001: symbole externe non résolu __purecall
1>ShuttlePB.obj : error LNK2019: symbole externe non résolu "void * __cdecl operator new(unsigned int)" (??
2@YAPAXI@Z) référencé dans la fonction _ovcInit
1>LINK : error LNK2001: symbole externe non résolu __DllMainCRTStartup@12
1>F:\Jeux\CTVATV\Modules\ShuttlePB.dll : fatal error LNK1120: 8 externes non résolus
1>Le journal de génération a été enregistré à l'emplacement
"file://c:\OrbiterSDK\Orbitersdk\samples\ShuttlePB2008\Release\BuildLog.htm"
1>ShuttlePB2008 - 9 erreur(s), 0 avertissement(s)
========== Génération : 0 a réussi, 1 a échoué, 0 mis à jour, 0 a été ignoré ==========
Curieusement en passant par un debug en premier je peux compiler en release mais la dll que je récupère fait
toujours le même poids !!!
-
postez moi le lien les libs c'est la merde mais je trouve toujours rapidement quand je peux tester, comme c'est du
tatonnement je suis infoutu de vous dire ce qui manque vraiment en lisant les messages. (par contre une fois résolu je peux
dire ce qui n'allais pas ;) )
Dan
-
MartySpaceLines a écrit:
Bien le bonjour! ;)
Alors... Comme beaucoup de monde ici, je connais à-peu-près le langage C++, mais lorsqu'il s'agit de configurer Visual et de
farfouiller dans toutes ces librairies au nom obscure (msvcrt et autres), alors là ça se corse!!
Pour quelqu'un qui s'y connaît, c'est surement un problème easy à résoudre, mais pour moi...no comment!
Ma sortie du debug:
1>------ Début de la génération : Projet : MSLJ_Gemini, Configuration : Debug Win32 ------
1>Édition des liens en cours...
1> Création de la bibliothèque .\Debug/MSLJ_Gemini.lib et de l'objet .\Debug/MSLJ_Gemini.exp
1>Config_Stage1.obj : error LNK2001: symbole externe non résolu "public: virtual void __thiscall
MFD::Update(struct HDC__ *)"
[...]
"file://c:\Users\Marty\Desktop\Orbiter_Gemini\Orbitersdk\samples\GeminiSpirit\Debug\BuildLog.htm"
1>MSLJ_Gemini - 7 erreur(s), 0 avertissement(s)
========== Génération : 0 a réussi, 1 a échoué, 0 mis à jour, 0 a été ignoré ==========
Sinon, mon visual est configuré comme dans le tuto de Dan, j'ai pas mis de "dépendances supplémentaires" (j'ai
essayé avec
quelques-unes: aucun résultat mais bon...c'était du tatonnage) et j'ai dû exclure msvcrt.lib et libcpmtd.lib (sinon il me
dit qu'elles font conflict...)
Merci beaucoûp à ceux qui oseront jeter un coup d'oeil là-dessus!
Je viens d'essayer de redémarrer avec le projet "ShuttlePB" et là aussi rien à faire :(
Ce qui me taquine surtout, c'est la lnk2001 qui vient avec MFD::Update (HDC)... et ça c'est vraiment bizarre: je fais
un vaisseau, donc techniquement y devrait même pas savoir ce qu'est qu'un MFD! (A moins que je le lui dise...)
-
MartySpaceLines a écrit:
Je viens d'essayer de redémarrer avec le projet "ShuttlePB" et là aussi rien à faire :(
Ce qui me taquine surtout, c'est la lnk2001 qui vient avec MFD::Update (HDC)... et ça c'est vraiment bizarre: je fais
un vaisseau, donc techniquement y devrait même pas savoir ce qu'est qu'un MFD! (A moins que je le lui dise...)
si les vaisseau créent les MFD donc c'est normal qu'il y' ait un lien.
Je viens de retster, juste en reprennant le ShuttlePB tout neuf, j'ai convertit le dsw en version visual studio 2008 (free)
et juste ajouté le lien vers ..\..\include dans le path et ajouté cette ligne : msvcrt.lib msvcirt.lib à "Ignore specific
libraries"
et ca a compilé et linké correctement. Mais bon j'ai pas testé le résultat
-
MartySpaceLines a écrit:
Sinon, mon visual est configuré comme dans le tuto de Dan, j'ai pas mis de "dépendances supplémentaires" (j'ai
essayé avec quelques-unes: aucun résultat mais bon...c'était du tatonnage) et j'ai dû exclure msvcrt.lib et libcpmtd.lib
(sinon il me dit qu'elles font conflict...)
J'ai testé ton projet, j'ai juste changé les ignore librarie pour mettre uniquement celle-la:
(dans ignore library: ) MSVCRT.lib
Ca compile nickel. Si ca marche toujours pas reposte le log de compilation et check bien tes chemins lib/include
A++
Dan
Message modifié ( 21-10-2009 14:25 )
-
edit : J'ai rien dit, le problème est résolu, merci la lecture, relecture, et encore relecture de la page 2 :D
edit 2 : J'ai réussi ma première animation !
Message modifié ( 24-10-2009 18:25 )
-
A peine un problème résolu qu'on tombe dans une nouvelle problématique !
Je m'explique :
Pour l'animation de l'iris, j'ai neuf lames qui tournent toutes autour du même axe mais avec des points de rotation
différents, donc pour mon code, j'ai mis ceci :
static UINT GroupMeshBlade1[1] = {6};
BladeOpen1 = new MGROUP_ROTATE(0,GroupMeshBlade1,1,_V(17.668,0,-30.601),_V(0,1,0),(float)(-0.4*PI));
static UINT GroupMeshBlade2[1] = {0};
BladeOpen2 = new MGROUP_ROTATE(0,GroupMeshBlade2,1,_V(-6.136,0,-34.798),_V(0,1,0),(float)(-0.4*PI));
static UINT GroupMeshBlade3[1] = {13};
BladeOpen3 = new MGROUP_ROTATE(0,GroupMeshBlade3,1,_V(-27.068,0,-22.713),_V(0,1,0),(float)(-0.4*PI));
static UINT GroupMeshBlade4[1] = {12};
BladeOpen4 = new MGROUP_ROTATE(0,GroupMeshBlade4,1,_V(-35.335,0,0),_V(0,1,0),(float)(-0.4*PI));
static UINT GroupMeshBlade5[1] = {11};
BladeOpen5 = new MGROUP_ROTATE(0,GroupMeshBlade5,1,_V(-27.05,0,22.751),_V(0,1,0),(float)(-0.4*PI));
static UINT GroupMeshBlade6[1] = {10};
BladeOpen6 = new MGROUP_ROTATE(0,GroupMeshBlade6,1,_V(-6.136,0,34.798),_V(0,1,0),(float)(-0.4*PI));
static UINT GroupMeshBlade7[1] = {9};
BladeOpen7 = new MGROUP_ROTATE(0,GroupMeshBlade7,1,_V(17.668,0,30.567),_V(0,1,0),(float)(-0.4*PI));
static UINT GroupMeshBlade8[1] = {8};
BladeOpen8 = new MGROUP_ROTATE(0,GroupMeshBlade8,1,_V(33.204,0,12.085),_V(0,1,0),(float)(-0.4*PI));
static UINT GroupMeshBlade9[1] = {7};
BladeOpen9 = new MGROUP_ROTATE(0,GroupMeshBlade9,1,_V(33.204,0,-12.085),_V(0,1,0),(float)(-0.4*PI));
uAnim_Blade = CreateAnimation (0.0);
AddAnimationComponent (uAnim_Blade,0,1,BladeOpen1);
AddAnimationComponent (uAnim_Blade,0,1,BladeOpen2);
AddAnimationComponent (uAnim_Blade,0,1,BladeOpen3);
AddAnimationComponent (uAnim_Blade,0,1,BladeOpen4);
AddAnimationComponent (uAnim_Blade,0,1,BladeOpen5);
AddAnimationComponent (uAnim_Blade,0,1,BladeOpen6);
AddAnimationComponent (uAnim_Blade,0,1,BladeOpen7);
AddAnimationComponent (uAnim_Blade,0,1,BladeOpen8);
AddAnimationComponent (uAnim_Blade,0,1,BladeOpen9);
C'est un peu fastidieux ! Y'a-t-il un moyen de définir le point de référence pour la rotation par rapport au groupe ou est-il
possible de créer une fonction pour rassembler le tout en une seule composante ?
Pour ce cas là ça va, mais c'est pour les panneaux solaires que je m'inquiète, une première rotation suivie d'une translation
et d'une deuxième rotation, ça risque de faire beaucoup de composantes pour l'animation à définir ! Surtout si après je veux
implémenter le fait que les panneaux solaires suivent le mouvement du soleil !
Quelqu'un aurait-il une idée ?
-
J'ai un petit probleme avec la super classe SaveRestoreScenario de Dan.
Elle est hyper pratique, mais je suis incapable de sauvegarder une variable Enum
Dans la declaration de ma classe dans mon header, j'ai:
enum DoorStatus {DOOR_CLOSED, DOOR_OPEN, DOOR_CLOSING, DOOR_OPENING} ArrayDep_status;
Je l'ai bien initialisé... En fais, tout marchais bien avec l'ancien systeme de sauvegarde, mais avec la classe de Dan, VC++
me sort l'erreur suivante a la compilation:
C2664: 'void SaveRestoreScenario::SavedVariable(int,int *)' : impossible de convertir le paramètre 2 de 'xxx::DoorStatus *' en 'int *'
Et quand je clique dessus il me renvoi à
Scn.SavedVariable(1, &ArrayDep_status);
Quelqu'un à une idée?
Message modifié ( 14-11-2009 17:58 )
-
Drenake a écrit:
Scn.SavedVariable(1, &ArrayDep_status);
Quelqu'un à une idée?
Les enum c'est des int en taille il suffit de forcer le type pour que le compilo gueule plus.
Donc tu fais comme cela:
Scn.SavedVariable(1, (int*)&ArrayDep_status);
"(int*)" devant force le type.
a++
Dan
-
AH! Je l'avais presque, j'avais essayé
..., (int)&ArrayDep_status);
J'imagine que le " * " c'est parce que la fonction utilise des pointeurs?!?
En tout cas, Merci oh grand maitre Dan :wor:
-
Exact il attend un pointeur de type int d'ou le "int*"
Mais y a pas de quoi, si on peut aider ;)
A++
Dan
-
Bonjour ? n'ayant pas de réponse sur le forum,
je pose la question différemment ici, on ne sait jamais.
J'essaie de programmer un panneau pour mon addon, j'ai suivi le tuto et l'API-Guide mais je bloque d'entrée ...
Dans le clbkLoadPanel (int id), je met ça:
{
HBITMAP hBmp = LoadBitmap (g_Param.hDLL, MAKEINTRESOURCE(IDB_BITMAP1));
oapiRegisterPanelBackground (hBmp, PANEL_ATTACH_BOTTOM|PANEL_MOVEOUT_BOTTOM, 0xFFFFFF);
return true;
}
ResEdit m'a créé un ".rc" à partir de mon dossier "Bitmaps" contenant mon "panel 2D" en Bmp 8 bits (1340x760) ainsi qu'un "resource.h" associé contenant : #define IDB_BITMAP1 100
J'ai ajoouté "resource.h" et mon ".rc" dans ma "solution", je compile, je replace la DLL créée dans "Modules", je lance Orbiter 2010 P1, tout est là, sauf ... mon panel 2D :worry: :wall:
QUESTION :
(https://www.surlatoile.com/smileys/repository/Musique/guitare-musique-hard-75.gif) Il est où le problème il est oùùù ?
:merci: