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.
BackGroundShell.c
// Quickdraw 3D sample code |
// |
// This file illustrates how to set up a pixmap based draw context. |
// A metafile is read into and imaged in the pixmap, this pixmap is combined |
// with a pixmap containing a background, so that the 3d data is drawn over |
// the background |
// |
// Nick Thompson, AppleLink: DEVSUPPORT (devsupport@applelink.apple.com) |
// |
// ©1994-5 Apple Computer Inc., All Rights Reserved |
// system headers |
#include <Devices.h> |
#include <Dialogs.h> |
#include <DiskInit.h> |
#include <Fonts.h> |
#include <Menus.h> |
#include <PictUtils.h> |
#include <QDOffScreen.h> |
#include <QuickDraw.h> |
#include <SegLoad.h> |
#include <StandardFile.h> |
#include <TextEdit.h> |
#include <ToolUtils.h> |
// for QuickDraw 3D |
#include "QD3D.h" |
#include "QD3DMath.h" |
#include "QD3DDrawContext.h" |
#include "QD3DShader.h" |
#include "QD3DTransform.h" |
#include "QD3DGroup.h" |
#include "QD3DCamera.h" |
#include "BackGroundShell.h" |
#include "BackGroundSupport.h" |
// get the interface to my error handler routines |
#include "MyErrorHandler.h" |
const RGBColor kClearColor = { 0x0000, 0xffff, 0x0000 } ; |
const RGBColor kWhiteColor = { 0xffff, 0xffff, 0xffff } ; |
//------------------------------------------------------------------------------------------- |
// function prototypes |
static void InitToolbox( void ) ; |
static void MainEventLoop( void ) ; |
static void HandleKeyPress(EventRecord *event) ; |
static void HandleOSEvent(EventRecord *event) ; |
void InitDocumentData( DocumentPtr theDocument ) ; |
TQ3Status DocumentDraw3DData( DocumentPtr theDocument ) ; |
void DisposeDocumentData( DocumentPtr theDocument) ; |
void DocumentDrawOnscreen(DocumentPtr theDocument, Rect *clipRect) ; |
OSErr WritePict( PicHandle myPic, short dstPictFRef ) ; |
OSErr GetOutputFileRef(short *dstPictFRef ) ; |
PicHandle ImageToPict( DocumentPtr theDocument, WindowPtr theWindow ) ; |
void DoSaveAs(DocumentPtr theDocument) ; |
//------------------------------------------------------------------------------------------- |
// |
Boolean gQuitFlag = false ; |
WindowPtr gMainWindow = nil ; |
DocumentRec gDocument ; |
//------------------------------------------------------------------------------------------- |
// main() |
// entry point for the application, initialize the toolbox, initialize QuickDraw 3D |
// and enter the main event loop. On exit from the main event loop, we want to call |
// the QuickDraw 3D exit function to clean up QuickDraw 3d. |
void main(void) |
{ |
TQ3Status myStatus; |
Rect rBounds = { 50, 50, 350, 350 } ; |
Str255 title = "\pSpinning Box" ; |
FSSpec theFileSpec ; // the file we are opening |
InitToolbox() ; |
if(MetafileFileSpecify( &theFileSpec )) { |
SetCursor(*(GetCursor(watchCursor))); |
// Initialize QuickDraw 3D, open a connection to the QuickDraw 3D library |
myStatus = Q3Initialize(); |
if ( myStatus == kQ3Failure ) |
DebugStr("\pErInitialize returned failure."); |
// install the error & warning handler - these get called whenever |
// errors or warnings occur, which means we don't have to check so |
// much |
Q3Error_Register( MyErrorHandler, 0L ); |
Q3Warning_Register( MyWarningHandler, 0L ); |
// set up our globals |
gQuitFlag = false ; |
gMainWindow = NewCWindow(nil,&rBounds,title,false,noGrowDocProc,(WindowPtr)-1,true,0) ; |
// initialise our document structure |
InitDocumentData( &gDocument ) ; |
// try to read the file into the main display group |
if((gDocument.fModel = MyNewModelFromFile(&theFileSpec)) != NULL ) { |
// get a bg picturre |
if(PictureFileSpecify(&theFileSpec)) { |
PicHandle thePicture ; |
if((thePicture = OpenPICTFile( &theFileSpec )) != nil ) { |
CGrafPtr savedPort ; |
GDHandle gdh ; |
OSErr theErr ; |
Rect bounds = (**thePicture).picFrame ; |
GetGWorld( &savedPort, &gdh ); |
// create the offscreen for the picture, this is faster than |
// calling DrawPicture each time through our update onscreen routine. |
theErr = NewGWorld(&gDocument.fBgPicture, 32, &bounds,nil,nil,0L); |
if(theErr != noErr ) |
ExitToShell() ; |
SetGWorld( gDocument.fBgPicture, nil ) ; |
DrawPicture( thePicture, &bounds ) ; |
KillPicture( thePicture ) ; |
// clear our compositing buffer |
theErr = NewGWorld(&gDocument.fCompositeBuffer, 32, &bounds,nil,nil,0L); |
if(theErr != noErr ) |
ExitToShell() ; |
SetGWorld( gDocument.fCompositeBuffer, nil ) ; |
RGBBackColor( &kClearColor ) ; |
EraseRect( &bounds ) ; |
// restore the environment |
SetGWorld( savedPort, gdh ); |
AdjustCamera( &gDocument, |
(bounds.right - bounds.left), |
(bounds.bottom - bounds.top) ) ; |
SetWTitle( gMainWindow, theFileSpec.name ); |
SizeWindow( gMainWindow, |
(bounds.right - bounds.left), |
(bounds.bottom - bounds.top), |
false ); |
ShowWindow( gMainWindow ) ; |
SetPort( gMainWindow ) ; |
SetCursor(&qd.arrow) ; |
MainEventLoop(); |
} |
} |
} |
// Close our connection to the QuickDraw 3D library |
myStatus = Q3Exit(); |
if ( myStatus == kQ3Failure ) |
DebugStr("\pErExit returned failure."); |
} |
} |
//------------------------------------------------------------------------------------------- |
// |
void InitDocumentData( DocumentPtr theDocument ) |
{ |
GWorldPtr theOffscreen ; |
GDHandle theDevice ; |
TQ3Point3D myOrigin = { 0, 0, 0 } ; |
// create a GWorld the size of the window area |
OSErr myErr = NewGWorld( &theDocument->fGWorld, |
32, |
&gMainWindow->portRect, |
nil, |
nil, |
0L ); |
if(myErr != noErr ) |
goto bail ; |
GetGWorld( &theOffscreen, &theDevice ) ; |
SetGWorld( theDocument->fGWorld, nil ) ; |
EraseRect( &gMainWindow->portRect ) ; |
SetGWorld( theOffscreen, theDevice ) ; |
// sets up the 3d data for the scene |
// Create view for QuickDraw 3D. |
theDocument->fView = MyNewView( theDocument->fGWorld ); |
// the main display group: |
theDocument->fModel = NULL ; |
// scale and group center |
theDocument->fGroupScale = 1; |
theDocument->fGroupCenter = myOrigin ; |
// the drawing styles: |
theDocument->fInterpolation = Q3InterpolationStyle_New(kQ3InterpolationStyleNone) ; |
theDocument->fBackFacing = Q3BackfacingStyle_New( kQ3BackfacingStyleBoth ) ; |
theDocument->fFillStyle = Q3FillStyle_New(kQ3FillStyleFilled ) ; |
// set the rotation matrix the identity matrix |
Q3Matrix4x4_SetIdentity(&theDocument->fRotation); |
return ; |
bail: |
// we failed setting up the GWorld |
// so we want to quit here |
ExitToShell() ; |
} |
void DisposeDocumentData( DocumentPtr theDocument) |
{ |
if(theDocument->fView) |
Q3Object_Dispose(theDocument->fView) ; // the view for the scene |
if(theDocument->fModel) |
Q3Object_Dispose(theDocument->fModel) ; // object in the scene being modelled |
if(theDocument->fInterpolation) |
Q3Object_Dispose(theDocument->fInterpolation) ; // interpolation style used when rendering |
if(theDocument->fBackFacing) |
Q3Object_Dispose(theDocument->fBackFacing) ; // whether to draw shapes that face away from the camera |
if(theDocument->fFillStyle) |
Q3Object_Dispose(theDocument->fFillStyle) ; // whether drawn as solid filled object or decomposed to components |
} |
//----------------------------------------------------------------------------- |
// assumes the port is set up before being called |
TQ3Status DocumentDraw3DData( DocumentPtr theDocument ) |
{ |
TQ3Status theStatus ; |
// Start rendering. |
Q3View_StartRendering(theDocument->fView) ; |
do { |
theStatus = SubmitScene( theDocument ) ; |
} while (Q3View_EndRendering(theDocument->fView) == kQ3ViewStatusRetraverse ); |
return theStatus ; |
} |
//------------------------------------------------------------------------------------------- |
// |
void DocumentDrawOnscreen(DocumentPtr theDocument, Rect *clipRect) |
{ |
if (theDocument->fGWorld) { |
CGrafPtr savedPort; |
GDHandle savedDevice; |
RGBColor savedColor ; |
GetGWorld( &savedPort, &savedDevice); |
// composite the image in the offscreen |
// first draw the BG Pict |
SetGWorld( theDocument->fCompositeBuffer, nil); |
GetBackColor(&savedColor); |
RGBBackColor(&kWhiteColor) ; |
CopyBits ((BitMapPtr) &theDocument->fBgPicture->portPixMap, |
(BitMapPtr) &theDocument->fCompositeBuffer->portPixMap, |
&theDocument->fBgPicture->portRect, |
&theDocument->fCompositeBuffer->portRect, |
srcCopy, |
0L); |
RGBBackColor(&savedColor) ; |
OpColor(&kClearColor); |
// next draw the 3d image over the bg pict using transparent copy |
CopyBits ((BitMapPtr) &theDocument->fGWorld->portPixMap, |
(BitMapPtr) &theDocument->fCompositeBuffer->portPixMap, |
&theDocument->fGWorld->portRect, |
&theDocument->fCompositeBuffer->portRect, |
srcCopy | transparent, |
0L); |
SetGWorld( (CGrafPtr)gMainWindow, nil); |
ClipRect( clipRect ) ; |
// don't need to lockPixels on the GWorld as the |
// offscreen remains locked (see IM: QD3D), the |
// pixmap for a pixmap draw context must remain locked |
CopyBits ((BitMapPtr) &theDocument->fCompositeBuffer->portPixMap, |
&gMainWindow->portBits, |
&theDocument->fCompositeBuffer->portRect, |
&gMainWindow->portRect, |
srcCopy, |
0L); |
SetGWorld( savedPort, savedDevice); |
} |
} |
//------------------------------------------------------------------------------------------- |
// |
short HiWrd(long aLong) |
{ |
return (((aLong) >> 16) & 0xFFFF) ; |
} |
//------------------------------------------------------------------------------------------- |
// |
short LoWrd(long aLong) |
{ |
return ((aLong) & 0xFFFF) ; |
} |
//------------------------------------------------------------------------------------------- |
// |
void InitToolbox() |
{ |
Handle menuBar = nil; |
MaxApplZone() ; |
MoreMasters() ; MoreMasters() ; MoreMasters() ; |
InitGraf( &qd.thePort ); |
InitFonts(); |
InitWindows(); |
FlushEvents( everyEvent, 0 ) ; |
// initialize application globals |
gQuitFlag = false; |
InitCursor(); |
} |
//------------------------------------------------------------------------------------------- |
// |
void MainEventLoop() |
{ |
EventRecord event; |
WindowPtr window; |
short thePart; |
Rect screenRect, updateRect; |
Point aPoint = {100, 100}; |
while( !gQuitFlag ) |
{ |
if (WaitNextEvent( everyEvent, &event, 0, nil )) |
{ |
switch (event.what) { |
case mouseDown: |
thePart = FindWindow( event.where, &window ); |
switch( thePart ) { |
case inMenuBar: |
break; |
case inDrag: |
screenRect = (**GetGrayRgn()).rgnBBox; |
DragWindow( window, event.where, &screenRect ); |
break ; |
case inContent: |
if (window != FrontWindow()) |
SelectWindow( window ); |
break ; |
case inGoAway: |
if (TrackGoAway( window, event.where )) { |
DisposeWindow ( window ); |
DisposeDocumentData( &gDocument ) ; |
gQuitFlag = true; |
} |
break ; |
default: |
break ; |
} |
break ; |
case updateEvt: |
window = (WindowPtr)event.message; |
updateRect = (**(window->visRgn)).rgnBBox; |
SetPort( window ) ; |
BeginUpdate( window ); |
DocumentDraw3DData( &gDocument ) ; |
DocumentDrawOnscreen( &gDocument, &updateRect ) ; |
EndUpdate( window ); |
break ; |
case keyDown: |
case autoKey: |
HandleKeyPress(&event); |
break; |
case diskEvt: |
if ( HiWrd(event.message) != noErr ) |
(void) DIBadMount(aPoint, event.message); |
break; |
case osEvt: |
case activateEvt: |
break; |
} |
} |
else { |
// we received a null event, rotate the cube |
TQ3Matrix4x4 tmp; |
Rect theRect = ((GrafPtr)gMainWindow)->portRect ; |
SetPort((GrafPtr)gMainWindow) ; |
Q3Matrix4x4_SetRotate_XYZ(&tmp, 0.1, 0.12, 0.08); |
Q3Matrix4x4_Multiply(&gDocument.fRotation, &tmp, &gDocument.fRotation); |
InvalRect( &theRect ) ; |
} |
} |
} |
//------------------------------------------------------------------------------------------- |
// |
void HandleKeyPress(EventRecord *event) |
{} |
//------------------------------------------------------------------------------------------- |
// |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14