Jump to content
  • Advertisement
Sign in to follow this  
Fl00Fy

Texture Mapping problems with Assimp

This topic is 1255 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

 

I've run into a problem trying to apply textures to a model which is loaded in through the Assimp model loader. The model is a simple 8 vertex cube. I've checked inside both Blender and 3DS Max to see if the UV mapping is correct, and it does seem to be. The texture is black and white checkers, and is 256x256 (in case the problem was the texture needed padding). 

I've exported the model in several different formats, and I've tried several different textures. The strange thing is that some of the model formats have different problems regarding the texture. In all cases it seems to be something to do with the UV coordinates, and since Blender and 3DS Max seem to believe they're correct, I'm under the impression that perhaps I'm loading the UV coordinates incorrectly. I'm also quite sure that the images are loaded correctly, as the images for the skybox are working fine, the difference being that the skybox generates it's own UV coordinates to use. 

 

Here's a screenshot of the scene: 

[attachment=26339:Screenshot 1.png]

 

How I'm loading the models:

static Mesh
	loadMesh(char *filename)
	{
		Mesh returnMesh;
		Assimp::Importer *importer = new Assimp::Importer();
		const aiScene *scene = importer->ReadFile(filename, 
			aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_GenUVCoords | aiProcess_TransformUVCoords);

		returnMesh.numMeshes = scene->mNumMeshes;
		returnMesh.numOfIndices = new GLuint[returnMesh.numMeshes];
		returnMesh.vaos = new GLuint[returnMesh.numMeshes];
		// generate and set up a VAO for each mesh
		glGenVertexArrays(returnMesh.numMeshes, returnMesh.vaos);

		for (unsigned int meshIndex = 0; meshIndex < scene->mNumMeshes; meshIndex++)
		{
			std::vector<GLuint> indices;
			const aiMesh* currentMesh = scene->mMeshes[meshIndex];

			for (unsigned int faceIndex = 0; faceIndex < currentMesh->mNumFaces; faceIndex++)
			{
				aiFace face = currentMesh->mFaces[faceIndex];

				assert(face.mNumIndices == 3);

				for (int index = 0; index < 3; index++)
				{
					//Add indices
					indices.push_back(face.mIndices[index]);
				}
			}

			returnMesh.numOfIndices[meshIndex] = indices.size();

			glBindVertexArray(returnMesh.vaos[meshIndex]);

			GLuint VBO;

			if (currentMesh->HasPositions())
			{
				glGenBuffers(1, &VBO);
				glBindBuffer(GL_ARRAY_BUFFER, VBO);
				glBufferData(GL_ARRAY_BUFFER, currentMesh->mNumVertices * 3 * sizeof(GLfloat), currentMesh->mVertices, GL_STATIC_DRAW);
				glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
				glEnableVertexAttribArray(0);
			}

			// VBO for normal data
			if (currentMesh->HasNormals()) {
				glGenBuffers(1, &VBO);
				glBindBuffer(GL_ARRAY_BUFFER, VBO);
				glBufferData(GL_ARRAY_BUFFER, currentMesh->mNumVertices * 3 * sizeof(GLfloat), currentMesh->mNormals, GL_STATIC_DRAW);
				glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
				glEnableVertexAttribArray(1);
			}

			// VBO for tex-coord data
			if (!building && currentMesh->HasTextureCoords(0)) {
				glGenBuffers(1, &VBO);
				glBindBuffer(GL_ARRAY_BUFFER, VBO);
				glBufferData(GL_ARRAY_BUFFER, currentMesh->mNumVertices * 2 * sizeof(GLfloat), currentMesh->mTextureCoords[0], GL_STATIC_DRAW);
				glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, 0);
				glEnableVertexAttribArray(2);
			}
			if (indices.size() > 0) {
				glGenBuffers(1, &VBO);
				glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBO);
				glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), indices.data(), GL_STATIC_DRAW);
			}

			// unbind vertex array
			glBindVertexArray(0);
			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

			}

		return returnMesh;
	}

How I'm loading the textures:

GLuint
    loadImage(char *fileName, int req_comp, uint32_t &width, uint32_t &height)
    {
        GLuint result;

        int widthAsInt;
		int heightAsInt;
        int componentsInImageFile;
        unsigned char* image = NULL;
        image = stbi_load(fileName,
                          &widthAsInt,
                          &heightAsInt,
                          &componentsInImageFile,
						  req_comp);

		width = widthAsInt;
		height = heightAsInt;

        if (image != NULL)
        {
            glGenTextures(1, &result);

            glBindTexture(GL_TEXTURE_2D, result);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_REPEAT);

			if ((req_comp == 2) || (req_comp == 4))
            {
                glTexImage2D(GL_TEXTURE_2D,
                             0,
                             GL_RGBA,
							 widthAsInt, heightAsInt,
                             0,
                             GL_RGBA,
                             GL_UNSIGNED_BYTE,
							 image);
            }
            else
            {
                glTexImage2D(GL_TEXTURE_2D,
                             0,
                             GL_RGB,
							 widthAsInt, heightAsInt,
                             0,
                             GL_RGB,
                             GL_UNSIGNED_BYTE,
							 image);
            }

            glBindTexture(GL_TEXTURE_2D, 0);

            stbi_image_free(image);
        }
        else
        {
            std::cout << "Failed to Load Image: " << fileName << std::endl;
		}

        return result;
    }

Had this problem for a couple weeks now and running out of ideas of how to fix it. 

Share this post


Link to post
Share on other sites
Advertisement

Assimp mesh texture coordinates have 3 components and not two. So when you copy the info into a buffer you need to take that into account.

	glBufferData(GL_ARRAY_BUFFER, currentMesh->mNumVertices * 3 * sizeof(GLfloat), currentMesh->mTextureCoords[0], GL_STATIC_DRAW);
	glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);

Or copy it into an intermediate buffer first

 
//textureVertices is an array of 2 float component uvs  
for (unsigned int vertex = 0; vertex < numVerts; vertex++){
  memcpy(&textureVertices[vertex].uv,   &thisMesh->mTextureCoords[0][vertex],sizeof(float) * 2);
}
 
glBufferData(GL_ARRAY_BUFFER,currentMesh->mNumVertices * 2 * sizeof(GLfloat), textureVertices, GL_STATIC_DRAW)
 
Edited by BloodOrange1981

Share this post


Link to post
Share on other sites

That was indeed the problem I was having. I remember actually changing a 3 to a 2 before for the UV coords thinking "there's only 2 components in a texture coordinate"! 

Thanks so much for the help!

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!