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.
Feature Files/VR3DObjects.c
////////// |
// |
// File: VR3DObjects.c |
// |
// Contains: QuickDraw 3D support for QuickTime VR movies. |
// |
// Written by: Tim Monroe |
// Parts modeled on BoxMoov code by Nick Thompson, Rick Evans, and Robert Dierkes |
// and on code in QD3D book (by yours truly!). |
// |
// Copyright: © 1996-1999 by Apple Computer, Inc., all rights reserved. |
// |
// Change History (most recent first): |
// |
// <37> 03/28/00 rtm changed ((**myPixMap).rowBytes & 0x3fff) to QTGetPixMapHandleRowBytes(myPixMap) |
// <36> 07/29/99 rtm set polyhedronAttributeSet to NULL in VR3DObjects_EnlistRectangle; now |
// the Set3DObjColor command works on rectangles as well as other objects |
// <35> 09/28/98 rtm added Q3InteractiveRenderer_ calls to VR3DObjects_CreateView |
// <34> 04/22/98 rtm used GetGWorldPixMap instead of gw->portPixMap in VR3DObjects_PrescreenRoutine |
// <33> 03/18/98 rtm minor cleanup to make things a little more structured |
// <32> 03/09/98 rtm removed VR3DObjects_GetEmbeddedPicture; moved code into VR3DTexture.c from |
// VR3DObjects_LoadEmbeddedMovie and VR3DObjects_LoopEmbeddedMovie |
// <31> 02/19/98 rtm changed default chroma key color to prevent transparency problems |
// <30> 01/28/98 rtm changed NewGWorld calls to QTNewGWorld |
// <29> 01/27/98 rtm fixed pixel depth problems: QD3D's GWorlds should all be 32-bit |
// <28> 10/13/97 rtm added VR3DObjects_CreateDefaultGroup call to VR3DObjects_GetModelFromFile |
// to provide default lighting for 3DMF files |
// <27> 10/03/97 rtm removed UPDATE_GWORLD_BROKEN symbol |
// <26> 09/23/97 rtm added endian adjustment to VR3DObjects_GetEmbeddedPicture |
// <25> 09/15/97 rtm added UPDATE_GWORLD_BROKEN symbol; should be removed later |
// when UpdateGWorld is fixed |
// <24> 09/12/97 rtm added Windows support to VR3DObjects_GetModelFromFile |
// <23> 07/17/97 rtm added VR3DObjects_DoIdle |
// <22> 05/05/97 rtm more work on geometry specifications; |
// added Set calls for styles, colors, etc. |
// <21> 05/04/97 rtm reworked geometry specifications; added Enlist_ functions |
// <20> 05/02/97 rtm made sound in texture movies directional |
// <19> 04/10/97 rtm added call to Q3View_Sync to prevent tearing |
// <18> 04/02/97 rtm copied file for integration with VRScript; removed support for object nodes |
// <17> 02/21/97 rtm added support for multi-node, mixed-type movies; |
// fixed window resizing for object nodes |
// <16> 02/10/97 rtm fixed up-vector; fixed pan/tilt granularity in object nodes |
// (now QD3D camera doesn't update until object view changes) |
// <15> 02/04/97 rtm begun implementing support for object nodes |
// <14> 01/24/97 rtm slight adjustment to camera-setting algorithm |
// <13> 01/23/97 rtm reworked camera-setting algorithm; now it works fine! |
// (replaced VR3DObjects_RotateCamera[XY] with VR3DObjects_SetCamera) |
// <12> 01/20/97 rtm various small tweaks; nothing major |
// <11> 01/17/97 rtm further work on tilting; still unable to fix it entirely |
// <10> 01/16/97 rtm added VR3DObjects_SetCameraAspectRatio |
// and VR3DObjects_UpdateDrawContext to handle window resizing |
// <9> 01/14/97 rtm added polyhedron object to VR3DObjects_CreateModel; added static texture support |
// <8> 01/13/97 rtm added some object types to VR3DObjects_CreateModel |
// <7> 01/10/97 rtm added VR3DObjects_MCActionFilterProc (later merged into ApplicationMCActionFilterProc) |
// <6> 01/09/97 rtm fixed jittering on pan/tilt/zoom; fixed VR3DObjects_RotateCameraX for correct tilting |
// <5> 01/03/97 rtm added animation (that is, rotation) support for 3D objects |
// <4> 12/23/96 rtm further work on 3D overlay; fixed some jitters |
// <3> 12/20/96 rtm added zooming support; implemented 3D overlay instead of 3D test window |
// <2> 12/16/96 rtm added 3D test window, intercept procedure |
// added QuickTime movie texture mapping support |
// <1> 12/13/96 rtm first file |
// |
// |
// This file provides functions to display 3D objects at specific locations in a panorama. |
// |
// Our strategy: QuickDraw 3D is a "slave" to VR: whenever the VR environment changes, |
// we change the QuickDraw 3D camera accordingly and render a new image to our view. |
// All this occurs in the prescreen buffer imaging complete procedure. |
// |
////////// |
// TODO: |
// + add lighting calls (create new light, move light, set light color/intensity etc.) |
#if QD3D_AVAIL |
////////// |
// |
// header files |
// |
////////// |
#include "VR3DObjects.h" |
////////// |
// |
// global variables |
// |
////////// |
extern Boolean gHasQuickDraw3D; // is QuickDraw 3D available? |
extern Boolean gHasQuickDraw3D15; // is QuickDraw 3D version 1.5 (or greater) available? |
////////// |
// |
// constants |
// |
////////// |
const TQ3Point3D kCameraOrigin = {0.0, 0.0, 0.0}; |
const TQ3Point3D kPointOfInterest = {0.0, 0.0, -1000.0}; |
const TQ3ColorRGB k3DObjColor = {0.5, 0.5, 0.5}; // default 3D object color |
const RGBColor k3DChromaColor = {0x1111, 0x2222, 0x3333}; // the default chroma key color |
////////// |
// |
// VR3DObjects_Init |
// Initialize for QuickDraw 3D. |
// |
////////// |
void VR3DObjects_Init (void) |
{ |
// make sure that QuickDraw 3D is available |
gHasQuickDraw3D = VR3DObjects_IsQD3DAvailable() ? true : false; |
// now perform any initialization |
if (gHasQuickDraw3D) { |
unsigned long myMajor, myMinor; |
Q3Initialize(); |
// see which version of QD3D is installed; version 1.5 provides some useful new geometries |
Q3GetVersion(&myMajor, &myMinor); |
gHasQuickDraw3D15 = ((myMajor >= 0x0001) && (myMinor >= 0x0005)); |
} |
} |
////////// |
// |
// VR3DObjects_Stop |
// Clean up for QuickDraw 3D. |
// |
////////// |
void VR3DObjects_Stop (void) |
{ |
// perform any QD3D-related shutdown operations |
if (gHasQuickDraw3D) |
Q3Exit(); |
} |
////////// |
// |
// VR3DObjects_IsQD3DAvailable |
// Is QuickDraw 3D available in the present operating environment? |
// |
////////// |
Boolean VR3DObjects_IsQD3DAvailable (void) |
{ |
#if TARGET_OS_MAC |
return((Ptr)Q3Initialize != (Ptr)kUnresolvedCFragSymbolAddress); |
#endif |
#if TARGET_OS_WIN32 |
return(true); |
#endif |
// the following code should work cross-platform, but currently it returns -5551 (gestaltUndefSelectorErr) on Windows |
// Boolean myQD3DAvail = false; |
// long myAttrs; |
// OSErr myErr = noErr; |
// |
// myErr = Gestalt(gestaltQD3D, &myAttrs); |
// if (myErr == noErr) |
// if (myAttrs & (1L << gestaltQD3DPresent)) |
// myQD3DAvail = true; |
// |
// return(myQD3DAvail); |
} |
////////// |
// |
// VR3DObjects_InitWindowData |
// Initialize the window-specific 3D data. |
// |
////////// |
void VR3DObjects_InitWindowData (WindowObject theWindowObject) |
{ |
ApplicationDataHdl myAppData; |
Rect myRect; |
OSErr myErr = noErr; |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject); |
if (myAppData != NULL) { |
// lock the application data handle |
HLock((Handle)myAppData); |
// get the size of the destination window |
if ((**theWindowObject).fMovie != NULL) |
GetMovieBox((**theWindowObject).fMovie, &myRect); |
// create an offscreen GWorld that is the size of the window area |
// (this GWorld is our draw context buffer) |
myErr = QTNewGWorld(&(**myAppData).fQD3DDCGWorld, kOffscreenPixelType, &myRect, NULL, NULL, kICMTempThenAppMemory); |
if (myErr != noErr) |
goto bail; |
// create a new view attached to the offscreen GWorld |
(**myAppData).fView = VR3DObjects_CreateView((**myAppData).fQD3DDCGWorld); |
// set the FOV vertical orientation flag to ON |
(**myAppData).fQD3DFOVIsVert = true; |
// set the default 3D chroma key color |
(**myAppData).fQD3DKeyColor = k3DChromaColor; |
// initialize QD3D camera's aspect ratio |
VR3DObjects_SetCameraAspectRatio(theWindowObject); |
// initialize QD3D camera's point-of-interest and FOV |
VR3DObjects_SetCamera(theWindowObject); |
bail: |
// unlock the application data handle |
HUnlock((Handle)myAppData); |
} |
} |
////////// |
// |
// VR3DObjects_DumpWindowData |
// Dump the window-specific 3D data. |
// |
////////// |
void VR3DObjects_DumpWindowData (WindowObject theWindowObject) |
{ |
ApplicationDataHdl myAppData; |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject); |
if (myAppData != NULL) { |
// dispose of the view object |
if ((**myAppData).fView) |
Q3Object_Dispose((**myAppData).fView); |
// dispose of GWorld used by this window object |
if ((**myAppData).fQD3DDCGWorld != NULL) |
DisposeGWorld((**myAppData).fQD3DDCGWorld); |
} |
} |
////////// |
// |
// VR3DObjects_DoIdle |
// Do any 3D-related processing that can or should occur at idle time. |
// Returns true if the caller should call QTVRUpdate, false otherwise. |
// |
////////// |
Boolean VR3DObjects_DoIdle (WindowObject theWindowObject) |
{ |
ApplicationDataHdl myAppData; |
VRScript3DObjPtr myPointer; |
Boolean myNeedUpdate = false; |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject); |
if (myAppData == NULL) |
return(myNeedUpdate); |
// if any currently visible 3D object is animated or has a movie texture, |
// we need to update window |
myPointer = (VRScript3DObjPtr)(**myAppData).fListArray[kVREntry_QD3DObject]; |
while ((myPointer != NULL) && !myNeedUpdate) { |
if (myPointer->fModelIsVisible) |
if ((myPointer->fModelIsAnimated) || (myPointer->fTextureIsMovie)) |
myNeedUpdate = true; |
myPointer = myPointer->fNextEntry; |
} |
return(myNeedUpdate); |
} |
////////// |
// |
// VR3DObjects_EnlistBox |
// Add a box to the list of 3D objects. |
// |
////////// |
void VR3DObjects_EnlistBox (WindowObject theWindowObject, UInt32 theEntryID, float theX, float theY, float theZ, float theXSize, float theYSize, float theZSize, UInt32 theOptions) |
{ |
TQ3BoxData myBoxData; |
TQ3GeometryObject myObject; |
TQ3GroupObject myGroup; |
myBoxData.boxAttributeSet = NULL; |
myBoxData.faceAttributeSet = NULL; |
Q3Point3D_Set(&myBoxData.origin, theXSize / -2.0, theYSize / -2.0, theZSize / -2.0); |
Q3Vector3D_Set(&myBoxData.orientation, 0.0, theYSize, 0.0); |
Q3Vector3D_Set(&myBoxData.majorAxis, 0.0, 0.0, theZSize); |
Q3Vector3D_Set(&myBoxData.minorAxis, theXSize, 0.0, 0.0); |
myObject = Q3Box_New(&myBoxData); |
if (myObject != NULL) { |
myGroup = VR3DObjects_CreateDefaultGroup(myObject); |
if (myGroup != NULL) |
VRScript_Enlist3DObject(theWindowObject, myGroup, theEntryID, theX, theY, theZ, theOptions); |
} |
} |
////////// |
// |
// VR3DObjects_EnlistCone |
// Add a cone to the list of 3D objects. |
// |
////////// |
void VR3DObjects_EnlistCone (WindowObject theWindowObject, UInt32 theEntryID, float theX, float theY, float theZ, float theMajRad, float theMinRad, float theHeight, UInt32 theOptions) |
{ |
TQ3ConeData myConeData; |
TQ3GeometryObject myObject; |
TQ3GroupObject myGroup; |
myConeData.coneAttributeSet = NULL; |
myConeData.interiorAttributeSet = NULL; |
myConeData.faceAttributeSet = NULL; |
myConeData.bottomAttributeSet = NULL; |
myConeData.caps = kQ3EndCapMaskBottom; |
Q3Point3D_Set(&myConeData.origin, 0.0, theHeight / -2.0, 0.0); |
Q3Vector3D_Set(&myConeData.orientation, 0.0, theHeight, 0.0); |
Q3Vector3D_Set(&myConeData.majorRadius, 0.0, 0.0, theMajRad); |
Q3Vector3D_Set(&myConeData.minorRadius, theMinRad, 0.0, 0.0); |
myObject = Q3Cone_New(&myConeData); |
if (myObject != NULL) { |
myGroup = VR3DObjects_CreateDefaultGroup(myObject); |
if (myGroup != NULL) { |
VR3DObjects_SetSubdivisionStyle(myGroup, 20); // set a finer subdivision style |
VRScript_Enlist3DObject(theWindowObject, myGroup, theEntryID, theX, theY, theZ, theOptions); |
} |
} |
} |
////////// |
// |
// VR3DObjects_EnlistCylinder |
// Add a cylinder to the list of 3D objects. |
// |
////////// |
void VR3DObjects_EnlistCylinder (WindowObject theWindowObject, UInt32 theEntryID, float theX, float theY, float theZ, float theMajRad, float theMinRad, float theHeight, UInt32 theOptions) |
{ |
TQ3CylinderData myCylinderData; |
TQ3GeometryObject myObject; |
TQ3GroupObject myGroup; |
myCylinderData.cylinderAttributeSet = NULL; |
myCylinderData.interiorAttributeSet = NULL; |
myCylinderData.topAttributeSet = NULL; |
myCylinderData.faceAttributeSet = NULL; |
myCylinderData.bottomAttributeSet = NULL; |
myCylinderData.caps = kQ3EndCapMaskTop | kQ3EndCapMaskBottom; |
Q3Point3D_Set(&myCylinderData.origin, 0.0, theHeight / -2.0, 0.0); |
Q3Vector3D_Set(&myCylinderData.orientation, 0.0, theHeight, 0.0); |
Q3Vector3D_Set(&myCylinderData.majorRadius, 0.0, 0.0, theMajRad); |
Q3Vector3D_Set(&myCylinderData.minorRadius, theMinRad, 0.0, 0.0); |
myObject = Q3Cylinder_New(&myCylinderData); |
if (myObject != NULL) { |
myGroup = VR3DObjects_CreateDefaultGroup(myObject); |
if (myGroup != NULL) { |
VR3DObjects_SetSubdivisionStyle(myGroup, 20); // set a finer subdivision style |
VRScript_Enlist3DObject(theWindowObject, myGroup, theEntryID, theX, theY, theZ, theOptions); |
} |
} |
} |
////////// |
// |
// VR3DObjects_EnlistEllipsoid |
// Add an ellipsoid to the list of 3D objects. |
// |
////////// |
void VR3DObjects_EnlistEllipsoid (WindowObject theWindowObject, UInt32 theEntryID, float theX, float theY, float theZ, float theMajRad, float theMinRad, float theHeight, UInt32 theOptions) |
{ |
TQ3EllipsoidData myEllipsoidData; |
TQ3GeometryObject myObject; |
TQ3GroupObject myGroup; |
myEllipsoidData.ellipsoidAttributeSet = NULL; |
myEllipsoidData.interiorAttributeSet = NULL; |
myEllipsoidData.caps = 0L; |
Q3Point3D_Set(&myEllipsoidData.origin, 0.0, 0.0, 0.0); |
Q3Vector3D_Set(&myEllipsoidData.orientation, 0.0, theHeight, 0.0); |
Q3Vector3D_Set(&myEllipsoidData.majorRadius, 0.0, 0.0, theMajRad); |
Q3Vector3D_Set(&myEllipsoidData.minorRadius, theMinRad, 0.0, 0.0); |
myObject = Q3Ellipsoid_New(&myEllipsoidData); |
if (myObject != NULL) { |
myGroup = VR3DObjects_CreateDefaultGroup(myObject); |
if (myGroup != NULL) { |
VR3DObjects_SetSubdivisionStyle(myGroup, 20); // set a finer subdivision style |
VRScript_Enlist3DObject(theWindowObject, myGroup, theEntryID, theX, theY, theZ, theOptions); |
} |
} |
} |
////////// |
// |
// VR3DObjects_EnlistTorus |
// Add a torus to the list of 3D objects. |
// |
////////// |
void VR3DObjects_EnlistTorus (WindowObject theWindowObject, UInt32 theEntryID, float theX, float theY, float theZ, float theMajRad, float theMinRad, float theHeight, float theRatio, UInt32 theOptions) |
{ |
TQ3TorusData myTorusData; |
TQ3GeometryObject myObject; |
TQ3GroupObject myGroup; |
myTorusData.torusAttributeSet = NULL; |
myTorusData.interiorAttributeSet = NULL; |
myTorusData.caps = 0L; |
myTorusData.ratio = theRatio; |
Q3Point3D_Set(&myTorusData.origin, 0.0, 0.0, 0.0); |
Q3Vector3D_Set(&myTorusData.orientation, 0.0, theHeight, 0.0); |
Q3Vector3D_Set(&myTorusData.majorRadius, 0.0, 0.0, theMajRad); |
Q3Vector3D_Set(&myTorusData.minorRadius, theMinRad, 0.0, 0.0); |
myObject = Q3Torus_New(&myTorusData); |
if (myObject != NULL) { |
myGroup = VR3DObjects_CreateDefaultGroup(myObject); |
if (myGroup != NULL) { |
VR3DObjects_SetSubdivisionStyle(myGroup, 20); // set a finer subdivision style |
VRScript_Enlist3DObject(theWindowObject, myGroup, theEntryID, theX, theY, theZ, theOptions); |
} |
} |
} |
////////// |
// |
// VR3DObjects_EnlistRectangle |
// Add a rectangle to the list of 3D objects. |
// This is intended to serve as a "screen" for texture-mapped movies or pictures. |
// |
////////// |
void VR3DObjects_EnlistRectangle (WindowObject theWindowObject, UInt32 theEntryID, float theX, float theY, float theZ, |
float theX1, float theY1, float theZ1, |
float theX2, float theY2, float theZ2, |
float theX3, float theY3, float theZ3, |
float theX4, float theY4, float theZ4, UInt32 theOptions) |
{ |
TQ3PolyhedronData myPolyData; |
static TQ3Vertex3D myVertices[4]; |
static TQ3Param2D myUVParams[4] = { |
{0.0, 0.0}, |
{0.0, 1.0}, |
{1.0, 1.0}, |
{1.0, 0.0} |
}; |
TQ3PolyhedronTriangleData myTriangles[2] = { |
{ { 0, 1, 3 }, kQ3PolyhedronEdge01 | kQ3PolyhedronEdge20, NULL }, |
{ { 1, 2, 3 }, kQ3PolyhedronEdge01 | kQ3PolyhedronEdge12, NULL } |
}; |
unsigned long myIndex; |
TQ3GeometryObject myObject; |
TQ3GroupObject myGroup; |
// set up vertices, edges, and triangular faces |
Q3Point3D_Set(&myVertices[0].point, theX1, theY1, theZ1); |
Q3Point3D_Set(&myVertices[1].point, theX2, theY2, theZ2); |
Q3Point3D_Set(&myVertices[2].point, theX3, theY3, theZ3); |
Q3Point3D_Set(&myVertices[3].point, theX4, theY4, theZ4); |
myVertices[0].attributeSet = NULL; |
myVertices[1].attributeSet = NULL; |
myVertices[2].attributeSet = NULL; |
myVertices[3].attributeSet = NULL; |
myPolyData.numVertices = 4; |
myPolyData.vertices = myVertices; |
myPolyData.numEdges = 0; |
myPolyData.edges = NULL; |
myPolyData.numTriangles = 2; |
myPolyData.triangles = myTriangles; |
// add uv parameterization to the polyhedron |
for (myIndex = 0; myIndex < myPolyData.numVertices; myIndex++) { |
myVertices[myIndex].attributeSet = Q3AttributeSet_New(); |
Q3AttributeSet_Add(myVertices[myIndex].attributeSet, kQ3AttributeTypeSurfaceUV, &myUVParams[myIndex]); |
} |
myPolyData.polyhedronAttributeSet = NULL; // inherit the attribute set from the current state |
myObject = Q3Polyhedron_New(&myPolyData); |
if (myObject != NULL) { |
myGroup = VR3DObjects_CreateDefaultGroup(myObject); |
if (myGroup != NULL) |
VRScript_Enlist3DObject(theWindowObject, myGroup, theEntryID, theX, theY, theZ, theOptions); |
} |
} |
////////// |
// |
// VR3DObjects_Enlist3DMFFile |
// Open a 3DMF file and add it to the list of 3D objects. |
// |
////////// |
void VR3DObjects_Enlist3DMFFile (WindowObject theWindowObject, UInt32 theEntryID, float theX, float theY, float theZ, UInt32 theOptions, char *thePathName) |
{ |
TQ3GroupObject myGroup; |
myGroup = VR3DObjects_GetModelFromFile(thePathName); |
if (myGroup != NULL) |
VRScript_Enlist3DObject(theWindowObject, myGroup, theEntryID, theX, theY, theZ, theOptions); |
} |
////////// |
// |
// VR3DObjects_CreateDefaultGroup |
// Return a default model containing the specified object. |
// |
////////// |
TQ3GroupObject VR3DObjects_CreateDefaultGroup (TQ3GeometryObject theObject) |
{ |
TQ3GroupObject myGroup; |
// create a new display group |
myGroup = Q3DisplayGroup_New(); |
if (myGroup != NULL) { |
TQ3ShaderObject myIlluminationShader; |
// create an illumination shader |
myIlluminationShader = Q3PhongIllumination_New(); |
if (myIlluminationShader != NULL) { |
TQ3AttributeSet myAttributeSet; |
// add the illumination shader to our display group |
Q3Group_AddObject(myGroup, myIlluminationShader); |
// add the default diffuse color to the group |
myAttributeSet = Q3AttributeSet_New(); |
Q3AttributeSet_Add(myAttributeSet, kQ3AttributeTypeDiffuseColor, &k3DObjColor); |
Q3Group_AddObject(myGroup, myAttributeSet); |
// add the geometry object to the group |
Q3Group_AddObject(myGroup, theObject); |
// dispose of the objects we've added to the group |
if (myIlluminationShader != NULL) |
Q3Object_Dispose(myIlluminationShader); |
} |
} |
if (theObject != NULL) |
Q3Object_Dispose(theObject); |
return(myGroup); |
} |
////////// |
// |
// VR3DObjects_CreateView |
// Return a view object for the QD3D objects in our model. |
// |
////////// |
TQ3ViewObject VR3DObjects_CreateView (GWorldPtr theGWorld) |
{ |
TQ3Status myStatus; |
TQ3ViewObject myView; |
TQ3DrawContextObject myDrawContext; |
TQ3RendererObject myRenderer; |
TQ3CameraObject myCamera; |
TQ3GroupObject myLights; |
// create a new view object |
myView = Q3View_New(); |
if (myView == NULL) |
goto bail; |
// create and set draw context |
myDrawContext = VR3DObjects_CreateDrawContext(theGWorld); |
if (myDrawContext == NULL) |
goto bail; |
myStatus = Q3View_SetDrawContext(myView, myDrawContext); |
if (myStatus == kQ3Failure) |
goto bail; |
Q3Object_Dispose(myDrawContext); |
// create and set renderer |
myRenderer = Q3Renderer_NewFromType(kQ3RendererTypeInteractive); |
if (myRenderer == NULL) { |
myRenderer = Q3Renderer_NewFromType(kQ3RendererTypeWireFrame); |
} else { |
// these two lines allow us to use the best possible renderer, |
// including hardware if it is installed. |
Q3InteractiveRenderer_SetDoubleBufferBypass(myRenderer, kQ3True); |
Q3InteractiveRenderer_SetPreferences(myRenderer, kQAVendor_BestChoice, 0); |
} |
if (myRenderer == NULL) |
goto bail; |
myStatus = Q3View_SetRenderer(myView, myRenderer); |
if (myStatus == kQ3Failure) |
goto bail; |
Q3Object_Dispose(myRenderer); |
// create and set camera |
myCamera = VR3DObjects_CreateCamera(theGWorld); |
if (myCamera == NULL) |
goto bail; |
myStatus = Q3View_SetCamera(myView, myCamera); |
if (myStatus == kQ3Failure) |
goto bail; |
Q3Object_Dispose(myCamera); |
// create and set lights |
myLights = VR3DObjects_CreateLights(); |
if (myLights == NULL) |
goto bail; |
myStatus = Q3View_SetLightGroup(myView, myLights); |
if (myStatus == kQ3Failure) |
goto bail; |
Q3Object_Dispose(myLights); |
return(myView); |
bail: |
// if any of the above creations failed, don't return a view |
return(NULL); |
} |
////////// |
// |
// VR3DObjects_CreateLights |
// Return a light group object for the QD3D objects in our model. |
// For displaying embedded movies, we need just the ambient light. |
// |
////////// |
TQ3GroupObject VR3DObjects_CreateLights (void) |
{ |
TQ3GroupPosition myGroupPosition; |
TQ3GroupObject myLightList; |
TQ3LightData myLightData; |
TQ3PointLightData myPointLightData; |
TQ3DirectionalLightData myDirectionalLightData; |
TQ3LightObject myAmbientLight, myPointLight, myFillLight; |
TQ3Point3D myPointLocation = {-10.0, 0.0, 10.0}; |
TQ3Vector3D myFillDirection = {10.0, 0.0, 10.0}; |
TQ3ColorRGB myWhiteLight = {1.0F, 1.0F, 1.0F}; |
// create the ambient light |
myLightData.isOn = kQ3True; |
myLightData.color = myWhiteLight; |
myLightData.brightness = 1.0F; |
myAmbientLight = Q3AmbientLight_New(&myLightData); |
if (myAmbientLight == NULL) |
goto bail; |
// create a point light |
myLightData.brightness = 1.0F; |
myPointLightData.lightData = myLightData; |
myPointLightData.castsShadows = kQ3False; |
myPointLightData.attenuation = kQ3AttenuationTypeNone; |
myPointLightData.location = myPointLocation; |
myPointLight = Q3PointLight_New(&myPointLightData); |
if (myPointLight == NULL) |
goto bail; |
// create a directional light for fill |
myLightData.brightness = 0.2F; |
myDirectionalLightData.lightData = myLightData; |
myDirectionalLightData.castsShadows = kQ3False; |
myDirectionalLightData.direction = myFillDirection; |
myFillLight = Q3DirectionalLight_New(&myDirectionalLightData); |
if (myFillLight == NULL) |
goto bail; |
// create a light group and add each of the lights to the group |
myLightList = Q3LightGroup_New(); |
if (myLightList == NULL) |
goto bail; |
myGroupPosition = Q3Group_AddObject(myLightList, myAmbientLight); |
if (myGroupPosition == 0) |
goto bail; |
myGroupPosition = Q3Group_AddObject(myLightList, myPointLight); |
if (myGroupPosition == 0) |
goto bail; |
myGroupPosition = Q3Group_AddObject(myLightList, myFillLight); |
if (myGroupPosition == 0) |
goto bail; |
Q3Object_Dispose(myAmbientLight); |
Q3Object_Dispose(myPointLight); |
Q3Object_Dispose(myFillLight); |
return(myLightList); |
bail: |
// if any of the above creations failed, don't return a light group |
return(NULL); |
} |
////////// |
// |
// VR3DObjects_CreateDrawContext |
// Return a draw context object for the QD3D objects in our model. |
// |
////////// |
TQ3DrawContextObject VR3DObjects_CreateDrawContext (GWorldPtr theGWorld) |
{ |
TQ3DrawContextObject myDrawContext; |
TQ3PixmapDrawContextData myPixMapDrawContextData; |
TQ3DrawContextData myDrawContextData; |
PixMapHandle myPixMap; |
Rect myRect; |
TQ3ColorARGB myClearColor; |
float myFactor = 0xffff; |
if (theGWorld == NULL) |
goto bail; |
// set the background color; |
// note that RGBColor is defined in the range 0-65535, |
// while TQ3ColorARGB is defined in the range 0.0-1.0; hence the division.... |
myClearColor.a = 0.0; |
myClearColor.r = k3DChromaColor.red / myFactor; |
myClearColor.g = k3DChromaColor.green / myFactor; |
myClearColor.b = k3DChromaColor.blue / myFactor; |
// fill in draw context data |
myDrawContextData.clearImageMethod = kQ3ClearMethodWithColor; |
myDrawContextData.clearImageColor = myClearColor; |
myDrawContextData.paneState = kQ3False; |
myDrawContextData.maskState = kQ3False; |
myDrawContextData.doubleBufferState = kQ3False; |
myPixMapDrawContextData.drawContextData = myDrawContextData; |
// the pixmap must remain locked in memory for as long as it exists |
myPixMap = GetGWorldPixMap(theGWorld); |
LockPixels(myPixMap); |
myRect = theGWorld->portRect; |
myPixMapDrawContextData.pixmap.width = myRect.right - myRect.left; |
myPixMapDrawContextData.pixmap.height = myRect.bottom - myRect.top; |
myPixMapDrawContextData.pixmap.rowBytes = (unsigned long)QTGetPixMapHandleRowBytes(myPixMap) |
myPixMapDrawContextData.pixmap.pixelType = kQ3PixelTypeRGB32; |
myPixMapDrawContextData.pixmap.pixelSize = 32; |
myPixMapDrawContextData.pixmap.bitOrder = kQ3EndianBig; |
myPixMapDrawContextData.pixmap.byteOrder = kQ3EndianBig; |
myPixMapDrawContextData.pixmap.image = GetPixBaseAddr(myPixMap); |
// create draw context and return it |
myDrawContext = Q3PixmapDrawContext_New(&myPixMapDrawContextData); |
bail: |
return(myDrawContext); |
} |
////////// |
// |
// VR3DObjects_CreateCamera |
// Return a camera object for the QD3D objects in our model. |
// Note that some of the initial values are wrong and will soon be reset (in InitApplicationWindowObject). |
// |
////////// |
TQ3CameraObject VR3DObjects_CreateCamera (CGrafPtr thePort) |
{ |
TQ3CameraObject myCamera; |
TQ3ViewAngleAspectCameraData myCameraData; |
TQ3Point3D myFrom = kCameraOrigin; |
TQ3Point3D myTo = kPointOfInterest; |
TQ3Vector3D myUp = {0.0, 1.0, 0.0}; |
float myFOV = 1.00; // initial FOV really depends on QTVR instance, so we reset this later |
float myHither = (float)0.01; |
float myYon = 1000.0; |
myCameraData.cameraData.placement.cameraLocation = myFrom; |
myCameraData.cameraData.placement.pointOfInterest = myTo; |
myCameraData.cameraData.placement.upVector = myUp; |
myCameraData.cameraData.range.hither = myHither; |
myCameraData.cameraData.range.yon = myYon; |
// the default camera view port |
myCameraData.cameraData.viewPort.origin.x = -1.0F; |
myCameraData.cameraData.viewPort.origin.y = 1.0F; |
myCameraData.cameraData.viewPort.width = 2.0F; |
myCameraData.cameraData.viewPort.height = 2.0F; |
// some default FOV and aspect ratio values |
myCameraData.fov = myFOV; |
myCameraData.aspectRatioXToY = |
(float)(thePort->portRect.right - thePort->portRect.left) / |
(float)(thePort->portRect.bottom - thePort->portRect.top); |
myCamera = Q3ViewAngleAspectCamera_New(&myCameraData); |
return(myCamera); |
} |
////////// |
// |
// VR3DObjects_GetModelAttributeSet |
// Get the attribute set of a 3D model. |
// |
////////// |
TQ3AttributeSet VR3DObjects_GetModelAttributeSet (VRScript3DObjPtr thePointer) |
{ |
TQ3AttributeSet myAttributeSet = NULL; |
if ((thePointer != NULL) && (thePointer->fModel != NULL)) { |
TQ3GroupPosition myPosition; |
// get the position of the attribute set in the group |
Q3Group_GetFirstPositionOfType(thePointer->fModel, kQ3SetTypeAttribute, &myPosition); |
if (myPosition != 0) // get the attribute set |
Q3Group_GetPositionObject(thePointer->fModel, myPosition, &myAttributeSet); |
} |
return(myAttributeSet); |
} |
////////// |
// |
// VR3DObjects_SetSubdivisionStyle |
// Create a subdivision style and add it to the specified group. |
// |
////////// |
void VR3DObjects_SetSubdivisionStyle (TQ3GroupObject theGroup, short theNumDivisions) |
{ |
TQ3SubdivisionStyleData myStyleData; |
TQ3StyleObject myStyleObject; |
TQ3GroupPosition myPosition; |
// get the position of the geometry object in the group |
Q3Group_GetFirstPositionOfType(theGroup, kQ3ShapeTypeGeometry, &myPosition); |
// set a subdivision style |
myStyleData.method = kQ3SubdivisionMethodConstant; |
myStyleData.c1 = theNumDivisions; |
myStyleData.c2 = theNumDivisions; |
myStyleObject = Q3SubdivisionStyle_New(&myStyleData); |
Q3Group_AddObjectBefore(theGroup, myPosition, myStyleObject); |
Q3Object_Dispose(myStyleObject); |
} |
////////// |
// |
// VR3DObjects_SetColor |
// Set the diffuse color of a 3D object. |
// |
////////// |
void VR3DObjects_SetColor (WindowObject theWindowObject, UInt32 theEntryID, float theRed, float theGreen, float theBlue, UInt32 theOptions) |
{ |
#pragma unused(theOptions) |
VRScript3DObjPtr myPointer; |
TQ3AttributeSet myAttributeSet; |
myPointer = (VRScript3DObjPtr)VRScript_GetObjectByEntryID(theWindowObject, kVREntry_QD3DObject, theEntryID); |
if (myPointer != NULL) { |
myAttributeSet = VR3DObjects_GetModelAttributeSet(myPointer); |
if (myAttributeSet != NULL) { |
TQ3ColorRGB myColor; |
// remove the existing diffuse color attribute |
Q3AttributeSet_Clear(myAttributeSet, kQ3AttributeTypeDiffuseColor); |
Q3ColorRGB_Set(&myColor, theRed, theGreen, theBlue); |
Q3AttributeSet_Add(myAttributeSet, kQ3AttributeTypeDiffuseColor, &myColor); |
} |
Q3Object_Dispose(myAttributeSet); |
} |
} |
////////// |
// |
// VR3DObjects_SetTransparency |
// Set the transparency level of a 3D object. |
// |
////////// |
void VR3DObjects_SetTransparency (WindowObject theWindowObject, UInt32 theEntryID, float theRed, float theGreen, float theBlue, UInt32 theOptions) |
{ |
#pragma unused(theOptions) |
VRScript3DObjPtr myPointer; |
TQ3AttributeSet myAttributeSet; |
myPointer = (VRScript3DObjPtr)VRScript_GetObjectByEntryID(theWindowObject, kVREntry_QD3DObject, theEntryID); |
if (myPointer != NULL) { |
myAttributeSet = VR3DObjects_GetModelAttributeSet(myPointer); |
if (myAttributeSet != NULL) { |
TQ3ColorRGB myColor; |
// remove the existing transparency color attribute |
Q3AttributeSet_Clear(myAttributeSet, kQ3AttributeTypeTransparencyColor); |
Q3ColorRGB_Set(&myColor, theRed, theGreen, theBlue); |
Q3AttributeSet_Add(myAttributeSet, kQ3AttributeTypeTransparencyColor, &myColor); |
} |
Q3Object_Dispose(myAttributeSet); |
} |
} |
////////// |
// |
// VR3DObjects_SetInterpolation |
// Set the interpolation style of a 3D object. |
// |
////////// |
void VR3DObjects_SetInterpolation (WindowObject theWindowObject, UInt32 theEntryID, UInt32 theStyle, UInt32 theOptions) |
{ |
#pragma unused(theOptions) |
VRScript3DObjPtr myPointer; |
myPointer = (VRScript3DObjPtr)VRScript_GetObjectByEntryID(theWindowObject, kVREntry_QD3DObject, theEntryID); |
if (myPointer != NULL) |
Q3InterpolationStyle_Set(myPointer->fInterpolation, (TQ3InterpolationStyle)theStyle); |
} |
////////// |
// |
// VR3DObjects_SetBackfacing |
// Set the backfacing style of a 3D object. |
// |
////////// |
void VR3DObjects_SetBackfacing (WindowObject theWindowObject, UInt32 theEntryID, UInt32 theStyle, UInt32 theOptions) |
{ |
#pragma unused(theOptions) |
VRScript3DObjPtr myPointer; |
myPointer = (VRScript3DObjPtr)VRScript_GetObjectByEntryID(theWindowObject, kVREntry_QD3DObject, theEntryID); |
if (myPointer != NULL) |
Q3BackfacingStyle_Set(myPointer->fBackFacing, (TQ3BackfacingStyle)theStyle); |
} |
////////// |
// |
// VR3DObjects_SetFill |
// Set the fill style of a 3D object. |
// |
////////// |
void VR3DObjects_SetFill (WindowObject theWindowObject, UInt32 theEntryID, UInt32 theStyle, UInt32 theOptions) |
{ |
#pragma unused(theOptions) |
VRScript3DObjPtr myPointer; |
myPointer = (VRScript3DObjPtr)VRScript_GetObjectByEntryID(theWindowObject, kVREntry_QD3DObject, theEntryID); |
if (myPointer != NULL) |
Q3FillStyle_Set(myPointer->fFillStyle, (TQ3FillStyle)theStyle); |
} |
////////// |
// |
// VR3DObjects_SetLocation |
// Set the location of a 3D object. |
// |
////////// |
void VR3DObjects_SetLocation (WindowObject theWindowObject, UInt32 theEntryID, float theX, float theY, float theZ, UInt32 theOptions) |
{ |
VRScript3DObjPtr myPointer; |
myPointer = (VRScript3DObjPtr)VRScript_GetObjectByEntryID(theWindowObject, kVREntry_QD3DObject, theEntryID); |
if (myPointer != NULL) { |
if (theOptions == kVRValue_Relative) { |
myPointer->fGroupCenter.x -= theX; |
myPointer->fGroupCenter.y += theY; |
myPointer->fGroupCenter.z -= theZ; |
} else { |
myPointer->fGroupCenter.x = -1 * theX; |
myPointer->fGroupCenter.y = theY; |
myPointer->fGroupCenter.z = -1 * theZ; |
} |
} |
} |
////////// |
// |
// VR3DObjects_SetRotation |
// Set the rotation factors of a 3D object. |
// |
////////// |
void VR3DObjects_SetRotation (WindowObject theWindowObject, UInt32 theEntryID, float theX, float theY, float theZ, UInt32 theOptions) |
{ |
VRScript3DObjPtr myPointer; |
myPointer = (VRScript3DObjPtr)VRScript_GetObjectByEntryID(theWindowObject, kVREntry_QD3DObject, theEntryID); |
if (myPointer != NULL) { |
if (theOptions == kVRValue_Relative) { |
myPointer->fRotateFactors.x += theX; |
myPointer->fRotateFactors.y += theY; |
myPointer->fRotateFactors.z += theZ; |
} else { |
myPointer->fRotateFactors.x = theX; |
myPointer->fRotateFactors.y = theY; |
myPointer->fRotateFactors.z = theZ; |
} |
} |
} |
////////// |
// |
// VR3DObjects_SetRotationState |
// Set the rotation state (on or off) of a 3D object. |
// |
////////// |
void VR3DObjects_SetRotationState (WindowObject theWindowObject, UInt32 theEntryID, Boolean theState, UInt32 theOptions) |
{ |
#pragma unused(theOptions) |
VRScript3DObjPtr myPointer; |
myPointer = (VRScript3DObjPtr)VRScript_GetObjectByEntryID(theWindowObject, kVREntry_QD3DObject, theEntryID); |
if (myPointer != NULL) { |
if (theState == kVRState_Toggle) |
theState = !(myPointer->fModelIsAnimated); |
myPointer->fModelIsAnimated = theState; |
} |
} |
////////// |
// |
// VR3DObjects_SetVisibleState |
// Set the visibility state (on or off) of a 3D object. |
// |
////////// |
void VR3DObjects_SetVisibleState (WindowObject theWindowObject, UInt32 theEntryID, Boolean theState, UInt32 theOptions) |
{ |
#pragma unused(theOptions) |
VRScript3DObjPtr myPointer; |
myPointer = (VRScript3DObjPtr)VRScript_GetObjectByEntryID(theWindowObject, kVREntry_QD3DObject, theEntryID); |
if (myPointer != NULL) { |
if (theState == kVRState_Toggle) |
theState = !(myPointer->fModelIsVisible); |
myPointer->fModelIsVisible = theState; |
} |
} |
////////// |
// |
// VR3DObjects_SetTexture |
// Set the texture of a 3D object. |
// |
////////// |
void VR3DObjects_SetTexture (WindowObject theWindowObject, UInt32 theEntryID, Boolean isMovie, UInt32 theOptions, char *thePathName) |
{ |
#pragma unused(theOptions) |
VRScript3DObjPtr myPointer; |
myPointer = (VRScript3DObjPtr)VRScript_GetObjectByEntryID(theWindowObject, kVREntry_QD3DObject, theEntryID); |
if (myPointer != NULL) { |
// delete any existing texture structure, since we'll soon create another one |
if (myPointer->fTexture != NULL) { |
VR3DTexture_Delete(myPointer->fTexture); |
myPointer->fTexture = NULL; |
} |
myPointer->fTextureIsMovie = isMovie; |
myPointer->fTexture = VR3DTexture_New(thePathName, isMovie); |
if (myPointer->fTexture != NULL) |
VR3DTexture_AddToGroup(myPointer->fTexture, myPointer->fModel); |
} |
} |
////////// |
// |
// VR3DObjects_AnimateModel |
// Animate the QuickDraw 3D model. |
// |
////////// |
void VR3DObjects_AnimateModel (VRScript3DObjPtr thePointer) |
{ |
TQ3Matrix4x4 myMatrix; |
TQ3Vector3D myVector; |
if (thePointer != NULL) { |
// rotate the object around the local x axis |
Q3Vector3D_Set(&myVector, 1.0, 0.0, 0.0); |
Q3Matrix4x4_SetRotateAboutAxis(&myMatrix, &(thePointer->fGroupCenter), &myVector, thePointer->fRotateFactors.x); |
Q3Matrix4x4_Multiply(&(thePointer->fRotation), &myMatrix, &(thePointer->fRotation)); |
// rotate the object around the local y axis |
Q3Vector3D_Set(&myVector, 0.0, 1.0, 0.0); |
Q3Matrix4x4_SetRotateAboutAxis(&myMatrix, &(thePointer->fGroupCenter), &myVector, thePointer->fRotateFactors.y); |
Q3Matrix4x4_Multiply(&(thePointer->fRotation), &myMatrix, &(thePointer->fRotation)); |
// rotate the object around the local z axis |
Q3Vector3D_Set(&myVector, 0.0, 0.0, 1.0); |
Q3Matrix4x4_SetRotateAboutAxis(&myMatrix, &(thePointer->fGroupCenter), &myVector, thePointer->fRotateFactors.z); |
Q3Matrix4x4_Multiply(&(thePointer->fRotation), &myMatrix, &(thePointer->fRotation)); |
} |
} |
////////// |
// |
// VR3DObjects_DrawModel |
// Draw any QuickDraw 3D models into the (offscreen GWorld) pixmap draw context. |
// This routine is called only in the prescreen buffer imaging complete procedure. |
// |
////////// |
TQ3Status VR3DObjects_DrawModel (WindowObject theWindowObject) |
{ |
ApplicationDataHdl myAppData; |
TQ3Status myStatus = kQ3Failure; |
TQ3ViewObject myView; |
VRScript3DObjPtr myPointer; |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject); |
if (myAppData == NULL) |
return(myStatus); |
myView = (**myAppData).fView; |
if (myView == NULL) |
return(myStatus); |
// if the camera needs to be updated, do so now |
if ((**myAppData).fViewHasChanged) |
VR3DObjects_SetCamera(theWindowObject); |
// our rendering loop |
myStatus = Q3View_StartRendering(myView); |
if (myStatus != kQ3Failure) |
do { |
// walk our linked list of 3D objects and render any visible objects, |
// after updating any object-specific properties |
myPointer = (VRScript3DObjPtr)(**myAppData).fListArray[kVREntry_QD3DObject]; |
while (myPointer != NULL) { |
if (myPointer->fModelIsVisible) { |
// if there is an active movie texture, advance the movie to the next frame |
if (myPointer->fTexture) |
if (myPointer->fTextureIsMovie) |
VR3DTexture_NextFrame(myPointer->fTexture); |
// if animation is active, animate the model |
if (myPointer->fModelIsAnimated) |
VR3DObjects_AnimateModel(myPointer); |
// submit the model |
Q3Push_Submit(myView); |
VR3DObjects_SubmitModel(myPointer, myView); |
Q3Pop_Submit(myView); |
} |
myPointer = myPointer->fNextEntry; |
} |
} while (Q3View_EndRendering(myView) == kQ3ViewStatusRetraverse); |
// wait until the rendering is completed... |
Q3View_Sync(myView); |
return(myStatus); |
} |
////////// |
// |
// VR3DObjects_SubmitModel |
// Submit a QuickDraw 3D model for rendering, picking, bounding, or writing. |
// |
////////// |
TQ3Status VR3DObjects_SubmitModel (VRScript3DObjPtr thePointer, TQ3ViewObject theView) |
{ |
TQ3Vector3D myTranslate; |
TQ3Vector3D myScale; |
if (thePointer != NULL) { |
myTranslate = *(TQ3Vector3D *) &(thePointer->fGroupCenter); |
myScale.x = myScale.y = myScale.z = thePointer->fGroupScale; |
Q3Style_Submit(thePointer->fInterpolation, theView); |
Q3Style_Submit(thePointer->fBackFacing, theView); |
Q3Style_Submit(thePointer->fFillStyle, theView); |
Q3MatrixTransform_Submit(&(thePointer->fRotation), theView); |
Q3TranslateTransform_Submit(&myTranslate, theView); |
Q3ScaleTransform_Submit(&myScale, theView); |
Q3DisplayGroup_Submit(thePointer->fModel, theView); |
return(kQ3Success); |
} |
return(kQ3Failure); |
} |
////////// |
// |
// VR3DObjects_GetModelFromFile |
// Open a model contained in a 3DMF file. |
// |
////////// |
TQ3GroupObject VR3DObjects_GetModelFromFile (char *thePathName) |
{ |
TQ3StorageObject myStorage; |
TQ3GroupObject myModel; |
OSErr myErr = noErr; |
#if TARGET_OS_MAC |
FSSpec myFSSpec; |
short myRefNum; |
// for Macintosh, open the file and create a Mac storage object |
FSMakeFSSpec(0, 0L, c2pstr(thePathName), &myFSSpec); |
myErr = FSpOpenDF(&myFSSpec, fsRdPerm, &myRefNum); |
if (myErr == noErr) |
myStorage = Q3MacintoshStorage_New(myRefNum); |
#endif |
#if TARGET_OS_WIN32 |
// for Windows, create a UNIX pathname storage object (Q3UnixPathStorage_New calls fopen internally) |
myStorage = Q3UnixPathStorage_New(thePathName); |
#endif |
if (myStorage != NULL) { |
TQ3FileObject myFile; |
TQ3Status myStatus; |
TQ3Object myObject; |
TQ3Boolean isEOF; |
// create a file object |
myFile = Q3File_New(); |
if (myFile == NULL) |
return(NULL); |
// associate the storage with the file |
Q3File_SetStorage(myFile, myStorage); |
Q3Object_Dispose(myStorage); |
// read the drawable objects from the file object into a new group |
myModel = Q3DisplayGroup_New(); |
if (myModel != NULL) { |
myStatus = Q3File_OpenRead(myFile, NULL); |
if (myStatus == kQ3Success) { |
do { |
myObject = Q3File_ReadObject(myFile); |
// if object read is not NULL, then process object |
if (myObject != NULL) { |
if (Q3Object_IsDrawable(myObject)) |
Q3Group_AddObject(myModel, myObject); |
Q3Object_Dispose(myObject); |
} |
// check to see whether we've reached the end of file yet |
isEOF = Q3File_IsEndOfFile(myFile); |
} while (isEOF == kQ3False); |
} |
} |
// close the file object |
Q3File_Close(myFile); |
} |
// apply illumination shader to model |
myModel = VR3DObjects_CreateDefaultGroup(myModel); |
#if TARGET_OS_MAC |
// close the file, since we've got the data we need |
FSClose(myRefNum); |
#endif |
#if TARGET_OS_WIN32 |
// no action required for UNIX pathname storage |
#endif |
return(myModel); |
} |
/////////// |
// |
// VR3DObjects_PrescreenRoutine |
// Draw the 3D objects into the current graphics world. |
// |
////////// |
void VR3DObjects_PrescreenRoutine (QTVRInstance theInstance, WindowObject theWindowObject) |
{ |
#pragma unused(theInstance) |
ApplicationDataHdl myAppData; |
CGrafPtr myGWorld; |
GDHandle myGDevice; |
PixMapHandle mySrcPixMap; |
PixMapHandle myDstPixMap; |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject); |
if (myAppData == NULL) |
return; |
// render any objects into the pixmap draw context |
VR3DObjects_DrawModel(theWindowObject); |
// get the current graphics world |
// (on entry, the current graphics world is set to the prescreen buffer) |
GetGWorld(&myGWorld, &myGDevice); |
RGBBackColor(&(**myAppData).fQD3DKeyColor); |
OpColor(&(**myAppData).fQD3DKeyColor); |
mySrcPixMap = GetGWorldPixMap((**myAppData).fQD3DDCGWorld); |
myDstPixMap = GetGWorldPixMap(myGWorld); |
// we don't need to lock the source pixel map, since it was locked when the draw context was created |
LockPixels(myDstPixMap); |
// copy the rendered image to the current graphics world |
CopyBits((BitMapPtr)(*mySrcPixMap), |
(BitMapPtr)(*myDstPixMap), |
&(**myAppData).fQD3DDCGWorld->portRect, |
&myGWorld->portRect, |
srcCopy | transparent, |
NULL); |
UnlockPixels(myDstPixMap); |
} |
////////// |
// |
// VR3DObjects_SetCamera |
// Set the FOV of the 3D camera associated with the specified window object; |
// then set the point-of-interest and the location of the 3D camera. |
// |
////////// |
void VR3DObjects_SetCamera (WindowObject theWindowObject) |
{ |
ApplicationDataHdl myAppData; |
TQ3ViewObject myView; |
TQ3CameraObject myCamera; |
TQ3CameraPlacement myCameraPos; |
QTVRInstance myInstance; |
if (theWindowObject == NULL) |
return; |
// get the QTVR instance associated with the specified window |
myInstance = (**theWindowObject).fInstance; |
if (myInstance == NULL) |
return; |
// get the view object associated with the specified window |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject); |
if (myAppData == NULL) |
return; |
myView = (**myAppData).fView; |
// get the camera associated with the view object |
Q3View_GetCamera(myView, &myCamera); |
if (myCamera != NULL) { |
float myFOV, myPan, myTilt; |
TQ3Point3D myPoint; |
TQ3Vector3D myUpVector; |
// set the camera's field of view |
myFOV = QTVRGetFieldOfView(myInstance); |
if ((**myAppData).fQD3DFOVIsVert) { |
Q3ViewAngleAspectCamera_SetFOV(myCamera, myFOV); |
} else { |
float myRatio; |
Q3ViewAngleAspectCamera_GetAspectRatio(myCamera, &myRatio); |
Q3ViewAngleAspectCamera_SetFOV(myCamera, myFOV * myRatio); |
} |
// get the camera's current pan and tilt angles |
myPan = QTVRGetPanAngle(myInstance); |
myTilt = QTVRGetTiltAngle(myInstance); |
// calculate the new point-of-interest |
myPoint.x = sin(myPan) * cos(myTilt) * k3DObjectDistance; |
myPoint.y = sin(myTilt) * k3DObjectDistance; |
myPoint.z = cos(myPan) * cos(myTilt) * k3DObjectDistance; |
// calculate the new up vector of the camera |
myUpVector.x = -sin(myTilt) * sin(myPan); |
myUpVector.y = +cos(myTilt); |
myUpVector.z = -sin(myTilt) * cos(myPan); |
Q3Vector3D_Normalize(&myUpVector, &myUpVector); |
Q3Camera_GetPlacement(myCamera, &myCameraPos); |
myCameraPos.upVector = myUpVector; |
myCameraPos.pointOfInterest = myPoint; |
myCameraPos.cameraLocation = kCameraOrigin; |
Q3Camera_SetPlacement(myCamera, &myCameraPos); |
// update the QD3D camera |
Q3View_SetCamera(myView, myCamera); |
Q3Object_Dispose(myCamera); |
} |
} |
////////// |
// |
// VR3DObjects_SetCameraAspectRatio |
// Adjust the aspect ratio of the QuickDraw 3D camera based on current window shape. |
// |
////////// |
void VR3DObjects_SetCameraAspectRatio (WindowObject theWindowObject) |
{ |
ApplicationDataHdl myAppData; |
TQ3ViewObject myView; |
TQ3CameraObject myCamera; |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject); |
if (myAppData == NULL) |
return; |
// get the window's view and camera objects |
myView = (**myAppData).fView; |
Q3View_GetCamera(myView, &myCamera); |
// adjust the aspect ratio of the camera |
if (myCamera != NULL) { |
Rect myRect; |
float myRatio; |
// get the size of the specified window |
if ((**theWindowObject).fMovie != NULL) |
GetMovieBox((**theWindowObject).fMovie, &myRect); |
// calculate the aspect ratio of the movie rectangle |
myRatio = (float)(myRect.right - myRect.left) / (float)(myRect.bottom - myRect.top); |
// determine whether QD3D FOV is horizontal or vertical |
(**myAppData).fQD3DFOVIsVert = (myRatio >= 1.0); |
// adjust camera's aspect ratio |
Q3ViewAngleAspectCamera_SetAspectRatio(myCamera, myRatio); |
Q3Object_Dispose(myCamera); |
} |
} |
////////// |
// |
// VR3DObjects_UpdateDrawContext |
// Delete current QD3D draw context and create a new one based on current window size. |
// |
////////// |
void VR3DObjects_UpdateDrawContext (WindowObject theWindowObject) |
{ |
ApplicationDataHdl myAppData; |
TQ3ViewObject myView; |
TQ3DrawContextObject myDrawContext; |
CGrafPtr mySavedPort; |
GDHandle mySavedDevice; |
Rect myRect; |
OSErr myErr = noErr; |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject); |
if (myAppData == NULL) |
return; |
// lock the application data handle |
HLock((Handle)myAppData); |
// get the size of the movie in the specified window |
if ((**theWindowObject).fMovie != NULL) |
GetMovieBox((**theWindowObject).fMovie, &myRect); |
// get the current drawing environment |
GetGWorld(&mySavedPort, &mySavedDevice); |
// update the pixmap draw context GWorld: dispose of the existing one and then allocate a new one |
DisposeGWorld((**myAppData).fQD3DDCGWorld); |
(**myAppData).fQD3DDCGWorld = NULL; |
myErr = QTNewGWorld(&(**myAppData).fQD3DDCGWorld, kOffscreenPixelType, &myRect, NULL, NULL, kICMTempThenAppMemory); |
if (myErr != noErr) |
goto bail; |
// get the window's view and draw context objects |
myView = (**myAppData).fView; |
Q3View_GetDrawContext(myView, &myDrawContext); |
// associate the new GWorld with the QD3D draw context |
if (myDrawContext != NULL) { |
// get rid of existing draw context |
Q3Object_Dispose(myDrawContext); |
// create and set new draw context |
myDrawContext = VR3DObjects_CreateDrawContext((**myAppData).fQD3DDCGWorld); |
Q3View_SetDrawContext(myView, myDrawContext); |
Q3Object_Dispose(myDrawContext); |
} |
bail: |
// restore the original drawing environment |
SetGWorld(mySavedPort, mySavedDevice); |
HUnlock((Handle)myAppData); |
} |
////////// |
// |
// VR3DObjects_DumpEntryMem |
// Release any memory associated with the specified list entry. |
// |
////////// |
void VR3DObjects_DumpEntryMem (VRScript3DObjPtr theEntry) |
{ |
if (theEntry != NULL) { |
if (theEntry->fModel) |
Q3Object_Dispose(theEntry->fModel); |
if (theEntry->fInterpolation) |
Q3Object_Dispose(theEntry->fInterpolation); |
if (theEntry->fBackFacing) |
Q3Object_Dispose(theEntry->fBackFacing); |
if (theEntry->fFillStyle) |
Q3Object_Dispose(theEntry->fFillStyle); |
VR3DTexture_Delete(theEntry->fTexture); |
} |
} |
#endif // QD3D_AVAIL |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14