Source/Q3UL_QD3DUtils.c

/*
 *
 * QuickDraw 3D code for a utility library.
 *
 * This file contains an amalgamation of code that has been useful for
 * QuickDraw 3D developers.
 *
 * Nick Thompson, nickt@apple.com
 * Send bug reports and feedback to devsupport@apple.com.
 *
 * ©1997 Apple Computer Inc, All Rights Reserved 
 *
 * Modification History:
 *
 */
 
#include "Q3ULPriv.h"
#include "Q3UL_QD3DUtils.h"
 
#include "QD3DDrawContext.h"
#include "QD3DLight.h"
#include "QD3DRenderer.h"
 
/*------------------------------------------------------------------------------
 * 
 */ 
 
TQ3ViewObject Q3UL_NewView(TQ3UL_WindowRef theWindow)
{
    TQ3Status               myStatus;
    TQ3ViewObject           myView;
    TQ3DrawContextObject        myDrawContext;
    TQ3RendererObject       myRenderer;
    TQ3CameraObject         myCamera;
    TQ3GroupObject          myLights;
    
    myView = Q3View_New();
    
    /*  Create and set draw context. */
    if ((myDrawContext = Q3UL_NewMacintoshDrawContext(theWindow)) == nil )
        goto bail;
        
    if ((myStatus = Q3View_SetDrawContext(myView, myDrawContext)) == kQ3Failure )
        goto bail;
 
    Q3Object_Dispose( myDrawContext ) ;
    
    /*  Create and set renderer. */
    
    
    
#if 0
    /* this would use the wireframe renderer */
    myRenderer = Q3Renderer_NewFromType(kQ3RendererTypeWireFrame);
    if ((myStatus = Q3View_SetRenderer(myView, myRenderer)) == kQ3Failure ) {
        goto bail;
    }
    
#else
 
    /* this would use the interactive software 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 = Q3UL_NewCamera(theWindow)) == nil )
        goto bail;
        
    if ((myStatus = Q3View_SetCamera(myView, myCamera)) == kQ3Failure )
        goto bail;
 
    Q3Object_Dispose( myCamera ) ;
    
    /*  Create and set lights. */
    if ((myLights = Q3UL_NewDefaultLightGroup()) == nil )
        goto bail;
        
    if ((myStatus = Q3View_SetLightGroup(myView, myLights)) == kQ3Failure )
        goto bail;
        
    Q3Object_Dispose(myLights);
 
    return ( myView );
    
bail:
    /*  If any of the above failed, then don't return a view. */
    return ( nil );
}
 
/*------------------------------------------------------------------------------
 * 
 */ 
 
 
TQ3DrawContextObject Q3UL_NewMacintoshDrawContext(TQ3UL_WindowRef theWindow)
{
    TQ3DrawContextData      myDrawContextData;
    TQ3MacDrawContextData   myMacDrawContextData;
    TQ3ColorARGB            ClearColor;
    WindowPtr               theMacWindow ;
    TQ3DrawContextObject    myDrawContext ;
    
    /*  Set the background color. */
    ClearColor.a = 1.0;
    ClearColor.r = 1.0;
    ClearColor.g = 1.0;
    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;
    
    /* this is the window associated with the view */
    theMacWindow = gWindowArray[theWindow].window ;
        
    myMacDrawContextData.window = (CGrafPtr) theMacWindow;      
    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 Q3UL_NewCamera(TQ3UL_WindowRef theWindow)
{
    TQ3ViewAngleAspectCameraData    perspectiveData;
    TQ3CameraObject             camera;
    
    TQ3Point3D                  from    = { 0.0, 0.0, 7.0 };
    TQ3Point3D                  to      = { 0.0, 0.0, 0.0 };
    TQ3Vector3D                 up      = { 0.0, 1.0, 0.0 };
 
    float                       fieldOfView = 1.0;
    float                       hither      = 0.001;
    float                       yon         = 1000;
    
    TQ3Status                   returnVal = kQ3Failure ;
    WindowPtr                   theMacWindow ;
 
    perspectiveData.cameraData.placement.cameraLocation     = from;
    perspectiveData.cameraData.placement.pointOfInterest    = to;
    perspectiveData.cameraData.placement.upVector           = up;
 
    perspectiveData.cameraData.range.hither = hither;
    perspectiveData.cameraData.range.yon    = yon;
 
    perspectiveData.cameraData.viewPort.origin.x = -1.0;
    perspectiveData.cameraData.viewPort.origin.y = 1.0;
    perspectiveData.cameraData.viewPort.width = 2.0;
    perspectiveData.cameraData.viewPort.height = 2.0;
    
    perspectiveData.fov             = fieldOfView;
    
    theMacWindow = gWindowArray[theWindow].window ;
 
    perspectiveData.aspectRatioXToY =
        (float) (theMacWindow->portRect.right - theMacWindow->portRect.left) / 
        (float) (theMacWindow->portRect.bottom - theMacWindow->portRect.top);
        
    camera = Q3ViewAngleAspectCamera_New(&perspectiveData);
 
    return camera ;
}
 
 
/*------------------------------------------------------------------------------
 * 
 */ 
 
TQ3GroupObject Q3UL_NewDefaultLightGroup( 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 = .2;
    myAmbientLight = Q3AmbientLight_New(&myLightData);
    if ( myAmbientLight == nil )
        goto bail;
    
    /*  Create point light. */
    myLightData.brightness = 1.0;
    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 ) ;
 
    return ( myLightList );
    
bail:
    /* If any of the above failed, then return nothing */
    return ( nil );
}