ftp.nice.ch/pub/next/graphics/3d/Sphere.1.0.N.bs.tar.gz#/Sphere/CL-Sphere/sphere.c

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.