Simple graphique avec GDI+

Description

Bonjour,
Je vous invite à "améliorer" un peu le code présenté sous "Simple graphique avec GDI" à l'aide de GDI+ (Graphics Device Interface plus).
Pour cela, nous allons utiliser quelques transformations 2D et l'"anti-aliasing".
Voir: Simple graphique avec GDI,    Anticrénelage ou anti-aliasing

Voici quelques propriétés du code présenté ici:
- aucune librairie graphique à installer.
- code sur un seul fichier: GraphicGDIplus.cpp.
- deux includes: <windows.h> et <gdiplus.h>.
- initialisation de GDI+.
- création de fonte.
- écriture de textes (non-horizontale à l'aide de transformations).
- anticrénelage (anti-aliasing) des textes.
- utilisation 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.
- anticrénelage (anti-aliasing) des polygones et de ses contours.
- ...
#include <windows.h>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")

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;
static Pen *pen;
static SolidBrush *bsh,*bshX,*bshY,*bshZ;
static Graphics *g;
static Font *fnt;

static void Prj(float x,float y,float z,PointF *p) { // Proj (x,y,z)-->p
  float w=WX*x+WY*y+WZ*z+Z;
  p->X=(float)((UX*x+UY*y)/w); p->Y=(float)((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
    PointF 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];
    g->FillPolygon(bshX,fX,4); g->DrawPolygon(pen,fX,4);
    g->FillPolygon(bshY,fY,4); g->DrawPolygon(pen,fY,4);
    g->FillPolygon(bshZ,fZ,4); g->DrawPolygon(pen,fZ,4);
  }
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT mes,WPARAM wParam,LPARAM lParam) {
  PAINTSTRUCT ps;
  switch(mes) {
  case WM_CREATE:
    pen=new Pen(Color(0XFFCCCCCC));
    bsh=new SolidBrush(Color());
    bshX=new SolidBrush(Color(0XFFCC9944));
    bshY=new SolidBrush(Color(0XFF994411));
    bshZ=new SolidBrush(Color(0XFFFFDD77));
    fnt=new Font(L"Times New Roman",20.0); return 0;
  case WM_PAINT:
    BeginPaint(hWnd,&ps); g=new Graphics(ps.hdc);
    g->SetSmoothingMode(SmoothingModeAntiAlias);
    g->DrawString(L"Éponge de Sierpinski (anti-aliasing)"
      ,-1,fnt,PointF(40,720),bsh);
    g->RotateTransform(-9);
    g->SetTextRenderingHint(TextRenderingHintAntiAlias);
    g->DrawString(L"Simple graphique avec GDI+",-1,fnt,PointF(40,60),bsh);
    g->ResetTransform(); g->TranslateTransform(440,320);
    cMin=20; Cube(-240,-240,-240,480);
    EndPaint(hWnd,&ps);
    return 0;
  case WM_DESTROY: PostQuitMessage(0); return 0;
  default: return DefWindowProc(hWnd,mes,wParam,lParam);
  }
}

int WINAPI WinMain(HINSTANCE hI,HINSTANCE,PSTR,int iCmdShow) {
  GdiplusStartupInput gdiplusStartupInput;
  ULONG_PTR gdiplusToken;
  GdiplusStartup(&gdiplusToken,&gdiplusStartupInput,0); // Initialize GDI+

  WNDCLASS wc={CS_HREDRAW|CS_VREDRAW,WndProc,0,0,hI,LoadIcon(0,IDI_APPLICATION)
    ,LoadCursor(0,IDC_ARROW),CreateSolidBrush(0XFFFFFF),0,"cGDI+"};
  RegisterClass(&wc);
  HWND hWnd=CreateWindow("cGDI+","Simple graphique avec GDI+",
    WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,880,800,0,0,hI,0);
  ShowWindow(hWnd,iCmdShow); UpdateWindow(hWnd);
  MSG m;
  while(GetMessage(&m,0,0,0)) {TranslateMessage(&m); DispatchMessage(&m);}
  GdiplusShutdown(gdiplusToken); return (int)m.wParam;
}

Sur la capture, on peut constater une amélioration de la qualité du rendu grâce à l'anticrénelage (anti-aliasing).
En contrepartie, le temps d'affichage est augmenté.

Si vous désirez une représentation sans les lignes de contour des polygones, supprimez toutes les instructions qui concernent la variable pen.

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
Essai direct: Eponge    Eponge évolution

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.