Gouraud Sample/Gouraud Triangle.cp

/*
    File:       Gouraud Triangle.cp
 
    Contains:   
 
    Written by: Timothy Carroll 
 
    Copyright:  Copyright © 1998-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 <RAVE.h>
#include "Common Stuff.h"
#include "RAVE Utilities.h"
#include <Fonts.h>
#include <Windows.h>
#include <Menus.h>
#include <TextEdit.h>
#include <Dialogs.h>
#include <Memory.h>
 
// Standard declarations
void main (void);
void DoRAVEWindow(void);
 
 
void main (void)
{
    // do standard mac init
    InitGraf(&qd.thePort);
    InitFonts();
    InitWindows();
    InitMenus();
    TEInit();
    InitDialogs(nil);
    InitCursor();
 
    MaxApplZone();
    MoreMasters(); MoreMasters(); MoreMasters(); MoreMasters(); MoreMasters();
 
    // Initialize the SIN and COS lookup tables (see RAVE Utilities.cp)
    if (InitializeLookups() == noErr)
        DoRAVEWindow();
}
 
 
void DoRAVEWindow(void)
{
    // These hold our errors
    OSErr           theErr = noErr;
    TQAError        theQAErr = kQANoErr;
    
    // These hold the window and device we'll put on the screen
    GDHandle        device = NULL;
    WindowRef       theWindow = NULL;
    
    // We try to center the window on the device.
    Rect            bounds = {0,0,320,320};
    Rect            deviceRect;
    
    // We use these parameters to describe our environment to RAVE
    TQADevice       qaDevice;
    TQARect         qaBoundsRect;
    
    // we get these items back from RAVE
    TQAEngine       *theEngine = NULL;
    TQADrawContext  *theContext = NULL;
    
    // We use these in our drawing loop to create our RAVE animation.
    int             loop = 0;
    TQAVGouraud     theTriangle[3];
    
    RgnHandle       gray;
    Rect            grayRect;
    
    
    // First, grab the first monitor with the deepest display
    gray = GetGrayRgn();
    grayRect = (**gray).rgnBBox;
    device = GetMaxDevice(&grayRect);
    FAIL_NIL (device, "\pERROR: No monitors found")
    
    // Center our bounds in the middle of the screen.
    deviceRect = (**device).gdRect;
 
    OffsetRect (&bounds,
                    (deviceRect.right+deviceRect.left-bounds.right)/2,
                    (deviceRect.bottom+deviceRect.top-bounds.bottom)/2);
    
    // Create a Window to hold the RAVE information.
        
    theWindow = NewCWindow(NULL, &bounds, "\pRAVE Window", true, zoomDocProc, (WindowRef) -1, false, 0);
    FAIL_NIL (theWindow, "\pERROR: Couldn't create RAVE Window")
    
    SetPortWindowPort (theWindow);
    
    // Next we need to find a RAVE engine and then build a DrawContext to draw into it.  First, we'll find
    // an engine that is capable of drawing to the selected GDevice.
 
    qaDevice.deviceType = kQADeviceGDevice;
    qaDevice.device.gDevice = device;
    
    // We have to explicitly enable the Apple hardware card because it isn't 100% RAVE compliant.
    // If we use this engine, we have to write special case code to deal with it.
#if qEnableAppleHardware
    QAEngineEnable (kQAVendor_Apple,kQAEngine_AppleHW);
#endif
    
    // We'll just grab the first engine that the system offers us.
 
    theEngine = QADeviceGetFirstEngine (&qaDevice);
    FAIL_NIL (theEngine, "\pERROR:  No RAVE engines available.")
    
    // Next we need to set up the a QARect with the Window's rectangle in GDevice local coordinates.
    
    qaBoundsRect.left = bounds.left - deviceRect.left;
    qaBoundsRect.right = bounds.right  - deviceRect.left;
    qaBoundsRect.top = bounds.top - deviceRect.top;
    qaBoundsRect.bottom = bounds.bottom - deviceRect.top;
 
    // If we wanted to create a clipping region, we'd do it here
    
    // Finally, we're ready to create the draw context!
    theQAErr = QADrawContextNew (&qaDevice, &qaBoundsRect, NULL, theEngine, 
                                 kQAContext_DeepZ | kQAContext_DoubleBuffer, &theContext);
    if (theQAErr != kQANoErr) SIGNAL_ERROR("\pERROR:  Failed to create RAVE draw context")
    FAIL_NIL (theContext, "\pERROR:  Failed to create RAVE draw context")
    
    // set the background to black
    QASetFloat (theContext, kQATag_ColorBG_a, 1.0);
    QASetFloat (theContext, kQATag_ColorBG_r, 0.0);
    QASetFloat (theContext, kQATag_ColorBG_g, 0.0);
    QASetFloat (theContext, kQATag_ColorBG_b, 0.0);
    
    // Finally, everything is ready!  We'll create an animated sequence and end it when the user
    // presses a button.
    
 
    while (!Button())
    {
    // Set up our points
    theTriangle[0].x = 160 + 150*gCosArray[loop];
    theTriangle[0].y = 160 + 150*gSinArray[loop];
    theTriangle[0].z = 0.25;
    theTriangle[0].invW = 1.0;
    theTriangle[0].a = 1;
    theTriangle[0].r = 1.0;
    theTriangle[0].g = 0.0;
    theTriangle[0].b = 0.0;
    
    theTriangle[1].x = 160 + 150*gCosArray[(loop+240) % 720];
    theTriangle[1].y = 160 + 150*gSinArray[(loop+240) % 720];
    theTriangle[1].z = 0.25;
    theTriangle[1].invW = 1.0;
    theTriangle[1].a = 1;
    theTriangle[1].r = 0.0;
    theTriangle[1].g = 1.0;
    theTriangle[1].b = 0.0; 
    
    theTriangle[2].x = 160 + 150*gCosArray[(loop+480) % 720];
    theTriangle[2].y = 160 + 150*gSinArray[(loop+480) % 720];
    theTriangle[2].z = 0.25;
    theTriangle[2].invW = 1.0;
    theTriangle[2].a = 1;
    theTriangle[2].r = 0.0;
    theTriangle[2].g = 0.0;
    theTriangle[2].b = 1.0; 
 
    // Render the triangle.
    QARenderStart (theContext, NULL, NULL);
    QADrawTriGouraud (theContext, &theTriangle[0], &theTriangle[1], &theTriangle[2], kQATriFlags_None);
    QARenderEnd(theContext, NULL);  
    
    // Increment our loop position 2.5 degrees
    loop = (loop+5) % 720;
    }
    
    error:
    // Either we got an error or the user finished.  In any case, tear everything down and return
    
    if (theContext != NULL)
        QADrawContextDelete (theContext);
    if (theWindow != NULL)
        DisposeWindow(theWindow);
    return;
}