#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;
}