Annotation of mstools/samples/spincube/paint.c, revision 1.1.1.1

1.1       root        1: /******************************************************************************\
                      2: *
                      3: *  MODULE:      PAINT.C
                      4: *
                      5: *  PURPOSE:     This is the module responsible for painting the SPINCUBE
                      6: *               custom control. When Paint() is called we retrieve a
                      7: *               pointer to a SPINCUBEINFO structure, and then use it's
                      8: *               current rotation & translation values to transform the
                      9: *               polyhedron described by gNormalizedVertices & gaiFacets.
                     10: *               Once we've transformed the vertices, we draw the
                     11: *               background, which consists of a grey rectangle and a few
                     12: *               black lines (a crass attempt to render a perspective
                     13: *               view into a "room"), on the offscreen bitmap associated
                     14: *               with the control (i.e. pSCI->hbmCompat). Then we walk the
                     15: *               facet list of the transformed polyhedron (gXformedVertices
                     16: *               & gaiFacets), drawing only those facets whose outward
                     17: *               normal faces us (again, drawing on pSCI->hbmCompat).
                     18: *               Finally, we BitBlt the appropriate rectangle from our
                     19: *               offscreen bitmap to the screen itself.
                     20: *
                     21: *               Drawing to the offscreen bitmap has two advantages over
                     22: *               drawing straight to the screen:
                     23: *
                     24: *                 1. The actual drawing the user sees consists of only
                     25: *                    a single BitBlt. Otherwise, the user would see us
                     26: *                    both erase the polyhedron in it's old position and
                     27: *                    draw it in it's new position (alot of flashing- not
                     28: *                    very smooth animation).
                     29: *
                     30: *                 2. When a spincube control with the SS_ERASE style
                     31: *                    is brought to the foreground, all it's contents
                     32: *                    i.e. the cube trails) are saved & can be re-Blted
                     33: *                    to the screen. Otherwise, all this info would be
                     34: *                    lost & there'd be a big blank spot in the middle
                     35: *                    of the control!
                     36: *
                     37: *               Interested persons should consult a text on 3 dimensional
                     38: *               graphics for more information (i.e. "Computer Graphics:
                     39: *               Principles and Practice", by Foley & van Dam).
                     40: *
                     41: *               Notes:
                     42: *
                     43: *               - A 3x2 tranformation matrix  is used instead of a  3x3
                     44: *                 matrix, since the transformed z-values aren't needed.
                     45: *                 (Normally these would be required for use in depth
                     46: *                 sorting  [for hidden surface removal], but  since we
                     47: *                 draw  only  a single convex polyhedron this  is not
                     48: *                 necessary.)
                     49: *
                     50: *               - A simplified perspective viewing transformation
                     51: *                 (which also  precludes the need for the transformed z
                     52: *                 coordinates). In a nutshell, the perspective  scale
                     53: *                 is as follows:
                     54: *
                     55: *                                    p' = S    x  p
                     56: *                                          per
                     57: *
                     58: *                 where:
                     59: *                        S    = WindowDepth /
                     60: *                         per      (WindowDepth + fCurrentZTranslation)
                     61: *
                     62: *                 (WindowDepth is  the greater of the  control's window
                     63: *                 height or window width.)
                     64: *
                     65: *
                     66: *  FUNCTIONS:   Paint()                         - the paint routine
                     67: *               TransformVertices()             - transforms vertices
                     68: *               ComputeRotationTransformation() - computes xformation
                     69: *                                                 based on current x, y
                     70: *                                                 and z rotation angles
                     71: *
                     72: *
                     73: *                                  Dan Knudson
                     74: *                           Microsoft Developer Support
                     75: *                  Copyright (c) 1992, 1993 Microsoft Corporation
                     76: *
                     77: \******************************************************************************/
                     78: 
                     79: #include <windows.h>
                     80: #include <math.h>
                     81: #include <stdlib.h>
                     82: #include "spincube.h"
                     83: #include "paint.h"
                     84: 
                     85: 
                     86: 
                     87: /******************************************************************************\
                     88: *
                     89: *  FUNCTION:     Paint
                     90: *
                     91: *  INPUTS:       hwnd - Handle of the window to draw into.
                     92: *
                     93: *  COMMENTS:     Draws window background & a polyhedron in the window.
                     94: *
                     95: \******************************************************************************/
                     96: 
                     97: void Paint (HWND hwnd)
                     98: {
                     99:   PSPINCUBEINFO  pSCI;
                    100:   RECT           rect;
                    101:   int            i;
                    102:   LONG           lScaleFactor;
                    103:   PAINTSTRUCT    ps;
                    104:   HRGN           hrgnClip;
                    105:   HBRUSH         hBrush, hBrushSave;
                    106:   int            iX, iY, iCX, iCY;
                    107:   int            facetIndex, numPoints;
                    108:   POINT          polygn[MAX_POINTS_PER_FACET];
                    109:   POINT          vector1, vector2;
                    110:   COLORREF       acrColor[6] = { 0x0000ff, 0x00ff00, 0xff0000,
                    111:                                  0x00ffff, 0xff00ff, 0xffff00 };
                    112: 
                    113:   pSCI = (PSPINCUBEINFO) GetWindowLong (hwnd, GWL_SPINCUBEDATA);
                    114: 
                    115:   BeginPaint (hwnd, &ps);
                    116: 
                    117:   if (memcmp((void *)&ps.rcPaint, (void *)&pSCI->rcCubeBoundary, sizeof(RECT))
                    118:       & !REPAINT_BKGND(pSCI))
                    119: 
                    120:   {
                    121:     //
                    122:     // We're not here because it's time to animate (i.e. this paint isn't
                    123:     //   the result of a WM_TIMER), so just do the Blt & blow out of here...
                    124:     //
                    125: 
                    126:     BitBlt (ps.hdc,
                    127:             ps.rcPaint.left,
                    128:             ps.rcPaint.top,
                    129:             ps.rcPaint.right - ps.rcPaint.left,
                    130:             ps.rcPaint.bottom - ps.rcPaint.top,
                    131:             pSCI->hdcCompat, ps.rcPaint.left,
                    132:             ps.rcPaint.top, SRCCOPY);
                    133: 
                    134:     EndPaint (hwnd, &ps);
                    135:     return;
                    136:   }
                    137: 
                    138: 
                    139:   //
                    140:   // The rectangle we get back is in Desktop coordinates, so we need to
                    141:   //   modify it to reflect coordinates relative to this window.
                    142:   //
                    143: 
                    144:   GetWindowRect (hwnd, &rect);
                    145: 
                    146:   rect.right  -= rect.left;
                    147:   rect.bottom -= rect.top;
                    148:   rect.left = rect.top = 0;
                    149: 
                    150: 
                    151:   //
                    152:   // Determine a "best fit" scale factor for our polyhedron
                    153:   //
                    154: 
                    155:   if (!(lScaleFactor = rect.right > rect.bottom ?
                    156:                        rect.bottom/12 : rect.right/12))
                    157: 
                    158:     lScaleFactor = 1;
                    159: 
                    160: 
                    161:   TransformVertices (hwnd, &rect, pSCI, lScaleFactor);
                    162: 
                    163: 
                    164:   //
                    165:   // Draw the window frame & background
                    166:   //
                    167:   // Note: The chances are that we are coming through here because we
                    168:   //   got a WM_TIMER message & it's time to redraw the cube to simulate
                    169:   //   animation. In that case all we want to erase/redraw is that small
                    170:   //   rectangle which bounded the polyhedron the last time. The less
                    171:   //   drawing that actually gets done the better, since we wnat to
                    172:   //   minimize the flicker on the screen. __BeginPaint__ is perfect for
                    173:   //   this because it causes all drawing outside of the invalid region
                    174:   //   to be "clipped" (no drawing is performed outside of the invalid
                    175:   //   region), and it also validates the invalid region.
                    176:   //
                    177: 
                    178:   if (DO_ERASE(hwnd) || REPAINT_BKGND(pSCI))
                    179:   {
                    180:     hrgnClip = CreateRectRgnIndirect (&ps.rcPaint);
                    181:     SelectClipRgn (pSCI->hdcCompat, hrgnClip);
                    182:     DeleteObject (hrgnClip);
                    183: 
                    184:     SelectObject (pSCI->hdcCompat, GetStockObject (GRAY_BRUSH));
                    185:     Rectangle    (pSCI->hdcCompat, (int)rect.left, (int)rect.top,
                    186:                   (int)rect.right, (int)rect.bottom);
                    187: 
                    188:     iX = (rect.right  - rect.left) / 4;
                    189:     iY = (rect.bottom - rect.top ) / 4;
                    190: 
                    191:     MoveToEx (pSCI->hdcCompat, (int)rect.left, (int)rect.top, NULL);
                    192:     LineTo   (pSCI->hdcCompat, (int)rect.left + iX, (int)rect.top + iY);
                    193:     LineTo   (pSCI->hdcCompat, (int)rect.left + iX, (int)rect.bottom - iY);
                    194:     LineTo   (pSCI->hdcCompat, (int)rect.left,      (int)rect.bottom);
                    195: 
                    196:     MoveToEx (pSCI->hdcCompat, (int)rect.right, (int)rect.top, NULL);
                    197:     LineTo   (pSCI->hdcCompat, (int)rect.right - iX, (int)rect.top + iY);
                    198:     LineTo   (pSCI->hdcCompat, (int)rect.right - iX, (int)rect.bottom- iY);
                    199:     LineTo   (pSCI->hdcCompat, (int)rect.right,      (int)rect.bottom);
                    200: 
                    201:     MoveToEx (pSCI->hdcCompat, (int)rect.left + iX,  (int)rect.top + iY, NULL);
                    202:     LineTo   (pSCI->hdcCompat, (int)rect.right - iX, (int)rect.top + iY);
                    203: 
                    204:     MoveToEx (pSCI->hdcCompat, (int)rect.left + iX,  (int)rect.bottom - iY, NULL);
                    205:     LineTo   (pSCI->hdcCompat, (int)rect.right - iX, (int)rect.bottom - iY);
                    206: 
                    207:     SelectClipRgn (pSCI->hdcCompat, NULL);
                    208: 
                    209:     pSCI->iOptions &= ~SPINCUBE_REPAINT_BKGND;
                    210:   }
                    211: 
                    212: 
                    213:   //
                    214:   // Draw the polyhedron. We'll walk through the facets list and compute
                    215:   //   the normal for each facet- if the normal has z > 0, then the facet
                    216:   //   faces us and we'll draw it. Note that this algorithim is ONLY valid
                    217:   //   for scenes with a single, convex polyhedron.
                    218:   //
                    219:   // Note: Use GetDC here because the above call to BeginPaint will
                    220:   //   probably not give us a DC with access to as much real estate as
                    221:   //   we'd like (we wouldn't be able to draw outside of the invalid
                    222:   //   region). We can party on the entire control window with the DC
                    223:   //   returned by GetDC.
                    224:   //
                    225: 
                    226:   for (i = 0, facetIndex = 0; i < NUMFACETS; i++)
                    227:   {
                    228:     vector1.x = gXformedVertices[gaiFacets[facetIndex + 1]].x -
                    229:                 gXformedVertices[gaiFacets[facetIndex]].x;
                    230:     vector1.y = gXformedVertices[gaiFacets[facetIndex + 1]].y -
                    231:                 gXformedVertices[gaiFacets[facetIndex]].y;
                    232:     vector2.x = gXformedVertices[gaiFacets[facetIndex + 2]].x -
                    233:                 gXformedVertices[gaiFacets[facetIndex + 1]].x;
                    234:     vector2.y = gXformedVertices[gaiFacets[facetIndex + 2]].y -
                    235:                 gXformedVertices[gaiFacets[facetIndex + 1]].y;
                    236: 
                    237:     for (numPoints = 0; gaiFacets[facetIndex] != -1; numPoints++, facetIndex++)
                    238:     {
                    239:       polygn[numPoints].x = gXformedVertices[gaiFacets[facetIndex]].x;
                    240:       polygn[numPoints].y = gXformedVertices[gaiFacets[facetIndex]].y;
                    241:     }
                    242: 
                    243:     facetIndex++; /* skip over the -1's in the facets list */
                    244:     if ((vector1.x*vector2.y - vector1.y*vector2.x) > 0)
                    245:     {
                    246:       hBrush     = CreateSolidBrush (acrColor[i]);
                    247:       hBrushSave = (HBRUSH) SelectObject (pSCI->hdcCompat, hBrush);
                    248: 
                    249:       Polygon (pSCI->hdcCompat, &polygn[0], numPoints);
                    250: 
                    251:       SelectObject (pSCI->hdcCompat, hBrushSave);
                    252:       DeleteObject (hBrush);
                    253:     }
                    254:   }
                    255: 
                    256:   iX  = pSCI->rcCubeBoundary.left < ps.rcPaint.left ?
                    257:         pSCI->rcCubeBoundary.left : ps.rcPaint.left;
                    258:   iY  = pSCI->rcCubeBoundary.top  < ps.rcPaint.top  ?
                    259:         pSCI->rcCubeBoundary.top  : ps.rcPaint.top;
                    260: 
                    261:   iCX = (pSCI->rcCubeBoundary.right > ps.rcPaint.right ?
                    262:          pSCI->rcCubeBoundary.right : ps.rcPaint.right) - iX;
                    263: 
                    264:   iCY = (pSCI->rcCubeBoundary.bottom > ps.rcPaint.bottom ?
                    265:          pSCI->rcCubeBoundary.bottom : ps.rcPaint.bottom) - iY;
                    266: 
                    267:   EndPaint (hwnd, &ps);
                    268: 
                    269:   ps.hdc = GetDC (hwnd);
                    270: 
                    271:   BitBlt (ps.hdc, iX, iY, iCX, iCY, pSCI->hdcCompat, iX, iY, SRCCOPY);
                    272: 
                    273:   ReleaseDC (hwnd, ps.hdc);
                    274: 
                    275: }
                    276: 
                    277: 
                    278: 
                    279: /******************************************************************************\
                    280: *
                    281: *  FUNCTION:     TransformVertices
                    282: *
                    283: *  INPUTS:       hwnd         - control window handle
                    284: *                pWindowRect  - pointer to RECT describing control's dimensions
                    285: *                pSCI         - pointer to control's SPINCUBEINFO structure
                    286: *                fScaleFactor - scale factor for use in this window
                    287: *
                    288: \******************************************************************************/
                    289: 
                    290: void TransformVertices (HWND hwnd,          RECT  *pWindowRect,
                    291:                         PSPINCUBEINFO pSCI, LONG  lScaleFactor)
                    292: {
                    293:   int    i;
                    294:   int    iWindowDepth = pWindowRect->right > pWindowRect->bottom ?
                    295:                         pWindowRect->right : pWindowRect->bottom;
                    296:   RECT   WindowRect;
                    297:   float  fDepthScale;
                    298:   int    iNewTranslationInc = (rand() % 10) + 2;
                    299:   float  fNewRotationInc    = (float) 0.01 * ((rand() % 30) + 2);
                    300: 
                    301:   WindowRect.left = - (WindowRect.right  = pWindowRect->right  >> 1);
                    302:   WindowRect.top  = - (WindowRect.bottom = pWindowRect->bottom >> 1);
                    303: 
                    304:   //
                    305:   // Initiailize the bounding rectangle with max/min vals
                    306:   //
                    307: 
                    308:   pSCI->rcCubeBoundary.left   =
                    309:   pSCI->rcCubeBoundary.top    = 100000; // big positive value
                    310:   pSCI->rcCubeBoundary.right  =
                    311:   pSCI->rcCubeBoundary.bottom = -100000; // small negative value
                    312: 
                    313: 
                    314:   //
                    315:   // First scale, then rotate, then translate each vertex.
                    316:   //   Keep track of the maximum & minimum values bounding the
                    317:   //   vertices in the x,y plane for use later in bounds checking.
                    318:   //
                    319:   // Note: we don't bother computing z values after the scale,
                    320:   //   as they are only really necessary for the rotation. If we
                    321:   //   were doing real bounds checking we'd need it, but this code
                    322:   //   simply uses the pSCI->iCurrentZTranslation to determine
                    323:   //   the z-boundaries.
                    324:   //
                    325: 
                    326:   for (i = 0; i < NUMVERTICES; i++)
                    327:   {
                    328:     LONG tempX;
                    329: 
                    330:     //
                    331:     // Copy the static vertices into a temp array
                    332:     //
                    333: 
                    334:     gXformedVertices[i] = gNormalizedVertices[i];
                    335: 
                    336:     //
                    337:     // The scale...
                    338:     //
                    339: 
                    340:     gXformedVertices[i].x *= lScaleFactor;
                    341:     gXformedVertices[i].y *= lScaleFactor;
                    342:     gXformedVertices[i].z *= lScaleFactor;
                    343: 
                    344:     //
                    345:     // The rotation...
                    346:     //
                    347: 
                    348:     ComputeRotationTransformation (pSCI->fCurrentXRotation,
                    349:                                    pSCI->fCurrentYRotation,
                    350:                                    pSCI->fCurrentZRotation);
                    351: 
                    352:     tempX   =               (LONG) (gM[0][0] * gXformedVertices[i].x +
                    353:                                     gM[0][1] * gXformedVertices[i].y +
                    354:                                     gM[0][2] * gXformedVertices[i].z);
                    355: 
                    356:     gXformedVertices[i].y = (LONG) (gM[1][0] * gXformedVertices[i].x +
                    357:                                     gM[1][1] * gXformedVertices[i].y +
                    358:                                     gM[1][2] * gXformedVertices[i].z);
                    359:     gXformedVertices[i].x = tempX;
                    360: 
                    361:     //
                    362:     // The translation...
                    363:     //
                    364: 
                    365:     gXformedVertices[i].x += pSCI->iCurrentXTranslation;
                    366:     gXformedVertices[i].y += pSCI->iCurrentYTranslation;
                    367: 
                    368:     //
                    369:     // Check if we have new max or min vals
                    370:     //
                    371: 
                    372:     if (pSCI->rcCubeBoundary.left > gXformedVertices[i].x)
                    373: 
                    374:       pSCI->rcCubeBoundary.left = gXformedVertices[i].x;
                    375: 
                    376:     if (pSCI->rcCubeBoundary.right < gXformedVertices[i].x)
                    377: 
                    378:       pSCI->rcCubeBoundary.right = gXformedVertices[i].x;
                    379: 
                    380:     if (pSCI->rcCubeBoundary.top > gXformedVertices[i].y)
                    381: 
                    382:       pSCI->rcCubeBoundary.top = gXformedVertices[i].y;
                    383: 
                    384:     if (pSCI->rcCubeBoundary.bottom < gXformedVertices[i].y)
                    385: 
                    386:       pSCI->rcCubeBoundary.bottom = gXformedVertices[i].y;
                    387:   }
                    388: 
                    389: 
                    390:   //
                    391:   // Now for some bounds checking, change translation & rotation increments
                    392:   //   if we hit a "wall". Also so the gbHitBoundary flag so we remember
                    393:   //   to flash the cube when we draw it.
                    394:   //
                    395: 
                    396:   if (pSCI->rcCubeBoundary.left < WindowRect.left)
                    397:   {
                    398:     pSCI->iCurrentXTranslationInc = iNewTranslationInc;
                    399:     pSCI->fCurrentZRotationInc    = fNewRotationInc;
                    400:   }
                    401: 
                    402:   else if (pSCI->rcCubeBoundary.right > WindowRect.right)
                    403:   {
                    404:     pSCI->iCurrentXTranslationInc = -iNewTranslationInc;
                    405:     pSCI->fCurrentZRotationInc    = -fNewRotationInc;
                    406:   }
                    407: 
                    408:   if (pSCI->rcCubeBoundary.top < WindowRect.top)
                    409:    {
                    410:     pSCI->iCurrentYTranslationInc = iNewTranslationInc;
                    411:     pSCI->fCurrentXRotationInc    = fNewRotationInc;
                    412:   }
                    413: 
                    414:   else if (pSCI->rcCubeBoundary.bottom > WindowRect.bottom)
                    415:   {
                    416:     pSCI->iCurrentYTranslationInc = -iNewTranslationInc;
                    417:     pSCI->fCurrentXRotationInc    = -fNewRotationInc;
                    418:   }
                    419: 
                    420:   if (pSCI->iCurrentZTranslation < (int) lScaleFactor<<1)
                    421:   {
                    422:     pSCI->iCurrentZTranslationInc = iNewTranslationInc;
                    423:     pSCI->fCurrentYRotationInc    = fNewRotationInc;
                    424:   }
                    425: 
                    426:   else if (pSCI->iCurrentZTranslation > (iWindowDepth - (int) lScaleFactor))
                    427:   {
                    428:     pSCI->iCurrentZTranslationInc = -iNewTranslationInc;
                    429:     pSCI->fCurrentYRotationInc    = -fNewRotationInc;
                    430:   }
                    431: 
                    432: 
                    433:   //
                    434:   // Now a kludgy scale based on depth (iCurrentZTranslation) of the center
                    435:   //   point of the polyhedron
                    436:   //
                    437: 
                    438:   fDepthScale =  ((float) iWindowDepth) /
                    439:                  ((float) (iWindowDepth + pSCI->iCurrentZTranslation));
                    440: 
                    441:   pSCI->rcCubeBoundary.left  = (LONG)(fDepthScale* pSCI->rcCubeBoundary.left  );
                    442:   pSCI->rcCubeBoundary.right = (LONG)(fDepthScale* pSCI->rcCubeBoundary.right );
                    443:   pSCI->rcCubeBoundary.top   = (LONG)(fDepthScale* pSCI->rcCubeBoundary.top   );
                    444:   pSCI->rcCubeBoundary.bottom= (LONG)(fDepthScale* pSCI->rcCubeBoundary.bottom);
                    445: 
                    446:   for (i = 0; i < NUMVERTICES; i++)
                    447:   {
                    448:     gXformedVertices[i].x = (LONG) (fDepthScale * gXformedVertices[i].x);
                    449:     gXformedVertices[i].y = (LONG) (fDepthScale * gXformedVertices[i].y);
                    450:   }
                    451: 
                    452: 
                    453:   //
                    454:   // If currently in motion then increment the current rotation & tranlation
                    455:   //
                    456: 
                    457:   if (IN_MOTION(hwnd))
                    458:   {
                    459:     pSCI->fCurrentXRotation += pSCI->fCurrentXRotationInc;
                    460:     pSCI->fCurrentYRotation += pSCI->fCurrentYRotationInc;
                    461:     pSCI->fCurrentZRotation += pSCI->fCurrentZRotationInc;
                    462: 
                    463:     pSCI->iCurrentXTranslation += pSCI->iCurrentXTranslationInc;
                    464:     pSCI->iCurrentYTranslation += pSCI->iCurrentYTranslationInc;
                    465:     pSCI->iCurrentZTranslation += pSCI->iCurrentZTranslationInc;
                    466:   }
                    467: 
                    468: 
                    469:   //
                    470:   // Up to this point all coordinates are relative to a window whose
                    471:   //   center is at (0,0). Now we'll translate appropriately...
                    472:   //
                    473: 
                    474:   pSCI->rcCubeBoundary.left   += pWindowRect->right  >> 1;
                    475:   pSCI->rcCubeBoundary.right  += pWindowRect->right  >> 1;
                    476:   pSCI->rcCubeBoundary.top    += pWindowRect->bottom >> 1;
                    477:   pSCI->rcCubeBoundary.bottom += pWindowRect->bottom >> 1;
                    478: 
                    479:   for (i = 0; i < NUMVERTICES; i++)
                    480:   {
                    481:     gXformedVertices[i].x += pWindowRect->right  >> 1;
                    482:     gXformedVertices[i].y += pWindowRect->bottom >> 1;
                    483:   }
                    484: 
                    485: 
                    486:   //
                    487:   // Since FillRect's are inclusive-exclusive (there'll be leftovers
                    488:   //   from the last cube we drew otherwise)...
                    489:   //
                    490: 
                    491:   pSCI->rcCubeBoundary.right++;
                    492:   pSCI->rcCubeBoundary.bottom++;
                    493: 
                    494: 
                    495:   //
                    496:   // Finally, adjust the rcCubeBoundary such that it fits entirely within
                    497:   //   the acutal control window. The reason for this is that when calling
                    498:   //   InvalidateRect from SpincubeWndProc\case_WM_TIMER we may get
                    499:   //   a different PAINSTRUCT.rcPaint (since InvalidateRect clips the passed
                    500:   //   in rect to the window bounds) and our abouve test to memcmp() will
                    501:   //   fail.
                    502:   //
                    503: 
                    504:   if (pSCI->rcCubeBoundary.left < 0)
                    505: 
                    506:     pSCI->rcCubeBoundary.left = 0;
                    507: 
                    508:   if (pSCI->rcCubeBoundary.top < 0)
                    509: 
                    510:     pSCI->rcCubeBoundary.top = 0;
                    511: 
                    512:   if (pSCI->rcCubeBoundary.right > pWindowRect->right)
                    513: 
                    514:     pSCI->rcCubeBoundary.right = pWindowRect->right;
                    515: 
                    516:   if (pSCI->rcCubeBoundary.bottom > pWindowRect->bottom)
                    517: 
                    518:     pSCI->rcCubeBoundary.bottom = pWindowRect->bottom;
                    519: }
                    520: 
                    521: 
                    522: /******************************************************************************\
                    523: *
                    524: *  FUNCTION:    ComputeRotationTransformation
                    525: *
                    526: *  INPUTS:      fRotationX - Angle to rotate about X axis.
                    527: *               fRotationY - Angle to rotate about Y axis.
                    528: *               fRotationZ - Angle to rotate about Z axis.
                    529: *
                    530: *  COMMENTS:    Computes a 3x2 tranformation matrix which rotates about
                    531: *               the Z axis, the Y axis, and the X axis, respectively.
                    532: *
                    533: \******************************************************************************/
                    534: 
                    535: void ComputeRotationTransformation (float fRotationX,
                    536:                                     float fRotationY,
                    537:                                     float fRotationZ)
                    538: {
                    539:   float sinX, cosX, sinY, cosY, sinZ, cosZ;
                    540: 
                    541:   sinX = (float) sin ((double) fRotationX);
                    542:   cosX = (float) cos ((double) fRotationX);
                    543:   sinY = (float) sin ((double) fRotationY);
                    544:   cosY = (float) cos ((double) fRotationY);
                    545:   sinZ = (float) sin ((double) fRotationZ);
                    546:   cosZ = (float) cos ((double) fRotationZ);
                    547: 
                    548:   gM[0][0] =  cosY*cosZ;
                    549:   gM[0][1] = -cosY*sinZ;
                    550:   gM[0][2] =  sinY;
                    551:   gM[1][0] =  sinX*sinY*cosZ + cosX*sinZ;
                    552:   gM[1][1] = -sinX*sinY*sinZ + cosX*cosZ;
                    553:   gM[1][2] = -sinX*cosY;
                    554: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.