Jump to content

[SOLVED] - Height Map Color Math Help


MackeyK24
 Share

Recommended Posts

I need some help with color math. I am trying to create height maps in code... i can read raw terrain data and get the float raw height value for each pixel (x,y) as a value from 0 to 1

0 being black and 1 being white. I need to convert that 0 to 1 float to a black and white pixel based on the level of 0 to 1.

Here is an example code block.. I need to basically create a Color.FromFloat type function as listed below:

                Texture2D duplicateHeightMap = new Texture2D(terrain.terrainData.heightmapWidth, terrain.terrainData.heightmapHeight, TextureFormat.ARGB32, false);
                float[,] rawHeights = terrain.terrainData.GetHeights(0, 0, terrain.terrainData.heightmapWidth, terrain.terrainData.heightmapHeight);

                /// run through the array row by row
                for (int y=0; y < duplicateHeightMap.height; y++)
                {
                    for (int x=0; x < duplicateHeightMap.width; x++)
                    {
                        // height map color (0 to 1)
                        float rawHeight = rawHeights[x, y];

                        // NOTE: HERE IS WHERE I NEED HELP (MAYBE GRAYSCALE ???)
                        Color color = Color.FromFloat(rawHeight);

                        duplicateHeightMap.SetPixel(x, y, color);
                    }
                }
                // Apply all SetPixel calls
                duplicateHeightMap.Apply();

 

Link to comment
Share on other sites

If you are familiar with the exporter code... Check out this enhancement for support native unity terrains (Note how i read the terrains raw heights... then create a height map based on the height values and use a darkness level to factor the level of darkness of the calculated grayscaled color channels):

        private BabylonMesh ConvertUnityTerrainToBabylon(Terrain terrain, GameObject gameObject, ref UnityMetaData metaData, ref List<BabylonExport.Entities.BabylonParticleSystem> particleSystems, ref List<UnityFlareSystem> lensFlares, ref string componentTags)
        {
            BabylonMesh babylonMesh = new BabylonMesh { name = gameObject.name, id = GetID(gameObject) };
            metaData.type = "Terrain";
            babylonMesh.tags = componentTags;
            babylonMesh.tags += " [TERRAIN]";
            if (!String.IsNullOrEmpty(babylonMesh.tags)) {
                babylonMesh.tags = babylonMesh.tags.Trim();
            }

            ExporterWindow.ReportProgress(1, "Parsing terrain: " + gameObject.name);

            var transform = gameObject.transform;

            babylonMesh.parentId = GetParentID(transform);

            babylonMesh.position = transform.localPosition.ToFloat();

            babylonMesh.rotation = new float[3];
            babylonMesh.rotation[0] = transform.localRotation.eulerAngles.x * (float)Math.PI / 180;
            babylonMesh.rotation[1] = transform.localRotation.eulerAngles.y * (float)Math.PI / 180;
            babylonMesh.rotation[2] = transform.localRotation.eulerAngles.z * (float)Math.PI / 180;

            babylonMesh.scaling = transform.localScale.ToFloat();

            babylonMesh.isVisible = false;
            babylonMesh.visibility = 0;
            babylonMesh.checkCollisions = false;

            // Terrain
            var generator = gameObject.GetComponent<BabylonTerrainGenerator>();
            if (terrain != null && generator != null) {
                bool png = (exportationOptions.DefaultImageFormat == (int)BabylonImageFormat.PNG);
                string fext = (png == true) ? ".png" : ".jpg";
                metaData.properties.Add("width", terrain.terrainData.size.x);
                metaData.properties.Add("length", terrain.terrainData.size.z);
                metaData.properties.Add("height", terrain.terrainData.size.y);
                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("minimumHeightLevel", generator.minimumHeightLevel);
                metaData.properties.Add("maximumHeightLevel", generator.maximumHeightLevel);
                metaData.properties.Add("groundTessellation", generator.groundTessellation);
                if (generator.terrainSurfaceMaterial != null) {
                    var mat = DumpMaterial(generator.terrainSurfaceMaterial);
                    metaData.properties.Add("surfaceMaterialId", mat.id);
                } else {
                    metaData.properties.Add("surfaceMaterialId", null);
                }
                float[,] rawHeights = terrain.terrainData.GetHeights(0, 0, terrain.terrainData.heightmapWidth, terrain.terrainData.heightmapHeight);
                if (generator.terrainMode == BabylonTerrainMode.HeightMap) {
                    ExporterWindow.ReportProgress(1, "Generating terrain heightmap: " + gameObject.name);
                    Texture2D heightMap = new Texture2D(terrain.terrainData.heightmapWidth, terrain.terrainData.heightmapHeight, TextureFormat.ARGB32, false);
                    for (int y=0; y < heightMap.height; y++) {
                        for (int x=0; x < heightMap.width; x++) {
                            float height = rawHeights[x, y];
                            float gray = (0.2126f * height * 255.0f) + 0.7152f * (height * 255.0f) + 0.0722f * (height * 255.0f);
                            gray = gray / generator.heightmapDarkness;
                            Color color = new Color(gray, gray, gray, 1.0f);
                            heightMap.SetPixel(x, y, color);
                        }
                    }
                    heightMap.Apply();
                    string tempFilename = "temp" + terrain.name.Replace(" ", "").Replace("(", "").Replace(")", "") + "Heightmap" + fext;
                    string tempTexturePath = Path.Combine(Application.dataPath.Replace("/Assets", "/Temp/data"), tempFilename);
                    string heightmapEncoding = (png) ? "data:image/png;base64," : "data:image/jpg;base64,";
                    byte[] heightmapBytes = (png) ? heightMap.EncodeToPNG() : heightMap.EncodeToJPG(exportationOptions.DefaultQualityLevel);
                    metaData.properties.Add("heightmapBase64", (heightmapEncoding + Convert.ToBase64String(heightmapBytes)));
                    string temp = Path.GetDirectoryName(tempTexturePath);
                    if (!Directory.Exists(temp)) Directory.CreateDirectory(temp);
                    File.WriteAllBytes(tempTexturePath, heightmapBytes);
                } else {
                    babylonMesh.isVisible = true;
                    babylonMesh.visibility = 1;
                    babylonMesh.checkCollisions = true;
                    ExporterWindow.ReportProgress(1, "Generating terrain mesh: " + gameObject.name);


                    
                }
            }
            babylonMesh.metadata = metaData;
            babylonScene.MeshesList.Add(babylonMesh);

            // 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;
        }

 

