컴퓨터 그래픽스 레포트



총 5가지 도형의 구현코드입니다.


-Bezier Spline

-Hermite Spline

-Koch Curve

-Sierpimsk Gasket

-Mamdel Brot


최근에 다큐멘터리에서 Mamdel Brot에 대한 내용을 보았는데 새삼 10여년 전에 저런 코드를 한번 구현해 봤다는게 신기하네요^^

지금보니 소스코드가 뭔 소린지 모르겠네요 ㅎㅎㅎ

어쩌자고 저렇게 구현했는지 ㅋㅋ


혹시 필요하신 분들께서는 그냥 참고 정도만 하세요~

위 5가지 예제의 결과물은 아래와 같아요


-Bezier Spline

-Hermite Spline


-Koch Curve




-Sierpimsk Gasket



-Mamdel Brot





소스코드입니다.


#include <gl\glut.h>

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#include <conio.h>


#define CNT 100 // u size

#define SIZE 500 // image size

#define TRUE 1

#define FALSE 0

#define BUFFER 100 // file name size

#define MASK_BIT 12   // Masking

#define NPOINT 4 // no. of point

#define EXIT 6 // Program Exit

#define STEP 7 // Koch Curve step

#define M_P 100000

#define ROUND(a) (int)(a+0.5)

#define MAX_COLOR 256



#define H1(u) (2*(u*u*u)-3*(u*u)+1)  // 배합함수

#define H2(u) (-2*(u*u*u)+3*(u*u))

#define H3(u) ((u*u*u)-2*(u*u)+u)

#define H4(u) ((u*u*u)-(u*u))



typedef struct _wcPt3 {

double x, y, z;

}wcPt3;


typedef struct _Complex

float x;

float y;

}Complex; 


typedef struct _RGB{

unsigned char R[MAX_COLOR],G[MAX_COLOR],B[MAX_COLOR];

}RGB;


////////////////////////////////////////////////////////

/* Global Variable List */


//Image Canvas Size

unsigned char Image[SIZE][SIZE][3];


/* Bezier Function */

wcPt3 initPt[NPOINT] = {{100.0, 150.0, 0.0}, {250.0, 120.0, 0.0}, 

{80.0, 90.0, 0.0}, {60.0, 120.0, 0.0}};

wcPt3 Curve[CNT];


/* Hermite Function */ 

void hermit();


/* Koch Curve */

wcPt3 temp[M_P];

wcPt3 koch_point[M_P] = {{0.3, 0.1, 0.0}, {0.3, 0.9, 0.0}, 

{0.9, 0.5, 0.0}, {0.3, 0.1, 0.0}};


/* Sierpimsk Gasket */

int Triangle[3][2] = {499, 0, 499, 499, 0, 250};


/* Mamdelbrot */

RGB color;

unsigned char R;

unsigned char G;

unsigned char B;


////////////////////////////////////////////////////////

/* Function List */

int Select_menu(); // select menu 

int WriteToImagePixel(); // Write Image to File

int lineDDA(int xa, int ya, int xb, int yb, char flagMask); // Draw Line 

void DrawLineMask(); // Draw Masked Line

void initImage(); // Image BgColor set


/* Bezier Function */

void Processing_Bezier(void); // Bezier Spline

void computeCoefficients(int n, int *c); // Factorial Calc

void computePoint(float u, wcPt3 *pt, int nControls, wcPt3 *controls, int *c);

void bezier(wcPt3 *controls, int nControls, int m, wcPt3 *curve);


/* Herimte Function */

void Processing_Hermite();


/* Koch Curve */

void Processing_Koch_Curve();

long koch_curve();


/* Sierpimsk Gasket */

void Processing_Sierpimsk_Gasket();

void sierpimsk_gasket();


/* Mamdelbrot */

void Processing_Mamdelbrot();

void mamdelbrot();

Complex complexSquare( Complex c);

int iterate(Complex z, int Iter);

void setColor(int color);

void setPixel(int x, int y);


///////////////////////////////////////////////////////

/* Start Main Proc */

int main(int argc, char **argv)

{

int select;

select = Select_menu();


while(select!=EXIT) {

switch(select) {

case 1:

Processing_Bezier();

break;

case 2:

Processing_Hermite();

break;

case 3:

Processing_Koch_Curve();

break;

case 4:

Processing_Sierpimsk_Gasket();

break;

case 5:

Processing_Mamdelbrot();

break;

case 6:

break;

default :

exit(1);

}


getch();

system("cls");

select = Select_menu();

}


return 0;

}


int Select_menu()

{

int select;


printf("1. Bezier Spline \n");

printf("2. Hermite Spline \n");

printf("3. Koch Curve \n");

printf("4. Sierpimsk Gasket \n");

printf("5. Mamdel Brot \n");

printf("6. EXIT\n");


scanf("%d",&select);


return select;

}



/* Write image to file */

int WriteToImagePixel()

