GDI+D: Scène 3D interactive

Soyez le premier à donner votre avis sur cette source.

Vue 5 fois - Téléchargée 1 fois

Description

Bonjour,

▼▼Bug CCM-CS: voir ci-dessous▼▼

Sous Windows, on peut programmer une représentation graphique non triviale en utilisant "que" GDI (Graphics Device Interface).
Il est bien entendu que le plus souvent, il vaut mieux étudier, installer et utiliser des librairies graphiques plus évoluées telles que OpenGL, DirectX, etc.

La scène 3D interactive construite ici devrait permettre de:
- Tourner un objet librement autour de son axe 3D vertical Z.
- Basculer (incliner) l'objet en bas ou en haut (par rapport à l'écran).
- Déplacer l'œil (perpendiculairement à l'écran) pour modifier l'effet de perspective.
- Agrandir ou rétrécir l'image 2D projetée (zoom 2D intelligent) avec la roulette.
- Déplacer l'image 2d obtenue (move 2D) avec bouton gauche de la souris.
- Modifier interactivement un paramètre de l'objet représenté (Damier).
- Obtenir une séquence de dessins sans scintillement.
- Modifier les dimensions de la fenêtre.

Elle est basés principalement sur "GDI+C: Dessin sans scintillement" et sur l'édification de la perspective qui suit.

Transformation (perspective) en notation matricielle

Projection 3D->2D:
       Basculement (rotX)         (rotZ)
(x')   (1   0       0   )   (cos(a) -sin(a) 0)   (x)
(y') = (0 cos(b) -sin(b)) * (sin(a)  cos(a) 0) * (y)
(z')   (0 sin(b)  cos(b))   (  0       0    1)   (z)

       (       cos(a)       -sin(a)       0)   (x)   (XX XY  0)   (x)
     = (cos(b)*sin(a) cos(b)*cos(a) -sin(b)) * (y) = (YX YY YZ) * (y)
       (sin(b)*sin(a) sin(b)*cos(a)  cos(b))   (z)   (ZX ZY ZZ)   (z)

Perspective: q = d/(d+y');  U = q*x';  V = q*z'; // W = q*y';

Avec la transformation 2D->2D (layout, mise en page):
       u = U0 + Dil*U; v = V0 + Dil*V;

struct Persp {
  const float DegToRad=0.01745329f;
  float D,XX,XY,YX,YY,YZ,ZX,ZY,ZZ; // XZ=0: vertical reste vertical

  void Def(float d,float az,float ab) {// az,ab: en degrés (°)
    float rz=az*DegToRad,rx=-ab*DegToRad; // en rad
    float sa=sinf(rz),ca=cosf(rz),sb=sinf(rx),cb=cosf(rx);
    D=d; XX=ca; XY=-sa;
    YX=cb*sa; YY=cb*ca; YZ=-sb;
    ZX=sb*sa; ZY=sb*ca; ZZ=cb;
  }
};

Nous choisissons ici un objet simple et "plat", adapté aux différentes étapes du programme:
struct Damier {
  int N=0,NN;
  float *C,*U,*V; // *W pas utilisé

  void Def(int n) { // Damier carré n*n centré à l'origine (n>0)
    if ((n<=0)||(n==N)) return;
    if (N>0) {free(C); free(U); free(V);}
    N=n; NN=(n+1)*(n+1);
    int m=NN*sizeof(float);
    C=(float*)malloc((n+1)*sizeof(float));
    U=(float*)malloc(m); V=(float*)malloc(m); // W=(float*)malloc(m);
    float d=200.0f/n,c=-100.0f;
    for (int i=0; i<n; ++i,c+=d) C[i]=c;
    C[n]=100.0f;
  }
  void Transf(Persp* psp) {
    for (int j=0,k=0; j<=N; ++j) {float y=C[j];
      for (int i=0; i<=N; ++i,++k) {
        float x=C[i],q=psp->D/(psp->D+psp->YX*x+psp->YY*y);
        U[k]=q*(psp->XX*x+psp->XY*y); V[k]=q*(psp->ZX*x+psp->ZY*y);
      }
    }
  }
  void Draw(HDC hdc,int u0,int v0,float dil) {
    const HBRUSH b1=CreateSolidBrush(0X22FF00),b2=CreateSolidBrush(0X0022FF);
    SelectObject(hdc,GetStockObject(NULL_PEN));
    int n1=N+1,n11=n1+1;
    for (int j=0,k=0; j<N; ++j,++k)
      for (int i=0; i<N; ++i,++k) {POINT fc[4];
        fc[0]={u0+(int)(dil*U[k])    ,v0+(int)(dil*V[k])};
        fc[1]={u0+(int)(dil*U[k+1])  ,v0+(int)(dil*V[k+1])};
        fc[2]={u0+(int)(dil*U[k+n11]),v0+(int)(dil*V[k+n11])};
        fc[3]={u0+(int)(dil*U[k+n1]) ,v0+(int)(dil*V[k+n1])};
        SelectObject(hdc,((i&1)==(j&1))?b1:b2); Polygon(hdc,fc,4);
    }
  }
};

 
Bonne lecture ... 
 
 

Liens

WikipédiA: Graphics Device Interface
CodeS-SourceS: GDI+A: Déplacement avec la souris
CodeS-SourceS: GDI+B: Move et Zoom avec la souris
CodeS-SourceS: GDI+C: Dessin sans scintillement
CodeS-SourceS/Javascript Retro-A: Scène et perspective
 
 

Bug CCM-CS: Charger une image

Depuis le 14 oct. 2017, personne ne peut déposer un code avec une image comme on est pourtant invité à le faire (voir par exemple: Liste des derniers codes sources).
A mon avis, ces images de capture sont très importantes !

En attendant, je mets cette image à disposition dans le fichier Capture.jpg du Zip, et demande au lecteur de m'excuser pour cette complication.

Je me permets de signaler ici ce bug d'une manière peu conventionnelle, car malgré bien des demandes, les "responsables" sont restés muets (voir: Discussion: Charger une image).

Dans tous les articles, j'enlèverai toute référence à ce bug dès qu'il sera de nouveau possible de charger une image (de capture) pour les articles existants et nouveaux.
 
 

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

Commenter la réponse de William VOIROL

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.