Files
firestorm/Gameleap/code/mw4/Tools/TCTb/HFslimMZ.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

7502 lines
173 KiB
C++

#include <MLR\MLRHeaders.hpp>
#include <ElementRenderer\GridElement.hpp>
#include <ElementRenderer\GroupElement.hpp>
#include <ElementRenderer\ShapeElement.hpp>
#if !defined(HFSLIMMZ_HPP)
#include "HFslimMZ.hpp"
#include "terra\terra.hpp"
#endif
//#define NON_DEBUG_BUG 1
#define CHANGE_0625
const Scalar One_Over_Three = 1.0f/3.0f;
extern FILE *analyzeFile;
bool doWater = false;
Scalar waterLevel;
bool doBSP = false;
bool doPrecise = false;
bool doInterest = false;
bool doTileCap = false;
bool doTileCapYovin = false;
bool doDensityMap = false;
bool silentMode = false;
const Scalar smaller = SMALL;
FILE *daWaterObj = NULL;
static int vertexCountObj;
DynamicArrayOf<PointStruct> uniquePoints;
int usedUniquePoints;
PointStruct *TriangleStruct::points = NULL;
DynamicArrayOf<TriangleStruct> triangleIndices;
int usedTriangleIndices;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
template <class T> void Swap(T& t1, T& t2)
{
T t;
t = t1;
t1 = t2;
t2 = t;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool IsPowerOf2(int X)
{
return !( X & ( X - 1 ) );
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
FindPoint(Point3D& point)
{
for(int i=0;i<usedUniquePoints;i++)
{
if(Close_Enough(uniquePoints[i].p.x, point.x) && Close_Enough(uniquePoints[i].p.z, point.z))
{
return i;
}
}
return -1;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
FindAddPoint(Point3D& point)
{
int closest = -1;
float closestRadius = 10000000000000000000000000000000.0f;
for(int i=0;i<usedUniquePoints;i++)
{
Vector3D v(
uniquePoints[i].p.x-point.x,
uniquePoints[i].p.y-point.y,
uniquePoints[i].p.z-point.z
);
float radius = v.GetLengthSquared();
if(radius<SMALL)
{
if(radius<closestRadius)
{
closest = i;
closestRadius = radius;
}
}
}
if(closest>=0)
{
return closest;
}
uniquePoints[usedUniquePoints++].p = point;
return (usedUniquePoints-1);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
RemoveTriangle(TriangleStruct *ts)
{
int i, j;
for(i=0;i<usedTriangleIndices;i++)
{
if(ts == &triangleIndices[i])
{
break;
}
}
if(i>=usedTriangleIndices)
{
return false;
}
PointStruct *point;
for(i=0;i<3;i++)
{
point = &ts->points[ts->v[i]];
do
{
for(j=0;j<point->connectedTo;j++)
{
if(point->myTri[j].tri==ts)
{
break;
}
}
if(j<point->connectedTo)
{
for(;j<point->connectedTo-1;j++)
{
point->myTri[j].tri = point->myTri[j+1].tri;
point->myTri[j].angle = point->myTri[j+1].angle;
point->myTri[j].pos = point->myTri[j+1].pos;
}
point->connectedTo--;
}
else
{
break;
}
} while(point->connectedTo>0);
}
return true;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
RemoveTriangle(int i)
{
int j;
if(i>=usedTriangleIndices)
{
return false;
}
TriangleStruct *ts = &triangleIndices[i];
PointStruct *point;
for(i=0;i<3;i++)
{
point = &ts->points[ts->v[i]];
do
{
for(j=0;j<point->connectedTo;j++)
{
if(point->myTri[j].tri==ts)
{
break;
}
}
if(j<point->connectedTo)
{
for(;j<point->connectedTo-1;j++)
{
point->myTri[j].tri = point->myTri[j+1].tri;
point->myTri[j].angle = point->myTri[j+1].angle;
point->myTri[j].pos = point->myTri[j+1].pos;
}
point->connectedTo--;
}
else
{
break;
}
} while(point->connectedTo>0);
}
return true;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
float
GetAngle(Point3D& p0, Point3D& p1, Point3D& p2)
{
Vector3D v1, v2;
v1.Subtract(p0, p1);
v2.Subtract(p2, p1);
v1.y = 0.0f;
v2.y = 0.0f;
Scalar l1 = v1.GetLength(), l2 = v2.GetLength();
if(Small_Enough(l1*l2))
{
return 0.0f;
}
l1 = (v1*v2)/(l1*l2);
l1 = l1 > 1.0f ? 1.0f : l1;
l1 = l1 < -1.0f ? -1.0f : l1;
return static_cast<float> (acos(l1));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
PointStruct::Add (TriangleStruct *ts, int pos)
{
Verify(Close_Enough(p.x, ts->GetPoint(pos).x) && Close_Enough(p.z, ts->GetPoint(pos).z));
myTri[connectedTo].tri = ts;
myTri[connectedTo].pos = pos;
myTri[connectedTo].angle = GetAngle(ts->GetPoint((pos-1+3)%3), ts->GetPoint(pos), ts->GetPoint((pos+1)%3));
Verify(myTri[connectedTo].angle<=Pi);
if(++connectedTo==myTri.GetLength())
{
myTri.SetLength(myTri.GetLength()+12);
}
Check_Object(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
PointStruct::CalculateAngles()
{
Check_Object(this);
for(int i=0;i<connectedTo;i++)
{
myTri[i].angle = GetAngle(
myTri[i].tri->GetPoint((myTri[i].pos-1+3)%3),
myTri[i].tri->GetPoint(myTri[i].pos),
myTri[i].tri->GetPoint((myTri[i].pos+1)%3)
);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
float
PointStruct::GetAngles()
{
Check_Object(this);
float angle = 0.0f;
if(connectedTo==0)
{
return angle;
}
for(int j=0;j<connectedTo;j++)
{
angle += myTri[j].angle;
}
return angle;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
float
PointStruct::GetExpectedAngles(Scalar xMin, Scalar zMin, Scalar xMax, Scalar zMax)
{
if( (p.x == xMin || p.x==xMax) &&
(p.z == zMin || p.z==zMax) )
{
return Pi*0.5f;
}
else
if( (p.x == xMin || p.x==xMax) ||
(p.z == zMin || p.z==zMax) )
{
return Pi;
}
else
{
return 2*Pi;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
PointStruct::CheckAngles(Scalar xMin, Scalar zMin, Scalar xMax, Scalar zMax, Scalar dX, Scalar dZ)
{
Check_Object(this);
if(connectedTo==0)
{
return true;
}
float angle = GetAngles();
if( (p.x == xMin || p.x==xMax) &&
(p.z == zMin || p.z==zMax) )
{
if(!Close_Enough(angle, Pi*0.5f, 0.005f))
{
return false;
}
}
else
if( (p.x == xMin || p.x==xMax) ||
(p.z == zMin || p.z==zMax) )
{
if(!Close_Enough(angle, Pi, 0.005f))
{
return false;
}
}
else
{
if(!Close_Enough(angle, 2.0f*Pi, 0.005f))
{
if(p.z==zMax-dZ)
{
if(!Close_Enough(angle, Pi, 0.005f))
{
return false;
}
}
else
{
return false;
}
}
}
return true;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
PointStruct::CheckAngles()
{
for(int j=0;j<connectedTo;j++)
{
if(Close_Enough(myTri[j].angle, Pi))
{
return false;
}
}
return true;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
PointStruct::TestInstance() const
{
for(int i=0;i<connectedTo;i++)
{
Verify(myTri[i].tri->v[0] < usedUniquePoints);
Verify(myTri[i].tri->v[1] < usedUniquePoints);
Verify(myTri[i].tri->v[2] < usedUniquePoints);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
TriangleAbstract::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 = GetPoint(0);
centerValid = true;
plane.normal.x = 0.0f;
plane.normal.y = 0.0f;
plane.normal.z = 1.0f;
plane.offset = 0.0f;
//
//-----------------------------------------------
// Generate all the information on the first pass
//-----------------------------------------------
//
position_a = GetPoint(2);
position_b = GetPoint(0);
position_c = GetPoint(1);
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)
{
Point3D p0, p1, p2;
p0 = GetPoint(0);
p1 = GetPoint(2);
p2 = GetPoint(1);
Vector3D v1,v2;
v1.Subtract(p1, p0);
v2.Subtract(p2, p1);
Vector3D axis;
axis.Cross(v1, v2);
if(Small_Enough(axis.GetLength()))
{
area = 0.0f;
return false;
}
plane.normal = axis;
plane.offset = plane.normal * p0;
center *= (One_Over_Three/area);
if(plane.normal.y<=Stuff::SMALL)
{
area = 0.0f;
return false;
}
}
else
{
center *= One_Over_Three;
area = 0.0f;
return false;
}
return true;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
WaterPools::AddEdge(Stuff::Point3D& p0, Stuff::Point3D& p1, const
Stuff::Normal3D& normal)
{
int i, j;
Verify(p0.y==waterLevel);
Verify(p1.y==waterLevel);
int oe0 = OnWhatEdge(p0);
int oe1 = OnWhatEdge(p1);
if(Close_Enough(p0, p1, smaller))
{
return;
}
for(i=0;i<waterEdgePointCount;i++)
{
if(Close_Enough(waterEdgePoints[i].p, p0, smaller))
{
break;
}
}
if(i==waterEdgePointCount)
{
Verify(waterEdgePoints[waterEdgePointCount].toEdgeCount == 0);
waterEdgePoints[waterEdgePointCount].p = p0;
waterEdgePoints[waterEdgePointCount].toEdge[waterEdgePoints[waterEdgePointCount].toEdgeCount++]
= waterEdgeCount;
waterEdgePoints[waterEdgePointCount].onEdge = oe0;
waterEdgePointCount++;
}
else
{
Verify(waterEdgePoints[i].toEdgeCount < 8);
waterEdgePoints[i].toEdge[waterEdgePoints[i].toEdgeCount++] =
waterEdgeCount;
}
waterEdge[waterEdgeCount].p[0] = i;
for(j=0;j<waterEdgePointCount;j++)
{
if(Close_Enough(waterEdgePoints[j].p, p1, smaller))
{
break;
}
}
if(j==waterEdgePointCount)
{
Verify(waterEdgePoints[waterEdgePointCount].toEdgeCount == 0);
waterEdgePoints[waterEdgePointCount].p = p1;
waterEdgePoints[waterEdgePointCount].toEdge[waterEdgePoints[waterEdgePointCount].toEdgeCount++]
= waterEdgeCount;
waterEdgePoints[waterEdgePointCount].onEdge = oe1;
waterEdgePointCount++;
}
else
{
Verify(waterEdgePoints[j].toEdgeCount < 8);
waterEdgePoints[j].toEdge[waterEdgePoints[j].toEdgeCount++] =
waterEdgeCount;
}
waterEdge[waterEdgeCount].p[1] = j;
waterEdge[waterEdgeCount].normal = normal;
waterEdgeCount++;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MidLevelRenderer::MLRPrimitiveBase*
WaterPools::LinkEdges()
{
if(waterEdgePointCount==0)
{
return NULL;
}
int i, j;
for(i=0;i<waterEdgePointCount;i++)
{
SPEW(("micgaert", "V%2d: %.12f %.12f", i, waterEdgePoints[i].p.x,
waterEdgePoints[i].p.z));
}
for(i=0;i<waterEdgeCount;i++)
{
SPEW(("micgaert", "E%2d: %d %d", i, waterEdge[i].p[0],
waterEdge[i].p[1]));
}
for(i=0;i<waterEdgePointCount;i++)
{
if(waterEdgePoints[i].toEdge[1] < 0 && waterEdgePoints[i].onEdge==0)
{
SPEW(("micgaert", "OH NO %d", i));
i = OnWhatEdge(waterEdgePoints[i]);
break;
}
}
for(i=0;i<waterEdgePointCount;i++)
{
waterEdgePoints[i].used = false;
}
i = 0;
int pool = 1, edge = -1;
int usedPoints = 0;
bool island = false;
DynamicArrayOf<Point3D> polygon(2*waterEdgePointCount);
DynamicArrayOf<Normal3D> normals(2*waterEdgePointCount);
DynamicArrayOf<WaterEdgePoint> edgePoints[4];
int vertexCount;
// find the open pools
int edgePointCount[4] = { 0, 0, 0, 0};
int mask = 1;
for(j=0;j<4;j++)
{
edgePoints[j].SetLength(waterEdgePointCount);
for(i=0;i<waterEdgePointCount;i++)
{
if(waterEdgePoints[i].onEdge & mask && waterEdgePoints[i].toEdge[1]==-1)
{
edgePoints[j][edgePointCount[j]++] = waterEdgePoints[i];
}
}
mask <<= 1;
}
if(edgePointCount[0]>1)
{
for(i=edgePointCount[0]-1;i>=0;i--)
{
for(j=1;j<=i;j++)
{
if(edgePoints[0][j-1].p.z > edgePoints[0][j].p.z)
{
Swap(edgePoints[0][j-1], edgePoints[0][j]);
}
}
}
}
if(edgePointCount[1]>1)
{
for(i=edgePointCount[1]-1;i>=0;i--)
{
for(j=1;j<=i;j++)
{
if(edgePoints[1][j-1].p.x > edgePoints[1][j].p.x)
{
Swap(edgePoints[1][j-1], edgePoints[1][j]);
}
}
}
}
if(edgePointCount[2]>1)
{
for(i=edgePointCount[2]-1;i>=0;i--)
{
for(j=1;j<=i;j++)
{
if(edgePoints[2][j-1].p.z < edgePoints[2][j].p.z)
{
Swap(edgePoints[2][j-1], edgePoints[2][j]);
}
}
}
}
if(edgePointCount[3]>1)
{
for(i=edgePointCount[3]-1;i>=0;i--)
{
for(j=1;j<=i;j++)
{
if(edgePoints[3][j-1].p.x < edgePoints[3][j].p.x)
{
Swap(edgePoints[3][j-1], edgePoints[3][j]);
}
}
}
}
if(edgePointCount[0] + edgePointCount[1] + edgePointCount[2] +
edgePointCount[3] > 0)
do
{
for(i=0;i<waterEdgePointCount;i++)
{
if(waterEdgePoints[i].used == 0 && waterEdgePoints[i].toEdge[1]==-1)
{
break;
}
}
if(i==waterEdgePointCount)
{
break;
}
vertexCount = 0;
int next;
do
{
while(waterEdgePoints[i].used == 0)
{
waterEdgePoints[i].used = pool;
usedPoints++;
polygon[vertexCount] = waterEdgePoints[i].p;
SPEW(("micgaert", "O: %6.1f %6.1f", polygon[vertexCount].x,
polygon[vertexCount].z));
if(waterEdgePoints[i].toEdge[0]==edge)
{
Verify(waterEdgePoints[i].toEdge[1]!=edge);
edge = waterEdgePoints[i].toEdge[1];
}
else
{
edge = waterEdgePoints[i].toEdge[0];
}
if(edge==-1)
{
normals[vertexCount++] = Normal3D::Down;
break;
}
normals[vertexCount++] = waterEdge[edge].normal;
if(waterEdge[edge].p[0] != i)
{
i = waterEdge[edge].p[0];
}
else
{
Verify(waterEdge[edge].p[1] != i);
i = waterEdge[edge].p[1];
}
if(i<0)
{
break;
}
}
// finding edges along the tile edge
int onWhatEdgeFirst = OnWhatEdge(polygon[0]);
int onWhatEdgeLast = OnWhatEdge(polygon[vertexCount-1]);
if(onWhatEdgeLast==0)
{
SPEW(("micgaert", "OH NO %d", edge));
}
mask = 1;
//
// i mask inD s nx nz ns
//
// 0 1 1 + 1 0 +
// 1 2 0 + 0 1 -
// 2 4 1 - 1 0 -
// 3 8 0 - 0 1 +
//
//
for(i=0;i<4;i++,mask<<=1)
{
if(onWhatEdgeLast & mask)
{
break;
Verify(edgePointCount[i] > 0);
}
}
// Verify(i<4);
bool cloakWise = false;
int edgePoint = -1;
if(i<4)
do
{
int sign = (i>1)?-1:1;
Scalar inDir[2];
Vector3D vx(1.0f, 0.0f, 0.0f);
inDir[0] = normals[vertexCount-2]*vx;
Vector3D vz(0.0f, 0.0f, 1.0f);
inDir[1] = normals[vertexCount-2]*vz;
cloakWise = sign*inDir[(i+1)&1]>0.0f;
if(polygon[vertexCount-1].x == x0 && polygon[vertexCount-1].z == z0)
{
edgePoint = 0;
Verify(((i==0)&&(cloakWise==true)) || ((i==3)&&(cloakWise==false)));
}
else
{
if(polygon[vertexCount-1].x == x0 && polygon[vertexCount-1].z == z1)
{
edgePoint = 1;
Verify(((i==1)&&(cloakWise==true)) || ((i==0)&&(cloakWise==false)));
}
else
{
if(polygon[vertexCount-1].x == x1 && polygon[vertexCount-1].z == z1)
{
edgePoint = 2;
Verify(((i==2)&&(cloakWise==true)) || ((i==1)&&(cloakWise==false)));
}
else
{
if(polygon[vertexCount-1].x == x1 && polygon[vertexCount-1].z == z0)
{
edgePoint = 3;
Verify(((i==3)&&(cloakWise==true)) || ((i==2)&&(cloakWise==false)));
}
else
{
edgePoint = -1;
}
}
}
}
normals[vertexCount-1] = Normal3D(
(((i+3)&3)>1?1:-1)*((i+1)&1)*1.0f,
0.0f,
(((i+3)&3)>1?1:-1)*(i&1)*1.0f
);
Verify(Close_Enough(normals[vertexCount-1].GetLengthSquared(), 1.0f));
Verify(mask & onWhatEdgeLast);
int same = -1;
if(edgePointCount[i]>0)
{
for(j=0;j<edgePointCount[i];j++)
{
if(Close_Enough(polygon[vertexCount-1], edgePoints[i][j].p, smaller))
{
same = j;
break;
}
}
if(j<edgePointCount[i])
{
}
else
{
Verify(edgePoint>=0);
next = cloakWise? 0 : edgePointCount[i]-1;
break;
}
}
else
{
}
if(edgePointCount[i]==0)
{
}
bool allOurs = j==edgePointCount[i];
// SPEW(("micgaert", "%d %f %f: %.1f %.1f %.1f",
// onWhatEdgeLast, inDir[0], inDir[1],
// normals[vertexCount-1].x, normals[vertexCount-1].y,
// normals[vertexCount-1].z
// ));
int whereTo = 0;
Point3D newPoint;
if(sign*inDir[(i+1)&1] > 0.0f)
{
if(j>=edgePointCount[i]-1)
{
newPoint = Point3D(
(i==0) ? x0 :
(i==1) ? (inDir[0]>0.0)? x1:x0 :
(i==2) ? x1 : (inDir[0]>0.0)? x1:x0,
waterLevel,
(i==0) ? (inDir[1]>0.0)? z1:z0 :
(i==1) ? z1 :
(i==2) ? (inDir[1]>0.0)? z1:z0 : z0
);
SPEW(("micgaert", "O: %6.1f %6.1f", newPoint.x, newPoint.z));
int k;
for(k=0;k<vertexCount;k++)
{
if(Close_Enough(polygon[k], newPoint, smaller))
{
break;
}
}
Verify(k==vertexCount);
polygon[vertexCount++] = newPoint;
onWhatEdgeLast = OnWhatEdge(polygon[vertexCount-1]);
}
else
{
next = j+1;
Verify(next<edgePointCount[i]);
break;
}
whereTo = 1;
mask<<=1;
if(mask>8)
{
mask = 1;
}
}
else
{
if(j==0 || j>=edgePointCount[i])
{
newPoint = Point3D(
(i==0) ? x0 :
(i==1) ? (inDir[0]>0.0)? x1:x0 :
(i==2) ? x1 : (inDir[0]>0.0)? x1:x0,
waterLevel,
(i==0) ? (inDir[1]>0.0)? z1:z0 :
(i==1) ? z1 :
(i==2) ? (inDir[1]>0.0)? z1:z0 : z0
);
SPEW(("micgaert", "O: %6.1f %6.1f", newPoint.x, newPoint.z));
int k;
for(k=0;k<vertexCount;k++)
{
if(Close_Enough(polygon[k], newPoint, smaller))
{
break;
}
}
Verify(k==vertexCount);
polygon[vertexCount++] = newPoint;
onWhatEdgeLast = OnWhatEdge(polygon[vertexCount-1]);
}
else
{
next = j-1;
Verify(next<edgePointCount[i]);
break;
}
whereTo = -1;
mask>>=1;
if(mask<=0)
{
mask = 8;
}
}
Verify(mask>0 && mask<16);
Verify(onWhatEdgeLast!=0);
i = (i+4+whereTo)&3;
} while(1);
int hello;
for(hello=0;hello<waterEdgePointCount;hello++)
{
if(Close_Enough(waterEdgePoints[hello].p, edgePoints[i][next].p,
smaller))
{
break;
}
}
if(waterEdgePoints[hello].used>0)
{
Verify(waterEdgePoints[hello].toEdge[1]==-1);
break;
}
else
{
Verify(hello<waterEdgePointCount);
i = hello;
};
} while (1);
// Verify(vertexCount>2);
pool++;
int j, up=0, down=0;
int upVC=0, downVC=0;
int bigA = -1;
Scalar axisL = 1000000.0f ;
for(j=0;j<vertexCount;j++)
{
if(daWaterObj!=NULL && vertexCount>2)
{
fprintf(daWaterObj, "v %.5f %.5f %.5f\n", polygon[j].x, waterLevel,
polygon[j].z);
}
int next = (j+1)%vertexCount;
Normal3D n(normals[j]);
n.y = 0.0f;
n.Normalize(n);
Vector3D v;
v.Cross(normals[j], normals[next]);
Scalar l = v.GetLengthSquared();
if(l>0.0f)
{
up++;
if(l<axisL)
{
bigA = j;
}
}
else
{
down++;
}
v.Cross(polygon[j], polygon[next], polygon[(j+2)%vertexCount]);
if(v.y>0.0f)
{
upVC++;
}
else
{
downVC++;
}
}
if(daWaterObj!=NULL && vertexCount>2)
{
fprintf(daWaterObj, "f");
if(upVC>downVC)
{
for(j=0;j<vertexCount;j++)
{
fprintf(daWaterObj, " %d", j+vertexCountObj);
}
}
else
{
for(j=vertexCount-1;j>=0;j--)
{
fprintf(daWaterObj, " %d", j+vertexCountObj);
}
}
fprintf(daWaterObj, "\n\n");
vertexCountObj += vertexCount;
}
SPEW(("micgaert", "==="));
// SPEW(("micgaert", "%d %d", up, down));
/* if(down==0)
{
for(j=0;j<vertexCount;j++)
{
(*coords)[cCount+j] = polygon[(j+bigA)%vertexCount];
(*index)[cCount+j] = cCount+j;
}
(*lengths)[pCount++] = vertexCount;
cCount += j;
}
*/
} while(usedPoints < waterEdgePointCount);
// find the closed pools
if(usedPoints < waterEdgePointCount)
{
do
{
for(i=0;i<waterEdgePointCount;i++)
{
if(waterEdgePoints[i].used == 0 && waterEdgePoints[i].toEdge[1]>=0)
{
break;
}
}
if(i==waterEdgePointCount)
{
break;
}
vertexCount = 0;
while(waterEdgePoints[i].used == 0)
{
waterEdgePoints[i].used = pool;
usedPoints++;
polygon[vertexCount] = waterEdgePoints[i].p;
if(waterEdgePoints[i].toEdge[0]==edge)
{
Verify(waterEdgePoints[i].toEdge[1]!=edge);
edge = waterEdgePoints[i].toEdge[1];
}
else
{
edge = waterEdgePoints[i].toEdge[0];
}
if(edge==-1)
{
normals[vertexCount++] = Normal3D::Down;
break;
}
normals[vertexCount++] = waterEdge[edge].normal;
if(waterEdge[edge].p[0] != i)
{
i = waterEdge[edge].p[0];
}
else
{
Verify(waterEdge[edge].p[1] != i);
i = waterEdge[edge].p[1];
}
if(i<0)
{
break;
}
}
pool++;
// island or pool
Verify(vertexCount>2);
int j, up=0, down=0;
int upVC=0, downVC=0;
int bigA = -1;
Scalar axisL = 1000000.0f ;
for(j=0;j<vertexCount;j++)
{
if(daWaterObj!=NULL)
{
fprintf(daWaterObj, "v %.5f %.5f %.5f\n", polygon[j].x, waterLevel,
polygon[j].z);
}
int next = (j+1)%vertexCount;
Normal3D n(normals[j]);
n.y = 0.0f;
n.Normalize(n);
SPEW(("micgaert", "C: %6.1f %6.1f %6.1f %6.1f", polygon[j].x,
polygon[j].z, n.x, n.z));
Vector3D v;
v.Cross(normals[j], normals[next]);
Scalar l = v.GetLengthSquared();
if(l>0.0f)
{
up++;
if(l<axisL)
{
bigA = j;
}
}
else
{
down++;
}
v.Cross(polygon[j], polygon[next], polygon[(j+2)%vertexCount]);
if(v.y>0.0f)
{
upVC++;
}
else
{
downVC++;
}
}
SPEW(("micgaert", "==="));
// SPEW(("micgaert", "%d %d", up, down));
/* if(down==0)
{
for(j=0;j<vertexCount;j++)
{
(*coords)[cCount+j] = polygon[(j+bigA)%vertexCount];
(*index)[cCount+j] = cCount+j;
}
(*lengths)[pCount++] = vertexCount;
cCount += j;
}
*/
if(daWaterObj!=NULL)
{
fprintf(daWaterObj, "f");
if(upVC>downVC)
{
for(j=0;j<vertexCount;j++)
{
fprintf(daWaterObj, " %d", j+vertexCountObj);
}
}
else
{
for(j=vertexCount-1;j>=0;j--)
{
fprintf(daWaterObj, " %d", j+vertexCountObj);
}
}
fprintf(daWaterObj, "\n\n");
vertexCountObj += vertexCount;
}
} while(usedPoints < waterEdgePointCount);
}
SPEW(("micgaert", "==="));
Verify(usedPoints == waterEdgePointCount);
return NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
WaterPools::OnWhatEdge(WaterEdgePoint& wep)
{
return OnWhatEdge(wep.p);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
WaterPools::OnWhatEdge(Point3D& p)
{
int onWhatEdge = 0;
if(Close_Enough(p.x, x0, 100.0f*smaller))
{
Verify(!Close_Enough(p.x, x1, 100.0f*smaller));
p.x = x0;
onWhatEdge |= 1;
}
else
{
if(Close_Enough(p.x, x1, 100.0f*smaller))
{
p.x = x1;
onWhatEdge |= 4;
}
}
if(Close_Enough(p.z, z0, 100.0f*smaller))
{
Verify(!Close_Enough(p.z, z1, 100.0f*smaller));
p.z = z0;
onWhatEdge |= 8;
}
else
{
if(Close_Enough(p.z, z1, 100.0f*smaller))
{
p.z = z1;
onWhatEdge |= 2;
}
}
return onWhatEdge;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
HFSlimMZ::HFSlimMZ()
{
X = (int)0.0f;
Z = (int)0.0f;
dX = 2.0f;
dY = 0.15f;
dZ = 2.0f;
Offset = 0.0f;
visHeight = 0;
simpleTerrainGroup.SetLength(0);
waterGroup.SetLength(0);
borderPixelFun = 0.0f;
waterTextureName = NULL;
waterTextureRatio = 4.0f;
waterMovieFrames = 1;
waterDetailMovieFrames = 1;
xCenterOffset = 0.0f;
zCenterOffset = 0.0f;
culturalFadeIn = 50.0f;
culturalFadeOut = 80.0f;
interestData = NULL;
mesh = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
HFSlimMZ::~HFSlimMZ()
{
for(int i=0;i<simpleTerrainGroup.GetLength();i++)
{
Unregister_Object(simpleTerrainGroup[i]);
delete simpleTerrainGroup[i];
simpleTerrainGroup[i] = NULL;
Unregister_Object(waterGroup[i]);
delete waterGroup[i];
waterGroup[i] = NULL;
}
simpleTerrainGroup.SetLength(0);
waterGroup.SetLength(0);
interestData.SetLength(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Stuff::ExtentBox
HFSlimMZ::GetExtents()
{
Stuff::ExtentBox ebox;
ebox.minX = GetX(0);
ebox.minZ = GetZ(0);
// ebox.maxX = GetX(X-1);
// ebox.maxZ = GetZ(Z-1);
ebox.maxX = GetX(xDim*256-1);
ebox.maxZ = GetZ(zDim*256-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
HFSlimMZ::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
HFSlimMZ::FillFromImage(Image &image, int smooth)
{
Verify(image.GetBpp()==8);
int
imgX = image.GetWidth(),
imgZ = image.GetHeight();
if((imgX%256 != 0) || (imgZ%256 != 0))
{
if(silentMode==true)
{
fprintf(stderr, "Image width and height has to be a multiple of 256. Program exits !\n");
exit(-1);
}
else
{
STOP(("Image width and height has to be a multiple of 256"));
}
}
xDim = imgX/256;
zDim = imgZ/256;
int xb = 0, zb = 0;
if(!IsPowerOf2(xDim) && xDim!=1)
{
xb = 2*( (xDim/2) + ((xDim%2) ? 1 : 0));
}
else
{
xb = xDim;
}
if(!IsPowerOf2(zDim) && zDim!=1)
{
zb = 2*( (zDim/2) + ((zDim%2) ? 1 : 0));
}
else
{
zb = zDim;
}
if(xb>zb)
{
X = xb*256 + 1;
Z = xb*256 + 1;
}
else
{
X = zb*256 + 1;
Z = zb*256 + 1;
}
Xoffset = (xb>xDim) ? 256 : 0;
Zoffset = (zb>zDim) ? 256 : 0;
field.SetLength(X*Z);
BYTE *ptr;
ptr = (BYTE *)image.Lock();
int i, j;
BYTE c;
#if 1
for(i=0;i<imgZ;i++)
{
for(j=0;j<imgX;j++)
{
field[(i+Zoffset)*X+j+Xoffset] = ptr[(imgZ-i-1)*imgX + imgX-j-1];
}
}
//============== filling in the corners ====================
c = ptr[(imgZ-1)*imgX + imgX-1];
for(i=0;i<Zoffset;i++)
{
for(j=0;j<Xoffset;j++)
{
field[i*X+j] = c;
}
}
c = ptr[(imgZ-1)*imgX + 0];
for(i=0;i<Zoffset;i++)
{
for(j=Xoffset+imgX;j<X;j++)
{
field[i*X+j] = c;
}
}
c = ptr[imgX-1];
for(i=Zoffset+imgZ;i<Z;i++)
{
for(j=0;j<Xoffset;j++)
{
field[i*X+j] = c;
}
}
c = ptr[0];
for(i=Zoffset+imgZ;i<Z;i++)
{
for(j=Xoffset+imgX;j<X;j++)
{
field[i*X+j] = c;
}
}
//============== filling in the sides ====================
for(i=Zoffset;i<Zoffset+imgZ;i++)
{
c = ptr[(imgZ-1-i+Zoffset)*imgX + imgX-1];
for(j=0;j<Xoffset;j++)
{
field[i*X+j] = c;
}
}
for(j=Xoffset;j<Xoffset+imgX;j++)
{
c = ptr[(imgZ-1)*imgX + imgX-1-j+Xoffset];
for(i=0;i<Zoffset;i++)
{
field[i*X+j] = c;
}
}
for(i=Zoffset;i<Zoffset+imgZ;i++)
{
c = ptr[(imgZ-1-i+Zoffset)*imgX];
for(j=Xoffset+imgX;j<X;j++)
{
field[i*X+j] = c;
}
}
for(j=Xoffset;j<Xoffset+imgX;j++)
{
c = ptr[imgX-1-j+Xoffset];
for(i=Zoffset+imgZ;i<Z;i++)
{
field[i*X+j] = c;
}
}
#else
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];
#endif
image.UnLock();
Blur2D(smooth);
/*
Image testImage(X, Z, ITYPE_INDEXED);;
testImage.MakeGrayscalePalette();
ptr = testImage.Lock();
for(i=0;i<X*Z;i++)
{
ptr[i] = field[i];
}
testImage.UnLock();
testImage.SaveGif("c:\\test1.gif");
*/
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
HFSlimMZ::FillInterestDataFromImage(Image &image)
{
Verify(image.GetBpp()>8);
int
imgX = image.GetWidth(),
imgZ = image.GetHeight();
if((imgX%256 != 0) || (imgZ%256 != 0))
{
if(silentMode==true)
{
fprintf(stderr, "Interest data image width and height has to be a multiple of 256. Program exits !\n");
exit(-1);
}
else
{
STOP(("Interest data image width and height has to be a multiple of 256"));
}
}
xDim = imgX/256;
zDim = imgZ/256;
int xb = 0, zb = 0;
if(!IsPowerOf2(xDim) && xDim!=1)
{
xb = 2*( (xDim/2) + ((xDim%2) ? 1 : 0));
}
else
{
xb = xDim;
}
if(!IsPowerOf2(zDim) && zDim!=1)
{
zb = 2*( (zDim/2) + ((zDim%2) ? 1 : 0));
}
else
{
zb = zDim;
}
if(xb>zb)
{
X = xb*256 + 1;
Z = xb*256 + 1;
}
else
{
X = zb*256 + 1;
Z = zb*256 + 1;
}
Xoffset = (xb>xDim) ? 256 : 0;
Zoffset = (zb>zDim) ? 256 : 0;
interestData.SetLength(X*Z);
BYTE *ptr;
ptr = (BYTE *)image.Lock();
int i, j;
BYTE c;
int cd = image.GetBpp()>>3;
#if 1
for(i=0;i<imgZ;i++)
{
for(j=0;j<imgX;j++)
{
interestData[(i+Zoffset)*X+j+Xoffset] = ptr[cd*((imgZ-i-1)*imgX +
imgX-j-1)+1];
}
}
//============== filling in the corners ====================
c = ptr[cd*((imgZ-1)*imgX + imgX-1)+1];
for(i=0;i<Zoffset;i++)
{
for(j=0;j<Xoffset;j++)
{
interestData[i*X+j] = c;
}
}
c = ptr[cd*((imgZ-1)*imgX + 0)+1];
for(i=0;i<Zoffset;i++)
{
for(j=Xoffset+imgX;j<X;j++)
{
interestData[i*X+j] = c;
}
}
c = ptr[cd*(imgX-1)+1];
for(i=Zoffset+imgZ;i<Z;i++)
{
for(j=0;j<Xoffset;j++)
{
interestData[i*X+j] = c;
}
}
c = ptr[cd*(0)+1];
for(i=Zoffset+imgZ;i<Z;i++)
{
for(j=Xoffset+imgX;j<X;j++)
{
interestData[i*X+j] = c;
}
}
//============== filling in the sides ====================
for(i=Zoffset;i<Zoffset+imgZ;i++)
{
c = ptr[cd*((imgZ-1-i+Zoffset)*imgX + imgX-1)+1];
for(j=0;j<Xoffset;j++)
{
interestData[i*X+j] = c;
}
}
for(j=Xoffset;j<Xoffset+imgX;j++)
{
c = ptr[cd*((imgZ-1)*imgX + imgX-1-j+Xoffset)+1];
for(i=0;i<Zoffset;i++)
{
interestData[i*X+j] = c;
}
}
for(i=Zoffset;i<Zoffset+imgZ;i++)
{
c = ptr[cd*((imgZ-1-i+Zoffset)*imgX)+1];
for(j=Xoffset+imgX;j<X;j++)
{
interestData[i*X+j] = c;
}
}
for(j=Xoffset;j<Xoffset+imgX;j++)
{
c = ptr[cd*(imgX-1-j+Xoffset)+1];
for(i=Zoffset+imgZ;i<Z;i++)
{
interestData[i*X+j] = c;
}
}
#else
for(i=0;i<Z-1;i++)
{
for(j=0;j<X-1;j++)
{
interestData[i*X+j] =
ptr[cd*((image.GetHeight()-i-1)*(X-1)+image.GetWidth()-j-1];
}
interestData[i*X+j] = interestData[i*X+j-1];
}
for(j=0;j<X-1;j++)
{
interestData[i*X+j] = interestData[(i-1)*X+j];
}
interestData[i*X+j] = interestData[i*X+j-1];
#endif
image.UnLock();
/*
Image testImage(X, Z, ITYPE_INDEXED);;
testImage.MakeGrayscalePalette();
ptr = testImage.Lock();
for(i=0;i<X*Z;i++)
{
ptr[i] = interestData[i];
}
testImage.UnLock();
testImage.SaveGif("c:\\test_id.gif");
*/
}
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++;
}
void GetFacesCBPrecise(Triangle &tri, void*)
{
Point3D point;
point.x = (float)tri.point1()[0];
point.y = 0.0f;
point.z = (float)tri.point1()[1];
triangleIndices[usedTriangleIndices].v[0] = FindAddPoint(point);
point.x = (float)tri.point3()[0];
point.y = 0.0f;
point.z = (float)tri.point3()[1];
triangleIndices[usedTriangleIndices].v[2] = FindAddPoint(point);
point.x = (float)tri.point2()[0];
point.y = 0.0f;
point.z = (float)tri.point2()[1];
triangleIndices[usedTriangleIndices].v[1] = FindAddPoint(point);
usedTriangleIndices++;
}
#define TERRAIN2_TEST
bool
HFSlimMZ::CreateMesh(
ElementRenderer::ListElement *parent,
int listIndex,
int diffLevel,
DynamicArrayOf<TriangleAbstract*>& tdtrilist,
frameArray *frame,
MLRState *state
)
{
int polygon_count = tdtrilist.GetLength();
if(polygon_count==0)
{
return false;
}
gos_PushCurrentHeap(MLR_Terrain2::PrimitiveHeap);
MLR_Terrain2 *erf_mesh = new MLR_Terrain2;
gos_PopCurrentHeap();
erf_mesh->SetDepthData(maxAllDepth-diffLevel, maxAllDepth);
erf_mesh->SetTileData(tX, tY);
#ifdef BORDERPIXEL
erf_mesh->SetBorderPixel(borderPixelFun);
#endif
// erf_mesh->SetOffset(xOffset, zOffset);
// erf_mesh->SetGrid(xGridSize, zGridSize);
for(int ii=0;ii<8;ii++)
{
erf_mesh->SetFrame(
ii,
(*frame)[ii][0] - xCenterOffset - Xoffset*dX,
(*frame)[ii][1] - zCenterOffset - Zoffset*dZ,
(*frame)[ii][2] - xCenterOffset - Xoffset*dX,
(*frame)[ii][3] - zCenterOffset - Zoffset*dZ
);
}
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]->GetPoint(0).x,
maxx=tdtrilist[0]->GetPoint(0).x,
miny=tdtrilist[0]->GetPoint(0).y,
maxy=tdtrilist[0]->GetPoint(0).y,
minz=tdtrilist[0]->GetPoint(0).z,
maxz=tdtrilist[0]->GetPoint(0).z;
Point3D
center0 = Point3D::Identity,
center1 = Point3D::Identity,
center2 = Point3D::Identity,
center3 = Point3D::Identity;
for(i=0;i<polygon_count;++i)
{
if(tdtrilist[i]->centerValid==false)
{
SPEWALWAYS(("micgaert", "Found invalid center!"));
if(false==tdtrilist[i]->GetSurfaceAreaAndCentroid())
{
continue;
}
}
center3 += tdtrilist[i]->center;
if(tdtrilist[i]->GetPoint(0).x < minx)
{
minX[0] = i;
minX[1] = 0;
minx = tdtrilist[i]->GetPoint(0).x;
} else if(tdtrilist[i]->GetPoint(0).x > maxx)
{
maxX[0] = i;
maxX[1] = 0;
maxx = tdtrilist[i]->GetPoint(0).x;
}
if(tdtrilist[i]->GetPoint(0).y < miny)
{
minY[0] = i;
minY[1] = 0;
miny = tdtrilist[i]->GetPoint(0).y;
} else if(tdtrilist[i]->GetPoint(0).y > maxy)
{
maxY[0] = i;
maxY[1] = 0;
maxy = tdtrilist[i]->GetPoint(0).y;
}
if(tdtrilist[i]->GetPoint(0).z < minz)
{
minZ[0] = i;
minZ[1] = 0;
minz = tdtrilist[i]->GetPoint(0).z;
} else if(tdtrilist[i]->GetPoint(0).z > maxz)
{
maxZ[0] = i;
maxZ[1] = 0;
maxz = tdtrilist[i]->GetPoint(0).z;
}
x = (int)(tdtrilist[i]->GetPoint(0).x/dX);
z = (int)(tdtrilist[i]->GetPoint(0).z/dZ);
vert_id[x + X*z]++;
if(vert_id[x + X*z]==1)
{
center0 += tdtrilist[i]->GetPoint(0);
point_count++;
}
if(tdtrilist[i]->GetPoint(2).x < minx)
{
minX[0] = i;
minX[1] = 2;
minx = tdtrilist[i]->GetPoint(2).x;
} else if(tdtrilist[i]->GetPoint(2).x > maxx)
{
maxX[0] = i;
maxX[1] = 2;
maxx = tdtrilist[i]->GetPoint(2).x;
}
if(tdtrilist[i]->GetPoint(2).y < miny)
{
minY[0] = i;
minY[1] = 2;
miny = tdtrilist[i]->GetPoint(2).y;
} else if(tdtrilist[i]->GetPoint(2).y > maxy)
{
maxY[0] = i;
maxY[1] = 2;
maxy = tdtrilist[i]->GetPoint(2).y;
}
if(tdtrilist[i]->GetPoint(2).z < minz)
{
minZ[0] = i;
minZ[1] = 2;
minz = tdtrilist[i]->GetPoint(2).z;
} else if(tdtrilist[i]->GetPoint(2).z > maxz)
{
maxZ[0] = i;
maxZ[1] = 2;
maxz = tdtrilist[i]->GetPoint(2).z;
}
x = (int)(tdtrilist[i]->GetPoint(2).x/dX);
z = (int)(tdtrilist[i]->GetPoint(2).z/dZ);
vert_id[x + X*z]++;
if(vert_id[x + X*z]==1)
{
center0 += tdtrilist[i]->GetPoint(1);
point_count++;
}
if(tdtrilist[i]->GetPoint(1).x < minx)
{
minX[0] = i;
minX[1] = 1;
minx = tdtrilist[i]->GetPoint(1).x;
} else if(tdtrilist[i]->GetPoint(1).x > maxx)
{
maxX[0] = i;
maxX[1] = 1;
maxx = tdtrilist[i]->GetPoint(1).x;
}
if(tdtrilist[i]->GetPoint(1).y < miny)
{
minY[0] = i;
minY[1] = 1;
miny = tdtrilist[i]->GetPoint(1).y;
} else if(tdtrilist[i]->GetPoint(1).y > maxy)
{
maxY[0] = i;
maxY[1] = 1;
maxy = tdtrilist[i]->GetPoint(1).y;
}
if(tdtrilist[i]->GetPoint(1).z < minz)
{
minZ[0] = i;
minZ[1] = 1;
minz = tdtrilist[i]->GetPoint(1).z;
} else if(tdtrilist[i]->GetPoint(1).z > maxz)
{
maxZ[0] = i;
maxZ[1] = 1;
maxz = tdtrilist[i]->GetPoint(1).z;
}
x = (int)(tdtrilist[i]->GetPoint(1).x/dX);
z = (int)(tdtrilist[i]->GetPoint(1).z/dZ);
vert_id[x + X*z]++;
if(vert_id[x + X*z]==1)
{
center0 += tdtrilist[i]->GetPoint(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]]->GetPoint(maxX[1]), tdtrilist[minX[0]]->GetPoint(minX[1]));
d[0] = v3.GetLengthSquared();
v3.Subtract(tdtrilist[maxY[0]]->GetPoint(maxY[1]), tdtrilist[minY[0]]->GetPoint(minY[1]));
d[1] = v3.GetLengthSquared();
v3.Subtract(tdtrilist[maxZ[0]]->GetPoint(maxZ[1]), tdtrilist[minZ[0]]->GetPoint(minZ[1]));
d[2] = v3.GetLengthSquared();
if(d[0] > d[1])
{
if(d[0]>d[2])
{
center1 = tdtrilist[maxX[0]]->GetPoint(maxX[1]);
center1 += tdtrilist[minX[0]]->GetPoint(minX[1]);
center1 *= 0.5f;
}
else
{
center1 = tdtrilist[maxZ[0]]->GetPoint(maxZ[1]);
center1 += tdtrilist[minZ[0]]->GetPoint(minZ[1]);
center1 *= 0.5f;
}
}
else
{
if(d[1]>d[2])
{
center1 = tdtrilist[maxY[0]]->GetPoint(maxY[1]);
center1 += tdtrilist[minY[0]]->GetPoint(minY[1]);
center1 *= 0.5f;
}
else
{
center1 = tdtrilist[maxZ[0]]->GetPoint(maxZ[1]);
center1 += tdtrilist[minZ[0]]->GetPoint(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)<=(*frame)[maxAllDepth][2] &&
GetX(x)>=(*frame)[maxAllDepth][0]);
Verify(GetZ(z)<=(*frame)[maxAllDepth][3] &&
GetZ(z)>=(*frame)[maxAllDepth][1]);
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;
}
if(nrOfPoints >= Limits::Max_Number_Vertices_Per_Mesh)
{
return false;
}
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;
}
}
}
BYTE *index = new BYTE [polygon_count*3];
int k, l;
for(i=0,l=0;i<polygon_count;i++)
{
k = 0;
x = (int)(tdtrilist[i]->GetPoint(0).x/dX);
z = (int)(tdtrilist[i]->GetPoint(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]->GetPoint(2).x/dX);
z = (int)(tdtrilist[i]->GetPoint(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]->GetPoint(1).x/dX);
z = (int)(tdtrilist[i]->GetPoint(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;
}
}
if(l<3)
{
erf_mesh->DetachReference();
return false;
}
gos_PushCurrentHeap(MLR_Terrain2::PrimitiveHeap);
erf_mesh->SetSubprimitiveLengths(NULL, l/3);
Scalar xOffset2 = xCenterOffset + Xoffset*dX;
Scalar zOffset2 = zCenterOffset + Zoffset*dZ;
for(i=0;i<nrOfPoints;i++)
{
coords[i].x -= xOffset2;
coords[i].z -= zOffset2;
}
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);
gos_PopCurrentHeap();
// delete [] coords;
// delete [] texCoords;
// delete [] index;
erf_mesh->FindFacePlanes();
if(state)
{
erf_mesh->SetReferenceState(*state);
}
else
{
erf_mesh->SetReferenceState(state0);
}
erf_mesh->SetReferenceState(state1, 1);
gos_PushCurrentHeap(ElementRenderer::ShapeElement::s_Heap);
ElementRenderer::ShapeElement* Shape = new ElementRenderer::ShapeElement;
Register_Object(Shape);
gos_PopCurrentHeap();
gos_PushCurrentHeap(MidLevelRenderer::ShapeHeap);
MLRShape *shape = new MLRShape(1);
Register_Object(shape);
gos_PopCurrentHeap();
shape->Add(erf_mesh);
erf_mesh->DetachReference();
Shape->SetMLRShape(shape);
const Point3D *p = NULL;
int nr_of_points = 0;
erf_mesh->GetCoordData(&p, &nr_of_points);
ReadOnlyArrayOf<Point3D> p_array;
p_array.AssignData(p, nr_of_points);
Shape->m_localOBB.ComputeBounds(p_array);
Shape->SetOBBMode();
/*
.localToParent = LinearMatrix4D::Identity;
center.x -= xCenterOffset + Xoffset*dX;
center.z -= zCenterOffset + Zoffset*dZ;
Shape->m_localOBB.localToParent.BuildTranslation(center);
Shape->m_localOBB.sphereRadius = maxRadius;
*/
parent->AttachIndexedChild(listIndex, Shape);
Shape->SetVolumeCullMode();
return true;
}
bool
HFSlimMZ::CreateMesh2(
ElementRenderer::ListElement *parent,
int listIndex,
int diffLevel,
DynamicArrayOf<TriangleAbstract*>& tdtrilist,
frameArray *frame,
MLRState *state,
bool underWater
)
{
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nCreateMesh2 parameters: parent = 0x%08X, listIndex = %d, diffLevel = %d,"
"\n &tdtrilist=0x%08X, frame = 0x%08X, MLRState = 0x%08X, underwater = %s",
(DWORD)(void*)parent, listIndex, diffLevel, (DWORD)(void*)&tdtrilist,
(DWORD)(void*)frame, (DWORD)(void*)state, underWater ? "TRUE" : "FALSE");
#endif
//#undef NON_DEBUG_BUG
int polygon_count = tdtrilist.GetLength();
if(polygon_count==0)
{
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nReturning right away with false");
#endif
return false;
}
// SPEWALWAYS(("micgaert", "#cm0"));
gos_PushCurrentHeap(MLR_Terrain2::PrimitiveHeap);
MLR_Terrain2 *erf_mesh = new MLR_Terrain2;
gos_PopCurrentHeap();
erf_mesh->SetDepthData(maxAllDepth-diffLevel, maxAllDepth);
erf_mesh->SetTileData(tX, tY);
#ifdef BORDERPIXEL
erf_mesh->SetBorderPixel(borderPixelFun);
#endif
// erf_mesh->SetOffset(xOffset, zOffset);
// erf_mesh->SetGrid(xGridSize, zGridSize);
for(int ii=0;ii<8;ii++)
{
erf_mesh->SetFrame(
ii,
(*frame)[ii][0] - xCenterOffset - Xoffset*dX,
(*frame)[ii][1] - zCenterOffset - Zoffset*dZ,
(*frame)[ii][2] - xCenterOffset - Xoffset*dX,
(*frame)[ii][3] - zCenterOffset - Zoffset*dZ
);
}
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);
DynamicArrayOf<Point3D> l_uniquePoints(Limits::Max_Number_Vertices_Per_Mesh);
BYTE *index = new BYTE [polygon_count*3];
int nrOfUniquePoints = 0;
// SPEWALWAYS(("micgaert", "#cm1"));
memset(vert_id.GetData(), 0, vert_id.GetSize());
int i, j, k;
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]->GetPoint(0).x,
maxx=tdtrilist[0]->GetPoint(0).x,
miny=tdtrilist[0]->GetPoint(0).y,
maxy=tdtrilist[0]->GetPoint(0).y,
minz=tdtrilist[0]->GetPoint(0).z,
maxz=tdtrilist[0]->GetPoint(0).z;
Point3D
center0 = Point3D::Identity,
center1 = Point3D::Identity,
center2 = Point3D::Identity,
center3 = Point3D::Identity;
int indexCount = 0;
for(i=0;i<polygon_count;++i)
{
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nPolygon count %d", i);
#endif
if(tdtrilist[i]->centerValid==false)
{
SPEWALWAYS(("micgaert", "Found invalid center"));
}
if(!tdtrilist[i]->GetSurfaceAreaAndCentroid())
{
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\ncontinue %d", i);
#endif
continue;
}
// SPEWALWAYS(("micgaert", "#cmZ.%d %f %f %f", i , tdtrilist[i]->center.x,
//tdtrilist[i]->center.y, tdtrilist[i]->center.z));
center3 += tdtrilist[i]->center;
for(j=0;j<3;j++)
{
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nBegin loop j %d", j);
#endif
if(tdtrilist[i]->GetPoint(j).x < minx)
{
minX[0] = i;
minX[1] = 0;
minx = tdtrilist[i]->GetPoint(j).x;
} else if(tdtrilist[i]->GetPoint(j).x > maxx)
{
maxX[0] = i;
maxX[1] = 0;
maxx = tdtrilist[i]->GetPoint(j).x;
}
if(tdtrilist[i]->GetPoint(j).y < miny)
{
minY[0] = i;
minY[1] = 0;
miny = tdtrilist[i]->GetPoint(j).y;
} else if(tdtrilist[i]->GetPoint(j).y > maxy)
{
maxY[0] = i;
maxY[1] = 0;
maxy = tdtrilist[i]->GetPoint(j).y;
}
if(tdtrilist[i]->GetPoint(j).z < minz)
{
minZ[0] = i;
minZ[1] = 0;
minz = tdtrilist[i]->GetPoint(j).z;
} else if(tdtrilist[i]->GetPoint(j).z > maxz)
{
maxZ[0] = i;
maxZ[1] = 0;
maxz = tdtrilist[i]->GetPoint(j).z;
}
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nSearching on k for unique points");
#endif
for(k=0;k<nrOfUniquePoints;k++)
{
if(Close_Enough(l_uniquePoints[k], tdtrilist[i]->GetPoint(j)))
{
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nBreaking %d", k);
#endif
break;
}
}
if(k==nrOfUniquePoints)
{
center0 += tdtrilist[i]->GetPoint(j);
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nAdding unique point before %d", k);
fprintf(stdout, "\n {%f, %f, %f}", tdtrilist[i]->GetPoint(j).x, tdtrilist[i]->GetPoint(j).y, tdtrilist[i]->GetPoint(j).z );
#endif
l_uniquePoints[nrOfUniquePoints++] = tdtrilist[i]->GetPoint(j);
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nAdding unique point after %d", k);
fprintf(stdout, "\n {%f, %f, %f}", l_uniquePoints[k].x, l_uniquePoints[k].y, l_uniquePoints[k].z );
#endif
// SPEWALWAYS(("micgaert", "#cm#.%d %f %f %f", nrOfUniquePoints-1,
//l_uniquePoints[nrOfUniquePoints-1].x, l_uniquePoints[nrOfUniquePoints-1].y,
//l_uniquePoints[nrOfUniquePoints-1].z));
}
index[indexCount+j] = k;
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nEnd loop j %d", j);
#endif
}
if(
index[indexCount]!=index[indexCount+1] &&
index[indexCount]!=index[indexCount+2] &&
index[indexCount+1]!=index[indexCount+2]
)
{
Swap(index[indexCount+1], index[indexCount+2]);
indexCount+=3;
}
}
if(nrOfUniquePoints==0 || nrOfUniquePoints >= Limits::Max_Number_Vertices_Per_Mesh)
{
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nReturning (no unique points) with false");
#endif
return false;
}
// SPEWALWAYS(("micgaert", "#cm2"));
center0 *= 1.0f/nrOfUniquePoints;
center0.x = GetX(center0.x);
center0.y += Offset;
center0.z = GetZ(center0.z);
// SPEWALWAYS(("micgaert", "#cmB.%f %f %f", center3.x, center3.y,
//center3.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]]->GetPoint(maxX[1]),
tdtrilist[minX[0]]->GetPoint(minX[1]));
d[0] = v3.GetLengthSquared();
v3.Subtract(tdtrilist[maxY[0]]->GetPoint(maxY[1]),
tdtrilist[minY[0]]->GetPoint(minY[1]));
d[1] = v3.GetLengthSquared();
v3.Subtract(tdtrilist[maxZ[0]]->GetPoint(maxZ[1]),
tdtrilist[minZ[0]]->GetPoint(minZ[1]));
d[2] = v3.GetLengthSquared();
if(d[0] > d[1])
{
if(d[0]>d[2])
{
center1 = tdtrilist[maxX[0]]->GetPoint(maxX[1]);
center1 += tdtrilist[minX[0]]->GetPoint(minX[1]);
center1 *= 0.5f;
}
else
{
center1 = tdtrilist[maxZ[0]]->GetPoint(maxZ[1]);
center1 += tdtrilist[minZ[0]]->GetPoint(minZ[1]);
center1 *= 0.5f;
}
}
else
{
if(d[1]>d[2])
{
center1 = tdtrilist[maxY[0]]->GetPoint(maxY[1]);
center1 += tdtrilist[minY[0]]->GetPoint(minY[1]);
center1 *= 0.5f;
}
else
{
center1 = tdtrilist[maxZ[0]]->GetPoint(maxZ[1]);
center1 += tdtrilist[minZ[0]]->GetPoint(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;
Vector2DScalar *texCoords = new Vector2DScalar[nrOfUniquePoints];
Point3D *coords = new Point3D [nrOfUniquePoints];
UnitVector3D sun;
sun = Vector3D(-1.0f, -1.0f, 0.0f);
Scalar radiusSquared = 0.0f,
maxRadius0 = 0.0f,
maxRadius1 = 0.0f,
maxRadius2 = 0.0f,
maxRadius3 = 0.0f;
// SPEWALWAYS(("micgaert", "#cm4 %d", nrOfUniquePoints));
for(i=0;i<nrOfUniquePoints;i++)
{
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nnrOfUniquePoints loop %d of %d", i, nrOfUniquePoints);
#endif
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nnrOfUniquePoints, coords[i].x, y, z {%f, %f, %f} before", l_uniquePoints[i].x, l_uniquePoints[i].y, l_uniquePoints[i].z );
#endif
#ifdef NON_DEBUG_BUG
{
float testfloat1 = 5.0f;
float testfloat2 = testfloat1 + coords[i].x;
fprintf(stdout, "\nTest floating point 1 (%f)", testfloat2);
}
#endif
coords[i] = l_uniquePoints[i];
coords[i].y += Offset;
v3.Subtract(coords[i], center0);
#ifdef NON_DEBUG_BUG
{
float testfloat1 = 5.0f;
float testfloat2 = testfloat1 + coords[i].x;
fprintf(stdout, "\nTest floating point 2 (%f)", testfloat2);
}
#endif
radiusSquared = v3.GetLengthSquared();
maxRadius0 = radiusSquared>maxRadius0 ? radiusSquared:maxRadius0;
v3.Subtract(coords[i], center1);
#ifdef NON_DEBUG_BUG
{
float testfloat1 = 5.0f;
float testfloat2 = testfloat1 + coords[i].x;
fprintf(stdout, "\nTest floating point 3 (%f)", testfloat2);
}
#endif
radiusSquared = v3.GetLengthSquared();
maxRadius1 = radiusSquared>maxRadius1 ? radiusSquared:maxRadius1;
v3.Subtract(coords[i], center2);
#ifdef NON_DEBUG_BUG
{
float testfloat1 = 5.0f;
float testfloat2 = testfloat1 + coords[i].x;
fprintf(stdout, "\nTest floating point 4 (%f)", testfloat2);
}
#endif
radiusSquared = v3.GetLengthSquared();
maxRadius2 = radiusSquared>maxRadius2 ? radiusSquared:maxRadius2;
v3.Subtract(coords[i], center3);
#ifdef NON_DEBUG_BUG
{
float testfloat1 = 5.0f;
float testfloat2 = testfloat1 + coords[i].x;
fprintf(stdout, "\nTest floating point 5 (%f)", testfloat2);
}
#endif
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
#ifdef NON_DEBUG_BUG
{
float testfloat1 = 5.0f;
float testfloat2 = testfloat1 + coords[i].x;
fprintf(stdout, "\nTest floating point 6 (%f)", testfloat2);
}
#endif
}
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nCalculating radius");
#endif
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;
// SPEWALWAYS(("micgaert", "#cm5"));
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;
}
}
}
// SPEWALWAYS(("micgaert", "#cm6"));
if(indexCount<3)
{
erf_mesh->DetachReference();
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nReturning (indexCount < 3) with false");
#endif
return false;
}
gos_PushCurrentHeap(MLR_Terrain2::PrimitiveHeap);
erf_mesh->SetSubprimitiveLengths(NULL, indexCount/3);
Scalar xOffset2 = xCenterOffset + Xoffset*dX;
Scalar zOffset2 = zCenterOffset + Zoffset*dZ;
for(i=0;i<nrOfUniquePoints;i++)
{
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nnrOfUniquePoints loop %d or %d, coords[i].x, y, z {%f, %f, %f} before", i, nrOfUniquePoints, coords[i].x , coords[i].y , coords[i].z );
#endif
coords[i].x -= xOffset2;
coords[i].z -= zOffset2;
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nnrOfUniquePoints loop %d or %d, coords[i].x, y, z {%f, %f, %f} after", i, nrOfUniquePoints, coords[i].x , coords[i].y , coords[i].z );
#endif
}
erf_mesh->SetCoordData(coords, nrOfUniquePoints);
#ifdef TERRAIN2_TEST
erf_mesh->SetCurrentDepth(maxAllDepth-diffLevel);
#else
erf_mesh->SetTexCoordData(texCoords, nrOfPoints);
#endif
erf_mesh->SetIndexData(index, indexCount);
gos_PopCurrentHeap();
// delete [] texCoords;
// delete [] index;
// SPEWALWAYS(("micgaert", "#cm7"));
erf_mesh->FindFacePlanes();
for(i=0;i<indexCount/3;i++)
{
Verify(erf_mesh->GetTrianglePlane(i)->normal.y > Stuff::SMALL);
}
if(state)
{
erf_mesh->SetReferenceState(*state);
}
else
{
erf_mesh->SetReferenceState(state0);
}
if(underWater==true)
{
erf_mesh->SetReferenceState(state2, 1);
}
else
{
erf_mesh->SetReferenceState(state1, 1);
}
// SPEWALWAYS(("micgaert", "#cm8"));
gos_PushCurrentHeap(ElementRenderer::ShapeElement::s_Heap);
ElementRenderer::ShapeElement* Shape = new ElementRenderer::ShapeElement;
Register_Object(Shape);
gos_PopCurrentHeap();
gos_PushCurrentHeap(MidLevelRenderer::ShapeHeap);
MLRShape *shape = new MLRShape(1);
Register_Object(shape);
gos_PopCurrentHeap();
shape->Add(erf_mesh);
erf_mesh->DetachReference();
Shape->SetMLRShape(shape);
const Point3D *p = NULL;
int nr_of_points = 0;
erf_mesh->GetCoordData(&p, &nr_of_points);
ReadOnlyArrayOf<Point3D> p_array;
p_array.AssignData(p, nr_of_points);
Shape->m_localOBB.ComputeBounds(p_array);
Shape->SetOBBMode();
/*
.localToParent = LinearMatrix4D::Identity;
center.x -= xCenterOffset + Xoffset*dX;
center.z -= zCenterOffset + Zoffset*dZ;
Shape->m_localOBB.localToParent.BuildTranslation(center);
Shape->m_localOBB.sphereRadius = maxRadius;
*/
parent->AttachIndexedChild(listIndex, Shape);
Shape->SetVolumeCullMode();
//#define NON_DEBUG_BUG 1
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nReturning true");
#endif
return true;
}
MLRPrimitiveBase*
HFSlimMZ::CreateWater(
Scalar x0, Scalar x1,
Scalar z0, Scalar z1,
Scalar waterLevel
)
{
gos_PushCurrentHeap(MLR_Water::PrimitiveHeap);
MLR_Water *ret = new MLR_Water;
DynamicArrayOf<Point3D> *coords = &ret->dataStore->coords;
Check_Object(coords);
coords->SetLength(25);
DynamicArrayOf<Vector2DScalar> *texCoords = &ret->dataStore->texCoords;
Check_Object(texCoords);
texCoords->SetLength(25);
DynamicArrayOf<ColorType> *colors = &ret->dataStore->colors;
Check_Object(colors);
colors->SetLength(25);
DynamicArrayOf<BYTE> *index = &ret->dataStore->index;
Check_Object(index);
index->SetLength(16*2*3);
int i, j;
for(i=0;i<5;i++)
{
for(j=0;j<5;j++)
{
int offset = i*5+j;
(*coords)[offset] = Point3D( x0+(i*(x1-x0))/4.0f, waterLevel, z0+(j*(z1-z0))/4.0f );
#if COLOR_AS_DWORD>0
(*colors)[offset] = 0xffffffff;
#else
(*colors)[offset] = RGBAColor::White;
#endif
(*texCoords)[offset] = Vector2DScalar(
((*coords)[offset].x-(x1+x0)/2.0f)*(waterTextureRatio/(x1-x0)),
((*coords)[offset].z-(z1+z0)/2.0f)*(waterTextureRatio/(z1-z0))
);
Verify((*texCoords)[offset][0] >= -waterTextureRatio && (*texCoords)[offset][0] <= waterTextureRatio);
Verify((*texCoords)[offset][1] >= -waterTextureRatio && (*texCoords)[offset][0] <= waterTextureRatio);
}
}
int k = 0;
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
// if((i+j)&1)
{
(*index)[k++] = i*5+j;
(*index)[k++] = (i+1)*5+j;
(*index)[k++] = i*5+j+1;
(*index)[k++] = i*5+j+1;
(*index)[k++] = (i+1)*5+j;
(*index)[k++] = (i+1)*5+j+1;
}
/*
else
{
(*index)[k++] = i*5+j;
(*index)[k++] = (i+1)*5+j;
(*index)[k++] = (i+1)*5+j+1;
(*index)[k++] = i*5+j+1;
(*index)[k++] = (i+1)*5+j+1;
(*index)[k++] = i*5+j+1;
}
*/
}
}
ret->SetSubprimitiveLengths(NULL, 16*2);
Scalar xOffset2 = xCenterOffset + Xoffset*dX;
Scalar zOffset2 = zCenterOffset + Zoffset*dZ;
for(i=0;i<25;i++)
{
(*coords)[i].x -= xOffset2;
(*coords)[i].z -= zOffset2;
}
ret->SetCoordData(coords->GetData(), 25);
ret->SetColorData(colors->GetData(), 25);
ret->SetIndexData(index->GetData(), 16*2*3);
ret->SetTexCoordData(texCoords->GetData(), 25);
ret->FindFacePlanes();
MLRState state, detState;
MLRTexture *texture = NULL;
if(waterMovieFrames>1)
{
texture = MLRTexturePool::Instance->AddMovie(waterTextureName, waterMovieFrames, 0.01f);
state.SetMovieTextureOn();
}
else
{
texture = MLRTexturePool::Instance->Add(waterTextureName);
}
Check_Object(texture);
state.SetTextureHandle(texture->GetTextureHandle());
state.SetBackFaceOff();
state.SetDitherOn();
state.SetTextureCorrectionOn();
state.SetZBufferCompareOn();
state.SetZBufferWriteOff();
state.SetAlphaMode(MLRState::AlphaInvAlphaMode);
state.SetPriority(MLRState::AlphaPriority);
ret->SetReferenceState(state);
detState = state;
detState.SetPriority(state.GetPriority()+1);
if(waterDetailInfo.movieFrames>1)
{
texture = MLRTexturePool::Instance->AddMovie(waterDetailInfo.name, waterDetailInfo.movieFrames, 0.01f);
detState.SetMovieTextureOn();
}
else
{
texture = MLRTexturePool::Instance->Add(waterDetailInfo.name);
}
Check_Object(texture);
detState.SetTextureHandle(texture->GetTextureHandle());
ret->SetDetailData(
waterDetailInfo.xOff,
waterDetailInfo.zOff,
waterDetailInfo.xFac,
waterDetailInfo.zFac,
waterDetailInfo.dStart,
waterDetailInfo.dEnd
);
ret->SetReferenceState(detState, 1);
gos_PopCurrentHeap();
return ret;
}
int
primCounter, maxPrims;
bool
HFSlimMZ::BinSort(
ElementRenderer::ListElement *parent,
int index,
int levDiff,
DynamicArrayOf<TriangleAbstract*>& tdtrilist,
int binSize,
frameArray *frame,
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, frame, 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, frame, 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);
gos_PushCurrentHeap(ElementRenderer::ListElement::s_Heap);
ElementRenderer::ListElement *group = new ElementRenderer::ListElement;
Register_Object(group);
group->SetSize(2);
gos_PopCurrentHeap();
//
//----------------------------------
// 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<TriangleAbstract*>
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.GetDistanceTo(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,
frame,
state))
{
Verify(group->GetIndexedElement(0) != NULL);
worked |= 1;
}
if (BinSort(
group,
1,
levDiff,
group_b,
binSize,
frame,
state))
{
Verify(group->GetIndexedElement(1) != NULL);
worked |= 2;
}
if(worked != 3)
{
if(worked == 0)
return false;
ElementRenderer::ListElement *smallgroup = new
ElementRenderer::ListElement;
Register_Object(smallgroup);
smallgroup->SetSize(1);
ElementRenderer::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);
smallgroup->NeedNewBounds();
smallgroup->SetVolumeCullMode();
}
else
{
Check_Object(group);
parent->AttachIndexedChild(index, group);
group->NeedNewBounds();
group->SetVolumeCullMode();
}
//
//-----------------------------------------
// Now set the bounding sphere of the group
//-----------------------------------------
//
return true;
}
bool
HFSlimMZ::BinSort2(
ElementRenderer::ListElement *parent,
int index,
int levDiff,
DynamicArrayOf<TriangleAbstract*>& tdtrilist,
int binSize,
frameArray *frame,
MLRState *state,
bool underWater
)
{
int polygon_count = tdtrilist.GetLength();
if (polygon_count==0)
{
return false;
}
//
//---------------------------------------------------------
// If the polygon mesh is already small enough, just return
//---------------------------------------------------------
//
// SPEWALWAYS(("micgaert", "#bs0"));
if (polygon_count <= binSize)
{
return CreateMesh2(parent, index, levDiff, tdtrilist, frame, state,
underWater);
}
DynamicArrayOf<Point3D> centroids(polygon_count);
unsigned i;
for (i=0; i<polygon_count; ++i)
{
if(tdtrilist[i]->centerValid==false)
{
SPEWALWAYS(("micgaert", "Found invalid center!"));
}
centroids[i] = tdtrilist[i]->center;
}
//
//------------------------------------------------------------------------
// Calculate the dividing plane, and if none can be found, don't do nothin
//------------------------------------------------------------------------
//
// SPEWALWAYS(("micgaert", "#bs1"));
Plane plane;
if (!plane.ComputeBestDividingPlane(centroids))
{
return CreateMesh2(parent, index, levDiff, tdtrilist, frame, state,
underWater);
}
//
//-------------------------------------------------------------------------
// The mesh is too big, so we have to cut it up. Make a group proxy to
// hold the new mesh collection
//-------------------------------------------------------------------------
//
// SPEWALWAYS(("micgaert", "#bs2"));
Check_Object(parent);
gos_PushCurrentHeap(ElementRenderer::ListElement::s_Heap);
ElementRenderer::ListElement *group = new ElementRenderer::ListElement;
Register_Object(group);
group->SetSize(2);
gos_PopCurrentHeap();
//
//----------------------------------
// Set the position of the group
//----------------------------------
//
LinearMatrix4D m;
m = parent->GetLocalToParent();
parent->SetLocalToParent(LinearMatrix4D::Identity);
group->SetLocalToParent(m);
// SPEWALWAYS(("micgaert", "#bs3"));
#if 0
const char *name;
if ((name=parent->GetName())!=NULL)
{
parent->SetName(NULL);
group->SetName(name);
}
#endif
DynamicArrayOf<TriangleAbstract*>
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
//------------------------------------------------------------------
//
// SPEWALWAYS(("micgaert", "#bs4"));
for (i=0; i<polygon_count; ++i)
{
if (plane.GetDistanceTo(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);
// SPEWALWAYS(("micgaert", "#bs5"));
//
//-------------------------------------------------------------------
// Now that the mesh has been split up, Bin_Sort each smaller mesh and
// destroy this mesh
//-------------------------------------------------------------------
//
int worked = 0;
if (BinSort2(
group,
0,
levDiff,
group_a,
binSize,
frame,
state,
underWater))
{
worked |= 1;
}
// SPEWALWAYS(("micgaert", "#bs6"));
if (BinSort2(
group,
1,
levDiff,
group_b,
binSize,
frame,
state,
underWater))
{
worked |= 2;
}
// SPEWALWAYS(("micgaert", "#bs7"));
if(worked != 3)
{
if(worked == 0)
return false;
ElementRenderer::ListElement *smallgroup = new ElementRenderer::ListElement;
Register_Object(smallgroup);
smallgroup->SetSize(1);
ElementRenderer::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);
group = smallgroup;
}
else
{
Check_Object(group);
parent->AttachIndexedChild(index, group);
}
// SPEWALWAYS(("micgaert", "#bs8"));
//
//-----------------------------------------
// Now set the bounding sphere of the group
//-----------------------------------------
//
group->NeedNewBounds();
group->SetVolumeCullMode();
return true;
}
void
HFSlimMZ::OptimizeHField(int depth, int binSize, const char *imagename)
{
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));
map = new DirectMap<real>(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;
Scalar percentage = (Scalar)depth / (X*Z);
mesh = new GreedySubdivision(map, percentage);
if(doInterest==true)
{
Verify(X*Z == interestData.GetLength());
mesh->interest_data.init(X, Z, interestData.GetData());
}
mesh->SetInterestMethod(doInterest);
mesh->SetSquareMethod(doTileCap);
mesh->SetBiggerSquareMethod(doTileCapYovin);
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");
if(doDensityMap==true && imagename!=NULL)
{
Image img;
img.CreateBlank(X, Z);
BYTE *ptr = img.Lock();
for(j=0;j<Z;j++)
{
for(i=0;i<X;i++)
{
ptr[3*(j*X+i)] = mesh->areUsed(Z-j-1, X-i-1);
ptr[3*(j*X+i)+1] = mesh->is_used(X-i-1, Z-j-1);
ptr[3*(j*X+i)+2] = mesh->are_used_32((X-i-1)>>5, (Z-j-1)>>5);
}
}
img.UnLock();
img.SaveTga((LPSTR)imagename);
exit(-1);
}
if(!doPrecise)
{
fprintf(stdout, "You don't care about precision !\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;
if(tdtrilist[i].GetSurfaceAreaAndCentroid()!=true)
{
if(silentMode==true)
{
fprintf(stderr, "Found a triangle with a face normal not pointing up, consider revising map ! Program exits !\n");
exit(-1);
}
else
{
STOP(("Found a triangle with a face normal not pointing up, consider revising map !"));
}
}
}
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) )
{
if(silentMode==true)
{
fprintf(stderr, "Found a triangle with a face normal not pointing up, consider revising map ! Program exits !\n");
exit(-1);
}
else
{
STOP(("Found a triangle with a face normal not pointing up, consider revising map !"));
}
}
/*
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);
}
else
{
fprintf(stdout, "You wanted it precise !");
usedUniquePoints = 0;
usedTriangleIndices = 0;
uniquePoints.SetLength(4*mesh->pointCount());
TriangleStruct::points = uniquePoints.GetData();
triangleIndices.SetLength(8*mesh->pointCount());
mesh->overFaces(GetFacesCBPrecise, NULL);
for(i=0;i<usedUniquePoints;i++)
{
uniquePoints[i].p.y = Offset + static_cast<float>(dY*mesh->eval(
(int)(uniquePoints[i].p.x),
(int)(uniquePoints[i].p.z)
));
uniquePoints[i].p.x *= dX;
uniquePoints[i].p.z *= dZ;
}
for(i=0;i<usedTriangleIndices;i++)
{
triangleIndices[i].GetSurfaceAreaAndCentroid();
}
OptPolyCount = usedTriangleIndices;
if(usedTriangleIndices == 0 || mesh->pointCount() == 0)
{
return;
}
for(i=0;i<usedTriangleIndices;++i)
{
if(! (triangleIndices[i].plane.normal.y > Stuff::SMALL) )
{
if(silentMode==true)
{
fprintf(stderr, "Found a triangle with a face normal not pointing up, consider revising map ! Program exits !\n");
exit(-1);
}
else
{
STOP(("Found a triangle with a face normal not pointing up, consider revising map !"));
}
}
}
fprintf(stdout, "optimized to %d triangles.\n", usedTriangleIndices);
}
}
int brokenTriangles;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
AnalyzeThis(
DynamicArrayOf<TriangleAbstract*> &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]->GetPoint(0).x >= x0n &&
tempTrianglesPtr[k]->GetPoint(0).x <= x1n &&
tempTrianglesPtr[k]->GetPoint(0).z >= z0n &&
tempTrianglesPtr[k]->GetPoint(0).z < z1n
)
{
l++;
}
if( tempTrianglesPtr[k]->GetPoint(1).x >= x0n &&
tempTrianglesPtr[k]->GetPoint(1).x <= x1n &&
tempTrianglesPtr[k]->GetPoint(1).z >= z0n &&
tempTrianglesPtr[k]->GetPoint(1).z <= z1n
)
{
l++;
}
if( tempTrianglesPtr[k]->GetPoint(2).x >= x0n &&
tempTrianglesPtr[k]->GetPoint(2).x <= x1n &&
tempTrianglesPtr[k]->GetPoint(2).z >= z0n &&
tempTrianglesPtr[k]->GetPoint(2).z <= z1n
)
{
l++;
}
if(l==3)
{
in++;
}
else if(l>0)
{
if(tempTrianglesPtr[k]->centerValid==false)
{
SPEWALWAYS(("micgaert", "Found invalid center!"));
}
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
HFSlimMZ::BuildTile(
DynamicArrayOf<TriangleStruct*>& tempTrianglesPtr,
int index,
int depth, int maxdepth,
int numOfTriangles,
DynamicArrayOf<unsigned char>& onOffPoints,
int maxNumOfTrianglesPerMesh,
Scalar xGridOffset,
Scalar zGridOffset,
Scalar xGrid,
Scalar zGrid,
int tileX,
int tileZ
)
{
int orgUsedTriangleIndices = usedTriangleIndices;
int i, j, inCount, newCount = 0, extraTriangles = 0, refused = 0;
int k, l, m;
Scalar x0, z0, x1, z1;
x0 = xGridOffset + tileX*xGrid;
z0 = zGridOffset + tileZ*zGrid;
x1 = x0 + xGrid;
z1 = z0 + zGrid;
for(i=0,j=0;i<numOfTriangles;j+=3,++i)
{
Verify(i<numOfTriangles);
Verify(j<3*numOfTriangles);
/* m = 0;
for(k=0;k<3;k++)
{
if(triangleIndices[i].v[k]==2)
{
m++;
}
}
if(m==1 && (z0==800.0f || z1==800.0f))
{
m--;
}
*/
if(onOffPoints[i] == 0)
{
inCount = 0;
int clipIt[3] = {0, 0, 0}, orIt = 0, addIt = 0xf;
for(k=0;k<3;k++)
{
if(triangleIndices[i].GetPoint(k).x < x0)
{
clipIt[k] |= 1;
}
if(triangleIndices[i].GetPoint(k).x > x1)
{
clipIt[k] |= 4;
}
if(triangleIndices[i].GetPoint(k).z < z0)
{
clipIt[k] |= 8;
}
if(triangleIndices[i].GetPoint(k).z > z1)
{
clipIt[k] |= 2;
}
orIt |= clipIt[k];
addIt &= clipIt[k];
}
if(orIt == 0)
{
onOffPoints[i] = 1;
tempTrianglesPtr[newCount++] = &triangleIndices[i];
uniquePoints[triangleIndices[i].v[0]].Add(&triangleIndices[i], 0);
uniquePoints[triangleIndices[i].v[1]].Add(&triangleIndices[i], 1);
uniquePoints[triangleIndices[i].v[2]].Add(&triangleIndices[i], 2);
}
else if(addIt==0)
{
if(orIt==1 || orIt==2 || orIt==4 || orIt==8)
{
Point3D triangle[3], clipPoints[8];
int index[8];
float angles[8];
for(k=0;k<3;k++)
{
triangle[k] = triangleIndices[i].GetPoint(k);
}
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=0;m<l;m++)
{
index[m] = FindAddPoint(clipPoints[m]);
}
int ba = -1;
float a = -360.0f;
for(m=0;m<l;m++)
{
angles[m] = GetAngle(
uniquePoints[index[(m-1+l)%l]].p,
uniquePoints[index[m]].p,
uniquePoints[index[(m+l)%l]].p
);
if(angles[m] > a)
{
a = angles[m];
ba = m;
}
}
for(m=1;m<l-1;m++)
{
triangleIndices[usedTriangleIndices].v[0] = index[ba];
triangleIndices[usedTriangleIndices].v[1] = index[(ba+m)%l];
triangleIndices[usedTriangleIndices].v[2] = index[(ba+m+1)%l];
if( (triangleIndices[usedTriangleIndices].v[0] !=
triangleIndices[usedTriangleIndices].v[1]) &&
(triangleIndices[usedTriangleIndices].v[0] !=
triangleIndices[usedTriangleIndices].v[2]) &&
(triangleIndices[usedTriangleIndices].v[1] !=
triangleIndices[usedTriangleIndices].v[2]) )
{
uniquePoints[triangleIndices[usedTriangleIndices].v[0]].Add(&triangleIndices[usedTriangleIndices],
0);
uniquePoints[triangleIndices[usedTriangleIndices].v[1]].Add(&triangleIndices[usedTriangleIndices],
1);
uniquePoints[triangleIndices[usedTriangleIndices].v[2]].Add(&triangleIndices[usedTriangleIndices],
2);
triangleIndices[usedTriangleIndices++].GetSurfaceAreaAndCentroid();
}
else
{
refused++;
}
}
}
else
{
int key=0, len[2] = {0, 0};
Point3D clipPoints[2][8];
int index[8];
float angles[8];
int clipMeToo[2][8];
for(k=0;k<3;k++)
{
clipPoints[key][k] = triangleIndices[i].GetPoint(k);
}
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)
);
Verify(len[!key]<7);
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)
);
Verify(len[!key]<7);
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)
);
Verify(len[!key]<7);
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)
);
Verify(len[!key]<7);
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=0;m<len[key];m++)
{
index[m] = FindAddPoint(clipPoints[key][m]);
}
int ba = -1;
float a = -360.0f;
for(m=0;m<len[key];m++)
{
angles[m] = GetAngle(
uniquePoints[index[(m-1+len[key])%len[key]]].p,
uniquePoints[index[m]].p,
uniquePoints[index[(m+len[key])%len[key]]].p
);
if(angles[m] > a)
{
a = angles[m];
ba = m;
}
}
for(m=1;m<len[key]-1;m++)
{
triangleIndices[usedTriangleIndices].v[0] = index[ba];
triangleIndices[usedTriangleIndices].v[1] = index[(ba+m)%len[key]];
triangleIndices[usedTriangleIndices].v[2] = index[(ba+m+1)%len[key]];
if( (triangleIndices[usedTriangleIndices].v[0] !=
triangleIndices[usedTriangleIndices].v[1]) &&
(triangleIndices[usedTriangleIndices].v[0] !=
triangleIndices[usedTriangleIndices].v[2]) &&
(triangleIndices[usedTriangleIndices].v[1] !=
triangleIndices[usedTriangleIndices].v[2]) )
{
uniquePoints[triangleIndices[usedTriangleIndices].v[0]].Add(&triangleIndices[usedTriangleIndices],
0);
uniquePoints[triangleIndices[usedTriangleIndices].v[1]].Add(&triangleIndices[usedTriangleIndices],
1);
uniquePoints[triangleIndices[usedTriangleIndices].v[2]].Add(&triangleIndices[usedTriangleIndices],
2);
triangleIndices[usedTriangleIndices++].GetSurfaceAreaAndCentroid();
}
else
{
refused++;
}
}
}
}
}
}
for(i=orgUsedTriangleIndices;i<usedTriangleIndices;i++)
{
tempTrianglesPtr[newCount++] = &triangleIndices[i];
}
tempTrianglesPtr.SetLength(newCount);
#if _ARMOR
for(i=0,j=0;i<newCount;++i)
{
if(onOffPoints[i] == 0)
{
Verify(tempTrianglesPtr[i]->GetPoint(0).x >= x0);
Verify(tempTrianglesPtr[i]->GetPoint(0).x <= x1);
Verify(tempTrianglesPtr[i]->GetPoint(0).z >= z0);
Verify(tempTrianglesPtr[i]->GetPoint(0).z <= z1);
Verify(tempTrianglesPtr[i]->GetPoint(1).x >= x0);
Verify(tempTrianglesPtr[i]->GetPoint(1).x <= x1);
Verify(tempTrianglesPtr[i]->GetPoint(1).z >= z0);
Verify(tempTrianglesPtr[i]->GetPoint(1).z <= z1);
Verify(tempTrianglesPtr[i]->GetPoint(2).x >= x0);
Verify(tempTrianglesPtr[i]->GetPoint(2).x <= x1);
Verify(tempTrianglesPtr[i]->GetPoint(2).z >= z0);
Verify(tempTrianglesPtr[i]->GetPoint(2).z <= z1);
}
}
#endif
brokenTriangles += newCount;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
HFSlimMZ::CreateTile(
ElementRenderer::ListElement *list,
ElementRenderer::GroupElement *waterList,
DynamicArrayOf<TriangleStruct*>& tempTrianglesPtr,
int index,
int depth, int maxdepth,
int maxNumOfTrianglesPerMesh,
Scalar xGridOffset,
Scalar zGridOffset,
Scalar xGrid,
Scalar zGrid,
int tileX,
int tileZ,
const char *texRoot
)
{
char textureName[1024];
Scalar x0, z0, x1, z1;
x0 = xGridOffset + tileX*xGrid;
z0 = zGridOffset + tileZ*zGrid;
x1 = x0 + xGrid;
z1 = z0 + zGrid;
MLRState state;
gos_PushCurrentHeap(ElementRenderer::GroupElement::s_Heap);
ElementRenderer::GroupElement *group = new ElementRenderer::GroupElement;
Register_Object(group);
list->AttachIndexedChild(index, group);
group->NeedNewBounds();
group->SetVolumeCullMode();
ElementRenderer::ListElement *subList = new ElementRenderer::ListElement;
Register_Object(subList);
subList->SetSize(1);
group->AttachChild(subList);
subList->NeedNewBounds();
subList->SetVolumeCullMode();
gos_PopCurrentHeap();
/*
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);
#if 0
sprintf(textureName, "%s_%1d_%02x%02x",
texRoot,
depth,
(1<<depth) - tileX/(1<<(maxdepth-depth)) - 1,
(1<<depth) - tileZ/(1<<(maxdepth-depth)) - 1
);
#else
sprintf(textureName, "%s_0_0000", texRoot);
#endif
MLRTexture *texture = MLRTexturePool::Instance->Add(textureName);
texture->SetHint(gosHint_AGPMemory | gosHint_DontShrink);
state.SetTextureHandle(texture->GetTextureHandle());
state.SetTextureWrapMode(MLRState::TextureClamp);
/* AnalyzeThis(
tempTrianglesPtr,
x0,
z0,
x1,
z1
);
*/
int i, j;
Scalar frame[8][4];
frame[0][0] = xGridOffset;
frame[0][1] = zGridOffset;
frame[0][2] = xGridOffset + 8*xGrid;
frame[0][3] = zGridOffset + 8*zGrid;
frame[1][0] = xGridOffset + 4*(tileX/4)*xGrid;
frame[1][1] = zGridOffset + 4*(tileZ/4)*zGrid;
frame[1][2] = frame[1][0] + 4*xGrid;
frame[1][3] = frame[1][1] + 4*zGrid;
for(i=2;i<8;i++)
{
frame[i][0] = xGridOffset + tileX*xGrid;
frame[i][1] = zGridOffset + tileZ*zGrid;
frame[i][2] = frame[i][0] + xGrid;
frame[i][3] = frame[i][1] + zGrid;
}
DynamicArrayOf<TriangleAbstract*> group_a;
int usable = tempTrianglesPtr.GetLength();
if(doWater==true)
{
DynamicArrayOf<TriangleStruct> underWaterTriangles(2*usable);
DynamicArrayOf<TriangleStruct> aboveWaterTriangles(2*usable);
WaterPools waterPools(usable, waterLevel);
waterPools.SetTileEdges(x0, x1, z0, z1);
int org=0, aw=0, uw=0;
for(i=0;i<usable;i++)
{
int ac=0, uc=0, ec=0;
for(j=0;j<3;j++)
{
if(tempTrianglesPtr[i]->GetPoint(j).y < waterLevel)
{
uc++;
}
else
{
if(tempTrianglesPtr[i]->GetPoint(j).y > waterLevel)
{
ac++;
}
else
{
ec++;
}
}
}
if(uc==0)
{
for(int q=0;q<3;q++)
{
Verify(tempTrianglesPtr[i]->v[q]<usedUniquePoints);
aboveWaterTriangles[aw].v[q] = tempTrianglesPtr[i]->v[q];
}
aw++;
}
else
{
if(ac==0)
{
for(int q=0;q<3;q++)
{
Verify(tempTrianglesPtr[i]->v[q]<usedUniquePoints);
underWaterTriangles[uw].v[q] = tempTrianglesPtr[i]->v[q];
}
if(underWaterTriangles[uw].GetSurfaceAreaAndCentroid()==true)
{
uw++;
}
}
else
{
Verify(ec<2);
if(ec==0)
{
Point3D v[4];
Vector3D vc;
Scalar l[4];
if(ac>uc)
{
for(j=0;j<3;j++)
{
if(tempTrianglesPtr[i]->GetPoint(j).y < waterLevel)
{
break;
}
}
Verify(j<3);
int next = (j+1)%3;
int prev = (j+2)%3;
int now = j;
v[0].Lerp(
tempTrianglesPtr[i]->GetPoint(next),
tempTrianglesPtr[i]->GetPoint(j),
(waterLevel-tempTrianglesPtr[i]->GetPoint(next).y)/
(tempTrianglesPtr[i]->GetPoint(j).y-tempTrianglesPtr[i]->GetPoint(next).y)
);
Verify(Close_Enough(waterLevel, v[0].y));
v[0].y = waterLevel;
v[1] = tempTrianglesPtr[i]->GetPoint(next);
v[2] = tempTrianglesPtr[i]->GetPoint(prev);
v[3].Lerp(
tempTrianglesPtr[i]->GetPoint(prev),
tempTrianglesPtr[i]->GetPoint(j),
(waterLevel-tempTrianglesPtr[i]->GetPoint(prev).y)/
(tempTrianglesPtr[i]->GetPoint(j).y-tempTrianglesPtr[i]->GetPoint(prev).y)
);
Verify(Close_Enough(waterLevel, v[3].y));
v[3].y = waterLevel;
waterPools.AddEdge(v[0], v[3], tempTrianglesPtr[i]->plane.normal);
vc.Cross(v[1], v[0], v[3]);
l[0] = vc.GetLengthSquared();
vc.Cross(v[2], v[1], v[0]);
l[1] = vc.GetLengthSquared();
vc.Cross(v[3], v[2], v[1]);
l[2] = vc.GetLengthSquared();
vc.Cross(v[0], v[3], v[2]);
l[3] = vc.GetLengthSquared();
int biggest = 0;
for(j=1;j<4;j++)
{
if(l[biggest]<l[j])
{
biggest = j;
}
}
aboveWaterTriangles[aw].v[0] = FindAddPoint(v[biggest]);
aboveWaterTriangles[aw].v[1] = FindAddPoint(v[(biggest+1)%4]);
aboveWaterTriangles[aw].v[2] = FindAddPoint(v[(biggest+2)%4]);
if(aboveWaterTriangles[aw].GetSurfaceAreaAndCentroid()==true)
{
aw++;
}
aboveWaterTriangles[aw].v[0] = FindAddPoint(v[biggest]);
aboveWaterTriangles[aw].v[1] = FindAddPoint(v[(biggest+2)%4]);
aboveWaterTriangles[aw].v[2] = FindAddPoint(v[(biggest+3)%4]);
if(aboveWaterTriangles[aw].GetSurfaceAreaAndCentroid()==true)
{
aw++;
}
underWaterTriangles[uw].v[0] = tempTrianglesPtr[i]->v[now];
Verify(underWaterTriangles[uw].v[0]<usedUniquePoints);
underWaterTriangles[uw].v[1] = FindAddPoint(v[0]);
Verify(underWaterTriangles[uw].v[1]<usedUniquePoints);
underWaterTriangles[uw].v[2] = FindAddPoint(v[3]);
Verify(underWaterTriangles[uw].v[2]<usedUniquePoints);
if(underWaterTriangles[uw].GetSurfaceAreaAndCentroid()==true)
{
uw++;
}
}
else
{
for(j=0;j<3;j++)
{
if(tempTrianglesPtr[i]->GetPoint(j).y > waterLevel)
{
break;
}
}
Verify(j<3);
int next = (j+1)%3;
int prev = (j+2)%3;
int now = j;
v[0].Lerp(
tempTrianglesPtr[i]->GetPoint(next),
tempTrianglesPtr[i]->GetPoint(j),
(waterLevel-tempTrianglesPtr[i]->GetPoint(next).y)/
(tempTrianglesPtr[i]->GetPoint(j).y-tempTrianglesPtr[i]->GetPoint(next).y)
);
Verify(Close_Enough(waterLevel, v[0].y));
v[0].y = waterLevel;
v[1] = tempTrianglesPtr[i]->GetPoint(next);
v[2] = tempTrianglesPtr[i]->GetPoint(prev);
v[3].Lerp(
tempTrianglesPtr[i]->GetPoint(prev),
tempTrianglesPtr[i]->GetPoint(j),
(waterLevel-tempTrianglesPtr[i]->GetPoint(prev).y)/
(tempTrianglesPtr[i]->GetPoint(j).y-tempTrianglesPtr[i]->GetPoint(prev).y)
);
Verify(Close_Enough(waterLevel, v[3].y));
v[3].y = waterLevel;
waterPools.AddEdge(v[0], v[3], tempTrianglesPtr[i]->plane.normal);
vc.Cross(v[1], v[0], v[3]);
l[0] = vc.GetLengthSquared();
vc.Cross(v[2], v[1], v[0]);
l[1] = vc.GetLengthSquared();
vc.Cross(v[3], v[2], v[1]);
l[2] = vc.GetLengthSquared();
vc.Cross(v[0], v[3], v[2]);
l[3] = vc.GetLengthSquared();
int biggest = 0;
for(j=1;j<4;j++)
{
if(l[biggest]<l[j])
{
biggest = j;
}
}
underWaterTriangles[uw].v[0] = FindAddPoint(v[biggest]);
Verify(underWaterTriangles[uw].v[0]<usedUniquePoints);
underWaterTriangles[uw].v[1] = FindAddPoint(v[(biggest+1)%4]);
Verify(underWaterTriangles[uw].v[1]<usedUniquePoints);
underWaterTriangles[uw].v[2] = FindAddPoint(v[(biggest+2)%4]);
Verify(underWaterTriangles[uw].v[2]<usedUniquePoints);
if(underWaterTriangles[uw].GetSurfaceAreaAndCentroid()==true)
{
uw++;
}
underWaterTriangles[uw].v[0] = FindAddPoint(v[biggest]);
Verify(underWaterTriangles[uw].v[0]<usedUniquePoints);
underWaterTriangles[uw].v[1] = FindAddPoint(v[(biggest+2)%4]);
Verify(underWaterTriangles[uw].v[1]<usedUniquePoints);
underWaterTriangles[uw].v[2] = FindAddPoint(v[(biggest+3)%4]);
Verify(underWaterTriangles[uw].v[2]<usedUniquePoints);
if(underWaterTriangles[uw].GetSurfaceAreaAndCentroid())
{
uw++;
}
aboveWaterTriangles[aw].v[0] = tempTrianglesPtr[i]->v[now];
aboveWaterTriangles[aw].v[1] = FindAddPoint(v[0]);
aboveWaterTriangles[aw].v[2] = FindAddPoint(v[3]);
if(aboveWaterTriangles[aw].GetSurfaceAreaAndCentroid()==true)
{
aw++;
}
}
}
else
{
for(j=0;j<3;j++)
{
if(!(tempTrianglesPtr[i]->GetPoint(j).y < waterLevel) &&
!(tempTrianglesPtr[i]->GetPoint(j).y > waterLevel))
{
break;
}
}
Verify(j<3);
int next = (j+1)%3;
int prev = (j+2)%3;
Point3D tempPoint;
if(tempTrianglesPtr[i]->GetPoint(next).y < waterLevel)
{
underWaterTriangles[uw].v[0] = tempTrianglesPtr[i]->v[j];
underWaterTriangles[uw].v[1] = tempTrianglesPtr[i]->v[next];
tempPoint.Lerp(
tempTrianglesPtr[i]->GetPoint(prev),
tempTrianglesPtr[i]->GetPoint(next),
(waterLevel-tempTrianglesPtr[i]->GetPoint(prev).y)/
(tempTrianglesPtr[i]->GetPoint(next).y-tempTrianglesPtr[i]->GetPoint(prev).y)
);
Verify(Close_Enough(waterLevel, tempPoint.y));
tempPoint.y = waterLevel;
underWaterTriangles[uw].v[2] = FindAddPoint(tempPoint);
waterPools.AddEdge(
underWaterTriangles[uw].GetPoint(0),
underWaterTriangles[uw].GetPoint(2),
tempTrianglesPtr[i]->plane.normal
);
if(underWaterTriangles[uw].GetSurfaceAreaAndCentroid()==true)
{
uw++;
}
aboveWaterTriangles[aw].v[0] = tempTrianglesPtr[i]->v[j];
aboveWaterTriangles[aw].v[1] = underWaterTriangles[uw-1].v[2];
aboveWaterTriangles[aw].v[2] = tempTrianglesPtr[i]->v[prev];
if(aboveWaterTriangles[aw].GetSurfaceAreaAndCentroid()==true)
{
aw++;
}
}
else
{
aboveWaterTriangles[aw].v[0] = tempTrianglesPtr[i]->v[j];
aboveWaterTriangles[aw].v[1] = tempTrianglesPtr[i]->v[next];
tempPoint.Lerp(
tempTrianglesPtr[i]->GetPoint(prev),
tempTrianglesPtr[i]->GetPoint(next),
(waterLevel-tempTrianglesPtr[i]->GetPoint(prev).y)/
(tempTrianglesPtr[i]->GetPoint(next).y-tempTrianglesPtr[i]->GetPoint(prev).y)
);
Verify(Close_Enough(waterLevel, tempPoint.y));
tempPoint.y = waterLevel;
aboveWaterTriangles[aw].v[2] = FindAddPoint(tempPoint);
waterPools.AddEdge(
aboveWaterTriangles[aw].GetPoint(0),
aboveWaterTriangles[aw].GetPoint(2),
tempTrianglesPtr[i]->plane.normal
);
if(aboveWaterTriangles[aw].GetSurfaceAreaAndCentroid()==true)
{
aw++;
}
underWaterTriangles[uw].v[0] = tempTrianglesPtr[i]->v[j];
underWaterTriangles[uw].v[1] = aboveWaterTriangles[aw-1].v[2];
underWaterTriangles[uw].v[2] = tempTrianglesPtr[i]->v[prev];
if(underWaterTriangles[uw].GetSurfaceAreaAndCentroid()==true)
{
uw++;
}
}
}
}
}
}
Verify(uw+aw >= usable);
if( (uw==0 && aw==usable) || (aw==0 && uw==usable) )
{
if(uw==usable)
{
gos_PushCurrentHeap(ElementRenderer::ListElement::s_Heap);
subList->SetSize(2);
gos_PopCurrentHeap();
}
group_a.SetLength(tempTrianglesPtr.GetLength());
for (i=0; i<tempTrianglesPtr.GetLength(); ++i)
{
group_a[i] = tempTrianglesPtr[i];
}
if(!BinSort2(
subList,
0,
maxdepth - depth,
group_a,
maxNumOfTrianglesPerMesh,
&frame,
&state,
uw==usable
)
)
{
if(silentMode==true)
{
fprintf(stderr, "Unstable triangle mesh created!");
}
else
{
PAUSE(("Unstable triangle mesh created!"));
}
}
else
{
if(uw==usable)
{
gos_PushCurrentHeap(ElementRenderer::ShapeElement::s_Heap);
ElementRenderer::ShapeElement* Shape = new ElementRenderer::ShapeElement;
Register_Object(Shape);
gos_PopCurrentHeap();
gos_PushCurrentHeap(MidLevelRenderer::ShapeHeap);
MLRShape *shape = new MLRShape(1);
Register_Object(shape);
gos_PopCurrentHeap();
MLRPrimitiveBase *prim = CreateWater( x0, x1, z0, z1, waterLevel);
Check_Object(prim);
shape->Add(prim);
prim->DetachReference();
Shape->SetMLRShape(shape);
const Point3D *p = NULL;
int nr_of_points = 0;
prim->GetCoordData(&p, &nr_of_points);
ReadOnlyArrayOf<Point3D> p_array;
p_array.AssignData(p, nr_of_points);
Shape->m_localOBB.ComputeBounds(p_array);
Shape->SetOBBMode();
/*
Shape->m_localOBB.localToParent = LinearMatrix4D::Identity;
Shape->m_localOBB.localToParent.BuildTranslation(
Point3D(
(x1+x0)*0.5f - xCenterOffset - Xoffset*dX,
waterLevel,
(z1+z0)*0.5f - zCenterOffset - Zoffset*dZ
)
);
Shape->m_localOBB.sphereRadius = 0.5f*xGrid*static_cast<Scalar>(sqrt(2.0f));
Check_Object(Shape);
*/
waterList->AttachChild(Shape);
Shape->SetVolumeCullMode();
subList->AttachIndexedChild(1, Shape);
}
brokenTriangles += usable;
}
}
else
{
// MLRPrimitiveBase *prim = waterPools.LinkEdges();
gos_PushCurrentHeap(ElementRenderer::ListElement::s_Heap);
subList->SetSize(3);
gos_PopCurrentHeap();
tempTrianglesPtr.SetLength(uw);
underWaterTriangles.SetLength(uw);
group_a.SetLength(uw);
for(i=0;i<uw;i++)
{
group_a[i] = &underWaterTriangles[i];
}
if(!BinSort2(
subList,
0,
maxdepth - depth,
group_a,
maxNumOfTrianglesPerMesh,
&frame,
&state,
true
)
)
{
if(silentMode==true)
{
fprintf(stderr, "Unstable triangle mesh created!");
}
else
{
PAUSE(("Unstable triangle mesh created!"));
}
}
else
{
brokenTriangles += uw;
}
tempTrianglesPtr.SetLength(aw);
aboveWaterTriangles.SetLength(aw);
group_a.SetLength(aw);
for(i=0;i<aw;i++)
{
group_a[i] = &aboveWaterTriangles[i];
}
if(!BinSort2(
subList,
1,
maxdepth - depth,
group_a,
maxNumOfTrianglesPerMesh,
&frame,
&state,
false
)
)
{
if(silentMode==true)
{
fprintf(stderr, "Unstable triangle mesh created!");
}
else
{
PAUSE(("Unstable triangle mesh created!"));
}
}
else
{
brokenTriangles += aw;
}
gos_PushCurrentHeap(ElementRenderer::ShapeElement::s_Heap);
ElementRenderer::ShapeElement* Shape = new ElementRenderer::ShapeElement;
Register_Object(Shape);
gos_PopCurrentHeap();
gos_PushCurrentHeap(MidLevelRenderer::ShapeHeap);
MLRShape *shape = new MLRShape(1);
Register_Object(shape);
gos_PopCurrentHeap();
MLRPrimitiveBase *prim = CreateWater( x0, x1, z0, z1, waterLevel);;
Check_Object(prim);
shape->Add(prim);
prim->DetachReference();
Shape->SetMLRShape(shape);
const Point3D *p = NULL;
int nr_of_points = 0;
prim->GetCoordData(&p, &nr_of_points);
ReadOnlyArrayOf<Point3D> p_array;
p_array.AssignData(p, nr_of_points);
Shape->m_localOBB.ComputeBounds(p_array);
Shape->SetOBBMode();
/*
Shape->m_localOBB.localToParent = LinearMatrix4D::Identity;
Shape->m_localOBB.localToParent.BuildTranslation(
Point3D(
(x1+x0)*0.5f - xCenterOffset - Xoffset*dX,
waterLevel,
(z1+z0)*0.5f - zCenterOffset - Zoffset*dZ
)
);
Shape->m_localOBB.sphereRadius = 0.5f*xGrid*static_cast<Scalar>(sqrt(2.0f));
Check_Object(Shape);
*/
waterList->AttachChild(Shape);
Shape->SetVolumeCullMode();
subList->AttachIndexedChild(2, Shape);
}
/*
bool px0z0, px0z1, px1z0, px1z1;
px0z0 = waterLevel < mesh->eval( (int)(x0/dX), (int)(z0/dZ) );
px0z1 = waterLevel < mesh->eval( (int)(x0/dX), (int)(z1/dZ) );
px1z0 = waterLevel < mesh->eval( (int)(x1/dX), (int)(z0/dZ) );
px1z1 = waterLevel < mesh->eval( (int)(x1/dX), (int)(z1/dZ) );
if(waterPools.waterEdgePointCount==0)
{
if(px0z0 == false)
{
Verify(px0z0==px0z1 && px0z0==px1z0 && px0z0==px1z1);
// found water
}
}
*/
}
else
{
group_a.SetLength(tempTrianglesPtr.GetLength());
for (i=0; i<tempTrianglesPtr.GetLength(); ++i)
{
group_a[i] = tempTrianglesPtr[i];
}
if(!BinSort(
subList,
0,
maxdepth - depth,
group_a,
maxNumOfTrianglesPerMesh,
&frame,
&state
)
)
{
if(silentMode==true)
{
fprintf(stderr, "Unstable triangle mesh created!");
}
else
{
PAUSE(("Unstable triangle mesh created!"));
}
}
}
group->Sync();
group->LockBounds();
group->SetNeverCullMode();
subList->LockBounds();
subList->SetNeverCullMode();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
HFSlimMZ::BuildTile(
ElementRenderer::ListElement *list,
ElementRenderer::GroupElement *waterList,
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<TriangleAbstract*> 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;
gos_PushCurrentHeap(ElementRenderer::GroupElement::s_Heap);
ElementRenderer::GroupElement *group = new ElementRenderer::GroupElement;
Register_Object(group);
list->AttachIndexedChild(index, group);
group->NeedNewBounds();
group->SetVolumeCullMode();
gos_PopCurrentHeap();
gos_PushCurrentHeap(ElementRenderer::ListElement::s_Heap);
ElementRenderer::ListElement *subList = new ElementRenderer::ListElement;
Register_Object(subList);
subList->SetSize(1);
group->AttachChild(subList);
subList->NeedNewBounds();
subList->SetVolumeCullMode();
gos_PopCurrentHeap();
/*
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);
#if 0
sprintf(textureName, "%s_%1d_%02x%02x",
texRoot,
depth,
(1<<depth) - tileX/(1<<(maxdepth-depth)) - 1,
(1<<depth) - tileZ/(1<<(maxdepth-depth)) - 1
);
#else
sprintf(textureName, "%s_0_0000", texRoot);
#endif
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]->GetPoint(0).x < x0)
{
clipIt[0] |= 1;
}
if(toSortTriangles[i]->GetPoint(0).x > x1)
{
clipIt[0] |= 4;
}
if(toSortTriangles[i]->GetPoint(0).z < z0)
{
clipIt[0] |= 8;
}
if(toSortTriangles[i]->GetPoint(0).z > z1)
{
clipIt[0] |= 2;
}
orIt |= clipIt[0];
addIt &= clipIt[0];
if(toSortTriangles[i]->GetPoint(1).x < x0)
{
clipIt[1] |= 1;
}
if(toSortTriangles[i]->GetPoint(1).x > x1)
{
clipIt[1] |= 4;
}
if(toSortTriangles[i]->GetPoint(1).z < z0)
{
clipIt[1] |= 8;
}
if(toSortTriangles[i]->GetPoint(1).z > z1)
{
clipIt[1] |= 2;
}
orIt |= clipIt[1];
addIt &= clipIt[1];
if(toSortTriangles[i]->GetPoint(2).x < x0)
{
clipIt[2] |= 1;
}
if(toSortTriangles[i]->GetPoint(2).x > x1)
{
clipIt[2] |= 4;
}
if(toSortTriangles[i]->GetPoint(2).z < z0)
{
clipIt[2] |= 8;
}
if(toSortTriangles[i]->GetPoint(2).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) )
{
if(silentMode==true)
{
fprintf(stderr, "Found a triangle with a face normal not pointing up, consider revising map ! Program exits !\n");
exit(-1);
}
else
{
STOP(("Found a triangle with a face normal not pointing up, consider revising map !"));
}
}
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]->GetPoint(0).x;
triangle[0].y = toSortTriangles[i]->GetPoint(0).y;
triangle[0].z = toSortTriangles[i]->GetPoint(0).z;
triangle[1].x = toSortTriangles[i]->GetPoint(1).x;
triangle[1].y = toSortTriangles[i]->GetPoint(1).y;
triangle[1].z = toSortTriangles[i]->GetPoint(1).z;
triangle[2].x = toSortTriangles[i]->GetPoint(2).x;
triangle[2].y = toSortTriangles[i]->GetPoint(2).y;
triangle[2].z = toSortTriangles[i]->GetPoint(2).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);
if(tempTriangles[extraTriangles].GetSurfaceAreaAndCentroid() == true)
{
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]->GetPoint(0).x;
clipPoints[key][0].y = toSortTriangles[i]->GetPoint(0).y;
clipPoints[key][0].z = toSortTriangles[i]->GetPoint(0).z;
clipPoints[key][1].x = toSortTriangles[i]->GetPoint(1).x;
clipPoints[key][1].y = toSortTriangles[i]->GetPoint(1).y;
clipPoints[key][1].z = toSortTriangles[i]->GetPoint(1).z;
clipPoints[key][2].x = toSortTriangles[i]->GetPoint(2).x;
clipPoints[key][2].y = toSortTriangles[i]->GetPoint(2).y;
clipPoints[key][2].z = toSortTriangles[i]->GetPoint(2).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
);
if(tempTriangles[extraTriangles].GetSurfaceAreaAndCentroid() == true)
{
tempTrianglesPtr[newCount++] = &tempTriangles[extraTriangles];
extraTriangles++;
}
}
}
}
}
}
// SPEWALWAYS(("micgaert", "#1"));
// tempTriangles.SetLength(extraTriangles);
tempTrianglesPtr.SetLength(newCount);
#if _ARMOR
for(i=0,j=0;i<newCount;++i)
{
if(onOffPoints[i] == 0)
{
Verify(tempTrianglesPtr[i]->GetPoint(0).x >= x0);
Verify(tempTrianglesPtr[i]->GetPoint(0).x <= x1);
Verify(tempTrianglesPtr[i]->GetPoint(0).z >= z0);
Verify(tempTrianglesPtr[i]->GetPoint(0).z <= z1);
Verify(tempTrianglesPtr[i]->GetPoint(1).x >= x0);
Verify(tempTrianglesPtr[i]->GetPoint(1).x <= x1);
Verify(tempTrianglesPtr[i]->GetPoint(1).z >= z0);
Verify(tempTrianglesPtr[i]->GetPoint(1).z <= z1);
Verify(tempTrianglesPtr[i]->GetPoint(2).x >= x0);
Verify(tempTrianglesPtr[i]->GetPoint(2).x <= x1);
Verify(tempTrianglesPtr[i]->GetPoint(2).z >= z0);
Verify(tempTrianglesPtr[i]->GetPoint(2).z <= z1);
}
}
#endif
if(newCount > 0)
{
AnalyzeThis(
tempTrianglesPtr,
x0,
z0,
x1,
z1
);
int i = 1<<(maxdepth - depth);
frameArray frame;
frame[0][0] = xGridOffset;
frame[0][1] = zGridOffset;
frame[0][2] = xGridOffset + 8*xGrid;
frame[0][3] = zGridOffset + 8*zGrid;
frame[1][0] = xGridOffset + 4*(tileX/4)*xGrid;
frame[1][1] = zGridOffset + 4*(tileZ/4)*zGrid;
frame[1][2] = frame[1][0] + 4*xGrid;
frame[1][3] = frame[1][1] + 4*zGrid;
for(i=2;i<8;i++)
{
frame[i][0] = xGridOffset + tileX*xGrid;
frame[i][1] = zGridOffset + tileZ*zGrid;
frame[i][2] = frame[i][0] + xGrid;
frame[i][3] = frame[i][1] + zGrid;
}
// SPEWALWAYS(("micgaert", "#2"));
if(doWater==true)
{
DynamicArrayOf<ToDrawTriangle> underWaterTriangles(2*newCount);
DynamicArrayOf<ToDrawTriangle> aboveWaterTriangles(2*newCount);
WaterPools waterPools(newCount, waterLevel);
waterPools.SetTileEdges(x0, x1, z0, z1);
int org=0, aw=0, uw=0;
for(i=0;i<newCount;i++)
{
int ac=0, uc=0, ec=0;
if(tempTrianglesPtr[i]->GetPoint(0).y < waterLevel)
{
uc++;
}
else
{
if(tempTrianglesPtr[i]->GetPoint(0).y > waterLevel)
{
ac++;
}
else
{
ec++;
}
}
if(tempTrianglesPtr[i]->GetPoint(1).y < waterLevel)
{
uc++;
}
else
{
if(tempTrianglesPtr[i]->GetPoint(1).y > waterLevel)
{
ac++;
}
else
{
ec++;
}
}
if(tempTrianglesPtr[i]->GetPoint(2).y < waterLevel)
{
uc++;
}
else
{
if(tempTrianglesPtr[i]->GetPoint(2).y > waterLevel)
{
ac++;
}
else
{
ec++;
}
}
if(uc==0)
{
for(int q=0;q<3;q++)
{
aboveWaterTriangles[aw].v[q] = tempTrianglesPtr[i]->GetPoint(q);
}
if(aboveWaterTriangles[aw].GetSurfaceAreaAndCentroid()==true)
{
aw++;
for(j=0;j<3;j++)
{
Verify(aboveWaterTriangles[aw-1].v[j].x<=frame[maxAllDepth][2] &&
aboveWaterTriangles[aw-1].v[j].x>=frame[maxAllDepth][0]);
Verify(aboveWaterTriangles[aw-1].v[j].z<=frame[maxAllDepth][3] &&
aboveWaterTriangles[aw-1].v[j].z>=frame[maxAllDepth][1]);
}
}
}
else
{
if(ac==0)
{
for(int q=0;q<3;q++)
{
underWaterTriangles[uw].v[q] = tempTrianglesPtr[i]->GetPoint(q);
}
if(underWaterTriangles[uw].GetSurfaceAreaAndCentroid()==true)
{
uw++;
for(j=0;j<3;j++)
{
Verify(underWaterTriangles[uw-1].v[j].x<=frame[maxAllDepth][2] &&
underWaterTriangles[uw-1].v[j].x>=frame[maxAllDepth][0]);
Verify(underWaterTriangles[uw-1].v[j].z<=frame[maxAllDepth][3] &&
underWaterTriangles[uw-1].v[j].z>=frame[maxAllDepth][1]);
}
}
}
else
{
Verify(ec<2);
if(ec==0)
{
Point3D v[4];
Vector3D vc;
Scalar l[4];
if(ac>uc)
{
for(j=0;j<3;j++)
{
if(tempTrianglesPtr[i]->GetPoint(j).y < waterLevel)
{
break;
}
}
Verify(j<3);
int next = (j+1)%3;
int prev = (j+2)%3;
int now = j;
v[0].Lerp(
tempTrianglesPtr[i]->GetPoint(next),
tempTrianglesPtr[i]->GetPoint(j),
(waterLevel-tempTrianglesPtr[i]->GetPoint(next).y)/
(tempTrianglesPtr[i]->GetPoint(j).y-tempTrianglesPtr[i]->GetPoint(next).y)
);
Verify(Close_Enough(waterLevel, v[0].y));
v[0].y = waterLevel;
v[1] = tempTrianglesPtr[i]->GetPoint(next);
v[2] = tempTrianglesPtr[i]->GetPoint(prev);
v[3].Lerp(
tempTrianglesPtr[i]->GetPoint(prev),
tempTrianglesPtr[i]->GetPoint(j),
(waterLevel-tempTrianglesPtr[i]->GetPoint(prev).y)/
(tempTrianglesPtr[i]->GetPoint(j).y-tempTrianglesPtr[i]->GetPoint(prev).y)
);
Verify(Close_Enough(waterLevel, v[3].y));
v[3].y = waterLevel;
waterPools.AddEdge(v[0], v[3], tempTrianglesPtr[i]->plane.normal);
vc.Cross(v[1], v[0], v[3]);
l[0] = vc.GetLengthSquared();
vc.Cross(v[2], v[1], v[0]);
l[1] = vc.GetLengthSquared();
vc.Cross(v[3], v[2], v[1]);
l[2] = vc.GetLengthSquared();
vc.Cross(v[0], v[3], v[2]);
l[3] = vc.GetLengthSquared();
int biggest = 0;
for(j=1;j<4;j++)
{
if(l[biggest]<l[j])
{
biggest = j;
}
}
aboveWaterTriangles[aw].v[0] = v[biggest];
aboveWaterTriangles[aw].v[1] = v[(biggest+1)%4];
aboveWaterTriangles[aw].v[2] = v[(biggest+2)%4];
if(aboveWaterTriangles[aw].GetSurfaceAreaAndCentroid()==true)
{
for(j=0;j<3;j++)
{
Verify(aboveWaterTriangles[aw].v[j].x<=frame[maxAllDepth][2] &&
aboveWaterTriangles[aw].v[j].x>=frame[maxAllDepth][0]);
Verify(aboveWaterTriangles[aw].v[j].z<=frame[maxAllDepth][3] &&
aboveWaterTriangles[aw].v[j].z>=frame[maxAllDepth][1]);
}
aw++;
}
aboveWaterTriangles[aw].v[0] = v[biggest];
aboveWaterTriangles[aw].v[1] = v[(biggest+2)%4];
aboveWaterTriangles[aw].v[2] = v[(biggest+3)%4];
if(aboveWaterTriangles[aw].GetSurfaceAreaAndCentroid()==true)
{
for(j=0;j<3;j++)
{
Verify(aboveWaterTriangles[aw].v[j].x<=frame[maxAllDepth][2] &&
aboveWaterTriangles[aw].v[j].x>=frame[maxAllDepth][0]);
Verify(aboveWaterTriangles[aw].v[j].z<=frame[maxAllDepth][3] &&
aboveWaterTriangles[aw].v[j].z>=frame[maxAllDepth][1]);
}
aw++;
}
underWaterTriangles[uw].v[0] = tempTrianglesPtr[i]->GetPoint(now);
underWaterTriangles[uw].v[1] = v[0];
underWaterTriangles[uw].v[2] = v[3];
if(underWaterTriangles[uw].GetSurfaceAreaAndCentroid()==true)
{
for(j=0;j<3;j++)
{
Verify(underWaterTriangles[uw].v[j].x<=frame[maxAllDepth][2] &&
underWaterTriangles[uw].v[j].x>=frame[maxAllDepth][0]);
Verify(underWaterTriangles[uw].v[j].z<=frame[maxAllDepth][3] &&
underWaterTriangles[uw].v[j].z>=frame[maxAllDepth][1]);
}
uw++;
}
}
else
{
for(j=0;j<3;j++)
{
if(tempTrianglesPtr[i]->GetPoint(j).y > waterLevel)
{
break;
}
}
Verify(j<3);
int next = (j+1)%3;
int prev = (j+2)%3;
int now = j;
v[0].Lerp(
tempTrianglesPtr[i]->GetPoint(next),
tempTrianglesPtr[i]->GetPoint(j),
(waterLevel-tempTrianglesPtr[i]->GetPoint(next).y)/
(tempTrianglesPtr[i]->GetPoint(j).y-tempTrianglesPtr[i]->GetPoint(next).y)
);
Verify(Close_Enough(waterLevel, v[0].y));
v[0].y = waterLevel;
v[1] = tempTrianglesPtr[i]->GetPoint(next);
v[2] = tempTrianglesPtr[i]->GetPoint(prev);
v[3].Lerp(
tempTrianglesPtr[i]->GetPoint(prev),
tempTrianglesPtr[i]->GetPoint(j),
(waterLevel-tempTrianglesPtr[i]->GetPoint(prev).y)/
(tempTrianglesPtr[i]->GetPoint(j).y-tempTrianglesPtr[i]->GetPoint(prev).y)
);
Verify(Close_Enough(waterLevel, v[3].y));
v[3].y = waterLevel;
waterPools.AddEdge(v[0], v[3], tempTrianglesPtr[i]->plane.normal);
vc.Cross(v[1], v[0], v[3]);
l[0] = vc.GetLengthSquared();
vc.Cross(v[2], v[1], v[0]);
l[1] = vc.GetLengthSquared();
vc.Cross(v[3], v[2], v[1]);
l[2] = vc.GetLengthSquared();
vc.Cross(v[0], v[3], v[2]);
l[3] = vc.GetLengthSquared();
int biggest = 0;
for(j=1;j<4;j++)
{
if(l[biggest]<l[j])
{
biggest = j;
}
}
underWaterTriangles[uw].v[0] = v[biggest];
underWaterTriangles[uw].v[1] = v[(biggest+1)%4];
underWaterTriangles[uw].v[2] = v[(biggest+2)%4];
if(underWaterTriangles[uw].GetSurfaceAreaAndCentroid()==true)
{
for(j=0;j<3;j++)
{
Verify(underWaterTriangles[uw].v[j].x<=frame[maxAllDepth][2] &&
underWaterTriangles[uw].v[j].x>=frame[maxAllDepth][0]);
Verify(underWaterTriangles[uw].v[j].z<=frame[maxAllDepth][3] &&
underWaterTriangles[uw].v[j].z>=frame[maxAllDepth][1]);
}
uw++;
}
underWaterTriangles[uw].v[0] = v[biggest];
underWaterTriangles[uw].v[1] = v[(biggest+2)%4];
underWaterTriangles[uw].v[2] = v[(biggest+3)%4];
if(underWaterTriangles[uw].GetSurfaceAreaAndCentroid())
{
for(j=0;j<3;j++)
{
Verify(underWaterTriangles[uw].v[j].x<=frame[maxAllDepth][2] &&
underWaterTriangles[uw].v[j].x>=frame[maxAllDepth][0]);
Verify(underWaterTriangles[uw].v[j].z<=frame[maxAllDepth][3] &&
underWaterTriangles[uw].v[j].z>=frame[maxAllDepth][1]);
}
uw++;
}
aboveWaterTriangles[aw].v[0] = tempTrianglesPtr[i]->GetPoint(now);
aboveWaterTriangles[aw].v[1] = v[0];
aboveWaterTriangles[aw].v[2] = v[3];
if(aboveWaterTriangles[aw].GetSurfaceAreaAndCentroid()==true)
{
for(j=0;j<3;j++)
{
Verify(aboveWaterTriangles[aw].v[j].x<=frame[maxAllDepth][2] &&
aboveWaterTriangles[aw].v[j].x>=frame[maxAllDepth][0]);
Verify(aboveWaterTriangles[aw].v[j].z<=frame[maxAllDepth][3] &&
aboveWaterTriangles[aw].v[j].z>=frame[maxAllDepth][1]);
}
aw++;
}
}
}
else
{
for(j=0;j<3;j++)
{
if(!(tempTrianglesPtr[i]->GetPoint(j).y < waterLevel) &&
!(tempTrianglesPtr[i]->GetPoint(j).y > waterLevel))
{
break;
}
}
Verify(j<3);
int next = (j+1)%3;
int prev = (j+2)%3;
if(tempTrianglesPtr[i]->GetPoint(next).y < waterLevel)
{
underWaterTriangles[uw].v[0] = tempTrianglesPtr[i]->GetPoint(j);
underWaterTriangles[uw].v[1] = tempTrianglesPtr[i]->GetPoint(next);
underWaterTriangles[uw].v[2].Lerp(
tempTrianglesPtr[i]->GetPoint(prev),
tempTrianglesPtr[i]->GetPoint(next),
(waterLevel-tempTrianglesPtr[i]->GetPoint(prev).y)/
(tempTrianglesPtr[i]->GetPoint(next).y-tempTrianglesPtr[i]->GetPoint(prev).y)
);
Verify(Close_Enough(waterLevel, underWaterTriangles[uw].v[2].y));
underWaterTriangles[uw].v[2].y = waterLevel;
waterPools.AddEdge(
underWaterTriangles[uw].v[0],
underWaterTriangles[uw].v[2],
tempTrianglesPtr[i]->plane.normal
);
if(underWaterTriangles[uw].GetSurfaceAreaAndCentroid()==true)
{
for(j=0;j<3;j++)
{
Verify(underWaterTriangles[uw].v[j].x<=frame[maxAllDepth][2] &&
underWaterTriangles[uw].v[j].x>=frame[maxAllDepth][0]);
Verify(underWaterTriangles[uw].v[j].z<=frame[maxAllDepth][3] &&
underWaterTriangles[uw].v[j].z>=frame[maxAllDepth][1]);
}
uw++;
}
aboveWaterTriangles[aw].v[0] = tempTrianglesPtr[i]->GetPoint(j);
aboveWaterTriangles[aw].v[1] = underWaterTriangles[uw-1].v[2];
aboveWaterTriangles[aw].v[2] = tempTrianglesPtr[i]->GetPoint(prev);
if(aboveWaterTriangles[aw].GetSurfaceAreaAndCentroid()==true)
{
for(j=0;j<3;j++)
{
Verify(aboveWaterTriangles[aw].v[j].x<=frame[maxAllDepth][2] &&
aboveWaterTriangles[aw].v[j].x>=frame[maxAllDepth][0]);
Verify(aboveWaterTriangles[aw].v[j].z<=frame[maxAllDepth][3] &&
aboveWaterTriangles[aw].v[j].z>=frame[maxAllDepth][1]);
}
aw++;
}
}
else
{
aboveWaterTriangles[aw].v[0] = tempTrianglesPtr[i]->GetPoint(j);
aboveWaterTriangles[aw].v[1] = tempTrianglesPtr[i]->GetPoint(next);
aboveWaterTriangles[aw].v[2].Lerp(
tempTrianglesPtr[i]->GetPoint(prev),
tempTrianglesPtr[i]->GetPoint(next),
(waterLevel-tempTrianglesPtr[i]->GetPoint(prev).y)/
(tempTrianglesPtr[i]->GetPoint(next).y-tempTrianglesPtr[i]->GetPoint(prev).y)
);
Verify(Close_Enough(waterLevel, aboveWaterTriangles[aw].v[2].y));
aboveWaterTriangles[aw].v[2].y = waterLevel;
waterPools.AddEdge(
aboveWaterTriangles[aw].v[0],
aboveWaterTriangles[aw].v[2],
tempTrianglesPtr[i]->plane.normal
);
if(aboveWaterTriangles[aw].GetSurfaceAreaAndCentroid()==true)
{
for(j=0;j<3;j++)
{
Verify(aboveWaterTriangles[aw].v[j].x<=frame[maxAllDepth][2] &&
aboveWaterTriangles[aw].v[j].x>=frame[maxAllDepth][0]);
Verify(aboveWaterTriangles[aw].v[j].z<=frame[maxAllDepth][3] &&
aboveWaterTriangles[aw].v[j].z>=frame[maxAllDepth][1]);
}
aw++;
}
underWaterTriangles[uw].v[0] = tempTrianglesPtr[i]->GetPoint(j);
underWaterTriangles[uw].v[1] = aboveWaterTriangles[aw-1].v[2];
underWaterTriangles[uw].v[2] = tempTrianglesPtr[i]->GetPoint(prev);
if(underWaterTriangles[uw].GetSurfaceAreaAndCentroid()==true)
{
for(j=0;j<3;j++)
{
Verify(underWaterTriangles[uw].v[j].x<=frame[maxAllDepth][2] &&
underWaterTriangles[uw].v[j].x>=frame[maxAllDepth][0]);
Verify(underWaterTriangles[uw].v[j].z<=frame[maxAllDepth][3] &&
underWaterTriangles[uw].v[j].z>=frame[maxAllDepth][1]);
}
uw++;
}
}
}
}
}
}
// SPEWALWAYS(("micgaert", "#3"));
Verify(uw+aw >= newCount);
if( (uw==0 && aw==newCount) || (aw==0 && uw==newCount) )
{
// SPEWALWAYS(("micgaert", "#3.5"));
if(uw==newCount)
{
gos_PushCurrentHeap(ElementRenderer::ListElement::s_Heap);
subList->SetSize(2);
gos_PopCurrentHeap();
}
if(!BinSort2(
subList,
0,
maxdepth - depth,
tempTrianglesPtr,
maxNumOfTrianglesPerMesh,
&frame,
&state,
uw==newCount
)
)
{
if(silentMode==true)
{
fprintf(stderr, "Unstable triangle mesh created!");
}
else
{
PAUSE(("Unstable triangle mesh created!"));
}
}
else
{
// SPEWALWAYS(("micgaert", "#5"));
if(uw==newCount)
{
gos_PushCurrentHeap(ElementRenderer::ShapeElement::s_Heap);
ElementRenderer::ShapeElement* Shape = new
ElementRenderer::ShapeElement;
Register_Object(Shape);
gos_PopCurrentHeap();
gos_PushCurrentHeap(MidLevelRenderer::ShapeHeap);
MLRShape *shape = new MLRShape(1);
Register_Object(shape);
gos_PopCurrentHeap();
MLRPrimitiveBase *prim = CreateWater( x0, x1, z0, z1, waterLevel);
Check_Object(prim);
shape->Add(prim);
prim->DetachReference();
Shape->SetMLRShape(shape);
const Point3D *p = NULL;
int nr_of_points = 0;
prim->GetCoordData(&p, &nr_of_points);
ReadOnlyArrayOf<Point3D> p_array;
p_array.AssignData(p, nr_of_points);
Shape->m_localOBB.ComputeBounds(p_array);
Shape->SetOBBMode();
/*
Shape->m_localOBB.localToParent = LinearMatrix4D::Identity;
Shape->m_localOBB.localToParent.BuildTranslation(
Point3D(
(x1+x0)*0.5f - xCenterOffset - Xoffset*dX,
waterLevel,
(z1+z0)*0.5f - zCenterOffset - Zoffset*dZ
)
);
Shape->m_localOBB.sphereRadius = 0.5f*xGrid*static_cast<Scalar>(sqrt(2.0f));
Check_Object(Shape);
*/
waterList->AttachChild(Shape);
Shape->SetVolumeCullMode();
subList->AttachIndexedChild(1, Shape);
}
brokenTriangles += newCount;
}
}
else
{
// MLRPrimitiveBase *prim = waterPools.LinkEdges();
// SPEWALWAYS(("micgaert", "#6"));
gos_PushCurrentHeap(ElementRenderer::ListElement::s_Heap);
subList->SetSize(3);
gos_PopCurrentHeap();
tempTrianglesPtr.SetLength(uw);
underWaterTriangles.SetLength(uw);
for(i=0;i<uw;i++)
{
tempTrianglesPtr[i] = &underWaterTriangles[i];
}
// SPEWALWAYS(("micgaert", "#7"));
if(!BinSort2(
subList,
0,
maxdepth - depth,
tempTrianglesPtr,
maxNumOfTrianglesPerMesh,
&frame,
&state,
true
)
)
{
if(silentMode==true)
{
fprintf(stderr, "Unstable triangle mesh created!");
}
else
{
PAUSE(("Unstable triangle mesh created!"));
}
}
else
{
brokenTriangles += uw;
}
tempTrianglesPtr.SetLength(aw);
aboveWaterTriangles.SetLength(aw);
for(i=0;i<aw;i++)
{
tempTrianglesPtr[i] = &aboveWaterTriangles[i];
}
// SPEWALWAYS(("micgaert", "#8"));
if(!BinSort2(
subList,
1,
maxdepth - depth,
tempTrianglesPtr,
maxNumOfTrianglesPerMesh,
&frame,
&state,
false
)
)
{
if(silentMode==true)
{
fprintf(stderr, "Unstable triangle mesh created!");
}
else
{
PAUSE(("Unstable triangle mesh created!"));
}
}
else
{
brokenTriangles += aw;
}
// SPEWALWAYS(("micgaert", "#8.1"));
gos_PushCurrentHeap(ElementRenderer::ShapeElement::s_Heap);
ElementRenderer::ShapeElement* Shape = new
ElementRenderer::ShapeElement;
Register_Object(Shape);
gos_PopCurrentHeap();
// SPEWALWAYS(("micgaert", "#8.2"));
gos_PushCurrentHeap(MidLevelRenderer::ShapeHeap);
MLRShape *shape = new MLRShape(1);
Register_Object(shape);
gos_PopCurrentHeap();
// SPEWALWAYS(("micgaert", "#8.3"));
MLRPrimitiveBase *prim = CreateWater( x0, x1, z0, z1, waterLevel);;
Check_Object(prim);
shape->Add(prim);
// SPEWALWAYS(("micgaert", "#8.4"));
prim->DetachReference();
Shape->SetMLRShape(shape);
const Point3D *p = NULL;
int nr_of_points = 0;
prim->GetCoordData(&p, &nr_of_points);
ReadOnlyArrayOf<Point3D> p_array;
p_array.AssignData(p, nr_of_points);
Shape->m_localOBB.ComputeBounds(p_array);
Shape->SetOBBMode();
/*
Shape->m_localOBB.localToParent = LinearMatrix4D::Identity;
Shape->m_localOBB.localToParent.BuildTranslation(
Point3D(
(x1+x0)*0.5f - xCenterOffset - Xoffset*dX,
waterLevel,
(z1+z0)*0.5f - zCenterOffset - Zoffset*dZ
)
);
// SPEWALWAYS(("micgaert", "#8.5"));
Shape->m_localOBB.sphereRadius = 0.5f*xGrid*static_cast<Scalar>(sqrt(2.0f));
Check_Object(Shape);
*/
waterList->AttachChild(Shape);
Shape->SetVolumeCullMode();
subList->AttachIndexedChild(2, Shape);
// SPEWALWAYS(("micgaert", "#9"));
}
/*
bool px0z0, px0z1, px1z0, px1z1;
px0z0 = waterLevel < mesh->eval( (int)(x0/dX), (int)(z0/dZ) );
px0z1 = waterLevel < mesh->eval( (int)(x0/dX), (int)(z1/dZ) );
px1z0 = waterLevel < mesh->eval( (int)(x1/dX), (int)(z0/dZ) );
px1z1 = waterLevel < mesh->eval( (int)(x1/dX), (int)(z1/dZ) );
if(waterPools.waterEdgePointCount==0)
{
if(px0z0 == false)
{
Verify(px0z0==px0z1 && px0z0==px1z0 && px0z0==px1z1);
// found water
}
}
*/
}
else
{
if(!BinSort(
subList,
0,
maxdepth - depth,
tempTrianglesPtr,
maxNumOfTrianglesPerMesh,
&frame,
&state
)
)
{
if(silentMode==true)
{
fprintf(stderr, "Unstable triangle mesh created!");
}
else
{
PAUSE(("Unstable triangle mesh created!"));
}
}
else
{
brokenTriangles += newCount;
}
}
}
else
{
if(silentMode==true)
{
fprintf(stderr, "Found an empty mesh ! Program exits !\n");
exit(-1);
}
else
{
STOP(("Found an empty mesh !"));
}
}
// SPEWALWAYS(("micgaert", "#10"));
tempTrianglesPtr.SetLength(0);
group->Sync();
group->LockBounds();
group->SetNeverCullMode();
subList->LockBounds();
subList->SetNeverCullMode();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
HFSlimMZ::SetMegaTexture(
int nrOfLevels,
int bucketSize,
const char *theName,
const char *outputpath
)
{
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::DefaultPriority + 1);
MLRTexture *texture = MLRTexturePool::Instance->Add(detailInfo.name);
state1.SetTextureHandle(texture->GetTextureHandle());
}
if(detailInfo.altname)
{
state2.SetTextureWrapMode(MLRState::TextureWrap);
state2.SetAlphaMode(detailInfo.alphaMode);
state2.SetPriority(MLRState::DefaultPriority + 1);
MLRTexture *texture = MLRTexturePool::Instance->Add(detailInfo.altname);
state2.SetTextureHandle(texture->GetTextureHandle());
}
DynamicArrayOf<unsigned char> onOffTriangles;
if(!doPrecise)
{
onOffTriangles.AssignValue(0, toSortTriangles.GetLength());
}
else
{
onOffTriangles.AssignValue(0, triangleIndices.GetLength());
}
int i, j, k, l, n, level;
simpleTerrainGroup.SetLength(xDim*zDim);
waterGroup.SetLength(xDim*zDim);
Stuff::ExtentBox allBox;
allBox = GetExtents();
int len = 1<<nrOfLevels;
xGridSize = (256/len)*dX;
zGridSize = (256/len)*dZ;
if(!doPrecise)
{
fprintf(stdout, "You don't care about precision !\n");
for(l=0;l<zDim;l++)
{
for(k=0;k<xDim;k++)
{
brokenTriangles = 0;
// sprintf(megaBaseName, "Content\\Maps\\%s\\%c%c_water.obj", theName, 'A'+l, 'A'+k );
// daWaterObj = fopen(megaBaseName, "wt");
// Verify(daWaterObj!=NULL);
vertexCountObj = 1;
sprintf(megaBaseName, "Maps\\%s\\%c%c\\%s_%c%c", theName, 'A'+l, 'A'+k, theName, 'A'+l, 'A'+k);
Scalar xOffset = dX*(k*256+Xoffset);
Scalar zOffset = dZ*(l*256+Zoffset);
gos_PushCurrentHeap(ElementRenderer::GridElement::s_Heap);
simpleTerrainGroup[l*xDim+k] =
new ElementRenderer::GridElement(
len, len,
zOffset - zCenterOffset,
xOffset - xCenterOffset,
dZ*256, dX*256
);
Register_Object(simpleTerrainGroup[l*xDim+k]);
waterGroup[l*xDim+k] = new ElementRenderer::GroupElement();
Register_Object(waterGroup[l*xDim+k]);
gos_PopCurrentHeap();
for(j=0;j<len;j++)
{
for(i=0;i<len;i++)
{
level = nrOfLevels;
tX = i;
tY = j;
// fprintf(daWaterObj, "\ng G%02d%02d\n", i, j);
BuildTile(
simpleTerrainGroup[l*xDim+k],
waterGroup[l*xDim+k],
j*len+i,
level,
nrOfLevels,
onOffTriangles,
bucketSize,
xOffset,
zOffset,
xGridSize,
zGridSize,
i,
j,
megaBaseName
);
// SPEWALWAYS(("micgaert", "%d %d %d %d\n", i, j, k, l));
}
}
simpleTerrainGroup[l*xDim+k]->LockBounds();
waterGroup[l*xDim+k]->LockBounds();
fprintf(stdout, "(%d, %d) \"broken\" triangles: %d\n", l, k, brokenTriangles);
// fclose(daWaterObj);
}
}
}
else
{
fprintf(stdout, "You wanted it precise !\n");
int numOfTriangles = usedTriangleIndices;
DynamicArrayOf<TriangleStruct*> *tempTrianglesPtr;
tempTrianglesPtr = new DynamicArrayOf<TriangleStruct*> [zDim*xDim*len*len];
int tJunction=0;
for(i=0,tJunction=0;i<usedUniquePoints;i++)
{
if(uniquePoints[i].CheckAngles(0.0f, 0.0f, GetXinM(), GetZinM(), dX, dZ)==false)
{
tJunction++;
SPEWALWAYS((0, "H%4x: %6.2f %6.2f %6.2f - %2d %.2f",
i,
uniquePoints[i].p.x, uniquePoints[i].p.y, uniquePoints[i].p.z,
uniquePoints[i].connectedTo,
uniquePoints[i].GetAngles()/Pi
));
if(silentMode!=true)
{
PAUSE(("Detected hole in terrain mesh!"));
}
}
}
for(l=0;l<zDim;l++)
{
for(k=0;k<xDim;k++)
{
brokenTriangles = 0;
Scalar xOffset = dX*(k*256+Xoffset);
Scalar zOffset = dZ*(l*256+Zoffset);
fprintf(stdout, "Working on (%d, %d)", l, k);
for(j=0;j<len;j++)
{
for(i=0;i<len;i++)
{
level = nrOfLevels;
tX = i;
tY = j;
tempTrianglesPtr[(l*xDim+k)*len*len + j*len + i].SetLength(numOfTriangles);
// fprintf(stdout, "\t(%d, %d)\n", i, j);
BuildTile(
tempTrianglesPtr[(l*xDim+k)*len*len + j*len + i],
j*len+i,
level,
nrOfLevels,
numOfTriangles,
onOffTriangles,
bucketSize,
xOffset,
zOffset,
xGridSize,
zGridSize,
i,
j
);
}
}
fprintf(stdout, " \"broken\" triangles: %d\n", brokenTriangles);
}
}
for(i=0,tJunction=0;i<usedUniquePoints;i++)
{
if(uniquePoints[i].CheckAngles(Xoffset*dX, Zoffset*dZ, dX*(xDim*256+Xoffset), dZ*(zDim*256+Zoffset), dX, dZ)==false)
{
SPEWALWAYS((0, "H%4x: %6.2f %6.2f %6.2f - %2d %.2f",
i,
uniquePoints[i].p.x, uniquePoints[i].p.y, uniquePoints[i].p.z,
uniquePoints[i].connectedTo,
uniquePoints[i].GetAngles()/Pi
));
// PAUSE(("Detected hole in terrain mesh!"));
}
}
double one_over_dX = 1.0f/dX;
double one_over_dZ = 1.0f/dZ;
bool redo;
tJunction = 0;
for(i=0;i<usedUniquePoints;i++)
{
if(uniquePoints[i].connectedTo==0)
{
continue;
}
redo = false;
Point3D point;
point = uniquePoints[i].p;
if(!Small_Enough(static_cast<Scalar>(fmod(uniquePoints[i].p.x, dX))))
{
point.x = static_cast<Scalar>(dX*floor(uniquePoints[i].p.x*one_over_dX + 0.5));
redo = true;
}
if(!Small_Enough(static_cast<Scalar>(fmod(uniquePoints[i].p.z, dZ))))
{
point.z = static_cast<Scalar>(dZ*floor(uniquePoints[i].p.z*one_over_dZ + 0.5));
redo = true;
}
if(redo==true)
{
point.y = GetHeight((int)(point.x/dX), (int)(point.z/dZ));
int pi = FindPoint(point);
uniquePoints[i].p = point;
if(pi<0 || i==pi)
{
for(j=0;j<uniquePoints[i].connectedTo;j++)
{
uniquePoints[uniquePoints[i].myTri[j].tri->v[0]].CalculateAngles();
uniquePoints[uniquePoints[i].myTri[j].tri->v[1]].CalculateAngles();
uniquePoints[uniquePoints[i].myTri[j].tri->v[2]].CalculateAngles();
}
uniquePoints[i].CalculateAngles();
}
else
{
int from, to;
if(i<pi)
{
from = pi;
to = i;
}
else
{
from = i;
to = pi;
}
for(j=0;j<uniquePoints[from].connectedTo;j++)
{
for(k=0;k<uniquePoints[to].connectedTo;k++)
{
if(uniquePoints[from].myTri[j].tri==uniquePoints[to].myTri[k].tri)
{
break;
}
}
if(k==uniquePoints[to].connectedTo)
{
uniquePoints[to].Add(uniquePoints[from].myTri[j].tri, uniquePoints[from].myTri[j].pos);
}
}
for(j=0;j<uniquePoints[to].connectedTo;j++)
{
for(k=0;k<3;k++)
{
if(uniquePoints[to].myTri[j].tri->v[k] == from)
{
uniquePoints[to].myTri[j].tri->v[k] = to;
}
}
}
for(k=0;k<uniquePoints[i].connectedTo;k++)
{
uniquePoints[uniquePoints[i].myTri[k].tri->v[0]].CalculateAngles();
uniquePoints[uniquePoints[i].myTri[k].tri->v[1]].CalculateAngles();
uniquePoints[uniquePoints[i].myTri[k].tri->v[2]].CalculateAngles();
}
uniquePoints[to].CalculateAngles();
uniquePoints[from].connectedTo = 0;
}
}
}
for(i=0;i<usedTriangleIndices;i++)
{
if(
triangleIndices[i].v[0]==triangleIndices[i].v[1] ||
triangleIndices[i].v[0]==triangleIndices[i].v[2] ||
triangleIndices[i].v[1]==triangleIndices[i].v[2]
)
{
RemoveTriangle(i);
triangleIndices[i].area = -1.0f;
}
else
{
triangleIndices[i].GetSurfaceAreaAndCentroid();
}
}
for(i=0,tJunction=0;i<usedUniquePoints;i++)
{
if(false == uniquePoints[i].CheckAngles(Xoffset*dX, Zoffset*dZ, dX*(xDim*256+Xoffset), dZ*(zDim*256+Zoffset), dX, dZ))
{
tJunction++;
SPEWALWAYS((0, "H%4x: %6.2f %6.2f %6.2f - %2d %.2f",
i,
uniquePoints[i].p.x, uniquePoints[i].p.y, uniquePoints[i].p.z,
uniquePoints[i].connectedTo,
uniquePoints[i].GetAngles()/Pi
));
// PAUSE(("Detected hole in terrain mesh!"));
}
}
Verify(tJunction==0);
int smallOne = 0, tiltedOne = 0;
for(i=0;i<usedTriangleIndices;i++)
{
if(triangleIndices[i].area < 0.0f)
{
continue;
}
if(triangleIndices[i].area > 0.0f && triangleIndices[i].area <= Stuff::SMALL)
{
smallOne++;
}
if(triangleIndices[i].plane.normal.y < Stuff::SMALL)
{
int pmin, pmid, pmax;
bool xCase = false, zCase = false;
if( // Triangle forms vertical line
Close_Enough(triangleIndices[i].GetPoint(0).x, triangleIndices[i].GetPoint(1).x) &&
Close_Enough(triangleIndices[i].GetPoint(0).x, triangleIndices[i].GetPoint(2).x)
)
{
if(triangleIndices[i].GetPoint(0).z < triangleIndices[i].GetPoint(1).z)
{
if(triangleIndices[i].GetPoint(0).z < triangleIndices[i].GetPoint(2).z)
{
pmin = triangleIndices[i].v[0];
if(triangleIndices[i].GetPoint(1).z < triangleIndices[i].GetPoint(2).z)
{
pmid = triangleIndices[i].v[1];
pmax = triangleIndices[i].v[2];
}
else
{
pmid = triangleIndices[i].v[2];
pmax = triangleIndices[i].v[1];
}
}
else
{
pmin = triangleIndices[i].v[2];
pmid = triangleIndices[i].v[0];
pmax = triangleIndices[i].v[1];
}
}
else
{
if(triangleIndices[i].GetPoint(1).z < triangleIndices[i].GetPoint(2).z)
{
pmin = triangleIndices[i].v[1];
if(triangleIndices[i].GetPoint(0).z < triangleIndices[i].GetPoint(2).z)
{
pmid = triangleIndices[i].v[0];
pmax = triangleIndices[i].v[2];
}
else
{
pmid = triangleIndices[i].v[2];
pmax = triangleIndices[i].v[0];
}
}
else
{
pmin = triangleIndices[i].v[2];
pmid = triangleIndices[i].v[1];
pmax = triangleIndices[i].v[0];
}
}
xCase = true;
}
if( // Triangle forms horizontal line
Close_Enough(triangleIndices[i].GetPoint(0).z, triangleIndices[i].GetPoint(1).z) &&
Close_Enough(triangleIndices[i].GetPoint(0).z, triangleIndices[i].GetPoint(2).z)
)
{
if(triangleIndices[i].GetPoint(0).x < triangleIndices[i].GetPoint(1).x)
{
if(triangleIndices[i].GetPoint(0).x < triangleIndices[i].GetPoint(2).x)
{
pmin = triangleIndices[i].v[0];
if(triangleIndices[i].GetPoint(1).x < triangleIndices[i].GetPoint(2).x)
{
pmid = triangleIndices[i].v[1];
pmax = triangleIndices[i].v[2];
}
else
{
pmid = triangleIndices[i].v[2];
pmax = triangleIndices[i].v[1];
}
}
else
{
pmin = triangleIndices[i].v[2];
pmid = triangleIndices[i].v[0];
pmax = triangleIndices[i].v[1];
}
}
else
{
if(triangleIndices[i].GetPoint(1).x < triangleIndices[i].GetPoint(2).x)
{
pmin = triangleIndices[i].v[1];
if(triangleIndices[i].GetPoint(0).x < triangleIndices[i].GetPoint(2).x)
{
pmid = triangleIndices[i].v[0];
pmax = triangleIndices[i].v[2];
}
else
{
pmid = triangleIndices[i].v[2];
pmax = triangleIndices[i].v[0];
}
}
else
{
pmin = triangleIndices[i].v[2];
pmid = triangleIndices[i].v[1];
pmax = triangleIndices[i].v[0];
}
}
zCase = true;
}
if(zCase==0 && xCase==0)
{
continue;
}
Verify(!(zCase && xCase));
Verify(uniquePoints[pmin].p.x <= uniquePoints[pmid].p.x && uniquePoints[pmid].p.x <= uniquePoints[pmax].p.x);
Verify(uniquePoints[pmin].p.z <= uniquePoints[pmid].p.z && uniquePoints[pmid].p.z <= uniquePoints[pmax].p.z);
int pfaraway = -1;
int pminDI = -1, pminVI = -1;
for(j=0;j<uniquePoints[pmin].connectedTo;j++)
{
/*
if(uniquePoints[pmin].myTri[j].tri->area < Stuff::SMALL)
{
continue;
}
*/
if(&triangleIndices[i]==uniquePoints[pmin].myTri[j].tri)
{
if(pminVI>=0)
{
if(silentMode==true)
{
fprintf(stderr, "Error while removing triangles without area ! Program exits !\n");
exit(-1);
}
else
{
STOP(("Error while removing triangles without area ?"));
}
}
pminVI = j;
continue;
}
for(k=0;k<3;k++)
{
if(uniquePoints[pmin].myTri[j].tri->v[k]==pmax)
{
break;
}
}
if(k<3)
{
for(k=0;k<3;k++)
{
if(uniquePoints[pmin].myTri[j].tri->v[k]!=pmax && uniquePoints[pmin].myTri[j].tri->v[k]!=pmin)
{
pfaraway = uniquePoints[pmin].myTri[j].tri->v[k];
break;
}
}
Verify(pfaraway>=0);
if(pminDI<0)
{
pminDI = j;
}
else
{
if(silentMode==true)
{
fprintf(stderr, "Error while removing triangles without area ! Program exits !\n");
exit(-1);
}
else
{
STOP(("Error while removing triangles without area !"));
}
}
}
}
int pmaxDI = -1, pmaxVI = -1;
for(j=0;j<uniquePoints[pmax].connectedTo;j++)
{
/*
if(uniquePoints[pmax].myTri[j].tri->area < Stuff::SMALL)
{
continue;
}
*/
if(&triangleIndices[i]==uniquePoints[pmax].myTri[j].tri)
{
if(pmaxVI>=0)
{
if(silentMode==true)
{
fprintf(stderr, "Error while removing triangles without area ! Program exits !\n");
exit(-1);
}
else
{
STOP(("Error while removing triangles without area ?"));
}
}
pmaxVI = j;
continue;
}
for(k=0;k<3;k++)
{
if(uniquePoints[pmax].myTri[j].tri->v[k]==pmin)
{
break;
}
}
if(k<3)
{
for(k=0;k<3;k++)
{
if(uniquePoints[pmax].myTri[j].tri->v[k]!=pmax && uniquePoints[pmax].myTri[j].tri->v[k]!=pmin)
{
Verify(pfaraway == uniquePoints[pmax].myTri[j].tri->v[k]);
break;
}
}
if(pmaxDI<0)
{
pmaxDI = j;
}
else
{
if(silentMode==true)
{
fprintf(stderr, "Error while removing triangles without area ! Program exits !\n");
exit(-1);
}
else
{
STOP(("Error while removing triangles without area !"));
}
}
}
}
if(pminDI>=0 && pmaxDI>=0)
{
for(k=0;k<3;k++)
{
if(uniquePoints[pmin].myTri[pminDI].tri->v[k]==pmax)
{
uniquePoints[pmin].myTri[pminDI].tri->v[k] = pmid;
uniquePoints[pmid].Add(uniquePoints[pmin].myTri[pminDI].tri, k);
uniquePoints[pmin].myTri[pminDI].tri->GetSurfaceAreaAndCentroid();
break;
}
}
uniquePoints[pmin].connectedTo--;
for(j=pminVI;j<uniquePoints[pmin].connectedTo;j++)
{
uniquePoints[pmin].myTri[j] = uniquePoints[pmin].myTri[j+1];
}
for(k=0;k<3;k++)
{
if(uniquePoints[pmax].myTri[pmaxVI].tri->v[k]==pmin)
{
uniquePoints[pmax].myTri[pmaxVI].tri->v[k] = pfaraway;
uniquePoints[pfaraway].Add(uniquePoints[pmax].myTri[pmaxVI].tri, k);
uniquePoints[pmax].myTri[pmaxVI].tri->GetSurfaceAreaAndCentroid();
break;
}
}
uniquePoints[pmax].connectedTo--;
for(j=pmaxDI;j<uniquePoints[pmax].connectedTo;j++)
{
uniquePoints[pmax].myTri[j] = uniquePoints[pmax].myTri[j+1];
}
uniquePoints[pmin].CalculateAngles();
uniquePoints[pmid].CalculateAngles();
uniquePoints[pmax].CalculateAngles();
uniquePoints[pfaraway].CalculateAngles();
tiltedOne++;
}
else
{
if(pminDI<0 && pmaxDI<0)
{
triangleIndices[i].area = 0.0f;
}
else
{
if(silentMode==true)
{
fprintf(stderr, "Error while removing triangles without area ! Program exits !\n");
exit(-1);
}
else
{
STOP(("Error while removing triangles without area !"));
}
}
}
}
}
for(i=0;i<usedTriangleIndices;i++)
{
if(triangleIndices[i].area == 0.0f)
{
RemoveTriangle(&triangleIndices[i]);
}
}
for(i=0,tJunction=0;i<usedUniquePoints;i++)
{
if(
Small_Enough(static_cast<Scalar>(fmod(uniquePoints[i].p.x, dX))) &&
Small_Enough(static_cast<Scalar>(fmod(uniquePoints[i].p.z, dZ)))
)
{
uniquePoints[i].p.y = GetHeight(
Round(uniquePoints[i].p.x/dX),
Round(uniquePoints[i].p.z/dZ)
);
}
if(false == uniquePoints[i].CheckAngles(Xoffset*dX, Zoffset*dZ, dX*(xDim*256+Xoffset), dZ*(zDim*256+Zoffset), dX, dZ))
{
#ifdef CHANGE_0625
if(
Close_Enough(uniquePoints[i].GetAngles(), Pi) &&
Close_Enough(uniquePoints[i].GetExpectedAngles(Xoffset*dX, Zoffset*dZ, dX*(xDim*256+Xoffset), dZ*(zDim*256+Zoffset)), 2*Pi)
)
{
int greaterX = 0, lesserX = 0, greaterZ = 0, lesserZ = 0, all = 0;
// check for orientation
for(j=0;j<uniquePoints[i].connectedTo;j++)
{
for(k=0;k<3;k++)
{
all++;
if(uniquePoints[i].p.x > uniquePoints[uniquePoints[i].myTri[j].tri->v[k]].p.x)
{
lesserX++;
}
if(uniquePoints[i].p.x < uniquePoints[uniquePoints[i].myTri[j].tri->v[k]].p.x)
{
greaterX++;
}
if(uniquePoints[i].p.z > uniquePoints[uniquePoints[i].myTri[j].tri->v[k]].p.z)
{
lesserZ++;
}
if(uniquePoints[i].p.z < uniquePoints[uniquePoints[i].myTri[j].tri->v[k]].p.z)
{
greaterZ++;
}
}
}
int gX = 0, lX = 0, gZ = 0, lZ = 0;
if(greaterX>0 && lesserX==0)
{
gX = 1;
}
if(greaterX==0 && lesserX>0)
{
lX = 1;
}
if(greaterZ>0 && lesserZ==0)
{
gZ = 1;
}
if(greaterZ==0 && lesserZ>0)
{
lZ = 1;
}
if(gX + lX + gZ + lZ == 1)
{
double dist, distMin = 10000;
int pmin;
if(gX || lX)
{
for(j=0;j<uniquePoints[i].connectedTo;j++)
{
for(k=0;k<3;k++)
{
if( i != uniquePoints[i].myTri[j].tri->v[k] &&
uniquePoints[i].p.x == uniquePoints[uniquePoints[i].myTri[j].tri->v[k]].p.x)
{
dist = fabs(uniquePoints[i].p.z - uniquePoints[uniquePoints[i].myTri[j].tri->v[k]].p.z);
if(dist < distMin)
{
distMin = dist;
pmin = uniquePoints[i].myTri[j].tri->v[k];
}
}
}
}
}
else
{
for(j=0;j<uniquePoints[i].connectedTo;j++)
{
for(k=0;k<3;k++)
{
if( i != uniquePoints[i].myTri[j].tri->v[k] &&
uniquePoints[i].p.z == uniquePoints[uniquePoints[i].myTri[j].tri->v[k]].p.z)
{
dist = fabs(uniquePoints[i].p.x - uniquePoints[uniquePoints[i].myTri[j].tri->v[k]].p.x);
if(dist < distMin)
{
distMin = dist;
pmin = uniquePoints[i].myTri[j].tri->v[k];
}
}
}
}
}
for(j=0;j<uniquePoints[i].connectedTo;j++)
{
for(k=0;k<3;k++)
{
if( i == uniquePoints[i].myTri[j].tri->v[k] )
{
uniquePoints[i].myTri[j].tri->v[k] = pmin;
break;
}
}
for(l=0;l<uniquePoints[pmin].connectedTo;l++)
{
if(uniquePoints[pmin].myTri[l].tri == uniquePoints[i].myTri[j].tri)
{
break;
}
}
if(l==uniquePoints[pmin].connectedTo)
{
uniquePoints[pmin].Add(uniquePoints[i].myTri[j].tri, k);
}
for(k=0;k<3;k++)
{
uniquePoints[uniquePoints[i].myTri[j].tri->v[k]].CalculateAngles();
}
uniquePoints[i].myTri[j].tri->GetSurfaceAreaAndCentroid();
}
uniquePoints[i].connectedTo = 0;
uniquePoints[pmin].CalculateAngles();
// try a remedy
tJunction++;
}
}
else
#endif
{
tJunction++;
SPEWALWAYS((0, "H%4x: %6.2f %6.2f %6.2f - %2d %.2f",
i,
uniquePoints[i].p.x, uniquePoints[i].p.y, uniquePoints[i].p.z,
uniquePoints[i].connectedTo,
uniquePoints[i].GetAngles()/Pi
));
if(silentMode!=true)
{
PAUSE(("Detected hole in terrain mesh!"));
}
}
}
}
DynamicArrayOf<TriangleStruct*> tileTrianglesPtr;
for(l=0;l<zDim;l++)
{
for(k=0;k<xDim;k++)
{
sprintf(megaBaseName, "Maps\\%s\\%c%c\\%s_%c%c", theName, 'A'+l, 'A'+k, theName, 'A'+l, 'A'+k);
Scalar xOffset = dX*(k*256+Xoffset);
Scalar zOffset = dZ*(l*256+Zoffset);
gos_PushCurrentHeap(ElementRenderer::GridElement::s_Heap);
simpleTerrainGroup[l*xDim+k] =
new ElementRenderer::GridElement(
len, len,
zOffset - zCenterOffset,
xOffset - xCenterOffset,
dZ*256, dX*256
);
Register_Object(simpleTerrainGroup[l*xDim+k]);
waterGroup[l*xDim+k] = new ElementRenderer::GroupElement();
Register_Object(waterGroup[l*xDim+k]);
gos_PopCurrentHeap();
for(j=0;j<len;j++)
{
for(i=0;i<len;i++)
{
int m, length = tempTrianglesPtr[(l*xDim+k)*len*len + j*len + i].GetLength();
int usable = 0;
tileTrianglesPtr.SetLength(length);
for(m=0;m<length;m++)
{
if(tempTrianglesPtr[(l*xDim+k)*len*len + j*len + i][m]->area < SMALL)
{
RemoveTriangle(tempTrianglesPtr[(l*xDim+k)*len*len + j*len + i][m]);
for(n=0,tJunction=0;n<usedUniquePoints;n++)
{
if(false == uniquePoints[n].CheckAngles(Xoffset*dX, Zoffset*dZ, dX*(xDim*256+Xoffset), dZ*(zDim*256+Zoffset), dX, dZ))
{
tJunction++;
SPEWALWAYS((0, "H%4x: %6.2f %6.2f %6.2f - %2d %.2f",
i,
uniquePoints[n].p.x, uniquePoints[i].p.y, uniquePoints[i].p.z,
uniquePoints[n].connectedTo,
uniquePoints[n].GetAngles()/Pi
));
if(silentMode!=true)
{
PAUSE(("Detected hole in terrain mesh!"));
}
}
}
continue;
}
else if(tempTrianglesPtr[(l*xDim+k)*len*len + j*len + i][m]->plane.normal.y < Stuff::SMALL)
{
RemoveTriangle(tempTrianglesPtr[(l*xDim+k)*len*len + j*len + i][m]);
for(n=0,tJunction=0;n<usedUniquePoints;n++)
{
if(false == uniquePoints[n].CheckAngles(Xoffset*dX, Zoffset*dZ, dX*(xDim*256+Xoffset), dZ*(zDim*256+Zoffset), dX, dZ))
{
tJunction++;
SPEWALWAYS((0, "H%4x: %6.2f %6.2f %6.2f - %2d %.2f",
i,
uniquePoints[n].p.x, uniquePoints[i].p.y, uniquePoints[i].p.z,
uniquePoints[n].connectedTo,
uniquePoints[n].GetAngles()/Pi
));
if(silentMode!=true)
{
PAUSE(("Detected hole in terrain mesh!"));
}
}
}
continue;
}
tileTrianglesPtr[usable++] = tempTrianglesPtr[(l*xDim+k)*len*len + j*len + i][m];
}
tileTrianglesPtr.SetLength(usable);
for(m=0,tJunction=0;m<usedUniquePoints;m++)
{
if(false == uniquePoints[m].CheckAngles(Xoffset*dX, Zoffset*dZ, dX*(xDim*256+Xoffset), dZ*(zDim*256+Zoffset), dX, dZ))
{
tJunction++;
SPEWALWAYS((0, "H%4x: %6.2f %6.2f %6.2f - %2d %.2f",
i,
uniquePoints[m].p.x, uniquePoints[i].p.y, uniquePoints[i].p.z,
uniquePoints[m].connectedTo,
uniquePoints[m].GetAngles()/Pi
));
if(silentMode!=true)
{
PAUSE(("Detected hole in terrain mesh!"));
}
}
}
tX = i;
tY = j;
CreateTile(
simpleTerrainGroup[l*xDim+k],
waterGroup[l*xDim+k],
tileTrianglesPtr,
j*len+i,
level,
nrOfLevels,
bucketSize,
xOffset,
zOffset,
xGridSize,
zGridSize,
i,
j,
megaBaseName
);
}
}
simpleTerrainGroup[l*xDim+k]->LockBounds();
}
}
}
fprintf(stdout, "Done HFSlimMZ::SetMegaTexture()");
return true;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
HFSlimMZ::SetCulturals(CulturalLoc* culLoc, int culLocCount)
{
int i, j, k, l, n, len = 8;
Stuff::ExtentBox allBox;
allBox = GetExtents();
Scalar xGridSize = (allBox.maxX-allBox.minX)/(len*xDim);
Scalar zGridSize = (allBox.maxZ-allBox.minZ)/(len*zDim);
DynamicArrayOf<CulturalLoc> culLocLocal(culLocCount);
int culLocLocalCount;
for(l=0;l<zDim;l++)
{
for(k=0;k<xDim;k++)
{
ElementRenderer::GridElement *zone = simpleTerrainGroup[l*xDim+k];
Scalar xGridOffset = k*dX*256;
Scalar zGridOffset = l*dZ*256;
for(j=0;j<len;j++)
{
for(i=0;i<len;i++)
{
ElementRenderer::Element *elem = zone->GetIndexedElement(j*len+i);
ElementRenderer::GroupElement *group = Cast_Object(ElementRenderer::GroupElement*, elem);
Scalar x0, z0, x1, z1;
x0 = xGridOffset + i*xGridSize - xCenterOffset;
z0 = zGridOffset + j*zGridSize - zCenterOffset;
x1 = x0 + xGridSize;
z1 = z0 + zGridSize;
x0 += 4.5f;
z0 += 4.5f;
x1 -= 4.5f;
z1 -= 4.5f;
for(n=0,culLocLocalCount=0;n<culLocCount;n++)
{
if(culLoc[n].loc.x > x0 && culLoc[n].loc.x < x1 && culLoc[n].loc.z > z0 && culLoc[n].loc.z < z1)
{
Line3D line(
Point3D(
culLoc[n].loc.x,
Offset-100.0f,
culLoc[n].loc.z
),
UnitVector3D(0.0f, 1.0f, 0.0f),
// 256*dY
1000
);
Normal3D normal;
ElementRenderer::CollisionQuery cq(&line, &normal);
#ifdef LAB_ONLY
bool ret =
#endif
group->CastRay(&cq);
#ifdef LAB_ONLY
if (!ret)
{
char szTemp[256];
sprintf(szTemp, "Natural couldn't find soil to plant on at x=%f, z=%f",culLoc[n].loc.x, culLoc[n].loc.z);
// PAUSE((szTemp));
}
#endif
Point3D end;
line.FindEnd(&end);
culLoc[n].loc.y = end.y;
culLocLocal[culLocLocalCount++] = culLoc[n];
}
}
if(culLocLocalCount>0)
{
Stuff::ChainIteratorOf<ElementRenderer::Element*> *children = group->MakeIterator();
Register_Object(children);
ElementRenderer::Element *child = NULL;
int count = 0;
child = children->ReadAndNext();
Unregister_Object(children);
delete children;
Verify(count<2);
ElementRenderer::ListElement *list = Cast_Object(ElementRenderer::ListElement*, child);
gos_PushCurrentHeap(ElementRenderer::ShapeElement::s_Heap);
ElementRenderer::ShapeElement* Shape = new ElementRenderer::ShapeElement;
Register_Object(Shape);
gos_PopCurrentHeap();
gos_PushCurrentHeap(MidLevelRenderer::ShapeHeap);
MLRCulturShape *shape = new MLRCulturShape();
Register_Object(shape);
gos_PopCurrentHeap();
MLRCultural *data = new MLRCultural[culLocLocalCount];
Mem_Copy(data, culLocLocal.GetData(), culLocLocalCount*sizeof(MLRCultural), culLocLocalCount*sizeof(MLRCultural));
shape->AssignCulturalData(data, culLocLocalCount);
shape->FadeValue(culturalFadeIn, culturalFadeOut);
Shape->SetMLRShape(shape);
Shape->m_localOBB.localToParent = LinearMatrix4D::Identity;
Shape->m_localOBB.localToParent.BuildTranslation(
Point3D(
xGridOffset + i*xGridSize + xGridSize*0.5f - xCenterOffset/* - Xoffset*dX*/,
0.0f,
zGridOffset + j*zGridSize + zGridSize*0.5f - zCenterOffset/* - Zoffset*dZ*/
)
);
Shape->m_localOBB.sphereRadius = static_cast<Scalar>(sqrt(xGridSize*xGridSize + zGridSize*zGridSize));
shape->SetCenterInWorld(
xGridOffset + i*xGridSize + xGridSize*0.5f - xCenterOffset/* - Xoffset*dX*/,
zGridOffset + j*zGridSize + zGridSize*0.5f - zCenterOffset/* - Zoffset*dZ*/,
Shape->m_localOBB.sphereRadius
);
int lCount = list->GetActiveCount();
gos_PushCurrentHeap(ElementRenderer::g_Heap);
list->ReSize(lCount+1);
gos_PopCurrentHeap();
list->AttachIndexedChild(lCount, Shape);
Shape->SetNeverCullMode();
}
}
}
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
HFSlimMZ::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;
}