Anda di halaman 1dari 20

Ce document a été fabriqué par PDFmail (Copyright RTE Software)

http://www.pdfmail.com

Nordine GRASSA
N° 142862
nourdine@bocal.cs.univ-paris8.fr

Site: http://inferno.cs.univ-paris8.fr/~nourdine

GRAPHISME EN 3D SUR UNE SPHERE


MEMOIRE DE LICENCE

1
Ce document a été fabriqué par PDFmail (Copyright RTE Software)
http://www.pdfmail.com

Préface

Dans le cadre du cours de Monsieur Pierre AUDIBERT « ALGORITHME


Géométrique » pour la Licence on a appris à faire des formes géométriques sur
écran.
J’ai choisi la sphère comme sujet pour mon mémoire de fin de Licence.
En effet le sujet traite une sphère et le but c’est d’arriver a la fin a une forme
géométrique qui ressemble plus au moins a la terre.
Pour cela plusieurs étapes.
D’abords je vais traiter le cas d’une sphère avec ses méridiens.
Ensuite la sphère avec ombre et lumière.
Enfin je vais plaquer le Plasma sur la sphère pour qu’elle ressemble à la terre.
Remarque
Le Plasma c’est un programme qui produit un nuage de dégrader de couleurs par
interpolation bilinéaire.

Tous les programmes sont réalisés en langage C, j’utilise les librairies


graphiques de X11, c’est l’outil principal pour l’interface de Linux.

Je tiens à remercier Monsieur Pierre AUDIBERT pour les excellents cours qu’il
donne à l’université de Paris8.

2
Ce document a été fabriqué par PDFmail (Copyright RTE Software)
http://www.pdfmail.com

I- Sphère avec ses méridiens

Pour avoir une sphère il faut avant tout connaître son équation : x^2+y^2+z^2=1
C’est l’équation d’une sphère de centre O et de rayon R=1.
On a besoin entre autre de deux angles longitude et l’altitude.
Pour cela on nomme lamda l’angle désignant l’altitude, lamda varie de –pi/2 à
+pi/2.
Et on nomme phi l’angle désignant la longitude, phi varie de 0 à (2*pi).
Grâce à ces deux angles on va pouvoir dessiner les méridiens d’une sphère.
Un méridien est un demi grand cercle.

Tracé d’un méridien

On se donne donc un angle phi, on fait varier lamda de –pi/2 à pi/2 d’un
paslamda.
Paslamda=pi/ (le nombre d’intervalle –pi/2 à pi/2) ;
Disant Np= le nombre d’intervalle –pi/2 à pi/2 ;
Donc paslamda=pi/Np.

S=sud=-pi/2.
N=Nord=+pi/2.
Np=4 (le nombre d’intervalle).

3
Ce document a été fabriqué par PDFmail (Copyright RTE Software)
http://www.pdfmail.com

Voici maintenant le programme faisant les méridiens d’une sphère.


Le principe est simple deux grandes boucles l’une pour faire varier lamda
alors que l’autre pour faire varier phi.

/******GRASSA NORDINE N°142862************************/


#include <stdio.h>
#include <X11/Xlib.h>
#include<time.h>
#include<math.h>

#define pas 1
#define LL 300
#define zoom 50
#define R 3
#define M 19
#define N 20
#define NN 1000
#define pi 3.14159

int Palette[20];
GC gc;
Window win,root;
Display *dpy;
XEvent event;
XGCValues xgcv;
XSetWindowAttributes xswa;
Pixmap Affiche,Efface;
Colormap cmp;
XFontStruct *fd;
int pix[500][500];
float x,y,z;
int i,j;
long bg,fg;
int screen;
int k=0;
void Init_couleur()
{
XColor coul;

/* rouge */
coul.red=60000;
coul.green=0;
coul.blue=0;
XAllocColor(dpy,cmp,&coul);
Palette[0]=coul.pixel;

/* vert */
coul.red=0;
coul.green=60000;
coul.blue=0;

4
Ce document a été fabriqué par PDFmail (Copyright RTE Software)
http://www.pdfmail.com

XAllocColor(dpy,cmp,&coul);
Palette[1]=coul.pixel;

/* bleu */
coul.red=0;
coul.green=0;
coul.blue=60000;
XAllocColor(dpy,cmp,&coul);
Palette[2]=coul.pixel;
}

