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.
DZDisplay.c
/* |
* File: DZDisplay.c |
* |
* Contents: Handles the window and its contents. |
* |
* Copyright © 1996 Apple Computer, Inc. |
*/ |
#ifndef USE_DRAW_SPROCKET |
#define USE_DRAW_SPROCKET 1 |
#endif |
#if USE_DRAW_SPROCKET |
#define USE_PIXMAP_DRAW_CONTEXT 1 |
#endif |
#include <assert.h> |
#include <Fonts.h> |
#include <Quickdraw.h> |
#include <SegLoad.h> |
#include <Windows.h> |
#include <QD3D.h> |
#include <QD3DCamera.h> |
#include <QD3DDrawContext.h> |
#include <QD3DGroup.h> |
#include <QD3DLight.h> |
#include <QD3DMath.h> |
#include <QD3DRenderer.h> |
#include <QD3DShader.h> |
#include <QD3DView.h> |
#include "DZDisplay.h" |
#include "DZGame.h" |
#include "DZInput.h" |
#include "DZResource.h" |
#if USE_DRAW_SPROCKET |
#include "DrawSprocket.h" |
#endif |
#if USE_DRAW_SPROCKET |
static DSpContextReference gDisplayContext = NULL; |
#else |
static WindowPtr gDisplayWindow = NULL; |
#endif |
static Boolean gDisplayActive = false; |
static PicHandle gDisplayStartScreen = NULL; |
static TQ3ViewObject gDisplayView = NULL; |
static TQ3DrawContextObject gDisplayDrawContext = NULL; |
static TQ3RendererObject gDisplayRenderer = NULL; |
static TQ3CameraObject gDisplayCamera = NULL; |
static TQ3GroupObject gDisplayLightGroup = NULL; |
static TQ3LightObject gDisplayAmbientLight = NULL; |
static TQ3LightObject gDisplayDirectionalLight = NULL; |
static TQ3LightObject gDisplayPointLight = NULL; |
static TQ3ShaderObject gDisplayIllumination = NULL; |
//¥ To get around an Interactive Renderer bug wherein Q3Renderer_Sync |
//¥ crashes when called on a renderer that has not rendered. |
static Boolean gDisplayHasRendered = false; |
static void Display_RenderImage( |
void); |
static void Display_BeginQD( |
void); |
static void Display_EndQD( |
void); |
static void Display_GetImageArea( |
TQ3Area* outArea); |
static float Display_GetImageAspectRatio( |
void); |
/* ============================================================================= |
* Display_Init (external) |
* |
* Creates the display window, initializes QD3D view etc. to draw in it. |
* ========================================================================== */ |
void Display_Init( |
void) |
{ |
OSStatus err = noErr; |
TQ3ViewAngleAspectCameraData viewAngleCameraData; |
TQ3PointLightData pointLightData; |
TQ3ColorRGB white = {1.0, 1.0, 1.0}; |
// Grab the start screen |
gDisplayStartScreen = GetPicture(kPictID_StartScreen); |
// Create the view |
gDisplayView = Q3View_New(); |
// Set up where to draw |
#if USE_DRAW_SPROCKET |
{ |
DSpContextAttributes attributes; |
DSpContextAttributes actual; |
DSpStartup(); |
// Create the display |
attributes.frequency = 0; |
attributes.displayWidth = 512; |
attributes.displayHeight = 384; |
attributes.reserved1 = 0; |
attributes.reserved2 = 0; |
attributes.colorNeeds = kDSpColorNeeds_Request; |
attributes.colorTable = NULL; |
attributes.contextOptions = 0; //¥ kDSpContextOption_QD3DAccel |
attributes.backBufferDepthMask = kDSpDepthMask_32 | kDSpDepthMask_16; |
attributes.displayDepthMask = kDSpDepthMask_32 | kDSpDepthMask_16; |
attributes.backBufferBestDepth = 16; |
attributes.displayBestDepth = 16; |
attributes.pageCount = 1; |
attributes.gameMustConfirmSwitch = false; |
attributes.reserved3[0] = 0; |
attributes.reserved3[1] = 0; |
attributes.reserved3[2] = 0; |
attributes.reserved3[3] = 0; |
err = DSpFindBestContext(&attributes, &gDisplayContext); |
if (err != noErr || gDisplayContext == NULL) |
{ |
//¥ PUT UP AN ALERT INDICATING THAT THERE ISN'T A |
//¥ DEVICE GOOD ENOUGH TO RUN ON. |
ExitToShell(); |
} |
DSpContext_Reserve(gDisplayContext, &attributes); |
DSpContext_FadeGammaOut(NULL, NULL); |
DSpContext_SetState(gDisplayContext, kDSpContextState_Active); |
Display_DrawContents(); |
DSpContext_FadeGammaIn(NULL, NULL); |
DSpContext_GetAttributes(gDisplayContext, &actual); |
#if USE_PIXMAP_DRAW_CONTEXT |
{ |
GWorldPtr theGWorld; |
PixMapHandle pixMapHandle; |
TQ3PixmapDrawContextData pixmapDrawContextData; |
// Create the pixmap draw context with the image pointing to our back buffer |
DSpContext_GetBackBuffer(gDisplayContext, kDSpBufferKind_Normal, &theGWorld); |
pixMapHandle = GetGWorldPixMap(theGWorld); |
pixmapDrawContextData.drawContextData.clearImageMethod = kQ3ClearMethodWithColor; |
pixmapDrawContextData.drawContextData.clearImageColor.a = 1.0; |
pixmapDrawContextData.drawContextData.clearImageColor.r = 0.0; |
pixmapDrawContextData.drawContextData.clearImageColor.g = 0.0; |
pixmapDrawContextData.drawContextData.clearImageColor.b = 0.0; |
pixmapDrawContextData.drawContextData.paneState = kQ3False; |
pixmapDrawContextData.drawContextData.maskState = kQ3False; |
pixmapDrawContextData.drawContextData.doubleBufferState = kQ3True; |
pixmapDrawContextData.pixmap.image = GetPixBaseAddr(pixMapHandle); |
pixmapDrawContextData.pixmap.width = attributes.displayWidth; |
pixmapDrawContextData.pixmap.height = attributes.displayHeight; |
pixmapDrawContextData.pixmap.rowBytes = (*pixMapHandle)->rowBytes & 0x00003FFF; |
pixmapDrawContextData.pixmap.pixelSize = actual.displayBestDepth; |
pixmapDrawContextData.pixmap.bitOrder = kQ3EndianBig; |
pixmapDrawContextData.pixmap.byteOrder = kQ3EndianBig; |
switch (pixmapDrawContextData.pixmap.pixelSize) |
{ |
case 16: |
pixmapDrawContextData.pixmap.pixelType = kQ3PixelTypeRGB16; |
break; |
case 32: |
pixmapDrawContextData.pixmap.pixelType = kQ3PixelTypeRGB32; |
break; |
default: |
assert(0); |
} |
gDisplayDrawContext = Q3PixmapDrawContext_New(&pixmapDrawContextData); |
} |
#else |
{ |
TQ3MacDrawContextData macDrawContextData; |
// Create the mac draw context with the port pointing to our back buffer |
macDrawContextData.drawContextData.clearImageMethod = kQ3ClearMethodWithColor; |
macDrawContextData.drawContextData.clearImageColor.a = 1.0; |
macDrawContextData.drawContextData.clearImageColor.r = 0.0; |
macDrawContextData.drawContextData.clearImageColor.g = 0.0; |
macDrawContextData.drawContextData.clearImageColor.b = 0.0; |
macDrawContextData.drawContextData.maskState = kQ3False; |
macDrawContextData.drawContextData.paneState = kQ3False; |
macDrawContextData.drawContextData.doubleBufferState = kQ3True; |
macDrawContextData.library = kQ3Mac2DLibraryNone; |
macDrawContextData.viewPort = NULL; |
macDrawContextData.grafPort = NULL; |
GetDisplayBackBuffer(gDisplayContext, &macDrawContextData.window); |
gDisplayDrawContext = Q3MacDrawContext_New(&macDrawContextData); |
} |
#endif |
} |
#else |
{ |
TQ3MacDrawContextData macDrawContextData; |
// Create the window |
gDisplayWindow = GetNewCWindow(kWindID_Display, NULL, (WindowPtr)(-1)); |
// Create the draw context |
macDrawContextData.drawContextData.clearImageMethod = kQ3ClearMethodWithColor; |
macDrawContextData.drawContextData.clearImageColor.a = 1.0; |
macDrawContextData.drawContextData.clearImageColor.r = 0.0; |
macDrawContextData.drawContextData.clearImageColor.g = 0.0; |
macDrawContextData.drawContextData.clearImageColor.b = 0.0; |
macDrawContextData.drawContextData.maskState = kQ3False; |
macDrawContextData.library = kQ3Mac2DLibraryNone; |
macDrawContextData.drawContextData.paneState = kQ3True; |
macDrawContextData.drawContextData.doubleBufferState = kQ3True; |
macDrawContextData.window = (CGrafPtr) gDisplayWindow; |
Display_GetImageArea(&macDrawContextData.drawContextData.pane); |
gDisplayDrawContext = Q3MacDrawContext_New(&macDrawContextData); |
} |
#endif |
Q3View_SetDrawContext(gDisplayView, gDisplayDrawContext); |
// Create the renderer |
#if 1 |
gDisplayRenderer = Q3Renderer_NewFromType(kQ3RendererTypeInteractive); |
Q3InteractiveRenderer_SetDoubleBufferBypass(gDisplayRenderer, kQ3True); |
#else |
gDisplayRenderer = Q3Renderer_NewFromType(kQ3RendererTypeWireframe); |
#endif |
Q3View_SetRenderer(gDisplayView, gDisplayRenderer); |
// Create the camera |
viewAngleCameraData.cameraData.placement.cameraLocation.x = 0.0; |
viewAngleCameraData.cameraData.placement.cameraLocation.y = 0.0; |
viewAngleCameraData.cameraData.placement.cameraLocation.z = 0.0; |
viewAngleCameraData.cameraData.placement.pointOfInterest.x = 1.0; |
viewAngleCameraData.cameraData.placement.pointOfInterest.y = 0.0; |
viewAngleCameraData.cameraData.placement.pointOfInterest.z = 0.0; |
viewAngleCameraData.cameraData.placement.upVector.x = 0.0; |
viewAngleCameraData.cameraData.placement.upVector.y = 1.0; |
viewAngleCameraData.cameraData.placement.upVector.z = 0.0; |
viewAngleCameraData.cameraData.range.hither = 0.2; |
viewAngleCameraData.cameraData.range.yon = 200.0; |
viewAngleCameraData.cameraData.viewPort.origin.x = -1.0; |
viewAngleCameraData.cameraData.viewPort.origin.y = 1.0; |
viewAngleCameraData.cameraData.viewPort.width = 2.0; |
viewAngleCameraData.cameraData.viewPort.height = 2.0; |
viewAngleCameraData.fov = 1.2; |
viewAngleCameraData.aspectRatioXToY = Display_GetImageAspectRatio(); |
gDisplayCamera = Q3ViewAngleAspectCamera_New(&viewAngleCameraData); |
Q3View_SetCamera(gDisplayView, gDisplayCamera); |
// Create the light group |
gDisplayLightGroup = Q3LightGroup_New(); |
Q3View_SetLightGroup(gDisplayView, gDisplayLightGroup); |
// Create the point light |
pointLightData.lightData.isOn = kQ3True; |
pointLightData.lightData.brightness = 5.0; |
pointLightData.lightData.color = white; |
pointLightData.castsShadows = kQ3True; |
pointLightData.attenuation = kQ3AttenuationTypeInverseDistance; |
pointLightData.location.x = 0.0; |
pointLightData.location.y = 0.0; |
pointLightData.location.z = 0.0; |
gDisplayPointLight = Q3PointLight_New(&pointLightData); |
Q3Group_AddObject(gDisplayLightGroup, gDisplayPointLight); |
// Create the illumination shader |
#if 1 |
gDisplayIllumination = Q3PhongIllumination_New(); |
#else |
gDisplayIllumination = Q3LambertIllumination_New(); |
#endif |
} |
/* ============================================================================= |
* Display_Exit (external) |
* |
* Takes down the window, disposes of the QD3D stuff. |
* ========================================================================== */ |
void Display_Exit( |
void) |
{ |
if (gDisplayHasRendered) |
{ |
// Q3Renderer_Sync(gDisplayRenderer, gDisplayView); |
Q3View_Sync(gDisplayView); |
} |
#if USE_DRAW_SPROCKET |
if(gDisplayContext != NULL) |
{ |
DSpContext_FadeGammaOut(NULL, NULL); |
DSpContext_Release(gDisplayContext); |
DSpContext_SetState(gDisplayContext, kDSpContextState_Active); |
DSpContext_FadeGammaIn(NULL, NULL); |
gDisplayContext = NULL; |
} |
DSpShutdown(); |
#else |
if (gDisplayWindow != NULL) |
{ |
DisposeWindow(gDisplayWindow); |
gDisplayWindow = NULL; |
} |
#endif |
if (gDisplayView != NULL) |
{ |
Q3Object_Dispose(gDisplayView); |
gDisplayView = NULL; |
} |
if (gDisplayDrawContext != NULL) |
{ |
Q3Object_Dispose(gDisplayDrawContext); |
gDisplayDrawContext = NULL; |
} |
if (gDisplayRenderer != NULL) |
{ |
Q3Object_Dispose(gDisplayRenderer); |
gDisplayRenderer = NULL; |
} |
if (gDisplayCamera != NULL) |
{ |
Q3Object_Dispose(gDisplayCamera); |
gDisplayCamera = NULL; |
} |
if (gDisplayLightGroup != NULL) |
{ |
Q3Object_Dispose(gDisplayLightGroup); |
gDisplayLightGroup = NULL; |
} |
if (gDisplayAmbientLight != NULL) |
{ |
Q3Object_Dispose(gDisplayAmbientLight); |
gDisplayAmbientLight = NULL; |
} |
if (gDisplayDirectionalLight != NULL) |
{ |
Q3Object_Dispose(gDisplayDirectionalLight); |
gDisplayDirectionalLight = NULL; |
} |
if (gDisplayPointLight != NULL) |
{ |
Q3Object_Dispose(gDisplayPointLight); |
gDisplayPointLight = NULL; |
} |
if (gDisplayIllumination != NULL) |
{ |
Q3Object_Dispose(gDisplayIllumination); |
gDisplayIllumination = NULL; |
} |
} |
/* ============================================================================= |
* Display_Activate (external) |
* |
* Handles activation and deactivation. |
* ========================================================================== */ |
void Display_Activate( |
Boolean inActivate) |
{ |
if (gDisplayActive != inActivate) |
{ |
gDisplayActive = inActivate; |
Input_Activate(inActivate); |
if (!gDisplayActive) |
{ |
Game_Silence(); |
} |
if (gDisplayHasRendered) |
{ |
// Q3Renderer_Sync(gDisplayRenderer, gDisplayView); |
Q3View_Sync(gDisplayView); |
} |
Display_DrawGrow(); |
} |
} |
/* ============================================================================= |
* Display_IsActive (external) |
* |
* Returns true if the game is active. |
* ========================================================================== */ |
Boolean Display_IsActive( |
void) |
{ |
#if USE_DRAW_SPROCKET |
return true; |
#else |
return gDisplayActive; |
#endif |
} |
/* ============================================================================= |
* Display_DrawGrow (external) |
* |
* Draws the grow box. |
* ========================================================================== */ |
void Display_DrawGrow( |
void) |
{ |
#if !USE_DRAW_SPROCKET |
Rect bounds; |
SetPort(gDisplayWindow); |
// Erase the horizontal part |
bounds = gDisplayWindow->portRect; |
bounds.top = bounds.bottom-15; |
EraseRect(&bounds); |
// Draw the grow box, but only the horizontal scroll stuff |
ClipRect(&bounds); |
DrawGrowIcon(gDisplayWindow); |
ClipRect(&gDisplayWindow->portRect); |
#endif |
} |
/* ============================================================================= |
* Display_DrawContents (external) |
* |
* Draws the contents of the window. |
* ========================================================================== */ |
void Display_DrawContents( |
void) |
{ |
TQ3Area area; |
FontInfo fontInfo; |
Rect bounds; |
Rect bounds1; |
static Str255 pausedString = "\pPaused"; //¥ SHOULD COME FROM RESOURCE |
switch (Game_GetState()) |
{ |
case kGameState_Playing: |
Display_RenderImage(); |
break; |
case kGameState_Paused: |
Display_RenderImage(); |
Display_BeginQD(); |
Display_GetImageArea(&area); |
TextFont(kFontIDGeneva); |
TextFace(bold); |
TextSize(72); |
GetFontInfo(&fontInfo); |
MoveTo( |
area.min.x + 0.5*(area.min.x + area.max.x - StringWidth(pausedString)), |
area.min.y + 0.5*(area.min.y + area.max.y + fontInfo.ascent)); |
ForeColor(redColor); |
DrawString(pausedString); |
ForeColor(blackColor); |
Display_EndQD(); |
break; |
case kGameState_Stopped: |
Display_BeginQD(); |
Display_GetImageArea(&area); |
bounds.top = area.min.y; |
bounds.left = area.min.x; |
bounds.bottom = area.max.y; |
bounds.right = area.max.x; |
PaintRect(&bounds); |
bounds1 = (*gDisplayStartScreen)->picFrame; |
OffsetRect( |
&bounds1, |
((bounds.right-bounds.left) - (bounds1.right-bounds1.left) >> 1) - bounds1.left, |
((bounds.bottom-bounds.top) - (bounds1.bottom-bounds1.top) >> 1) - bounds1.top); |
DrawPicture(gDisplayStartScreen, &bounds1); |
Display_EndQD(); |
break; |
} |
} |
/* ============================================================================= |
* Display_RenderImage (internal) |
* |
* Draws the 3D part of the window. |
* ========================================================================== */ |
void Display_RenderImage( |
void) |
{ |
Q3View_StartRendering(gDisplayView); |
do |
{ |
// Set up the rendering state |
Q3InterpolationStyle_Submit(kQ3InterpolationStyleVertex, gDisplayView); |
Q3BackfacingStyle_Submit(kQ3BackfacingStyleFlip, gDisplayView); |
Q3FillStyle_Submit(kQ3FillStyleFilled, gDisplayView); |
Q3Object_Submit(gDisplayIllumination, gDisplayView); |
// Draw the game contents |
Game_Submit(gDisplayView); |
} |
while (Q3View_EndRendering(gDisplayView) == kQ3ViewStatusRetraverse); |
gDisplayHasRendered = true; |
#if USE_DRAW_SPROCKET |
// we don't need to swap buffers because we're single buffered |
#endif |
} |
/* ============================================================================= |
* Display_Resize (external) |
* |
* Called after the window has changed size. |
* ========================================================================== */ |
void Display_Resize( |
void) |
{ |
#if !USE_DRAW_SPROCKET |
TQ3Area imageArea; |
// Reset the clip |
ClipRect(&gDisplayWindow->portRect); |
// Change the draw context |
Display_GetImageArea(&imageArea); |
Q3DrawContext_SetPane(gDisplayDrawContext, &imageArea); |
// Change the camera aspect ratio |
Q3ViewAngleAspectCamera_SetAspectRatio(gDisplayCamera, Display_GetImageAspectRatio()); |
#endif |
} |
/* ============================================================================= |
* Display_GetWindow (external) |
* |
* Returns our window pointer. |
* ========================================================================== */ |
WindowPtr Display_GetWindow( |
void) |
{ |
#if USE_DRAW_SPROCKET |
return NULL; |
#else |
return gDisplayWindow; |
#endif |
} |
/* ============================================================================= |
* Display_SetViewerPosition (external) |
* |
* Moves the camera and point light based on the given info. |
* ========================================================================== */ |
void Display_SetViewerPosition( |
const TQ3Point3D* inPosition, |
const TQ3Vector3D* inDirection, |
const TQ3Vector3D* inUp) |
{ |
TQ3CameraPlacement placement; |
assert(inPosition != NULL); |
assert(inDirection != NULL); |
assert(inUp != NULL); |
// Move the camera |
placement.cameraLocation = *inPosition; |
placement.upVector = *inUp; |
Q3Point3D_Vector3D_Add(inPosition, inDirection, &placement.pointOfInterest); |
Q3Camera_SetPlacement(gDisplayCamera, &placement); |
// Move the point light |
Q3PointLight_SetLocation(gDisplayPointLight, inPosition); |
} |
/* ============================================================================= |
* Display_GetViewerPosition (external) |
* |
* Returns the current camera position. |
* ========================================================================== */ |
void Display_GetViewerPosition( |
TQ3Point3D* outPosition, |
TQ3Vector3D* outDirection, |
TQ3Vector3D* outUp) |
{ |
TQ3CameraPlacement placement; |
assert(outPosition != NULL); |
assert(outDirection != NULL); |
assert(outUp != NULL); |
Q3Camera_GetPlacement(gDisplayCamera, &placement); |
*outPosition = placement.cameraLocation; |
*outUp = placement.upVector; |
Q3Point3D_Subtract( |
&placement.pointOfInterest, |
&placement.cameraLocation, |
outDirection); |
} |
/* ============================================================================= |
* Display_GetImageArea (internal) |
* |
* Sets outArea to the area occupied by the 3D image part of the window. |
* ========================================================================== */ |
void Display_GetImageArea( |
TQ3Area* outArea) |
{ |
assert(outArea != NULL); |
#if USE_DRAW_SPROCKET |
{ |
DSpContextAttributes attributes; |
DSpContext_GetAttributes(gDisplayContext, &attributes); |
outArea->min.x = 0; |
outArea->max.x = attributes.displayWidth; |
outArea->min.y = 0; |
outArea->max.y = attributes.displayHeight; |
} |
#else |
outArea->min.x = gDisplayWindow->portRect.left; |
outArea->max.x = gDisplayWindow->portRect.right; |
outArea->min.y = gDisplayWindow->portRect.top; |
outArea->max.y = gDisplayWindow->portRect.bottom-15; |
#endif |
} |
/* ============================================================================= |
* Display_GetImageAspectRatio (internal) |
* |
* Returns the aspect ratio of the area occupied by the 3D image part of the |
* window. |
* ========================================================================== */ |
float Display_GetImageAspectRatio( |
void) |
{ |
TQ3Area imageArea; |
Display_GetImageArea(&imageArea); |
return (imageArea.max.x-imageArea.min.x) / (imageArea.max.y-imageArea.min.y); |
} |
/* ============================================================================= |
* Display_BeginQD (internal) |
* |
* Sets up for doing Quickdraw drawing. |
* ========================================================================== */ |
void Display_BeginQD( |
void) |
{ |
if (gDisplayHasRendered) |
{ |
// Q3Renderer_Sync(gDisplayRenderer, gDisplayView); |
Q3View_Sync(gDisplayView); |
} |
#if USE_DRAW_SPROCKET |
{ |
CGrafPtr port; |
DSpContext_GetBackBuffer(gDisplayContext, kDSpBufferKind_Normal, &port); |
SetPort((GrafPtr) port); |
} |
#else |
SetPort(gDisplayWindow); |
#endif |
} |
/* ============================================================================= |
* Display_EndQD (internal) |
* |
* Undoes what Display_BeginQD did. |
* ========================================================================== */ |
void Display_EndQD( |
void) |
{ |
#if USE_DRAW_SPROCKET |
// do nothing |
#else |
// do nothing |
#endif |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-10-14