

/*
	File:		QD3DSupport.c
	
	Contains:	QD3D support routines
	
	Written by:	Scott Kuechle, based on original Gerbils code by Brian Greenstone

	Copyright:	© 1998 by Apple Computer, Inc. All rights reserved
	
	Change History (most recent first)
	
		<2>		9/28/98		rtm		made changes for Metrowerks compiler
		<1>		9/01/98		srk		first file


*/

/************************************************************
*                                                           *
*    INCLUDE FILES                                          *
*                                                           *
*************************************************************/

#include "QD3DSupport.h"
#include "Utils.h"


/************************************************************
*                                                           *
*    FUNCTION PROTOTYPES                                    *
*                                                           *
*************************************************************/

#if TARGET_OS_MAC
	static TQ3ViewObject 			QD3DSupport_NewView(WindowPtr theWindow);
	static TQ3DrawContextObject 	QD3DSupport_NewDrawContext(WindowPtr theWindow);
	static TQ3ShaderObject 			QD3DSupport_CreateShaderFromTexture(short grndTextureResourceID);
#else if TARGET_OS_WIN32
	static TQ3ViewObject 			QD3DSupport_NewView(HWND theWindow);
	static TQ3DrawContextObject 	QD3DSupport_NewDrawContext(HWND theWindow);
	static TQ3ShaderObject 			QD3DSupport_CreateShaderFromTexture(LPTSTR	grndTextureFilePath);
#endif

static TQ3GroupObject 			QD3DSupport_GroundInit(TQ3ShaderObject	groundShaderObject);
static TQ3CameraObject 			QD3DSupport_NewCamera(float docWidth, float docHeight);
static TQ3GroupObject			QD3DSupport_NewLights(void);
static OSErr 					QD3DSupport_QuickTimeInit (void);
static TQ3GroupObject 			QD3DSupport_NewTrackGroup(TQ3ShaderObject	theShader);



/************************************************************
*                                                           *
*    FUNCTION:  QD3DSupport_NewView                         *
*                                                           *
*    PURPOSE:   Creates a new QD3D view object, along with  *
*               the accompanying draw context, light and    *
*               camera objects                              *
*                                                           *
*************************************************************/

#if TARGET_OS_MAC
	static TQ3ViewObject QD3DSupport_NewView(WindowPtr theWindow)
#else if TARGET_OS_WIN32
	static TQ3ViewObject QD3DSupport_NewView(HWND theWindow)
#endif
{
	TQ3Status				myStatus;
	TQ3ViewObject			myView;
	TQ3DrawContextObject	myDrawContext;
	TQ3RendererObject		myRenderer;
	TQ3GroupObject			myLights;
	TQ3CameraObject			myCamera;
#if TARGET_OS_WIN32
	RECT					clientRect;
	BOOL					success;
#endif


		myView = Q3View_New();
		if (myView == nil)
		{
			goto bail;
		}

		//	Create and set draw context.
		if ((myDrawContext = QD3DSupport_NewDrawContext(theWindow)) == nil )
		{
			goto bail;
		}
			
		if ((myStatus = Q3View_SetDrawContext(myView, myDrawContext)) == kQ3Failure )
		{
			goto bail;
		}

		Q3Object_Dispose( myDrawContext ) ;
		
		//	Create and set renderer.
		
		// this would use the Z-Buffer renderer
	#if 0

		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;
			}
			// these two lines set us up to use the best possible renderer,
			// including  hardware if it is installed.
			Q3InteractiveRenderer_SetDoubleBufferBypass (myRenderer, kQ3True);						
			Q3InteractiveRenderer_SetPreferences(myRenderer, kQAVendor_BestChoice, 0);

		}
		else
		{
			goto bail;
		}
	#endif

		Q3Object_Dispose( myRenderer ) ;
		
		//	Create and set camera.
		#if TARGET_OS_MAC
			if ( (myCamera = QD3DSupport_NewCamera((float) (theWindow->portRect.right - theWindow->portRect.left),
													(float) (theWindow->portRect.bottom - theWindow->portRect.top))) == nil )
			{
				goto bail;
			}
		#else if TARGET_OS_WIN32
			success = GetClientRect(theWindow, &clientRect);
			if (success)
			{
				if ( (myCamera = QD3DSupport_NewCamera((float)RECT_WIDTH(clientRect), (float)RECT_HEIGHT(clientRect))) == nil )
				{
					goto bail;
				}
			}
			else
			{
				goto bail;
			}
		#endif
			
		if ((myStatus = Q3View_SetCamera(myView, myCamera)) == kQ3Failure )
		{
			goto bail;
		}
		Q3Object_Dispose( myCamera ) ;
		
		//	Create and set lights.
		if ((myLights = QD3DSupport_NewLights()) == 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 );
}


