MackeyK24 Posted December 2, 2016 Share Posted December 2, 2016 Hey Dave... I really need your help in finishing up my build in babylonjs terrain system. I think i may need some mods to the CreateGroundFromHeightmap or maybe help in creating a new CreateGroundFromUnityHeightmap where we go in and compensate for the height map coming from unity and 'post' process those height values to make it look good in babylon. Please take a look at the the video link explaining the problem (Also is attached a TestTerrain.png height map at 100 width/length and 50 height for to try to get to make look good with a creategroundfromheightmap call): Dear Dave - Please Help Try This Playground and see if can't get not so choppy around the edges: http://www.babylonjs-playground.com/#RDPE6#1 Quote Link to comment Share on other sites More sharing options...
Gugis Posted December 2, 2016 Share Posted December 2, 2016 Who's Dave? Quote Link to comment Share on other sites More sharing options...
MackeyK24 Posted December 2, 2016 Author Share Posted December 2, 2016 @davrous ... One the main BabylonJS guys Quote Link to comment Share on other sites More sharing options...
MackeyK24 Posted December 2, 2016 Author Share Posted December 2, 2016 @davrous ... Here is a playground: http://www.babylonjs-playground.com/#RDPE6 Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted December 3, 2016 Share Posted December 3, 2016 Hello Mackey, I'm not @davrous but I'm pretty sure the problem is in the texture generated. There is not enough detail (as far as I can see it generates color (height) from dark to dark grey where it is supposed to generate from black to white). Everything else seems fine. The subdivisions value is the number of triangle per row. Here only 5 subdivisions: (so 5 triangles per row) Here with 10: So in your case, if you want a smooth terrain 100 is really fine (as long as you provide a back to white height map) Quote Link to comment Share on other sites More sharing options...
MackeyK24 Posted December 3, 2016 Author Share Posted December 3, 2016 So not greyscale... So any idea on how to to take those greyscale values and make them more black and white? Here is the Code to get terrain heights (raw grayscale heights): 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]; Color pixel = new Color(inverted, inverted, inverted, 1.0f); heightMap.SetPixel(x, y, pixel); } } heightMap.Apply(); Quote Link to comment Share on other sites More sharing options...
MackeyK24 Posted December 3, 2016 Author Share Posted December 3, 2016 Does that mean EVERY PIXEL is either totally white or totally black... No shades of gray in between... How does it do variations if every pixel is either totally black or totally white? Quote Link to comment Share on other sites More sharing options...
Sebavan Posted December 3, 2016 Share Posted December 3, 2016 I guess in Unity each sample (0 - 1) is relative to the (0 - size.y) of your terrain.data.size so not normalized against each other so if your max (size.y) is 1000 but you have no "big mountains", your values could get stuck between (0 and 10) e.g (0 - 0.01) in your samples. This is then converted to 8 bit picture so only 0 - 255 where 0 would be 0 and 255 -> size.y e.g. 1000 therefore each unit in color is about a step of 4 in the terrain height meaning all of your value would be either 0 or 1 for 4 or 2 for 8 or 3 for 12 which would be almost fully black as we are seeing in your picture and creates a really low res height. Maybe you could at export find the min - max sample and normalized everything in between. Those values could then be used in your metadata to control the ground creation in bjs and you would be sure to use the full 255 available units in your texture. The number are all wrong and made up and only here to illustrate. Not sure I am clear enough btw.... I normalized your texture by hand and have now this: http://www.babylonjs-playground.com/#RDPE6#2 with I agree it may still not be smooth enough but the limitation to byte for the texture is annoying (only 255 different levels). 2 solutions to smooth it more would be: 1. Interpolating in the create ground map function so if our res is bigger than the texture, we can infer some values (still have some artifacts). 2. Or we could add a way to pack the data from unity in the the 4 textures channels (or 2 only cause Unity stores terraindata in 16 bit integer I guess not 32) and create back the ground from it. Quote Link to comment Share on other sites More sharing options...
MackeyK24 Posted December 3, 2016 Author Share Posted December 3, 2016 What about this: Instead of using raw heights, use GetInterpolatedHeight(x,y) If you have to use TerrainData for some reason, then you'd want GetInterpolatedHeight. The x and y values that you supply are normalized to the terrain, so that 0.0, 0.0 is the lower-left corner, and 1.0, 1.0 is the upper-right corner Quote Link to comment Share on other sites More sharing options...
MackeyK24 Posted December 3, 2016 Author Share Posted December 3, 2016 If we just can't get it with using unity height maps... Maybe ill just pull that feature and focus on Terrain Exporter instead...Which might not be a bad idea because i can't seem to get to the Terrain Mesh Renderer (SharedRender) so i can't get to the light map baking info for shadows cast on to the terrain. If i use a scene to create a terrain and save as mesh asset you can then use in your actual scene as a regular mesh so you can then bake light maps onto the material using the mesh renderer. Also if you re-export the terrain since its and exported asset in the project it SHOULD just refresh and show the changes you made to the asset. Dunno... i will keep playing with terrains... I gotta get that working because that segues to my next feature (which is working beautifully so far) Navigation Mesh, Navigation Agent and Off Link Mesh MetaData Support (that my scene manager wraps up in a nice API to use the native unity navigation information to implement our own babylonjs open navigation system... you can use WHATEVER pathfinding system you want using the supplied navigation mesh, plus all the aux data you need to fully implement your AI things like obstacle avoidance ) And i need to be able to put a navigation mesh on a terrain and use them BOTH in my babylon scene Quote Link to comment Share on other sites More sharing options...
NasimiAsl Posted December 3, 2016 Share Posted December 3, 2016 @MackeyK24 r u have any pic (for unity height map ) any sample Quote Link to comment Share on other sites More sharing options...
MackeyK24 Posted December 3, 2016 Author Share Posted December 3, 2016 Yes my sample Grayscale pic (with apparently not enough detail of black to white) is in the FIRST POST Quote Link to comment Share on other sites More sharing options...
MackeyK24 Posted December 4, 2016 Author Share Posted December 4, 2016 Hey @Sebavan ... Do you think you have a hot minute to help me with some code... I don't know how to 'normalize' the image like you did. But your height map looks great. I don't know the what math formula to use to change color pixels to a 'normalized' image. CAN YOU PLEASE edit the following code where i get all the grayscale pixels and simply put back into normalized map pixels... Can you actually tweak that little bit of code to 'normalize' the Color32[] pixels and set that new Color32[] pixel array into the normalmapTexture.SetPixels32(): Vector3 terrainSize = terrain.terrainData.size; 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]; Color pixel = new Color(inverted, inverted, inverted, 1.0f); heightMap.SetPixel(x, y, pixel); } } heightMap.Apply(); Texture2D normalizedMap = new Texture2D(hwidth, hheight, TextureFormat.ARGB32, false); Color32[] grayscalePixels = heightMap.GetPixels32(); //////////////////////////////////////////////////////////////////////////////////////// // PLEASE HELP - TODO: Normailize Pixels from heightMapTexture to normalizedMapTexture // For Now Just Set Same Pixel Back, No Conversion Yet /////////////////////////////////////////////////////////////////////////////////////// normalizedMap.SetPixels32(grayscalePixels); /////////////////////////////////////////////////////////////////////////////////////// normalizedMap.Apply(); string tempFilename = "temp" + terrain.name.Replace(" ", "").Replace("(", "").Replace(")", "") + "Heightmap.png"; string tempTexturePath = Path.Combine(Application.dataPath.Replace("/Assets", "/Temp/data"), tempFilename); byte[] heightmapBytes = normalizedMap.EncodeToPNG(); string temp = Path.GetDirectoryName(tempTexturePath); if (!Directory.Exists(temp)) Directory.CreateDirectory(temp); File.WriteAllBytes(tempTexturePath, heightmapBytes); Quote Link to comment Share on other sites More sharing options...
Sebavan Posted December 5, 2016 Share Posted December 5, 2016 Yep, I ll do tomorrow evening and try to allow half float packing for better accuracy . Happy to help, Thx for your contribution. Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted December 5, 2016 Share Posted December 5, 2016 Hello not sure to understand why you cannot take your value which is between 0 and X and scale it down to 0..1 ? Just go through all pixels to find the highest. Call this value HighValue for instance and then store pixel = value / HighValue Quote Link to comment Share on other sites More sharing options...
MackeyK24 Posted December 5, 2016 Author Share Posted December 5, 2016 Actually, i think i am already using 0 to 1 values. I am using TerrainData.GetHeights Documentation: Returns a two dimensional array of heightmap samples. The samples are represented as float values ranging from 0 to 1 Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted December 5, 2016 Share Posted December 5, 2016 yes but this not ensure that the full range is used Perhaps all values are between 0 to 0.5 Quote Link to comment Share on other sites More sharing options...
MackeyK24 Posted December 5, 2016 Author Share Posted December 5, 2016 In that case... I think the TerrainData.GetHeight (which is 0 to size.y) can then be used as you suggested pixel = value / HighestValue Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted December 5, 2016 Share Posted December 5, 2016 Yep:) Quote Link to comment Share on other sites More sharing options...
MackeyK24 Posted December 5, 2016 Author Share Posted December 5, 2016 Hey @Deltakosh ... What do you think about my Dual Mesh Terrain Approach... Using a an invisible low res ground mesh for collisions so can move smooth upon and then creating a res mesh with the materials that are just for visuals with collisions = false... http://www.html5gamedevs.com/topic/26816-dual-mesh-terrainsgood-or-bad/ Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted December 5, 2016 Share Posted December 5, 2016 I like it a lot (this is what we are doing for the Epsilon demo) Quote Link to comment Share on other sites More sharing options...
MackeyK24 Posted December 5, 2016 Author Share Posted December 5, 2016 Kool... If you say that ok... Then ill put it in the toolkit Quote Link to comment Share on other sites More sharing options...
MackeyK24 Posted December 5, 2016 Author Share Posted December 5, 2016 @Deltakosh Can you check this out as well: http://www.html5gamedevs.com/topic/26831-computing-normals-from-verts-and-triangles/ Quote Link to comment Share on other sites More sharing options...
Sebavan Posted December 6, 2016 Share Posted December 6, 2016 Hello, Here is your new loop: float min = float.MaxValue; float max = float.MinValue; for (int y = 0; y < hheight; y++) { for (int x = 0; x < hwidth; x++) { float inverted = rawHeights[y, x]; min = Mathf.Min(min, inverted); max = Mathf.Max(max, inverted); } } float ratio = 1.0f / (max - min); for (int y = 0; y < hheight; y++) { for (int x = 0; x < hwidth; x++) { float inverted = rawHeights[y, x]; inverted *= ratio; Color pixel = new Color(inverted, inverted, inverted, 1.0f); heightMap.SetPixel(x, y, pixel); } } Think to also reuse the min max as the min max in BJS when you create the height map. The dual mesh approach will help a lot. I guess you could maybe also leverage the LOD from unity. Quote Link to comment Share on other sites More sharing options...
MackeyK24 Posted December 6, 2016 Author Share Posted December 6, 2016 Does LOD make sense on a terrain ??? won't the terrain your walking on always be the same distance from camera??? Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.