{

FILE *fp; // file pointer

char name[BUFFER]; // buffer

int j,k; // loop index

printf("Insert File Name : ");

scanf("%s",name);


fp = fopen(name,"wb");

printf("Name : %s\n",name);

if(fp==NULL) { printf("File open failed!!!\n"); return FALSE; }


fprintf(fp,"P6\n");

fprintf(fp,"%d %d\n",SIZE,SIZE);

fprintf(fp,"%d\n",255);

for(j=0; j<SIZE; j++) {

for(k=0; k<SIZE; k++) {

putc((unsigned char)Image[j][k][0],fp);

putc((unsigned char)Image[j][k][1],fp);

putc((unsigned char)Image[j][k][2],fp);

}

}

fclose(fp);

return TRUE;

}


/* Line to init Points */

void DrawLineMask()

{

int i;

for(i=0; i<NPOINT-1; i++)

lineDDA(initPt[i].x,initPt[i].y,initPt[i+1].x,initPt[i+1].y,TRUE);

}


/* Init Image Background color to white */

void initImage()

{

int i,j;

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

for(j=0; j<SIZE; j++) {

Image[i][j][0] = 255;

Image[i][j][1] = 255;

Image[i][j][2] = 255;

}

}

}


/* Draw Line */

int lineDDA(int xa, int ya, int xb, int yb, char flagMask)

{

int dx = xb - xa;

int dy = yb - ya;

int step, k, cnt;

float xIncrement, yIncrement, x = (float)xa, y = (float)ya;

int mask[MASK_BIT] = {0,0,0,1,1,1,0,0,0,1,1,1};


if( abs(dx) > abs(dy) )

step = abs(dx);

else

step = abs(dy);

xIncrement = dx / (float) step;

yIncrement = dy / (float) step;


for(k=0; k<step; k++) {

cnt = k % MASK_BIT;

x += xIncrement;

y += yIncrement;


int width_pos = abs((int)x);

int height_pos = abs((int)y);

if(flagMask==TRUE) {

if(mask[cnt]==1)

Image[height_pos][width_pos][0] = 0;

Image[height_pos][width_pos][1] = 0;

Image[height_pos][width_pos][2] = 0;

}


else if (flagMask==FALSE)

Image[height_pos][width_pos][0] = 0;

Image[height_pos][width_pos][1] = 0;

Image[height_pos][width_pos][2] = 0;

}


return TRUE;

}



void computeCoefficients(int n, int *c) {

int k, i;


for(k = 0 ; k <= n ; k++ ) {

c[k] = 1;

for(i = n ; i >=k+1; i--)

c[k] *= i;

for(i = n-k ; i >= 2; i--)

c[k] /= i;

}

}


void computePoint(float u, wcPt3 *pt, int nControls, wcPt3 *controls, int *c) {

int k, n = nControls -1;

float blend;


pt->x = 0.0 ; pt->y = 0.0; pt->z = 0.0;


for(k = 0 ; k <nControls ; k++) {

blend = c[k] * powf(u, k) * powf(1-u, n-k);

pt->x += controls[k].x * blend;

pt->y += controls[k].y * blend;

pt->z += controls[k].z * blend;

}

}


/* Bezier Function */

void bezier(wcPt3 *controls, int nControls, int m, wcPt3 *curve) {

int *c = (int *)malloc(nControls * sizeof(int));

int i;


computeCoefficients(nControls -1, c);

for( i = 0 ; i <= m ; i++ ) 

computePoint(i / (float)m, &curve[i], nControls, controls, c);

free(c);

}


void Processing_Bezier(void)

{

/* init image background color */

initImage();


/* Draw Mask Line */

DrawLineMask();


/* make points no. of CNT */

bezier(initPt, NPOINT, CNT, Curve);


/* Draw Line to Points */

for(int i=0; i<CNT-1; i++)

lineDDA((int)Curve[i].x,(int)Curve[i].y,(int)Curve[i+1].x,(int)Curve[i+1].y,FALSE);

/* image write to file */

WriteToImagePixel();

printf("Processing Bezier Success \n");

}



void Processing_Hermite()

{

/* init image background color */

initImage();


/* Draw Mask Line */

DrawLineMask();


/* make points no. of CNT */

hermit();


/* image write to file */

WriteToImagePixel();

printf("Processing Hermite Success \n");


}


void hermit()

{

int xa=220,ya=40,xb=80,yb=150,xv=20,yv=-33,xv1=-4,yv1=50;

float f;

int i = 0;

int x, y, x_1, y_1;

int n = 200;


x_1 = x = xa;

y_1 = y = ya;


while(i <= n){

f = (float)(i / n);

x = (int)(H1(f) * xa + H2(f) * xb + H3(f) * xv1 + H4(f) * xv1);

y = (int)(H1(f) * ya + H2(f) * yb + H3(f) * yv1 + H4(f) * yv1);

lineDDA(x_1, y_1, x, y,FALSE);

x_1 = x;

y_1 = y;

i++;

}

}


long koch_curve()

