Orbiter Francophone > Création Orbiter Francophone

Les déplacements en apesanteur, c'est ICI !

(1/3) > >>

jeanus:
Bonjour, changement de programme.
J’arrête le DSSV Apollonius, j’arrête l'ISS by Jeanus.

Faire l'addon du siècle c'est bien, donner à tout le monde la possibilité d'en faire de-même, c'est mieux !

Pour que tout le monde ait accès aux déplacements en apesanteur "réalistes", je vais vous donner tous les codes C++ avec les explications pour que vous puissiez vous même créer vos propres vaisseaux ou/et modifier vos anciennes réalisations sous réserves qu'elle ne soient pas écrites en "Spacecraft …"

Vous pourrez et devrez en abuser ainsi que les modifier et les faire évoluer, parce-que je ne suis pas parfait … quoi que !!!

Ceci sera donc ma modeste contribution à Orbiter.

=======================================================

Avant toutes choses, il vous faudra créer un mesch spécifique pour l'intérieur de votre vaisseau ou pourquoi pas une base (pour l'infrastructure vous pourrez toujours demander à JacquesMomo !), donc normales visibles de l'intérieur.

Si vous faites un cube la programmation des "limites" sera très simple. Après, tout est permi, il y aura plus de lignes de codes, c'est tout.
 

Le principe est le même si vous êtes à l'extérieur d'une zone dans la quelle vous ne voulez pas entrer, exemple l'ISS … vous faites un mesch invisible autour de la structure "réelle" (mesch que vous n'avez pas besoin d'éditer, fait juste pour calculer les limites)

 

Avec une vitesse de déplacement très faible, vous aurez l'impression de vous promener en vous accrochant à la structure et si vous atteignez les limites extérieures, vous serez bloqué par un filin invisible qui vous relie à l'ISS.

La base est terminée, jusque là, ça va ? on ne peut pas faire plus simple …

jeanus:
Voyons maintenant les commandes. Toute la programmation est organisée autour d'une souris 3 boutons (5 boutons  ce serait mieux, on verra pourquoi après).

Déplacements      Droit / Gauche   >   rotation autour de l'axe   Y   en statique et en mouvement
         Haut / Bas      >   rotation autour de l'axe   X   en statique et en mouvement
Clic Droit + dép. Droit / Gauche   >   rotation autour de l'axe   Z   en mouvement uniquement
(avec 5 boutons vous pourrez facilement recréer la rotation en statique …)

      Molette de la souris vers l'avant      >   incrémentation de la vitesse > déplacement dans l'axe +Z
Molette de la souris vers l'arrière    >   décrémentation de la vitesse > déplacement dans l'axe -Z

Clic Droit et Gauche simultannés   >   Basculement du mode déplacement vers le mode commande, matérialisé par le remplacement du curseur "croix" par un curseur "doigt" ou "main".

Dans cette configuration, le déplacement est figé, vous etes devant un tableau de commande (ou scanner, d’où la "main" …), le bouton gauche de la souris vous permet d'actionner les différentes commandes que vous avez programmées.

Voilà, c'est fini !!!

Maintenant place aux explications des différents codes C++ utilisés … rassurez-vous c'est aussi simple.
=======================================

#include "MaClasseAddon.h"
!
 
#include "windows.h" … à ajouter dans la classe "_.h"


