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.
sources/PickOne_Support.c
/* PickOne_Support.c |
Quickdraw 3D sample code |
Nick Thompson |
Scott Kuechle - March 1997 |
(c)1994-97 Apple computer Inc., All Rights Reserved |
*/ |
/* -------------------------------------------------------------------- |
** Includes |
*/ |
#include "PickOne_Support.h" |
#include "PickOne_documentStructure.h" |
#include "QD3DDrawContext.h" |
#include "QD3DRenderer.h" |
#include "QD3DShader.h" |
#include "QD3DCamera.h" |
#include "QD3DLight.h" |
#include "QD3DGeometry.h" |
#include "QD3DGroup.h" |
#include "QD3DMath.h" |
#include "QD3DTransform.h" |
/* -------------------------------------------------------------------- |
** Global Variables |
*/ |
static TQ3Point3D documentGroupCenter; |
static float documentGroupScale; |
/* -------------------------------------------------------------------- |
** Local Functions |
*/ |
TQ3DrawContextObject MyNewDrawContext(WindowPtr theWindow) ; |
TQ3CameraObject MyNewCamera(WindowPtr theWindow) ; |
TQ3GroupObject MyNewLights(void) ; |
TQ3ViewObject MyNewView(WindowPtr theWindow) |
{ |
TQ3Status myStatus; |
TQ3ViewObject myView; |
TQ3DrawContextObject myDrawContext; |
TQ3RendererObject myRenderer; |
TQ3CameraObject myCamera; |
TQ3GroupObject myLights; |
myView = Q3View_New(); |
/* Create and set draw context. */ |
if ((myDrawContext = MyNewDrawContext(theWindow)) == nil ) |
goto bail; |
if ((myStatus = Q3View_SetDrawContext(myView, myDrawContext)) == kQ3Failure ) |
goto bail; |
Q3Object_Dispose( myDrawContext ) ; |
/* Create and set renderer. */ |
/* this would use the wireframe renderer */ |
/* Not very useful for this app */ |
#if 0 |
myRenderer = Q3Renderer_NewFromType(kQ3RendererTypeWireFrame); |
if ((myStatus = Q3View_SetRenderer(myView, myRenderer)) == kQ3Failure ) { |
goto bail; |
} |
#else |
/* this would use the interactive plug-in renderer */ |
if ((myRenderer = Q3Renderer_NewFromType(kQ3RendererTypeInteractive)) != nil ) { |
if ((myStatus = Q3View_SetRenderer(myView, myRenderer)) == kQ3Failure ) { |
goto bail; |
} |
} |
else { |
goto bail; |
} |
#endif |
Q3Object_Dispose( myRenderer ) ; |
/* Create and set camera. */ |
if ( (myCamera = MyNewCamera(theWindow)) == nil ) |
goto bail; |
if ((myStatus = Q3View_SetCamera(myView, myCamera)) == kQ3Failure ) |
goto bail; |
Q3Object_Dispose( myCamera ) ; |
/* Create and set lights. */ |
if ((myLights = MyNewLights()) == nil ) |
goto bail; |
if ((myStatus = Q3View_SetLightGroup(myView, myLights)) == kQ3Failure ) |
goto bail; |
Q3Object_Dispose(myLights); |
/* Done!!! */ |
return ( myView ); |
bail: |
/* If any of the above failed, then don't return a view. */ |
return ( nil ); |
} |
/* ---------------------------------------------------------------------------------- */ |
TQ3DrawContextObject MyNewDrawContext(WindowPtr theWindow) |
{ |
TQ3DrawContextData myDrawContextData; |
TQ3MacDrawContextData myMacDrawContextData; |
TQ3ColorARGB ClearColor; |
TQ3DrawContextObject myDrawContext ; |
/* Set the background color. */ |
ClearColor.a = 1.0; |
ClearColor.r = 0.0; |
ClearColor.g = 0.2; |
ClearColor.b = 1.0; |
/* Fill in draw context data. */ |
myDrawContextData.clearImageMethod = kQ3ClearMethodWithColor; |
myDrawContextData.clearImageColor = ClearColor; |
myDrawContextData.paneState = kQ3False; |
myDrawContextData.maskState = kQ3False; |
myDrawContextData.doubleBufferState = kQ3True; |
myMacDrawContextData.drawContextData = myDrawContextData; |
myMacDrawContextData.window = (CGrafPtr) theWindow; /* this is the window associated with the view */ |
myMacDrawContextData.library = kQ3Mac2DLibraryNone; |
myMacDrawContextData.viewPort = nil; |
myMacDrawContextData.grafPort = nil; |
/* Create draw context and return it, if itÕs nil the caller must handle */ |
myDrawContext = Q3MacDrawContext_New(&myMacDrawContextData) ; |
return myDrawContext ; |
} |
/* ---------------------------------------------------------------------------------- */ |
TQ3CameraObject MyNewCamera(WindowPtr theWindow) |
{ |
TQ3ViewAngleAspectCameraData perspectiveData; |
TQ3CameraData someCameraData; |
TQ3CameraObject camera; |
TQ3Point3D from = { 0.0, 0.0, 3.0 }; |
TQ3Point3D to = { 0.0, 0.0, 0.0 }; |
TQ3Vector3D up = { 0.0, 1.0, 0.0 }; |
float fieldOfView = 1.0; |
float hither = 0.00001; |
float yon = 10; |
TQ3Status returnVal = kQ3Failure ; |
someCameraData.placement.cameraLocation = from; |
someCameraData.placement.pointOfInterest = to; |
someCameraData.placement.upVector = up; |
someCameraData.range.hither = hither; |
someCameraData.range.yon = yon; |
someCameraData.viewPort.origin.x = -1.0; |
someCameraData.viewPort.origin.y = 1.0; |
someCameraData.viewPort.width = 2.0; |
someCameraData.viewPort.height = 2.0; |
perspectiveData.cameraData = someCameraData; |
perspectiveData.fov = fieldOfView; |
perspectiveData.aspectRatioXToY = |
(float) (theWindow->portRect.right - theWindow->portRect.left) / |
(float) (theWindow->portRect.bottom - theWindow->portRect.top); |
camera = Q3ViewAngleAspectCamera_New(&perspectiveData); |
return camera ; |
} |
/* ---------------------------------------------------------------------------------- */ |
TQ3GroupObject MyNewLights(void) |
{ |
TQ3GroupPosition myGroupPosition; |
TQ3GroupObject myLightList; |
TQ3LightData myLightData; |
TQ3PointLightData myPointLightData; |
TQ3DirectionalLightData myDirectionalLightData; |
TQ3LightObject myAmbientLight, myPointLight, myFillLight; |
TQ3Point3D pointLocation = { -10.0, 0.0, 10.0 }; |
TQ3Vector3D fillDirection = { 10.0, 0.0, 10.0 }; |
TQ3ColorRGB WhiteLight = { 1.0, 1.0, 1.0 }; |
/* Set up light data for ambient light. This light data will be used for point and fill */ |
/* light also. */ |
myLightData.isOn = kQ3True; |
myLightData.color = WhiteLight; |
/* Create ambient light. */ |
myLightData.brightness = .3; |
myAmbientLight = Q3AmbientLight_New(&myLightData); |
if ( myAmbientLight == nil ) |
goto bail; |
/* Create point light. */ |
myLightData.brightness = 0.60; |
myPointLightData.lightData = myLightData; |
myPointLightData.castsShadows = kQ3False; |
myPointLightData.attenuation = kQ3AttenuationTypeNone; |
myPointLightData.location = pointLocation; |
myPointLight = Q3PointLight_New(&myPointLightData); |
if ( myPointLight == nil ) |
goto bail; |
/* Create fill light. */ |
myLightData.brightness = .2; |
myDirectionalLightData.lightData = myLightData; |
myDirectionalLightData.castsShadows = kQ3False; |
myDirectionalLightData.direction = fillDirection; |
myFillLight = Q3DirectionalLight_New(&myDirectionalLightData); |
if ( myFillLight == nil ) |
goto bail; |
/* Create light group and add each of the lights into the group. */ |
myLightList = Q3LightGroup_New(); |
if ( myLightList == nil ) |
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 ) ; |
/* Done! */ |
return ( myLightList ); |
bail: |
/* If any of the above failed, then return nothing! */ |
return ( nil ); |
} |
static TQ3GroupPosition MyAddTransformedObjectToGroup( TQ3GroupObject theGroup, TQ3Object theObject, TQ3Vector3D *translation ) |
{ |
TQ3TransformObject transform; |
transform = Q3TranslateTransform_New(translation); |
Q3Group_AddObject(theGroup, transform); |
Q3Object_Dispose(transform); |
return Q3Group_AddObject(theGroup, theObject); |
} |
TQ3GroupObject MyNewModel() |
{ |
TQ3GroupObject myGroup = NULL; |
TQ3GroupObject mySubGroupCone = NULL, |
mySubGroupEllipsoid = NULL, |
mySubGroupBox = NULL; |
TQ3GeometryObject myEllipsoid, cone, myBox; |
TQ3ShaderObject myIlluminationShader ; |
TQ3DisplayGroupState theState; |
TQ3StyleObject theStyleObject; |
TQ3SubdivisionStyleData theSubdivisionStyleData; |
if ((myGroup = Q3DisplayGroup_New()) != NULL ) { |
/* Define a shading type for the group */ |
/* and add the shader to the group */ |
myIlluminationShader = Q3PhongIllumination_New(); |
/* myIlluminationShader = Q3LambertIllumination_New(); |
*/ Q3Group_AddObject(myGroup, myIlluminationShader); |
/* dispose of the objects we created here */ |
if( myIlluminationShader ) |
Q3Object_Dispose(myIlluminationShader); |
theStyleObject = Q3InterpolationStyle_New(kQ3InterpolationStyleVertex); |
Q3Group_AddObject(myGroup, theStyleObject) ; |
Q3Object_Dispose(theStyleObject); |
theSubdivisionStyleData.method = kQ3SubdivisionMethodConstant; |
theSubdivisionStyleData.c1 = 16; |
theSubdivisionStyleData.c2 = 16; |
theStyleObject = Q3SubdivisionStyle_New(&theSubdivisionStyleData); |
Q3Group_AddObject(myGroup, theStyleObject) ; |
Q3Object_Dispose(theStyleObject); |
if ((mySubGroupBox = Q3OrderedDisplayGroup_New()) != NULL ) { |
// Define a shading type for the group |
// and add the shader to the group |
myIlluminationShader = Q3PhongIllumination_New(); |
Q3Group_AddObject(mySubGroupBox, myIlluminationShader); |
if( myIlluminationShader ) |
Q3Object_Dispose(myIlluminationShader); |
myBox = MyNewBox(); |
if( myBox ) { |
Q3Group_AddObject(mySubGroupBox, myBox) ; |
Q3Object_Dispose( myBox ); |
} |
myAddMatrixTransformToGroup( mySubGroupBox ); |
mySetGroupState(mySubGroupBox); |
Q3Group_AddObject(myGroup, mySubGroupBox) ; |
Q3Object_Dispose(mySubGroupBox); |
} |
if ((mySubGroupEllipsoid = Q3OrderedDisplayGroup_New()) != NULL ) { |
myEllipsoid = MyNewEllipsoid(); |
if( myEllipsoid ) { |
Q3Group_AddObject(mySubGroupEllipsoid, myEllipsoid); |
Q3Object_Dispose( myEllipsoid ); |
} |
myAddMatrixTransformToGroup( mySubGroupEllipsoid ); |
mySetGroupState(mySubGroupEllipsoid); |
Q3Group_AddObject(myGroup, mySubGroupEllipsoid) ; |
Q3Object_Dispose(mySubGroupEllipsoid); |
} |
if ((mySubGroupCone = Q3OrderedDisplayGroup_New()) != NULL ) { |
cone = MyNewCone(); |
if( cone ) { |
Q3Group_AddObject(mySubGroupCone, cone); |
Q3Object_Dispose( cone ); |
} |
myAddMatrixTransformToGroup( mySubGroupCone ); |
mySetGroupState(mySubGroupCone); |
Q3Group_AddObject(myGroup, mySubGroupCone) ; |
Q3Object_Dispose(mySubGroupCone); |
} |
} |
/* Now, get the state of the current model */ |
Q3DisplayGroup_GetState(myGroup, &theState); |
/* we don't want to push and pop for PERFORMANCE!! */ |
theState = theState | (kQ3DisplayGroupStateMaskIsInline); |
Q3DisplayGroup_SetState(myGroup, theState); |
theState = theState | (kQ3DisplayGroupStateMaskIsPicked); |
Q3DisplayGroup_SetState(myGroup, theState); |
/* Done! */ |
return ( myGroup ); |
} |
/* ----------------------------------------------------------------------------------------------- */ |
TQ3Status GetDocumentGroupBoundingBox( |
TQ3ViewObject view, |
TQ3GroupObject group, |
TQ3BoundingBox *viewBBox) |
{ |
TQ3Status status; |
TQ3ViewStatus viewStatus ; |
status = Q3View_StartBoundingBox( view, kQ3ComputeBoundsExact ); |
do { |
status = Q3DisplayGroup_Submit(group, view); |
} while((viewStatus = Q3View_EndBoundingBox( view, viewBBox )) == kQ3ViewStatusRetraverse ); |
return status ; |
} |
TQ3Status ComputeCenterOfBoundingBox(TQ3BoundingBox *viewBBox, |
TQ3Point3D *center) |
{ |
if (viewBBox->isEmpty == kQ3True) { |
return kQ3Failure; |
} |
else { |
center->x = (viewBBox->min.x + viewBBox->max.x)/2; |
center->y = (viewBBox->min.y + viewBBox->max.y)/2; |
center->z = (viewBBox->min.z + viewBBox->max.z)/2; |
return kQ3Success; |
} |
} |
void MyColorBoxFaces( TQ3BoxData *myBoxData ) |
{ |
TQ3ColorRGB faceColor ; |
short face ; |
// sanity check - you need to have set up |
// the face attribute set for the box data |
// before calling this. |
if( myBoxData->faceAttributeSet == NULL ) |
return ; |
// make each face of a box a different color |
for( face = 0; face < 6; face++) { |
myBoxData->faceAttributeSet[face] = Q3AttributeSet_New(); |
switch( face ) { |
case 0: |
faceColor.r = 0.0; |
faceColor.g = 1.0; |
faceColor.b = 0.0; |
break; |
case 1: |
faceColor.r = 0.0; |
faceColor.g = 1.0; |
faceColor.b = 0.0; |
break; |
case 2: |
faceColor.r = 0.0; |
faceColor.g = 1.0; |
faceColor.b = 0.0; |
break; |
case 3: |
faceColor.r = 0.0; |
faceColor.g = 1.0; |
faceColor.b = 0.0; |
break; |
case 4: |
faceColor.r = 0.0; |
faceColor.g = 1.0; |
faceColor.b = 0.0; |
break; |
case 5: |
faceColor.r = 0.0; |
faceColor.g = 1.0; |
faceColor.b = 0.0; |
break; |
} |
Q3AttributeSet_Add(myBoxData->faceAttributeSet[face], kQ3AttributeTypeDiffuseColor, &faceColor); |
} |
} |
TQ3GroupObject MyNewBox() |
{ |
TQ3BoxData myBoxData; |
TQ3GeometryObject myBox = NULL; |
TQ3SetObject faces[6] ; |
short face ; |
myBoxData.boxAttributeSet = nil; |
myBoxData.faceAttributeSet = faces; |
MyColorBoxFaces( &myBoxData ) ; |
/* create the box itself */ |
Q3Point3D_Set(&myBoxData.origin, 0.5, 0, 0); |
Q3Vector3D_Set(&myBoxData.orientation, 0, 0.5, 0); |
Q3Vector3D_Set(&myBoxData.majorAxis, 0, 0, 0.5); |
Q3Vector3D_Set(&myBoxData.minorAxis, 0.5, 0, 0); |
myBox = Q3Box_New(&myBoxData); |
for( face = 0; face < 6; face++) { |
if( myBoxData.faceAttributeSet[face] != NULL ) |
Q3Object_Dispose(myBoxData.faceAttributeSet[face]); |
} |
return myBox; |
} |
TQ3GroupObject MyNewCone() |
{ |
TQ3ConeData theConeData; |
TQ3GeometryObject cone = NULL; |
TQ3ColorRGB theColor; |
TQ3Status status; |
Q3Point3D_Set(&theConeData.origin, 0, 0, 0); |
Q3Vector3D_Set(&theConeData.orientation, 0, 1.0, 0); |
Q3Vector3D_Set(&theConeData.majorRadius, 0.0, 0.0, 0.26); |
Q3Vector3D_Set(&theConeData.minorRadius, 0.26, 0.0, 0.0); |
theConeData.uMin = 0.0; theConeData.uMax = 1.0; |
theConeData.vMin = 0.0; theConeData.vMax = 1.0; |
theConeData.caps = kQ3EndCapMaskBottom; |
theConeData.interiorAttributeSet = NULL; |
theConeData.bottomAttributeSet = NULL; |
theConeData.faceAttributeSet = NULL; |
theConeData.coneAttributeSet = Q3AttributeSet_New() ; |
theColor.r = 1.0; theColor.g = 1.0; theColor.b = 0.0; |
status = Q3AttributeSet_Add (theConeData.coneAttributeSet, |
kQ3AttributeTypeDiffuseColor, |
&theColor); |
cone = Q3Cone_New(&theConeData); |
Q3Object_Dispose(theConeData.coneAttributeSet); |
return cone; |
} |
TQ3GroupObject MyNewEllipsoid() |
{ |
TQ3GeometryObject myEllipsoid = NULL; |
TQ3EllipsoidData myEllipsoidData; |
TQ3ColorRGB theColor; |
TQ3Status status; |
myEllipsoidData.interiorAttributeSet = NULL; |
myEllipsoidData.ellipsoidAttributeSet = Q3AttributeSet_New(); |
myEllipsoidData.caps = kQ3EndCapNone; |
Q3Point3D_Set(&myEllipsoidData.origin, -1.0, 0.5, 0); |
Q3Vector3D_Set(&myEllipsoidData.orientation, 0, 0.5, 0); |
Q3Vector3D_Set(&myEllipsoidData.minorRadius, 0, 0, -0.4); |
Q3Vector3D_Set(&myEllipsoidData.majorRadius, 0.5, 0, 0); |
myEllipsoidData.uMin = 0.0; myEllipsoidData.uMax = 1.0; |
myEllipsoidData.vMin = 0.0; myEllipsoidData.vMax = 1.0; |
theColor.r = 1.0; theColor.g = 0.0; theColor.b = 0.0; |
status = Q3AttributeSet_Add (myEllipsoidData.ellipsoidAttributeSet, |
kQ3AttributeTypeDiffuseColor, |
&theColor); |
myEllipsoid = Q3Ellipsoid_New(&myEllipsoidData); |
Q3Object_Dispose(myEllipsoidData.ellipsoidAttributeSet); |
return myEllipsoid; |
} |
TQ3Status myAddMatrixTransformToGroup( TQ3GroupObject theGroup) |
{ |
TQ3TransformObject transform; |
TQ3Matrix4x4 matrix; |
TQ3Status status; |
TQ3GroupPosition groupPos; |
status = kQ3Failure; |
Q3Matrix4x4_SetRotate_XYZ(&matrix, 0.0, 0.0, 0.0); |
transform = Q3MatrixTransform_New(&matrix); |
if (transform != NULL) { |
groupPos = Q3Group_AddObject(theGroup, transform) ; |
if (groupPos != NULL) { |
status = kQ3Success; |
} |
Q3Object_Dispose(transform); |
} |
return status; |
} |
TQ3Status mySetGroupState(TQ3GroupObject theGroup) |
{ |
TQ3DisplayGroupState theState; |
TQ3Status status; |
status = Q3DisplayGroup_GetState(theGroup, &theState); |
if (status == kQ3Success) { |
theState = theState | (kQ3DisplayGroupStateMaskIsPicked); |
status = Q3DisplayGroup_SetState(theGroup, theState); |
} |
return status; |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14