JurassicParkTrespasser/jp2_pc/Source/Test/scan.cpp
2018-01-01 23:07:24 +01:00

178 lines
4.7 KiB
C++

/***********************************************************************************************
*
* Copyright © DreamWorks Interactive. 1996
*
* Implementation of scan.hpp.
*
***********************************************************************************************
*
* $Log:: /JP2_PC/Source/Test/scan.cpp $
*
* 7 96/07/12 18:02 Speter
* Added Z checking to scanline loop.
*
* 6 96/06/26 16:44 Speter
* Updated for new transform modules.
*
* 5 96/05/23 9:42 Speter
* Added casts to avoid warnings.
*
* 4 96/05/13 14:21 Speter
* Changed bWithin call to bBetween
*
* 3 96/05/07 15:21 Speter
* Made coordinate type an additional template parameter.
* Use integer Y instead of real Y to iterate through scanline values.
*
* 2 96/04/24 12:55 Speter
* Test files for RasterTest project now converted to work in our common code base. Still not
* style-compliant.
*
* 1 96/04/23 16:22 Speter
* These are all test files to help test raster, geom, etc.
* They are not JP2PC-style compatible.
*
**********************************************************************************************/
#include <math.h>
#include "common.hpp"
#include "scan.hpp"
/*************************************************************************
* CScanPoly implementation
*************************************************************************/
template<class T, class Coord> CScanPoly<T, Coord>::CScanPoly(Coord acoord[], int i_cnt, int i_left, int i_top, int i_right, int i_bottom)
/*
* Constructor for the iterator. Sets structure up for iteration by saving
* relevant initialisation parameters, and calculating min and max Y.
*/
{
// Initialise struct.
acoordPoly = acoord;
iCount = i_cnt;
// Copy clip coords in floating point.
Left = (T) i_left;
Right = (T) i_right;
// Find min and max Y.
T t_y = acoordPoly[0].tY;
T t_ymax = acoordPoly[0].tY;
for (int i = 1; i < iCount; i++)
{
SetMin(t_y, acoordPoly[i].tY);
SetMax(t_ymax, acoordPoly[i].tY);
}
//
// Set Y and Ymax to integer values.
//
iY = Max((int)ceil(t_y), i_top);
iYmax = Min((int)t_ymax, i_bottom);
// Subtract 1 from Y in anticipation of first call to operator++().
iY--;
}
template<class T, class Coord> bool CScanPoly<T, Coord>::operator ++(int)
/*
* The iterator. Increments Y, then calculates iX1 and iX2 for that Y.
* Returns 1 if not done, 0 if done.
*
* Method:
* For a given Y, the horizontal line is intersected with every side of the poly.
* The minimum and maximum iX values of the intersections become iX1 and iX2.
*
****/
{
// Loop until we get to a Y value that isn't clipped away.
for (;;)
{
iY++;
if (iY >= iYmax)
return 0;
T t_y = (T) iY;
// Search thru all sides, finding intersections with horizontal line at t_y.
bool b_found = 0;
for (int i = 0; i < iCount; i++) {
int i_2 = i+1;
if (i_2 == iCount) i_2 = 0;
if (bBetween(t_y, acoordPoly[i].tY, acoordPoly[i_2].tY))
{
// It intersects side i.
if (acoordPoly[i].tY == acoordPoly[i_2].tY)
{
// The side is a horizontal line, get the 2 points.
if (acoordPoly[i].tX < acoordPoly[i_2].tX)
{
coordLeft = acoordPoly[i];
coordRight = acoordPoly[i_2];
}
else
{
coordLeft = acoordPoly[i_2];
coordRight = acoordPoly[i];
}
}
else
{
//
// Find the intersecting point.
// The Coord operators + and * will give us the
// value of X at the intersection, as well as all
// other associated values (e.g. u,v).
//
T t = (t_y - acoordPoly[i].tY)
/ (acoordPoly[i_2].tY - acoordPoly[i].tY);
Coord coord = acoordPoly[i] * (T(1) - t)
+ acoordPoly[i_2] * t;
if (!b_found)
coordLeft = coordRight = coord;
else
{
if (coord.tX < coordLeft.tX)
coordLeft = coord;
if (coord.tX > coordRight.tX)
coordRight = coord;
}
}
b_found = 1;
}
}
//
// Now we have left and right coords.
// Calculate x increment.
//
if (coordLeft.tX != coordRight.tX)
coordInc = (coordRight - coordLeft) / (coordRight.tX - coordLeft.tX);
//
// Now round the coordinates to integers.
//
iX1 = (int) Max((T) ceil(coordLeft.tX), Left);
iX2 = (int) Min((T) floor(coordRight.tX), Right);
if (iX1 > iX2)
continue;
// Adjust associated values.
coordLeft += coordInc * ((T)iX1 - coordLeft.tX);
coordRight += coordInc * ((T)iX2 - coordRight.tX);
if (coordLeft.tZ < (T)0.1 || coordRight.tZ < (T)0.1)
continue;
// Line is visible.
return 1;
}
}