/************************************************************
*                                                           *
*    FUNCTION:  QD3DSupport_NewDrawContext                  *
*                                                           *
*    PURPOSE:   Creates a new QD3D draw context object      *
*                                                           *
*                                                           *
*                                                           *
*                                                           *
*************************************************************/

#if TARGET_OS_MAC

static TQ3DrawContextObject QD3DSupport_NewDrawContext(WindowPtr theWindow)
{
	TQ3DrawContextData		myDrawContextData;
	TQ3MacDrawContextData	myMacDrawContextData;
	TQ3ColorARGB			ClearColor;
	TQ3DrawContextObject	myDrawContext ;
	
		/*	Set the background color. */
		ClearColor.a = 1.0F;
		ClearColor.r = 0.0F;
		ClearColor.g = 0.0F;
		ClearColor.b = 1.0F;
		
		/*	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 = (CGrafPtr) theWindow;
		
		/*	Create draw context and return it, if itŐs nil the caller must handle */
		myDrawContext = Q3MacDrawContext_New(&myMacDrawContextData) ;

		return myDrawContext ;
}


#else if TARGET_OS_WIN32

static TQ3DrawContextObject QD3DSupport_NewDrawContext(HWND theWindow)
{

	TQ3DrawContextData			myDrawContextData;
	TQ3Win32DCDrawContextData	myWin32DCDrawContextData;
	TQ3DrawContextObject		myDrawContext ;
	DWORD						wndClassStyle;
	TQ3ColorARGB				ClearColor;


		/*	Set the background color. */

		ClearColor.a = 1.0;
		ClearColor.r = 0.0;
		ClearColor.g = 0.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;

		myWin32DCDrawContextData.drawContextData = myDrawContextData;

		/* Assertion: window MUST be CS_OWNDC */

		wndClassStyle = GetClassLong( theWindow, GCL_STYLE );
		if( CS_OWNDC != ( wndClassStyle & CS_OWNDC ) )
		{
			return NULL;
		}

		/* set up the win32DCDrawContext */
		myWin32DCDrawContextData.hdc = GetDC( theWindow );

		/*	Create draw context and return it, if it's NULL the caller must handle */
		myDrawContext = Q3Win32DCDrawContext_New(&myWin32DCDrawContextData) ;

		ReleaseDC(theWindow, myWin32DCDrawContextData.hdc);

		return myDrawContext ;

}

#endif

/************************************************************
*                                                           *
*    FUNCTION:  QD3DSupport_NewCamera                       *
*                                                           *
*    PURPOSE:   Creates our camera                          *
*                                                           *
*                                                           *
*************************************************************/

