123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- //===========================================================================//
- // Copyright (C) Microsoft Corporation. All rights reserved. //
- //===========================================================================//
- //---------------------------------------------------------------------------------------------------
- // Screen Clip code for use with video cards without guard bands and BLADE.
- //
- // Generally, we will only need one or two of the below routines per triangle.
- //
- // If a triangle is completely on screen, none of the below should be called.
- //
- // Each triangle can be easily checked to see which of the below should be
- // called in its case. An easy, low-end machine optimization would be to
- // NOT call any of the below for TGL/MSL shapes which are partly off screen
- // and simply not to draw the shape. Profiling will indicate if this is
- // necessary.
- //
- // Color space clipping is HUGELY painful and we are cheating until it
- // becomes necessary to do otherwise.
- //
- // Triangles will be converted into polygons with as many as five sides.
- // It will be necessary in the draw code to hand the vertices down to
- // GOS/BLADE in triangles to avoid any weirdness in their code!
- //
- // These routines are easily optimized and assembled if and when it becomes
- // necessary to do so. Routines should be inlined for speed!
- //---------------------------------------------------------------------------------------------------
- #ifndef CLIP_H
- #define CLIP_H
- #include <gameos.hpp>
- //---------------------------------------------------------------------------------------------------
- inline void xLeftEdgeclip (gos_VERTEX *vertices, long &numVertices, float leftEdge)
- {
- //------------------------------------------
- //make local copy of all point data involved
- gos_VERTEX points[6];
- memcpy(points,vertices,sizeof(gos_VERTEX)*numVertices);
- //------------------------------------------
- long first = numVertices-1;
- long second = 0;
- //----------------------------------------------
- // Index to current vertex in clipped polygon.
- //----------------------------------------------
- long work = 0;
- //------------------------------
- //final number of polygon points
- //------------------------------
- long n_points= 0;
- //----------------------------
- //process points in edge order
- //----------------------------
- for (long s=0; s<numVertices; s++, second++)
- {
- float clipEdgeTest = points[first].x;
- //----------------------------------------------------------------
- // if this point is not beyond the clipping Edge, store it.
- //----------------------------------------------------------------
- if (clipEdgeTest >= leftEdge)
- {
- //------------------------------------------------------------
- gos_VERTEX* workv = &(vertices[work]);
- memcpy(workv,&(points[first]),sizeof(gos_VERTEX));
- //------------------------------------------------------------
-
- work++;
- n_points++;
- }
-
- //------------------------------------------------------------
- //if the line defined by first and second intersects the
- //clipping plane, generate a new point and calculate its info.
- //------------------------------------------------------------
-
- if (((clipEdgeTest < leftEdge) && (points[second].x >= leftEdge)) ||
- ((clipEdgeTest >= leftEdge) && (points[second].x < leftEdge)))
- {
- gos_VERTEX* workv = &(vertices[work]);
-
- float sry = points[second].y;
- float srx = points[second].x;
- float srz = points[second].z;
- float srw = points[second].rhw;
- float sru = points[second].u;
- float srv = points[second].v;
-
- float fry = points[first].y;
- float frx = points[first].x;
- float frz = points[first].z;
- float frw = points[first].rhw;
- float fru = points[first].u;
- float frv = points[first].v;
-
- float mu = (leftEdge - srx)/(frx - srx);
-
- workv->x = leftEdge;
- workv->y = ((fry - sry) * mu) + sry;
- workv->z = ((frz - srz) * mu) + srz;
- // Clipping color is HUGELY painful at this point. Try cheating first!
- if (clipEdgeTest < leftEdge)
- {
- workv->argb = points[first].argb;
- workv->frgb = points[first].frgb;
- }
- else
- {
- workv->argb = points[second].argb;
- workv->frgb = points[second].frgb;
- }
- workv->rhw = ((frw - srw) * mu) + srw;
- workv->u = ((fru - sru) * mu) + sru;
- workv->v = ((frv - srv) * mu) + srv;
- work++;
- n_points++;
- }
-
- first = second;
- }
- numVertices = n_points;
- }
- //---------------------------------------------------------------------------------------------------
- inline void xRightEdgeclip (gos_VERTEX *vertices, long &numVertices, float rightEdge)
- {
- //------------------------------------------
- //make local copy of all point data involved
- gos_VERTEX points[6];
- memcpy(points,vertices,sizeof(gos_VERTEX)*numVertices);
- //------------------------------------------
- long first = numVertices-1;
- long second = 0;
- //----------------------------------------------
- // Index to current vertex in clipped polygon.
- //----------------------------------------------
- long work = 0;
- //------------------------------
- //final number of polygon points
- //------------------------------
- long n_points= 0;
- //----------------------------
- //process points in edge order
- //----------------------------
- for (long s=0; s<numVertices; s++, second++)
- {
- float clipEdgeTest = points[first].x;
- //----------------------------------------------------------------
- // if this point is not beyond the clipping Edge, store it.
- //----------------------------------------------------------------
- if (clipEdgeTest < rightEdge)
- {
- //------------------------------------------------------------
- gos_VERTEX* workv = &(vertices[work]);
- memcpy(workv,&(points[first]),sizeof(gos_VERTEX));
- //------------------------------------------------------------
-
- work++;
- n_points++;
- }
-
- //------------------------------------------------------------
- //if the line defined by first and second intersects the
- //clipping plane, generate a new point and calculate its info.
- //------------------------------------------------------------
-
- if (((clipEdgeTest >= rightEdge) && (points[second].x < rightEdge)) ||
- ((clipEdgeTest < rightEdge) && (points[second].x >= rightEdge)))
- {
- gos_VERTEX* workv = &(vertices[work]);
-
- float sry = points[second].y;
- float srx = points[second].x;
- float srz = points[second].z;
- float srw = points[second].rhw;
- float sru = points[second].u;
- float srv = points[second].v;
-
- float fry = points[first].y;
- float frx = points[first].x;
- float frz = points[first].z;
- float frw = points[first].rhw;
- float fru = points[first].u;
- float frv = points[first].v;
-
- float mu = (rightEdge - srx)/(frx - srx);
-
- workv->x = rightEdge - 1.0f;
- workv->y = ((fry - sry) * mu) + sry;
- workv->z = ((frz - srz) * mu) + srz;
- // Clipping color is HUGELY painful at this point. Try cheating first!
- if (clipEdgeTest >= rightEdge)
- {
- workv->argb = points[first].argb;
- workv->frgb = points[first].frgb;
- }
- else
- {
- workv->argb = points[second].argb;
- workv->frgb = points[second].frgb;
- }
- workv->rhw = ((frw - srw) * mu) + srw;
- workv->u = ((fru - sru) * mu) + sru;
- workv->v = ((frv - srv) * mu) + srv;
- work++;
- n_points++;
- }
-
- first = second;
- }
- numVertices = n_points;
- }
- //---------------------------------------------------------------------------------------------------
- inline void yTopEdgeclip (gos_VERTEX *vertices, long &numVertices, float topEdge)
- {
- //------------------------------------------
- //make local copy of all point data involved
- gos_VERTEX points[6];
- memcpy(points,vertices,sizeof(gos_VERTEX)*numVertices);
- //------------------------------------------
- long first = numVertices-1;
- long second = 0;
- //----------------------------------------------
- // Index to current vertex in clipped polygon.
- //----------------------------------------------
- long work = 0;
- //------------------------------
- //final number of polygon points
- //------------------------------
- long n_points= 0;
- //----------------------------
- //process points in edge order
- //----------------------------
- for (long s=0; s<numVertices; s++, second++)
- {
- float clipEdgeTest = points[first].y;
- //----------------------------------------------------------------
- // if this point is not beyond the clipping Edge, store it.
- //----------------------------------------------------------------
- if (clipEdgeTest >= topEdge)
- {
- //------------------------------------------------------------
- gos_VERTEX* workv = &(vertices[work]);
- memcpy(workv,&(points[first]),sizeof(gos_VERTEX));
- //------------------------------------------------------------
-
- work++;
- n_points++;
- }
-
- //------------------------------------------------------------
- //if the line defined by first and second intersects the
- //clipping plane, generate a new point and calculate its info.
- //------------------------------------------------------------
-
- if (((clipEdgeTest < topEdge) && (points[second].y >= topEdge)) ||
- ((clipEdgeTest >= topEdge) && (points[second].y < topEdge)))
- {
- gos_VERTEX* workv = &(vertices[work]);
-
- float sry = points[second].y;
- float srx = points[second].x;
- float srz = points[second].z;
- float srw = points[second].rhw;
- float sru = points[second].u;
- float srv = points[second].v;
-
- float fry = points[first].y;
- float frx = points[first].x;
- float frz = points[first].z;
- float frw = points[first].rhw;
- float fru = points[first].u;
- float frv = points[first].v;
-
- float mu = (topEdge - sry)/(fry - sry);
-
- workv->y = topEdge;
- workv->x = ((frx - srx) * mu) + srx;
- workv->z = ((frz - srz) * mu) + srz;
- // Clipping color is HUGELY painful at this point. Try cheating first!
- if (clipEdgeTest < topEdge)
- {
- workv->argb = points[first].argb;
- workv->frgb = points[first].frgb;
- }
- else
- {
- workv->argb = points[second].argb;
- workv->frgb = points[second].frgb;
- }
- workv->rhw = ((frw - srw) * mu) + srw;
- workv->u = ((fru - sru) * mu) + sru;
- workv->v = ((frv - srv) * mu) + srv;
- work++;
- n_points++;
- }
-
- first = second;
- }
- numVertices = n_points;
- }
- //---------------------------------------------------------------------------------------------------
- inline void yBottomEdgeclip (gos_VERTEX *vertices, long &numVertices, float bottomEdge)
- {
- //------------------------------------------
- //make local copy of all point data involved
- gos_VERTEX points[6];
- memcpy(points,vertices,sizeof(gos_VERTEX)*numVertices);
- //------------------------------------------
- long first = numVertices-1;
- long second = 0;
- //----------------------------------------------
- // Index to current vertex in clipped polygon.
- //----------------------------------------------
- long work = 0;
- //------------------------------
- //final number of polygon points
- //------------------------------
- long n_points= 0;
- //----------------------------
- //process points in edge order
- //----------------------------
- for (long s=0; s<numVertices; s++, second++)
- {
- float clipEdgeTest = points[first].y;
- //----------------------------------------------------------------
- // if this point is not beyond the clipping Edge, store it.
- //----------------------------------------------------------------
- if (clipEdgeTest < bottomEdge)
- {
- //------------------------------------------------------------
- gos_VERTEX* workv = &(vertices[work]);
- memcpy(workv,&(points[first]),sizeof(gos_VERTEX));
- //------------------------------------------------------------
-
- work++;
- n_points++;
- }
-
- //------------------------------------------------------------
- //if the line defined by first and second intersects the
- //clipping plane, generate a new point and calculate its info.
- //------------------------------------------------------------
-
- if (((clipEdgeTest >= bottomEdge) && (points[second].y < bottomEdge)) ||
- ((clipEdgeTest < bottomEdge) && (points[second].y >= bottomEdge)))
- {
- gos_VERTEX* workv = &(vertices[work]);
-
- float sry = points[second].y;
- float srx = points[second].x;
- float srz = points[second].z;
- float srw = points[second].rhw;
- float sru = points[second].u;
- float srv = points[second].v;
-
- float fry = points[first].y;
- float frx = points[first].x;
- float frz = points[first].z;
- float frw = points[first].rhw;
- float fru = points[first].u;
- float frv = points[first].v;
-
- float mu = (bottomEdge - sry)/(fry - sry);
-
- workv->y = bottomEdge - 1.0f;
- workv->x = ((frx - srx) * mu) + srx;
- workv->z = ((frz - srz) * mu) + srz;
- // Clipping color is HUGELY painful at this point. Try cheating first!
- if (clipEdgeTest >= bottomEdge)
- {
- workv->argb = points[first].argb;
- workv->frgb = points[first].frgb;
- }
- else
- {
- workv->argb = points[second].argb;
- workv->frgb = points[second].frgb;
- }
- workv->rhw = ((frw - srw) * mu) + srw;
- workv->u = ((fru - sru) * mu) + sru;
- workv->v = ((frv - srv) * mu) + srv;
- work++;
- n_points++;
- }
-
- first = second;
- }
- numVertices = n_points;
- }
- //---------------------------------------------------------------------------------------------------
- #endif
|