This is sphere.c in view mode; [Download] [Up]
/* Sphere.c
Varun Mitroo
March 1, 1991
To compile, type:
cc sphere.c -o sphere
Options:
-r <number> Radius of the sphere. Default 150
-la <number> Number of latitude sections. Default 10
-lo <number> Number of longitude sections. Default 18
-theta <number> Horizontal angle in degrees. Default 30 degrees
-phi <number> Vertical angle in degrees. Default 45 degrees
-clip Activate hidden-line removal
-noclip Deactivate hidden-line removal. On by default
-shade Activate shading
-noshade Deactivate shading. On by default
This program outputs to stdout. Output should be redirected to a file.
Example:
sphere > test.ps - Creates file test.ps with default settings
sphere -clip > test.ps - Same file as above with hidden line removal
sphere -shade -la 20 -theta -40 -phi 25 -lo 25 -r 100 > test.ps
Above line sets shading on with 20 latitude sections, 25
longitude sections, theta 40 degrees, phi 25 degrees, and
a radius of 100.
**************************************************************/
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define PI (3.14159265)
#define TRUE (1)
#define FALSE (0)
typedef int boolean;
typedef char *string;
typedef float vector3D[3];
typedef struct PointThreeD {
float x,y,z;
} PointThreeD;
typedef struct PointTwoD {
float x,y;
} PointTwoD;
/***************************************************************/
void CrossXYZ(v1, v2, crossProd)
vector3D v1, v2, crossProd;
{
crossProd[0] = v1[1] * v2[2] - v1[2] * v2[1];
crossProd[1] = v1[2] * v2[0] - v1[0] * v2[2];
crossProd[2] = v1[0] * v2[1] - v1[1] * v2[0];
}
boolean ReadParam();
void DrawSphere();
boolean StrEqual (str1, str2)
string str1, str2;
{
return (!strcmp(str1, str2));
}
/****************** Global Variables ***************************/
float radius = 150, xMiddle = 0, yMiddle = 0, theta = -PI/6, phi = PI/4, gray;
int xSize = 400, ySize = 400, longi = 18, lati = 10;
boolean clipFlag = FALSE, shadeFlag = FALSE;
float sinTheta, sinPhi, cosTheta, cosPhi;
/***************************************************************/
main (argc, argv)
int argc;
string *argv;
{
if (ReadParam(argc,argv) == FALSE) DrawSphere();
else exit(1);
}
/***************************************************************/
boolean ReadParam(argc, argv)
int argc;
string argv[];
{
int count = 1;
while (count < argc)
{
if (StrEqual(argv[count], "-r"))
{
count++;
if (count < argc) radius = atof(argv[count]);
count++;
}
else if (StrEqual(argv[count], "-clip"))
{
clipFlag = TRUE;
count++;
}
else if (StrEqual(argv[count], "-noclip"))
{
shadeFlag = FALSE;
clipFlag = FALSE;
count++;
}
else if (StrEqual(argv[count], "-shade"))
{
shadeFlag = TRUE;
clipFlag = TRUE;
count++;
}
else if (StrEqual(argv[count], "-noshade"))
{
shadeFlag = FALSE;
count++;
}
else if (StrEqual(argv[count], "-la"))
{
count++;
if (count < argc) lati = atof(argv[count]);
count++;
}
else if (StrEqual(argv[count], "-lo"))
{
count++;
if (count < argc) longi = atof(argv[count]);
count++;
}
else if (StrEqual(argv[count], "-theta"))
{
count++;
if (count < argc) theta = -atof(argv[count]) / 180 * PI;
count++;
}
else if (StrEqual(argv[count], "-phi"))
{
count++;
if (count < argc) phi = atof(argv[count]) / 180 * PI;
count++;
}
else {
printf("Error with arguments: %s [-r] [-la] [-lo] [-theta] [-phi] [-clip/noclip] [-shade/noshade]\n", argv[0]);
return (TRUE);
exit(1);
}
}
return (FALSE);
}
/***************************************************************/
void PrintHeader()
{
printf("%%!PS-Adobe-2.0 EPSF-1.2\n");
printf("%%%%BoundingBox: 0 0 %d %d\n", xSize, ySize);
printf("%%%%Creator: Varun Mitroo\n");
printf("%%%%Title: Sphere\n");
printf("%%%%EndComments\n\n");
}
/***************************************************************/
void BoundingBox()
{
printf("0 0 moveto\n");
printf("0 %d lineto\n", ySize);
printf("%d %d lineto\n", xSize, ySize);
printf("%d 0 lineto\n", xSize);
if (shadeFlag==TRUE)
printf("closepath gsave .333 setgray fill grestore 0 setgray stroke\n");
else printf("closepath gsave 1 setgray fill grestore 0 setgray stroke\n");
}
/***************************************************************/
boolean PolyVisible(poly)
PointThreeD *poly;
{
vector3D v1, v2, cross;
v1[0] = poly[0].x - poly[1].x;
v1[1] = poly[0].y - poly[1].y;
v1[2] = poly[0].z - poly[1].z;
v2[0] = poly[2].x - poly[1].x;
v2[1] = poly[2].y - poly[1].y;
v2[2] = poly[2].z - poly[1].z;
if ((v1[0] == 0) && (v1[1] == 0) && (v1[2] == 0))
{
v1[0] = poly[3].x - poly[2].x;
v1[1] = poly[3].y - poly[2].y;
v1[2] = poly[3].z - poly[2].z;
}
CrossXYZ(v1, v2, cross);
if (cross[2] < 0) return (TRUE);
else return (FALSE);
}
/***************************************************************/
boolean CalcLight(poly)
PointThreeD *poly;
{
vector3D v1, v2, cross;
v1[0] = poly[0].x - poly[1].x;
v1[1] = poly[0].y - poly[1].y;
v1[2] = poly[0].z - poly[1].z;
v2[0] = poly[2].x - poly[1].x;
v2[1] = poly[2].y - poly[1].y;
v2[2] = poly[2].z - poly[1].z;
if ((v1[0] == 0) && (v1[1] == 0) && (v1[2] == 0))
{
v1[0] = poly[3].x - poly[2].x;
v1[1] = poly[3].y - poly[2].y;
v1[2] = poly[3].z - poly[2].z;
}
CrossXYZ(v1, v2, cross);
gray = -cross[2] / sqrt(cross[0]*cross[0] + cross[1]*cross[1] + cross[2]*cross[2]);
}
/***************************************************************/
void Rotate(px, py, pz)
float *px, *py, *pz;
{
float xt, yt;
xt = *pz * sinTheta + *px * cosTheta;
*pz = *pz * cosTheta - *px * sinTheta;
*px = xt;
yt = *py * cosPhi - *pz * sinPhi;
*pz = *py * sinTheta + *pz * cosPhi;
*py = yt;
}
/***************************************************************/
void DrawPolygon(curPoly)
PointThreeD curPoly[];
{
boolean drawFlag;
if (shadeFlag==TRUE) CalcLight(curPoly);
Rotate(&curPoly[0].x, &curPoly[0].y, &curPoly[0].z);
Rotate(&curPoly[1].x, &curPoly[1].y, &curPoly[1].z);
Rotate(&curPoly[2].x, &curPoly[2].y, &curPoly[2].z);
Rotate(&curPoly[3].x, &curPoly[3].y, &curPoly[3].z);
if (clipFlag==TRUE) drawFlag = PolyVisible(curPoly);
if ((clipFlag && drawFlag) || (clipFlag == FALSE))
{
printf("%0f %0f moveto\n", xMiddle + curPoly[0].x, yMiddle + curPoly[0].y);
printf("%0f %0f lineto\n", xMiddle + curPoly[1].x, yMiddle + curPoly[1].y);
printf("%0f %0f lineto\n", xMiddle + curPoly[2].x, yMiddle + curPoly[2].y);
printf("%0f %0f lineto\n", xMiddle + curPoly[3].x, yMiddle + curPoly[3].y);
printf("closepath\n");
if (shadeFlag==FALSE) printf("stroke\n");
else
{
printf("%0f setgray\n", gray);
printf("fill\n");
}
}
}
void DrawPolygon3(curPoly)
PointThreeD curPoly[];
{
boolean drawFlag;
if (shadeFlag==TRUE) CalcLight(curPoly);
Rotate(&curPoly[0].x, &curPoly[0].y, &curPoly[0].z);
Rotate(&curPoly[1].x, &curPoly[1].y, &curPoly[1].z);
Rotate(&curPoly[2].x, &curPoly[2].y, &curPoly[2].z);
if (clipFlag==TRUE) drawFlag = PolyVisible(curPoly);
if ((clipFlag && drawFlag) || (clipFlag == FALSE))
{
printf("%0f %0f moveto\n", xMiddle + curPoly[0].x, yMiddle + curPoly[0].y);
printf("%0f %0f lineto\n", xMiddle + curPoly[1].x, yMiddle + curPoly[1].y);
printf("%0f %0f lineto\n", xMiddle + curPoly[2].x, yMiddle + curPoly[2].y);
printf("closepath\n");
if (shadeFlag==FALSE) printf("stroke\n");
else
{
printf("%0f setgray\n", gray);
printf("fill\n");
}
}
}
/***************************************************************/
void ComputeSphere()
{
float step1, step2, count1, count2, s1, s2, c1, c2, ts1, ts2, tc1, tc2, x, y, z;
PointThreeD curPoly[4];
xMiddle = xSize / 2;
yMiddle = ySize / 2;
sinTheta = sin(theta); sinPhi = sin(phi);
cosTheta = cos(theta); cosPhi = cos(phi);
step1 = PI / lati;
step2 = PI / longi;
/************ Draw Top Row *******************/
c1 = 1;
s1 = 0;
tc1 = cos(step1);
ts1 = sin(step1);
for (count2 = 0; count2 < PI * 2; count2 = count2 + step2)
{
curPoly[0].x=0;
curPoly[0].y=radius;
curPoly[0].z=0;
c2 = cos(count2);
s2 = sin(count2);
tc2 = cos(count2+step2);
ts2 = sin(count2+step2);
curPoly[1].x = ts1 * tc2 * radius;
curPoly[1].y = tc1 * radius;
curPoly[1].z = ts1 * ts2 * radius;
curPoly[2].x = ts1 * c2 * radius;
curPoly[2].y = tc1 * radius;
curPoly[2].z = ts1 * s2 * radius;
DrawPolygon3(curPoly);
}
/************ Draw Body of Sphere *******************/
for (count1 = step1; count1 < (PI-step1); count1 = count1 + step1)
{
c1 = cos(count1);
s1 = sin(count1);
tc1 = cos(count1+step1);
ts1 = sin(count1+step1);
for (count2 = 0; count2 < PI * 2; count2 = count2 + step2)
{
c2 = cos(count2);
s2 = sin(count2);
tc2 = cos(count2+step2);
ts2 = sin(count2+step2);
curPoly[0].x = s1 * c2 * radius;
curPoly[0].y = c1 * radius;
curPoly[0].z = s1 * s2 * radius;
curPoly[1].x = s1 * tc2 * radius;
curPoly[1].y = c1 * radius;
curPoly[1].z = s1 * ts2 * radius;
curPoly[2].x = ts1 * tc2 * radius;
curPoly[2].y = tc1 * radius;
curPoly[2].z = ts1 * ts2 * radius;
curPoly[3].x = ts1 * c2 * radius;
curPoly[3].y = tc1 * radius;
curPoly[3].z = ts1 * s2 * radius;
DrawPolygon(curPoly);
}
}
/************ Draw Bottom Row *******************/
c1 = -1;
s1 = 0;
tc1 = cos(PI-step1);
ts1 = sin(PI-step1);
for (count2 = 0; count2 < PI * 2; count2 = count2 + step2)
{
curPoly[0].x=0;
curPoly[0].y=-radius;
curPoly[0].z=0;
c2 = cos(count2);
s2 = sin(count2);
tc2 = cos(count2+step2);
ts2 = sin(count2+step2);
curPoly[1].x = ts1 * c2 * radius;
curPoly[1].y = tc1 * radius;
curPoly[1].z = ts1 * s2 * radius;
curPoly[2].x = ts1 * tc2 * radius;
curPoly[2].y = tc1 * radius;
curPoly[2].z = ts1 * ts2 * radius;
DrawPolygon3(curPoly);
}
}
/***************************************************************/
void DrawSphere()
{
PrintHeader();
BoundingBox();
ComputeSphere();
printf("showpage\n");
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.