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.
3DMF2PICTShell.c
// Quickdraw 3D sample code |
// |
// 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 "3DMF2PICTShell.h" |
#include "3DMF2PICTSupport.h" |
// get the interface to my error handler routines |
#include "MyErrorHandler.h" |
//------------------------------------------------------------------------------------------- |
// 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 ) { |
AdjustCamera( &gDocument, |
(gMainWindow->portRect.right - gMainWindow->portRect.left), |
(gMainWindow->portRect.bottom - gMainWindow->portRect.top) ) ; |
SetWTitle( gMainWindow, theFileSpec.name ); |
ShowWindow( gMainWindow ) ; |
SetPort( gMainWindow ) ; |
SetCursor(&qd.arrow) ; |
MainEventLoop(); |
} |
DisposeDocumentData( &gDocument ) ; |
// 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) |
{ |
Q3Object_Dispose(theDocument->fView) ; // the view for the scene |
Q3Object_Dispose(theDocument->fModel) ; // object in the scene being modelled |
Q3Object_Dispose(theDocument->fInterpolation) ; // interpolation style used when rendering |
Q3Object_Dispose(theDocument->fBackFacing) ; // whether to draw shapes that face away from the camera |
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 ; |
//{ |
// TQ3CameraData theCameraData ; |
// TQ3CameraObject theCameraObject; |
// |
// Q3View_GetCamera(theDocument->fView, &theCameraObject); |
// Q3Camera_GetData(theCameraObject, &theCameraData); |
//Debugger() ; |
// |
//} |
// 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; |
GetGWorld( &savedPort, &savedDevice); |
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->fGWorld->portPixMap, |
&gMainWindow->portBits, |
&theDocument->fGWorld->portRect, |
&gMainWindow->portRect, |
srcCopy, |
0L); |
SetGWorld( savedPort, savedDevice); |
} |
} |
//-------------------------------------------------------------------------------------- |
OSErr WritePict( PicHandle myPic, short dstPictFRef ) |
{ |
long length ; |
long dummy ; |
int index ; |
OSErr result ; |
// ok, myPic now contains a handle to the compressed picture |
HLock( (Handle)(Handle)myPic); |
// set up the 512 byte header for a PICT file |
dummy = 0; |
for( index = 0; index < ( 512 / 4 ); index ++ ){ |
length = 4 ; |
if( (result = FSWrite(dstPictFRef, &length, &dummy)) != noErr ) { |
// ErrorAlert( rErrorStrs, eCantWriteFile ); |
return result ; |
} |
} |
length = GetHandleSize( (Handle)myPic); |
if( (result = FSWrite(dstPictFRef, &length, *myPic)) != noErr ) { |
//ErrorAlert( rErrorStrs, eCantWriteFile ); |
return result ; |
} |
// now get rid of the picture handle |
HUnlock( (Handle) (Handle)myPic ) ; |
KillPicture(myPic); |
return noErr ; |
} |
//-------------------------------------------------------------------------------------- |
OSErr GetOutputFileRef(short *dstPictFRef ) // GetOutputFileRefNum |
{ |
StandardFileReply aPictSFR; // new style Standard file record |
OSErr result ; |
SFTypeList types = { 'PICT',0 }; // we are only interested in PICT files |
// check to see if we have the new style standard file package |
StandardPutFile( "\pSave PICT as:", "\pNew PICT", &aPictSFR); |
if ( aPictSFR.sfGood ) { |
// Delete the file of the same name, if one exits, |
// and create a new PICT file. |
FSpDelete(&aPictSFR.sfFile); |
result = FSpCreate( &aPictSFR.sfFile,'ttxt','PICT', aPictSFR.sfScript); |
if (result != noErr) { |
return result; |
} |
// open the data fork for writing |
// ??? need to change the permissions here ??? |
result = FSpOpenDF( &aPictSFR.sfFile, fsCurPerm, dstPictFRef); |
if (result != noErr) { |
return result; |
} |
} |
else |
return userCanceledErr ; |
return noErr ; |
} |
//-------------------------------------------------------------------------------------- |
PicHandle ImageToPict( DocumentPtr theDocument, WindowPtr theWindow ) |
{ |
PicHandle thePicture = OpenPicture(&theDocument->fGWorld->portRect) ; |
DocumentDrawOnscreen( theDocument, &theWindow->portRect) ; |
ClosePicture() ; |
return thePicture ; |
} |
//-------------------------------------------------------------------------------------- |
void DoSaveAs(DocumentPtr theDocument) |
{ |
short dstPictFRef = 0; |
PicHandle myPic = nil; |
OSErr theErr; |
extern gxShape gthePicture; // defined in BitmAp Shape with Clip.c |
// get an open a file for writing |
if( (theErr = GetOutputFileRef( &dstPictFRef )) != noErr ) { |
return ; |
} |
else { |
if(( myPic = ImageToPict ( theDocument, gMainWindow )) != nil ) { |
if(WritePict( myPic, dstPictFRef ) != noErr ) { |
FSClose(dstPictFRef); |
return ; |
} |
} |
} |
FSClose(dstPictFRef); |
return ; |
} |
//------------------------------------------------------------------------------------------- |
// |
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 )) { |
DoSaveAs(&gDocument) ; |
DisposeWindow ( window ); |
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