[comp.sys.mac.programmer] Improvement to Ray Tracer

oster@dewey.soe.berkeley.edu (David Phillip Oster) (06/11/89)

Comp.sys.mac.binaries recently saw a ray tracer posting. The ray tracer
produces a file with the ascii string:
"420 320\r" followed by 420x320 bytes of binary data. The ray tracer is
accompanied by a short program to show this file on your screen.  This
posting includes a replacement for that program.

To build it, you'll need lightspeed C. Make a project consisting of this
file and MacTraps. You don't need any other libraries. You don't need any
 .rsrc file.

The source is short, so if you are curious about color quickdraw, enjoy 
reading it.

/*  By David Oster June 10, 1989
	Once by Jason Castan - reads in a file called data.dis that was
	created by the ray tracer and then draws it. Needs colorQD to run.
	You should set your monitor to 256 colors before running this program.
	
	This version has been rewritten to:
	1.) be many times faster
	2.) allow compile time control of contrast through the constant CONTRAST
	3.) draw colors correctly, the original didn't actually change the palette
		(at least on my machine.)
	4.) allow you to click on other windows with multifinder
	5.) handle update events
	6.) if you uncomment the PumpContrast() routine, it will automatically crank
		through a set of contrasts.
*/
#include "EventMgr.h"
#include "color.h"
#include "windowmgr.h"

/* make this number 256 for no contrast correction,
	make it larger to turn up the contrast.
	2000L is about the useful maximum.
	 600L looks nice.
 */
#define CONTRAST (unsigned long) 256L

unsigned  LMin(a, b)unsigned long a, b;{ return (unsigned) (a < b ? a : b); }

PixMapHandle	myPixMap;
WindowPtr		wind;
PaletteHandle	mp;
CTabHandle		myCTable;
long 			lastTime; 
long			contrst = CONTRAST;

main(){
	Rect			bnds;
	int 			ref;
	long 			len;
	Handle 			h;


	FlushEvents(everyEvent, 0L);
	InitGraf( (Ptr) &thePort);
	InitFonts();
	InitWindows();
	InitCursor();
	InitDialogs(0L);
	InitMenus();
	TEInit();
	SetRect(&bnds, 0, 0, 420, 320);
	OffsetRect(&bnds, 20, 60);	/* move window away from menu bar */
	wind = (WindowPtr) NewCWindow(0L,&bnds,"\phi",FALSE,altDBoxProc,-1L,FALSE,0L);


	/* Create a new, empty, pixmap color table
	 */
	myCTable = (CTabHandle) NewHandle(2*sizeof(short) + sizeof(long) + 256L*sizeof(ColorSpec));
	if(myCTable == 0L)return;
	MoveHHi((Handle) myCTable);
	HLock(myCTable);
	(**myCTable).ctSeed = GetCTSeed();
	(**myCTable).ctFlags = 0;
	(**myCTable).ctSize = 255;

	SetPrimCTab(CONTRAST);

	/* and a matching palette
	 */
	mp = NewPalette(256, myCTable, pmTolerant, 0);
	if(mp == 0L)return;

	SetPalette(wind, mp, TRUE);
	ShowWindow(wind);

	OffsetRect(&bnds, -bnds.left, -bnds.top);	/* align pixmap with window */
	SetPort(wind);
	h = NewHandle(320*420L);
	if (h == 0L) return;
	MoveHHi(h);
	HLock(h);
	if(noErr != FSOpen("\pdata.dis", 0, &ref))return;
	len = 8;
	if(noErr != FSRead(ref, &len, *h)){	FSClose(ref); return;}
	len = 320*420L;
	if(noErr != FSRead(ref, &len, *h)){	FSClose(ref); return;}
	FSClose(ref);

	

	/* Create and fill in a pixmap.
	 */
	myPixMap = NewPixMap();
	if(myPixMap == 0L)return;
	(**myPixMap).bounds = bnds;
	(**myPixMap).rowBytes = 0x8000 | ((bnds.right-bnds.left));
	if((**myPixMap).pmTable != 0L)
		DisposHandle((**myPixMap).pmTable);
	(**myPixMap).pmTable = myCTable;
	(**myPixMap).pixelSize = 8;
	(**myPixMap).baseAddr = *h;

	MoveHHi((Handle) myPixMap);
	HLock((Handle) myPixMap);

	for(;;){
		OneEvent();
	}
}

/* SetPrimCTab - set the color table to uniform grays with this contrast value
	(but don't tell the Macintosh o.s. about it.)
 */
SetPrimCTab(contrst)long contrst;{
	int i;
	register ColorSpec *cspec;

	(**myCTable).ctSeed = GetCTSeed();
	cspec = &(**myCTable).ctTable[0];

	for(i = 0;i <256;i++, cspec++){
		cspec->value = i;
		cspec->rgb.red =
		cspec->rgb.blue =
		cspec->rgb.green = LMin(i*contrst, 0xFFFFL);
	}
}

/* SetPrimCTab - set the color table to uniform grays with this contrast value
 */
SetCTab(contrst)long contrst;{
	SetPrimCTab(contrst);
	CTab2Palette(myCTable, GetPalette(wind), pmTolerant, 0);
	ActivatePalette(wind);
}

/* OneEvent - quit on a mousedown. update the window as needed. 
	do nothing on other events.
 */
OneEvent(){
	EventRecord event;

	if(GetNextEvent(everyEvent, &event)){
		switch(event.what){
		case mouseDown:	ExitToShell();
		case updateEvt:
			SetCursor(&arrow);
			BeginUpdate((WindowPtr) event.message);
			CopyBits(*myPixMap, &thePort->portBits, &thePort->portRect, &thePort->portRect, srcCopy, 0L);
			EndUpdate((WindowPtr) event.message);
			lastTime = event.when;
			break;
		}
	}else{
		SystemTask();
		if(event.when - lastTime > 30){
			PumpContrast();
			lastTime = event.when;
		}
	}
}

/* PumpContrast - uncomment this if you want to see a little contrast animation.
 */
PumpContrast(){
#if 0
		if(contrst > 2000L){
			contrst = 256L;
		}else{
			contrst = (contrst*6L)/5L;
		}
		SetCTab(contrst);
#endif
}

pepke@loligo.cc.fsu.edu (Eric Pepke) (06/15/89)

I have written a program to display MTV ray tracer files of any size on a 
color Macintosh II in color using Paul Heckbert's median cut algorithm.  
It can save the resulting images and their palettes as NCSA Image files.  
It is still fairly primitive, but it works, and I have used it to produce 
several stills and one animation.  In most cases, the output is hard to
distinguish from full 24-bit RGB.

Some day I will distribute this widely, but right now I need beta testers.
If you are interested in beta testing this program or you have a favorite
RGB image file format that you would like to be able to read, send me
mail one of the addresses below.  Do not 'r'eply to this message; I might
never get the reply.

Eric Pepke                                     INTERNET: pepke@gw.scri.fsu.edu
Supercomputer Computations Research Institute  MFENET:   pepke@fsu
Florida State University                       SPAN:     scri::pepke
Tallahassee, FL 32306-4052                     BITNET:   pepke@fsu

Disclaimer: My employers seldom even LISTEN to my opinions.
Meta-disclaimer: Any society that needs disclaimers has too many lawyers.