static TQ3CameraObject QD3DSupport_NewCamera(float 			docWidth,
											float 			docHeight)
{
	TQ3ViewAngleAspectCameraData	perspectiveData;
	TQ3CameraObject					camera;
	
	TQ3Point3D 					from 	= { 30.0F, 50.0F, -50.0F };
	TQ3Point3D 					to 		= { 30.0F, 0.0F, 0.0F };
	TQ3Vector3D 				up 		= { 0.0F, 1.0F, 0.0F };

	float 						fieldOfView = 1.2F;
	float 						hither 		= 0.2F;
	float 						yon 		= 200.0F;
	

		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.0F;
		perspectiveData.cameraData.viewPort.origin.y 	= 	1.0F;
		perspectiveData.cameraData.viewPort.width		= 	2.0F;
		perspectiveData.cameraData.viewPort.height 		= 	2.0F;
		
		perspectiveData.fov				= fieldOfView;
		perspectiveData.aspectRatioXToY	= docWidth / docHeight;

		camera = Q3ViewAngleAspectCamera_New(&perspectiveData);

		return camera ;
}


/************************************************************
*                                                           *
*    FUNCTION:  QD3DSupport_NewLights                       *
*                                                           *
*    PURPOSE:   Create our lights                           *
*                                                           *
*                                                           *
*************************************************************/

static TQ3GroupObject QD3DSupport_NewLights()
{
	TQ3GroupPosition		myGroupPosition;
	TQ3GroupObject			myLightList;
	TQ3LightData			myLightData;
	TQ3LightObject			myAmbientLight = NULL;
	TQ3ColorRGB				WhiteLight = { 1.0F, 1.0F, 1.0F };
	
		/*	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 = 0.8F;
		myAmbientLight = Q3AmbientLight_New(&myLightData);
		if ( myAmbientLight == 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;
		}

		Q3Object_Dispose( myAmbientLight ) ;

		/*	Done! */
		return ( myLightList );
		
	bail:
		/*	If any of the above failed, then return nothing! */
		if (myAmbientLight != NULL)
		{
			Q3Object_Dispose( myAmbientLight ) ;
		}
		return ( nil );
}


/************************************************************
*                                                           *
*    FUNCTION:  QD3DSupport_NewTrackGroup                   *
*                                                           *
*    PURPOSE:   Creates a new group for our track & its     *
*               associated shader object                    *
*                                                           *
*                                                           *
*************************************************************/

static TQ3GroupObject QD3DSupport_NewTrackGroup(TQ3ShaderObject	theShader)
{
	TQ3GroupObject	myGroup = NULL;	
			
		if ((myGroup = Q3OrderedDisplayGroup_New()) != NULL )
		{
		TQ3GroupPosition myGroupPosition;
		
				/* ADD TEXTURE SHADER OBJECT TO GROUP */
			myGroupPosition = Q3Group_AddObject(myGroup, theShader);
			if ( myGroupPosition == nil )
			{
				Utils_DisplayErrorMsg("Group_AddObject failed!");
			}
		}
						
		/*	Done! */
		return ( myGroup );
}



/************************************************************
*                                                           *
*    FUNCTION:  QD3DSupport_GroundInit                      *
*                                                           *
*    PURPOSE:   Creates a new ground object and group       *
*                                                           *
*                                                           *
*************************************************************/