void MonVaisseau::clbkPostStep(double simt, double simdt, double mjd)
{

   if (iDetecteChangementSeconde != (int)simt)
   {
      iTempDeSimulationTotal++;
      iDetecteChangementSeconde = (int)simt;
   }

   if (DIRXY == 1)   //reprendre l'état initial général   un flag qui recale le curseur au centre de l'écran après l'action d'une commande, le curseur "doigt" est peut-être n'importe ou sur l'écran, lorsque vous revenez en mode "déplacement", si vous n'etiez pas recentré vous partiriez "en vrille rapide" !!!
   {
      // Remplacement du curseur et mise au centre de l'écran
      HCURSOR mon_curseur_ à_moi = LoadCursor(NULL, MAKEINTRESOURCE(32515)); 32515 code du curseur "croix" pour les déplacements. Vous pouvez créer vos propres curseur et les charger avec ceci :
LoadCursorFromFile("\\Orbiter2016\\Textures\\MonVaisseau/mon_curseur.cur");

      HCURSOR copimon_curseur_ à_moi = CopyCursor(mon_curseur_ à_moi);
      SetSystemCursor(copimon_curseur_ à_moi, 32512); là on remplace 32512 qui est le curseur Windows d'origine par par le curseur que vous avez défini.

      Mxo = (GetSystemMetrics(SM_CXSCREEN) / 2);//(1920/2);résolution d'écran
      Myo = (GetSystemMetrics(SM_CYSCREEN) / 2);//(1080/2);résolution d'écran
      SetCursorPos(Mxo, Myo); on positionne le curseur au centre de l'écran.

      DIRXY = 0; on passe le flag à 0

      oapiCameraSetCockpitDir(RAD*xd, RAD*yd, true); vous regardez droit devant avec une croix comme viseur !

      unsigned int speed = 1; Vitesse de déplacement de la souris très faible, on repassera à 10 en vitesse normale pour avoir plus d'amplitude en mode "commande".

      void *pvoid;
      pvoid = &speed;
      SystemParametersInfo(SPI_SETMOUSESPEED, 0, (void*)speed, SPIF_SENDCHANGE); vitesse de déplacement de la souris = 1

MISE EN PLACE TERMINEE

jeanus:
Gestion de la souris


   if ((GetAsyncKeyState(VK_LBUTTON) & 0x8000) != 0 && (GetAsyncKeyState(VK_RBUTTON) & 0x8000) != 0)
affichage doigt de commande ou scanner bouton D & G souris
   {
      unsigned int time;
      time = GetTickCount();
      while (GetTickCount() < time + 300) {}   //  ms
      (kst == 1) ? kst = 0 : kst = 1; mode commande ou mode déplacement (flip-flap)
   }   ça c'est la tempo pour assurer le passage du mode déplacement au mode commande, de façon fluide.

   if (kst == 1)
//doigt de commandes
   {
      VTS = 0;
      if (ZV == 0) test pour savoir si c'est un tableau ou un scanner
      {
         HCURSOR Doicurs = LoadCursor(NULL, MAKEINTRESOURCE(32649)); 32649 curseur "doigt"
//doigt pousse boutons
         HCURSOR Doigtcurs = CopyCursor(Doicurs);
         SetCursor(Doicurs);
      }
      else if (ZV != 0 && (iz<-16 || iz>-18)) c'est un scanner
      {
         HCURSOR Maincurs = LoadCursor(NULL, MAKEINTRESOURCE(32514)); 32514 curseur "main"
//main pour scanner
         HCURSOR maincurs = CopyCursor(Maincurs);
         SetCursor(maincurs);
      }
      unsigned int speed = 10;
      void *pvoid;
      pvoid = &speed;
      SystemParametersInfo(SPI_SETMOUSESPEED, 0, (void*)speed, SPIF_SENDCHANGE);
      vkst = 1; vitesse souris 10 pour amplitude sur tableaux de commandes

   }
   if (kst == 0 && vkst == 1)
recalage curseur sur sa position initiale centre écran vitesse souris 0 après commande
   {
      DIRXY = 1;
      vkst = 0;
   }

SOIT ON SE DÉPLACE SOIT ON COMMANDE

POSITIONNEMENT DANS L'ESPACE, EN APESANTEUR

   if (kst == 0 && DIRXY == 0 && vst == 0)
regard   rotation en X et Y
   {
      if ((GetAsyncKeyState(VK_RBUTTON) & 0x8000) == 0)
 bouton Droit de la souris pour rotation en Z    – Pas de rotation demandée
      {
         if (GetCursorPos(&p))
         {
            Mx = p.x;
            My = p.y;
            MxDif = (Mx != Mxo) ? Mxo - Mx : -0.5;
+ Droite – Gauche
            MyDif = (My != Myo) ? Myo - My : -0.5;
+ Haut – Bas
            if (ZV == 0) { (yd > 89.999 && yd < 269.999) ? yv = -1 : yv = 1; } modification du sens de rotation en fonction du secteur, + ou – de 90 à 270 et de 271 à 89. 3 décimales pour la finesse.
            else (yv = -1);
            yd = yd + (MyDif / 100);
            if (yd > 359.9) yd = 0;
            if (yd < 0) yd = 359.9;

            (xd > 89.999 && xd < 269.999) ? xv = -1 : xv = 1; Idem ci dessus
            xd = xd + (yv*(MxDif / 100));
            if (xd > 359.9) xd = 0;
            if (xd < 0) xd = 359.9;

            if (tlt != 0) recalage à 0 tlt après rotation en Z

            {
               if (VTS == 0 && (((abs(sin(RAD*xd))) > 0.35) || ((abs(sin(RAD*yd))) > 0.35)))
               {
                  if (tlt < 0) tlt = tlt + 0.2;
                  if (tlt > 0) tlt = tlt - 0.2;
                  if (tlt < 0.3 && tlt > -0.3) tlt = 0;
                  SetCameraDefaultDirection(_V(0, 0, 1), RAD * tlt);
               }
            }
            oapiCameraSetCockpitDir(RAD*xd, RAD*yd, true);
vous regardez dans la bonne direction
            oxd = xd; oyd = yd;
vous recalez votre regard à 0
         }
      }
      Else
rotation en Z demandée
      {
         if (VTS>0 && abs(sin(RAD*xd)<0.35) && abs(sin(RAD*yd)<0.35))

autorisation de rotation en Z si vous etes en mouvement !!! à modifier avec une souris 5 boutons.( ou supprimer, à vous de voir)

         {
            GetCursorPos(&p);
            Mx2 = p.x;
            MxDif2 = Mxo - Mx2;//(Mx2 != Mxo) ?  : -0.5
            if (MxDif2 > 0) tlt = tlt + 0.3;
droite
            if (MxDif2 < 0) tlt = tlt - 0.3;
gauche
            if (tlt > 180)tlt = -179.7;
            else if (tlt < -180)tlt = 179.7;
            SetCursorPos(Mxo, Myo);  recentrage visée
            SetCameraDefaultDirection(_V(0, 0, 1), RAD * tlt); application du tilt
            oapiCameraSetCockpitDir(RAD*oxd, RAD*oyd, true); recentrage regard
         }
      }
   }

LES ROTATIONS C'EST FAIT

jeanus:
vitesse de déplacement

La molette de la souris étant utilisée dans Orbiter pour effectuer un zoom,
En fait la modification de l'angle d'ouverture,
j'ai trouvé plus facile de récuperer l'information d'ouverture
pour gerer les accelerations positives ou negatives
tout en limitant la vitesse maxi de déplacement,
que d'aller chercher un code "WinApi", que je ne connais pas.
J'avais demandé à "Doc Martin" quel code il utilise … jamais eu de retour …


   zDelta = oapiCameraAperture();  récupération valeur d'ouverture

{
   if (zDelta < (RAD * 25))          récupération du sens de rotation de la molette pour accélération "<"
        ou décélération ">"
      {
      VTS = VTS + 0.2;         incrémentation de la vitesse de déplacement
      oapiCameraSetAperture(RAD * 25);   figeage de l'ouverture
      if (VTS > 0.8)  VTS = 0.8;
if (xv != xvd || yv != yvd)VTS = 0;
      SX = sin(RAD * xd);
      SY = sin(RAD * yd);
      (xd > 89.999 && xd < 269.999) ? xvd = -1 : xvd = 1;
      (yd > 89.999 && yd < 269.999) ? yvd = -1 : yvd = 1;
      X = yvd * -SX;
      Y = SY;

      if ((xd < 95 && xd>85) || (xd < 275 && xd>265) || (yd < 95 && yd>85) || (yd < 275 && yd>265)) Z = 0;
      else Z = xvd * yvd * (min(abs(cos(RAD * xd)), abs(cos(RAD * yd))));
      }
   else if (zDelta >(RAD * 25))          décélération
      {
      oapiCameraSetAperture(RAD * 25);
      if (xv != xvd || yv != yvd)VTS = 0;
      SX = sin(RAD * xd);
      SY = sin(RAD * yd);
      (xd > 89.999 && xd < 269.999) ? xvd = -1 : xvd = 1;
      (yd > 89.999 && yd < 269.999) ? yvd = -1 : yvd = 1;
      X = yvd * -SX;
      Y = SY;
      if ((xd < 95 && xd>85) || (xd < 275 && xd>265) || (yd < 95 && yd>85) || (yd < 275 && yd>265)) Z = 0;
      else Z = xvd * yvd * (min(abs(cos(RAD * xd)), abs(cos(RAD * yd))));
      VTS = VTS - 0.1;
      if (VTS < -0.4) VTS = -0.4;
      }
}

ON PRÉPARE LES DÉPLACEMENTS, C'EST QUE DE LA TRIGO !

Y'A PUS QU'A

MAINTENANT ON BOUGE !


   //TEST ZONE VIE TECH / SERRE C'est ici qu'il faut faire le test entre les différentes zones … 2ème déssin 1ère page

   if (ZVD == 0) ça c'était pour le DSSV
   {
      
                            DEBUT VAISSEAU ZONE CENTRALE                          
      


      if (VTS>0) Vitesse positive
      {
         double dc = simdt * CAMERA_OPERATING_SPEED * VTS;
         ix = ix + (dc * X);
         iy = iy + (dc * Y);
         iz = iz + (dc * Z);
      }
      else if (VTS<0) Vitesse négative
      {
         double dc = simdt * CAMERA_OPERATING_SPEED * abs(VTS);
         ix = ix - (dc * X);
         iy = iy - (dc * Y);
         iz = iz - (dc * Z);
      }
      SetCameraOffset(_V(ix, iy, iz));
      ox = ix; oy = iy; oz = iz;

I  BILIEVE  I  CAN  FLY !!!!

OUI MAIS JE PASSE AU TRAVERS DES MURS

BON, ALORS ON GÈRE LES COLLISIONS

jeanus:
limites de la zone de déplacement:

Le DSSV est relativement complexe avec ses SAS automatiques et ses salles coniques. Je vous laisse analyser les limitations mises en place, vous avez encore la vidéo dans le "post" du DSSV SUR VOS ECRANS … BIENTÔT, pour vous aider.



if (iz<Pzmax && iz>8.5) Pxmax = Pymax = (2.8 + ((iz - 3.5)*0.218)), Pymin = -Pxmax, Pxmin = -(0.7 + ((iz - 3.5)*0.40));limites de zone
if (iz<8.49 && iz>3.49) Pxmax = Pymax = (2.8 + ((iz - 3.5)*0.218)), Pymin = -Pxmax, Pxmin = -(0.7 + ((iz - 3.5)*0.082));limites de zone

if (iz<4.9 && iz>1.5 && (SASinfo_AV_status == SASINFOAV_CLOSED))  VTS = 0;   si vous n'êtes pas dans l'axe du sas ou si celui-ci est fermé,vous vous arretez         
if (iz<4.9 && iz>1.5) Pxmax = 1.25, Pymax = 0.75, Pxmin = 0.15, Pymin = -0.75;      passage du sas                                    
if (iz<3 && iz>-3.5) Pxmax = Pymax = 1.8, Pymin = Pxmin = -1.8; limites de zone
if (iz<-3.49 && iz>-11)Pxmax = 2; Pymax = 2.6; Pxmin = -2; Pymin = -2.6;limites de zone

if (iz<-10.99 && iz>-12.5 && (SASinfo_TEC_status == SASINFOTEC_CLOSED)) VTS = 0;   Re SAS                                    
if (iz<-11 && iz>-12) Pxmax = 0.5, Pymax = 0.8, Pxmin = -0.5, Pymin = -0.8;      Re-passage                                       
if (iz<-11.99 && iz>-25.28 && ZV == 0) Pxmax = Pymax = 3.7, Pymin = Pxmin = -3.7;   intervale d'accès zones                                    
if (iz<-23.5 && iz>-26.6 && (SASTEC_AR_status == SASTECAR_CLOSED))  VTS = 0;   Re SAS                                       
if (iz<-23.37 && iz>-26.74) Pxmax = 0.5, Pymax = 0.8, Pxmin = -0.5, Pymin = -0.8;      Re-passage                                 
if (iz<-26.74 && iz>-31.44) Pxmax = Pymax = 3, Pxmin = Pymin = -3; limites de zone         

if (iz<-29 && (SAS_AR_status == SASAR_CLOSED))  VTS = 0;          Re SAS                                             
if (iz<-31.43) Pxmax = Pymax = 0.45, Pxmin = Pymin = -0.45;            Re-passage         

fin limites vaisseau
 
   VOUS N'ALLEZ PAS DIRE QUE C'EST COMPLIQUE, Non ?


Maintenant, si on bute sur les parois, on s'arrête. Si vous mettez un petite valeur de vitesse (VTS), comme vous ne serrez jamais parfaitement perpendiculaire à la cloison, vous aurez la sensation d'être vraiement en apesanteur avec un léger flottement …

         if (iz < Pzmin) { iz = Pzmin; VTS = 0; }
         if (iz > Pzmax) { iz = Pzmax; VTS = 0; }
         if (ix < Pxmin) { ix = Pxmin; VTS = 0.05; }
         if (ix > Pxmax) { ix = Pxmax; VTS = 0.05; }
         if (iy < Pymin) { iy = Pymin; VTS = 0.05; }
         if (iy > Pymax) { iy = Pymax; VTS = 0.05; }


Et c'est tout !

(Si vous réussisez à faire plus simple, faites-le savoir, donnez vos codes, ce sera super simpa !!!)

Ultime précision : Si vous démarrez par votre addon "VVIaDeAeGdC" (Vaisseau Virtuel Interactif avec Déplacements en Apesanteur et Gestion des Collisions !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!) vous aurez au milieu de l'écran une croix avec une vitesse de déplacement de la souris très faible à savoir 1, pour vous déplacer "en apesanteur". Si vous passez en mode "commande", vous aurez un "doigt" avec une vitesse de 10 (vitesse originale Windows).
En faisant F3 et en basculant dans un autre vaisseau, vous serez dans la configuration "terminale" de votre addon. Si c'est un "doigt" avec V=10, tout ira bien … si c'est une "croix" avec une vitesse de 1 vous allez avoir de petits problèmes …

Ceci dans le cas ou le vaisseau dans lequel vous allez N'EST PAS MODIFIE "VVIaDeAeGdC". Bien evidemment lorsque tous les vaisseaux d'Orbiter auront été modifiés par leur créateur (ceux en C++) ça ira mieux … en attendant… mèf !

Concernant la gestion des déplacements avec la souris, si Doc Martin pouvait intégrer les codes "WinApi" aux codes "OrbiterApi" cela pourrait faciliter la tâche … may be !

Si je peux faire plus, vous le dites, si les concepteurs de l'ISS "ATO Z" veulent les fichiers 3DS des zones de déplacements extérieurs, intérieures ainsi que les SAS "Carré sur rails" internes ou les "ronds", j'ai tout à leur disposition, demandez c'est cadeau.

Navigation

[0] Message Index

[#] Next page

Go to full version