Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
RAVE CommonCode/RAVE Utilities.cp
/* |
File: RAVE Utilities.cp |
Contains: RAVE Utilities defines a number of useful functions for working with RAVE, |
including functions to find the deepest GDevice, loading textures from a PICT |
resource, and so on. Essentially, it defines a number of pieces of common code |
that were useful to many of my projects. |
Written by: Timothy Carroll |
Copyright: Copyright ©1996-1999 by Apple Computer, Inc., All Rights Reserved. |
You may incorporate this Apple sample source code into your program(s) without |
restriction. This Apple sample source code has been provided "AS IS" and the |
responsibility for its operation is yours. You are not permitted to redistribute |
this Apple sample source code as "Apple sample source code" after having made |
changes. If you're going to re-distribute the source, we require that you make |
it clear in the source that the code was descended from Apple sample source |
code, but that you've made changes. |
Change History (most recent first): |
7/15/1999 Karl Groethe Updated for Metrowerks Codewarror Pro 2.1 |
*/ |
#include <fp.h> |
#include "Rave Utilities.h" |
#include "common stuff.h" |
#include <Memory.h> |
#include <Resources.h> |
/***************************************************************************** |
LOOKUP TABLES |
I use SIN and COS in a number of places, and we don't need perfect precision, |
so we generate a set of lookup tables on 0.5 degree increments. Most of the |
3D math routines use these lookups to generate matrices. |
*****************************************************************************/ |
float gSinArray[721]; // [720] = [0] |
float gCosArray[721]; // [720] = [0] |
OSStatus InitializeLookups(void) |
{ |
int loop; |
for (loop = 0; loop < 720; loop++) |
{ |
double angle = (loop * 0.5)/57.296; |
gSinArray[loop] = sin (angle); |
gCosArray[loop] = cos (angle); |
} |
gSinArray[720] = gSinArray[0]; |
gCosArray[720] = gCosArray[0]; |
return noErr; |
} |
/***************************************************************************** |
RAVE ENGINE FUNCTIONS |
FindTextureMappingEngine walks the list of available engines and returns |
the first engine capable of Texture Mapping that will run on the device. |
GetListOfEngines creates a handle filled with references to all engines |
available to the application that run on the GDevice passed in the routine. |
Pass in NULL to find all engines. |
*****************************************************************************/ |
TQAEngine *FindTextureMappingEngine (TQADevice *device) |
{ |
TQAEngine *engine = NULL; |
TQAError theQAErr = kQANoErr; |
unsigned long features; |
engine = QADeviceGetFirstEngine (device); |
while (engine != NULL) |
{ |
theQAErr = QAEngineGestalt (engine, |
kQAGestalt_OptionalFeatures, |
&features); |
if ((theQAErr == kQANoErr) && (features & kQAOptional_Texture)) |
return engine; |
engine = QADeviceGetNextEngine (device, engine); |
} |
// Failed to find an engine that supports texture mapping |
return NULL; |
} |
OSStatus GetListOfEngines (GDHandle screen, Handle *list, long *number) |
{ |
OSStatus theErr = noErr; |
TQAError theQAErr = kQANoErr; |
long loop, tempCount; |
Handle tempList; |
// We need a device structure to build the list of engines. |
// We only need to set it up if we were passed a GDevice. |
TQADevice device, *devicePtr = NULL; |
TQAEngine *engine; |
if (screen) |
{ |
device.deviceType = kQADeviceGDevice; |
device.device.gDevice = screen; |
devicePtr = &device; |
} |
// We walk the list of engines twice. First, we count the number |
// of engines, and allocate a handle large enough to hold the |
// engine references. Second, we walk the list a second time and |
// stuff the handle. |
// The software engine should always be available, so I consider |
// a count of 0 to be an error. |
tempCount = 0; |
engine = QADeviceGetFirstEngine (devicePtr); |
while (engine != NULL) |
{ |
tempCount++; |
engine = QADeviceGetNextEngine (devicePtr, engine); |
} |
if (tempCount == 0) |
SIGNAL_ERROR ("\pERROR: No Engines available for this GDevice") |
// Allocate a handle for the list. |
tempList = NewHandle (tempCount * sizeof (TQAEngine *)); |
theErr = MemError(); |
FAIL_OSERR (theErr, "\pError:Unable to allocate a handle for the engine list") |
FAIL_NIL(tempList, "\pError:Unable to allocate a handle for the engine list") |
// Walk the list again and stuff the references into the handle |
engine = QADeviceGetFirstEngine (devicePtr); |
for (loop = 0; loop < tempCount; loop++) |
{ |
(*(TQAEngine ***)tempList)[loop] = engine; |
engine = QADeviceGetNextEngine (devicePtr, engine); |
} |
// Everything went successfully, fill in the list and count and return no error; |
*list = tempList; |
*number = tempCount; |
goto cleanup; |
error: |
// If an error occurred, clear the list and return the error. |
if (theErr == noErr) |
theErr = paramErr; |
if (tempList) |
DisposeHandle (tempList); |
*list = NULL; |
*number = 0; |
cleanup: |
return theErr; |
} |
TQATexture *LoadTextureFromPictResource (TQAEngine *engine, short pictID) |
{ |
TQAError theQAErr = kQANoErr; |
OSStatus theErr = noErr; |
TQAImage image; |
TQATexture *texture= NULL; |
PicHandle picture = NULL; |
Rect pictRect; |
GWorldPtr pictWorld = NULL; |
PixMapHandle pictPix = NULL; |
CGrafPtr savePort = NULL; |
GDHandle saveDevice = NULL; |
// Load the texture from the resource; |
picture = GetPicture (pictID); |
theErr = ResError(); |
FAIL_NIL (picture, "\pERROR: Failed to load the texture resource") |
FAIL_OSERR (theErr,"\pERROR: Failed to load the texture resource") |
// for now, we assume that the PICT is a valid size -- that is, |
// it should be a power of 2 in both dimensions. |
// Create a 32-bit GWorld to hold the pix map data. |
pictRect = (**picture).picFrame; |
OffsetRect (&pictRect, -pictRect.left, -pictRect.top); |
theErr = NewGWorld(&pictWorld, 32, &pictRect, NULL, NULL, NULL); |
FAIL_OSERR (theErr, "\pERROR:Couldn't create the texture gworld") |
FAIL_NIL (pictWorld,"\pERROR:Couldn't create the texture gworld") |
pictPix = GetGWorldPixMap (pictWorld); |
FAIL_NIL (pictPix, "\pERROR:Couldn't retrieve the texture PixMap") |
FAIL_FALSE (LockPixels (pictPix),"\pERROR:Couldn't lock the texture PixMap") |
// Draw the picture into the GWorld |
GetGWorld (&savePort, &saveDevice); |
SetGWorld (pictWorld, NULL); |
DrawPicture(picture, &pictRect); |
SetGWorld (savePort, saveDevice); |
// Fill in the image structure to describe our GWorld and create the texture |
image.width = pictRect.right; |
image.height = pictRect.bottom; |
image.rowBytes = (**pictPix).rowBytes & 0x3FFF; |
image.pixmap = GetPixBaseAddr (pictPix); |
// Create the texture and detach it so that the engine is responsible for it |
theQAErr = QATextureNew (engine,kQATexture_None ,kQAPixel_RGB32,&image, &texture); |
if (theQAErr != kQANoErr) SIGNAL_ERROR ("\pError: RAVE failed to allocate the texture") |
theQAErr = QATextureDetach (engine, texture); |
if (theQAErr != kQANoErr) SIGNAL_ERROR ("\pError: RAVE failed to detach the texture") |
// We're done -- jump to the cleanup code and return. |
goto cleanup; |
error: |
// We hit an error, so we need to make sure we cleanup |
// everything and return a NULL texture |
if (texture != NULL) |
QATextureDelete (engine, texture); |
texture = NULL; |
cleanup: |
if (picture != NULL) |
ReleaseResource ((Handle) picture); |
if (pictWorld != NULL) |
DisposeGWorld (pictWorld); |
return texture; |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14