#include #include #include #include #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 uniquePoints; int usedUniquePoints; PointStruct *TriangleStruct::points = NULL; DynamicArrayOf triangleIndices; int usedTriangleIndices; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // template 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=0) { return closest; } uniquePoints[usedUniquePoints++].p = point; return (usedUniquePoints-1); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool RemoveTriangle(TriangleStruct *ts) { int i, j; for(i=0;i=usedTriangleIndices) { return false; } PointStruct *point; for(i=0;i<3;i++) { point = &ts->points[ts->v[i]]; do { for(j=0;jconnectedTo;j++) { if(point->myTri[j].tri==ts) { break; } } if(jconnectedTo) { for(;jconnectedTo-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;jconnectedTo;j++) { if(point->myTri[j].tri==ts) { break; } } if(jconnectedTo) { for(;jconnectedTo-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 (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;iGetPoint((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;jv[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 polygon(2*waterEdgePointCount); DynamicArrayOf normals(2*waterEdgePointCount); DynamicArrayOf 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;i1) { 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 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=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;k8) { 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>=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;hello0) { Verify(waterEdgePoints[hello].toEdge[1]==-1); break; } else { Verify(hello2); pool++; int j, up=0, down=0; int upVC=0, downVC=0; int bigA = -1; Scalar axisL = 1000000.0f ; for(j=0;j2) { 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(l0.0f) { upVC++; } else { downVC++; } } if(daWaterObj!=NULL && vertexCount>2) { fprintf(daWaterObj, "f"); if(upVC>downVC) { for(j=0;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=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;j0.0f) { up++; if(l0.0f) { upVC++; } else { downVC++; } } SPEW(("micgaert", "===")); // SPEW(("micgaert", "%d %d", up, down)); /* if(down==0) { for(j=0;jdownVC) { for(j=0;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 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(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= 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;i8); 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& 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< 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;icenterValid==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 0 ) { Verify(nrOfPoints=(*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(sqrt(maxRadius0)); maxRadius1 = static_cast(sqrt(maxRadius1)); maxRadius2 = static_cast(sqrt(maxRadius2)); maxRadius3 = static_cast(sqrt(maxRadius3)); Point3D center; Scalar maxRadius; if(maxRadius0GetPoint(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;iSetCoordData(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 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& 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< vert_id(X*Z); DynamicArrayOf 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;icenterValid==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;kGetPoint(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;imaxRadius0 ? 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(sqrt(maxRadius0)); maxRadius1 = static_cast(sqrt(maxRadius1)); maxRadius2 = static_cast(sqrt(maxRadius2)); maxRadius3 = static_cast(sqrt(maxRadius3)); Point3D center; Scalar maxRadius; // SPEWALWAYS(("micgaert", "#cm5")); if(maxRadius0DetachReference(); #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;iSetCoordData(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;iGetTrianglePlane(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 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 *coords = &ret->dataStore->coords; Check_Object(coords); coords->SetLength(25); DynamicArrayOf *texCoords = &ret->dataStore->texCoords; Check_Object(texCoords); texCoords->SetLength(25); DynamicArrayOf *colors = &ret->dataStore->colors; Check_Object(colors); colors->SetLength(25); DynamicArrayOf *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& 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 centroids(polygon_count); unsigned i; for (i=0; icenter; } // //------------------------------------------------------------------------ // 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 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; i0); 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& 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 centroids(polygon_count); unsigned i; for (i=0; icenterValid==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 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; i0); 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(X,Z); int i, j; float maxY = 0; for(j=0;jref(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()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;jareUsed(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(dY*mesh->eval( (int)(tdtrilist[i].v[0].x), (int)(tdtrilist[i].v[0].z) )); tdtrilist[i].v[1].y = Offset + static_cast(dY*mesh->eval( (int)(tdtrilist[i].v[1].x), (int)(tdtrilist[i].v[1].z) )); tdtrilist[i].v[2].y = Offset + static_cast(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 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(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;ipointCount() == 0) { return; } for(i=0;i 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 &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;iGetPoint(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& tempTrianglesPtr, int index, int depth, int maxdepth, int numOfTriangles, DynamicArrayOf& 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 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 a) { a = angles[m]; ba = m; } } for(m=1;m 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 a) { a = angles[m]; ba = m; } } for(m=1;mGetPoint(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& 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<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 group_a; int usable = tempTrianglesPtr.GetLength(); if(doWater==true) { DynamicArrayOf underWaterTriangles(2*usable); DynamicArrayOf aboveWaterTriangles(2*usable); WaterPools waterPools(usable, waterLevel); waterPools.SetTileEdges(x0, x1, z0, z1); int org=0, aw=0, uw=0; for(i=0;iGetPoint(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]v[q]; } aw++; } else { if(ac==0) { for(int q=0;q<3;q++) { Verify(tempTrianglesPtr[i]->v[q]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]v[now]; Verify(underWaterTriangles[uw].v[0]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]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; iAdd(prim); prim->DetachReference(); Shape->SetMLRShape(shape); const Point3D *p = NULL; int nr_of_points = 0; prim->GetCoordData(&p, &nr_of_points); ReadOnlyArrayOf 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(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;iAdd(prim); prim->DetachReference(); Shape->SetMLRShape(shape); const Point3D *p = NULL; int nr_of_points = 0; prim->GetCoordData(&p, &nr_of_points); ReadOnlyArrayOf 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(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; iSync(); group->LockBounds(); group->SetNeverCullMode(); subList->LockBounds(); subList->SetNeverCullMode(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void HFSlimMZ::BuildTile( ElementRenderer::ListElement *list, ElementRenderer::GroupElement *waterList, int index, int depth, int maxdepth, DynamicArrayOf& 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 tempTrianglesPtr(numOfTriangles); DynamicArrayOf 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<Add(textureName); texture->SetHint(gosHint_AGPMemory | gosHint_DontShrink); state.SetTextureHandle(texture->GetTextureHandle()); state.SetTextureWrapMode(MLRState::TextureClamp); for(i=0,j=0;iGetPoint(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;mGetPoint(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 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;mGetPoint(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 underWaterTriangles(2*newCount); DynamicArrayOf aboveWaterTriangles(2*newCount); WaterPools waterPools(newCount, waterLevel); waterPools.SetTileEdges(x0, x1, z0, z1); int org=0, aw=0, uw=0; for(i=0;iGetPoint(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]=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]=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 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(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;iAdd(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 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(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 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<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 *tempTrianglesPtr; tempTrianglesPtr = new DynamicArrayOf [zDim*xDim*len*len]; int tJunction=0; for(i=0,tJunction=0;i(fmod(uniquePoints[i].p.x, dX)))) { point.x = static_cast(dX*floor(uniquePoints[i].p.x*one_over_dX + 0.5)); redo = true; } if(!Small_Enough(static_cast(fmod(uniquePoints[i].p.z, dZ)))) { point.z = static_cast(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;jv[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(iv[k] == from) { uniquePoints[to].myTri[j].tri->v[k] = to; } } } for(k=0;kv[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 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;jarea < 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;jarea < 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;jv[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(fmod(uniquePoints[i].p.x, dX))) && Small_Enough(static_cast(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[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;jv[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;jv[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;jv[k] ) { uniquePoints[i].myTri[j].tri->v[k] = pmin; break; } } for(l=0;lv[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 tileTrianglesPtr; for(l=0;larea < SMALL) { RemoveTriangle(tempTrianglesPtr[(l*xDim+k)*len*len + j*len + i][m]); for(n=0,tJunction=0;nplane.normal.y < Stuff::SMALL) { RemoveTriangle(tempTrianglesPtr[(l*xDim+k)*len*len + j*len + i][m]); for(n=0,tJunction=0;nLockBounds(); } } } 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 culLocLocal(culLocCount); int culLocLocalCount; for(l=0;lGetIndexedElement(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 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 *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(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; }