Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
1677 lines
38 KiB
C++
1677 lines
38 KiB
C++
#include <MLR\MLRHeaders.hpp>
|
|
|
|
#if !defined(HFSLIMMZ0P3_HPP)
|
|
#include "HFSlimMZ0p3.hpp"
|
|
#include "terra\terra.hpp"
|
|
#endif
|
|
|
|
const Scalar One_Over_Three = 1.0f/3.0f;
|
|
|
|
extern FILE *analyzeFile;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ToDrawTriangle::GetSurfaceAreaAndCentroid()
|
|
{
|
|
//
|
|
//---------------------
|
|
// Set up the variables
|
|
//---------------------
|
|
//
|
|
Point3D
|
|
position_a = Point3D::Identity,
|
|
position_b,
|
|
position_c = Point3D::Identity;
|
|
Vector3D
|
|
leg_1,
|
|
leg_2 = Vector3D::Identity;
|
|
|
|
//
|
|
//-----------------------------------
|
|
// Spin through, testing the vertices
|
|
//-----------------------------------
|
|
//
|
|
area = 0.0f;
|
|
center = Point3D::Identity;
|
|
|
|
//
|
|
//-----------------------------------------------
|
|
// Generate all the information on the first pass
|
|
//-----------------------------------------------
|
|
//
|
|
position_a = v[0];
|
|
position_b = v[1];
|
|
position_c = v[2];
|
|
|
|
leg_1.Subtract(position_b, position_a);
|
|
leg_2.Subtract(position_c, position_a);
|
|
|
|
//
|
|
//-----------------------------------------------------------------
|
|
// Compute the cross-product of the two legs to get the area of the
|
|
// triangle
|
|
//-----------------------------------------------------------------
|
|
//
|
|
Vector3D vcp;
|
|
vcp.Cross(leg_1, leg_2);
|
|
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// Add the three triangle points together and multiply by the area of
|
|
// the triangle to give a weighted sum for the polygon centroid
|
|
//-------------------------------------------------------------------
|
|
//
|
|
Point3D centroid;
|
|
centroid.Add(position_a, position_b);
|
|
centroid += position_c;
|
|
|
|
Scalar wedge_area = vcp.GetLength() * 0.5f;
|
|
|
|
if (area <= SMALL)
|
|
{
|
|
if (wedge_area > SMALL)
|
|
{
|
|
area += wedge_area;
|
|
centroid *= wedge_area;
|
|
}
|
|
center = centroid;
|
|
}
|
|
else
|
|
{
|
|
if (wedge_area > SMALL)
|
|
{
|
|
area += wedge_area;
|
|
centroid *= wedge_area;
|
|
center += centroid;
|
|
}
|
|
}
|
|
|
|
plane.normal.x = 0.0f;
|
|
plane.normal.y = 0.0f;
|
|
plane.normal.z = 1.0f;
|
|
plane.offset = 0.0f;
|
|
|
|
if(area > SMALL)
|
|
{
|
|
plane.BuildPlane(
|
|
v[0],
|
|
v[2],
|
|
v[1]
|
|
);
|
|
|
|
center *= (One_Over_Three/area);
|
|
}
|
|
else
|
|
{
|
|
center *= One_Over_Three;
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
HFSlimMZ0p3::HFSlimMZ0p3()
|
|
{
|
|
X = (int)0.0f;
|
|
Z = (int)0.0f;
|
|
|
|
dX = 2.0f;
|
|
dY = 0.15f;
|
|
dZ = 2.0f;
|
|
|
|
xOffset = 0.0f;
|
|
zOffset = 0.0f;
|
|
|
|
Offset = 0.0f;
|
|
visHeight = 0;
|
|
|
|
simpleTerrainGroup.SetLength(0);
|
|
|
|
borderPixelFun = 0.0f;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
HFSlimMZ0p3::~HFSlimMZ0p3()
|
|
{
|
|
for(int i=0;i<simpleTerrainGroup.GetLength();i++)
|
|
{
|
|
Unregister_Object(simpleTerrainGroup[i]);
|
|
delete simpleTerrainGroup[i];
|
|
simpleTerrainGroup[i] = NULL;
|
|
}
|
|
simpleTerrainGroup.SetLength(0);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Stuff::ExtentBox
|
|
HFSlimMZ0p3::GetExtents()
|
|
{
|
|
Stuff::ExtentBox ebox;
|
|
|
|
ebox.minX = GetX(0);
|
|
ebox.minZ = GetZ(0);
|
|
|
|
ebox.maxX = GetX(X-1);
|
|
ebox.maxZ = GetZ(Z-1);
|
|
|
|
int i, j;
|
|
Scalar h;
|
|
ebox.maxY = ebox.minY = GetHeight(0, 0);
|
|
|
|
for (j=1;j<Z;j++)
|
|
for (i=1;i<X;i++)
|
|
{
|
|
h = GetHeight(i, j);
|
|
if(ebox.maxY < h)
|
|
{
|
|
ebox.maxY = h;
|
|
}
|
|
if(ebox.minY > h)
|
|
{
|
|
ebox.minY = h;
|
|
}
|
|
}
|
|
|
|
return ebox;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void
|
|
HFSlimMZ0p3::Blur2D (int smooth)
|
|
{
|
|
|
|
// Precondition for stability: 0 < scale < exp(0.25)
|
|
// Good choice for iterative blurring is scale = exp(0.125)
|
|
float scale = static_cast<float>(exp(0.125));
|
|
float** temp = new float*[Z];
|
|
int x, y;
|
|
for (y = 0; y < Z; y++)
|
|
temp[y] = new float[X];
|
|
|
|
for(int i=0;i<smooth;i++)
|
|
{
|
|
float logscale = float(log(scale));
|
|
|
|
for (y = 0; y < Z; y++)
|
|
{
|
|
float ryp = y+scale, rym = y-scale;
|
|
int yp = (int) floor(ryp), ym = (int) ceil(rym);
|
|
|
|
for (x = 0; x < X; x++)
|
|
{
|
|
float rxp = x+scale, rxm = x-scale;
|
|
int xp = (int) floor(rxp), xm = (int) ceil(rxm);
|
|
|
|
// x portion of second central difference
|
|
float xsum = -2*field[y*X+x];
|
|
if ( xp >= X-1 ) // use boundary value
|
|
xsum += field[y*X+X-1];
|
|
else // linearly interpolate
|
|
xsum += field[y*X+xp]+(rxp-xp)*(field[y*X+xp+1]-field[y*X+xp]);
|
|
if ( xm <= 0 ) // use boundary value
|
|
xsum += field[y*X+0];
|
|
else // linearly interpolate
|
|
xsum += field[y*X+xm]+(rxm-xm)*(field[y*X+xm]-field[y*X+xm-1]);
|
|
|
|
// y portion of second central difference
|
|
float ysum = -2*field[y*X+x];
|
|
if ( yp >= Z-1 ) // use boundary value
|
|
ysum += field[(Z-1)*X+x];
|
|
else // linearly interpolate
|
|
ysum += field[yp*X+x]+(ryp-yp)*(field[(yp+1)*X+x]-field[yp*X+x]);
|
|
if ( ym <= 0 ) // use boundary value
|
|
ysum += field[0*X+x];
|
|
else // linearly interpolate
|
|
ysum += field[ym*X+x]+(rym-ym)*(field[ym*X+x]-field[(ym-1)*X+x]);
|
|
|
|
temp[y][x] = field[y*X+x]+logscale*(xsum+ysum);
|
|
}
|
|
}
|
|
|
|
for (y = 0; y < Z; y++)
|
|
for (x = 0; x < X; x++)
|
|
field[y*X+x] = temp[y][x];
|
|
}
|
|
|
|
for (y = 0; y < Z; y++)
|
|
delete[] temp[y];
|
|
delete[] temp;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
HFSlimMZ0p3::FillFromImage(Image &image, int smooth)
|
|
{
|
|
X = image.GetWidth()+1;
|
|
Z = image.GetHeight()+1;
|
|
|
|
Verify(((X-1)%256 == 0) && ((Z-1)%256 == 0));
|
|
xDim = image.GetWidth()/256;
|
|
zDim = image.GetHeight()/256;
|
|
|
|
Verify(image.GetBpp()==8);
|
|
|
|
field.SetLength(X*Z);
|
|
|
|
unsigned char *ptr;
|
|
ptr=(unsigned char *)image.Lock();
|
|
|
|
int i, j;
|
|
for(i=0;i<Z-1;i++)
|
|
{
|
|
for(j=0;j<X-1;j++)
|
|
{
|
|
field[i*X+j] = ptr[(image.GetHeight()-i-1)*(X-1)+image.GetWidth()-j-1];
|
|
}
|
|
field[i*X+j] = field[i*X+j-1];
|
|
}
|
|
for(j=0;j<X-1;j++)
|
|
{
|
|
field[i*X+j] = field[(i-1)*X+j];
|
|
}
|
|
field[i*X+j] = field[i*X+j-1];
|
|
|
|
image.UnLock();
|
|
|
|
Blur2D(smooth);
|
|
}
|
|
|
|
int triangleCounter = 0;
|
|
|
|
Scalar xGridSize, zGridSize;
|
|
int tX, tY;
|
|
|
|
void GetFacesCB(Triangle &tri,void *cbp)
|
|
{
|
|
ToDrawTriangle *tdtrilist = (ToDrawTriangle *)cbp;
|
|
tdtrilist[triangleCounter].SetPoint(0,(float)tri.point1()[0],0.0f,(float)tri.point1()[1]);
|
|
tdtrilist[triangleCounter].SetPoint(1,(float)tri.point2()[0],0.0f,(float)tri.point2()[1]);
|
|
tdtrilist[triangleCounter].SetPoint(2,(float)tri.point3()[0],0.0f,(float)tri.point3()[1]);
|
|
|
|
triangleCounter++;
|
|
}
|
|
|
|
#define TERRAIN2_TEST
|
|
|
|
Point3D center;
|
|
Scalar maxRadius;
|
|
|
|
bool
|
|
HFSlimMZ0p3::CreateMesh(
|
|
MLR_Terrain2 *erf_mesh,
|
|
DynamicArrayOf<ToDrawTriangle*>& tdtrilist,
|
|
ExtentBox *uvFrame
|
|
)
|
|
{
|
|
int polygon_count = tdtrilist.GetLength();
|
|
if(polygon_count==0 || polygon_count*3 >= Limits::Max_Number_Vertices_Per_Mesh)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
DynamicArrayOf<int> vert_id(X*Z);
|
|
memset(vert_id.GetData(), 0, vert_id.GetSize());
|
|
|
|
int i, j, x, z, point_count = 0;
|
|
|
|
int minX[2]={0,0},
|
|
maxX[2]={0,0},
|
|
minY[2]={0,0},
|
|
maxY[2]={0,0},
|
|
minZ[2]={0,0},
|
|
maxZ[2]={0,0};
|
|
Scalar
|
|
minx=tdtrilist[0]->v[0].x,
|
|
maxx=tdtrilist[0]->v[0].x,
|
|
miny=tdtrilist[0]->v[0].y,
|
|
maxy=tdtrilist[0]->v[0].y,
|
|
minz=tdtrilist[0]->v[0].z,
|
|
maxz=tdtrilist[0]->v[0].z;
|
|
|
|
Point3D
|
|
center0 = Point3D::Identity,
|
|
center1 = Point3D::Identity,
|
|
center2 = Point3D::Identity,
|
|
center3 = Point3D::Identity;
|
|
|
|
for(i=0;i<polygon_count;++i)
|
|
{
|
|
center3 += tdtrilist[i]->center;
|
|
|
|
if(tdtrilist[i]->v[0].x < minx)
|
|
{
|
|
minX[0] = i;
|
|
minX[1] = 0;
|
|
minx = tdtrilist[i]->v[0].x;
|
|
} else if(tdtrilist[i]->v[0].x > maxx)
|
|
{
|
|
maxX[0] = i;
|
|
maxX[1] = 0;
|
|
maxx = tdtrilist[i]->v[0].x;
|
|
}
|
|
if(tdtrilist[i]->v[0].y < miny)
|
|
{
|
|
minY[0] = i;
|
|
minY[1] = 0;
|
|
miny = tdtrilist[i]->v[0].y;
|
|
} else if(tdtrilist[i]->v[0].y > maxy)
|
|
{
|
|
maxY[0] = i;
|
|
maxY[1] = 0;
|
|
maxy = tdtrilist[i]->v[0].y;
|
|
}
|
|
if(tdtrilist[i]->v[0].z < minz)
|
|
{
|
|
minZ[0] = i;
|
|
minZ[1] = 0;
|
|
minz = tdtrilist[i]->v[0].z;
|
|
} else if(tdtrilist[i]->v[0].z > maxz)
|
|
{
|
|
maxZ[0] = i;
|
|
maxZ[1] = 0;
|
|
maxz = tdtrilist[i]->v[0].z;
|
|
}
|
|
|
|
x = (int)(tdtrilist[i]->v[0].x/dX);
|
|
z = (int)(tdtrilist[i]->v[0].z/dZ);
|
|
|
|
vert_id[x + X*z]++;
|
|
if(vert_id[x + X*z]==1)
|
|
{
|
|
center0 += tdtrilist[i]->v[0];
|
|
point_count++;
|
|
}
|
|
|
|
if(tdtrilist[i]->v[2].x < minx)
|
|
{
|
|
minX[0] = i;
|
|
minX[1] = 2;
|
|
minx = tdtrilist[i]->v[2].x;
|
|
} else if(tdtrilist[i]->v[2].x > maxx)
|
|
{
|
|
maxX[0] = i;
|
|
maxX[1] = 2;
|
|
maxx = tdtrilist[i]->v[2].x;
|
|
}
|
|
if(tdtrilist[i]->v[2].y < miny)
|
|
{
|
|
minY[0] = i;
|
|
minY[1] = 2;
|
|
miny = tdtrilist[i]->v[2].y;
|
|
} else if(tdtrilist[i]->v[2].y > maxy)
|
|
{
|
|
maxY[0] = i;
|
|
maxY[1] = 2;
|
|
maxy = tdtrilist[i]->v[2].y;
|
|
}
|
|
if(tdtrilist[i]->v[2].z < minz)
|
|
{
|
|
minZ[0] = i;
|
|
minZ[1] = 2;
|
|
minz = tdtrilist[i]->v[2].z;
|
|
} else if(tdtrilist[i]->v[2].z > maxz)
|
|
{
|
|
maxZ[0] = i;
|
|
maxZ[1] = 2;
|
|
maxz = tdtrilist[i]->v[2].z;
|
|
}
|
|
x = (int)(tdtrilist[i]->v[2].x/dX);
|
|
z = (int)(tdtrilist[i]->v[2].z/dZ);
|
|
vert_id[x + X*z]++;
|
|
if(vert_id[x + X*z]==1)
|
|
{
|
|
center0 += tdtrilist[i]->v[1];
|
|
point_count++;
|
|
}
|
|
|
|
if(tdtrilist[i]->v[1].x < minx)
|
|
{
|
|
minX[0] = i;
|
|
minX[1] = 0;
|
|
minx = tdtrilist[i]->v[1].x;
|
|
} else if(tdtrilist[i]->v[1].x > maxx)
|
|
{
|
|
maxX[0] = i;
|
|
maxX[1] = 1;
|
|
maxx = tdtrilist[i]->v[1].x;
|
|
}
|
|
if(tdtrilist[i]->v[1].y < miny)
|
|
{
|
|
minY[0] = i;
|
|
minY[1] = 1;
|
|
miny = tdtrilist[i]->v[1].y;
|
|
} else if(tdtrilist[i]->v[1].y > maxy)
|
|
{
|
|
maxY[0] = i;
|
|
maxY[1] = 1;
|
|
maxy = tdtrilist[i]->v[1].y;
|
|
}
|
|
if(tdtrilist[i]->v[1].z < minz)
|
|
{
|
|
minZ[0] = i;
|
|
minZ[1] = 1;
|
|
minz = tdtrilist[i]->v[1].z;
|
|
} else if(tdtrilist[i]->v[1].z > maxz)
|
|
{
|
|
maxZ[0] = i;
|
|
maxZ[1] = 1;
|
|
maxz = tdtrilist[i]->v[1].z;
|
|
}
|
|
x = (int)(tdtrilist[i]->v[1].x/dX);
|
|
z = (int)(tdtrilist[i]->v[1].z/dZ);
|
|
vert_id[x + X*z]++;
|
|
if(vert_id[x + X*z]==1)
|
|
{
|
|
center0 += tdtrilist[i]->v[2];
|
|
point_count++;
|
|
}
|
|
}
|
|
|
|
center0 *= 1.0f/point_count;
|
|
center0.x = GetX(center0.x);
|
|
center0.y += Offset;
|
|
center0.z = GetZ(center0.z);
|
|
|
|
center3 *= 1.0f/polygon_count;
|
|
center3.x = GetX(center3.x);
|
|
center3.y += Offset;
|
|
center3.z = GetZ(center3.z);
|
|
|
|
Vector3D v3;
|
|
Scalar d[3];
|
|
|
|
v3.Subtract(tdtrilist[maxX[0]]->v[maxX[1]], tdtrilist[minX[0]]->v[minX[1]]);
|
|
d[0] = v3.GetLengthSquared();
|
|
|
|
v3.Subtract(tdtrilist[maxY[0]]->v[maxY[1]], tdtrilist[minY[0]]->v[minY[1]]);
|
|
d[1] = v3.GetLengthSquared();
|
|
|
|
v3.Subtract(tdtrilist[maxZ[0]]->v[maxZ[1]], tdtrilist[minZ[0]]->v[minZ[1]]);
|
|
d[2] = v3.GetLengthSquared();
|
|
|
|
if(d[0] > d[1])
|
|
{
|
|
if(d[0]>d[2])
|
|
{
|
|
center1 = tdtrilist[maxX[0]]->v[maxX[1]];
|
|
center1 += tdtrilist[minX[0]]->v[minX[1]];
|
|
center1 *= 0.5f;
|
|
}
|
|
else
|
|
{
|
|
center1 = tdtrilist[maxZ[0]]->v[maxZ[1]];
|
|
center1 += tdtrilist[minZ[0]]->v[minZ[1]];
|
|
center1 *= 0.5f;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(d[1]>d[2])
|
|
{
|
|
center1 = tdtrilist[maxY[0]]->v[maxY[1]];
|
|
center1 += tdtrilist[minY[0]]->v[minY[1]];
|
|
center1 *= 0.5f;
|
|
}
|
|
else
|
|
{
|
|
center1 = tdtrilist[maxZ[0]]->v[maxZ[1]];
|
|
center1 += tdtrilist[minZ[0]]->v[minZ[1]];
|
|
center1 *= 0.5f;
|
|
}
|
|
}
|
|
|
|
center1.x = GetX(center1.x);
|
|
center1.y += Offset;
|
|
center1.z = GetZ(center1.z);
|
|
|
|
center2.x = GetX((maxx+minx)*0.5f);
|
|
center2.y = (maxy+miny)*0.5f;
|
|
center2.z = GetZ((maxz+minz)*0.5f);
|
|
|
|
center2.y += Offset;
|
|
|
|
Point3D *coords = new Point3D [point_count];
|
|
Vector2DScalar *texCoords = new Vector2DScalar[point_count];
|
|
|
|
UnitVector3D sun;
|
|
sun = Vector3D(-1.0f, -1.0f, 0.0f);
|
|
|
|
int nrOfPoints = 0;
|
|
Scalar radiusSquared,
|
|
maxRadius0 = 0.0f,
|
|
maxRadius1 = 0.0f,
|
|
maxRadius2 = 0.0f,
|
|
maxRadius3 = 0.0f;
|
|
|
|
for(z=0;z<Z;z++)
|
|
for(x=0;x<X;x++)
|
|
{
|
|
if( vert_id[x + X*z] > 0 )
|
|
{
|
|
Verify(nrOfPoints<point_count);
|
|
vert_id[z*X+x] = nrOfPoints;
|
|
|
|
Verify(GetX(x)<=uvFrame->maxX && GetX(x)>=uvFrame->minX);
|
|
Verify(GetZ(z)<=uvFrame->maxZ && GetZ(z)>=uvFrame->minZ);
|
|
|
|
coords[nrOfPoints].x = GetX(x);
|
|
coords[nrOfPoints].y = GetHeight(x, z);
|
|
coords[nrOfPoints].z = GetZ(z);
|
|
|
|
v3.Subtract(coords[nrOfPoints], center0);
|
|
|
|
radiusSquared = v3.GetLengthSquared();
|
|
maxRadius0 = radiusSquared>maxRadius0 ? radiusSquared:maxRadius0;
|
|
|
|
v3.Subtract(coords[nrOfPoints], center1);
|
|
|
|
radiusSquared = v3.GetLengthSquared();
|
|
maxRadius1 = radiusSquared>maxRadius1 ? radiusSquared:maxRadius1;
|
|
|
|
v3.Subtract(coords[nrOfPoints], center2);
|
|
|
|
radiusSquared = v3.GetLengthSquared();
|
|
maxRadius2 = radiusSquared>maxRadius2 ? radiusSquared:maxRadius2;
|
|
|
|
v3.Subtract(coords[nrOfPoints], center3);
|
|
|
|
radiusSquared = v3.GetLengthSquared();
|
|
maxRadius3 = radiusSquared>maxRadius3 ? radiusSquared:maxRadius3;
|
|
|
|
#ifndef TERRAIN2_TEST
|
|
texCoords[nrOfPoints][0] =
|
|
borderPixelFun + (1.0f-2*borderPixelFun)*((uvFrame->maxX - coords[nrOfPoints].x)/(uvFrame->maxX-uvFrame->minX));
|
|
texCoords[nrOfPoints][1] =
|
|
borderPixelFun + (1.0f-2*borderPixelFun)*((uvFrame->maxZ - coords[nrOfPoints].z)/(uvFrame->maxZ-uvFrame->minZ));
|
|
#endif
|
|
nrOfPoints++;
|
|
}
|
|
else
|
|
vert_id[z*X+x] = -1;
|
|
}
|
|
|
|
maxRadius0 = static_cast<Scalar>(sqrt(maxRadius0));
|
|
maxRadius1 = static_cast<Scalar>(sqrt(maxRadius1));
|
|
maxRadius2 = static_cast<Scalar>(sqrt(maxRadius2));
|
|
maxRadius3 = static_cast<Scalar>(sqrt(maxRadius3));
|
|
|
|
if(maxRadius0<maxRadius1)
|
|
{
|
|
if(maxRadius0<maxRadius2)
|
|
{
|
|
if(maxRadius0<maxRadius3)
|
|
{
|
|
maxRadius = maxRadius0;
|
|
center = center0;
|
|
}
|
|
else
|
|
{
|
|
maxRadius = maxRadius3;
|
|
center = center3;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(maxRadius2<maxRadius3)
|
|
{
|
|
maxRadius = maxRadius2;
|
|
center = center2;
|
|
}
|
|
else
|
|
{
|
|
maxRadius = maxRadius3;
|
|
center = center3;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(maxRadius1<maxRadius2)
|
|
{
|
|
if(maxRadius1<maxRadius3)
|
|
{
|
|
maxRadius = maxRadius1;
|
|
center = center1;
|
|
}
|
|
else
|
|
{
|
|
maxRadius = maxRadius3;
|
|
center = center3;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(maxRadius2<maxRadius3)
|
|
{
|
|
maxRadius = maxRadius2;
|
|
center = center2;
|
|
}
|
|
else
|
|
{
|
|
maxRadius = maxRadius3;
|
|
center = center3;
|
|
}
|
|
}
|
|
}
|
|
|
|
unsigned short *index = new unsigned short [polygon_count*3];
|
|
|
|
int k, l;
|
|
|
|
for(i=0,l=0;i<polygon_count;i++)
|
|
{
|
|
k = 0;
|
|
|
|
x = (int)(tdtrilist[i]->v[0].x/dX);
|
|
z = (int)(tdtrilist[i]->v[0].z/dZ);
|
|
j = x + X*z;
|
|
Verify(vert_id[j]>=0);
|
|
index[l++] = vert_id[j];
|
|
|
|
if(z==Z-1)
|
|
k++;
|
|
|
|
x = (int)(tdtrilist[i]->v[2].x/dX);
|
|
z = (int)(tdtrilist[i]->v[2].z/dZ);
|
|
j = x + X*z;
|
|
Verify(vert_id[j]>=0);
|
|
index[l++] = vert_id[j];
|
|
if(z==Z-1)
|
|
k++;
|
|
|
|
x = (int)(tdtrilist[i]->v[1].x/dX);
|
|
z = (int)(tdtrilist[i]->v[1].z/dZ);
|
|
j = x + X*z;
|
|
Verify(vert_id[j]>=0);
|
|
index[l++] = vert_id[j];
|
|
if(z==Z-1)
|
|
k++;
|
|
|
|
if(k>=2)
|
|
{
|
|
j = 0;
|
|
}
|
|
|
|
if(
|
|
index[l-3]==index[l-2] ||
|
|
index[l-2]==index[l-1] ||
|
|
index[l-1]==index[l-3]
|
|
)
|
|
{
|
|
l-=3;
|
|
continue;
|
|
}
|
|
|
|
Vector3D vCross;
|
|
vCross.Cross(
|
|
coords[index[l-1]],
|
|
coords[index[l-2]],
|
|
coords[index[l-3]]
|
|
);
|
|
|
|
if(Small_Enough(vCross) || vCross.y<=SMALL)
|
|
{
|
|
l-=3;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
gos_PushCurrentHeap(MidLevelRenderer::Heap);
|
|
erf_mesh->SetSubprimitiveLengths(NULL, l/3);
|
|
|
|
#ifdef _ARMOR
|
|
for(i=0;i<nrOfPoints;i++)
|
|
{
|
|
for(j=0;j<8;j++)
|
|
{
|
|
Verify(coords[i].x>=erf_mesh->GetFrame(j, 0) && coords[i].x<=erf_mesh->GetFrame(j, 2) );
|
|
Verify(coords[i].z>=erf_mesh->GetFrame(j, 1) && coords[i].z<=erf_mesh->GetFrame(j, 3) );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
erf_mesh->SetCoordData(coords, nrOfPoints);
|
|
|
|
#ifdef TERRAIN2_TEST
|
|
erf_mesh->SetFrame(0, xOffset, zOffset, xOffset+8*xGridSize, zOffset+8*zGridSize);
|
|
erf_mesh->SetCurrentDepth(0);
|
|
#else
|
|
erf_mesh->SetTexCoordData(texCoords, nrOfPoints);
|
|
#endif
|
|
|
|
erf_mesh->SetIndexData(index, l);
|
|
gos_PopCurrentHeap();
|
|
erf_mesh->FindFacePlanes();
|
|
|
|
delete [] coords;
|
|
delete [] texCoords;
|
|
delete [] index;
|
|
|
|
|
|
return true;
|
|
}
|
|
|
|
int
|
|
primCounter, maxPrims;
|
|
|
|
void
|
|
HFSlimMZ0p3::OptimizeHField(int depth, int binSize)
|
|
{
|
|
if(X*Z == 0)
|
|
{
|
|
return;
|
|
}
|
|
fprintf(stdout, "Going to optimize the terrain: MaxNr.Of Points: %d BinSize: %d\n", depth, binSize);
|
|
|
|
tdtrilist.SetLength((X-1)*(Z-1));
|
|
DirectMap<real> map(X,Z);
|
|
|
|
int i, j;
|
|
|
|
float maxY = 0;
|
|
for(j=0;j<Z;j++)
|
|
for(i=0;i<X;i++)
|
|
{
|
|
map.ref(i,j) = field[j*X + i];
|
|
}
|
|
Offset = 0.0;
|
|
|
|
MASK = new ImportMask;
|
|
MASK->width=X;
|
|
MASK->height=Z;
|
|
|
|
GreedySubdivision mesh(&map);
|
|
point_limit=1024;
|
|
|
|
point_limit = depth;
|
|
|
|
triangleCounter = 0;
|
|
int count=1;
|
|
while(mesh.pointCount()<point_limit && mesh.maxError() > error_threshold)
|
|
{
|
|
mesh.greedyInsert();
|
|
}
|
|
fprintf(stdout, "The mesh was greedy.\n");
|
|
|
|
mesh.overFaces(GetFacesCB, tdtrilist.GetData());
|
|
for(i=0;i<triangleCounter;i++)
|
|
{
|
|
tdtrilist[i].v[0].y = Offset + static_cast<float>(dY*mesh.eval(
|
|
(int)(tdtrilist[i].v[0].x),
|
|
(int)(tdtrilist[i].v[0].z)
|
|
));
|
|
|
|
tdtrilist[i].v[1].y = Offset + static_cast<float>(dY*mesh.eval(
|
|
(int)(tdtrilist[i].v[1].x),
|
|
(int)(tdtrilist[i].v[1].z)
|
|
));
|
|
|
|
tdtrilist[i].v[2].y = Offset + static_cast<float>(dY*mesh.eval(
|
|
(int)(tdtrilist[i].v[2].x),
|
|
(int)(tdtrilist[i].v[2].z)
|
|
));
|
|
|
|
tdtrilist[i].v[0].x *= dX;
|
|
tdtrilist[i].v[0].z *= dZ;
|
|
|
|
tdtrilist[i].v[1].x *= dX;
|
|
tdtrilist[i].v[1].z *= dZ;
|
|
|
|
tdtrilist[i].v[2].x *= dX;
|
|
tdtrilist[i].v[2].z *= dZ;
|
|
|
|
tdtrilist[i].GetSurfaceAreaAndCentroid();
|
|
}
|
|
|
|
OptPolyCount = triangleCounter;
|
|
|
|
if(triangleCounter == 0 || mesh.pointCount() == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
toSortTriangles.SetLength(triangleCounter);
|
|
|
|
for(i=0,j=0;i<triangleCounter;++i)
|
|
{
|
|
if(! (tdtrilist[i].plane.normal.y > Stuff::SMALL) )
|
|
{
|
|
STOP(("Danger Danger !"));
|
|
}
|
|
|
|
/*
|
|
if( !(tdtrilist[i].GetV0().x==0.0f && tdtrilist[i].GetV0().z==GetZinM()) &&
|
|
!(tdtrilist[i].GetV1().x==0.0f && tdtrilist[i].GetV1().z==GetZinM()) &&
|
|
!(tdtrilist[i].GetV2().x==0.0f && tdtrilist[i].GetV2().z==GetZinM())
|
|
)
|
|
*/
|
|
{
|
|
toSortTriangles[j++] = &tdtrilist[i];
|
|
}
|
|
}
|
|
toSortTriangles.SetLength(j);
|
|
|
|
fprintf(stdout, "optimized to %d triangles.\n", j);
|
|
}
|
|
|
|
int brokenTriangles;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
AnalyzeThis(
|
|
DynamicArrayOf<ToDrawTriangle*> &tempTrianglesPtr,
|
|
Scalar x0,
|
|
Scalar z0,
|
|
Scalar x1,
|
|
Scalar z1
|
|
)
|
|
{
|
|
int i, j, k, l, len = tempTrianglesPtr.GetLength();
|
|
int divide = 2;
|
|
Scalar x0n, z0n, x1n, z1n;
|
|
|
|
fprintf(analyzeFile, "%d ", len);
|
|
|
|
int in, out;
|
|
|
|
for(i=0;i<divide;i++)
|
|
{
|
|
for(j=0;j<divide;j++)
|
|
{
|
|
x0n = x0 + j*(x1-x0)/divide;
|
|
x1n = x0 + (j+1)*(x1-x0)/divide;
|
|
z0n = z0 + i*(z1-z0)/divide;
|
|
z1n = z0 + (i+1)*(z1-z0)/divide;
|
|
|
|
in = 0;
|
|
out = 0;
|
|
for(k=0;k<len;k++)
|
|
{
|
|
l = 0;
|
|
if( tempTrianglesPtr[k]->GetV0().x >= x0n && tempTrianglesPtr[k]->GetV0().x <= x1n &&
|
|
tempTrianglesPtr[k]->GetV0().z >= z0n && tempTrianglesPtr[k]->GetV0().z < z1n
|
|
)
|
|
{
|
|
l++;
|
|
}
|
|
if( tempTrianglesPtr[k]->GetV1().x >= x0n && tempTrianglesPtr[k]->GetV1().x <= x1n &&
|
|
tempTrianglesPtr[k]->GetV1().z >= z0n && tempTrianglesPtr[k]->GetV1().z <= z1n
|
|
)
|
|
{
|
|
l++;
|
|
}
|
|
if( tempTrianglesPtr[k]->GetV2().x >= x0n && tempTrianglesPtr[k]->GetV2().x <= x1n &&
|
|
tempTrianglesPtr[k]->GetV2().z >= z0n && tempTrianglesPtr[k]->GetV2().z <= z1n
|
|
)
|
|
{
|
|
l++;
|
|
}
|
|
|
|
if(l==3)
|
|
{
|
|
in++;
|
|
}
|
|
else if(l>0)
|
|
{
|
|
if( tempTrianglesPtr[k]->center.x >= x0n && tempTrianglesPtr[k]->center.x <= x1n &&
|
|
tempTrianglesPtr[k]->center.z >= z0n && tempTrianglesPtr[k]->center.z <= z1n
|
|
)
|
|
{
|
|
out++;
|
|
}
|
|
}
|
|
}
|
|
|
|
fprintf(analyzeFile, "%d %d ", in, out);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
fprintf(analyzeFile, "\n");
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool
|
|
HFSlimMZ0p3::BuildTile(
|
|
MLR_Terrain2 *erf_mesh,
|
|
DynamicArrayOf<unsigned char>& onOffPoints,
|
|
int maxNumOfTrianglesPerMesh,
|
|
Scalar x0,
|
|
Scalar z0,
|
|
Scalar x1,
|
|
Scalar z1
|
|
)
|
|
{
|
|
int numOfTriangles = toSortTriangles.GetLength();
|
|
|
|
DynamicArrayOf<ToDrawTriangle*> tempTrianglesPtr(numOfTriangles);
|
|
DynamicArrayOf<ToDrawTriangle> tempTriangles(numOfTriangles);
|
|
|
|
int i, j, inCount, newCount = 0, extraTriangles = 0;
|
|
int k, l, m;
|
|
|
|
for(i=0,j=0;i<numOfTriangles;j+=3,++i)
|
|
{
|
|
Verify(i<numOfTriangles);
|
|
Verify(j<3*numOfTriangles);
|
|
if(onOffPoints[i] == 0)
|
|
{
|
|
inCount = 0;
|
|
int clipIt[3] = {0, 0, 0}, orIt = 0, addIt = 0xf;
|
|
|
|
if(toSortTriangles[i]->GetV0().x < x0)
|
|
{
|
|
clipIt[0] |= 1;
|
|
}
|
|
if(toSortTriangles[i]->GetV0().x > x1)
|
|
{
|
|
clipIt[0] |= 4;
|
|
}
|
|
if(toSortTriangles[i]->GetV0().z < z0)
|
|
{
|
|
clipIt[0] |= 8;
|
|
}
|
|
if(toSortTriangles[i]->GetV0().z > z1)
|
|
{
|
|
clipIt[0] |= 2;
|
|
}
|
|
|
|
orIt |= clipIt[0];
|
|
addIt &= clipIt[0];
|
|
|
|
if(toSortTriangles[i]->GetV1().x < x0)
|
|
{
|
|
clipIt[1] |= 1;
|
|
}
|
|
if(toSortTriangles[i]->GetV1().x > x1)
|
|
{
|
|
clipIt[1] |= 4;
|
|
}
|
|
if(toSortTriangles[i]->GetV1().z < z0)
|
|
{
|
|
clipIt[1] |= 8;
|
|
}
|
|
if(toSortTriangles[i]->GetV1().z > z1)
|
|
{
|
|
clipIt[1] |= 2;
|
|
}
|
|
|
|
orIt |= clipIt[1];
|
|
addIt &= clipIt[1];
|
|
|
|
if(toSortTriangles[i]->GetV2().x < x0)
|
|
{
|
|
clipIt[2] |= 1;
|
|
}
|
|
if(toSortTriangles[i]->GetV2().x > x1)
|
|
{
|
|
clipIt[2] |= 4;
|
|
}
|
|
if(toSortTriangles[i]->GetV2().z < z0)
|
|
{
|
|
clipIt[2] |= 8;
|
|
}
|
|
if(toSortTriangles[i]->GetV2().z > z1)
|
|
{
|
|
clipIt[2] |= 2;
|
|
}
|
|
|
|
orIt |= clipIt[2];
|
|
addIt &= clipIt[2];
|
|
|
|
if(orIt == 0)
|
|
{
|
|
onOffPoints[i] = 1;
|
|
|
|
if(toSortTriangles[i]->area > SMALL)
|
|
{
|
|
if(! (toSortTriangles[i]->plane.normal.y > Stuff::SMALL) )
|
|
{
|
|
STOP(("Danger Danger !"));
|
|
}
|
|
tempTrianglesPtr[newCount++] = toSortTriangles[i];
|
|
}
|
|
}
|
|
else if(addIt==0)
|
|
{
|
|
if(orIt==1 || orIt==2 || orIt==4 || orIt==8)
|
|
{
|
|
Point3D triangle[3], clipPoints[6];
|
|
|
|
triangle[0].x = toSortTriangles[i]->GetV0().x;
|
|
triangle[0].y = toSortTriangles[i]->GetV0().y;
|
|
triangle[0].z = toSortTriangles[i]->GetV0().z;
|
|
|
|
triangle[1].x = toSortTriangles[i]->GetV1().x;
|
|
triangle[1].y = toSortTriangles[i]->GetV1().y;
|
|
triangle[1].z = toSortTriangles[i]->GetV1().z;
|
|
|
|
triangle[2].x = toSortTriangles[i]->GetV2().x;
|
|
triangle[2].y = toSortTriangles[i]->GetV2().y;
|
|
triangle[2].z = toSortTriangles[i]->GetV2().z;
|
|
|
|
l = 0;
|
|
for(k=0;k<3;k++)
|
|
{
|
|
int next = k+1>2?0:k+1;
|
|
if(clipIt[k]==0)
|
|
{
|
|
clipPoints[l++] = triangle[k];
|
|
if(clipIt[next]==0)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(clipIt[next]!=0)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
//
|
|
//-----------------------------------------------------
|
|
// Find the boundary conditions that match our clipping
|
|
// plane
|
|
//-----------------------------------------------------
|
|
//
|
|
int mask = 1;
|
|
for (m=0; m<4; m++)
|
|
{
|
|
if((clipIt[k] | clipIt[next]) & mask)
|
|
{
|
|
switch(m)
|
|
{
|
|
case 0:
|
|
clipPoints[l].AddScaled(
|
|
triangle[k],
|
|
Vector3D(
|
|
triangle[next].x - triangle[k].x,
|
|
triangle[next].y - triangle[k].y,
|
|
triangle[next].z - triangle[k].z
|
|
),
|
|
(x0-triangle[k].x)/(triangle[next].x-triangle[k].x)
|
|
|
|
);
|
|
clipPoints[l++].x = x0;
|
|
break;
|
|
case 1:
|
|
clipPoints[l].AddScaled(
|
|
triangle[k],
|
|
Vector3D(
|
|
triangle[next].x - triangle[k].x,
|
|
triangle[next].y - triangle[k].y,
|
|
triangle[next].z - triangle[k].z
|
|
),
|
|
(z1-triangle[k].z)/(triangle[next].z-triangle[k].z)
|
|
);
|
|
clipPoints[l++].z = z1;
|
|
break;
|
|
case 2:
|
|
clipPoints[l].AddScaled(
|
|
triangle[k],
|
|
Vector3D(
|
|
triangle[next].x - triangle[k].x,
|
|
triangle[next].y - triangle[k].y,
|
|
triangle[next].z - triangle[k].z
|
|
),
|
|
(x1-triangle[k].x)/(triangle[next].x-triangle[k].x)
|
|
);
|
|
clipPoints[l++].x = x1;
|
|
break;
|
|
case 3:
|
|
clipPoints[l].AddScaled(
|
|
triangle[k],
|
|
Vector3D(
|
|
triangle[next].x - triangle[k].x,
|
|
triangle[next].y - triangle[k].y,
|
|
triangle[next].z - triangle[k].z
|
|
),
|
|
(z0-triangle[k].z)/(triangle[next].z-triangle[k].z)
|
|
);
|
|
clipPoints[l++].z = z0;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
mask <<= 1;
|
|
}
|
|
}
|
|
Verify(l>2);
|
|
for(m=1;m<l-1;m++)
|
|
{
|
|
tempTriangles[extraTriangles].SetPoint(0, clipPoints[0].x, clipPoints[0].y, clipPoints[0].z);
|
|
tempTriangles[extraTriangles].SetPoint(1, clipPoints[m].x, clipPoints[m].y, clipPoints[m].z);
|
|
tempTriangles[extraTriangles].SetPoint(2, clipPoints[m+1].x, clipPoints[m+1].y, clipPoints[m+1].z);
|
|
|
|
tempTriangles[extraTriangles].GetSurfaceAreaAndCentroid();
|
|
|
|
if(tempTriangles[extraTriangles].area > SMALL)
|
|
{
|
|
if(! (tempTriangles[extraTriangles].plane.normal.y > Stuff::SMALL) )
|
|
{
|
|
STOP(("Danger Danger !"));
|
|
}
|
|
|
|
tempTrianglesPtr[newCount++] = &tempTriangles[extraTriangles];
|
|
extraTriangles++;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
int key=0, len[2] = {0, 0};
|
|
Point3D clipPoints[2][6];
|
|
int clipMeToo[2][6];
|
|
|
|
clipPoints[key][0].x = toSortTriangles[i]->GetV0().x;
|
|
clipPoints[key][0].y = toSortTriangles[i]->GetV0().y;
|
|
clipPoints[key][0].z = toSortTriangles[i]->GetV0().z;
|
|
|
|
clipPoints[key][1].x = toSortTriangles[i]->GetV1().x;
|
|
clipPoints[key][1].y = toSortTriangles[i]->GetV1().y;
|
|
clipPoints[key][1].z = toSortTriangles[i]->GetV1().z;
|
|
|
|
clipPoints[key][2].x = toSortTriangles[i]->GetV2().x;
|
|
clipPoints[key][2].y = toSortTriangles[i]->GetV2().y;
|
|
clipPoints[key][2].z = toSortTriangles[i]->GetV2().z;
|
|
|
|
clipMeToo[key][0] = clipIt[0];
|
|
clipMeToo[key][1] = clipIt[1];
|
|
clipMeToo[key][2] = clipIt[2];
|
|
|
|
len[key] = 3;
|
|
|
|
int next, mask = 1;
|
|
for(m=0;m<4;++m)
|
|
{
|
|
if(orIt & mask)
|
|
{
|
|
for(k=0;k<len[key];k++)
|
|
{
|
|
next = (k+1) < len[key] ? k+1 : 0;
|
|
|
|
if(!(clipMeToo[key][k] & mask))
|
|
{
|
|
clipPoints[!key][len[!key]++] = clipPoints[key][k];
|
|
if(!(clipMeToo[key][next] & mask))
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(clipMeToo[key][next] & mask)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
switch(m)
|
|
{
|
|
case 0:
|
|
clipPoints[!key][len[!key]].AddScaled(
|
|
clipPoints[key][k],
|
|
Vector3D(
|
|
clipPoints[key][next].x - clipPoints[key][k].x,
|
|
clipPoints[key][next].y - clipPoints[key][k].y,
|
|
clipPoints[key][next].z - clipPoints[key][k].z
|
|
),
|
|
(x0-clipPoints[key][k].x)/(clipPoints[key][next].x-clipPoints[key][k].x)
|
|
);
|
|
clipPoints[!key][len[!key]++].x = x0;
|
|
break;
|
|
case 1:
|
|
clipPoints[!key][len[!key]].AddScaled(
|
|
clipPoints[key][k],
|
|
Vector3D(
|
|
clipPoints[key][next].x - clipPoints[key][k].x,
|
|
clipPoints[key][next].y - clipPoints[key][k].y,
|
|
clipPoints[key][next].z - clipPoints[key][k].z
|
|
),
|
|
(z1-clipPoints[key][k].z)/(clipPoints[key][next].z-clipPoints[key][k].z)
|
|
);
|
|
clipPoints[!key][len[!key]++].z = z1;
|
|
break;
|
|
case 2:
|
|
clipPoints[!key][len[!key]].AddScaled(
|
|
clipPoints[key][k],
|
|
Vector3D(
|
|
clipPoints[key][next].x - clipPoints[key][k].x,
|
|
clipPoints[key][next].y - clipPoints[key][k].y,
|
|
clipPoints[key][next].z - clipPoints[key][k].z
|
|
),
|
|
(x1-clipPoints[key][k].x)/(clipPoints[key][next].x-clipPoints[key][k].x)
|
|
);
|
|
clipPoints[!key][len[!key]++].x = x1;
|
|
break;
|
|
case 3:
|
|
clipPoints[!key][len[!key]].AddScaled(
|
|
clipPoints[key][k],
|
|
Vector3D(
|
|
clipPoints[key][next].x - clipPoints[key][k].x,
|
|
clipPoints[key][next].y - clipPoints[key][k].y,
|
|
clipPoints[key][next].z - clipPoints[key][k].z
|
|
),
|
|
(z0-clipPoints[key][k].z)/(clipPoints[key][next].z-clipPoints[key][k].z)
|
|
);
|
|
clipPoints[!key][len[!key]++].z = z0;
|
|
break;
|
|
}
|
|
}
|
|
key = !key;
|
|
for(k=0;k<len[key];k++)
|
|
{
|
|
clipMeToo[key][k] = 0;
|
|
if(clipPoints[key][k].x < x0)
|
|
{
|
|
clipMeToo[key][k] |= 1;
|
|
}
|
|
if(clipPoints[key][k].x > x1)
|
|
{
|
|
clipMeToo[key][k] |= 4;
|
|
}
|
|
if(clipPoints[key][k].z < z0)
|
|
{
|
|
clipMeToo[key][k] |= 8;
|
|
}
|
|
if(clipPoints[key][k].z > z1)
|
|
{
|
|
clipMeToo[key][k] |= 2;
|
|
}
|
|
}
|
|
len[!key] = 0;
|
|
}
|
|
mask <<= 1;
|
|
}
|
|
|
|
for(m=1;m<len[key]-1;m++)
|
|
{
|
|
tempTriangles[extraTriangles].SetPoint(0,
|
|
clipPoints[key][0].x,
|
|
clipPoints[key][0].y,
|
|
clipPoints[key][0].z
|
|
);
|
|
tempTriangles[extraTriangles].SetPoint(1,
|
|
clipPoints[key][m].x,
|
|
clipPoints[key][m].y,
|
|
clipPoints[key][m].z
|
|
);
|
|
tempTriangles[extraTriangles].SetPoint(2,
|
|
clipPoints[key][m+1].x,
|
|
clipPoints[key][m+1].y,
|
|
clipPoints[key][m+1].z
|
|
);
|
|
|
|
tempTriangles[extraTriangles].GetSurfaceAreaAndCentroid();
|
|
|
|
|
|
if(tempTriangles[extraTriangles].area > SMALL)
|
|
{
|
|
if(! (tempTriangles[extraTriangles].plane.normal.y > Stuff::SMALL) )
|
|
{
|
|
STOP(("Danger Danger !"));
|
|
}
|
|
tempTrianglesPtr[newCount++] = &tempTriangles[extraTriangles];
|
|
extraTriangles++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// tempTriangles.SetLength(extraTriangles);
|
|
tempTrianglesPtr.SetLength(newCount);
|
|
|
|
#if _ARMOR
|
|
for(i=0,j=0;i<newCount;++i)
|
|
{
|
|
if(onOffPoints[i] == 0)
|
|
{
|
|
Verify(tempTrianglesPtr[i]->GetV0().x >= x0);
|
|
Verify(tempTrianglesPtr[i]->GetV0().x <= x1);
|
|
Verify(tempTrianglesPtr[i]->GetV0().z >= z0);
|
|
Verify(tempTrianglesPtr[i]->GetV0().z <= z1);
|
|
|
|
Verify(tempTrianglesPtr[i]->GetV1().x >= x0);
|
|
Verify(tempTrianglesPtr[i]->GetV1().x <= x1);
|
|
Verify(tempTrianglesPtr[i]->GetV1().z >= z0);
|
|
Verify(tempTrianglesPtr[i]->GetV1().z <= z1);
|
|
|
|
Verify(tempTrianglesPtr[i]->GetV2().x >= x0);
|
|
Verify(tempTrianglesPtr[i]->GetV2().x <= x1);
|
|
Verify(tempTrianglesPtr[i]->GetV2().z >= z0);
|
|
Verify(tempTrianglesPtr[i]->GetV2().z <= z1);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
MLR_Terrain2 *ret_mesh = NULL;
|
|
|
|
if(newCount > 0)
|
|
{
|
|
AnalyzeThis(
|
|
tempTrianglesPtr,
|
|
x0,
|
|
z0,
|
|
x1,
|
|
z1
|
|
);
|
|
|
|
Stuff::ExtentBox box;
|
|
box.minX = x0;
|
|
box.maxX = x1;
|
|
box.minY = Offset;
|
|
box.maxY = Offset+256.0f;
|
|
box.minZ = z0;
|
|
box.maxZ = z1;
|
|
|
|
if(!CreateMesh(erf_mesh, tempTrianglesPtr, &box))
|
|
{
|
|
PAUSE(("Unstable triangle mesh created!"));
|
|
}
|
|
else
|
|
{
|
|
brokenTriangles += newCount;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
STOP(("Danger Danger !"));
|
|
}
|
|
|
|
tempTrianglesPtr.SetLength(0);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool
|
|
HFSlimMZ0p3::SetMegaTexture(
|
|
int nrOfLevels,
|
|
int bucketSize,
|
|
const char *theName
|
|
)
|
|
{
|
|
static char megaBaseName[1024];
|
|
|
|
|
|
if(detailInfo.name)
|
|
{
|
|
/*
|
|
state1.SetBackFaceOn();
|
|
state1.SetDitherOff();
|
|
state1.SetTextureCorrectionOn();
|
|
state1.SetZBufferCompareOn();
|
|
state1.SetZBufferWriteOff();
|
|
|
|
|
|
state1.SetFilterMode(MLRState::BiLinearFilterMode);
|
|
|
|
state1.SetFogMode(MLRState::DisableFogMode);
|
|
state1.SetFogData(
|
|
0xff000000,
|
|
0.0f,
|
|
90.0f,
|
|
100.0f
|
|
);
|
|
*/
|
|
state1.SetTextureWrapMode(MLRState::TextureWrap);
|
|
state1.SetAlphaMode(detailInfo.alphaMode);
|
|
state1.SetPriority(MLRState::AlphaPriority);
|
|
MLRTexture *texture = MLRTexturePool::Instance->Add(detailInfo.name);
|
|
state1.SetTextureHandle(texture->GetTextureHandle());
|
|
}
|
|
|
|
DynamicArrayOf<unsigned char> onOffTriangles;
|
|
onOffTriangles.AssignValue(0, toSortTriangles.GetLength());
|
|
|
|
int i, j, k, l, m, n;
|
|
simpleTerrainGroup.SetLength(xDim*zDim);
|
|
|
|
Stuff::ExtentBox allBox;
|
|
allBox = GetExtents();
|
|
|
|
int len = 1<<nrOfLevels;
|
|
|
|
xGridSize = (allBox.maxX-allBox.minX)/(len*xDim);
|
|
zGridSize = (allBox.maxZ-allBox.minZ)/(len*zDim);
|
|
|
|
for(l=0;l<zDim;l++)
|
|
{
|
|
for(k=0;k<xDim;k++)
|
|
{
|
|
brokenTriangles = 0;
|
|
|
|
sprintf(megaBaseName, "Maps\\%s\\%c%c\\%s_%c%c", theName, 'A'+l, 'A'+k, theName, 'A'+l, 'A'+k);
|
|
|
|
xOffset = k*dX*256;
|
|
zOffset = l*dZ*256;
|
|
gos_PushCurrentHeap(ElementRenderer::Heap);
|
|
simpleTerrainGroup[l*xDim+k] = new GridElement(len, len, zOffset, xOffset, dZ*256, dX*256);
|
|
Register_Object(simpleTerrainGroup[l*xDim+k]);
|
|
simpleTerrainGroup[l*xDim+k]->SetName("OptimizedTerrain");
|
|
gos_PopCurrentHeap();
|
|
|
|
|
|
for(j=0;j<len;j++)
|
|
{
|
|
for(i=0;i<len;i++)
|
|
{
|
|
tX = i;
|
|
tY = j;
|
|
|
|
gos_PushCurrentHeap(ElementRenderer::Heap);
|
|
ElementRenderer::GroupElement *group = new GroupElement;
|
|
Register_Object(group);
|
|
|
|
simpleTerrainGroup[l*xDim+k]->AttachIndexedChild(j, i, group);
|
|
|
|
group->NeedNewBounds();
|
|
group->SetVolumeCullMode();
|
|
ElementRenderer::ListElement *subList = new ListElement;
|
|
Register_Object(subList);
|
|
subList->SetSize(4);
|
|
group->AttachChild(subList);
|
|
subList->NeedNewBounds();
|
|
subList->SetVolumeCullMode();
|
|
gos_PopCurrentHeap();
|
|
|
|
for(n=0;n<2;n++)
|
|
{
|
|
for(m=0;m<2;m++)
|
|
{
|
|
MLRState state;
|
|
|
|
|
|
/*
|
|
state.SetBackFaceOn();
|
|
state.SetDitherOff();
|
|
state.SetTextureCorrectionOn();
|
|
state.SetZBufferCompareOn();
|
|
state.SetZBufferWriteOn();
|
|
|
|
state.SetFilterMode(MLRState::BiLinearFilterMode);
|
|
|
|
state.SetFogMode(MLRState::OverrideFogMode);
|
|
state.SetFogData(
|
|
0xff9090f0,
|
|
0.0f,
|
|
700.0f,
|
|
1000.0f
|
|
);
|
|
*/
|
|
char textureName[1024];
|
|
|
|
state.SetPriority(MLRState::DefaultPriority);
|
|
|
|
#if 0
|
|
sprintf(textureName, "%s_%1d_%02x%02x",
|
|
megaBaseName,
|
|
depth,
|
|
(1<<depth) - tileX/(1<<(maxdepth-depth)) - 1,
|
|
(1<<depth) - tileZ/(1<<(maxdepth-depth)) - 1
|
|
);
|
|
#else
|
|
sprintf(textureName, "%s_0_0000", megaBaseName);
|
|
#endif
|
|
|
|
MLRTexture *texture = MLRTexturePool::Instance->Add(textureName);
|
|
texture->SetHint(gosHint_AGPMemory | gosHint_DontShrink);
|
|
state.SetTextureHandle(texture->GetTextureHandle());
|
|
state.SetTextureWrapMode(MLRState::TextureClamp);
|
|
|
|
gos_PushCurrentHeap(MidLevelRenderer::Heap);
|
|
MLR_Terrain2 *erf_mesh = new MLR_Terrain2;
|
|
gos_PopCurrentHeap();
|
|
|
|
erf_mesh->SetReferenceState(state);
|
|
erf_mesh->SetReferenceState(state1, 1);
|
|
|
|
erf_mesh->SetLevelTexture(0, texture->GetTextureHandle());
|
|
|
|
Scalar x0, z0, x1, z1;
|
|
|
|
if(i<len/2)
|
|
{
|
|
x0 = xOffset;
|
|
x1 = xOffset + (len/2)*xGridSize;
|
|
}
|
|
else
|
|
{
|
|
x0 = xOffset + (len/2)*xGridSize;
|
|
x1 = xOffset + len*xGridSize;
|
|
}
|
|
if(j<len/2)
|
|
{
|
|
z0 = zOffset;
|
|
z1 = zOffset + (len/2)*zGridSize;
|
|
}
|
|
else
|
|
{
|
|
z0 = zOffset + (len/2)*zGridSize;
|
|
z1 = zOffset + len*zGridSize;
|
|
}
|
|
erf_mesh->SetFrame(1, x0, z0, x1, z1);
|
|
|
|
x0 = xOffset + i*xGridSize;
|
|
z0 = zOffset + j*zGridSize;
|
|
x1 = x0 + xGridSize;
|
|
z1 = z0 + zGridSize;
|
|
|
|
erf_mesh->SetFrame(0, xOffset, zOffset, xOffset+len*xGridSize, zOffset+len*zGridSize);
|
|
|
|
erf_mesh->SetFrame(2, x0, z0, x1, z1);
|
|
erf_mesh->SetFrame(3, x0, z0, x1, z1);
|
|
erf_mesh->SetFrame(4, x0, z0, x1, z1);
|
|
erf_mesh->SetFrame(5, x0, z0, x1, z1);
|
|
erf_mesh->SetFrame(6, x0, z0, x1, z1);
|
|
erf_mesh->SetFrame(7, x0, z0, x1, z1);
|
|
|
|
erf_mesh->SetDepthData(maxAllDepth, maxAllDepth);
|
|
erf_mesh->SetTileData(tX, tY);
|
|
erf_mesh->SetBorderPixel(borderPixelFun);
|
|
|
|
Register_Object(erf_mesh);
|
|
|
|
erf_mesh->SetDetailData(
|
|
detailInfo.xOff,
|
|
detailInfo.zOff,
|
|
detailInfo.xFac,
|
|
detailInfo.zFac,
|
|
detailInfo.dStart,
|
|
detailInfo.dEnd
|
|
);
|
|
|
|
x0 = xOffset + i*xGridSize + m*xGridSize/2.0f;
|
|
z0 = zOffset + j*zGridSize + n*xGridSize/2.0f;
|
|
x1 = x0 + xGridSize/2.0f;
|
|
z1 = z0 + zGridSize/2.0f;
|
|
|
|
BuildTile(erf_mesh, onOffTriangles, bucketSize, x0, z0, x1, z1);
|
|
|
|
|
|
gos_PushCurrentHeap(ElementRenderer::Heap);
|
|
ShapeElement* Shape = new ShapeElement;
|
|
Register_Object(Shape);
|
|
gos_PopCurrentHeap();
|
|
|
|
gos_PushCurrentHeap(MidLevelRenderer::Heap);
|
|
MLRShape *shape = new MLRShape(1);
|
|
Register_Object(shape);
|
|
gos_PopCurrentHeap();
|
|
|
|
shape->Add(erf_mesh);
|
|
erf_mesh->DetachReference();
|
|
|
|
Shape->SetMLRShape(shape);
|
|
|
|
Shape->m_localOBB.localToParent = LinearMatrix4D::Identity;
|
|
Shape->m_localOBB.localToParent.BuildTranslation(center);
|
|
|
|
Shape->m_localOBB.sphereRadius = maxRadius;
|
|
subList->AttachIndexedChild(2*n+m, Shape);
|
|
Shape->SetVolumeCullMode();
|
|
|
|
|
|
}
|
|
}
|
|
|
|
group->Sync();
|
|
group->LockBounds();
|
|
group->SetNeverCullMode();
|
|
subList->LockBounds();
|
|
subList->SetNeverCullMode();
|
|
}
|
|
}
|
|
|
|
simpleTerrainGroup[l*xDim+k]->LockBounds();
|
|
|
|
|
|
fprintf(stdout, "\"broken\" triangles: %d\n", brokenTriangles);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Scalar
|
|
HFSlimMZ0p3::GetHeight(int x, int z)
|
|
{
|
|
if (x<0) x = 0;
|
|
if (x>GetX()-1)
|
|
{
|
|
x = GetX() - 1;
|
|
}
|
|
if (z<0) z = 0;
|
|
if (z>GetZ()-1)
|
|
{
|
|
z = GetZ() - 1;
|
|
}
|
|
return field[z*X + x]*dY + Offset;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void ToDrawTriangle::SetPoint(int idx,float x,float y,float z)
|
|
{
|
|
Verify(idx>=0 && idx<3);
|
|
|
|
v[idx].x=x;
|
|
v[idx].y=y;
|
|
v[idx].z=z;
|
|
}
|
|
|
|
|