Example #1
0
        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);
        }
Example #2
0
    void Export()
    {
        int                index       = 0;
        string             fileName    = EditorUtility.SaveFilePanel("Export Terrain File", "", "Terrain", "obj");
        BabylonMesh        babylonMesh = new BabylonMesh();
        BabylonTerrainData terrainData = Unity3D2Babylon.Tools.CreateTerrainData(terrain, (int)saveResolution, terrainObject.transform.localPosition, false);

        Unity3D2Babylon.Tools.GenerateBabylonMeshTerrainData(terrainData, babylonMesh, flipNormals);

        System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
        StreamWriter sw = new StreamWriter(fileName);

        try
        {
            // StringBuilder stuff is done this way because it's faster than using the "{0} {1} {2}"etc. format
            // Which is important when you're exporting huge terrains.
            sw.WriteLine("# U3D - BabylonJS - Terrain Mesh File");

            // Write vertices
            counter    = tCount = 0;
            totalCount = ((babylonMesh.positions.Length / 3) * 2 + (babylonMesh.indices.Length / 3)) / progressUpdateInterval;
            for (index = 0; index < babylonMesh.positions.Length / 3; index++)
            {
                UpdateProgress();
                StringBuilder sb = new StringBuilder("v ", 32);
                sb.Append(babylonMesh.positions[index * 3].ToString()).Append(" ").
                Append(babylonMesh.positions[index * 3 + 1].ToString()).Append(" ").
                Append(babylonMesh.positions[index * 3 + 2].ToString());
                sw.WriteLine(sb);
            }

            // Write normals
            for (index = 0; index < babylonMesh.normals.Length / 3; index++)
            {
                UpdateProgress();
                StringBuilder sb = new StringBuilder("vn ", 32);
                sb.Append(babylonMesh.normals[index * 3].ToString()).Append(" ").
                Append(babylonMesh.normals[index * 3 + 1].ToString()).Append(" ").
                Append(babylonMesh.normals[index * 3 + 2].ToString());
                sw.WriteLine(sb);
            }

            // Write uvs
            for (index = 0; index < babylonMesh.uvs.Length / 2; index++)
            {
                UpdateProgress();
                StringBuilder sb = new StringBuilder("vt ", 32);
                sb.Append(babylonMesh.uvs[index * 2].ToString()).Append(" ").
                Append(babylonMesh.uvs[index * 2 + 1].ToString());
                sw.WriteLine(sb);
            }

            // Write triangles
            for (int i = 0; i < babylonMesh.indices.Length; i += 3)
            {
                UpdateProgress();
                StringBuilder sb = new StringBuilder("f ", 64);
                sb.Append(babylonMesh.indices[i] + 1).Append("/").Append(babylonMesh.indices[i] + 1).Append(" ").
                Append(babylonMesh.indices[i + 1] + 1).Append("/").Append(babylonMesh.indices[i + 1] + 1).Append(" ").
                Append(babylonMesh.indices[i + 2] + 1).Append("/").Append(babylonMesh.indices[i + 2] + 1);
                sw.WriteLine(sb);
            }
        }
        catch (Exception err)
        {
            Debug.Log("Error saving file: " + err.Message);
        }
        sw.Close();

        terrain = null;
        EditorUtility.DisplayProgressBar("Babylon.js", "Saving terrain mesh data... This may take a while.", 1f);
        AssetDatabase.Refresh();
        EditorUtility.ClearProgressBar();
        this.Close();
    }