Skip to content

Commit

Permalink
MGEXEgui: Refactor distant landscape generation.
Browse files Browse the repository at this point in the history
  • Loading branch information
Hrnchamd committed Apr 8, 2023
1 parent 6af5a51 commit 4f2c844
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 50 deletions.
41 changes: 20 additions & 21 deletions MGEfuncs/LandTessellator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,13 @@ class LandMesh {
}

static bool SaveMeshes(LPCSTR file_path, vector<LandMesh>& meshes) {
DWORD mesh_count, unused;
HANDLE file = CreateFile(file_path,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0);
HANDLE file = CreateFile(file_path, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
if (file == INVALID_HANDLE_VALUE) {
return false;
}
mesh_count = meshes.size();
WriteFile(file, &mesh_count, 4, &unused, 0 );

DWORD unused, mesh_count = meshes.size();
WriteFile(file, &mesh_count, sizeof(mesh_count), &unused, 0);

for (size_t i = 0; i < meshes.size(); ++i) {
if (!meshes[i].Save(file)) {
Expand Down Expand Up @@ -174,15 +174,14 @@ class HeightFieldSampler {
float scaleX, scaleY;
};

float top, left, bottom, right;
float minX, minY, maxX, maxY;
float* data;
size_t data_height;
size_t data_width;
size_t data_width, data_height;
AtlasRegion* atlas_data;
size_t atlas_count;

HeightFieldSampler(float* d, size_t dh, size_t dw, float* adata, size_t ac, float t, float l, float b, float r) :
top(t), left(l), bottom(b), right(r), data(d), data_height(dh), data_width(dw),
HeightFieldSampler(float* d, size_t dw, size_t dh, float* adata, size_t ac, float _minX, float _minY, float _maxX, float _maxY) :
minX(_minX), minY(_minY), maxX(_maxX), maxY(_maxY), data(d), data_width(dw), data_height(dh),
atlas_data(reinterpret_cast<AtlasRegion*>(adata)), atlas_count(ac) {}
~HeightFieldSampler() {}

Expand All @@ -201,15 +200,15 @@ class HeightFieldSampler {

float SampleHeight(float x, float y) {
// Figure which height values to sample.
size_t low_x, high_x, low_y, high_y;
int low_x, high_x, low_y, high_y;

float data_x = (x - left) / 128.0f;
float data_y = (y - bottom) / 128.0f;
float data_x = (x - minX) / 128.0f;
float data_y = (y - minY) / 128.0f;

low_x = (size_t)floor(data_x);
high_x = (size_t)ceil(data_x);
low_y = (size_t)floor(data_y);
high_y = (size_t)ceil(data_y);
low_x = (int)floor(data_x);
high_x = (int)ceil(data_x);
low_y = (int)floor(data_y);
high_y = (int)ceil(data_y);

// Bilinear interpolation
float x_interp = data_x - (float)low_x;
Expand All @@ -224,7 +223,7 @@ class HeightFieldSampler {
return result;
}

float GetHeightValue(size_t x, size_t y) {
float GetHeightValue(int x, int y) {
if (x < 0) {
x = 0;
}
Expand Down Expand Up @@ -771,10 +770,10 @@ class RoamLandPatch {
}
};

extern "C" void TessellateLandscapeAtlased(char* file_path, float* height_data, unsigned int data_height, unsigned int data_width, float* atlas_data, unsigned int atlas_count, float top, float left, float bottom, float right, float error_tolerance) {
extern "C" void TessellateLandscapeAtlased(char* file_path, float* height_data, unsigned int data_width, unsigned int data_height, float* atlas_data, unsigned int atlas_count, float minX, float minY, float maxX, float maxY, float error_tolerance) {

// Create sampler
HeightFieldSampler sampler(height_data, data_height, data_width, atlas_data, atlas_count, top, left, bottom, right);
HeightFieldSampler sampler(height_data, data_width, data_height, atlas_data, atlas_count, minX, minY, maxX, maxY);

// Create patches
const float patch_width = 32768.0f, patch_height = 32768.0f;
Expand All @@ -783,7 +782,7 @@ extern "C" void TessellateLandscapeAtlased(char* file_path, float* height_data,

vector<RoamLandPatch> patches;

Vector3 corner(left, bottom, 0.0f);
Vector3 corner(minX, minY, 0.0f);

// Fill in patch data
patches.resize(patches_across * patches_down);
Expand All @@ -803,7 +802,7 @@ extern "C" void TessellateLandscapeAtlased(char* file_path, float* height_data,
}
// Move the corner up and back to the left edge for the next patch
corner.y += patch_height;
corner.x = left;
corner.x = minX;
}

// Connect neighboring patches
Expand Down
43 changes: 16 additions & 27 deletions MGEgui/DistantLand/DistantLandForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2224,32 +2224,27 @@ private static void GenerateMesh(LAND land, string path) {
/* Land mesh methods */

private void GenerateWorldMesh(int detail, string path) {
// Generate optimized landscape mesh
// Landscape detail selection
float tolerance = 125.0f;
if (detail >= 0 && detail <= 4) {
var toleranceOptions = new float[] { 15.0f, 70.0f, 125.0f, 180.0f, 235.0f };
tolerance = toleranceOptions[detail];
}

// Produce large heightmap array
int MapSpanX = MapMaxX - MapMinX + 1;
int MapSpanY = MapMaxY - MapMinY + 1;
int MapOffsetX = -MapMinX;
int MapOffsetY = -MapMinY;
int DataSpanX = MapSpanX * 64;
int DataSpanY = MapSpanY * 64;

int vCount = 64 / (1 << detail);
float vSpacing = 128f * (float)(1 << detail);
int VertsAcross = MapSpanX * vCount;
int VertsDown = MapSpanY * vCount;
int tFaces = (VertsAcross - 1) * (VertsDown - 1) * 2;
int tVerts = VertsAcross * VertsDown;
float texMultX = 1 / (float)VertsAcross;
float texMultY = 1 / (float)VertsDown;

// Produce large heightmap array
var height_data = new float[DataSpanX * DataSpanY];

for (int y1 = MapMinY; y1 <= MapMaxY; y1++) {
for (int y2 = 0; y2 < 64; y2++) {
for (int x1 = MapMinX; x1 <= MapMaxX; x1++) {
for (int x2 = 0; x2 < 64; x2++) {
int y = (y1 + MapOffsetY) * 64 + y2;
int x = (x1 + MapOffsetX) * 64 + x2;
int y = (y1 - MapMinY) * 64 + y2;
int x = (x1 - MapMinX) * 64 + x2;
if (LandMap[x1, y1] != null) {
height_data[y * DataSpanX + x] = (float)LandMap[x1, y1].Heights[x2, y2] * 8.0f;
} else {
Expand All @@ -2275,20 +2270,14 @@ private void GenerateWorldMesh(int detail, string path) {
iAtlas += 8;
}

float left = (float)(MapMinX * 64) * 128.0f;
float right = (float)((MapMaxX + 1) * 64) * 128.0f;
float bottom = (float)(MapMinY * 64) * 128.0f;
float top = (float)((MapMaxY + 1) * 64) * 128.0f;

// Landscape detail selection
float tolerance = 125.0f;
if (detail >= 0 && detail <= 4) {
var toleranceOptions = new float[] { 15.0f, 70.0f, 125.0f, 180.0f, 235.0f };
tolerance = toleranceOptions[detail];
}
// Generate optimized landscape mesh
float minX = (float)MapMinX * 8192.0f;
float maxX = (float)(MapMaxX + 1) * 8192.0f;
float minY = (float)MapMinY * 8192.0f;
float maxY = (float)(MapMaxY + 1) * 8192.0f;

backgroundWorker.ReportProgress(10, strings["LandTessellating"]);
NativeMethods.TessellateLandscapeAtlased(path, height_data, (uint)DataSpanY, (uint)DataSpanX, atlas_data, (uint)Atlas.Count, top, left, bottom, right, tolerance);
NativeMethods.TessellateLandscapeAtlased(path, height_data, (uint)DataSpanX, (uint)DataSpanY, atlas_data, (uint)Atlas.Count, minX, minY, maxX, maxY, tolerance);
}

/* Statics tab properties */
Expand Down
4 changes: 2 additions & 2 deletions MGEgui/Imports.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ internal static extern float ProcessNif(
[DllImport("MGE3/MGEfuncs.dll", CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Ansi, EntryPoint = "TessellateLandscapeAtlased")]
internal static extern void TessellateLandscapeAtlased([MarshalAs(UnmanagedType.LPStr)] string file_path,
[MarshalAs(UnmanagedType.LPArray)] float[] height_data, uint data_height, uint data_width,
[MarshalAs(UnmanagedType.LPArray)] float[] height_data, uint data_width, uint data_height,
[MarshalAs(UnmanagedType.LPArray)] float[] atlas_data, uint atlas_count,
float top, float left, float bottom, float right, float error_tolerance);
float minX, float minY, float maxX, float maxY, float error_tolerance);

[DllImport("MGE3/MGEfuncs.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "GetVertSize")]
internal static extern int GetVertSize();
Expand Down

0 comments on commit 4f2c844

Please sign in to comment.