/**************************************************************************\ * * Module Name: logon.cxx * * Copyright (c) 1997 Microsoft Corporation * \**************************************************************************/ #include #include #include #include #include "logon.hxx" #include "logobj.hxx" #include "util.hxx" static GLIRECT nullRect = {0}; /**************************************************************************\ * LOG_OBJECT * * \**************************************************************************/ //#define DEEP_FRAME 1 LOG_OBJECT::LOG_OBJECT() { pTex = NULL; // Set some default size values... fImageSize.width = fImageSize.height = OBJECT_WIDTH; bShowContext = FALSE; // Only show image to start fCurContextWidth = 0.0f; fMaxContextWidth = OBJECT_WIDTH / 2.0f; #if DEEP_FRAME fFrameSize.width = fFrameSize.height = FRAME_SIZE; #else fFrameSize.width = fFrameSize.height = 0.0f; #endif bFramed = FALSE; // fFrameDepth is depth offset in z-direction. Since the frame is usually // drawn further away from the viewer (down -z axis), it is negative. #if DEEP_FRAME fFrameDepth = - 3.3f; #else fFrameDepth = - FRAME_DEPTH; #endif bSwapHints = FALSE; dest[0] = dest[1] = dest[2] = 0.0f; ResetMotion(); rect = nullRect; // Calc initial coords CalcCoords(); } LOG_OBJECT::~LOG_OBJECT() { } void LOG_OBJECT::ShowFrame( BOOL bShow ) { if( bFramed == bShow ) return; // new state bFramed = bShow; if( bFramed ) { // mf : could optimize by not redoing this if framesize constant... CalcFrameCoords(); } } void LOG_OBJECT::ShowContext( BOOL bShow ) { if( bShowContext == bShow ) return; // new state bShowContext = bShow; CalcCoords(); //mf: !!! readjust dest to reflect this ? } void LOG_OBJECT::SetDest( float x, float y, float z ) { dest[0] = x; dest[1] = y; dest[2] = z; } void LOG_OBJECT::SetDest( POINT3D *pDest ) { dest[0] = pDest->x; dest[1] = pDest->y; dest[2] = pDest->z; } void LOG_OBJECT::GetDest( POINT3D *pDest ) { pDest->x = dest[0]; pDest->y = dest[1]; pDest->z = dest[2]; } void LOG_OBJECT::OffsetDest( float x, float y, float z ) { dest[0] += x; dest[1] += y; dest[2] += z; } void LOG_OBJECT::SetTexture( TEXTURE *pTexture ) { pTex = pTexture; if( !pTex ) return; // Set the size of the object based on the aspect ratio of the texture // The textures for all the objects should have the same dimensions. float aspectRatio = pTex->GetAspectRatio(); // width/height // The texture is assumed to have an image on the right, and context on // the left, of equal size // We'll keep the width consant, and vary height according to aspect fImageSize.width = OBJECT_WIDTH / 2.0f; fImageSize.height = OBJECT_WIDTH / aspectRatio; fMaxContextWidth = fImageSize.width; fCurContextWidth = fMaxContextWidth; CalcCoords(); } void LOG_OBJECT::SetContextSize( float fPortion ) { // This sets the visible portion of the context ( 0.0 - 1.0 ) fCurContextWidth = fPortion * fMaxContextWidth; // Recalc coords CalcCoords(); } void LOG_OBJECT::SetImageSize( FSIZE *pSize ) { fImageSize = *pSize; float fPortion = fCurContextWidth / fMaxContextWidth; fMaxContextWidth = fImageSize.width; fCurContextWidth = fPortion * fMaxContextWidth; CalcCoords(); } void LOG_OBJECT::Translate() { glTranslatef(dest[0]+offset[0], dest[1]+offset[1], dest[2]+offset[2]); } void LOG_OBJECT::Rotate() { if( ang != 0.0f ) glRotatef(ang, rotAxis[0], rotAxis[1], rotAxis[2]); } void LOG_OBJECT::Draw() { Draw( FALSE ); } void LOG_OBJECT::Draw( BOOL bUpdateWinRect ) { // Draws object in its current position // An object either has its context showing on the right or not. If not, // then origin is the centre of the image, else origin is on border of // image and context pTex->MakeCurrent(); // Set the objects texture glPushMatrix(); Translate(); Rotate(); if( bUpdateWinRect ) { UpdateLocalTransforms( UPDATE_MODELVIEW_MATRIX_BIT ); CalcWinRect( FALSE ); } DrawFace(); if( bFramed ) DrawFrame(); glPopMatrix(); if( bSwapHints ) AddSwapHintRect( &rect ); } void LOG_OBJECT::DrawFace() { glNormal3f( 0.0f, 0.0f, 1.0f ); glBegin( GL_QUADS ); glTexCoord2fv( (float *) &texPoint[0] ); glVertex2fv( (float *) &point[0] ); glTexCoord2fv( (float *) &texPoint[1] ); glVertex2fv( (float *) &point[1] ); glTexCoord2fv( (float *) &texPoint[2] ); glVertex2fv( (float *) &point[2] ); glTexCoord2fv( (float *) &texPoint[3] ); glVertex2fv( (float *) &point[3] ); glEnd(); } void LOG_OBJECT::DrawFrame() { glDisable( GL_TEXTURE_2D ); glEnable( GL_LIGHTING ); glBegin( GL_QUADS ); glNormal3fv( (float *) &frameNormal[0] ); glVertex3fv( (float *) &point[0] ); glVertex3fv( (float *) &point[4] ); glVertex3fv( (float *) &point[7] ); glVertex3fv( (float *) &point[3] ); glNormal3fv( (float *) &frameNormal[1] ); glVertex3fv( (float *) &point[1] ); glVertex3fv( (float *) &point[5] ); glVertex3fv( (float *) &point[4] ); glVertex3fv( (float *) &point[0] ); glNormal3fv( (float *) &frameNormal[2] ); glVertex3fv( (float *) &point[2] ); glVertex3fv( (float *) &point[6] ); glVertex3fv( (float *) &point[5] ); glVertex3fv( (float *) &point[1] ); glNormal3fv( (float *) &frameNormal[3] ); glVertex3fv( (float *) &point[3] ); glVertex3fv( (float *) &point[7] ); glVertex3fv( (float *) &point[6] ); glVertex3fv( (float *) &point[2] ); glEnd(); glDisable( GL_LIGHTING ); glEnable( GL_TEXTURE_2D ); } void LOG_OBJECT::CalcWinRect() { CalcWinRect( TRUE ); } void LOG_OBJECT::CalcWinRect( BOOL bTransform ) { POINT3D ptOut[8]; int nPts = bFramed ? 8 : 4; if( bTransform ) { // Need to transorm object according to current translation & rotation glPushMatrix(); Translate(); Rotate(); UpdateLocalTransforms( UPDATE_MODELVIEW_MATRIX_BIT ); glPopMatrix(); } TransformObjectToWindow( point, ptOut, nPts ); // Update the rect member CalcMinMaxRect( ptOut, &rect, nPts ); } void LOG_OBJECT::CalcCoords() { POINT3D *pt; // Calculate object coords based on current state of the object. If // bShowContext, then origin is in centre of object, else it's in centre // of image part of object. // Also calculate frame coords if applicable. // Points are ordered CCW from top right for each face pt = point; pt[0].z = pt[1].z = pt[2].z = pt[3].z = 0.0f; // Calc front face points if( ! bShowContext ) { POINT2D image = { fImageSize.width / 2.0f, fImageSize.height / 2.0f }; pt[0].x = image.x; pt[0].y = image.y; pt[1].x = -image.x; pt[1].y = image.y; pt[2].x = -image.x; pt[2].y = -image.y; pt[3].x = image.x; pt[3].y = -image.y; } else { POINT2D image = { fImageSize.width, fImageSize.height / 2.0f }; pt[0].x = image.x; pt[0].y = image.y; pt[1].x = -fCurContextWidth; pt[1].y = image.y; pt[2].x = -fCurContextWidth; pt[2].y = -image.y; pt[3].x = image.x; pt[3].y = -image.y; } // Calc frame points if( bFramed ) { CalcFrameCoords(); } // Always need the texture coords //mf: optimize... CalcTexCoords(); } void LOG_OBJECT::CalcFrameCoords() { POINT3D *frontPt = point; POINT3D *pt = point + 4; pt[0].z = pt[1].z = pt[2].z = pt[3].z = fFrameDepth; pt[0].x = frontPt[0].x + fFrameSize.width; pt[0].y = frontPt[0].y + fFrameSize.height; pt[1].x = frontPt[1].x - fFrameSize.width; pt[1].y = frontPt[1].y + fFrameSize.height; pt[2].x = frontPt[2].x - fFrameSize.width; pt[2].y = frontPt[2].y - fFrameSize.height; pt[3].x = frontPt[3].x + fFrameSize.width; pt[3].y = frontPt[3].y - fFrameSize.height; // May as well do the normals too CalcFrameNormals(); } void LOG_OBJECT::CalcFrameNormals() { POINT3D *pNorm = frameNormal; float fDepth = fFrameDepth; float fFramex = fFrameSize.width; float fFramey = fFrameSize.height; // Calc the face normals for the sides of the frame. The faces are // ordered CCW from the right face. float norm1 = (float) fabs( fDepth ); pNorm[0].x = norm1; pNorm[0].y = 0.0f; pNorm[0].x = fFramex; pNorm[1].x = 0.0f; pNorm[1].y = norm1; pNorm[1].x = fFramey; pNorm[0].x = -norm1; pNorm[0].y = 0.0f; pNorm[0].x = fFramex; pNorm[1].x = 0.0f; pNorm[1].y = -norm1; pNorm[1].x = fFramey; mtk_NormalizePoints( pNorm, 4 ); } void LOG_OBJECT::CalcTexCoords() { // Calculate texture coords based on current state of the object. // The texture spans across the front face, and includes the image on right, // and context on left. The 't' coords are constant, but the 's' coord // varies, depending on if or how much context is shown. // Again, points are ordered CCW from top right for each face // Calc ratio of image over total width of object float ratio = fImageSize.width / (fImageSize.width + fMaxContextWidth); float sStart = 1.0f - ratio; if( bShowContext ) { sStart -= (fCurContextWidth / fMaxContextWidth) * (1.0f - ratio); } texPoint[0].s = texPoint[3].s = 1.0f; texPoint[1].s = texPoint[2].s = sStart; texPoint[0].t = texPoint[1].t = 1.0f; texPoint[2].t = texPoint[3].t = 0.0f; } void LOG_OBJECT::GetRect( GLIRECT *pRect ) { *pRect = rect; } #if 0 void LOG_OBJECT::GetPos( POINT3D *curpos ) { float *fpos = (float *) curpos; for( int i = 0; i < 3; i ++ ) fpos[i] = dest[i] + offset[i]; } #endif /**************************************************************************\ * NextFlyIteration * * Calcs next offset and angle for a 'fly'sequence * \**************************************************************************/ BOOL LOG_OBJECT::NextFlyIteration() { int i; if( !iter ) { // Done iterating return FALSE; } // Calculate new iterations for (i = 0; i < 3; i++) { offset[i] = Clamp( iter, offset[i] ); } ang = Clamp( iter, ang); iter--; return TRUE; } /**************************************************************************\ * ResetMotion * * Resets all position and motion params to 0 * \**************************************************************************/ void LOG_OBJECT::ResetMotion() { offset[0] = offset[1] = offset[2] = 0.0f; rotAxis[0] = rotAxis[1] = rotAxis[2] = 0.0f; ang = 0.0f; iter = 0; } /**************************************************************************\ * * Ranomnly chooses motion params for a fly sequence * * The motion is 'damped', since near the end of the fly sequence the object * is constrained to 0 rotation and the dest[] position * \**************************************************************************/ void LOG_OBJECT::SetDampedFlyMotion( float deviation ) { SetDampedFlyMotion( deviation, NULL ); } void LOG_OBJECT::SetDampedFlyMotion( float deviation, POINT3D *pOffset ) { if( pOffset ) { // Use supplied offset offset[0] = pOffset->x; offset[1] = pOffset->y; offset[2] = pOffset->z; } else { // Calc a random offset offset[0] = MyRand(); offset[1] = MyRand(); offset[2] = MyRand(); } ang = 260.0f * MyRand(); rotAxis[0] = MyRand(); rotAxis[1] = MyRand(); rotAxis[2] = MyRand(); iter = (int) (deviation * MyRand() + 60.0f); }