static TQ3GroupObject QD3DSupport_GroundInit(TQ3ShaderObject	groundShaderObject)
{
	long				i;
	TQ3GeometryObject	polygonObj = NULL;
	TQ3GroupPosition	myGroupPosition;
	TQ3GroupObject		groundGroup;
	TQ3PolygonData		polygonData;
	TQ3Vertex3D			vertices[kNumGrndTextureVertices] = {0,-3,GROUND_SIZE,nil,
															GROUND_SIZE,-3,GROUND_SIZE,nil,
															GROUND_SIZE,-3,-GROUND_SIZE,nil,
															0,-3,-GROUND_SIZE,nil};
	TQ3AttributeSet		attribs[kNumGrndTextureVertices] = {NULL, NULL, NULL, NULL};
	float				ambient = 1.0F;
	TQ3Param2D			uv[kNumGrndTextureVertices] = {0,0,1,0,1,1,0,1};



		if (groundShaderObject == NULL)

		{

			return NULL;

		}


		groundGroup =  Q3OrderedDisplayGroup_New();
		if (groundGroup == NULL)
		{
			return NULL;
		}
			
				/* ADD TEXTURE SHADER OBJECT TO GROUP */
		myGroupPosition = Q3Group_AddObject(groundGroup, groundShaderObject);
		if ( myGroupPosition == nil )
		{
			Utils_DisplayErrorMsg("Q3Group_AddObject failed!");
			goto outOfMem;
		}
		Q3Object_Dispose(groundShaderObject);


				/* CREATE VERTICES */
			
		for (i=0; i < kNumGrndTextureVertices; i++)
		{
			attribs[i] = Q3AttributeSet_New();	
			if( attribs[i] == NULL )
			{
				Utils_DisplayErrorMsg("Attribute set creation failed!");	
				goto outOfMem;
			}
			Q3AttributeSet_Add(attribs[i], kQ3AttributeTypeShadingUV, &uv[i]);
			vertices[i].attributeSet = attribs[i];
		}

				/* CREATE NEW POLYGON OBJECT */

		polygonData.numVertices = kNumGrndTextureVertices;
		polygonData.vertices = vertices;
		polygonData.polygonAttributeSet = nil;
		polygonObj = Q3Polygon_New(&polygonData);			
		
		if( polygonObj == NULL )
		{
			Utils_DisplayErrorMsg("Polygon_New failed!");	
			goto outOfMem;
		}
		
		for (i=0; i < kNumGrndTextureVertices; i++)
		{			
			Q3Object_Dispose(attribs[i]);
			attribs[i] = NULL;
		}

		myGroupPosition = Q3Group_AddObject(groundGroup, polygonObj);
		Q3Object_Dispose(polygonObj);
		if ( myGroupPosition == nil )
		{
			Utils_DisplayErrorMsg("Q3Group_AddObject failed!");	
			goto outOfMem;
		}
		
			/* Success! */
			
		return groundGroup;
		
			/* Error handling */
	outOfMem:
		if (groundGroup)
		{
			Q3Object_Dispose(groundGroup);
		}

		for (i=0; i < kNumGrndTextureVertices; i++)
		{			
			if( attribs[i] )
			{
				Q3Object_Dispose(attribs[i]);
			}
		}
		
		return NULL;
}


/************************************************************
*                                                           *
*    FUNCTION:  QD3DSupport_InitDoc3DData                   *
*                                                           *
*    PURPOSE:   General initialization routine which        *
*               creates our QD3D view and builds our track  *
*               and ground objects                          *
*                                                           *
*                                                           *
*************************************************************/

#if TARGET_OS_MAC
	void QD3DSupport_InitDoc3DData( WindowPtr 	window,
									DocumentPtr theDocument )
#else if TARGET_OS_WIN32
	void QD3DSupport_InitDoc3DData( HWND 		window,
									DocumentPtr theDocument )
