Графика
Фрактал (листья папоротника)
» Кликните сюда для просмотра оффтоп текста.. «
Код
//////////////////////////////////////////////////////////////////////////////
//
// Leafs drawing
// (c) Johna Smith, 1996
//
// Method description:
// We take a closed area, which will be main leaf. We want to generate
// four fractal leafs from this one. To make it we need to scale, move and
// rotate main leaf. These transformations described by the following
// equations:
// x'=ax+by+c, y'=dx+ey+f
// So we need 6 coefficients for each leaf (24 coefficients at all).
// These coefficients are calculated with special mathematical method
// (here are already calculated coefficients)
// To draw whole picture we need an iterational process:
// 1) Take any point within main leaf borders
// 2) Call function iterate for one of 4 leafs (its nuber we select
// randomly but than the larger is leaf's area the higher is probability
// that we call 'iterate' for this leaf
// 3) Then we take transformed point as (x,y) and repeat iterations
//
// ! This program is NOT optimized for best performance !
// To do so don't use putpixel function - change bytes in video memory directly.
//
//////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <graphics.h>
#include <conio.h>
// this function initializes graphics mode
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void init_gr(void)
{
/* request autodetection */
int gdriver = DETECT, gmode, errorcode;
/* initialize graphics mode */
initgraph(&gdriver, &gmode, "");
/* read result of initialization */
errorcode = graphresult();
if (errorcode != grOk) /* an error occurred */
{
printf("Graphics error: %s\n", grapherrormsg(errorcode));
printf("Press any key to halt:");
getch();
exit(1); /* return with error code */
}
}
// this function shuts graphics mode down
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void end_gr(void)
{
closegraph();
}
// this function puts pixel on the screen in (x,y) position using color 'color'
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void PutPixel(int x, int y, int color)
{
putpixel(x,y,color);
}
#define N 200000L // number of points
float x=0, y=0; // iteration variables (are global)
// a b c d e f probability
float coeff[4][6] = {{ 0.00, 0.00, 0.00,0.16,0.00,0.00,}, // 01%
{ 0.85, 0.04,-0.04,0.85,0.00,1.60,}, // 85%
{ 0.05,-0.26, 0.23,0.22,0.00,1.60,}, // 07%
{-0.15, 0.30, 0.26,0.24,0.00,0.44,},}; // 07%
int colors[5]={10,11,2,3,2};
void iterate(char i,int c)
{
float x1,y1;
x1=x*coeff[i][0]+y*coeff[i][1]+coeff[i][4];
y1=x*coeff[i][2]+y*coeff[i][3]+coeff[i][5];
x=x1;
y=y1;
putpixel ((int)(y*64),240-(int)(x*48),c);
}
int main (void)
{
int leaf,color;
// initializing graphics mode
init_gr();
// drawing leafs
for (long int i=0;i<N;i++)
{
color=colors[random(5)]; // random color
leaf=random(1000); // selecting leaf to draw
if (leaf<=10) iterate(0,color);
else if (leaf<=860) iterate(1,color);
else if (leaf<=930) iterate(2,color);
else iterate(3,color);
}
/* clean up */
getch();
end_gr();
return 0;
}
Рисование линии (по Брезенхэму)
» Кликните сюда для просмотра оффтоп текста.. «
Код
//////////////////////////////////////////////////////////////////////////////
//
// Bresengham line drawing
// (c) Johna Smith, 1996
//
// Method description:
// Determine dy=(y2-y1), dx=(x2-x1)
// We plot first point of the line and increase errors of plotting
// (xerr and yerr) by dx and dy respectively. If the error is greater
// than largest from dx and dy then we should correct next point and
// shift it to 1 pixel by that axe where error was too big.
//
// ! This program is NOT optimized for best performance !
// To do so don't use putpixel function - change bytes in video memory directly.
//
//////////////////////////////////////////////////////////////////////////////
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
// this function initializes graphics mode
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void init_gr(void)
{
/* request autodetection */
int gdriver = DETECT, gmode, errorcode;
/* initialize graphics mode */
initgraph(&gdriver, &gmode, "");
/* read result of initialization */
errorcode = graphresult();
if (errorcode != grOk) /* an error occurred */
{
printf("Graphics error: %s\n", grapherrormsg(errorcode));
printf("Press any key to halt:");
getch();
exit(1); /* return with error code */
}
}
// this function shuts graphics mode down
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void end_gr(void)
{
closegraph();
}
// this function puts pixel on the screen in (x,y) position using color 'color'
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void PutPixel(int x, int y, int color)
{
putpixel(x,y,color);
}
void BLine(int x1,int y1,int x2, int y2, int color)
{
int delta_x,delta_y,incx,incy,t,distance;
int xerr=0,yerr=0;
// determine dx and dy
delta_x=x2-x1;
delta_y=y2-y1;
// determine steps by x and y axes (it will be +1 if we move in forward
// direction and -1 if we move in backward direction
if (delta_x>0) incx=1;
else if (delta_x==0) incx=0;
else incx=-1;
if (delta_y>0) incy=1;
else if (delta_y==0) incy=0;
else incy=-1;
delta_x=abs(delta_x);
delta_y=abs(delta_y);
// select largest from deltas and use it as a main distance
if (delta_x>delta_y) distance=delta_x;
else distance=delta_y;
for (t=0;t<=distance+1;t++)
{
PutPixel(x1,y1,color);
// increasing error
xerr+=delta_x;
yerr+=delta_y;
// if error is too big then we should decrease it by changing
// coordinates of the next plotting point to make it closer
// to the true line
if(xerr>distance)
{
xerr-=distance;
x1+=incx;
}
if (yerr>distance)
{
yerr-=distance;
y1+=incy;
}
}
}
int main(void)
{
// initializing graphics mode
init_gr();
/* examples */
BLine(0, 0, 640, 480,15);
BLine(320, 0, 320, 480,10);
BLine(0, 240, 640, 240,11);
BLine(0, 480, 640, 0,12);
BLine(320, 11, 10, 5,13);
BLine(320, 11, 630, 5,13);
/* clean up */
getch();
end_gr();
return 0;
}
Рисование окружности (по Брезенхэму)
» Кликните сюда для просмотра оффтоп текста.. «
Код
//////////////////////////////////////////////////////////////////////////////
//
// Bresengham circle drawing
// (c) Johna Smith, 1996
//
// Method description:
// In this algorithm all floating point math changed to sequences
// of additions and substractions. The main idea of this algorithm
// is to increase x and y by the value of the error between them.
//
// ! This program is NOT optimized for best performance !
// To do so don't use putpixel function - change bytes in video memory directly.
//
//////////////////////////////////////////////////////////////////////////////
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
// this function initializes graphics mode
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void init_gr(void)
{
/* request autodetection */
int gdriver = DETECT, gmode, errorcode;
/* initialize graphics mode */
initgraph(&gdriver, &gmode, "");
/* read result of initialization */
errorcode = graphresult();
if (errorcode != grOk) /* an error occurred */
{
printf("Graphics error: %s\n", grapherrormsg(errorcode));
printf("Press any key to halt:");
getch();
exit(1); /* return with error code */
}
}
// this function shuts graphics mode down
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void end_gr(void)
{
closegraph();
}
// this function puts pixel on the screen in (x,y) position using color 'color'
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void PutPixel(int x, int y, int color)
{
putpixel(x,y,color);
}
float const ratio=1.0; // you can change this to draw ellipses
// This function plots points that belongs to the circle
// It recieves offsets from center for the fist quadrant
// and plots symmetrical points in all four quadrants
void plot_circle(int x,int y, int x_center, int y_center, int color)
{
int x_start,y_start,x_end,y_end,x1,y1;
// the distanse between start and end can be greater than 1 if ratio!=1
y_start=y*ratio;
y_end=(y+1)*ratio;
x_start=x*ratio;
x_end=(x+1)*ratio;
for (x1=x_start;x1<x_end;++x1)
{
// plot points in all four quadrants
PutPixel(x1+x_center,y+y_center,color);
PutPixel(x1+x_center,y_center-y,color);
PutPixel(x_center-x1,y+y_center,color);
PutPixel(x_center-x1,y_center-y,color);
}
for (y1=y_start;y1<y_end;++y1)
{
// plot points in all four quadrants
PutPixel(y1+x_center,x+y_center,color);
PutPixel(y1+x_center,y_center-x,color);
PutPixel(x_center-y1,x+y_center,color);
PutPixel(x_center-y1,y_center-x,color);
}
}
// This is main function that draws circle using function
void Circle(int x1,int y1,int radius, int color)
{
int x,y,delta;
// Y * we start from * and increase x step by step
// | decreasing y when needed
// |
// |
// --------------------
// | X
// |
// |
// |
y=radius;
delta=3-2*radius; // delta is an error
// calculate values for first quadrant
for (x=0;x<y;x++) // x is a main axe
{
// plot points symmetrically in all quadrants
plot_circle(x,y,x1,y1,color);
if (delta<0) delta+=4*x+6;
else
{
delta+=4*(x-y)+10;
y--; // it's time to decrease y
}
}
x=y;
if (y!=0) plot_circle(x,y,x1,y1,color);
}
int main(void)
{
// initializing graphics mode
init_gr();
/* examples */
Circle(200,200,100,14);
Circle(300,200,100,15);
Circle(400,200,100,13);
Circle(250,100,100,12);
Circle(350,100,100,11);
Circle(50,400,25,2);
Circle(500,400,25,2);
/* clean up */
getch();
end_gr();
return 0;
}
Сглаживание кривой В-сплайном
» Кликните сюда для просмотра оффтоп текста.. «
Код
//////////////////////////////////////////////////////////////////////////////
//
// Curve fitting using B-splines
// (c) Johna Smith, 1996
//
// Method description:
// We are drawing lines between points using the following formulas:
// x(t)=((a3*t+a2)*t+a1)*t+a0
// y(t)=((b3*t+b2)*t+b1)*t+b0
// t=0..1
// Look program for formulas for coefficients ai,bi
// These coefficients depends on coordinates of current point,
// previous one, next and next-next ones.
//
//////////////////////////////////////////////////////////////////////////////
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
// this function initializes graphics mode
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void init_gr(void)
{
/* request autodetection */
int gdriver = DETECT, gmode, errorcode;
/* initialize graphics mode */
initgraph(&gdriver, &gmode, "");
/* read result of initialization */
errorcode = graphresult();
if (errorcode != grOk) /* an error occurred */
{
printf("Graphics error: %s\n", grapherrormsg(errorcode));
printf("Press any key to halt:");
getch();
exit(1); /* return with error code */
}
}
// this function shuts graphics mode down
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void end_gr(void)
{
closegraph();
}
// this function moves CP to (x,y) position
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void MoveTo(int x, int y)
{
moveto(x,y);
}
// this function draws a line to (x,y) position
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void LineTo(int x, int y)
{
lineto(x,y);
}
// this function draws a line from (x1,y1) to (x2,y2)
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void Line(int x1, int y1, int x2, int y2)
{
line(x1,y1,x2,y2);
}
const N=21; // number of points
const M=300.0; // number of steps between two points
// coordinates of all given points
int x[N]={50,25,50,125,200,225,275,475,590,615,615,615,600,475,275,225,200,125,50,25
,50};
int y[N]={140,100,60,40,70,90,85,75,80,85,100,115,120,125,115,110,130,160,140,100,60
};
// coefficients
float t,xA,xB,xC,xD,yA,yB,yC,yD,a0,a1,a2,a3,b0,b1,b2,b3;
int n,i,j,first;
int main(void)
{
// initializing graphics mode
init_gr();
/* mark the given points */
for (i=0;i<N;i++)
{
Line(x[i]-4,y[i]-4,x[i]+4,y[i]+4);
Line(x[i]+4,y[i]-4,x[i]-4,y[i]+4);
}
/* main loop */
first=1;
for(i=1;i<N-2;i++)
{
// calculating coefficients
xA=x[i-1]; xB=x[i]; xC=x[i+1]; xD=x[i+2];
yA=y[i-1]; yB=y[i]; yC=y[i+1]; yD=y[i+2];
a3=(-xA+3*(xB-xC)+xD)/6.0; b3=(-yA+3*(yB-yC)+yD)/6.0;
a2=(xA-2*xB+xC)/2.0; b2=(yA-2*yB+yC)/2.0;
a1=(xC-xA)/2.0; b1=(yC-yA)/2.0;
a0=(xA+4*xB+xC)/6.0; b0=(yA+4*yB+yC)/6.0;
for (j=0;j<M;j++) // drawing curve between two given points
{
t=(float)j/(float)M;
if (first)
{
first=0;
MoveTo(((a3*t+a2)*t+a1)*t+a0,((b3*t+b2)*t+b1)*t+b0);
} else LineTo(((a3*t+a2)*t+a1)*t+a0,((b3*t+b2)*t+b1)*t+b0);
}
}
/* clean up */
getch();
end_gr();
return 0;
}
Рисование куба
» Кликните сюда для просмотра оффтоп текста.. «
Код
//////////////////////////////////////////////////////////////////////////////
//
// Generating and drawing cube
// (c) Johna Smith, 1996
//
// Method description:
// Cube is one of simplest figures in stereometry.
// We just need to generate 'n' squares parallel to X,Y and Z axes
//
//////////////////////////////////////////////////////////////////////////////
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <dos.h>
#define Pi 3.1415926536
enum Action{move,draw};
struct Point3D
{
int x;
int y;
int z;
Action action;
};
// this function initializes graphics mode
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void init_gr(void)
{
/* request autodetection */
int gdriver = DETECT, gmode, errorcode;
/* initialize graphics mode */
initgraph(&gdriver, &gmode, "");
/* read result of initialization */
errorcode = graphresult();
if (errorcode != grOk) /* an error occurred */
{
printf("Graphics error: %s\n", grapherrormsg(errorcode));
printf("Press any key to halt:");
getch();
exit(1); /* return with error code */
}
}
// this function shuts graphics mode down
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void end_gr(void)
{
closegraph();
}
// this function moves CP to (x,y) position
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void MoveTo(int x, int y)
{
moveto(x,y);
}
// this function draws a line to (x,y) position
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void LineTo(int x, int y)
{
lineto(x,y);
}
void draw3Dobject(Point3D *object, int N, float rho, float theta,
float phi, float dist_to_screen, int xshift, int yshift)
{
int x,y;
float xe,ye,ze,costh,sinph,cosph,sinth,v11,v12,v13,v21,v22,v32,v33,v23,v43;
// calculating coefficients
costh=cos(theta);
sinth=sin(theta);
cosph=cos(phi);
sinph=sin(phi);
v11=-sinth; v12=-cosph*costh; v13=-sinph*costh;
v21=costh; v22=-cosph*sinth; v23=-sinph*sinth;
v32=sinph; v33=-cosph;
v43=rho;
for (int i=0;i<N;i++)
{
// calculating eye coordinates
xe=v11*(object+i)->x+v21*(object+i)->y;
ye=v12*(object+i)->x+v22*(object+i)->y+v32*(object+i)->z;
ze=v13*(object+i)->x+v23*(object+i)->y+v33*(object+i)->z+v43;
// calculating screen coordinates
x=dist_to_screen*xe/ze+xshift;
y=dist_to_screen*ye/ze+yshift;
// drawing
if((object+i)->action==move)
MoveTo(x,y);
else
LineTo(x,y);
}
}
int main(void)
{
const int n=4; // number of cubes segments +1
Point3D cube[15*n]; // coordinates for cubes points
float rho=1900,theta=Pi/3,phi=2*Pi/3,dist_to_screen=600; // view point
int xshift=300, yshift=140; // picture offset
float side=300; // cubes parameters
float delta;// auxulary variable
// initializing graphics mode
init_gr();
// generating cube
delta=side/(n-1);
for (int i=0;i<n;i++)
{
for(int j=i*5;j<i*5+5;j++)
{
cube[j].x=i*delta;
cube[j].action=draw;
}
cube[i*5].y=0;
cube[i*5].z=0;
cube[i*5].action=move;
cube[i*5+1].y=side;
cube[i*5+1].z=0;
cube[i*5+2].y=side;
cube[i*5+2].z=side;
cube[i*5+3].y=0;
cube[i*5+3].z=side;
cube[i*5+4].y=0;
cube[i*5+4].z=0;
}
int c=5*n;
for (i=0;i<n;i++)
{
for(int j=i*5;j<i*5+5;j++)
{
cube[c+j].y=i*delta;
cube[c+j].action=draw;
}
cube[c+i*5].x=0;
cube[c+i*5].z=0;
cube[c+i*5].action=move;
cube[c+i*5+1].x=side;
cube[c+i*5+1].z=0;
cube[c+i*5+2].x=side;
cube[c+i*5+2].z=side;
cube[c+i*5+3].x=0;
cube[c+i*5+3].z=side;
cube[c+i*5+4].x=0;
cube[c+i*5+4].z=0;
}
c=10*n;
for (i=0;i<n;i++)
{
for(int j=i*5;j<i*5+5;j++)
{
cube[c+j].z=i*delta;
cube[c+j].action=draw;
}
cube[c+i*5].y=0;
cube[c+i*5].x=0;
cube[c+i*5].action=move;
cube[c+i*5+1].y=side;
cube[c+i*5+1].x=0;
cube[c+i*5+2].y=side;
cube[c+i*5+2].x=side;
cube[c+i*5+3].y=0;
cube[c+i*5+3].x=side;
cube[c+i*5+4].y=0;
cube[c+i*5+4].x=0;
}
// drawing
draw3Dobject(cube,15*n,rho,theta,phi,dist_to_screen,xshift,yshift);
/* clean up */
getch();
end_gr();
return 0;
}
Рисование тора
» Кликните сюда для просмотра оффтоп текста.. «
Код
//////////////////////////////////////////////////////////////////////////////
//
// Generating and drawing torus
// (c) Johna Smith, 1996
//
// Method description:
// Torus has two main circles, which are described by
// two systems of eqations:
// x=Rcos(a) x=R+rcos(b)
// y=Rsin(a) y=0
// z=0 z=rsin(b)
// By generating this circles (approximating by polygons) we can get torus
//
//////////////////////////////////////////////////////////////////////////////
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <dos.h>
#define Pi 3.1415926536
enum Action{move,draw};
struct Point3D
{
int x;
int y;
int z;
Action action;
};
// this function initializes graphics mode
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void init_gr(void)
{
/* request autodetection */
int gdriver = DETECT, gmode, errorcode;
/* initialize graphics mode */
initgraph(&gdriver, &gmode, "");
/* read result of initialization */
errorcode = graphresult();
if (errorcode != grOk) /* an error occurred */
{
printf("Graphics error: %s\n", grapherrormsg(errorcode));
printf("Press any key to halt:");
getch();
exit(1); /* return with error code */
}
}
// this function shuts graphics mode down
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void end_gr(void)
{
closegraph();
}
// this function moves CP to (x,y) position
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void MoveTo(int x, int y)
{
moveto(x,y);
}
// this function draws a line to (x,y) position
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void LineTo(int x, int y)
{
lineto(x,y);
}
void draw3Dobject(Point3D *object, int N, float rho, float theta,
float phi, float dist_to_screen, int xshift, int yshift)
{
int x,y;
float xe,ye,ze,costh,sinph,cosph,sinth,v11,v12,v13,v21,v22,v32,v33,v23,v43;
// calculating coefficients
costh=cos(theta);
sinth=sin(theta);
cosph=cos(phi);
sinph=sin(phi);
v11=-sinth; v12=-cosph*costh; v13=-sinph*costh;
v21=costh; v22=-cosph*sinth; v23=-sinph*sinth;
v32=sinph; v33=-cosph;
v43=rho;
for (int i=0;i<N;i++)
{
// calculating eye coordinates
xe=v11*(object+i)->x+v21*(object+i)->y;
ye=v12*(object+i)->x+v22*(object+i)->y+v32*(object+i)->z;
ze=v13*(object+i)->x+v23*(object+i)->y+v33*(object+i)->z+v43;
// calculating screen coordinates
x=dist_to_screen*xe/ze+xshift;
y=dist_to_screen*ye/ze+yshift;
// drawing
if((object+i)->action==move)
MoveTo(x,y);
else
LineTo(x,y);
}
}
int main(void)
{
const int n=20; // number of torus' segments
Point3D torus[2*n*(n+1)]; // coordinates for torus' points
float rho=1800,theta=0,phi=3*Pi/4,dist_to_screen=600; // view point
int xshift=300, yshift=250; // picture offset
float delta=2.0*Pi/n, r=75, R=300; // torus' parameters
float alpha,cosa,sina,beta,x; // auxulary variables
// initializing graphics mode
init_gr();
// generating torus
for (int i=0;i<n;i++)
{
alpha=i*delta;
cosa=cos(alpha);
sina=sin(alpha);
for (int j=0;j<n+1;j++)
{
beta=j*delta;
x=R+r*cos(beta);
torus[i*(n+1)+j].x=cosa*x;
torus[i*(n+1)+j].y=sina*x;
torus[i*(n+1)+j].z=r*sin(beta);
torus[i*(n+1)+j].action=((i==0 && j==0)?move:draw);
}
}
int c=n*n+n;
for (i=0;i<n;i++)
{
beta=i*delta;
x=R+r*cos(beta);
for (int j=0;j<n+1;j++)
{
alpha=j*delta;
cosa=cos(alpha);
sina=sin(alpha);
torus[c+i*(n+1)+j].x=cosa*x;
torus[c+i*(n+1)+j].y=sina*x;
torus[c+i*(n+1)+j].z=r*sin(beta);
torus[c+i*(n+1)+j].action=draw;
}
}
// drawing
draw3Dobject(torus,2*n*(n+1),rho,theta,phi,dist_to_screen,xshift,yshift);
/* clean up */
getch();
end_gr();
return 0;
}
Рисование 3D объекта
» Кликните сюда для просмотра оффтоп текста.. «
Код
//////////////////////////////////////////////////////////////////////////////
//
// Drawing 3D object
// (c) Johna Smith, 1996
//
// Method description:
// Function draw3Dobject recieves the following parameters:
// object - reference to array of points of the drawn object
// N - number of points in this array
// rho \
// phi |- spherical coordinates of point of view
// theta /
// dist_to_screen - distance from viewpoint to screen
// xshift, yshift - picture will be shifted by this values
//
//////////////////////////////////////////////////////////////////////////////
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <dos.h>
#define Pi 3.1415926536
enum Action{move,draw};
struct Point3D
{
int x;
int y;
int z;
Action action;
};
// this function initializes graphics mode
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void init_gr(void)
{
/* request autodetection */
int gdriver = DETECT, gmode, errorcode;
/* initialize graphics mode */
initgraph(&gdriver, &gmode, "");
/* read result of initialization */
errorcode = graphresult();
if (errorcode != grOk) /* an error occurred */
{
printf("Graphics error: %s\n", grapherrormsg(errorcode));
printf("Press any key to halt:");
getch();
exit(1); /* return with error code */
}
}
// this function shuts graphics mode down
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void end_gr(void)
{
closegraph();
}
// this function moves CP to (x,y) position
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void MoveTo(int x, int y)
{
moveto(x,y);
}
// this function draws a line to (x,y) position
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void LineTo(int x, int y)
{
lineto(x,y);
}
void draw3Dobject(Point3D *object, int N, float rho, float theta,
float phi, float dist_to_screen, int xshift, int yshift)
{
int x,y;
float xe,ye,ze,costh,sinph,cosph,sinth,v11,v12,v13,v21,v22,v32,v33,v23,v43;
// calculating coefficients
costh=cos(theta);
sinth=sin(theta);
cosph=cos(phi);
sinph=sin(phi);
v11=-sinth; v12=-cosph*costh; v13=-sinph*costh;
v21=costh; v22=-cosph*sinth; v23=-sinph*sinth;
v32=sinph; v33=-cosph;
v43=rho;
for (int i=0;i<N;i++)
{
// calculating eye coordinates
xe=v11*(object+i)->x+v21*(object+i)->y;
ye=v12*(object+i)->x+v22*(object+i)->y+v32*(object+i)->z;
ze=v13*(object+i)->x+v23*(object+i)->y+v33*(object+i)->z+v43;
// calculating screen coordinates
x=dist_to_screen*xe/ze+xshift;
y=dist_to_screen*ye/ze+yshift;
// drawing
if((object+i)->action==move)
MoveTo(x,y);
else
LineTo(x,y);
}
}
int main(void)
{
Point3D thetr[]={{100,100,100,move},
{100,200,100,draw},
{200,100,100,draw},
{100,100,100,draw},
{100,100,200,draw},
{200,100,100,draw},
{100,100,200,move},
{100,200,100,draw}};
int N=sizeof(thetr)/sizeof(Point3D);
float rho=700,theta=Pi/4,phi=Pi/4,dist_to_screen=300;
int xshift=300, yshift=150;
// initializing graphics mode
init_gr();
/* examples */
while (!kbhit())
{
theta+=0.05;
// rotating viewpoint
if (phi>2*Pi) phi-=2*Pi;
setcolor(11);
draw3Dobject(thetr,N,rho,theta,phi,dist_to_screen,xshift,yshift);
setcolor(0);
delay(15);
draw3Dobject(thetr,N,rho,theta,phi,dist_to_screen,xshift,yshift);
}
/* clean up */
getch();
end_gr();
return 0;
}
Вращение 3D объекта
» Кликните сюда для просмотра оффтоп текста.. «
Код
//////////////////////////////////////////////////////////////////////////////
//
// Rotating 3D object
// (c) Johna Smith, 1996
//
// Method description:
// Given: vector X, angle a
// To rotate this vector about axe X we should apply the following
// operation: X'=X*Rx, where Rx - is matrix of rotation
// [ 1 0 0 0 ]
// [ 0 cos a sin a 0 ]
// Rx=[ 0 -sin a cos a 0 ]
// [ 0 0 0 1 ]
// Applying this operation to every point of the given object we
// rotate it.
//
//////////////////////////////////////////////////////////////////////////////
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <dos.h>
#define Pi 3.1415926536
enum Action{move,draw};
struct Point3D
{
float x;
float y;
float z;
Action action;
};
// this function initializes graphics mode
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void init_gr(void)
{
/* request autodetection */
int gdriver = DETECT, gmode, errorcode;
/* initialize graphics mode */
initgraph(&gdriver, &gmode, "");
/* read result of initialization */
errorcode = graphresult();
if (errorcode != grOk) /* an error occurred */
{
printf("Graphics error: %s\n", grapherrormsg(errorcode));
printf("Press any key to halt:");
getch();
exit(1); /* return with error code */
}
}
// this function shuts graphics mode down
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void end_gr(void)
{
closegraph();
}
// this function moves CP to (x,y) position
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void MoveTo(int x, int y)
{
moveto(x,y);
}
// this function draws a line to (x,y) position
// it will work only if you're using Borland C++ compiler & BGI drivers
// if you're using another compiler you should overwrite body of this function
void LineTo(int x, int y)
{
lineto(x,y);
}
void draw3Dobject(Point3D *object, int N, float rho, float theta,
float phi, float dist_to_screen, int xshift, int yshift)
{
int x,y;
float xe,ye,ze,costh,sinph,cosph,sinth,v11,v12,v13,v21,v22,v32,v33,v23,v43;
// calculating coefficients
costh=cos(theta);
sinth=sin(theta);
cosph=cos(phi);
sinph=sin(phi);
v11=-sinth; v12=-cosph*costh; v13=-sinph*costh;
v21=costh; v22=-cosph*sinth; v23=-sinph*sinth;
v32=sinph; v33=-cosph;
v43=rho;
for (int i=0;i<N;i++)
{
// calculating eye coordinates
xe=v11*(object+i)->x+v21*(object+i)->y;
ye=v12*(object+i)->x+v22*(object+i)->y+v32*(object+i)->z;
ze=v13*(object+i)->x+v23*(object+i)->y+v33*(object+i)->z+v43;
// calculating screen coordinates
x=dist_to_screen*xe/ze+xshift;
y=dist_to_screen*ye/ze+yshift;
// drawing
if((object+i)->action==move)
MoveTo(x,y);
else
LineTo(x,y);
}
}
void RotateX(Point3D *object, int n, float angle)
{
float cosa,sina,y,z;
cosa=cos(angle);
sina=sin(angle);
for(int i=0;i<n;i++)
{
y=(object+i)->y*cosa-(object+i)->z*sina;
z=(object+i)->y*sina+(object+i)->z*cosa;
(object+i)->y=y;
(object+i)->z=z;
}
}
void RotateY(Point3D *object, int n, float angle)
{
float cosa,sina,x,z;
cosa=cos(angle);
sina=sin(angle);
for(int i=0;i<n;i++)
{
x=(object+i)->x*cosa+(object+i)->z*sina;
z=-(object+i)->x*sina+(object+i)->z*cosa;
(object+i)->x=x;
(object+i)->z=z;
}
}
void RotateZ(Point3D *object, int n, float angle)
{
float cosa,sina,x,y;
cosa=cos(angle);
sina=sin(angle);
for(int i=0;i<n;i++)
{
x=(object+i)->x*cosa-(object+i)->y*sina;
y=(object+i)->x*sina+(object+i)->y*cosa;
(object+i)->x=x;
(object+i)->y=y;
}
}
int main(void)
{
Point3D thetr[]={{100,100,100,move},
{100,200,100,draw},
{200,100,100,draw},
{100,100,100,draw},
{100,100,200,draw},
{200,100,100,draw},
{100,100,200,move},
{100,200,100,draw}};
Point3D cube[]={{-50,-50,-50,move},
{-50,50,-50,draw},
{-50,50,50,draw},
{50,50,50,draw},
{50,50,-50,draw},
{50,-50,-50,draw},
{50,-50,50,draw},
{-50,-50,50,draw},
{-50,50,50,draw},
{-50,-50,50,move},
{-50,-50,-50,draw},
{50,-50,-50,draw},
{50,50,-50,move},
{-50,50,-50,draw},
{50,-50,50,move},
{50,50,50,draw}};
int N=sizeof(thetr)/sizeof(Point3D);
int M=sizeof(cube)/sizeof(Point3D);
float rho=1500,theta=Pi/4,phi=-3*Pi/4,dist_to_screen=700;
int xshift=300, yshift=150,xshift1=200,yshift1=200;
// initializing graphics mode
init_gr();
/* examples */
while (!kbhit())
{
RotateX(cube,M,Pi/24);
RotateY(cube,M,Pi/24);
RotateZ(cube,M,Pi/24);
RotateY(thetr,N,Pi/30);
setcolor(12);
draw3Dobject(thetr,N,rho,theta,phi,dist_to_screen,xshift,yshift);
draw3Dobject(cube,M,rho,theta,phi,dist_to_screen,xshift1,yshift1);
setcolor(0);
delay(35);
draw3Dobject(thetr,N,rho,theta,phi,dist_to_screen,xshift,yshift);
draw3Dobject(cube,M,rho,theta,phi,dist_to_screen,xshift1,yshift1);
}
/* clean up */
getch();
end_gr();
return 0;
}