[+] Embedded uncompressed textures support.

[F] Orphaned textures ID issue.
pull/1011/head
Alexandr Arutjunov 2016-09-29 17:15:21 +03:00
parent a93a230f9e
commit d63bff707e
2 changed files with 116 additions and 73 deletions

View File

@ -164,7 +164,118 @@ std::list<aiMatrix4x4> mat_list;
void CGLView::ImportTextures(const QString& pScenePath) void CGLView::ImportTextures(const QString& pScenePath)
{ {
auto LoadTexture = [&](const QString& pFileName) -> bool ///TODO: IME texture mode, operation.
{
ILboolean success; ILboolean success;
GLuint id_ogl_texture;// OpenGL texture ID.
if(!pFileName.startsWith(AI_EMBEDDED_TEXNAME_PREFIX))
{
ILuint id_image;// DevIL image ID.
QString basepath = pScenePath.left(pScenePath.lastIndexOf('/') + 1);// path with '/' at the end.
QString fileloc = (basepath + pFileName);
fileloc.replace('\\', "/");
ilGenImages(1, &id_image);// Generate DevIL image ID.
ilBindImage(id_image);
success = ilLoadImage(fileloc.toLocal8Bit());
if(!success)
{
LogError(QString("Couldn't load Image: %1").arg(fileloc));
return false;
}
// Convert every colour component into unsigned byte. If your image contains alpha channel you can replace IL_RGB with IL_RGBA.
success = ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);
if(!success)
{
LogError("Couldn't convert image.");
return false;
}
glGenTextures(1, &id_ogl_texture);// Texture ID generation.
mTexture_IDMap[pFileName] = id_ogl_texture;// save texture ID for filename in map
glBindTexture(GL_TEXTURE_2D, id_ogl_texture);// Binding of texture ID.
// Redefine standard texture values
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);// We will use linear interpolation for magnification filter.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);// We will use linear interpolation for minifying filter.
glTexImage2D(GL_TEXTURE_2D, 0, ilGetInteger(IL_IMAGE_BPP), ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), 0,
ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE, ilGetData());// Texture specification.
//Cleanup
ilDeleteImages(1, &id_image);// Because we have already copied image data into texture data we can release memory used by image.
}
else
{
struct SPixel_Description
{
const char* FormatHint;
const GLint Image_InternalFormat;
const GLint Pixel_Format;
};
constexpr SPixel_Description Pixel_Description[] = {
{"rgba8880", GL_RGB, GL_RGB},
{"rgba8888", GL_RGBA, GL_RGBA}
};
constexpr size_t Pixel_Description_Count = sizeof(Pixel_Description) / sizeof(SPixel_Description);
size_t idx_description;
// Get texture index.
bool ok;
size_t idx_texture = pFileName.right(strlen(AI_EMBEDDED_TEXNAME_PREFIX)).toULong(&ok);
if(!ok)
{
LogError("Can not get index of the embedded texture from path in material.");
return false;
}
// Create alias for conveniance.
const aiTexture& als = *mScene->mTextures[idx_texture];
if(als.mHeight == 0)// Compressed texture.
{
LogError("IME: compressed embedded textures are not implemented.");
}
else
{
ok = false;
for(size_t idx = 0; idx < Pixel_Description_Count; idx++)
{
if(als.CheckFormat(Pixel_Description[idx].FormatHint))
{
idx_description = idx;
ok = true;
break;
}
}
if(!ok)
{
LogError(QString("Unsupported format hint for embedded texture: [%1]").arg(als.achFormatHint));
return false;
}
glGenTextures(1, &id_ogl_texture);// Texture ID generation.
mTexture_IDMap[pFileName] = id_ogl_texture;// save texture ID for filename in map
glBindTexture(GL_TEXTURE_2D, id_ogl_texture);// Binding of texture ID.
// Redefine standard texture values
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);// We will use linear interpolation for magnification filter.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);// We will use linear interpolation for minifying filter.
// Texture specification.
glTexImage2D(GL_TEXTURE_2D, 0, Pixel_Description[idx_description].Image_InternalFormat, als.mWidth, als.mHeight, 0,
Pixel_Description[idx_description].Pixel_Format, GL_UNSIGNED_BYTE, (uint8_t*)als.pcData);
}// if(als.mHeight == 0) else
}// if(!filename.startsWith(AI_EMBEDDED_TEXNAME_PREFIX)) else
return true;
};// auto LoadTexture = [&](const aiString& pPath)
if(mScene == nullptr) if(mScene == nullptr)
{ {
@ -183,12 +294,7 @@ ILboolean success;
ilInit();// Initialization of DevIL. ilInit();// Initialization of DevIL.
// //
// Load embedded textures // Load textures.
//
if(mScene->HasTextures()) LogError("Support for meshes with embedded textures is not implemented.");
//
// Load textures from external files.
// //
// Get textures file names and number of textures. // Get textures file names and number of textures.
for(size_t idx_material = 0; idx_material < mScene->mNumMaterials; idx_material++) for(size_t idx_material = 0; idx_material < mScene->mNumMaterials; idx_material++)
@ -200,10 +306,10 @@ ILboolean success;
{ {
if(mScene->mMaterials[idx_material]->GetTexture(aiTextureType_DIFFUSE, idx_texture, &path) != AI_SUCCESS) break; if(mScene->mMaterials[idx_material]->GetTexture(aiTextureType_DIFFUSE, idx_texture, &path) != AI_SUCCESS) break;
mTexture_IDMap[path.data] = 0;// Fill map with invalid ID's. LoadTexture(QString(path.C_Str()));
idx_texture++; idx_texture++;
} while(true); } while(true);
}// for(size_t idx_mat = 0; idx_mat < scene->mNumMaterials; idx_mat++) }// for(size_t idx_material = 0; idx_material < mScene->mNumMaterials; idx_material++)
// Textures list is empty, exit. // Textures list is empty, exit.
if(mTexture_IDMap.size() == 0) if(mTexture_IDMap.size() == 0)
@ -212,71 +318,6 @@ ILboolean success;
return; return;
} }
size_t num_textures = mTexture_IDMap.size();
ILuint* id_images = nullptr;// Array with DevIL image ID's.
GLuint* id_textures = nullptr;// Array with OpenGL textures ID's.
// Generate DevIL image IDs.
id_images = new ILuint[num_textures];
ilGenImages(num_textures, id_images);// Generation of 'num_textures' image names.
// Create and fill array with OpenGL texture ID's.
id_textures = new GLuint[num_textures];
///TODO: if can not load textures then will stay orphande texture ID's in OpenGL. Generate OpenGL ID's after successfull loading of image.
glGenTextures(num_textures, id_textures);// Texture ID's generation.
QMap<QString, GLuint>::iterator map_it = mTexture_IDMap.begin();// Get iterator
QString basepath = pScenePath.left(pScenePath.lastIndexOf('/') + 1);// path with '/' at the end.
for(size_t idx_texture = 0; idx_texture < num_textures; idx_texture++)
{
//save IL image ID
QString filename = map_it.key();// get filename
mTexture_IDMap[filename] = id_textures[idx_texture];// save texture ID for filename in map
map_it++;// next texture
ilBindImage(id_images[idx_texture]);// Binding of DevIL image name.
QString fileloc = basepath + filename; /* Loading of image */
fileloc.replace('\\', "/");
success = ilLoadImage(fileloc.toLocal8Bit());
if(!success)
{
LogError(QString("Couldn't load Image: %1").arg(fileloc));
goto it_for_err;
}
// Convert every colour component into unsigned byte. If your image contains alpha channel you can replace IL_RGB with IL_RGBA.
success = ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);
if(!success)
{
LogError("Couldn't convert image.");
goto it_for_err;
}
glBindTexture(GL_TEXTURE_2D, id_textures[idx_texture]);// Binding of texture ID.
// Redefine standard texture values
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);// We will use linear interpolation for magnification filter.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);// We will use linear interpolation for minifying filter.
glTexImage2D(GL_TEXTURE_2D, 0, ilGetInteger(IL_IMAGE_BPP), ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), 0,
ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE, ilGetData());// Texture specification.
continue;
it_for_err:
LogError(QString("DevIL error: %1, [%2]").arg(ilGetError()).arg(ilGetString(ilGetError())));
mTexture_IDMap.remove(filename);
}// for(size_t idx_texture = 0; idx_texture < num_textures; i++)
// Because we have already copied image data into texture data we can release memory used by image.
ilDeleteImages(num_textures, id_images);
//Cleanup
delete [] id_images;
delete [] id_textures;
} }
void CGLView::BBox_GetForNode(const aiNode& pNode, const aiMatrix4x4& pParent_TransformationMatrix, SBBox& pNodeBBox, bool& pFirstAssign) void CGLView::BBox_GetForNode(const aiNode& pNode, const aiMatrix4x4& pParent_TransformationMatrix, SBBox& pNodeBBox, bool& pFirstAssign)

View File

@ -156,6 +156,8 @@ private:
// Lighting // Lighting
bool mLightingEnabled = false;///< If true then OpenGL lighting is enabled (glEnable(GL_LIGHTING)), if false - disabled. bool mLightingEnabled = false;///< If true then OpenGL lighting is enabled (glEnable(GL_LIGHTING)), if false - disabled.
// Textures // Textures
///TODO: map is goooood, but not for case when one image can be used in different materials with difference in: texture transformation, targeting of the
/// texture (ambient or emission, or even height map), texture properties.
QMap<QString, GLuint> mTexture_IDMap;///< Map image filenames to textures ID's. QMap<QString, GLuint> mTexture_IDMap;///< Map image filenames to textures ID's.
/**********************************/ /**********************************/