#endif
{
	TQ3Status 		status;
	TQ3ShaderObject	groundShaderObject;
	short			partCount;
	
	#if TARGET_OS_WIN32

		OSErr err;
		DWORD error;


	#endif


			/* Initialize QuickDraw 3D, open a connection to the QuickDraw 3D library */

		status = Q3Initialize();
		if ( status == kQ3Failure )
		{
			Utils_DisplayFatalErrorMsg("QD3D Initialization failure!");
		}
		
		#if TARGET_OS_WIN32

			err = QD3DSupport_QuickTimeInit ();

			if ( err != noErr )
			{
				Utils_DisplayFatalErrorMsg("QTML Initialization failure!");
			}
		#endif

		theDocument->fSplinePointsPtr 	= NULL;
		theDocument->fNumSplineNubs 	= 0;
		theDocument->fNumSplinePoints 	= 0;
		theDocument->fTrackIndex 		= 0;
		theDocument->fMainWindow 		= window;

			/* sets up the 3d data for the scene */
			/* Create view for QuickDraw 3D. */
		theDocument->fView = QD3DSupport_NewView( theDocument->fMainWindow ) ;
		if (theDocument->fView == NULL)
		{
			Utils_DisplayFatalErrorMsg("Failure creating a new view!");
		}
		
			/* get the view's camera for use later */
		Q3View_GetCamera(theDocument->fView, &theDocument->fCamera);
		
			/* the drawing styles: */
		theDocument->fInterpolation = Q3InterpolationStyle_New(kQ3InterpolationStyleVertex) ;
		theDocument->fBackFacing 	= Q3BackfacingStyle_New(kQ3BackfacingStyleBoth ) ;
		theDocument->fFillStyle 	= Q3FillStyle_New(kQ3FillStyleFilled ) ;


			/* get shaders for ground/track textures */
		#if TARGET_OS_MAC
		
			groundShaderObject = QD3DSupport_CreateShaderFromTexture(kGrndTextureResID);
			theDocument->fTrackShader = QD3DSupport_CreateShaderFromTexture(kTextureRezID);

		#else if TARGET_OS_WIN32
		
			error = Utils_Win32_BuildCurDirPath((Ptr)&theDocument->fGroundTextureFilePath, kGroundTextureFileName);
			if (!Utils_Win32_DoesFileExist((char *)&theDocument->fGroundTextureFilePath))

			{

				Utils_DisplayFatalErrorMsg("Failure loading ground texture file GroundTexture.pct!");

			}

			error = Utils_Win32_BuildCurDirPath((Ptr)&theDocument->fTrackTextureFilePath, kTrackTextureFileName);
			if (!Utils_Win32_DoesFileExist((char *)&theDocument->fGroundTextureFilePath))

			{

				Utils_DisplayFatalErrorMsg("Failure loading track texture file MetalTrack.pct!");

			}

			
			groundShaderObject = QD3DSupport_CreateShaderFromTexture((Ptr)&theDocument->fGroundTextureFilePath);
			theDocument->fTrackShader = QD3DSupport_CreateShaderFromTexture((Ptr)&theDocument->fTrackTextureFilePath);

		#endif
		
			/* create ground/track groups */
			
		theDocument->fGroundGroup = QD3DSupport_GroundInit(groundShaderObject);
		theDocument->fTrackGroup = QD3DSupport_NewTrackGroup (theDocument->fTrackShader);
		
			/* load track parts */

		#if TARGET_OS_WIN32

			Track_LoadPartsFromFile((PartType *)&theDocument->fPartsList, &partCount);

		#elif TARGET_OS_MAC

			Track_LoadPartsFromRez((PartType *)&theDocument->fPartsList, &partCount);

		#endif

			/* build track from track parts */
		if (partCount > 0)
		{
			Track_MakeRandomTrack((TrackSectionType *)&theDocument->fTrackSectionList, MAX_TRACK_SECTIONS);
			Track_CreateMasterNubList((TrackSectionType *)&theDocument->fTrackSectionList,
									partCount,
									(PartType *)&theDocument->fPartsList,
									(NubEntryType *)&theDocument->fNubArray,
									&theDocument->fNumSplineNubs);	/* on output, new spline count */

			Track_CalcSplineCurve(&theDocument->fSplinePointsPtr,
								MAX_SPLINE_POINTS,
								(NubEntryType *)&theDocument->fNubArray,
								theDocument->fNumSplineNubs,
								&theDocument->fNumSplinePoints,
								kTrackSubDivFactor);

			Track_BuildCoasterGeometry_Mesh(kSkipValue,
											theDocument->fTrackGroup,
											theDocument->fNumSplinePoints,
											theDocument->fSplinePointsPtr);
		}

}
/************************************************************
*                                                           *
*    FUNCTION:  QD3DSupport_DisposeDoc3DData                *
*                                                           *
*    PURPOSE:   Dispose of our QD3D objects                 *
*                                                           *
*                                                           *
*************************************************************/