void sphere(){

float x0=200;
float y0=200;
double fi,lamda;
float alphadeg=30; //degres
double alpha=(pi/180)*alphadeg;//180
double tetap=atan(sin(alpha));
float cost=cos(tetap);
float sint=sin(tetap);
float oap=sqrt((1+sin(alpha)*sin(alpha))/2);
float obp=oap;
float ocp=cos(alpha);
float c;
float pasfi=(2*pi)/N;
float paslamda=pi/NN;
int xs[10],ys[10];
float d[10];
int oldxs[10];
int oldys[10];
fi=0;
for(i=0;i<N;i++)
{
lamda=-1.5707;
for(j=0;j<=NN;j++)
{
x=R*cos(lamda)*cos(fi);
y=R*cos(lamda)*sin(fi);
z=R*sin(lamda);
c=sqrt(2.)*tan(alpha);
lamda+=paslamda;
xs[k]=x0+(x-y)*zoom*oap*cost;
ys[k]=y0-(x+y)*zoom*oap*sint -zoom*ocp*z;//pt sur l'ecran
d[k]=x+y-c*z;

if(d[k]<0)
{
XSetForeground (dpy, gc,Palette[0]);
XDrawPoint (dpy, win, gc,xs[k], ys[k]);

5
Ce document a été fabriqué par PDFmail (Copyright RTE Software)
http://www.pdfmail.com

}
if(j>0)
XDrawLine (dpy, win, gc, oldxs[k], oldys[k],xs[k],ys[k]);
else
{
XSetForeground (dpy, gc,Palette[2]);
XDrawPoint (dpy, win, gc,xs[k], ys[k]);
}
oldxs[k]=xs[k];
oldys[k]=ys[k];
}
fi+=pasfi;
}
k++;
}

/*-----------------------------------------------*/
/* INITIALISATION DE X11 ET OUVERTURE DE FENETRE */
/*-----------------------------------------------*/

void ouvre_fenetre(int L,int H)


{
int i;
unsigned long white_pixel, black_pixel;
char *dpyn = NULL;
XSetWindowAttributes attrib;
XColor couleur;
if ((dpy = XOpenDisplay (dpyn)) == NULL) {
fprintf (stderr, "Can't open Display\n");
exit (1);
}

gc = DefaultGC (dpy, screen);


screen = DefaultScreen (dpy);
root = RootWindow (dpy, screen);
bg=WhitePixel (dpy, screen);
fg=BlackPixel (dpy, screen);
attrib.background_pixel= WhitePixel (dpy, screen);
attrib.border_pixel = BlackPixel (dpy, screen);
cmp=DefaultColormap(dpy,screen);

Affiche=XCreatePixmap(dpy,DefaultRootWindow(dpy),640,400,DefaultDepth(dpy,screen));

attrib.event_mask=ExposureMask|KeyPressMask|ButtonPressMask|ButtonReleaseMask|Point
erMotionMask;

6
Ce document a été fabriqué par PDFmail (Copyright RTE Software)
http://www.pdfmail.com

win=XCreateWindow(dpy,DefaultRootWindow(dpy),0,0,640,400,100,DefaultDepth(dpy,Def
aultScreen(dpy)),InputOutput,DefaultVisual(dpy,DefaultScreen(dpy)),CWEventMask|CWBac
kPixel|CWBorderPixel,&attrib);

XStoreName (dpy, win, "SPHERE");


XMapWindow (dpy, win);

XFlush( dpy);
while(1)
{
XNextEvent( dpy, &event);

switch( event.type )
{

case ButtonPress:
switch( event.xbutton.button)
{

// case Expose:
case Button1:
Init_couleur();
sphere();
break;
/* case Button2:
carre(20,20,300);
break;*/
case Button3:
XDestroyWindow(dpy,win);
XCloseDisplay(dpy);
return;
}
}
}
}

int main()
{
ouvre_fenetre(640,400);
return True;
}

Résultat :

7
Ce document a été fabriqué par PDFmail (Copyright RTE Software)
http://www.pdfmail.com

