Advertisement

Icosphere and height map

Started by September 13, 2016 09:34 PM
3 comments, last by Toastmastern 7 years, 12 months ago

Hello,

After doing some research without finding any good tutorials and only hints on how to proceed with my height map for a icosphere I started working on my own idea and this is what I came up with:

1. Take a image of the planet in question in greyscale and import it to a 2D array. I found a large HD image from NASA with a 8192x4096 pixels.

2. Calculate Longitude and Latitude for every vertex in my Icosphere, I started with 7 division but will try 8 divisons later on for more details.
Here is my code for getting my hand on Long and Lat cordinates.


float r = sqrtf(mPlanetMesh.vertices[i].position.x * mPlanetMesh.vertices[i].position.x + mPlanetMesh.vertices[i].position.y * mPlanetMesh.vertices[i].position.y + mPlanetMesh.vertices[i].position.z * mPlanetMesh.vertices[i].position.z);

float longitude = fmodf((270 + (atan2f(mPlanetMesh.vertices[i].position.x, mPlanetMesh.vertices[i].position.z)) * 180 / M_PI), 360.0f) - 180;

float latitude = (90 - acosf(mPlanetMesh.vertices[i].position.y / r) * (180 / M_PI));

This does give me values for Long between -180 and 180 and for Lat between -90 and 90. But I don't know if the calculations are correct.

3. Use this Long and Lat value to get the correct Pixel:


mHeightMap[(int)((180 + longitude) * (8192 / 360))][(int)((90 - latitude) * (4096 / 180))])

Again I am not sure this will work for my image to get the correct values.

4. Calculate the normals for every vertex:


mPlanetMesh.vertices[i].normal.x = cosf(latitude * (M_PI / 180)) * cosf(longitude * (M_PI / 180));

mPlanetMesh.vertices[i].normal.y = cosf(latitude * (M_PI / 180)) * sinf(longitude * (M_PI / 180));

mPlanetMesh.vertices[i].normal.z = sinf(latitude * (M_PI / 180));

Once again I am not sure this calculations are correct since they are depending on both that they are correct by themself but also that the Long and Lat calculations are correct.

5. Multiply the normal vector with the height vector(the height vector have of course been recalculated to represent values betweeen the lowest and highest point on the planet)

6. Add the multiplied vector to the vertex.

7. Render

Now on 7 divisions I get something that looks like a landscape even tho the details is very low and it looks kinda crapy in general. On 8 divisions I get a lot off lines going through the middle of the planet for some reason.
My plan was to make sure the calculations are correct before going into detail of what might be the problem there. The caluclations might solve it(It should atleast since without the calculations the sphere looks like a spehere.)

I might be approaching this from the wrong direction and it might be a easier way to solve this. please enligthen me if thats the case :)

Best regards and thanks in advance

Toastmastern

A few observations:

1. Do you really need to compute the radius each time? Isn't it a known quantity?

2. Why are you converting every angle to degrees? That's useless and you then have to convert them back to radians (or other range) to be able to use them.

3. The normal of each vertex is the vertex itself normalized. You can thus simply multiply the vector by some value to get the displaced one. If the vector has lenght R and you want its height to be H, you simply have to multiply by H/R.

4. This is probably all best done in a shader. The base displacement can be done in a vertex shader and you can probably also use a tessellation shader to increase details when needed. Finally lighting can do a great work in adding details.

5. I still have to check the correctness of your formulas.

Advertisement

A few observations:
1. Do you really need to compute the radius each time? Isn't it a known quantity?
2. Why are you converting every angle to degrees? That's useless and you then have to convert them back to radians (or other range) to be able to use them.
3. The normal of each vertex is the vertex itself normalized. You can thus simply multiply the vector by some value to get the displaced one. If the vector has lenght R and you want its height to be H, you simply have to multiply by H/R.
4. This is probably all best done in a shader. The base displacement can be done in a vertex shader and you can probably also use a tessellation shader to increase details when needed. Finally lighting can do a great work in adding details.
5. I still have to check the correctness of your formulas.


Thanks for your replies and to taken the time to look at my code. After rethinking some parts I realized some things

for example as you say, the radius is known and is now a constant instead which isn't recalculated each time.

The normal vector is so much more simple then I first realized the calculation now looks like:
mPlanetMesh.vertices[i].normal.x = mPlanetMesh.vertices[i].position.x / PLANETRADIUS;
mPlanetMesh.vertices[i].normal.y = mPlanetMesh.vertices[i].position.y / PLANETRADIUS;
mPlanetMesh.vertices[i].normal.z = mPlanetMesh.vertices[i].position.z / PLANETRADIUS;
The Long Lat calc now looks like this:
float longitude = atan2f(mPlanetMesh.vertices[i].position.z, mPlanetMesh.vertices[i].position.x) * (180 / M_PI);
		float latitude = 90 - (acosf(mPlanetMesh.vertices[i].position.y/ PLANETRADIUS) * (180 / M_PI));
and as you say the calc to pi is not needed but I did as well to make it easier in my head for now :)

Also another error was the input from the bmp file was totaly off but after starting to use CImg it works flawless.

The details are still abit meh but I don't think I need to use 8 division to increase that number. I bet it is possible to use my height map in the shader to use the tessellation to increase the details? Right now the tessellation just splits up my triangles which doesnt increase the details. Am I right or? any pointers to where I could find some information on how to do that?

//Toastmastern

In the shader you can do many different things to improve the details:

1. Increase the tessellation dynamically using the tessellation shader,

2. Use displacement mapping to give the impression of details without actually adding more geometry.

In the shader you can do many different things to improve the details:

1. Increase the tessellation dynamically using the tessellation shader,

2. Use displacement mapping to give the impression of details without actually adding more geometry.

Right now I am working on a plan so that all new vertices created by the tessellation shader also get individual height points. Displacement mapping is something I plan to look into at a later stage the same with dynamic tessellation(by this you might mean what I am currently doing right now, I'm not sure :) ). Right now I have the tessellation amount bound to the players altitude above the planet, any other way to do this that is smarter?

//Toastmastern

This topic is closed to new replies.

Advertisement