Greetings everyone, I've been looking for spherical terrains, spherical heightmap and procedural planets. All what i've got are just suggests on how to, without many examples or code easy to understand (hell yes, i'm new in Unity). I combined two scripts i got on this website, my goal would be: 1) Generate a simple heightmap on a plane. 2) Morph it into a sphere. The crappy code is here, if some guru can help would be very appreciated. Thanks. Code (csharp): // This script is placed in public domain. The author takes no responsibility for any possible harm. var heightMap : Texture2D; var material : Material; var size = Vector3(200, 30, 200); var collision : boolean; var radius: float; var numSegments: int; var numStrips: int; function Start () { GenerateHeightmap(radius, numSegments, numStrips); } function GenerateHeightmap (radius: float, numSegments: int, numStrips: int) { // Create the game object containing the renderer gameObject.AddComponent(MeshFilter); gameObject.AddComponent("MeshRenderer"); if (material) renderer.material = material; else renderer.material.color = Color.white; // Retrieve a mesh instance var mesh : Mesh = GetComponent(MeshFilter).mesh; // The number of rings of vertices is one greater then the number of // horizontal strips and each ring has two vertices at the seam. var numYLevels = numStrips + 1; var numRingSteps = numSegments + 1; var width : int = Mathf.Min(heightMap.width, 255); var height : int = Mathf.Min(heightMap.height, 255); var y = 0; var x = 0; // Build vertices and UVs var vertices = new Vector3[height * width]; var uv = new Vector2[height * width]; var tangents = new Vector4[height * width]; var uvScale = Vector2 (1.0 / (width - 1), 1.0 / (height - 1)); var sizeScale = Vector3 (size.x / (width - 1), size.y, size.z / (height - 1)); for (y=0;y<height;y++) { for (x=0;x<width;x++) { var pixelHeight = heightMap.GetPixel(x, y).grayscale; var vertex = Vector3 (x, pixelHeight, y); vertices[y*width + x] = Vector3.Scale(sizeScale, vertex); uv[y*width + x] = Vector2.Scale(Vector2 (x, y), uvScale); // Calculate tangent vector: a vector that goes from previous vertex // to next along X direction. We need tangents if we intend to // use bumpmap shaders on the mesh. var vertexL = Vector3( x-1, heightMap.GetPixel(x-1, y).grayscale, y ); var vertexR = Vector3( x+1, heightMap.GetPixel(x+1, y).grayscale, y ); var tan = Vector3.Scale( sizeScale, vertexR - vertexL ).normalized; tangents[y*width + x] = Vector4( tan.x, tan.y, tan.z, -1.0 ); } } // Assign them to the mesh mesh.vertices = vertices; mesh.uv = uv; // -------------------------------------------------------------------------------------------------------------- // Store the normalised X and Z values of a ring for repeated usage (this // saves a few Cos and Sin calls overall). var ring = new Vector3[numRingSteps]; var fracCircle: float; for (i = 0; i <= numSegments; i++) { fracCircle = (i * 1.0) / (numSegments * 1.0); var angle = fracCircle * 2.0 * Mathf.PI; ring[i].x = Mathf.Sin(angle); ring[i].z = Mathf.Cos(angle); } // Calculate the vertex positions from the parameter values. The vertex position // is the same as the normal vector multiplied by the radius and the UV is easily // obtained from the parameter values. for (l = 0; l <= numStrips; l++) { var fracArc = (l * 1.0) / (numStrips * 1.0); var yCoord = Mathf.Cos(fracArc * Mathf.PI); var radFrac = Mathf.Sin(fracArc * Mathf.PI); for (s = 0; s <= numSegments; s++) { fracCircle = (s * 1.0) / (numSegments * 1.0); var normVert = ring[s] * radFrac; normVert.y = yCoord; vertices[l * numRingSteps + s] = normVert * radius; } } // -------------------------------------------------------------------------------------------------------------- // Build triangle indices: 3 indices into vertex array for each triangle var triangles = new int[(height - 1) * (width - 1) * 6]; var index = 0; for (y=0;y<height-1;y++) { for (x=0;x<width-1;x++) { // For each grid cell output two triangles triangles[index++] = (y * width) + x; triangles[index++] = ((y+1) * width) + x; triangles[index++] = (y * width) + x + 1; triangles[index++] = ((y+1) * width) + x; triangles[index++] = ((y+1) * width) + x + 1; triangles[index++] = (y * width) + x + 1; } } // And assign them to the mesh mesh.triangles = triangles; // Auto-calculate vertex normals from the mesh mesh.RecalculateNormals(); // Assign tangents after recalculating normals mesh.tangents = tangents; mesh.vertices = vertices; // Assign collision if (collision == true) { GetComponent(MeshCollider).sharedMesh = mesh; } }
I think a better thing to do would be to make 6 heightmaps, and make a cubesphere out of them. I doubt you can get a heightmap to map usefully to a sphere (without distortion). --Eric
Thank you for the answer. Do you know where i can find some examples about this method? I mean a package or a tutorial. As i said I'm really new in Unity.
the distortions/anomalies at the poles of a lat/long sphere are not that disturbing. search the forums. andeeee has posted a script for a parametrical sphere as the unity built in sphere has some serious uv issues at the poles. then you must create some noise for surface details and put it in a texture which is mapped on the sphere. perlin noise is widely used but i suggest simplex noise. always head for 3d noise because your sphere is a 3d body and with 2d noise you get into problems with tiling. with 3d noise simply take the positions of the pixels on the sphere to calculate the noise there and when you always pick the octaves of noise from a sphere with different radius for different frequenzies/wavelength you have no problem with tiling. i'm currently working at a procedural planet generator which i will sell at the assetstore in some months when things go well.
If you saw my script, Paramsphere.js by Andeeee was already "implemented". Paramsphere.js and HeightmapGenerator.js from Procedural Examples was the two examples i used. Now, as i said two times, i'm a newbie regard procedurals so any method NOT documented by some examples or anything related to it isn't an help for me at all. Maybe do you have a starting example (code or package) on how would be possible spherify a simple heightmap keeping its relief around the sphere? Note: Till now i used 3ds Max in order to load my heightmaps directly via displace modifier, so to automatically generate an heightfield around a sphere. I think it is a good method but it loose details because vertices optimizations, so i thought could be better generate it procedurally. PS. If you didn't understand what i said, is my fault, English isn't my main language, sorry.
i have noticed it afterwards. some weeks ago i had also been a newbie in this field. only if you work with the stuff you may get above newbie level. if you just pick a ready implementation you probably wont. there are also enough examples and tutorials outside which are not unity specific but the principle is the same. a bit thinking is still required though. i just have code which depends on many stuff and as i said i want to sell it. publishing it for free would be something between unwise and stupid. same applies for me. sorry when i can't be of more help but this is a complicated and wide field. so you probably wont find a ready made solution which fits all your needs. i also started from scratch and in 1 or 2 weeks you could have something ready. if you have detailed questions there are many people to help you. but its always a bit probelamtic to request other people doing the work for you (which includes internet search for sources/tutorials etc.). for your two goals/questions from the first post i had give you some hints and advises in my previous post. what you make out of it is up to you.
You could also start with a geodesic sphere (mesh or built in run time) and then move each vertex along its original normal by some noise (perlin works great here).