void QD3DSupport_DisposeDoc3DData( DocumentPtr theDocument)
{
	TQ3Status status;

		Q3Object_Dispose(theDocument->fView) ;				/* the view for the scene */
		Q3Object_Dispose(theDocument->fCamera) ;			/* the camera for the scene */
		Q3Object_Dispose(theDocument->fTrackGroup) ;
		Q3Object_Dispose(theDocument->fGroundGroup) ;
		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 */
		Q3Object_Dispose(theDocument->fTrackShader) ;			/* whether drawn as solid filled object or decomposed to components */

		status = Q3Exit();
		if ( status == kQ3Failure )
		{
			Utils_DisplayErrorMsg("QD3D Exit returned failure");
		}

}

/************************************************************
*                                                           *
*    FUNCTION:  QD3DSupport_DocDraw3DData                   *
*                                                           *
*    PURPOSE:   Draws our track and ground group objects    *
*                                                           *
*                                                           *
*************************************************************/

TQ3Status QD3DSupport_DocDraw3DData( DocumentPtr theDocument )
{

	Q3View_StartRendering(theDocument->fView );
	do
	{		
		Q3Style_Submit( theDocument->fInterpolation, theDocument->fView );
		Q3Style_Submit( theDocument->fBackFacing, theDocument->fView );
		Q3Style_Submit( theDocument->fFillStyle, theDocument->fView );
		Q3DisplayGroup_Submit( theDocument->fTrackGroup, theDocument->fView );
		Q3DisplayGroup_Submit( theDocument->fGroundGroup, theDocument->fView );

	} while (Q3View_EndRendering(theDocument->fView) == kQ3ViewStatusRetraverse );

	Track_MoveCamera(theDocument->fCamera,
					theDocument->fSplinePointsPtr,
					theDocument->fNumSplinePoints,
					&theDocument->fTrackIndex);

	return kQ3Success ;
}


/************************************************************
*                                                           *
*    FUNCTION:  QD3DSupport_QuickTimeInit                   *
*                                                           *
*    PURPOSE:   Initalize QuickTime                         *
*                                                           *
*                                                           *
*************************************************************/

static OSErr QD3DSupport_QuickTimeInit (void)
{
	#if TARGET_OS_WIN32
		OSErr err;

			err = InitializeQTML(0L);
			if (err != noErr)
			{

				return err;

			}
	#endif

	return ( EnterMovies () );
}



/************************************************************
*                                                           *
*    FUNCTION:  QD3DSupport_CreateShaderFromTexture         *
*                                                           *
*    PURPOSE:   Create our shader object                    *
*                                                           *
*                                                           *
*************************************************************/

#if TARGET_OS_MAC

	static TQ3ShaderObject QD3DSupport_CreateShaderFromTexture(short grndTextureResourceID)
	{
		TQ3ShaderObject 	shaderObject = NULL;
		PicHandle			picH;
		Rect				picRect;

			Utils_Mac_GetPictForTexture(grndTextureResourceID, &picH, &picRect);
			if (picH == NULL)
			{
				Utils_DisplayFatalErrorMsg("Failure retrieving ground textures!");
			}
			
			shaderObject = TextureMap_Get(picH, &picRect);
			
			ReleaseResource((Handle)picH);
			
			return shaderObject;
	}
	
#else if TARGET_OS_WIN32

	static TQ3ShaderObject QD3DSupport_CreateShaderFromTexture(LPTSTR	grndTextureFilePath)
	{
		TQ3ShaderObject 	shaderObject = NULL;
		PicHandle			picH;
		Rect				picRect;
		ComponentResult		result;

		
			result = Utils_Win32_GetPicFromFile(grndTextureFilePath, &picH, &picRect);
			if (picH == NULL)
			{
				Utils_DisplayFatalErrorMsg("Failure retrieving ground textures!");
			}
			
			shaderObject = TextureMap_Get(picH, &picRect);
			
				/* release memory occupied by picture */
			KillPicture(picH);
			
			return shaderObject;
	}
	
#endif

