private void markOverrideTessellations(ErrorMetricRefine refiner) { JaggedContainer <byte> v = TerrainGlobals.getEditor().getJaggedTesselation(); int width = TerrainGlobals.getTerrain().getNumXVerts(); long id; byte maskValue; v.ResetIterator(); while (v.MoveNext(out id, out maskValue)) { if (maskValue == BTerrainEditor.cTesselationEmptyVal) { continue; } int x = (int)(id / width); int z = (int)(id - x * width); if (maskValue == (int)BTerrainEditor.eTessOverrideVal.cTess_Max) { refiner.setMarkedPt(x, z, true); } else if (maskValue == (int)BTerrainEditor.eTessOverrideVal.cTess_Min) { refiner.setMarkedPt(x, z, false); } } }
private byte giveMaxTesselation(ref ErrorMetricRefine refiner, int xOff, int zOff, int nodeWidth, float minortyBias) { int PatchWidth = 17; int numP = 0; int numF = 0; refiner.giveStatsInArea(xOff, zOff, PatchWidth, PatchWidth, out numP, out numF); float rat = (float)numP / (float)numF; //CLM THIS MUST MATCH THE 360 //float[] tessLevels ={ 15, 7, 3, 1 }; byte maxTess = 3; if (numP == 0) { maxTess = 3; } else if (numF == 0) { maxTess = 0; } else { if (rat <= 0.25f) { maxTess = 3; //==1 } else if (rat <= 0.5f) { maxTess = 2; //==3 } else if (rat <= 0.75f) { maxTess = 1; //==7 } else //if (rat <= 1.0f) { maxTess = 0; //==15 } } return(maxTess); }
private void writeTessData(bool refineTerrain, float eLOD, float minorityBias, ref ExportResults results) { ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); //write the 'header' int nodeWidth = 16; int numXPatches = (int)(TerrainGlobals.getTerrain().getNumXVerts() / (float)nodeWidth); int numZPatches = (int)(TerrainGlobals.getTerrain().getNumXVerts() / (float)nodeWidth); int numXChunks = (int)(TerrainGlobals.getTerrain().getNumXVerts() / (float)BTerrainQuadNode.getMaxNodeDepth()); int numPatches = numXPatches * numZPatches; binWriter.Write(Xbox_EndianSwap.endSwapI32(numXPatches)); binWriter.Write(Xbox_EndianSwap.endSwapI32(numZPatches)); //do this for each patch byte[] tDat = new byte[numPatches]; Vector4[] bbDat = new Vector4[numPatches * 2]; //CLM - instead of writing floating point values (and taking up more memory) //write indexes into our discrete step array if (refineTerrain) { ErrorMetricRefine refiner = null; refiner = new ErrorMetricRefine(); refiner.init(TerrainGlobals.getTerrain().getNumXVerts(), TerrainGlobals.getTerrain().getNumZVerts()); refiner.refine(eLOD);//, nodeWidth + 1); markOverrideTessellations(refiner); for (int x = 0; x < numXPatches; x++) { for (int z = 0; z < numZPatches; z++) { int xMinVert = x * nodeWidth; int zMinVert = z * nodeWidth; tDat[x + z * numXPatches] = giveMaxTesselation(ref refiner, xMinVert, zMinVert, nodeWidth, minorityBias); } } refiner.destroy(); refiner = null; smoothTessNeighbors(tDat, numXPatches, numZPatches); } else { for (int i = 0; i < numPatches; i++) { tDat[i] = 0; } } //write to the disk for (int i = 0; i < tDat.Length; i++) { binWriter.Write(tDat[i]); } //generate and write our bounding boxes for (int x = 0; x < numXPatches; x++) { for (int z = 0; z < numZPatches; z++) { Vector4 min = new Vector4(9000, 9000, 9000, 0); Vector4 max = new Vector4(-9000, -9000, -9000, 0); for (int i = 0; i < nodeWidth + 1; i++) { for (int j = 0; j < nodeWidth + 1; j++) { int xVal = x * nodeWidth + i; int zVal = z * nodeWidth + j; if (xVal >= TerrainGlobals.getTerrain().getNumXVerts() || zVal >= TerrainGlobals.getTerrain().getNumXVerts()) { continue; } long kIndex = xVal + TerrainGlobals.getTerrain().getNumXVerts() * zVal; Vector3 v = TerrainGlobals.getTerrain().getPos(xVal, zVal); if (v.X < min.X) { min.X = v.X; } if (v.Y < min.Y) { min.Y = v.Y; } if (v.Z < min.Z) { min.Z = v.Z; } if (v.X > max.X) { max.X = v.X; } if (v.Y > max.Y) { max.Y = v.Y; } if (v.Z > max.Z) { max.Z = v.Z; } } } //NOTE: THE GAME EXPECTS THIS DATA IN NON-SWIZZLED FORM int q = x + z * numZPatches; q *= 2; bbDat[q] = min; bbDat[q + 1] = max; } } for (int i = 0; i < bbDat.Length; i++) { binWriter.Write(Xbox_EndianSwap.endSwapF32(bbDat[i].X)); binWriter.Write(Xbox_EndianSwap.endSwapF32(bbDat[i].Y)); binWriter.Write(Xbox_EndianSwap.endSwapF32(bbDat[i].Z)); binWriter.Write(Xbox_EndianSwap.endSwapF32(bbDat[i].W)); } ExportTo360.mECF.addChunk((int)eXTD_ChunkID.cXTD_TessChunk, chunkHolder, binWriter.BaseStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; results.terrainTessValuesMemorySize = tDat.Length + (bbDat.Length * sizeof(float) * 4); tDat = null; bbDat = null; }