Annotation of mstools/samples/spincube/paint.c, revision 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.