kurt@cashew.asd.sgi.com (Kurt Akeley) (04/02/91)
In article <1991Mar27.174104.26867@hellgate.utah.edu> thomson@cs.utah.edu (Rich Thomson) writes: |>Several times on comp.graphics the SGI folks have offered up the |>famous "1 million polygons/second" quotation from marketing literature |>when referring to peak performance on the VGX series of machines. |> |>The polygons in question are 50 pixel triangle strips that are flat |>shaded. Also, they may have rendered them without the Z buffer turned |>on (the spec sheet is away from me at the moment). |>... |>So: is this a "theoretical" number, or is it attainable by a program, |>no matter how contorted? We take our graphics performance claims very seriously here at Silicon Graphics. They represent performances that are achievable with carefully tuned programs that use ONLY commands that are available in the Graphics Library. We distinguish between two different classes of performance: primitive performance and fill performance. Primitive performance is the rate that points, lines, polygons, and characters can be drawn per second, assuming no limitation from pixel manipulation, measured with different modes activated (such as lighting). Fill performance is the rate that pixels are filled, assuming an infinite supply of graphics primitives, again with different modes active (zbuffer, blending, etc). Primitive performances are always specified conservatively, we always claim a lower number than can actually be achieved. Fill performances are usually specified as a "not-to-be-exceeded" maximum that is approached asymptotically as larger and larger primitives are drawn. Due to slight overheads of memory and display refresh, achievable fill rates are sometimes as much as 10 percent lower than the claimed rates. I have included the source code to the program that I use to verify the performance of triangle meshes. I ran this program on my 5-span VGX with the following results: size=8, offset=4, zbuffer(1), events=500000, lighting=1 running on cashew, GL4DVGX-4.0, Fri Mar 29 15:22:58 1991 Triangle mesh performance (lighted): 1 triangles per mesh: 189393 triangles per second 2 triangles per mesh: 304878 triangles per second 3 triangles per mesh: 299400 triangles per second 4 triangles per mesh: 387596 triangles per second 5 triangles per mesh: 471698 triangles per second 10 triangles per mesh: 574712 triangles per second 20 triangles per mesh: 641025 triangles per second 30 triangles per mesh: 675648 triangles per second 62 triangles per mesh: 714240 triangles per second Display listed triangle mesh (lighted): 62 triangles per mesh: 769181 triangles per second Display listed triangle mesh (colored): 62 triangles per mesh: 1020342 triangles per second Quadrilateral strip performance (lighted): 31 quads per mesh: 342465 quads per second Independent triangle performance (lighted): 1 triangles per mesh: 192307 triangles per second Triangle mesh performance (flat shaded): 10 triangles per mesh: 943396 triangles per second 20 triangles per mesh: 925925 triangles per second 30 triangles per mesh: 1063787 triangles per second 62 triangles per mesh: 1086886 triangles per second Quadrilateral strip performance (flat shaded): 31 quads per mesh: 420167 quads per second Independent triangle performance (flat shaded): 1 triangles per mesh: 280898 triangles per second Note that performances of well over 1 million triangles per second are achieved for long meshes of single- and multi-colored triangles, with the zbuffer enabled. When lighting and smooth shading are enabled, the performance drops to roughly 3/4 of a million triangles per second. (Here's where the marketing error crept in - the correct claim is 1 million connected triangles per second, multi-colored, flat shaded, zbuffered, projected, subpixel positioned. It's hard to keep all these modes straight!) Note also that I had to limit the triangles to about 30 pixels each, as my machine is a 5-span VGX. A 10-span VGX has double the fill rate, and is able to achieve these performances with 50-pixel triangles. I will be happy to supply other performance testing routines by email on request. -- kurt ----------------------------- cut here ---------------------------------- /************************************************************************** Copyright 1991 by Silicon Graphics Incorporated, Mountain View, California. All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Silicon Graphics not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. **************************************************************************/ /* * Kurt Akeley * March 1991 * * Test performance of triangle meshes (strips) */ #include <stdio.h> #include <gl.h> #include <device.h> #include <sys/types.h> #include <sys/times.h> #include <sys/param.h> #define OUTFILE stdout #define MAXVERTEX 102 #define VERTSIZE 8 #define LIGHTVERT(i) n3f(fp+(VERTSIZE*(i))); v3f(fp+(VERTSIZE*(i))+4) #define COLORVERT(i) c3f(fp+(VERTSIZE*(i))); v3f(fp+(VERTSIZE*(i))+4) #define FLATVERT(i) v3f(fp+(VERTSIZE*(i))+4) float *meshbuf; int dolighting = TRUE; long events; main(argc,argv) char *argv[]; { register i,j,k; int size, offset; int doz; /* allocate a quad-aligned buffer */ meshbuf = (float*)malloc(sizeof(float)*(MAXVERTEX*VERTSIZE + 3)); meshbuf = (float*)(((long)(meshbuf+3)) & 0xfffffff0); /* evaluate command line arguments */ size = 10; offset = 5; doz = TRUE; events = 100000; dolighting = TRUE; if (argc > 1) size = atoi(argv[1]); if (argc > 2) offset = atoi(argv[2]); if (argc > 3) doz = atoi(argv[3]); if (argc > 4) events = atoi(argv[4]); if (argc > 5) dolighting = atoi(argv[5]); fprintf(OUTFILE,"size=%d, offset=%d, zbuffer(%d), events=%d, lighting=%d\n", size, offset, doz, events, dolighting); fflush(OUTFILE); /* initialize graphics */ prefposition(10,32*size+30,10,size+30); foreground(); winopen("meshspeed"); RGBmode(); overlay(2); gconfig(); zbuffer(doz); zfunction(ZF_ALWAYS); subpixel(TRUE); qdevice(ESCKEY); shademodel(GOURAUD); timestamp(); /* initialize lighting */ initlight(); /* clear the screen */ cpack(0); clear(); drawmode(OVERDRAW); color(0); clear(); drawmode(NORMALDRAW); /* initialize data arrays */ for (i=0; i<MAXVERTEX; i+=1) { meshbuf[VERTSIZE*i+0] = (i&1) ? 0.0 : 1.0; meshbuf[VERTSIZE*i+1] = 0.0; meshbuf[VERTSIZE*i+2] = (i&1) ? 1.0 : 0.0; meshbuf[VERTSIZE*i+3] = 0; meshbuf[VERTSIZE*i+4] = 10.0 + (float)(size*(i>>1)) + (float)(offset*(i&1)); meshbuf[VERTSIZE*i+5] = 10.0 + (float)(size*(i&1)); meshbuf[VERTSIZE*i+6] = 0.0; meshbuf[VERTSIZE*i+7] = 0; } /* run the tests */ fprintf(OUTFILE,"Triangle mesh performance (lighted):\n"); meshlight1(); meshlight2(); meshlight3(); meshlight4(); meshlight5(); meshlight10(); meshlight20(); meshlight30(); meshlight62(); fprintf(OUTFILE,"Display listed triangle mesh (lighted):\n"); dlmeshlight62(); fprintf(OUTFILE,"Display listed triangle mesh (colored):\n"); dlmeshcolor62(); fprintf(OUTFILE,"Quadrilateral strip performance (lighted):\n"); quadlight31(); fprintf(OUTFILE,"Independent triangle performance (lighted):\n"); indlight(); fprintf(OUTFILE,"Triangle mesh performance (flat shaded):\n"); meshflat10(); meshflat20(); meshflat30(); meshflat62(); fprintf(OUTFILE,"Quadrilateral strip performance (flat shaded):\n"); quadflat31(); fprintf(OUTFILE,"Independent triangle performance (flat shaded):\n"); indflat(); } meshlight1() { register i; register float *fp; czclear(0,0); light(TRUE); startclock(); for (i=events; i>0; i--) { fp = meshbuf; bgntmesh(); LIGHTVERT(0); LIGHTVERT(1); LIGHTVERT(2); endtmesh(); } stopclock(events,1,"triangles"); light(FALSE); } meshlight2() { register i; register float *fp; czclear(0,0); light(TRUE); startclock(); for (i=events/2; i>0; i--) { fp = meshbuf; bgntmesh(); LIGHTVERT(0); LIGHTVERT(1); LIGHTVERT(2); LIGHTVERT(3); endtmesh(); } stopclock(events/2,2,"triangles"); light(FALSE); } meshlight3() { register i; register float *fp; czclear(0,0); light(TRUE); startclock(); for (i=events/3; i>0; i--) { fp = meshbuf; bgntmesh(); LIGHTVERT(0); LIGHTVERT(1); LIGHTVERT(2); LIGHTVERT(3); LIGHTVERT(4); endtmesh(); } stopclock(events/3,3,"triangles"); light(FALSE); } meshlight4() { register i; register float *fp; czclear(0,0); light(TRUE); startclock(); for (i=events/4; i>0; i--) { fp = meshbuf; bgntmesh(); LIGHTVERT(0); LIGHTVERT(1); LIGHTVERT(2); LIGHTVERT(3); LIGHTVERT(4); LIGHTVERT(5); endtmesh(); } stopclock(events/4,4,"triangles"); light(FALSE); } meshlight5() { register i; register float *fp; czclear(0,0); light(TRUE); startclock(); for (i=events/5; i>0; i--) { fp = meshbuf; bgntmesh(); LIGHTVERT(0); LIGHTVERT(1); LIGHTVERT(2); LIGHTVERT(3); LIGHTVERT(4); LIGHTVERT(5); LIGHTVERT(6); endtmesh(); } stopclock(events/5,5,"triangles"); light(FALSE); } meshlight10() { register i; register float *fp; czclear(0,0); light(TRUE); startclock(); for (i=events/10; i>0; i--) { fp = meshbuf; bgntmesh(); LIGHTVERT(0); LIGHTVERT(1); LIGHTVERT(2); LIGHTVERT(3); LIGHTVERT(4); LIGHTVERT(5); LIGHTVERT(6); LIGHTVERT(7); LIGHTVERT(8); LIGHTVERT(9); LIGHTVERT(10); LIGHTVERT(11); endtmesh(); } stopclock(events/10,10,"triangles"); light(FALSE); } meshlight20() { register i; register float *fp; czclear(0,0); light(TRUE); startclock(); for (i=events/20; i>0; i--) { fp = meshbuf; bgntmesh(); LIGHTVERT(0); LIGHTVERT(1); LIGHTVERT(2); LIGHTVERT(3); LIGHTVERT(4); LIGHTVERT(5); LIGHTVERT(6); LIGHTVERT(7); LIGHTVERT(8); LIGHTVERT(9); LIGHTVERT(10); LIGHTVERT(11); LIGHTVERT(12); LIGHTVERT(13); LIGHTVERT(14); LIGHTVERT(15); LIGHTVERT(16); LIGHTVERT(17); LIGHTVERT(18); LIGHTVERT(19); LIGHTVERT(20); LIGHTVERT(21); endtmesh(); } stopclock(events/20,20,"triangles"); light(FALSE); } meshlight30() { register i; register float *fp; czclear(0,0); light(TRUE); startclock(); for (i=events/30; i>0; i--) { fp = meshbuf; bgntmesh(); LIGHTVERT(0); LIGHTVERT(1); LIGHTVERT(2); LIGHTVERT(3); LIGHTVERT(4); LIGHTVERT(5); LIGHTVERT(6); LIGHTVERT(7); LIGHTVERT(8); LIGHTVERT(9); LIGHTVERT(10); LIGHTVERT(11); LIGHTVERT(12); LIGHTVERT(13); LIGHTVERT(14); LIGHTVERT(15); LIGHTVERT(16); LIGHTVERT(17); LIGHTVERT(18); LIGHTVERT(19); LIGHTVERT(20); LIGHTVERT(21); LIGHTVERT(22); LIGHTVERT(23); LIGHTVERT(24); LIGHTVERT(25); LIGHTVERT(26); LIGHTVERT(27); LIGHTVERT(28); LIGHTVERT(29); LIGHTVERT(30); LIGHTVERT(31); endtmesh(); } stopclock(events/30,30,"triangles"); light(FALSE); } meshlight62() { register i; register float *fp; czclear(0,0); light(TRUE); startclock(); for (i=events/62; i>0; i--) { fp = meshbuf; bgntmesh(); LIGHTVERT(0); LIGHTVERT(1); LIGHTVERT(2); LIGHTVERT(3); LIGHTVERT(4); LIGHTVERT(5); LIGHTVERT(6); LIGHTVERT(7); LIGHTVERT(8); LIGHTVERT(9); LIGHTVERT(10); LIGHTVERT(11); LIGHTVERT(12); LIGHTVERT(13); LIGHTVERT(14); LIGHTVERT(15); LIGHTVERT(16); LIGHTVERT(17); LIGHTVERT(18); LIGHTVERT(19); LIGHTVERT(20); LIGHTVERT(21); LIGHTVERT(22); LIGHTVERT(23); LIGHTVERT(24); LIGHTVERT(25); LIGHTVERT(26); LIGHTVERT(27); LIGHTVERT(28); LIGHTVERT(29); LIGHTVERT(30); LIGHTVERT(31); LIGHTVERT(32); LIGHTVERT(33); LIGHTVERT(34); LIGHTVERT(35); LIGHTVERT(36); LIGHTVERT(37); LIGHTVERT(38); LIGHTVERT(39); LIGHTVERT(40); LIGHTVERT(41); LIGHTVERT(42); LIGHTVERT(43); LIGHTVERT(44); LIGHTVERT(45); LIGHTVERT(46); LIGHTVERT(47); LIGHTVERT(48); LIGHTVERT(49); LIGHTVERT(50); LIGHTVERT(51); LIGHTVERT(52); LIGHTVERT(53); LIGHTVERT(54); LIGHTVERT(55); LIGHTVERT(56); LIGHTVERT(57); LIGHTVERT(58); LIGHTVERT(59); LIGHTVERT(60); LIGHTVERT(61); LIGHTVERT(62); LIGHTVERT(63); endtmesh(); } stopclock(events/62,62,"triangles"); light(FALSE); } #define MESHPERDL 10 dlmeshlight62() { register i,j; register float *fp; makeobj(1); for (i=0; i<MESHPERDL; i++) { fp = meshbuf; bgntmesh(); for (j=0; j<64; j++) { LIGHTVERT(j); } endtmesh(); } closeobj(); czclear(0,0); light(TRUE); startclock(); for (i=events/(62*MESHPERDL); i>0; i--) callobj(1); stopclock(events/62,62,"triangles"); light(FALSE); } dlmeshcolor62() { register i,j; register float *fp; makeobj(1); for (i=0; i<MESHPERDL; i++) { fp = meshbuf; bgntmesh(); for (j=0; j<64; j++) { COLORVERT(j); } endtmesh(); } closeobj(); czclear(0,0); shademodel(FLAT); startclock(); for (i=events/(62*MESHPERDL); i>0; i--) callobj(1); stopclock(events/62,62,"triangles"); shademodel(GOURAUD); } quadlight31() { register i; register float *fp; czclear(0,0); light(TRUE); startclock(); for (i=events/31; i>0; i--) { fp = meshbuf; bgnqstrip(); LIGHTVERT(0); LIGHTVERT(1); LIGHTVERT(2); LIGHTVERT(3); LIGHTVERT(4); LIGHTVERT(5); LIGHTVERT(6); LIGHTVERT(7); LIGHTVERT(8); LIGHTVERT(9); LIGHTVERT(10); LIGHTVERT(11); LIGHTVERT(12); LIGHTVERT(13); LIGHTVERT(14); LIGHTVERT(15); LIGHTVERT(16); LIGHTVERT(17); LIGHTVERT(18); LIGHTVERT(19); LIGHTVERT(20); LIGHTVERT(21); LIGHTVERT(22); LIGHTVERT(23); LIGHTVERT(24); LIGHTVERT(25); LIGHTVERT(26); LIGHTVERT(27); LIGHTVERT(28); LIGHTVERT(29); LIGHTVERT(30); LIGHTVERT(31); LIGHTVERT(32); LIGHTVERT(33); LIGHTVERT(34); LIGHTVERT(35); LIGHTVERT(36); LIGHTVERT(37); LIGHTVERT(38); LIGHTVERT(39); LIGHTVERT(40); LIGHTVERT(41); LIGHTVERT(42); LIGHTVERT(43); LIGHTVERT(44); LIGHTVERT(45); LIGHTVERT(46); LIGHTVERT(47); LIGHTVERT(48); LIGHTVERT(49); LIGHTVERT(50); LIGHTVERT(51); LIGHTVERT(52); LIGHTVERT(53); LIGHTVERT(54); LIGHTVERT(55); LIGHTVERT(56); LIGHTVERT(57); LIGHTVERT(58); LIGHTVERT(59); LIGHTVERT(60); LIGHTVERT(61); LIGHTVERT(62); LIGHTVERT(63); endqstrip(); } stopclock(events/31,31,"quads"); light(FALSE); } indlight() { register i; register float *fp; czclear(0,0); light(TRUE); startclock(); for (i=events/4; i>0; i--) { fp = meshbuf; bgnpolygon(); LIGHTVERT(0); LIGHTVERT(1); LIGHTVERT(2); endpolygon(); bgnpolygon(); LIGHTVERT(0); LIGHTVERT(1); LIGHTVERT(2); endpolygon(); bgnpolygon(); LIGHTVERT(0); LIGHTVERT(1); LIGHTVERT(2); endpolygon(); bgnpolygon(); LIGHTVERT(0); LIGHTVERT(1); LIGHTVERT(2); endpolygon(); } stopclock(events,1,"triangles"); light(FALSE); } meshflat10() { register i; register float *fp; czclear(0,0); cpack(0xffffffff); shademodel(FLAT); startclock(); for (i=events/10; i>0; i--) { fp = meshbuf; bgntmesh(); FLATVERT(0); FLATVERT(1); FLATVERT(2); FLATVERT(3); FLATVERT(4); FLATVERT(5); FLATVERT(6); FLATVERT(7); FLATVERT(8); FLATVERT(9); FLATVERT(10); FLATVERT(11); endtmesh(); } stopclock(events/10,10,"triangles"); shademodel(GOURAUD); } meshflat20() { register i; register float *fp; czclear(0,0); cpack(0xffffffff); shademodel(FLAT); startclock(); for (i=events/20; i>0; i--) { fp = meshbuf; bgntmesh(); FLATVERT(0); FLATVERT(1); FLATVERT(2); FLATVERT(3); FLATVERT(4); FLATVERT(5); FLATVERT(6); FLATVERT(7); FLATVERT(8); FLATVERT(9); FLATVERT(10); FLATVERT(11); FLATVERT(12); FLATVERT(13); FLATVERT(14); FLATVERT(15); FLATVERT(16); FLATVERT(17); FLATVERT(18); FLATVERT(19); FLATVERT(20); FLATVERT(21); endtmesh(); } stopclock(events/20,20,"triangles"); shademodel(GOURAUD); } meshflat30() { register i; register float *fp; czclear(0,0); cpack(0xffffffff); shademodel(FLAT); startclock(); for (i=events/30; i>0; i--) { fp = meshbuf; bgntmesh(); FLATVERT(0); FLATVERT(1); FLATVERT(2); FLATVERT(3); FLATVERT(4); FLATVERT(5); FLATVERT(6); FLATVERT(7); FLATVERT(8); FLATVERT(9); FLATVERT(10); FLATVERT(11); FLATVERT(12); FLATVERT(13); FLATVERT(14); FLATVERT(15); FLATVERT(16); FLATVERT(17); FLATVERT(18); FLATVERT(19); FLATVERT(20); FLATVERT(21); FLATVERT(22); FLATVERT(23); FLATVERT(24); FLATVERT(25); FLATVERT(26); FLATVERT(27); FLATVERT(28); FLATVERT(29); FLATVERT(30); FLATVERT(31); endtmesh(); } stopclock(events/30,30,"triangles"); shademodel(GOURAUD); } meshflat62() { register i; register float *fp; czclear(0,0); cpack(0xffffffff); shademodel(FLAT); startclock(); for (i=events/62; i>0; i--) { fp = meshbuf; bgntmesh(); FLATVERT(0); FLATVERT(1); FLATVERT(2); FLATVERT(3); FLATVERT(4); FLATVERT(5); FLATVERT(6); FLATVERT(7); FLATVERT(8); FLATVERT(9); FLATVERT(10); FLATVERT(11); FLATVERT(12); FLATVERT(13); FLATVERT(14); FLATVERT(15); FLATVERT(16); FLATVERT(17); FLATVERT(18); FLATVERT(19); FLATVERT(20); FLATVERT(21); FLATVERT(22); FLATVERT(23); FLATVERT(24); FLATVERT(25); FLATVERT(26); FLATVERT(27); FLATVERT(28); FLATVERT(29); FLATVERT(30); FLATVERT(31); FLATVERT(32); FLATVERT(33); FLATVERT(34); FLATVERT(35); FLATVERT(36); FLATVERT(37); FLATVERT(38); FLATVERT(39); FLATVERT(40); FLATVERT(41); FLATVERT(42); FLATVERT(43); FLATVERT(44); FLATVERT(45); FLATVERT(46); FLATVERT(47); FLATVERT(48); FLATVERT(49); FLATVERT(50); FLATVERT(51); FLATVERT(52); FLATVERT(53); FLATVERT(54); FLATVERT(55); FLATVERT(56); FLATVERT(57); FLATVERT(58); FLATVERT(59); FLATVERT(60); FLATVERT(61); FLATVERT(62); FLATVERT(63); endtmesh(); } stopclock(events/62,62,"triangles"); shademodel(GOURAUD); } quadflat31() { register i; register float *fp; czclear(0,0); cpack(0xffffffff); shademodel(FLAT); startclock(); for (i=events/31; i>0; i--) { fp = meshbuf; bgnqstrip(); FLATVERT(0); FLATVERT(1); FLATVERT(2); FLATVERT(3); FLATVERT(4); FLATVERT(5); FLATVERT(6); FLATVERT(7); FLATVERT(8); FLATVERT(9); FLATVERT(10); FLATVERT(11); FLATVERT(12); FLATVERT(13); FLATVERT(14); FLATVERT(15); FLATVERT(16); FLATVERT(17); FLATVERT(18); FLATVERT(19); FLATVERT(20); FLATVERT(21); FLATVERT(22); FLATVERT(23); FLATVERT(24); FLATVERT(25); FLATVERT(26); FLATVERT(27); FLATVERT(28); FLATVERT(29); FLATVERT(30); FLATVERT(31); FLATVERT(32); FLATVERT(33); FLATVERT(34); FLATVERT(35); FLATVERT(36); FLATVERT(37); FLATVERT(38); FLATVERT(39); FLATVERT(40); FLATVERT(41); FLATVERT(42); FLATVERT(43); FLATVERT(44); FLATVERT(45); FLATVERT(46); FLATVERT(47); FLATVERT(48); FLATVERT(49); FLATVERT(50); FLATVERT(51); FLATVERT(52); FLATVERT(53); FLATVERT(54); FLATVERT(55); FLATVERT(56); FLATVERT(57); FLATVERT(58); FLATVERT(59); FLATVERT(60); FLATVERT(61); FLATVERT(62); FLATVERT(63); endqstrip(); } stopclock(events/31,31,"quads"); shademodel(GOURAUD); } indflat() { register i; register float *fp; czclear(0,0); cpack(0xffffffff); shademodel(FLAT); startclock(); for (i=events/4; i>0; i--) { fp = meshbuf; bgnpolygon(); FLATVERT(0); FLATVERT(1); FLATVERT(2); endpolygon(); bgnpolygon(); FLATVERT(0); FLATVERT(1); FLATVERT(2); endpolygon(); bgnpolygon(); FLATVERT(0); FLATVERT(1); FLATVERT(2); endpolygon(); bgnpolygon(); FLATVERT(0); FLATVERT(1); FLATVERT(2); endpolygon(); } stopclock(events,1,"triangles"); shademodel(GOURAUD); } struct tms tbuf; long gtime; startclock() { sleep(1); finish(); gtime = times(&tbuf); } stopclock(meshes,tripermesh,s) long meshes,tripermesh; char *s; { float period; float timepermesh; float rate, crate; int callspermesh; finish(); callspermesh = 2*tripermesh + 6; period = (float)(times(&tbuf) - gtime) / 100.0; timepermesh = period / (float)meshes; rate = (float)tripermesh / timepermesh; fprintf(OUTFILE," %2d %s per mesh: %6d %s per second\n", tripermesh, s, (int)rate, s); fflush(OUTFILE); interrupt(); } float brass[] = { AMBIENT, 0.35, 0.25, 0.1, DIFFUSE, 0.65, 0.5, 0.35, SPECULAR, 0.0, 0.0, 0.0, SHININESS, 5.0, LMNULL }; float whitelight[] = { AMBIENT, 0.0, 0.0, 0.0, LCOLOR, 1.0, 1.0, 1.0, POSITION, 0.0, 0.0, 1.0, 0.0, LMNULL }; float infinite[] = { AMBIENT, 0.3, 0.3, 0.3, LOCALVIEWER, 0.0, LMNULL }; float idmat[] = { 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 }; initlight() { /* provide a simple lighting model just for timing purposes */ long xsize,ysize; getsize(&xsize,&ysize); mmode(MPROJECTION); ortho(-0.5,(float)xsize-0.5,-0.5,(float)ysize-0.5,0.0,10000.0); mmode(MVIEWING); loadmatrix(idmat); lmdef(DEFMATERIAL, 1, 0, brass); lmdef(DEFLIGHT, 1, 0, whitelight); lmdef(DEFLMODEL, 1, 0, infinite); lmbind(LIGHT1, 1); lmbind(LMODEL, 1); } light(b) { /* turn lighting on and off */ if (dolighting) lmbind(MATERIAL, b ? 1 : 0); else cpack(0xffffffff); } interrupt() { /* check queue for escape key and exit if found */ short dev,val; while (qtest()) { if (qread(&val) == ESCKEY) { exit(0); } } } timestamp() { /* print host name and time/date */ char s[100]; char gv[100]; time_t t; gethostname(s,100); gversion(gv); t = time(0); fprintf(OUTFILE,"running on %s, %s, %s",s,gv,ctime(&t)); }