private BabylonMesh ConvertUnityTerrainToBabylon(Terrain terrain, GameObject gameObject, float progress, ref UnityMetaData metaData, ref List<BabylonExport.Entities.BabylonParticleSystem> particleSystems, ref List<UnityFlareSystem> lensFlares, ref string componentTags)
{
ExporterWindow.ReportProgress(progress, "Exporting terrain: " + gameObject.name);
var transform = gameObject.transform;
float[] position = transform.localPosition.ToFloat();
float[] rotation = new float[3];
rotation[0] = transform.localRotation.eulerAngles.x * (float)Math.PI / 180;
rotation[1] = transform.localRotation.eulerAngles.y * (float)Math.PI / 180;
rotation[2] = transform.localRotation.eulerAngles.z * (float)Math.PI / 180;
float[] scaling = transform.localScale.ToFloat();
BabylonMesh babylonMesh = new BabylonMesh { name = gameObject.name, id = GetID(gameObject) };
metaData.type = "Terrain";
if (!String.IsNullOrEmpty(componentTags))
{
babylonMesh.tags = componentTags;
}
babylonMesh.tags += " [TERRAIN]";
if (!String.IsNullOrEmpty(babylonMesh.tags))
{
babylonMesh.tags = babylonMesh.tags.Trim();
}
babylonMesh.parentId = GetParentID(transform);
babylonMesh.position = Vector3.zero.ToFloat();
babylonMesh.rotation = rotation;
babylonMesh.scaling = scaling;
babylonMesh.isVisible = true;
babylonMesh.visibility = 1;
babylonMesh.checkCollisions = false;
metaData.properties["collisionMeshId"] = null;
var generator = gameObject.GetComponent<BabylonTerrainGenerator>();
if (generator != null && terrain != null)
{
// TODO: Terrain tree information
object treeInstances = null;
object treePrototypes = null;
// Terrain metadata infomation
Vector3 terrainSize = terrain.terrainData.size;
metaData.properties.Add("width", terrainSize.x);
metaData.properties.Add("length", terrainSize.z);
metaData.properties.Add("height", terrainSize.y);
metaData.properties.Add("position", position);
metaData.properties.Add("rotation", rotation);
metaData.properties.Add("scaling", scaling);
metaData.properties.Add("thickness", terrain.terrainData.thickness);
metaData.properties.Add("detailWidth", terrain.terrainData.detailWidth);
metaData.properties.Add("detailHeight", terrain.terrainData.detailHeight);
metaData.properties.Add("heightmapWidth", terrain.terrainData.heightmapWidth);
metaData.properties.Add("heightmapHeight", terrain.terrainData.heightmapHeight);
metaData.properties.Add("wavingGrassAmount", terrain.terrainData.wavingGrassAmount);
metaData.properties.Add("wavingGrassSpeed", terrain.terrainData.wavingGrassSpeed);
metaData.properties.Add("wavingGrassStrength", terrain.terrainData.wavingGrassStrength);
metaData.properties.Add("wavingGrassTint", terrain.terrainData.wavingGrassTint.ToFloat());
metaData.properties.Add("treeInstanceCount", terrain.terrainData.treeInstanceCount);
metaData.properties.Add("treeInstances", treeInstances);
metaData.properties.Add("treePrototypes", treePrototypes);
metaData.properties.Add("physicsState", generator.physicsActive);
metaData.properties.Add("physicsMass", generator.physicsMass);
metaData.properties.Add("physicsFriction", generator.physicsFriction);
metaData.properties.Add("physicsRestitution", generator.physicsRestitution);
metaData.properties.Add("physicsImpostor", (int)generator.physicsImpostor);
metaData.properties.Add("groundTessellation", generator.groundTessellation);
// Generate detailed mesh
ExporterWindow.ReportProgress(progress, "Generating terrain mesh: " + gameObject.name);
BabylonTerrainData terrainMeshData = Unity3D2Babylon.Tools.CreateTerrainData(terrain.terrainData, (int)generator.terrainResolution, transform.localPosition, true);
Tools.GenerateBabylonMeshTerrainData(terrainMeshData, babylonMesh, false, babylonScene, transform);
if (generator.surfaceMaterial != null)
{
babylonMesh.materialId = DumpMaterial(generator.surfaceMaterial, terrain.lightmapIndex, terrain.lightmapScaleOffset, generator.coordinatesIndex).id;
}
// Generate collision heightmap
var terrainCollider = gameObject.GetComponent<TerrainCollider>();
if (terrainCollider != null && terrainCollider.enabled)
{
ExporterWindow.ReportProgress(progress, "Generating terrain heightmap: " + gameObject.name);
float minheight = float.MaxValue;
float maxheight = float.MinValue;
int hwidth = terrain.terrainData.heightmapWidth;
int hheight = terrain.terrainData.heightmapHeight;
float[,] rawHeights = terrain.terrainData.GetHeights(0, 0, hwidth, hheight);
Texture2D heightMap = new Texture2D(hwidth, hheight, TextureFormat.ARGB32, false);
for (int y = 0; y < hheight; y++)
{
for (int x = 0; x < hwidth; x++)
{
float inverted = rawHeights[y, x];
minheight = Mathf.Min(minheight, inverted);
maxheight = Mathf.Max(maxheight, inverted);
}
}
List<Color32> pixels = new List<Color32>();
for (int y = 0; y < hheight; y++)
{
for (int x = 0; x < hwidth; x++)
{
float inverted = rawHeights[y, x];
if (generator.heightmapStrength > 0)
{
float threadhold = minheight + generator.floorThreashold;
if (inverted > threadhold)
{
inverted += (generator.heightmapStrength / 10.0f);
}
}
byte[] packed = BitConverter.GetBytes(inverted);
if (packed != null && packed.Length >= 4)
{
pixels.Add(new Color32(packed[0], packed[1], packed[2], packed[3]));
}
}
}
heightMap.SetPixels32(pixels.ToArray());
heightMap.Apply();
byte[] heightmapBytes = heightMap.EncodeToPNG();
metaData.properties.Add("heightmapBase64", ("data:image/png;base64," + Convert.ToBase64String(heightmapBytes)));
}
}
else
{
UnityEngine.Debug.LogWarning("No valid terrain or generator found for: " + gameObject.name);
}
babylonMesh.metadata = metaData;
babylonScene.MeshesList.Add(babylonMesh);
SceneBuilder.Metadata.properties["hasTerrainMeshes"] = true;
// Animations
ExportAnimations(transform, babylonMesh);
if (IsRotationQuaternionAnimated(babylonMesh))
{
babylonMesh.rotationQuaternion = transform.localRotation.ToFloat();
}
// Lens Flares
ParseLensFlares(gameObject, babylonMesh.id, ref lensFlares);
// Particles Systems
ParseParticleSystems(gameObject, babylonMesh.id, ref particleSystems);
return babylonMesh;
}