Jump to content
  • Advertisement
Sign in to follow this  
lexington

Heightmap problems

This topic is 837 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey everyone.

 

I have been following this tutorial http://www.mbsoftworks.sk/index.php?page=tutorials&series=1&tutorial=24 when trying to learn how to do a heightmap. I have managed to read in the vertex data but something is not correct.

 

When using the following grayscale image heightmap (in which i just display the vertex positions for now) Starts off very well but then it seems to duplicate the first part onto the end of the map (also seems like everything is a bit bunched up as the middle hole is not in the middle of the heightmap) Which results in it looking like this.

 

https://gyazo.com/cd642c41a92d4345bb4ca06dbc12ba1c

 

Atm I feel that the problem must be to do with the height of the pixel i read in but im not 100% sure. from what i have read up , the way i do it should be correct

 

Currently the grayscale image is a BMP 24 bitdepth 257*257. I use SDL to read in the image to calculate the vertex height

 

 

Below is the code i am currently using 

 

getting the vertex points (like the tutorial i make sure the x and z are between -0.5 and 0.5 so it is centred)

	SDL_Surface* img = SDL_LoadBMP(imagepath);
	if (!img)
	{
	    std::cout << "could not load the image";
		return;
	}


	rows = img->h;
	cols = img->w;


	std::vector< std::vector<glm::vec3> > Tvetrices (rows,std::vector<glm::vec3>(cols));
	std::vector< std::vector<glm::vec3> > TFinalNormals = std::vector< std::vector<glm::vec3> >(rows, std::vector<glm::vec3>(cols));
	std::vector< std::vector<glm::vec2> >  TUVs (rows , std::vector<glm::vec2>(cols));

	float fTextureU = float(cols)*0.1f;
	float fTextureV = float(rows)*0.1f;

	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			float colscale = float(j) / float(cols - 1);
			float rowscale = float(i) / float(rows - 1);

			Uint32 pixle = ((Uint32*)img->pixels)[i * img->pitch/4 + j];
			Uint8 r, g, b;
			SDL_GetRGB(pixle, img->format, &r, &g, &b);
			float hight = (float)r / 255.0;


			Tvetrices[i][j] = glm::vec3((-0.5f + colscale) * 10, hight, (-0.5f + rowscale) * 10);
			TUVs[i][j] = glm::vec2(fTextureU*colscale, fTextureV*rowscale);

		}
	}

	vetrices = Tvetrices;

VBO set up (just want points for now so no intention for setup for tri's)

	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			testver.push_back(vetrices[i][j]);
		}

	}
	
	glBufferData(GL_ARRAY_BUFFER, testver.size() * sizeof(glm::vec3), &testver[0], GL_STATIC_DRAW);

draw call 

	glUseProgram(_program);

	glBindVertexArray(_VAO);

	glUniformMatrix4fv(_shaderModelMatLocation, 1, GL_FALSE, glm::value_ptr(_modelMatrix));
	glUniformMatrix4fv(_shaderViewMatLocation, 1, GL_FALSE, glm::value_ptr(viewMatrix));
	glUniformMatrix4fv(_shaderProjMatLocation, 1, GL_FALSE, glm::value_ptr(projMatrix));

	glDrawArrays(GL_POINTS, 0, testver.size());

Any help will be greatly appreciated 

Edited by lexington

Share this post


Link to post
Share on other sites
Advertisement

It looks like you're sampling from the wrong location on the heightmap. Can you show us the original heightmap image?

Share this post


Link to post
Share on other sites

Uint32 pixle = ((Uint32*)img->pixels)[i * img->pitch/4 + j];

 

What's the significance of the /4 part? According to the wiki the pitch is the number of bytes per row, not sure why you are dividing it by 4. It might be worth you accessing the Pixel Format and checking the bytes per pixel to ensure everything matches up.

Share this post


Link to post
Share on other sites

 

 

What's the significance of the /4 part? According to the wiki the pitch is the number of bytes per row, not sure why you are dividing it by 4. It might be worth you accessing the Pixel Format and checking the bytes per pixel to ensure everything matches up.

 

without the /4, an access violation occurs. with ever example of 24 bitdepth image that i have seen, everyone puts the /4 after 

 

also the bits per pixel came back as 24

 

and the bytes per pixel came back 3

Edited by lexington

Share this post


Link to post
Share on other sites

I don't know SDL, but if it's a 24bit image, each pixel might be 3 bytes instead of 4 (although sometimes 24 bit images store their data in 4 byte chunks for good memory alignment). You're treating it like if it were 4.

 

That is, each j that gets incremented reads from a position 4 bytes further in the buffer, since you're casting the array to a Uint32*.

 

Because your source image has equal values for r, g, and b, this error wouldn't be very obvious. You're basically reading an r value, then a g value, then a b value, and so on.

 

Instead, you may need to index it as a byte array, and increment by j * 3 (and remove the /4 from the pitch calculation).

Share this post


Link to post
Share on other sites

@Phil_T

 

Arr yes you are correct, i am treating the image as if it was 4 bytes per pixel instead of 3 (or it was a 32 bit bitmap ofcs).

 

Sorry to ask as just a little confused but what do you mean by "Instead, you may need to index it as a byte array, and increment by j * 3" (the "index it as a byte array" part mainly)

 

Cheers

Share this post


Link to post
Share on other sites

@Phil_T

 

Like the following?

Uint8 *pixle = ((Uint8*)img->pixels);
pixle += (i * img->pitch) + (j * sizeof(Uint8) * 3);
Uint32 temppix = *((Uint32*)pixle);

Uint8 r, g, b;
SDL_GetRGB(temppix, img->format, &r, &g, &b);
float hight = (float)r / 255.0;

i had to change it back to uint32 at the end as that is only what the SDL_GetRGB function will take.

 

The results are much better

 

https://gyazo.com/10795f58b070189ea3e23f1fd376372f

Share this post


Link to post
Share on other sites

@Phil_T

 

Like the following?

Uint8 *pixle = ((Uint8*)img->pixels);
pixle += (i * img->pitch) + (j * sizeof(Uint8) * 3);
Uint32 temppix = *((Uint32*)pixle);

Uint8 r, g, b;
SDL_GetRGB(temppix, img->format, &r, &g, &b);
float hight = (float)r / 255.0;

i had to change it back to uint32 at the end as that is only what the SDL_GetRGB function will take.

 

The results are much better

 

https://gyazo.com/10795f58b070189ea3e23f1fd376372f

 

That looks a lot better. It's probably a good idea to replace that 3 with the BytesPerPixel value from the pixel format. It is probably 3 since it works but it might not always be 3.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!