{

int i,step;

long tp = NPOINT;


for(step = 0; step < STEP; step++)

{

tp += (tp-1) * 3;

if (tp > M_P) break;


for(i =0; i < tp; i+=4)

{

temp[i].x = koch_point[i/4].x;

temp[i].y = koch_point[i/4].y;

}


for(i = 0; i < tp; i++)

{

if( (i%4) == 1)

{

temp[i].x = temp[i-1].x + (temp[i+3].x - temp[i-1].x) / 3;

temp[i].y = temp[i-1].y + (temp[i+3].y - temp[i-1].y) / 3;


temp[i+2].x = temp[i+3].x - (temp[i+3].x - temp[i-1].x) / 3;

temp[i+2].y = temp[i+3].y - (temp[i+3].y - temp[i-1].y) / 3;

}

else if( (i%4) == 2)

{

temp[i].x = temp[i-1].x/2 + temp[i+1].x/2 + sqrt(3)/2*temp[i-1].y - sqrt(3)/2*temp[i+1].y;

temp[i].y = temp[i-1].y/2 + temp[i+1].y/2 - sqrt(3)/2*temp[i-1].x + sqrt(3)/2*temp[i+1].x;

}

}

for(i = 0 ; i < tp; i++)

{

koch_point[i].x = temp[i].x;

koch_point[i].y = temp[i].y;

}

}

return tp;

}


void Processing_Koch_Curve()

{

/* init image background color */

initImage();


/* make points no. of CNT */

long cnt = koch_curve();


/* Draw Koch Curve */

for(int i = 0; i < cnt - 1 ; i++)

lineDDA((int)(koch_point[i].x*(SIZE-1)+.5),(int)(koch_point[i].y*(SIZE-1)+0.5),

(int)(koch_point[i+1].x*(SIZE-1)+0.5),(int)(koch_point[i+1].y*(SIZE-1)+0.5), FALSE);


/* image write to file */

WriteToImagePixel();

printf("Processing Koch Curve Success \n");


}


void sierpimsk_gasket()

{

int i,j;

int cx, cy, px, py;


for(i = 0 ; i < 3; i++)

Image[Triangle[i][0]][Triangle[i][1]][0] = 0;

Image[Triangle[i][0]][Triangle[i][1]][1] = 0;

Image[Triangle[i][0]][Triangle[i][1]][2] = 0;

px = Triangle[0][0];

py = Triangle[0][1];


for(i = 0; i < M_P ; i++)

{

j = rand() % 3;


cx = (int)((double)(px+Triangle[j][0])/2.0 + 0.5);

cy = (int)((double)(py+Triangle[j][1])/2.0 + 0.5);


Image[cx][cy][0] = 0;

Image[cx][cy][1] = 0;

Image[cx][cy][2] = 0;

px = cx;

py = cy;

}

}


void Processing_Sierpimsk_Gasket()

{

/* init image background color */

initImage();

/* make points no. of CNT */

sierpimsk_gasket();


/* image write to file */

WriteToImagePixel();

printf("Processing Sierpimsk Gasket Success \n");

}


Complex complexSquare( Complex c)

{

Complex newz;


newz.x = c.x * c.x - c.y * c.y;

newz.y = 2 * c.x * c.y;


return (newz);

}


int iterate(Complex z, int Iter)

{

int cnt = 0;

Complex c = z;


while(( c.x * c.x + c.y * c.y <= 4. ) && (cnt < Iter))

{

c = complexSquare(c);

c.x += z.x;

c.y += z.y;

cnt++;

}

return (cnt);

}


void GetRandomColor()

{

for(int i = 0; i < 256; i++)

{

color.R[i] = rand() % 256;

color.G[i] = i;

color.B[i] = rand() % 256;

}

}


void mamdelbrot()

{

int x,y,cnt;

Complex z;

float realMax = 0.25, realMin = -0.75, imagMax = 2.1, imagMin = -1.0;


float realInc=(realMax-realMin) / (SIZE*4.5);

float imagInc=(imagMax-imagMin) / (SIZE*4.5);


for( x = 0, z.x = realMin; x < SIZE; x++, z.x += realInc)

{

for(y=0, z.y = imagMin; y < SIZE; y++, z.y+=imagInc)

{

cnt = iterate(z,100);

if ( cnt == 100)

setColor(255);

else

{

for (int i = 0 ; i < cnt ; i++ )

setColor(i);

}

setPixel(x, y);

}

}

}


void setColor(int index)

{

R = color.R[index];

G = color.G[index];

B = color.B[index];

}


void setPixel(int x, int y)

{

Image[x][y][0] = R;

Image[x][y][1] = G;

Image[x][y][2] = B;

}


void Processing_Mamdelbrot()

{

/* init image background color */

initImage();


/* Get Color */

GetRandomColor();


/* Processing mamdelbrot */ 

mamdelbrot();


/* image write to file */

WriteToImagePixel();

printf("Processing MamdelBrot Success \n");

}



////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////