Maintenant qu’on sait dessiner une sphère avec ses méridiens on va essayer de
placer des points sur les méridiens formant des facettes qu’on va dessiner.
Pour cela on va numéroter les points de la sphère.
Si on se place dans le cas précèdent.
Exemple : Np=4
Le nombre de points sur un méridien est Np+1 donc 5 points.
Pour trouver le nombre total de points on multiplie 5*(le nombre de méri dien).
Ainsi Npp= (Np+1)*N avec N le nombre de méridien et Npp le nombre total de
points.
Maintenant il va falloir prendre les facettes pour chaque point.

Exemple :

8
Ce document a été fabriqué par PDFmail (Copyright RTE Software)
http://www.pdfmail.com

Le programme est quasiment de même que celui de dessus sauf qu’il faut
rajouter les donner qu’on vient de voir ainsi le programme devient :

void map(){
int numm, nump;
int N=50;
int Np=20;
int Npp=N*(Np+1);
float x0=200;
float y0=200;
//double fi,lamda;
float fi,lamda;
float alphadeg=30; //degres//30
double alpha=(pi/180)*alphadeg;//180
double tetap=atan(sin(alpha));
float cost=cos(tetap);
float sint=sin(tetap);
float oap=sqrt((1+sin(alpha)*sin(alpha))/2);
float obp=oap;
float ocp=cos(alpha);
float c;
float pasfi=(2*pi)/N;

float lamdaz=(pi/180)*5;//5
float paslamda=(pi-(2*lamdaz))/Np;
int xs[100000];
int ys[100000];
float d[100000];
int oldxs[100000];
int oldys[100000];
fi=0;
k=0;
for(i=0;i<N;i++)
{
lamda=((-pi)/2)+lamdaz;
for(j=0;j<Np+1;j++)

9
Ce document a été fabriqué par PDFmail (Copyright RTE Software)
http://www.pdfmail.com

{
x=R*cos(lamda)*cos(fi);
y=R*cos(lamda)*sin(fi);
z=R*sin(lamda);
c=sqrt(2.)*tan(alpha);

xs[k]=x0+(x-y)*zoom*oap*cost;
ys[k]=y0-(x+y)*zoom*oap*sint -(zoom*ocp*z);//pt sur l'ecran
d[k]=x+y-(c*z);
lamda+=paslamda;
k++;
}

fi+=pasfi;
}
XFlush(dpy);
XSetForeground(dpy, gc, Palette[1]);
XDrawString (dpy, win, gc, 8, 23, "Lancer", 6);

/*dessin des facettes*/

for(f=0;f<Npp;f++){

numm=f/(Np+1);
nump=f%(Np+1);
lamda=((-pi)/2)+lamdaz +paslamda*nump;
fi=pasfi*numm;
x=R*cos(lamda)*cos(fi);
y=R*cos(lamda)*sin(fi);
z=R*sin(lamda);
zcyl=tan(lamda);
//dessiner la facette
/*
XSetForeground (dpy, gc,Palette[2]);
XFillPolygon(dpy,win,gc,p,3,Nonconvex, CoordModeOrigin);
*/
/*enregistrer les facettes*/
if((f+1)%(Np+1) !=0)
{
if(d[f]<0)
{
p[0].x = xs[f];
p[0].y = ys[f];
p[1].x = xs[f+1];
p[1].y = ys[f+1];
p[2].x = xs[(f+Np+2)%Npp];
p[2].y = ys [(f+Np+2)%Npp];
p[3].x = xs[(f+Np+1)%Npp];
p[3].y = ys[(f+Np+1)%Npp];

10
Ce document a été fabriqué par PDFmail (Copyright RTE Software)
http://www.pdfmail.com

XSetForeground (dpy, gc,f);//pour la couleur


XDrawPoints(dpy, win, gc, p, 4, CoordModeOrigin) /* pour mettre les points en
place */
XFillPolygon(dpy,win,gc,p,4,Nonconvex, CoordModeOrigin);/*pour dessiner les
facettes avec la couleur donner*/
}
}

Résultat : sphère seulement avec les points ensuite avec facettes

11
Ce document a été fabriqué par PDFmail (Copyright RTE Software)
http://www.pdfmail.com

On peut faire mieux par exemple plaquer une image sur la sphère ou bien
transférer le Plasma sur la sphère.
On va traiter le deuxième cas.
Pour cela il nous faut le programme du Plasma.
Je vais faire un plasma en deux dimensions.
L’algorithme consiste à donner une valeur aléatoire aux quatre points extrêmes
d’un carré, et pour ces quatre points on calculera cinq nouveaux points qui
serviront à l’étape suivante puis ainsi de suite jusqu'à recouvrir toute la surface

On obtient donc :

12
Ce document a été fabriqué par PDFmail (Copyright RTE Software)
http://www.pdfmail.com

Code source :

#define L 512

float palette[1000000];
int c1,c2,c3,c4;

void la_palette()
{
int i;
int j;

int r=0;
int v=0;
int b=65535;

cmp = DefaultColormap(dpy,screen);

for(i=0;i<85;i++)
{

b-=768;
v+=768;

x_colors.red=r;
x_colors.green=v;
x_colors.blue=b;
XAllocColor(dpy,cmp,&x_colors);

13
Ce document a été fabriqué par PDFmail (Copyright RTE Software)
http://www.pdfmail.com

palette[j]=x_colors.pixel;
j++;
}

v=65535;

for(i=85;i<170;i++)
{
v-=768;
r+=768;

x_colors.red=r;
x_colors.green=v;
x_colors.blue=b;
XAllocColor(dpy,cmp,&x_colors);
palette[j]=x_colors.pixel;
j++;
}

b=0;
v=0;
r=65535;

for(i=170;i<256;i++)
{

r-=768;
b+=768;

x_colors.red=r;
x_colors.green=v;
x_colors.blue=b;
XAllocColor(dpy,cmp,&x_colors);
palette[j]=x_colors.pixel;
j++;
}

void affichepoint()
{
int i;
int j;

for(i=0;i<L;i++)
for(j=0;j<L;j++)
{

14
Ce document a été fabriqué par PDFmail (Copyright RTE Software)
http://www.pdfmail.com

XSetForeground(dpy,gc,pix[i][j]);
XDrawPoint(dpy,win,gc,i,j);
}
}

void affiche_palette()
{
int i;
int j;

for(i=0;i<L;i++)
for(j=0;j<L;j++)

{
XSetForeground(dpy,gc,palette[i]);
XDrawPoint(dpy,win,gc,i,j);
}
}

void carre(int x,int y,int l)


{
int cc,cm1,cm2,cm3,cm4;

if(l>1)
{

cc=(pix[x][y]+pix[x+l][y]+pix[x+l][y+l]+pix[x][y+l])/4;
cc=cc-l+rand()%(2*l);
if(cc>255)cc=cc%256;
if(cc<0)cc=cc+256;
if(pix[x+l/2][y+l/2] == 256)
pix[x+l/2][y+l/2] = cc;

cm1=(pix[x][y]+pix[x+l][y])/2;
cm1=cm1-l+rand()%(2*l);
if(cm1>255)cm1=cm1%256;
if(cm1<0)cm1=cm1+256;
if(pix[x+l/2][y] == 256)
pix[x+l/2][y] = cm1;

cm2=(pix[x][y]+pix[x][y+l])/2;
cm2=cm2-l+rand()%(2*l);
if(cm2>255)cm2=cm2%256;
if(cm2<0)cm2=cm2+256;
if(pix[x][y+l/2] == 256)

15
Ce document a été fabriqué par PDFmail (Copyright RTE Software)
http://www.pdfmail.com

pix[x][y+l/2] = cm2;

cm3=(pix[x+l][y]+pix[x+l][y+l])/2;
cm3=cm3-l+rand()%(2*l);
if(cm3>255)cm3=cm3%256;
if(cm3<0)cm3=cm3+256;
if(pix[x+l][y+l/2] == 256)
pix[x+l][y+l/2] = cm3;

cm4=(pix[x][y+l]+pix[x+l][y+l])/2;
cm4=cm4-l+rand()%(2*l);
if(cm4>255)cm4=cm4%256;
if(cm4<0)cm4=cm4+256;
if(pix[x+l/2][y+l] == 256)
pix[x+l/2][y+l] = cm4;

carre(x,y,l/2);
carre(x+(l/2),y,l/2);
carre(x+(l/2),y+(l/2),l/2);
carre(x,y+(l/2),l/2);
}
}

void plasma(){

//int c1,c2,c3,c4;

int x0=2 ;
int y0=2 ;
int x1=x0+LL;
int y1=y0;
int x2=x0+LL;
int y2=y0+LL;
int x3=x0;
int y3=y0+LL;
int i,j;

for(i=0;i<L;i++)
for(j=0;j<L;j++)
pix[i][j] =256;

// la_palette();
//affichepoint();
srand(getpid());

c1=rand()%256;

16
Ce document a été fabriqué par PDFmail (Copyright RTE Software)
http://www.pdfmail.com

c2=rand()%256;
c3=rand()%256;
c4=rand()%256;

pix[x0][y0] = c1;
pix[x1][y1] = c2;
pix[x2][y2] = c3;
pix[x3][y3] = c4;

//printf("\n c1 =====>%d ",c1);

carre(x0,y0,LL);
}

La dernière étape consiste à plaquer le Plasma sur la sphère.


Principe
On va prendre un pixel du plasma on le transfère sur un cylindre qui enveloppe
la sphère comme ça on gardera la même couleur, on répète cela pour tout les
pixels on aura a la fin la sphère avec le plasma.

Toujours le même programme vous verrez les changements en rouge :


#include "plasma_final.h"

void mapplasma(){
int numm, nump;
float lamdaz=(pi/180)*5;
int N=380;
int Np=262;
int Npp=N*(Np+1);
float x0= 200;
float y0= 200;
float fi,lamda;
float alphadeg=30; //degres
double alpha=(pi/180)*alphadeg;//180
double tetap=atan(sin(alpha));
float cost=cos(tetap);
float sint=sin(tetap);
float oap=sqrt((1+sin(alpha)*sin(alpha))/2);

float ocp=cos(alpha);
float c=sqrt(2.)*tan(alpha);
float pasfi=(2*pi)/N;
float paslamda=(pi-(2*lamdaz))/Np;

17
Ce document a été fabriqué par PDFmail (Copyright RTE Software)
http://www.pdfmail.com

unsigned int xs[100000];


unsigned int ys[100000];
float d[100000];

fi=0;
k=0;
for(i=0;i<N;i++)
{
lamda=-1.5707+lamdaz;
for(j=0;j<=Np;j++)
{
x=R*cos(lamda)*cos(fi);
y=R*cos(lamda)*sin(fi);
z=R*sin(lamda);
xs[k]=x0+(x-y)*zoom*oap*cost;
ys[k]=y0-(x+y)*zoom*oap*sint -(zoom*ocp*z);//pt sur l'ecran
d[k]=x+y-(c*z);
lamda+=paslamda;
k++;
}

fi+=pasfi;

}
/*----------point k-------------------*/

for(k=0;k<Npp;k++)
{
numm=k/(Np+1);
nump=k%(Np+1);
fi=pasfi*numm;
lamda=((-pi)/2)+lamdaz + paslamda*nump;
x=R*cos(lamda)*cos(fi);
y=R*cos(lamda)*sin(fi);
z=R*sin(lamda);
/*------------chercher la couleur-----------*/
z_cylindre=tan(lamda);
zoom_h =LL/(2*pi);
zoom_v =LL/(2*tan((pi/2)-lamdaz));
xe=zoom_h*fi;
ye=zoom_v*z_cylindre;
couleur[k]=pix[xe][ye];
if((k+1)%(Np+1) !=0 && d[k]<0){

p[0].x = xs[k];
p[0].y = ys[k];
p[1].x = xs[k+1];
p[1].y = ys[k+1];

18
Ce document a été fabriqué par PDFmail (Copyright RTE Software)
http://www.pdfmail.com

p[2].x = xs[(k+Np+2)%Npp];
p[2].y = ys [(k+Np+2)%Npp];
p[3].x = xs[(k+Np+1)%Npp];
p[3].y = ys[(k+Np+1)%Npp];

XSetForeground (dpy, gc,couleur[k]);


//XDrawPoints(dpy,win,gc,p,4,0);
XFillPolygon(dpy,win,gc,p,4,0,0);

}
}

Et voici la sphère avec le plasma :

19
Ce document a été fabriqué par PDFmail (Copyright RTE Software)
http://www.pdfmail.com

20