Files
firestorm/Gameleap/code/mw4/Tools/TCTb/HFslim.cpp
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
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.
2026-06-24 21:28:16 -05:00

2358 lines
53 KiB
C++

#include <MLR\MLRHeaders.hpp>
#if !defined(HFSLIM_HPP)
#include "HFslim.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;
}
}
if(area > SMALL)
{
center *= (One_Over_Three/area);
}
else
{
center *= One_Over_Three;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
HFSlim::HFSlim()
{
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;
nrOfIZs = 0;
terrainGroup = new GroupElement();
Register_Object(terrainGroup);
fullTerrainGroup = NULL;
simpleTerrainGroup = NULL;
borderPixelFun = 0.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
HFSlim::~HFSlim()
{
if(fullTerrainGroup!=NULL)
{
Unregister_Object(fullTerrainGroup);
delete fullTerrainGroup;
fullTerrainGroup = NULL;
}
if(simpleTerrainGroup!=NULL)
{
Unregister_Object(simpleTerrainGroup);
delete simpleTerrainGroup;
simpleTerrainGroup = NULL;
}
Unregister_Object(terrainGroup);
delete terrainGroup;
terrainGroup = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Stuff::ExtentBox
HFSlim::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
HFSlim::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
HFSlim::FillFromImage(Image &image, int smooth)
{
X = image.GetWidth()+1;
Z = image.GetHeight()+1;
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
bool
HFSlim::CreateMesh(
ListElement *parent,
int listIndex,
int diffLevel,
DynamicArrayOf<ToDrawTriangle*>& tdtrilist,
ExtentBox *uvFrame,
MLRState *state
)
{
int polygon_count = tdtrilist.GetLength();
if(polygon_count==0 || polygon_count*3 >= Limits::Max_Number_Vertices_Per_Mesh)
{
return false;
}
#ifndef TERRAIN2_TEST
MLR_I_DeT_TMesh *erf_mesh = new MLR_I_DeT_TMesh;
#else
MLR_Terrain2 *erf_mesh = new MLR_Terrain2;
erf_mesh->SetOffset(0.0f, 0.0f);
erf_mesh->SetDepthData(maxAllDepth-diffLevel, maxAllDepth);
erf_mesh->SetTileData(tX, tY);
erf_mesh->SetGrid(xGridSize, zGridSize);
erf_mesh->SetBorderPixel(borderPixelFun);
#endif
Register_Object(erf_mesh);
erf_mesh->SetDetailData(
detailInfo.xOff,
detailInfo.zOff,
detailInfo.xFac*(1<<diffLevel),
detailInfo.zFac*(1<<diffLevel),
detailInfo.dStart,
detailInfo.dEnd
);
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;
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));
Point3D center;
Scalar maxRadius;
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))
{
l-=3;
continue;
}
}
erf_mesh->SetSubprimitiveLengths(NULL, l/3);
erf_mesh->SetCoordData(coords, nrOfPoints);
#ifdef TERRAIN2_TEST
erf_mesh->SetCurrentDepth(maxAllDepth-diffLevel);
#else
erf_mesh->SetTexCoordData(texCoords, nrOfPoints);
#endif
erf_mesh->SetIndexData(index, l);
erf_mesh->FindFacePlanes();
delete [] coords;
delete [] texCoords;
delete [] index;
if(state)
{
erf_mesh->SetReferenceState(*state);
}
else
{
erf_mesh->SetReferenceState(state0);
}
erf_mesh->SetReferenceState(state1, 1);
ShapeElement* Shape = new ShapeElement;
Register_Object(Shape);
MLRShape *shape = new MLRShape(1);
Register_Object(shape);
shape->Add(erf_mesh);
erf_mesh->DetachReference();
Shape->SetMLRShape(shape);
Shape->localOBB.localToParent = Stuff::LinearMatrix4D::Identity;
Shape->localOBB.localToParent.BuildTranslation(center);
Shape->localOBB.sphereRadius = maxRadius;
// Shape->SetVolumeCullMode();
Shape->SetRootMode();
parent->AttachIndexedChild(listIndex, Shape);
Shape->SetVolumeCullMode();
return true;
}
int
primCounter, maxPrims;
bool
HFSlim::BinSort(
ListElement *parent,
int index,
int levDiff,
DynamicArrayOf<ToDrawTriangle*>& tdtrilist,
int binSize,
ExtentBox *uvFrame,
MLRState *state
)
{
int polygon_count = tdtrilist.GetLength();
if (polygon_count==0)
{
return false;
}
//
//---------------------------------------------------------
// If the polygon mesh is already small enough, just return
//---------------------------------------------------------
//
if (polygon_count <= binSize)
{
return CreateMesh(parent, index, levDiff, tdtrilist, uvFrame, state);
}
DynamicArrayOf<Point3D> centroids(polygon_count);
unsigned i;
for (i=0; i<polygon_count; ++i)
{
centroids[i] = tdtrilist[i]->center;
}
//
//------------------------------------------------------------------------
// Calculate the dividing plane, and if none can be found, don't do nothin
//------------------------------------------------------------------------
//
Plane plane;
if (!plane.ComputeBestDividingPlane(centroids))
{
return CreateMesh(parent, index, levDiff, tdtrilist, uvFrame, state);
}
//
//-------------------------------------------------------------------------
// The mesh is too big, so we have to cut it up. Make a group proxy to
// hold the new mesh collection
//-------------------------------------------------------------------------
//
Check_Object(parent);
ListElement *group = new ListElement;
Register_Object(group);
group->SetSize(2);
//
//----------------------------------
// Set the position of the group
//----------------------------------
//
LinearMatrix4D m;
m = parent->GetLocalToParent();
parent->SetLocalToParent(LinearMatrix4D::Identity);
group->SetLocalToParent(m);
#if 0
const char *name;
if ((name=parent->GetName())!=NULL)
{
parent->SetName(NULL);
group->SetName(name);
}
#endif
DynamicArrayOf<ToDrawTriangle*>
group_a(polygon_count),
group_b(polygon_count);
unsigned
count_a = 0,
count_b = 0;
//
//------------------------------------------------------------------
// Sort each of the centroids against the plane into one of two bins
//------------------------------------------------------------------
//
for (i=0; i<polygon_count; ++i)
{
if (plane.DistanceTo(centroids[i]) < 0.0f)
group_b[count_b++] = tdtrilist[i];
else
group_a[count_a++] = tdtrilist[i];
}
//
//---------------------------------
// Now add the polygons to each bin
//---------------------------------
//
Verify(count_a>0);
group_a.SetLength(count_a);
// bin_a->AddPolygons(process, group_a);
Verify(count_b>0);
group_b.SetLength(count_b);
// bin_b->AddPolygons(process, group_b);
//
//-------------------------------------------------------------------
// Now that the mesh has been split up, Bin_Sort each smaller mesh and
// destroy this mesh
//-------------------------------------------------------------------
//
int worked = 0;
if (BinSort(
group,
0,
levDiff,
group_a,
binSize,
uvFrame,
state))
{
worked |= 1;
}
if (BinSort(
group,
1,
levDiff,
group_b,
binSize,
uvFrame,
state))
{
worked |= 2;
}
if(worked != 3)
{
if(worked == 0)
return false;
ListElement *smallgroup = new ListElement;
Register_Object(smallgroup);
group->SetSize(1);
Element *element;
if(worked==1)
{
element = group->GetIndexedElement(0);
element->DetachFromParent();
}
else
{
element = group->GetIndexedElement(1);
element->DetachFromParent();
}
delete group;
smallgroup->AttachIndexedChild(0, element);
Check_Object(smallgroup);
parent->AttachIndexedChild(index, smallgroup);
}
else
{
Check_Object(group);
parent->AttachIndexedChild(index, group);
}
//
//-----------------------------------------
// Now set the bounding sphere of the group
//-----------------------------------------
//
group->NeedNewBounds();
group->SetVolumeCullMode();
return true;
}
void
HFSlim::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];
if(field[j*X + i] > maxY)
{
maxY = field[j*X + i];
}
}
Offset = -maxY*dY;
MASK = new ImportMask;
MASK->width=X;
MASK->height=Z;
GreedySubdivision mesh(&map);
point_limit=1024;
if(depth==0)
point_limit = GetFullPolyCount()/4;
else
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].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);
nrOfIZs = 1;
}
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");
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
HFSlim::BuildTile(
ElementRenderer::ListElement *list,
int index,
int depth, int maxdepth,
DynamicArrayOf<unsigned char>& onOffPoints,
int maxNumOfTrianglesPerMesh,
Scalar xGridOffset,
Scalar zGridOffset,
Scalar xGrid,
Scalar zGrid,
int tileX,
int tileZ,
const char *texRoot
)
{
char textureName[1024];
int numOfTriangles = toSortTriangles.GetLength();
DynamicArrayOf<ToDrawTriangle*> tempTrianglesPtr(numOfTriangles);
DynamicArrayOf<ToDrawTriangle> tempTriangles(numOfTriangles);
int i, j, inCount, newCount = 0, extraTriangles = 0;
int k, l, m;
Scalar x0, z0, x1, z1;
x0 = xGridOffset + tileX*xGrid;
z0 = zGridOffset + tileZ*zGrid;
x1 = x0 + xGrid;
z1 = z0 + zGrid;
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
);
*/
state.SetPriority(MLRState::DefaultPriority);
sprintf(textureName, "%s_%1d_%02x%02x",
texRoot,
depth,
(1<<depth) - tileX/(1<<(maxdepth-depth)) - 1,
(1<<depth) - tileZ/(1<<(maxdepth-depth)) - 1
);
MLRTexture *texture = MLRTexturePool::Instance->Add(textureName);
texture->SetHint(gosHint_AGPMemory | gosHint_DontShrink);
state.SetTextureHandle(texture->GetTextureHandle());
state.SetTextureWrapMode(MLRState::TextureClamp);
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;
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)
);
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)
);
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)
);
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)
);
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();
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)
);
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)
);
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)
);
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)
);
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)
{
tempTrianglesPtr[newCount++] = &tempTriangles[extraTriangles];
extraTriangles++;
}
}
}
}
}
}
// tempTriangles.SetLength(extraTriangles);
tempTrianglesPtr.SetLength(newCount);
if(newCount > 0)
{
AnalyzeThis(
tempTrianglesPtr,
x0,
z0,
x1,
z1
);
int i = 1<<(maxdepth - depth);
x0 = xGridOffset + (tileX/i)*(i*xGrid);
z0 = zGridOffset + (tileZ/i)*(i*zGrid);
x1 = x0 + i*xGrid;
z1 = z0 + i*zGrid;
Stuff::ExtentBox box;
box.minX = x0;
box.maxX = x1;
box.minY = Offset;
box.maxY = 0.0f;
box.minZ = z0;
box.maxZ = z1;
if(!BinSort(
list,
index,
maxdepth - depth,
tempTrianglesPtr,
maxNumOfTrianglesPerMesh,
&box,
&state
)
)
{
}
else
{
brokenTriangles += newCount;
}
}
else
{
}
tempTrianglesPtr.SetLength(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
HFSlim::DescentToUnderMountain(
int depth,
#ifdef GRID_TEST
ElementRenderer::GridElement *group,
#else
ElementRenderer::ListElement *group,
#endif
DynamicArrayOf<unsigned char>& onOffPoints,
int maxNumOfTrianglesPerMesh,
Scalar x0,
Scalar z0,
Scalar x1,
Scalar z1,
int tileX,
int tileZ,
const char *texRoot
)
{
if((depth & 0xff) ==0)
{
char textureName[1024];
int numOfTriangles = toSortTriangles.GetLength();
DynamicArrayOf<ToDrawTriangle*> tempTrianglesPtr(numOfTriangles);
DynamicArrayOf<ToDrawTriangle> tempTriangles(numOfTriangles);
int i, j, inCount, newCount = 0, extraTriangles = 0;
int k, l, 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
);
*/
state.SetPriority(MLRState::DefaultPriority);
sprintf(textureName, "%s_%1d_%02x%02x", texRoot, (depth>>8)-depth&0xff, tileX, tileZ);
MLRTexture *texture = MLRTexturePool::Instance->Add(textureName);
state.SetTextureHandle(texture->GetTextureHandle());
state.SetTextureWrapMode(MLRState::TextureClamp);
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;
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)
);
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)
);
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)
);
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)
);
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();
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)
);
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)
);
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)
);
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)
);
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();
tempTrianglesPtr[newCount++] = &tempTriangles[extraTriangles];
extraTriangles++;
}
}
}
}
}
// tempTriangles.SetLength(extraTriangles);
tempTrianglesPtr.SetLength(newCount);
if(newCount > 0)
{
#ifdef GRID_TEST
group->SetSize(1, 1);
#else
group->SetSize(1);
#endif
Stuff::ExtentBox box;
box.minX = x0;
box.maxX = x1;
box.minY = Offset;
box.maxY = 0.0f;
box.minZ = z0;
box.maxZ = z1;
if(!BinSort(
group,
0,
0,
tempTrianglesPtr,
maxNumOfTrianglesPerMesh,
&box,
&state
)
)
{
#ifdef GRID_TEST
group->SetSize(0, 0);
#else
group->SetSize(0);
#endif
}
else
{
fprintf(analyzeFile, "%d\n", newCount);
brokenTriangles += newCount;
}
}
else
{
#ifdef GRID_TEST
group->SetSize(0, 0);
#else
group->SetSize(0);
#endif
}
tempTrianglesPtr.SetLength(0);
}
else
{
#ifdef GRID_TEST
ElementRenderer::GridElement
#else
ElementRenderer::ListElement
#endif
*group00, *group01, *group10, *group11;
#ifdef GRID_TEST
group->SetSize(2, 2);
group00 = new ElementRenderer::GridElement(2, 2);
#else
group->SetSize(4);
group00 = new ElementRenderer::ListElement;
#endif
Register_Object(group00);
#ifdef GRID_TEST
group->AttachIndexedChild(0, 0, group00);
#else
group->AttachIndexedChild(0, group00);
group00->NeedNewBounds();
group00->SetVolumeCullMode();
#endif
#ifdef GRID_TEST
group01 = new ElementRenderer::GridElement(2, 2);
#else
group01 = new ElementRenderer::ListElement;
#endif
Register_Object(group01);
#ifdef GRID_TEST
group->AttachIndexedChild(0, 1, group01);
#else
group->AttachIndexedChild(1, group01);
group01->NeedNewBounds();
group01->SetVolumeCullMode();
#endif
#ifdef GRID_TEST
group10 = new ElementRenderer::GridElement(2, 2);
#else
group10 = new ElementRenderer::ListElement;
#endif
Register_Object(group10);
#ifdef GRID_TEST
group->AttachIndexedChild(1, 0, group10);
#else
group->AttachIndexedChild(2, group10);
group10->NeedNewBounds();
group10->SetVolumeCullMode();
#endif
#ifdef GRID_TEST
group11 = new ElementRenderer::GridElement(2, 2);
#else
group11 = new ElementRenderer::ListElement;
#endif
Register_Object(group11);
#ifdef GRID_TEST
group->AttachIndexedChild(1, 1, group11);
#else
group->AttachIndexedChild(3, group11);
group11->NeedNewBounds();
group11->SetVolumeCullMode();
#endif
DescentToUnderMountain(
depth-1, group00, onOffPoints, maxNumOfTrianglesPerMesh,
x0, z0, x0 + (x1-x0)/2.0f, z0 + (z1-z0)/2.0f, 2*tileX, 2*tileZ, texRoot
);
DescentToUnderMountain(
depth-1, group01, onOffPoints, maxNumOfTrianglesPerMesh,
x0 + (x1-x0)/2.0f, z0, x1, z0 + (z1-z0)/2.0f, 2*tileX+1, 2*tileZ, texRoot
);
DescentToUnderMountain(
depth-1, group10, onOffPoints, maxNumOfTrianglesPerMesh,
x0, z0 + (z1-z0)/2.0f, x0 + (x1-x0)/2.0f, z1, 2*tileX, 2*tileZ+1, texRoot
);
DescentToUnderMountain(
depth-1, group11, onOffPoints, maxNumOfTrianglesPerMesh,
x0 + (x1-x0)/2.0f, z0 + (z1-z0)/2.0f, x1, z1, 2*tileX+1, 2*tileZ+1, texRoot
);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
HFSlim::SetMegaTexture(
int nrOfLevels,
int bucketSize,
const char *mega_base_name,
DetailLevelInfo *dli
)
{
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.SetAlphaMode(detailInfo.alphaMode);
state1.SetPriority(MLRState::DefaultPriority + 1);
MLRTexture *texture = MLRTexturePool::Instance->Add(detailInfo.name);
state1.SetTextureHandle(texture->GetTextureHandle());
}
DynamicArrayOf<unsigned char> onOffTriangles;
onOffTriangles.AssignValue(0, toSortTriangles.GetLength());
if(simpleTerrainGroup)
{
Unregister_Object(simpleTerrainGroup);
delete simpleTerrainGroup;
simpleTerrainGroup = NULL;
}
Stuff::ExtentBox allBox;
allBox = GetExtents();
brokenTriangles = 0;
#ifdef GRID_TEST
int len = 1<<nrOfLevels;
simpleTerrainGroup = new GridElement(len, len);
Register_Object(simpleTerrainGroup);
simpleTerrainGroup->SetName("OptimizedTerrain");
int i, j, level;
xGridSize = (allBox.maxX-allBox.minX)/len;
zGridSize = (allBox.maxZ-allBox.minZ)/len;
for(j=0;j<len;j++)
{
for(i=0;i<len;i++)
{
if(dli->width*dli->height==0)
{
level = nrOfLevels;
}
else
{
Verify(dli->width == len);
Verify(dli->height == len);
switch(dli->array[(dli->height-j-1)*len+dli->width-i-1])
{
case 0:
level = nrOfLevels-2;
break;
case 1:
level = nrOfLevels-1;
break;
case 2:
level = nrOfLevels;
break;
default:
level = nrOfLevels;
}
}
tX = i;
tY = j;
BuildTile(
simpleTerrainGroup,
j*len+i,
level,
nrOfLevels,
onOffTriangles,
bucketSize,
allBox.minX,
allBox.minZ,
(allBox.maxX-allBox.minX)/len,
(allBox.maxZ-allBox.minZ)/len,
i,
j,
mega_base_name
);
}
}
simpleTerrainGroup->LockBounds();
simpleTerrainGroup->SetDimensions(0.0f, 0.0f, GetXinM(), GetZinM());
#else
simpleTerrainGroup = new ListElement;
Register_Object(simpleTerrainGroup);
simpleTerrainGroup->SetName("OptimizedTerrain");
DescentToUnderMountain
(
(nrOfLevels<<8) + nrOfLevels,
simpleTerrainGroup,
bucketSize,
allBox.minZ,
allBox.maxX,
allBox.maxZ,
0,
0,
);
simpleTerrainGroup->NeedNewBounds();
#endif
fprintf(stdout, "\"broken\" triangles: %d\n", brokenTriangles);
return true;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
HFSlim::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 HFSlim::DisplayFull(bool bl)
{
ElementRenderer::Element *element;
if(bl==true)
{
element=terrainGroup->FindElement(fullTerrainGroup->GetName());
if(element==NULL)
terrainGroup->AttachChild(fullTerrainGroup);
}
else
{
element=terrainGroup->FindElement(fullTerrainGroup->GetName());
if(element!=NULL)
terrainGroup->DetachChild(fullTerrainGroup);
}
}
void HFSlim::DisplayOpt(bool bl)
{
ElementRenderer::Element *element;
if(bl==true)
{
element=terrainGroup->FindElement(simpleTerrainGroup->GetName());
if(element==NULL)
terrainGroup->AttachChild(simpleTerrainGroup);
}
else
{
element=terrainGroup->FindElement(simpleTerrainGroup->GetName());
if(element!=NULL)
terrainGroup->DetachChild(simpleTerrainGroup);
}
}
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;
}