Then in the unity loader i create the actual ground like this:

            // Parse scene native mesh and heightmap terrains
            var terrains:BABYLON.Mesh[] = this._scene.getMeshesByTags("[TERRAIN]");
            if (terrains != null) {
                terrains.forEach((terrain)=>{
                    if (terrain.metadata != null && terrain.metadata.properties != null) {
                        if (terrain.metadata.properties.heightmapBase64) {
                            var tempBase64:string = terrain.metadata.properties.heightmapBase64;
                            var terrainWidth:number = terrain.metadata.properties.width;
                            var terrainLength:number = terrain.metadata.properties.length;
                            var terrainHeight:number = terrain.metadata.properties.height;
                            var minimumHeightLevel:number = terrain.metadata.properties.minimumHeightLevel;
                            var maximumHeightLevel:number = terrain.metadata.properties.maximumHeightLevel;
                            var groundTessellation:number = terrain.metadata.properties.groundTessellation;
                            var surfaceMaterialId:string = terrain.metadata.properties.surfaceMaterialId;
                            var surfaceMaterialInst:BABYLON.Material = null;
                            if (surfaceMaterialId != null && surfaceMaterialId !== "") {
                                var material:BABYLON.Material = this._scene.getMaterialByID(surfaceMaterialId);
                                surfaceMaterialInst = material;
                            }
                            BABYLON.MeshBuilder.CreateGroundFromHeightMap((terrain.name + "_Mesh"), tempBase64, {
                                width: terrainWidth,
                                height: terrainLength,
                                subdivisions: groundTessellation,
                                minHeight: minimumHeightLevel,
                                maxHeight: maximumHeightLevel,
                                updatable: true,
                                onReady: (mesh:BABYLON.Mesh) => {
                                    mesh.parent = terrain;
                                    mesh.scaling = terrain.scaling.clone();
                                    mesh.position.x -= terrain.position.x;
                                    mesh.position.z -= terrain.position.z;
                                    mesh.checkCollisions = true;
                                    if (surfaceMaterialInst != null) {
                                        mesh.material = surfaceMaterialInst;
                                    }
                                }
                            }, this._scene);
                        } else {
                            // TODO: Native Mesh - Note should try do all c# editor side
                        }
                    }
                });
            }

 

You gotta luv that metadata i added :)

 

Note: Although i get VERY SLOW and CHOPPY movement using the activeCamera.attachControl for user input. Also brings fps down about 15fps soon as you start moving on the created found terrain... Ever heard of that ???

 

 

Link to comment
Share on other sites

8 hours ago, MackeyK24 said:

Although i get VERY SLOW and CHOPPY movement using the activeCamera.attachControl for user input. Also brings fps down about 15fps soon as you start moving on the created found terrain... Ever heard of that ???

Hi again MK24!  You're kickin' good butt, as always.  Nice work.

Do you know about "profiling" in the browser's dev tools area?  I haven't used it much at all, but rumor says you can easily find what is bogging-down a scene. *shrug*

Any chance you can reproduce the symptom in a playground scene?  That might tell more.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...