Simple graphique avec GDI

Description

Bonjour,

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.

Voir: Wiki GDI, Windows GDI (english), Windows Programming/GDI and Drawing

Voici quelques propriétés du code présenté ici:
- aucune librairie graphique à installer.
- un seul fichier: GraphicGDI.cpp ou GraphicGDIa.cpp.
- un seul include: #include <windows.h>.
- création de fonte.
- écriture de textes (aussi non-horizontal).
- utilisation partielle des transformations 2D GDI.
- représentation de l'éponge de Sierpinski (appels récursifs).
- l'objet 3D est "calculé" au moment du dessin.
- vraie perspective (alors que GDI n'a aucune fonctionnalité 3D).
- projection 3D->2D "fixe".
- élimination des facettes et arêtes cachées.
- ...
#include <windows.h>

static float cMin,UX=-646.2198F,UY=861.6264F,VX=320,VY=240,VZ=-1000
  ,WX=-0.742781F,WY=-0.557086F,WZ=-0.371391F,Z=1077; // perspective
static HPEN pen=CreatePen(PS_SOLID,0,0XCCCCCC); // contour des polygones
static HBRUSH bshX=CreateSolidBrush(0X55BB00),bshY=CreateSolidBrush(0XBB5500)
  ,bshZ=CreateSolidBrush(0X77FFFF);
static HFONT fnt=CreateFont(22,9,90,50,400,0,0,0,0,0,0,0,16,"Times New Roman");
static HDC hdc;

static void Prj(float x,float y,float z,POINT *p) { // Projection (x,y,z)-->p
  float w=WX*x+WY*y+WZ*z+Z;
  p->x=(int)((UX*x+UY*y)/w); p->y=(int)((VX*x+VY*y+VZ*z)/w);
}

static void Cube(float x,float y,float z,float c) {
  if (c>cMin) { // subdivision en 27-7 = 20 petits cubes
    float xa=x+(c/=3),xb=xa+c,ya=y+c,yb=ya+c,za=z+c,zb=za+c;
    Cube(x,y ,z ,c); Cube(xa,y ,z ,c); Cube(x ,ya,z ,c); Cube(xb,y ,z ,c);
    Cube(x,yb,z ,c); Cube(xb,ya,z ,c); Cube(xa,yb,z ,c); Cube(xb,yb,z ,c);
    Cube(x,y ,za,c); Cube(xb,y ,za,c); Cube(x ,yb,za,c); Cube(xb,yb,za,c);
    Cube(x,y ,zb,c); Cube(xa,y ,zb,c); Cube(x ,ya,zb,c); Cube(xb,y ,zb,c);
    Cube(x,yb,zb,c); Cube(xb,ya,zb,c); Cube(xa,yb,zb,c); Cube(xb,yb,zb,c);
  } else { // (c <= cMin): projection et dessin
    POINT fX[4],fY[4],fZ[4]; // 3 facettes visibles
    Prj(x+c,y  ,z  ,fX); Prj(x+c,y+c,z  ,fX+1); fY[3]=fX[1];
    Prj(x  ,y+c,z  ,fY); Prj(x  ,y+c,z+c,fY+1); fZ[3]=fY[1];
    Prj(x  ,y  ,z+c,fZ); Prj(x+c,y  ,z+c,fZ+1); fX[3]=fZ[1];
    Prj(x+c,y+c,z+c,fX+2); fZ[2]=fY[2]=fX[2];
    SelectObject(hdc,bshX); Polygon(hdc,fX,4);
    SelectObject(hdc,bshY); Polygon(hdc,fY,4);
    SelectObject(hdc,bshZ); Polygon(hdc,fZ,4);
  }
}

LRESULT CALLBACK WndProc(HWND h,UINT m,WPARAM wP,LPARAM lP) {
  switch(m) {
    case WM_PAINT: {PAINTSTRUCT ps;
      BeginPaint(h,&ps); hdc=ps.hdc; // hdc global
      HGDIOBJ ff=SelectObject(hdc,fnt); // font fnt
      TextOut(hdc,55,55,"Simple graphique avec GDI",25);
      SelectObject(hdc,ff); // initial font
      TextOut(hdc,120,720,"Éponge de Sierpinski:  22.06.2014 / WV",38);
      SelectObject(hdc,pen);
      SetViewportOrgEx(hdc,440,320,0); // origine
      cMin=20; Cube(-240,-240,-240,480); // appel récursif
      EndPaint(h,&ps);
    } return 0;
    case WM_CLOSE: DestroyWindow(h); return 0;
    case WM_DESTROY: PostQuitMessage(0); return 0;
    default: return DefWindowProc(h,m,wP,lP);
  }
}

int WINAPI WinMain(HINSTANCE hI,HINSTANCE hP,LPSTR lC,int nC) {
  WNDCLASS wc={CS_HREDRAW|CS_VREDRAW,WndProc,0,0,hI,LoadIcon(0,IDI_APPLICATION)
    ,LoadCursor(0,IDC_ARROW),CreateSolidBrush(0XF7F7F7),0,"cGDI"};
  RegisterClass(&wc);
  HWND h=CreateWindow("cGDI","Simple graphique avec GDI"
    ,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,880,800,0,0,hI,0);
  ShowWindow(h,nC); UpdateWindow(h);
  MSG m;
  while(GetMessage(&m,0,0,0)>0) {TranslateMessage(&m); DispatchMessage(&m);}
  return m.wParam;
}

Avez-vous remarqué les crénelages (aliasing) de l'affichage ?

Définition CreateFont(...).

GraphicGDIa.cpp est quasiment identique à GraphicGDI.cpp, mais dessine le contour des facettes avec la même couleur que l'intérieur:

Les éléments de GDI non traités ici sont principalement les régions, les images et les "Bitmaps".
 
 
Voir aussi: Fractales, éponge 3d de Sierpinski-Menger

Bonne lecture

Codes Sources

A voir également

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.