Annotation of pmsdk/samples/shapes/sdraw.c, revision 1.1

1.1     ! root        1: /*--------------------------------------------------------*\
        !             2:     SDRAW.C - 3D to 2D transformations and draw routines
        !             3: \*--------------------------------------------------------*/
        !             4: 
        !             5: #include <stddef.h>
        !             6: #include <os2.h>
        !             7: #include <math.h>
        !             8: #include "sstruct.h"
        !             9: 
        !            10: extern SHAPE rgshape [];
        !            11: 
        !            12: POINT3D pt3FillBuffer [MAX_POINTS];
        !            13: 
        !            14: extern INT yPelAdjust;
        !            15: 
        !            16: 
        !            17: /*
        !            18:  *  ScalePoint:
        !            19:  *     - replace destination point by source point after scaling
        !            20:  */
        !            21: 
        !            22: VOID ScalePoint (
        !            23:     POINT3D *ppt3Source,
        !            24:     POINT3D *ppt3Dest,
        !            25:     LONG iScale )
        !            26:     {
        !            27:     ppt3Dest->x = (INT) ( ((LONG) ppt3Source->x * iScale) >> 6 );
        !            28:     ppt3Dest->y = (INT) ( ((LONG) ppt3Source->y * iScale) >> 6 );
        !            29:     ppt3Dest->z = (INT) ( ((LONG) ppt3Source->z * iScale) >> 6 );
        !            30:     }
        !            31: 
        !            32: 
        !            33: /*
        !            34:  *  ChangeScale:
        !            35:  *     - to be called after a window changes size
        !            36:  *     - scales a shape's appropriate variables for the new size
        !            37:  *     - the centre of the window indicates the new window size
        !            38:  */
        !            39: 
        !            40: extern VOID ChangeScale (
        !            41:     PSV psv )
        !            42:     {
        !            43:     LONG xScale = psv->ptCentre.x;
        !            44:     LONG yScale = (psv->ptCentre.y << 10) / yPelAdjust;
        !            45:     LONG iScale = (xScale > yScale) ? yScale : xScale;
        !            46:     INIT *pinit = rgshape [psv->iShape].pinit;
        !            47: 
        !            48:     if (iScale < MIN_SCALE)
        !            49:        {
        !            50:        /* set lower bound on the scale of a shape */
        !            51: 
        !            52:        iScale = MIN_SCALE;
        !            53:        }
        !            54: 
        !            55:     /* scale the initial size of the shape */
        !            56: 
        !            57:     ScalePoint (&pinit->pt3SizeMid, &psv->pt3Size, iScale);
        !            58:     psv->pt3SizeMid = psv->pt3Size;
        !            59: 
        !            60:     /* scale the magnitude of the sinusoidal size change */
        !            61: 
        !            62:     ScalePoint (&pinit->pt3SizeMag, &psv->pt3SizeMag, iScale);
        !            63: 
        !            64:     /* scale the viewing distance */
        !            65:     /* (so that perspective is independent of window size) */
        !            66: 
        !            67:     psv->zViewDist = pinit->zViewDist * iScale;
        !            68:     }
        !            69: 
        !            70: 
        !            71: /*
        !            72:  *  lSin:
        !            73:  *     - fast integer sine function with granularity of 1 degree
        !            74:  *     - constraint:  -360 <= angle <= 360
        !            75:  *     - returns the sine of an angle * 16384 (shifted left by 14)
        !            76:  */
        !            77: 
        !            78: LONG lSin(
        !            79:     INT iAngle )
        !            80:     {
        !            81:     static INT iSinTable [91] =
        !            82:        { 0, 286, 572, 857, 1143, 1428, 1713, 1997, 2280, 2563, 2845, 3126,
        !            83:        3406, 3686, 3964, 4240, 4516, 4790, 5063, 5334, 5604, 5872, 6138,
        !            84:        6402, 6664, 6924, 7182, 7438, 7692, 7943, 8192, 8438, 8682, 8923,
        !            85:        9162, 9397, 9630, 9860, 10087, 10311, 10531, 10749, 10963, 11174,
        !            86:        11381, 11585, 11786, 11982, 12176, 12365, 12551, 12733, 12911, 13085,
        !            87:        13255, 13421, 13583, 13741, 13894, 14044, 14189, 14330, 14466, 14598,
        !            88:        14726, 14849, 14968, 15082, 15191, 15296, 15396, 15491, 15582, 15668,
        !            89:        15749, 15826, 15897, 15964, 16026, 16083, 16135, 16182, 16225, 16262,
        !            90:        16294, 16322, 16344, 16362, 16374, 16382, 16384 };
        !            91: 
        !            92:     if (iAngle < 0)
        !            93:        iAngle += 360;
        !            94: 
        !            95:     if (iAngle < 180)
        !            96:        if (iAngle < 90)
        !            97:            return( (LONG) iSinTable [iAngle] );
        !            98:        else
        !            99:            return( (LONG) iSinTable [180 - iAngle] );
        !           100:     else
        !           101:        if (iAngle < 270)
        !           102:            return( (LONG) -iSinTable [iAngle - 180] );
        !           103:        else
        !           104:            return( (LONG) -iSinTable [360 - iAngle] );
        !           105:     }
        !           106: 
        !           107: 
        !           108: /*
        !           109:  *  iAngleAdd (macro):
        !           110:  *     - adds the second angle to first angle
        !           111:  *     - stores result (which is in range 0 to 359) in the first angle
        !           112:  */
        !           113: 
        !           114: #define iAngleAdd( iA1,iA2)                        \
        !           115:     if ( ((iA1) += (iA2)) < 0 ) (iA1) += 360;      \
        !           116:     else if ( (iA1) >= 360 )   (iA1) -= 360;
        !           117: 
        !           118: 
        !           119: /*
        !           120:  *  AddToAngle:
        !           121:  *     - adds the 3D angular velocity to the 3D angle
        !           122:  */
        !           123: 
        !           124: VOID AddToAngle(
        !           125:     POINT3D *ppt3Angle,
        !           126:     POINT3D *ppt3AngVel )
        !           127:     {
        !           128:     iAngleAdd (ppt3Angle->x, ppt3AngVel->x)
        !           129:     iAngleAdd (ppt3Angle->y, ppt3AngVel->y)
        !           130:     iAngleAdd (ppt3Angle->z, ppt3AngVel->z)
        !           131:     }
        !           132: 
        !           133: 
        !           134: /*
        !           135:  *  CalcSize:
        !           136:  *     - calculates the new size for sinusoidal size variation
        !           137:  *       ie.  <size> = <middle> + <magnitude> * SIN (<angle>)
        !           138:  */
        !           139: 
        !           140: VOID CalcSize(
        !           141:     POINT3D *ppt3Size,
        !           142:     POINT3D *ppt3SizeMid,
        !           143:     POINT3D *ppt3SizeMag,
        !           144:     POINT3D *ppt3SizeAng )
        !           145:     {
        !           146:     ppt3Size->x = ppt3SizeMid->x +
        !           147:            (INT) (ppt3SizeMag->x * lSin( ppt3SizeAng->x ) >> 14);
        !           148:     ppt3Size->y = ppt3SizeMid->y +
        !           149:            (INT) (ppt3SizeMag->y * lSin( ppt3SizeAng->y ) >> 14);
        !           150:     ppt3Size->z = ppt3SizeMid->z +
        !           151:            (INT) (ppt3SizeMag->z * lSin( ppt3SizeAng->z ) >> 14);
        !           152:     }
        !           153: 
        !           154: 
        !           155: /*
        !           156:  *  CalcPoints:
        !           157:  *     - transform the 3D points to 2D points
        !           158:  *     - transformation includes:
        !           159:  *         a) scaling points
        !           160:  *         b) rotating points around x/y/z axis
        !           161:  *         c) perspective transformation
        !           162:  *         d) translating to centre of window
        !           163:  */
        !           164: 
        !           165: VOID CalcPoints (
        !           166:     PSV psv,
        !           167:     INT cPoints,
        !           168:     POINT3D rgpt3 [],
        !           169:     POINTL rgpt [] )
        !           170:     {
        !           171:     LONG sinx = lSin( psv->pt3Angle.x );
        !           172:     LONG cosx = lSin((psv->pt3Angle.x + 90) % 360 );
        !           173:     LONG siny = lSin( psv->pt3Angle.y );
        !           174:     LONG cosy = lSin((psv->pt3Angle.y + 90) % 360 );
        !           175:     LONG sinz = lSin( psv->pt3Angle.z );
        !           176:     LONG cosz = lSin((psv->pt3Angle.z + 90) % 360 );
        !           177:     LONG x, y, z, x2, y2, z2;
        !           178:     LONG z0 = psv->zViewDist;
        !           179:     INT i;
        !           180:     LONG xSize = psv->pt3Size.x;
        !           181:     LONG ySize = psv->pt3Size.y;
        !           182:     LONG zSize = psv->pt3Size.z;
        !           183: 
        !           184:     for( i=0; i < cPoints; i++ )
        !           185:        {
        !           186:        /* scale points relative to x/y/z axis of shape */
        !           187: 
        !           188:        x = (LONG) rgpt3 [i].x * xSize;
        !           189:        y = (LONG) rgpt3 [i].y * ySize;
        !           190:        z = (LONG) rgpt3 [i].z * zSize;
        !           191: 
        !           192:        /* rotate around X axis */
        !           193: 
        !           194:        y2 = ( y * cosx - z * sinx ) >> 14;
        !           195:        z2 = ( z * cosx + y * sinx ) >> 14;
        !           196: 
        !           197:        /* rotate around Y axis */
        !           198: 
        !           199:        z  = ( z2 * cosy - x * siny ) >> 14;
        !           200:        x2 = ( x * cosy + z2 * siny ) >> 14;
        !           201: 
        !           202:        /* rotate around Z axis */
        !           203: 
        !           204:        x  = ( x2 * cosz - y2 * sinz ) >> 14;
        !           205:        y  = ( y2 * cosz + x2 * sinz ) >> 14;
        !           206: 
        !           207:        if (psv->fShaded)
        !           208:            {
        !           209:            /* store points used for shading */
        !           210:            /* (before perspective - light source is at infinity) */
        !           211: 
        !           212:            pt3FillBuffer [i].x = (INT) (x >> 8);
        !           213:            pt3FillBuffer [i].y = (INT) (y >> 8);
        !           214:            pt3FillBuffer [i].z = (INT) (z >> 8);
        !           215:            }
        !           216: 
        !           217:        if (psv->fPerspective)
        !           218:            {
        !           219:            /* avoid overflow when doing perspective */
        !           220: 
        !           221:            x = (x * (z0 >> 6)) / ((z0 - z) >> 6);
        !           222:            y = (y * (z0 >> 6)) / ((z0 - z) >> 6);
        !           223:            }
        !           224: 
        !           225:        /* store translated points in 2D table */
        !           226:        /* note: points must be rescaled to fit in window */
        !           227: 
        !           228:        rgpt [i].x = (x >> 8) + psv->ptCentre.x;
        !           229:        rgpt [i].y = (( (y >> 8) * yPelAdjust ) >> 10) + psv->ptCentre.y;
        !           230:        }
        !           231:     }
        !           232: 
        !           233: 
        !           234: /*
        !           235:  *  DrawLines:
        !           236:  *     - draws a shape using the lines of the object (clipping off)
        !           237:  */
        !           238: 
        !           239: VOID DrawLines (
        !           240:     HPS hps,
        !           241:     LINE rgline [],
        !           242:     POINTL rgpt [] )
        !           243:     {
        !           244:     INT i;
        !           245:     INT iPoint1, iPoint2 = -1;
        !           246: 
        !           247:     for( i=0; (iPoint1 = rgline [i].p1) >= 0; i++ )
        !           248:        {
        !           249:        if (iPoint1 != iPoint2)
        !           250:            {
        !           251:            GpiSetCurrentPosition( hps, &rgpt [iPoint1] );
        !           252:            }
        !           253:        iPoint2 = rgline [i].p2;
        !           254:        GpiLine( hps, &rgpt [iPoint2] );
        !           255:        }
        !           256:     }
        !           257: 
        !           258: 
        !           259: /*
        !           260:  *  DrawFaces:
        !           261:  *     - draws a shape using the faces of the object (clipping on)
        !           262:  */
        !           263: 
        !           264: VOID DrawFaces (
        !           265:     HPS hps,
        !           266:     FACE rgface [],
        !           267:     POINTL rgpt [] )
        !           268:     {
        !           269:     INT i = 0;
        !           270:     INT iEndFace, cSpread;
        !           271:     INT iPoint1, iPoint2, iPoint3;
        !           272:     LONG xV1, yV1, xV2, yV2;
        !           273:     LONG zNormal;
        !           274: 
        !           275:     iPoint1 = rgface [i++];
        !           276:     do
        !           277:        {
        !           278:        /* get 3 points spread out on surface */
        !           279: 
        !           280:        iEndFace = i;
        !           281:        while (rgface [iEndFace++] >= 0)
        !           282:            ;
        !           283:        cSpread = iEndFace - i + 1;
        !           284: 
        !           285:        if (cSpread > 5)
        !           286:            {
        !           287:            cSpread /= 3;
        !           288:            iPoint2 = rgface [i - 1 + cSpread];
        !           289:            iPoint3 = rgface [i - 1 + 2 * cSpread];
        !           290:            }
        !           291:        else
        !           292:            {
        !           293:            iPoint2 = rgface [i];
        !           294:            iPoint3 = rgface [i + 1];
        !           295:            }
        !           296: 
        !           297:        /* calculate z coordinate of normal (using 3 points on surface) */
        !           298: 
        !           299:        xV1 = rgpt [iPoint3].x - rgpt [iPoint2].x;
        !           300:        yV1 = rgpt [iPoint3].y - rgpt [iPoint2].y;
        !           301:        xV2 = rgpt [iPoint1].x - rgpt [iPoint2].x;
        !           302:        yV2 = rgpt [iPoint1].y - rgpt [iPoint2].y;
        !           303:        zNormal = xV1 * yV2 - yV1 * xV2;
        !           304: 
        !           305:        if (zNormal > 0)
        !           306:            {
        !           307:            /* face is pointing towards the user */
        !           308: 
        !           309:            /* draw the perimeter of the face */
        !           310: 
        !           311:            GpiSetCurrentPosition( hps, &rgpt [iPoint1] );
        !           312:            while (( iPoint2 = rgface [i++] ) >= 0)
        !           313:                GpiLine( hps, &rgpt [iPoint2] );
        !           314:            GpiLine( hps, &rgpt [iPoint1] );
        !           315: 
        !           316:            while (iPoint2 == -1)
        !           317:                {
        !           318:                /* draw a pattern associated with the face */
        !           319: 
        !           320:                iPoint1 = rgface [i++];
        !           321:                GpiSetCurrentPosition( hps, &rgpt [iPoint1] );
        !           322:                while ((iPoint2 = rgface [i++] ) >= 0)
        !           323:                    GpiLine( hps, &rgpt [iPoint2] );
        !           324:                }
        !           325:            }
        !           326:        else
        !           327:            /* face is not visible - skip over it */
        !           328: 
        !           329:            while (rgface [i++] >= -1)
        !           330:                ;
        !           331:        }
        !           332:     while (( iPoint1 = rgface [i++] ) >= 0);
        !           333:     }
        !           334: 
        !           335: 
        !           336: /*
        !           337:  *  ChangeShapePosition:
        !           338:  *     - calculate 2D points for new position
        !           339:  *     - blank out old position
        !           340:  *     - draw in new position
        !           341:  */
        !           342: 
        !           343: extern VOID ChangeShapePosition (
        !           344:     PSV psv )
        !           345:     {
        !           346:     HPS hps;
        !           347:     POINTL *pptTemp;
        !           348:     SHAPE *pshape = &rgshape [psv->iShape];
        !           349:     OBJECT *pobject = pshape->pobject;
        !           350: 
        !           351:     if (psv->fVarySize)
        !           352:        {
        !           353:        /* vary the size */
        !           354: 
        !           355:        AddToAngle (&psv->pt3SizeAng, &pshape->pinit->pt3SizeVel );
        !           356:        CalcSize (&psv->pt3Size, &psv->pt3SizeMid,
        !           357:            &psv->pt3SizeMag, &psv->pt3SizeAng );
        !           358:        }
        !           359: 
        !           360:     /* rotate */
        !           361: 
        !           362:     AddToAngle (&psv->pt3Angle, &psv->pt3AngVel );
        !           363: 
        !           364:     /* calculate new position */
        !           365: 
        !           366:     CalcPoints (psv, pobject->cPoints, pobject->rgpt3, psv->rgptNew );
        !           367: 
        !           368:     hps = psv->hpsClient;
        !           369: 
        !           370:     /* blank out old position */
        !           371: 
        !           372:     if (psv->fErased)
        !           373:        psv->fErased = FALSE;
        !           374:     else
        !           375:        {
        !           376:        GpiSetColor (hps, CLR_WHITE);
        !           377:        if (psv->fClipping)
        !           378:            DrawFaces (hps, pobject->rgface, psv->rgptOld );
        !           379:        else
        !           380:            DrawLines (hps, pobject->rgline, psv->rgptOld );
        !           381:        }
        !           382: 
        !           383:     /* draw at new position */
        !           384: 
        !           385:     GpiSetColor (hps, CLR_BLACK);
        !           386:     if (psv->fClipping)
        !           387:        DrawFaces (hps, pobject->rgface, psv->rgptNew );
        !           388:     else
        !           389:        DrawLines (hps, pobject->rgline, psv->rgptNew );
        !           390: 
        !           391:     /* swap 2D points buffers - new becomes old */
        !           392: 
        !           393:     pptTemp = psv->rgptOld;
        !           394:     psv->rgptOld = psv->rgptNew;
        !           395:     psv->rgptNew = pptTemp;
        !           396:     }
        !           397: 
        !           398: 
        !           399: VOID DrawAndFill (
        !           400:     PSV psv )
        !           401:     {
        !           402:     HPS hps = psv->hpsClient;
        !           403:     OBJECT *pobject = rgshape [psv->iShape].pobject;
        !           404:     FACE *rgface = pobject->rgface;
        !           405:     POINTL *rgpt = psv->rgptNew;
        !           406:     INT i = 0;
        !           407:     INT iEndFace, cSpread;
        !           408:     INT iPoint1, iPoint2, iPoint3;
        !           409:     LONG xV1, yV1, zV1, xV2, yV2, zV2;
        !           410:     LONG iDiv;
        !           411:     LONG xN, yN, zN;
        !           412:     LONG zNormal;
        !           413:     LONG sinx = lSin( psv->pt2LightAng.x );
        !           414:     LONG cosx = lSin((psv->pt2LightAng.x + 90) % 360 );
        !           415:     LONG siny = lSin( psv->pt2LightAng.y );
        !           416:     LONG cosy = lSin((psv->pt2LightAng.y + 90) % 360 );
        !           417:     POINTL pt;
        !           418: 
        !           419:     CalcPoints (psv, pobject->cPoints, pobject->rgpt3, rgpt );
        !           420: 
        !           421:     GpiSavePS (hps);
        !           422:     GpiCreateLogColorTable (hps, LCOL_RESET, LCOLF_RGB, 0L, 0L, NULL);
        !           423: 
        !           424:     iPoint1 = rgface [i++];
        !           425:     do
        !           426:        {
        !           427:        /* get 3 points spread out on surface */
        !           428: 
        !           429:        iEndFace = i;
        !           430:        while (rgface [iEndFace++] >= 0)
        !           431:            ;
        !           432:        cSpread = iEndFace - i + 1;
        !           433: 
        !           434:        if (cSpread > 5)
        !           435:            {
        !           436:            cSpread /= 3;
        !           437:            iPoint2 = rgface [i - 1 + cSpread];
        !           438:            iPoint3 = rgface [i - 1 + 2 * cSpread];
        !           439:            }
        !           440:        else
        !           441:            {
        !           442:            iPoint2 = rgface [i];
        !           443:            iPoint3 = rgface [i + 1];
        !           444:            }
        !           445: 
        !           446:        /* calculate z coordinate of normal (using 3 points on surface) */
        !           447: 
        !           448:        xV1 = rgpt [iPoint3].x - rgpt [iPoint2].x;
        !           449:        yV1 = rgpt [iPoint3].y - rgpt [iPoint2].y;
        !           450:        xV2 = rgpt [iPoint1].x - rgpt [iPoint2].x;
        !           451:        yV2 = rgpt [iPoint1].y - rgpt [iPoint2].y;
        !           452:        zNormal = xV1 * yV2 - yV1 * xV2;
        !           453: 
        !           454:        if (zNormal > 0)
        !           455:            {
        !           456:            /* face is pointing towards the user */
        !           457: 
        !           458:            /* normalize vectors */
        !           459: 
        !           460:            xV1 = pt3FillBuffer [iPoint3].x - pt3FillBuffer [iPoint2].x;
        !           461:            yV1 = pt3FillBuffer [iPoint3].y - pt3FillBuffer [iPoint2].y;
        !           462:            zV1 = pt3FillBuffer [iPoint3].z - pt3FillBuffer [iPoint2].z;
        !           463: 
        !           464:            xV2 = pt3FillBuffer [iPoint1].x - pt3FillBuffer [iPoint2].x;
        !           465:            yV2 = pt3FillBuffer [iPoint1].y - pt3FillBuffer [iPoint2].y;
        !           466:            zV2 = pt3FillBuffer [iPoint1].z - pt3FillBuffer [iPoint2].z;
        !           467: 
        !           468:            iDiv = (LONG) sqrt ((double) (xV1 * xV1 + yV1 * yV1 + zV1 * zV1) );
        !           469:            xV1 = (xV1 << 10) / iDiv;
        !           470:            yV1 = (yV1 << 10) / iDiv;
        !           471:            zV1 = (zV1 << 10) / iDiv;
        !           472: 
        !           473:            iDiv = (LONG) sqrt ((double) (xV2 * xV2 + yV2 * yV2 + zV2 * zV2) );
        !           474:            xV2 = (xV2 << 10) / iDiv;
        !           475:            yV2 = (yV2 << 10) / iDiv;
        !           476:            zV2 = (zV2 << 10) / iDiv;
        !           477: 
        !           478:            /* calculate normal to surface */
        !           479: 
        !           480:            xN = (yV1 * zV2 - zV1 * yV2) >> 10;
        !           481:            yN = (zV1 * xV2 - xV1 * zV2) >> 10;
        !           482:            zN = (xV1 * yV2 - yV1 * xV2) >> 10;
        !           483: 
        !           484:            /* rotate normal around X and Y axes */
        !           485: 
        !           486:            zN = ( zN * cosx + xN * sinx ) >> 14;
        !           487:            zN = ( zN * cosy + yN * siny ) >> 14;
        !           488: 
        !           489:            /* change range of zNormal from [0,1023] to [128,255] */
        !           490: 
        !           491:            zNormal = zN >> 3;
        !           492:            if (zNormal < 0)
        !           493:                zNormal = 0;
        !           494:            else if (zNormal > 127)
        !           495:                zNormal = 127;
        !           496:            zNormal += 128;
        !           497: 
        !           498:            GpiSetColor (hps, zNormal);
        !           499: 
        !           500:            /* draw the perimeter of the face */
        !           501: 
        !           502:            GpiBeginArea (hps, BA_NOBOUNDARY | BA_ALTERNATE);
        !           503: 
        !           504:            GpiSetCurrentPosition( hps, &rgpt [iPoint1] );
        !           505:            while (( iPoint2 = rgface [i++] ) >= 0)
        !           506:                GpiLine( hps, &rgpt [iPoint2] );
        !           507:            GpiLine( hps, &rgpt [iPoint1] );
        !           508: 
        !           509:            GpiEndArea (hps);
        !           510: 
        !           511:            GpiSetColor (hps, zNormal << 16 );
        !           512: 
        !           513:            while (iPoint2 == -1)
        !           514:                {
        !           515:                /* draw a pattern associated with the face */
        !           516: 
        !           517:                iPoint1 = rgface [i++];
        !           518:                GpiSetCurrentPosition( hps, &rgpt [iPoint1] );
        !           519:                while ((iPoint2 = rgface [i++] ) >= 0)
        !           520:                    GpiLine( hps, &rgpt [iPoint2] );
        !           521:                }
        !           522:            }
        !           523:        else
        !           524:            /* face is not visible - skip over it */
        !           525: 
        !           526:            while (rgface [i++] >= -1)
        !           527:                ;
        !           528:        }
        !           529:     while (( iPoint1 = rgface [i++] ) >= 0);
        !           530: 
        !           531:     GpiRestorePS (hps, -1L);
        !           532:     }

unix.superglobalmegacorp.com

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