add per-tile min/max elevation support
This commit is contained in:
@@ -53,6 +53,8 @@ public static class GeoTileAddressablesBuilder
|
||||
public double Ymin;
|
||||
public double GlobalMin;
|
||||
public double GlobalMax;
|
||||
public double TileMin;
|
||||
public double TileMax;
|
||||
}
|
||||
|
||||
internal struct BuildRequest
|
||||
@@ -348,7 +350,9 @@ public static class GeoTileAddressablesBuilder
|
||||
tileId = tile.TileId,
|
||||
offsetX = (float)(tile.Xmin - minX),
|
||||
offsetZ = (float)(tile.Ymin - minY),
|
||||
baseY = (float)tile.GlobalMin
|
||||
baseY = (float)tile.TileMin,
|
||||
tileMin = (float)tile.TileMin,
|
||||
tileMax = (float)tile.TileMax
|
||||
};
|
||||
}
|
||||
|
||||
@@ -405,6 +409,8 @@ public static class GeoTileAddressablesBuilder
|
||||
int IDX_YMIN = headerMap["ymin"];
|
||||
int IDX_GMIN = headerMap["global_min"];
|
||||
int IDX_GMAX = headerMap["global_max"];
|
||||
int IDX_TMIN = headerMap.TryGetValue("tile_min", out var idxTileMin) ? idxTileMin : -1;
|
||||
int IDX_TMAX = headerMap.TryGetValue("tile_max", out var idxTileMax) ? idxTileMax : -1;
|
||||
int IDX_TILE_KEY = headerMap.TryGetValue("tile_key", out var idxTileKey) ? idxTileKey : -1;
|
||||
|
||||
for (int i = 1; i < lines.Length; i++)
|
||||
@@ -417,6 +423,10 @@ public static class GeoTileAddressablesBuilder
|
||||
int maxIdx = Math.Max(IDX_TILE, Math.Max(IDX_XMIN, Math.Max(IDX_YMIN, Math.Max(IDX_GMIN, IDX_GMAX))));
|
||||
if (IDX_TILE_KEY >= 0)
|
||||
maxIdx = Math.Max(maxIdx, IDX_TILE_KEY);
|
||||
if (IDX_TMIN >= 0)
|
||||
maxIdx = Math.Max(maxIdx, IDX_TMIN);
|
||||
if (IDX_TMAX >= 0)
|
||||
maxIdx = Math.Max(maxIdx, IDX_TMAX);
|
||||
if (parts.Length <= maxIdx)
|
||||
continue;
|
||||
|
||||
@@ -426,6 +436,16 @@ public static class GeoTileAddressablesBuilder
|
||||
var ymin = double.Parse(parts[IDX_YMIN], ci);
|
||||
var tileKeyRaw = IDX_TILE_KEY >= 0 ? parts[IDX_TILE_KEY].Trim() : "";
|
||||
var tileKey = ResolveTileKey(tileKeyRaw, xmin, ymin, tileKeyConfig, out var xKey, out var yKey);
|
||||
var globalMin = double.Parse(parts[IDX_GMIN], ci);
|
||||
var globalMax = double.Parse(parts[IDX_GMAX], ci);
|
||||
double tileMin = globalMin;
|
||||
double tileMax = globalMax;
|
||||
if (IDX_TMIN >= 0 && IDX_TMIN < parts.Length &&
|
||||
double.TryParse(parts[IDX_TMIN], NumberStyles.Float, ci, out var parsedTileMin))
|
||||
tileMin = parsedTileMin;
|
||||
if (IDX_TMAX >= 0 && IDX_TMAX < parts.Length &&
|
||||
double.TryParse(parts[IDX_TMAX], NumberStyles.Float, ci, out var parsedTileMax))
|
||||
tileMax = parsedTileMax;
|
||||
|
||||
tiles.Add(new TileRecord
|
||||
{
|
||||
@@ -435,8 +455,10 @@ public static class GeoTileAddressablesBuilder
|
||||
YKey = yKey,
|
||||
Xmin = xmin,
|
||||
Ymin = ymin,
|
||||
GlobalMin = double.Parse(parts[IDX_GMIN], ci),
|
||||
GlobalMax = double.Parse(parts[IDX_GMAX], ci)
|
||||
GlobalMin = globalMin,
|
||||
GlobalMax = globalMax,
|
||||
TileMin = tileMin,
|
||||
TileMax = tileMax
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@@ -149,7 +149,7 @@ public class GeoTileImporter : EditorWindow
|
||||
|
||||
EditorGUILayout.HelpBox(
|
||||
"Creates one Unity Terrain per CSV row and positions tiles on a meter grid.\n" +
|
||||
"Absolute elevation mapping: Terrain Y = global_min, Terrain height = (global_max - global_min).\n" +
|
||||
"Absolute elevation mapping: Terrain Y = tile_min (fallback global_min), Terrain height = (tile_max - tile_min).\n" +
|
||||
"CSV is header-driven (order-independent). Optionally applies ortho JPGs and instantiates buildings/trees GLBs.",
|
||||
MessageType.Info);
|
||||
|
||||
@@ -336,7 +336,7 @@ public class GeoTileImporter : EditorWindow
|
||||
|
||||
int imported = 0, skipped = 0;
|
||||
int importedTextures = 0;
|
||||
var placements = new List<(string tileId, float ux, float uz, float gmin)>();
|
||||
var placements = new List<(string tileId, float ux, float uz, float baseY)>();
|
||||
|
||||
for (int i = 0; i < selectedTiles.Count; i++)
|
||||
{
|
||||
@@ -344,17 +344,17 @@ public class GeoTileImporter : EditorWindow
|
||||
var tileId = tile.TileId;
|
||||
double xmin = tile.Xmin;
|
||||
double ymin = tile.Ymin;
|
||||
double gmin = tile.GlobalMin;
|
||||
double gmax = tile.GlobalMax;
|
||||
double baseMin = tile.TileMin;
|
||||
double baseMax = tile.TileMax;
|
||||
|
||||
if (tile.OutRes != heightmapResolution)
|
||||
Debug.LogWarning($"[GeoTileImporter] Tile {tileId}: out_res={tile.OutRes} but importer expects {heightmapResolution}.");
|
||||
|
||||
float heightRange = (float)(gmax - gmin);
|
||||
float heightRange = (float)(baseMax - baseMin);
|
||||
if (heightRange <= 0.0001f)
|
||||
{
|
||||
skipped++;
|
||||
Debug.LogWarning($"[GeoTileImporter] Tile {tileId}: invalid height range (global_max <= global_min). Skipping.");
|
||||
Debug.LogWarning($"[GeoTileImporter] Tile {tileId}: invalid height range (tile_max <= tile_min). Skipping.");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -422,7 +422,7 @@ public class GeoTileImporter : EditorWindow
|
||||
|
||||
float ux = (float)(xmin - originX);
|
||||
float uz = (float)(ymin - originY);
|
||||
go.transform.position = new Vector3(ux, (float)gmin, uz);
|
||||
go.transform.position = new Vector3(ux, (float)baseMin, uz);
|
||||
|
||||
var terrain = go.GetComponent<Terrain>();
|
||||
terrain.drawInstanced = true;
|
||||
@@ -463,9 +463,9 @@ public class GeoTileImporter : EditorWindow
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"[GeoTileImporter] Imported {tileId} ({tile.TileKey}) @ XZ=({ux},{uz}) Y={gmin} heightRange={heightRange} usedU16={usedU16}");
|
||||
Debug.Log($"[GeoTileImporter] Imported {tileId} ({tile.TileKey}) @ XZ=({ux},{uz}) Y={baseMin} heightRange={heightRange} usedU16={usedU16}");
|
||||
imported++;
|
||||
placements.Add((tileId, ux, uz, (float)gmin));
|
||||
placements.Add((tileId, ux, uz, (float)baseMin));
|
||||
}
|
||||
|
||||
Debug.Log($"[GeoTileImporter] DONE. Imported={imported}, Skipped={skipped}, OrthoApplied={importedTextures} under '{parentName}'.");
|
||||
@@ -672,6 +672,8 @@ public class GeoTileImporter : EditorWindow
|
||||
int IDX_GMIN = headerMap["global_min"];
|
||||
int IDX_GMAX = headerMap["global_max"];
|
||||
int IDX_RES = headerMap["out_res"];
|
||||
int IDX_TMIN = headerMap.ContainsKey("tile_min") ? headerMap["tile_min"] : -1;
|
||||
int IDX_TMAX = headerMap.ContainsKey("tile_max") ? headerMap["tile_max"] : -1;
|
||||
int IDX_TILE_KEY = headerMap.ContainsKey("tile_key") ? headerMap["tile_key"] : -1;
|
||||
|
||||
for (int i = 1; i < lines.Length; i++)
|
||||
@@ -684,6 +686,10 @@ public class GeoTileImporter : EditorWindow
|
||||
int needMaxIndex = Math.Max(Math.Max(Math.Max(Math.Max(IDX_TILE, IDX_XMIN), IDX_YMIN), IDX_GMIN), Math.Max(IDX_GMAX, IDX_RES));
|
||||
if (IDX_TILE_KEY >= 0)
|
||||
needMaxIndex = Math.Max(needMaxIndex, IDX_TILE_KEY);
|
||||
if (IDX_TMIN >= 0)
|
||||
needMaxIndex = Math.Max(needMaxIndex, IDX_TMIN);
|
||||
if (IDX_TMAX >= 0)
|
||||
needMaxIndex = Math.Max(needMaxIndex, IDX_TMAX);
|
||||
|
||||
if (parts.Length <= needMaxIndex)
|
||||
{
|
||||
@@ -697,6 +703,16 @@ public class GeoTileImporter : EditorWindow
|
||||
var ymin = double.Parse(parts[IDX_YMIN], ci);
|
||||
var tileKeyRaw = IDX_TILE_KEY >= 0 ? parts[IDX_TILE_KEY].Trim() : "";
|
||||
var tileKey = ResolveTileKey(tileKeyRaw, xmin, ymin, out var xKey, out var yKey);
|
||||
var globalMin = double.Parse(parts[IDX_GMIN], ci);
|
||||
var globalMax = double.Parse(parts[IDX_GMAX], ci);
|
||||
double tileMin = globalMin;
|
||||
double tileMax = globalMax;
|
||||
if (IDX_TMIN >= 0 && IDX_TMIN < parts.Length &&
|
||||
double.TryParse(parts[IDX_TMIN], NumberStyles.Float, ci, out var parsedTileMin))
|
||||
tileMin = parsedTileMin;
|
||||
if (IDX_TMAX >= 0 && IDX_TMAX < parts.Length &&
|
||||
double.TryParse(parts[IDX_TMAX], NumberStyles.Float, ci, out var parsedTileMax))
|
||||
tileMax = parsedTileMax;
|
||||
|
||||
tiles.Add(new TileRecord
|
||||
{
|
||||
@@ -706,8 +722,10 @@ public class GeoTileImporter : EditorWindow
|
||||
YKey = yKey,
|
||||
Xmin = xmin,
|
||||
Ymin = ymin,
|
||||
GlobalMin = double.Parse(parts[IDX_GMIN], ci),
|
||||
GlobalMax = double.Parse(parts[IDX_GMAX], ci),
|
||||
GlobalMin = globalMin,
|
||||
GlobalMax = globalMax,
|
||||
TileMin = tileMin,
|
||||
TileMax = tileMax,
|
||||
OutRes = int.Parse(parts[IDX_RES], ci)
|
||||
});
|
||||
}
|
||||
@@ -775,6 +793,8 @@ public class GeoTileImporter : EditorWindow
|
||||
public double Ymin;
|
||||
public double GlobalMin;
|
||||
public double GlobalMax;
|
||||
public double TileMin;
|
||||
public double TileMax;
|
||||
public int OutRes;
|
||||
}
|
||||
|
||||
@@ -786,7 +806,7 @@ public class GeoTileImporter : EditorWindow
|
||||
}
|
||||
|
||||
|
||||
private void ImportBuildings(List<(string tileId, float ux, float uz, float gmin)> placements)
|
||||
private void ImportBuildings(List<(string tileId, float ux, float uz, float baseY)> placements)
|
||||
{
|
||||
if (!importBuildings)
|
||||
return;
|
||||
@@ -810,7 +830,7 @@ public class GeoTileImporter : EditorWindow
|
||||
}
|
||||
|
||||
int imported = 0, missing = 0;
|
||||
foreach (var (tileId, ux, uz, gmin) in placements)
|
||||
foreach (var (tileId, ux, uz, baseY) in placements)
|
||||
{
|
||||
string glbPath = Path.Combine(activeDir, $"{tileId}.glb").Replace("\\", "/");
|
||||
if (!File.Exists(glbPath))
|
||||
@@ -831,7 +851,7 @@ public class GeoTileImporter : EditorWindow
|
||||
var inst = PrefabUtility.InstantiatePrefab(prefab) as GameObject ?? Instantiate(prefab);
|
||||
inst.name = tileId;
|
||||
inst.transform.SetParent(parent.transform, false);
|
||||
inst.transform.position = new Vector3(ux, gmin, uz);
|
||||
inst.transform.position = new Vector3(ux, baseY, uz);
|
||||
inst.transform.localRotation = Quaternion.Euler(0f, 180f, 0f);
|
||||
inst.isStatic = true;
|
||||
imported++;
|
||||
@@ -840,7 +860,7 @@ public class GeoTileImporter : EditorWindow
|
||||
Debug.Log($"[GeoTileImporter] Buildings ({sourceLabel}) imported={imported}, missing/failed={missing} under '{buildingsParentName}'.");
|
||||
}
|
||||
|
||||
private void ImportTrees(List<(string tileId, float ux, float uz, float gmin)> placements)
|
||||
private void ImportTrees(List<(string tileId, float ux, float uz, float baseY)> placements)
|
||||
{
|
||||
if (!importTrees)
|
||||
return;
|
||||
@@ -865,7 +885,7 @@ public class GeoTileImporter : EditorWindow
|
||||
}
|
||||
|
||||
int importedTiles = 0, importedChunks = 0, missingTiles = 0;
|
||||
foreach (var (tileId, ux, uz, gmin) in placements)
|
||||
foreach (var (tileId, ux, uz, baseY) in placements)
|
||||
{
|
||||
// Look for chunk files: {tileId}_0_0.glb, {tileId}_0_1.glb, etc.
|
||||
// Standard tree export creates 4x4 chunks per tile
|
||||
@@ -889,7 +909,7 @@ public class GeoTileImporter : EditorWindow
|
||||
// Create container for this tile's tree chunks
|
||||
var tileContainer = new GameObject($"Trees_{tileId}");
|
||||
tileContainer.transform.SetParent(parent.transform, false);
|
||||
tileContainer.transform.position = new Vector3(ux, gmin, uz);
|
||||
tileContainer.transform.position = new Vector3(ux, baseY, uz);
|
||||
tileContainer.transform.localRotation = Quaternion.Euler(0f, 180f, 0f);
|
||||
tileContainer.isStatic = true;
|
||||
|
||||
@@ -917,7 +937,7 @@ public class GeoTileImporter : EditorWindow
|
||||
Debug.Log($"[GeoTileImporter] Trees imported: {importedTiles} tiles, {importedChunks} chunks, {missingTiles} missing under '{treesParentName}'.");
|
||||
}
|
||||
|
||||
private void ImportFurniture(List<(string tileId, float ux, float uz, float gmin)> placements)
|
||||
private void ImportFurniture(List<(string tileId, float ux, float uz, float baseY)> placements)
|
||||
{
|
||||
if (!importFurniture)
|
||||
return;
|
||||
@@ -939,7 +959,7 @@ public class GeoTileImporter : EditorWindow
|
||||
int imported = 0, skipped = 0;
|
||||
var ci = CultureInfo.InvariantCulture;
|
||||
|
||||
foreach (var (tileId, ux, uz, gmin) in placements)
|
||||
foreach (var (tileId, ux, uz, baseY) in placements)
|
||||
{
|
||||
string csvPath = Path.Combine(furnitureDir, $"{tileId}.csv").Replace("\\", "/");
|
||||
if (!File.Exists(csvPath))
|
||||
@@ -973,7 +993,7 @@ public class GeoTileImporter : EditorWindow
|
||||
// Create tile container
|
||||
var tileContainer = new GameObject($"Furniture_{tileId}");
|
||||
tileContainer.transform.SetParent(parent.transform, false);
|
||||
tileContainer.transform.position = new Vector3(ux, gmin, uz);
|
||||
tileContainer.transform.position = new Vector3(ux, baseY, uz);
|
||||
tileContainer.isStatic = true;
|
||||
|
||||
for (int i = 1; i < lines.Length; i++)
|
||||
@@ -1044,7 +1064,7 @@ public class GeoTileImporter : EditorWindow
|
||||
}
|
||||
|
||||
obj.transform.SetParent(tileContainer.transform, false);
|
||||
obj.transform.localPosition = new Vector3(xLocal, zGround - gmin, yLocal);
|
||||
obj.transform.localPosition = new Vector3(xLocal, zGround - baseY, yLocal);
|
||||
obj.isStatic = true;
|
||||
imported++;
|
||||
}
|
||||
@@ -1059,7 +1079,7 @@ public class GeoTileImporter : EditorWindow
|
||||
Debug.Log($"[GeoTileImporter] Furniture imported={imported}, skipped={skipped} under '{furnitureParentName}'.");
|
||||
}
|
||||
|
||||
private void ImportEnhancedTrees(List<(string tileId, float ux, float uz, float gmin)> placements)
|
||||
private void ImportEnhancedTrees(List<(string tileId, float ux, float uz, float baseY)> placements)
|
||||
{
|
||||
if (!importEnhancedTrees)
|
||||
return;
|
||||
@@ -1081,7 +1101,7 @@ public class GeoTileImporter : EditorWindow
|
||||
int imported = 0, skipped = 0;
|
||||
var ci = CultureInfo.InvariantCulture;
|
||||
|
||||
foreach (var (tileId, ux, uz, gmin) in placements)
|
||||
foreach (var (tileId, ux, uz, baseY) in placements)
|
||||
{
|
||||
string csvPath = Path.Combine(enhancedTreesDir, $"{tileId}.csv").Replace("\\", "/");
|
||||
if (!File.Exists(csvPath))
|
||||
@@ -1119,7 +1139,7 @@ public class GeoTileImporter : EditorWindow
|
||||
// Create tile container
|
||||
var tileContainer = new GameObject($"Trees_{tileId}");
|
||||
tileContainer.transform.SetParent(parent.transform, false);
|
||||
tileContainer.transform.position = new Vector3(ux, gmin, uz);
|
||||
tileContainer.transform.position = new Vector3(ux, baseY, uz);
|
||||
tileContainer.isStatic = true;
|
||||
|
||||
for (int i = 1; i < lines.Length; i++)
|
||||
@@ -1217,7 +1237,7 @@ public class GeoTileImporter : EditorWindow
|
||||
}
|
||||
|
||||
treeObj.transform.SetParent(tileContainer.transform, false);
|
||||
treeObj.transform.localPosition = new Vector3(xLocal, zGround - gmin, yLocal);
|
||||
treeObj.transform.localPosition = new Vector3(xLocal, zGround - baseY, yLocal);
|
||||
treeObj.isStatic = true;
|
||||
imported++;
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ public class GeoTilePrefabImporter : EditorWindow
|
||||
public int YKey;
|
||||
public double Xmin, Ymin, Xmax, Ymax;
|
||||
public double GlobalMin, GlobalMax;
|
||||
public double TileMin, TileMax;
|
||||
public int OutRes;
|
||||
}
|
||||
|
||||
@@ -144,6 +145,7 @@ public class GeoTilePrefabImporter : EditorWindow
|
||||
"Creates one .prefab asset per tile in the manifest.\n" +
|
||||
"Each prefab contains: Terrain (with TerrainData), Buildings, Trees, Furniture.\n" +
|
||||
"TerrainData and TerrainLayers are saved as separate .asset files.\n" +
|
||||
"Per-tile elevation: uses tile_min/tile_max when present (falls back to global_min/global_max).\n" +
|
||||
"IMPORTANT: Use 'Place All Prefabs in Scene' to position tiles correctly.",
|
||||
MessageType.Info);
|
||||
|
||||
@@ -495,6 +497,8 @@ public class GeoTilePrefabImporter : EditorWindow
|
||||
int IDX_YMAX = headerMap["ymax"];
|
||||
int IDX_GMIN = headerMap["global_min"];
|
||||
int IDX_GMAX = headerMap["global_max"];
|
||||
int IDX_TMIN = headerMap.ContainsKey("tile_min") ? headerMap["tile_min"] : -1;
|
||||
int IDX_TMAX = headerMap.ContainsKey("tile_max") ? headerMap["tile_max"] : -1;
|
||||
int IDX_RES = headerMap["out_res"];
|
||||
int IDX_TILE_KEY = headerMap.ContainsKey("tile_key") ? headerMap["tile_key"] : -1;
|
||||
|
||||
@@ -509,6 +513,10 @@ public class GeoTilePrefabImporter : EditorWindow
|
||||
Math.Max(Math.Max(IDX_YMAX, IDX_GMIN), Math.Max(IDX_GMAX, IDX_RES)));
|
||||
if (IDX_TILE_KEY >= 0)
|
||||
maxIdx = Math.Max(maxIdx, IDX_TILE_KEY);
|
||||
if (IDX_TMIN >= 0)
|
||||
maxIdx = Math.Max(maxIdx, IDX_TMIN);
|
||||
if (IDX_TMAX >= 0)
|
||||
maxIdx = Math.Max(maxIdx, IDX_TMAX);
|
||||
if (parts.Length <= maxIdx)
|
||||
{
|
||||
Debug.LogWarning($"[GeoTilePrefabImporter] Skipping line {i + 1}: too few columns.");
|
||||
@@ -521,6 +529,16 @@ public class GeoTilePrefabImporter : EditorWindow
|
||||
var ymin = double.Parse(parts[IDX_YMIN], ci);
|
||||
var tileKeyRaw = IDX_TILE_KEY >= 0 ? parts[IDX_TILE_KEY].Trim() : "";
|
||||
var tileKey = ResolveTileKey(tileKeyRaw, xmin, ymin, out var xKey, out var yKey);
|
||||
var globalMin = double.Parse(parts[IDX_GMIN], ci);
|
||||
var globalMax = double.Parse(parts[IDX_GMAX], ci);
|
||||
double tileMin = globalMin;
|
||||
double tileMax = globalMax;
|
||||
if (IDX_TMIN >= 0 && IDX_TMIN < parts.Length &&
|
||||
double.TryParse(parts[IDX_TMIN], NumberStyles.Float, ci, out var parsedTileMin))
|
||||
tileMin = parsedTileMin;
|
||||
if (IDX_TMAX >= 0 && IDX_TMAX < parts.Length &&
|
||||
double.TryParse(parts[IDX_TMAX], NumberStyles.Float, ci, out var parsedTileMax))
|
||||
tileMax = parsedTileMax;
|
||||
|
||||
tiles.Add(new TileMetadata
|
||||
{
|
||||
@@ -532,8 +550,10 @@ public class GeoTilePrefabImporter : EditorWindow
|
||||
Ymin = ymin,
|
||||
Xmax = double.Parse(parts[IDX_XMAX], ci),
|
||||
Ymax = double.Parse(parts[IDX_YMAX], ci),
|
||||
GlobalMin = double.Parse(parts[IDX_GMIN], ci),
|
||||
GlobalMax = double.Parse(parts[IDX_GMAX], ci),
|
||||
GlobalMin = globalMin,
|
||||
GlobalMax = globalMax,
|
||||
TileMin = tileMin,
|
||||
TileMax = tileMax,
|
||||
OutRes = int.Parse(parts[IDX_RES], ci)
|
||||
});
|
||||
}
|
||||
@@ -601,7 +621,7 @@ public class GeoTilePrefabImporter : EditorWindow
|
||||
private bool CreateTilePrefab(TileMetadata tile)
|
||||
{
|
||||
// Validate height range
|
||||
float heightRange = (float)(tile.GlobalMax - tile.GlobalMin);
|
||||
float heightRange = (float)(tile.TileMax - tile.TileMin);
|
||||
if (heightRange <= 0.0001f)
|
||||
{
|
||||
Debug.LogWarning($"[GeoTilePrefabImporter] Tile {tile.TileId}: invalid height range. Skipping.");
|
||||
@@ -686,6 +706,8 @@ public class GeoTilePrefabImporter : EditorWindow
|
||||
metadata.ymin = tile.Ymin;
|
||||
metadata.globalMin = tile.GlobalMin;
|
||||
metadata.globalMax = tile.GlobalMax;
|
||||
metadata.tileMin = tile.TileMin;
|
||||
metadata.tileMax = tile.TileMax;
|
||||
|
||||
// Add child components
|
||||
if (includeBuildings)
|
||||
@@ -769,15 +791,15 @@ public class GeoTilePrefabImporter : EditorWindow
|
||||
}
|
||||
|
||||
// Building GLB vertices have absolute Z (elevation) from CityGML.
|
||||
// Since prefab root will be at Y=gmin when placed, offset buildings by -gmin
|
||||
// so building world Y = gmin + (-gmin) + GLB_Y = GLB_Y (correct absolute elevation)
|
||||
// Since prefab root will be at Y=tile_min when placed, offset buildings by -tile_min
|
||||
// so building world Y = tile_min + (-tile_min) + GLB_Y = GLB_Y (correct absolute elevation)
|
||||
var instance = PrefabUtility.InstantiatePrefab(buildingPrefab) as GameObject;
|
||||
if (instance == null)
|
||||
instance = Instantiate(buildingPrefab);
|
||||
|
||||
instance.name = "Buildings";
|
||||
instance.transform.SetParent(root.transform, false);
|
||||
instance.transform.localPosition = new Vector3(0f, -(float)tile.GlobalMin, 0f);
|
||||
instance.transform.localPosition = new Vector3(0f, -(float)tile.TileMin, 0f);
|
||||
instance.transform.localRotation = Quaternion.Euler(0f, 180f, 0f);
|
||||
instance.isStatic = true;
|
||||
}
|
||||
@@ -799,11 +821,11 @@ public class GeoTilePrefabImporter : EditorWindow
|
||||
}
|
||||
|
||||
// Tree GLB vertices use absolute elevation (z_ground from DGM).
|
||||
// Since prefab root will be at Y=gmin when placed, offset trees by -gmin
|
||||
// so tree world Y = gmin + (-gmin) + GLB_Y = GLB_Y (correct absolute elevation)
|
||||
// Since prefab root will be at Y=tile_min when placed, offset trees by -tile_min
|
||||
// so tree world Y = tile_min + (-tile_min) + GLB_Y = GLB_Y (correct absolute elevation)
|
||||
var treesContainer = new GameObject("Trees");
|
||||
treesContainer.transform.SetParent(root.transform, false);
|
||||
treesContainer.transform.localPosition = new Vector3(0f, -(float)tile.GlobalMin, 0f);
|
||||
treesContainer.transform.localPosition = new Vector3(0f, -(float)tile.TileMin, 0f);
|
||||
treesContainer.transform.localRotation = Quaternion.Euler(0f, 180f, 0f);
|
||||
treesContainer.isStatic = true;
|
||||
|
||||
@@ -863,7 +885,7 @@ public class GeoTilePrefabImporter : EditorWindow
|
||||
furnitureContainer.transform.localPosition = Vector3.zero;
|
||||
furnitureContainer.isStatic = true;
|
||||
|
||||
float gmin = (float)tile.GlobalMin;
|
||||
float baseY = (float)tile.TileMin;
|
||||
|
||||
for (int i = 1; i < lines.Length; i++)
|
||||
{
|
||||
@@ -883,7 +905,7 @@ public class GeoTilePrefabImporter : EditorWindow
|
||||
|
||||
GameObject obj = CreateFurnitureObject(furnitureType, height, i);
|
||||
obj.transform.SetParent(furnitureContainer.transform, false);
|
||||
obj.transform.localPosition = new Vector3(xLocal, zGround - gmin, yLocal);
|
||||
obj.transform.localPosition = new Vector3(xLocal, zGround - baseY, yLocal);
|
||||
obj.isStatic = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -978,7 +1000,7 @@ public class GeoTilePrefabImporter : EditorWindow
|
||||
treesContainer.transform.localPosition = Vector3.zero;
|
||||
treesContainer.isStatic = true;
|
||||
|
||||
float gmin = (float)tile.GlobalMin;
|
||||
float baseY = (float)tile.TileMin;
|
||||
|
||||
for (int i = 1; i < lines.Length; i++)
|
||||
{
|
||||
@@ -1008,7 +1030,7 @@ public class GeoTilePrefabImporter : EditorWindow
|
||||
|
||||
GameObject treeObj = CreateEnhancedTree(height, radius, canopyColor, i);
|
||||
treeObj.transform.SetParent(treesContainer.transform, false);
|
||||
treeObj.transform.localPosition = new Vector3(xLocal, zGround - gmin, yLocal);
|
||||
treeObj.transform.localPosition = new Vector3(xLocal, zGround - baseY, yLocal);
|
||||
treeObj.isStatic = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@@ -12,15 +12,18 @@ public class GeoTileMetadata : MonoBehaviour
|
||||
public double ymin;
|
||||
public double globalMin;
|
||||
public double globalMax;
|
||||
public double tileMin;
|
||||
public double tileMax;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the world position this tile should be placed at, given a global origin.
|
||||
/// </summary>
|
||||
public Vector3 GetWorldPosition(double originX, double originY)
|
||||
{
|
||||
double baseY = tileMax > tileMin ? tileMin : globalMin;
|
||||
return new Vector3(
|
||||
(float)(xmin - originX),
|
||||
(float)globalMin,
|
||||
(float)baseY,
|
||||
(float)(ymin - originY)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,4 +18,6 @@ public class TileEntry
|
||||
public float offsetX;
|
||||
public float offsetZ;
|
||||
public float baseY;
|
||||
public float tileMin;
|
||||
public float tileMax;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user