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.
OpenGL Movie.c
/* |
File: OpenGLMovie.c |
Contains: OpenGL Movie demo |
Copyright: 2000 Apple Computer, Inc., All Rights Reserved |
Change History (most recent first): |
<6+> 2/24/01 ggs fix window return for full screen |
<6> 12/5/00 ggs Fixed unused variables |
<5> 12/4/00 ggs Fixed some Carbon and mac OS X things |
<4> 11/25/00 ggs fixed non-Carbon parts and added comments |
<3> 11/25/00 ggs Split controls |
<2> 11/25/00 ggs Completed options and dialog) |
<1> 10/29/00 ggs Name change |
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. |
("Apple") in consideration of your agreement to the following terms, and your |
use, installation, modification or redistribution of this Apple software |
constitutes acceptance of these terms. If you do not agree with these terms, |
please do not use, install, modify or redistribute this Apple software. |
In consideration of your agreement to abide by the following terms, and subject |
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs |
copyrights in this original Apple software (the "Apple Software"), to use, |
reproduce, modify and redistribute the Apple Software, with or without |
modifications, in source and/or binary forms; provided that if you redistribute |
the Apple Software in its entirety and without modifications, you must retain |
this notice and the following text and disclaimers in all such redistributions of |
the Apple Software. Neither the name, trademarks, service marks or logos of |
Apple Computer, Inc. may be used to endorse or promote products derived from the |
Apple Software without specific prior written permission from Apple. Except as |
expressly stated in this notice, no other rights or licenses, express or implied, |
are granted by Apple herein, including but not limited to any patent rights that |
may be infringed by your derivative works or by other works in which the Apple |
Software may be incorporated. |
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO |
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED |
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN |
COMBINATION WITH YOUR PRODUCTS. |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR |
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION |
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT |
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN |
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#ifdef __APPLE_CC__ |
#include "Carbon Include.h" |
#include <Carbon/Carbon.h> |
#include <AGL/agl.h> |
#include <OpenGL/gl.h> |
#include <OpenGL/glext.h> |
#include <AGL/aglRenderers.h> |
#else |
#include <FixMath.h> |
#include <Fonts.h> |
#include <Gestalt.h> |
#include <Navigation.h> |
#include <sound.h> |
#include <DrawSprocket.h> |
#include <gl.h> |
#include <glext.h> |
#include <glm.h> |
#include <agl.h> |
#include <aglRenderers.h> |
#endif |
#include <math.h> |
#include <stdio.h> |
#include <string.h> |
#include "Carbon SetupGL.h" |
#include "AGLString.h" |
#include "OpenGLMovie.h" |
//----------------------------------------------------------------------------------------------------------------------- |
struct structMovieSettings gMovieSettings = {640, 480, 256, 16, false, true, true, true, true}; |
// GL texturing |
GLubyte * gpTexture; // texture storage (used on for set up when direct texturing |
short gUsedTextureHeight = 0, gUsedTextureWidth = 0; |
float gfTextureScale = (float) 1.0; |
short gvTextureOffset = 0, gvTextureEnd = 0, ghTextureOffset = 0, ghTextureEnd = 0; |
// Movie |
Rect gMovieRect = {0, 0, 0, 0}; |
short gMovieWidth = 100, gMovieHeight = 75; |
Movie gMovie = NULL; |
TimeValue gMovieDuration = 0L; |
// Movie off screen |
GWorldPtr gpOffscreen = NULL; |
PixMapHandle ghPixMap = NULL; |
unsigned char * gpBaseAddr = NULL; |
unsigned long gRowStride = 0; |
MovieDrawingCompleteUPP gMovieDrawUPP; |
Boolean gfMovieDraw = false; |
// GL stuff |
Boolean gfHasPackedPixels = false; |
structGLInfo glInfo; |
structGLWindowInfo glWInfo; |
AGLDrawable gaglDraw = NULL; |
Rect grectWin; |
AGLContext gaglContext = 0; |
DSpContextReference gdspContext = 0; |
GLuint gFontList = 0; |
char gInfoString [512] = ""; |
//----------------------------------------------------------------------------------------------------------------------- |
OSErr QTPlayMovieFrameAtTime (Movie theMovie, TimeValue atTime); |
void SetPlaybackInfoString (void); |
void InitializeQTEnvironment (void); |
pascal OSErr MovieDrawProc (Movie movie, long refcon); |
OSErr InitializeMovie (void); |
void InitGL (short width, short height); |
void SetFrustum (short width, short height, float focalLen, float minDepth, float maxDepth); |
void MoveFrame (float * outx, float * outy, float * outz, float time); |
void SwizzleMovieToTexture (void); |
void DrawGL(Rect * pRect); |
#pragma mark - |
//----------------------------------------------------------------------------------------------------------------------- |
// QTPlayMovieFrameAtTime - sets movie to time and updates |
OSErr QTPlayMovieFrameAtTime (Movie theMovie, TimeValue atTime) |
{ |
OSErr anErr = noErr; |
if (NULL == theMovie) |
return paramErr; |
if (atTime == 0L) |
{ |
GoToBeginningOfMovie (theMovie); |
anErr = GetMoviesError (); |
} |
else |
{ |
if (atTime > gMovieDuration) |
SetMovieTimeValue (theMovie, gMovieDuration); |
else |
SetMovieTimeValue (theMovie, atTime); |
anErr = GetMoviesError (); |
} |
if (noErr == anErr) |
anErr = UpdateMovie (theMovie); |
if (noErr == anErr) |
{ |
MoviesTask (theMovie, 0L); |
anErr = GetMoviesError (); |
} |
return anErr; |
} |
#pragma mark - |
//----------------------------------------------------------------------------------------------------------------------- |
// UseWaitNextEvent - accessor function to determine whether user wants to use WNE |
Boolean UseWaitNextEvent (void) |
{ |
return gMovieSettings.fUseWaitNextEvent; |
} |
//----------------------------------------------------------------------------------------------------------------------- |
// IsFullScreen - are we in full screen mode |
Boolean IsFullScreen (void) |
{ |
return gMovieSettings.fFullScreen; |
} |
//----------------------------------------------------------------------------------------------------------------------- |
// ProcessFullScreenEvent - handle DrawSprocket events call safe for full screen and non-full screen |
Boolean ProcessFullScreenEvent (EventRecord * pEvent) |
{ |
Boolean fProcessed = false; |
if (IsFullScreen ()) |
DSpProcessEvent (pEvent, &fProcessed); |
return (fProcessed); |
} |
#pragma mark - |
//----------------------------------------------------------------------------------------------------------------------- |
// SetPlaybackInfoString - Set playback info string based on user selected options |
void SetPlaybackInfoString (void) |
{ |
char strTemp [512]; |
short texDepth; |
if (!gMovieSettings.fTryPackedPixel || !gfHasPackedPixels) |
texDepth = 24; |
else |
texDepth = gMovieSettings.wOffScreenDepth; |
sprintf (gInfoString, "Win: %dx%d, Tex: %dx%dx%d (Update: %dx%d)", gMovieSettings.wWindowWidth, gMovieSettings.wWindowHeight, |
gMovieSettings.wTextureSize, gMovieSettings.wTextureSize, texDepth, gUsedTextureWidth, gUsedTextureHeight); |
if (gMovieSettings.fTryPackedPixel && gfHasPackedPixels) |
{ |
sprintf (strTemp, "%s, Packed Pix", gInfoString); |
sprintf (gInfoString, "%s", strTemp); |
} |
if (gMovieSettings.fTryPackedPixel && gfHasPackedPixels && !gMovieSettings.fDirectTexturing) |
{ |
sprintf (strTemp, "%s, glmCopy", gInfoString); |
sprintf (gInfoString, "%s", strTemp); |
} |
if (gMovieSettings.fVBLSync) |
{ |
sprintf (strTemp, "%s, VSync", gInfoString); |
sprintf (gInfoString, "%s", strTemp); |
} |
if (gMovieSettings.fUseFog) |
{ |
sprintf (strTemp, "%s, Fog", gInfoString); |
sprintf (gInfoString, "%s", strTemp); |
} |
if (gMovieSettings.fUseWaitNextEvent) |
{ |
sprintf (strTemp, "%s, WNE", gInfoString); |
sprintf (gInfoString, "%s", strTemp); |
} |
} |
//----------------------------------------------------------------------------------------------------------------------- |
// SetupGLMovie - setup GL, set up GL texturing, set up QT playback into off screen |
// returns a CGrafPtr (aglDrawable) that is the drawable, for fullscreen we may not own the window |
// associated with the drawable, for non-fullscreen we will |
OSStatus SetupGLMovie (void) |
{ |
Rect rectWin; |
// OSErr anErr = noErr; |
// OSType mediaType = VideoMediaType; |
GDHandle origDevice; |
CGrafPtr origPort; |
short i = 0, deviceNum = -1; |
MatrixRecord movieMatrix; |
Rect rectNewMovie; |
// Boolean done = false; |
InitializeQTEnvironment(); |
if ( InitializeMovie() != noErr ) ExitToShell(); // we had problems with the movie. |
if (!gMovie) |
ExitToShell(); |
GetGWorld (&origPort, &origDevice); // save onscreen graphics port |
// Build GL context and window -------------------------- |
if (gMovieSettings.fFullScreen) |
{ |
// we want a context and a drawable |
deviceNum = -1; |
glInfo.width = gMovieSettings.wWindowWidth; // width of drawable (screen width in full screen mode) |
glInfo.height = gMovieSettings.wWindowHeight; // height of drawable (screen height in full screen mode) |
glInfo.fSizeMust = true; // dspContext must be requested height (ignored in window mode) |
// Note: This basically determines whether or not displays will step down to allocate or fail |
glInfo.pixelDepth = gMovieSettings.wOffScreenDepth;// requested pixel depth |
glInfo.fDepthMust = true; // pixel depth must be set (if false then curretn depth will be used if able) |
glInfo.fFullscreen = true; // use DSp to get fullscreen? |
glInfo.fAcceleratedMust = true; // must renderer be accelerated? |
glInfo.VRAM = 0 * 1000000; // minimum VRAM |
glInfo.freq = 0; // desired vertical refresh frquency in Hz (0 = any) |
glInfo.fmt = 0; // output pixel format |
glInfo.aglAttributes [i++] = AGL_RGBA; |
glInfo.aglAttributes [i++] = AGL_ALL_RENDERERS; |
glInfo.aglAttributes [i++] = AGL_DOUBLEBUFFER; |
glInfo.aglAttributes [i++] = AGL_NO_RECOVERY; // should be used whenever packed pixels is used to disable software back up textures |
glInfo.aglAttributes [i++] = AGL_NONE; |
if (noErr != BuildGL (&gaglDraw, &gaglContext, &gdspContext, &deviceNum, &glInfo)) |
return paramErr; |
if (!gaglContext) |
return paramErr; |
SetRect (&rectWin, (short) 0, (short) 0, (short) glInfo.width, (short) glInfo.height); // l t r b |
HideCursor (); |
} |
else |
{ |
SetRect (&rectWin, (short) 50, (short) 50, (short) (gMovieSettings.wWindowWidth + 50), (short) (gMovieSettings.wWindowHeight + 50)); // l t r b |
#if TARGET_API_MAC_CARBON |
gaglDraw = GetWindowPort (NewCWindow (NULL, &rectWin, "\pOpenGL Movie", false, kWindowFullZoomGrowDocumentProc, (WindowPtr)-1, true, 0)); |
ShowWindow (GetWindowFromPort (gaglDraw)); |
#else |
gaglDraw = (CGrafPtr) NewCWindow (NULL, &rectWin, "\pOpenGL Movie", false, kWindowFullZoomGrowDocumentProc, (WindowPtr)-1, true, 0); |
ShowWindow ((WindowPtr) gaglDraw); |
#endif |
glWInfo.fAcceleratedMust = true; // must renderer be accelerated? |
glWInfo.VRAM = 0 * 1048576; // minimum VRAM (if not zero this is always required) |
glWInfo.textureRAM = 0 * 1048576; // minimum texture RAM (if not zero this is always required) |
glWInfo.fDraggable = false; // desired vertical refresh frquency in Hz (0 = any) |
glWInfo.fmt = 0; // output pixel format |
i = 0; |
glWInfo.aglAttributes [i++] = AGL_RGBA; |
glWInfo.aglAttributes [i++] = AGL_DOUBLEBUFFER; |
glWInfo.aglAttributes [i++] = AGL_ACCELERATED; |
glWInfo.aglAttributes [i++] = AGL_NO_RECOVERY; // should be used whenever packed pixels is used to disable software back up textures |
glWInfo.aglAttributes [i++] = AGL_NONE; |
BuildGLFromWindow (GetWindowFromPort (gaglDraw), &gaglContext, &glWInfo); |
if (!gaglContext) |
return paramErr; |
} |
if (gaglDraw) |
SetPort ((GrafPtr)gaglDraw); |
// font handling |
{ |
short fNum; |
GetFNum("\pMonaco", &fNum); // build font |
gFontList = BuildFontGL (gaglContext, fNum, normal, 9); |
} |
// Setup OpenGL for movie texturing --------------------- |
InitGL (rectWin.right - rectWin.left, rectWin.bottom - rectWin.top); |
grectWin = rectWin; |
// Setup texturing and movie scaling ------------------- |
gMovieWidth = (short) (gMovieRect.right - gMovieRect.left); |
gMovieHeight = (short) (gMovieRect.bottom - gMovieRect.top); |
if (gMovieSettings.wTextureSize == 0) // set to power of two larger than movie |
{ |
short shift = 0; |
long value; |
if (gMovieWidth > gMovieHeight) |
value = gMovieWidth; |
else |
value = gMovieHeight; |
while (value) |
{ |
value = value >> 1; |
shift++; |
} |
value = 1; |
while (shift) |
{ |
value = value << 1; |
shift--; |
} |
gMovieSettings.wTextureSize = (short) value; |
} |
gvTextureOffset = 0; gvTextureEnd = gMovieHeight; ghTextureOffset = 0; ghTextureEnd = gMovieWidth; |
if (gMovieWidth > gMovieHeight) |
{ |
gfTextureScale = (float) gMovieWidth / (float) (gMovieSettings.wTextureSize); |
gUsedTextureHeight = (short) (gMovieHeight / gfTextureScale); |
gUsedTextureWidth = (short) (gMovieWidth / gfTextureScale); |
gvTextureOffset = (short) ((gMovieSettings.wTextureSize - gUsedTextureHeight) / 2); |
ghTextureOffset = 0; |
} |
else // harder case needs to be inset left and right |
{ |
gfTextureScale = (float) gMovieHeight / (float) gMovieSettings.wTextureSize; |
gUsedTextureHeight = (short) (gMovieHeight / gfTextureScale); |
gUsedTextureWidth = (short) (gMovieWidth / gfTextureScale); |
ghTextureOffset = (short) ((gMovieSettings.wTextureSize - gUsedTextureWidth) / 2); |
gvTextureOffset = 0; |
} |
gvTextureEnd = (short) (gUsedTextureHeight + gvTextureOffset); |
ghTextureEnd = (short) (gUsedTextureWidth + ghTextureOffset); |
// Setup QuickTimemovie playback ----------------------- |
SetIdentityMatrix (&movieMatrix); |
ScaleMatrix (&movieMatrix, X2Fix ( 1.0 / gfTextureScale), X2Fix (1.0 / gfTextureScale), X2Fix (0.0), X2Fix (0.0)); |
SetMovieMatrix (gMovie, &movieMatrix); |
SetRect (&rectNewMovie, 0, 0, gUsedTextureWidth, gUsedTextureHeight); // l,t, r, b |
// force 32 bit offscreen if no packed pixel |
if (!gMovieSettings.fTryPackedPixel || !gfHasPackedPixels) |
gMovieSettings.wOffScreenDepth = 32; |
gRowStride = gUsedTextureWidth * gMovieSettings.wOffScreenDepth / 8; |
gpBaseAddr = (unsigned char *) NewPtrClear (gRowStride * gUsedTextureHeight); |
if (gMovieSettings.wOffScreenDepth == 32) |
QTNewGWorldFromPtr (&gpOffscreen, k32ARGBPixelFormat, &rectNewMovie, NULL, NULL, 0, gpBaseAddr, gRowStride); |
else |
QTNewGWorldFromPtr (&gpOffscreen, k16BE555PixelFormat, &rectNewMovie, NULL, NULL, 0, gpBaseAddr, gRowStride); |
if (NULL == gpOffscreen) |
{ |
DebugStr ("\pCould not allocate off screen"); |
ExitToShell (); |
} |
SetGWorld(gpOffscreen, NULL); // set current graphics port to offscreen |
SetMovieGWorld(gMovie, (CGrafPtr)gpOffscreen, NULL); |
ghPixMap = GetGWorldPixMap (gpOffscreen); |
if (ghPixMap) |
{ |
if (LockPixels (ghPixMap)) // lock offscreen pixel map |
{ |
gpBaseAddr = (unsigned char *) GetPixBaseAddr (ghPixMap);//(**ghPixMap).baseAddr; // find base addr and stride |
gRowStride = (unsigned long) GetPixRowBytes (ghPixMap); //(**ghPixMap).rowBytes & 0x3FFF; |
} |
else |
{ |
DebugStr ("\pCould not lock PixMap"); |
ExitToShell (); |
} |
} |
else |
{ |
DebugStr ("\pCould not GetGWorldPixMap"); |
ExitToShell (); |
} |
SetGWorld(origPort, origDevice); // set current graphics port to offscreen |
QTPlayMovieFrameAtTime (gMovie, 0L); |
SetPlaybackInfoString (); |
return noErr; |
} |
//----------------------------------------------------------------------------------------------------------------------- |
// CleanupGLMovie - dump QT offscreen, texture storage, GL and window |
void CleanupGLMovie (void) |
{ |
// how to dispose QTGWorldFromPtr correctly? |
DisposeGWorld (gpOffscreen); |
//DisposePtr ((Ptr) gpBaseAddr); // dump gworld image area |
DisposePtr ((Ptr) gpTexture); // dump texture memory |
DeleteFontGL (gFontList); |
if (gMovieSettings.fFullScreen) |
{ |
DestroyGL (&gaglDraw, &gaglContext, &gdspContext, &glInfo); |
ShowCursor (); |
} |
else |
{ |
DestroyGLFromWindow (&gaglContext, &glWInfo); |
if (gaglDraw) |
#if TARGET_API_MAC_CARBON |
DisposeWindow (GetWindowFromPort (gaglDraw)); |
#else |
DisposeWindow ((WindowPtr) gaglDraw); |
#endif |
gaglDraw = NULL; |
} |
DisposeMovieDrawingCompleteUPP (gMovieDrawUPP); |
} |
//----------------------------------------------------------------------------------------------------------------------- |
pascal OSErr MovieDrawProc (Movie movie, long refcon) |
{ |
#pragma unused (movie, refcon) |
gfMovieDraw = true; |
return noErr; |
} |
//----------------------------------------------------------------------------------------------------------------------- |
// InitializeMovie - Initialize needed movie parts for the offscreen handling. |
OSErr InitializeMovie(void) |
{ |
OSErr anErr = OpenMovie (&gMovie); |
GetMovieBox(gMovie, &gMovieRect); |
OffsetRect(&gMovieRect, -gMovieRect.left, -gMovieRect.top); |
SetMovieBox(gMovie, &gMovieRect); |
gMovieDuration = GetMovieDuration(gMovie); |
gMovieDrawUPP = NewMovieDrawingCompleteUPP (MovieDrawProc); |
SetMovieDrawingCompleteProc (gMovie, movieDrawingCallWhenChanged, gMovieDrawUPP,0); |
return anErr; |
} |
//----------------------------------------------------------------------------------------------------------------------- |
// InitializeQTEnvironment - check for at least AT 4.0 and activate QT |
void InitializeQTEnvironment(void) |
{ |
OSErr anErr = noErr; |
long qtVersion = 0L; |
if(noErr != Gestalt (gestaltQuickTime, &qtVersion)) |
{ |
DebugStr ("\pThe QuickTime extension is not present in this system"); |
ExitToShell(); |
} |
if( (qtVersion >> 16 ) < 0x400 ) |
{ |
DebugStr ("\pWe need QT 4.0 or higher due to APIs used in this sample, consult the sources (exit)."); |
ExitToShell(); |
} |
anErr = EnterMovies(); |
if(anErr != noErr) |
{ |
DebugStr ("\pProblems with Entermovies, returning errors (exit)"); |
ExitToShell(); |
} |
} |
//----------------------------------------------------------------------------------------------------------------------- |
// SuspendFullScreenGLMovie - suspends full screen for background switch |
OSStatus SuspendFullScreenGLMovie (void) |
{ |
return SuspendFullScreenGL (gaglDraw, gaglContext); |
ShowCursor (); |
} |
//----------------------------------------------------------------------------------------------------------------------- |
// ResumeFullScreenGLMovie - resumes full screen after background switch |
OSStatus ResumeFullScreenGLMovie (void) |
{ |
HideCursor (); |
return ResumeFullScreenGL (gaglDraw, gaglContext); |
} |
//----------------------------------------------------------------------------------------------------------------------- |
// ResumeGLMovie - resumes after background switch |
OSStatus ResumeGLMovie (void) |
{ |
return ResumeGL (gaglContext); |
// resume QuickTime |
SetMovieRate (gMovie, X2Fix (1.0)); |
} |
//----------------------------------------------------------------------------------------------------------------------- |
// ResumeGLMovie - resumes after background switch |
OSStatus SuspendGLMovie (void) |
{ |
// pause QuickTime |
SetMovieRate (gMovie, X2Fix (0.0)); |
return PauseGL (gaglContext); |
} |
//----------------------------------------------------------------------------------------------------------------------- |
// UpdateGLMovieForGrow - handles GL updates for growing windows |
void UpdateGLMovieForGrow (short width, short height) |
{ |
gMovieSettings.wWindowWidth = width; |
gMovieSettings.wWindowHeight = height; |
SetPlaybackInfoString (); |
if (!IsFullScreen ()) |
aglUpdateContext (gaglContext); // can't call with aglSetFullScreen |
glViewport (0, 0, width, height); |
SetFrustum (width, height, 2.0, 1.0, 100.0); |
} |
//----------------------------------------------------------------------------------------------------------------------- |
// SetFrustum - sets up view frustrum to maintain movie aspect ratio |
void SetFrustum (short width, short height, float focalLen, float minDepth, float maxDepth) |
{ |
float heightOverWidth = (float) height / (float) width; // 0.75 intially; |
float f = minDepth / focalLen; |
float h = heightOverWidth * f; |
glMatrixMode(GL_PROJECTION); |
glLoadIdentity(); |
glFrustum(-f, f, -h, h, minDepth, maxDepth); |
} |
//----------------------------------------------------------------------------------------------------------------------- |
// InitGL - checks for packed pixel support, sets up GL for texturing (with or without packed pixel support) and fog if needed |
void InitGL (short width, short height) |
{ |
GLfloat rFog[4] = {0.0, 0.0, 0.0, 1.0}; |
long sizeTexture; |
// set up GL params |
UpdateGLMovieForGrow (width, height); |
glEnable(GL_TEXTURE_2D); |
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); |
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); |
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
if (gMovieSettings.fUseFog) |
{ |
rFog[0] = 0.8; rFog[1] = 0.9; rFog[2] = 0.9; rFog[3] = 1.0; |
glEnable(GL_FOG); |
glFogi(GL_FOG_MODE, GL_LINEAR); |
glFogf(GL_FOG_START, 1.0); |
glFogf(GL_FOG_END, 6.5); |
glFogfv(GL_FOG_COLOR, rFog); |
glHint(GL_FOG_HINT, GL_NICEST); |
} |
glClearColor(rFog[0], rFog[1], rFog[2], rFog[3]); |
if (gMovieSettings.fVBLSync) |
{ |
GLint swapInt = 1; |
aglSetInteger (gaglContext, AGL_SWAP_INTERVAL, &swapInt); |
} |
// packed pixel extension check |
if (gMovieSettings.fTryPackedPixel) |
{ |
// get version string |
const GLubyte * strVersion = glGetString (GL_VERSION); |
// get extension string |
const GLubyte * strExtension = glGetString (GL_EXTENSIONS); |
if (strstr ((const char *) strVersion, "1.2") || strstr ((const char *) strExtension, "GL_APPLE_packed_pixel")) |
gfHasPackedPixels = true; |
else |
gfHasPackedPixels = false; |
} |
// allocated texture buffer must be allocated for all cases |
if (!gMovieSettings.fTryPackedPixel || !gfHasPackedPixels) |
// allocate RGB 888 texture buffer |
sizeTexture = 3 * gMovieSettings.wTextureSize * gMovieSettings.wTextureSize; // size of texture in bytes |
else |
//allocate 32 or 16 bit buffer |
sizeTexture = gMovieSettings.wOffScreenDepth / 8 * gMovieSettings.wTextureSize * gMovieSettings.wTextureSize; // size of texture in bytes |
gpTexture = (GLubyte *) NewPtrClear (sizeTexture); |
if (!gpTexture) |
ExitToShell (); |
if (gMovieSettings.fUseFog) // clear buffer to fog color |
{ |
long i, j; |
short stepSize; |
long pixValue; |
if (!gMovieSettings.fTryPackedPixel || !gfHasPackedPixels) |
{ |
pixValue = ((((long)(rFog[0] * 255)) << 16) & 0x00FF0000) + ((((long)(rFog[1] * 255)) << 8) & 0x0000FF00) + ((((long)(rFog[2] * 255))) & 0x000000FF); |
stepSize = 3; |
} |
else if (gMovieSettings.wOffScreenDepth == 32) |
{ |
pixValue = ((((long)(rFog[0] * 255)) << 16) & 0x00FF0000) + ((((long)(rFog[1] * 255)) << 8) & 0x0000FF00) + ((((long)(rFog[2] * 255))) & 0x000000FF); |
stepSize = 4; |
} |
else |
{ |
pixValue = ((((long)(rFog[0] * 255)) << 7) & 0x00007C00) + ((((long)(rFog[1] * 255)) << 2) & 0x000003E0) + ((((long)(rFog[2] * 255)) >> 3) & 0x0000001F); |
stepSize = 2; |
} |
for (i = 0; i < sizeTexture; i += stepSize) |
for (j = 0; j < stepSize; j++) |
*(((unsigned char *)gpTexture) + i + j) = (unsigned char) (pixValue >> ((stepSize - 1 - j) * 8)); |
} |
// set up initial black texture |
if (gMovieSettings.fTryPackedPixel && gfHasPackedPixels) |
{ |
if (gMovieSettings.wOffScreenDepth == 32) |
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, gMovieSettings.wTextureSize, gMovieSettings.wTextureSize, 0, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, gpTexture); |
else |
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, gMovieSettings.wTextureSize, gMovieSettings.wTextureSize, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV, gpTexture); |
} |
else |
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, gMovieSettings.wTextureSize, gMovieSettings.wTextureSize, 0, GL_RGB, GL_UNSIGNED_BYTE, gpTexture); |
} |
//----------------------------------------------------------------------------------------------------------------------- |
// DrawGLMovieFrame - draws one movie frame at current time |
void DrawGLMovieFrame (void) |
{ |
MoviesTask (gMovie, 0); |
DrawGL (&grectWin); |
} |
//----------------------------------------------------------------------------------------------------------------------- |
// GLMovieDone - checks for complet movie, reseting if we are looping |
Boolean GLMovieDone (void) |
{ |
if (!gMovieSettings.fLoopMovie) |
return IsMovieDone (gMovie); |
else if (IsMovieDone (gMovie)) |
StartGLMovie (); |
return false; |
} |
//----------------------------------------------------------------------------------------------------------------------- |
// StartGLMovie - sets movie to beginning |
void StartGLMovie (void) |
{ |
GoToBeginningOfMovie (gMovie); |
StartMovie (gMovie); |
} |
//----------------------------------------------------------------------------------------------------------------------- |
// EndGLMovie - draws last frame |
void EndGLMovie (void) |
{ |
QTPlayMovieFrameAtTime (gMovie, GetMovieTime (gMovie, NULL)); // nudge one last time to make sure last frame is drawn. |
DrawGL (&grectWin); |
} |
//----------------------------------------------------------------------------------------------------------------------- |
// MoveFrame - moves quad in 3D space based on frustum edges and velocities |
void MoveFrame (float * outx, float * outy, float * outz, float time) |
{ |
static Boolean init = true; |
static float vmax = 0.3, vmin = 0.1; |
static float currx = 0.0, curry = 0.0, currz = 0.0; |
static float vx = 0.0, vy = 0.0, vz = 0.0; |
static float zMod = 8.0; |
// static float size = 1.0; |
static float ax = 0.1, ay = 0.1, az = 0.1; |
float xedge = 1.0, yedge = .75; |
float edgeDelta; |
// init velocities --------------------- |
if (init == true) |
{ |
init = false; |
vx = (vmax - vmin) / 2 + vmin + vmin / 3; |
vy = (vmax - vmin) / 2 + vmin - vmin / 5; |
vz = (vmax * zMod - vmin * zMod) / 2 + vmin * zMod; |
} |
// move polygon ------------------- |
currz = currz + vz * time; |
if ((currz > 8.0) || (currz < 2.0)) |
{ |
if (currz > 8.0) |
currz = 8.0; |
if (currz < 2.0) |
currz = 2.0; |
vz = - vz; |
if (vz > 0.0) |
{ |
if (vz > vmax * zMod) |
az = -vmax; |
else if (vx < vmin * zMod) |
az = vmax; |
vz += az * time; |
} |
else |
{ |
if (vz < -vmax * zMod) |
az = vmax; |
else if (vz > -vmin * zMod) |
az = -vmax; |
vz += az * time; |
} |
} |
edgeDelta = 1.414 / currz; // size offset |
currx = currx + vx * currz * time; |
if ((((currx / currz * 2.0) > (xedge - edgeDelta)) && (vx > 0)) || (((currx / currz * 2.0) < -(xedge - edgeDelta)) && (vx < 0))) |
{ |
vx = - vx; |
if (vx > 0.0) |
{ |
if (vx > vmax) |
ax = -vmax / 10.0; |
else if (vx < vmin) |
ax = vmax / 10.0; |
vx += ax * time; |
} |
else |
{ |
if (vx < -vmax) |
ax = vmax / 10.0; |
else if (vx > -vmin) |
ax = -vmax / 10.0; |
vx += ax * time; |
} |
} |
curry = curry + vy * currz * time; |
if ((((curry / currz * 2.0) > (yedge - edgeDelta)) && (vy > 0)) || (((curry / currz * 2.0) < -(yedge - edgeDelta)) && (vy < 0))) |
{ |
vy = - vy; |
if (vy > 0.0) |
{ |
if (vy > vmax) |
ay = -vmax / 10.0; |
else if (vy < vmin) |
ax = vmax / 10.0; |
vy += ay * time; |
} |
else |
{ |
if (vy < -vmax) |
ay = vmax / 10.0; |
else if (vy > -vmin) |
ay = -vmax / 10.0; |
vy += ay * time; |
} |
} |
*outx = currx; |
*outy = curry; |
*outz = currz; |
} |
//----------------------------------------------------------------------------------------------------------------------- |
// SwizzleMovieToTexture - non-packed pixels texture swizzle standard Mac ARGB_8888 to RGB_888 |
void SwizzleMovieToTexture (void) |
{ |
// will have 32 bit QT movie if were ever get here |
register int i,j; |
register unsigned char * pos = NULL; |
register unsigned char * pTextile = gpTexture; |
for (j = 0; j < gUsedTextureHeight; j++) |
{ |
for (i = 0; i < gUsedTextureWidth; i++) |
{ |
pos = (unsigned char *)(gpBaseAddr + (j * gRowStride) + (i * 4)); |
*(pTextile++) = *(pos + 1); |
*(pTextile++) = *(pos + 2); |
*(pTextile++) = *(pos + 3); |
} |
} |
} |
//----------------------------------------------------------------------------------------------------------------------- |
// OpenGL Drawin |
void DrawGL(Rect * pRect) |
{ |
short width; |
short height; |
static float time = 0.0; |
static long ticksPrev = 0; |
static float xRot = 0.0, yRot = 0.0, zRot = 0.0; |
float rx, ry, rz; |
float alpha; |
// get viewport size -------------- |
// for text |
width = pRect->right - pRect->left; |
height = pRect->bottom - pRect->top; |
// update texture ----------------- |
if (gfMovieDraw) |
{ |
if (gMovieSettings.fTryPackedPixel && gfHasPackedPixels) |
{ |
#ifndef __APPLE_CC__ // glm not avialable in Mac OS X |
if (gMovieSettings.fDirectTexturing) |
{ |
#endif |
if (gMovieSettings.wOffScreenDepth == 32) |
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, gUsedTextureWidth, gUsedTextureHeight, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, gpBaseAddr); |
else |
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, gUsedTextureWidth, gUsedTextureHeight, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV, gpBaseAddr); |
#ifndef __APPLE_CC__ // glm not avialable in Mac OS X |
} |
else |
{ |
glmCopy (gpBaseAddr, (unsigned char *) gpTexture, gUsedTextureWidth * gMovieSettings.wOffScreenDepth / 8, gUsedTextureHeight, gRowStride, gUsedTextureWidth * gMovieSettings.wOffScreenDepth / 8); |
if (gMovieSettings.wOffScreenDepth == 32) |
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, gUsedTextureWidth, gUsedTextureHeight, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, gpTexture); |
else |
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, gUsedTextureWidth, gUsedTextureHeight, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV, gpTexture); |
} |
#endif |
} |
else |
{ |
SwizzleMovieToTexture (); |
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, gUsedTextureWidth, gUsedTextureHeight, GL_RGB, GL_UNSIGNED_BYTE, gpTexture); |
} |
gfMovieDraw = false; |
} |
// move frame --------------------- |
if (ticksPrev) |
time = ((float) (TickCount () - ticksPrev)) / 60.0; |
else |
time = 0.0; |
ticksPrev = TickCount (); |
// draw polygon ------------------- |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
glMatrixMode (GL_MODELVIEW); |
glLoadIdentity (); |
MoveFrame (&rx, &ry, &rz, time); |
glTranslatef (rx, ry, -rz); |
zRot += 62 * time; // rotate |
glRotatef (zRot, 0.0, 0.0, 1.0); |
yRot += 47 * time; // spin |
glRotatef (yRot, 0.0, 1.0, 0.0); |
xRot += 55 * time; // tumble |
// glRotatef (xRot, 1.0, 0.0, 0.0); |
alpha = 1.0; // fabs (cos (f)); // |
glBegin(GL_QUADS); |
glTexCoord3f (0.0, 0.0, 0.0); glColor4f (1.0, 1.0, 1.0, alpha); glVertex3f (-1, -1, 0); |
glTexCoord3f (0.0, 1.0, 0.0); glColor4f (1.0, 1.0, 1.0, alpha); glVertex3f (-1, 1, 0); |
glTexCoord3f (1.0, 1.0, 0.0); glColor4f (1.0, 1.0, 1.0, alpha); glVertex3f (1, 1, 0); |
glTexCoord3f (1.0, 0.0, 0.0); glColor4f (1.0, 1.0, 1.0, alpha); glVertex3f (1, -1, 0); |
glEnd(); |
// draw text ---------------------- |
{ |
// set to per pixel orthographic context for 2D/text drawing |
GLint matrixMode; |
GLfloat rFog[4]; |
glDisable(GL_TEXTURE_2D); |
glGetIntegerv (GL_MATRIX_MODE, &matrixMode); |
if (gMovieSettings.fUseFog) |
glGetFloatv (GL_FOG_COLOR, rFog); |
glMatrixMode (GL_PROJECTION); |
glPushMatrix(); |
glLoadIdentity (); |
glMatrixMode (GL_MODELVIEW); |
glPushMatrix(); |
glLoadIdentity (); |
glScalef (2.0 / width, -2.0 / height, 1.0); |
glTranslatef (-width / 2.0, -height / 2.0, 0.0); |
// now have pixel scaled ortho mapping |
if (gMovieSettings.fUseFog) |
glColor3f (1.0 - rFog[0], 1.0 - rFog[1], 1.0 - rFog[2]); |
else |
glColor3f (1.0, 1.0, 1.0); |
glRasterPos3f (10, 15, 0); |
DrawFrameRate (gFontList); |
glRasterPos3f (10, 30, 0); |
DrawCStringGL (gInfoString, gFontList); |
glRasterPos3f (10, height - 20, 0); |
DrawCStringGL ((char*) glGetString (GL_VENDOR), gFontList); |
glRasterPos3f (10, height - 5, 0); |
DrawCStringGL ((char*) glGetString (GL_RENDERER), gFontList); |
glPopMatrix(); // GL_MODELVIEW |
glMatrixMode (GL_PROJECTION); |
glPopMatrix(); |
glMatrixMode (matrixMode); |
glEnable(GL_TEXTURE_2D); |
} |
aglSwapBuffers(gaglContext); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14