Assimp не импортирует текстуры

Я использую Assimp для импорта 3D-моделей в моем игровом движке. По какой-то причине, независимо от того, какую модель или формат я использую, assimp не сообщает о каких-либо текстурах. Почему это?

Ниже приведена очень простая установка с assimp:

const aiScene* scene = importer.ReadFile(asset, aiProcessPreset_TargetRealtime_Quality);

if (scene->HasMaterials())
        {
            for (unsigned int i = 0; i < scene->mNumMaterials; i++)
            {
                const aiMaterial* material = scene->mMaterials[i];
                aiString texturePath;

                unsigned int numTextures= material->GetTextureCount(aiTextureType_DIFFUSE);   // always 0

                if (material->GetTextureCount(aiTextureType_DIFFUSE) > 0 && material->GetTexture(aiTextureType_DIFFUSE, 0, &texturePath) == AI_SUCCESS) 
                {
                   // never happens..
                   // scene->mNumTextures is always 0 aswell.
                }
            }
        }

Я использую различные модели, которые, как я уверен, имеют текстуры, например, модели из учебных пособий, которые разработаны по очень конкретной причине загрузки текстурированных моделей с использованием Assimp. (например, http://www.lighthouse3d.com/cg-topics/code-samples/importing-3d-models-with-assimp)

Что может быть причиной этого?

3 ответа

Я знаю, что это довольно старо, но у меня была именно эта проблема последние пару дней, и мне удалось ее решить, так что вот решение для тех, кто ищет.

Есть две возможные причины, по которым ваши текстуры не загружаются:

  1. Текстуры встроены.

или же

  1. Что-то не так с вашим файлом материалов для модели.

Если это случай № 1, то он не работает просто потому, что GetTexture и GetTextureCount не применяются к встроенным материалам. Вложенные материалы, как правило, просто простые цвета. Если вы хотите узнать, как импортировать внедренные материалы, взгляните на примеры кодов ASSIMP или исходный код AssimpView.

Скорее всего, ваша проблема в случае № 2: что-то не так с вашим файлом материалов. Например, файлы модели.OBJ поставляются с соответствующим файлом.MTL, если они текстурированные. Если файл.MTL отсутствует, текстуры не будут загружаться. Если с файлом.MTL что-то не так, текстуры также не будут загружаться.

Итак, убедитесь, что все ваши файлы.mtl есть и любые другие файлы материалов (включая изображения для самих текстур). Если они есть, то следующее, что вам нужно сделать, это открыть модель с помощью инструмента AssimpView. Убедитесь, что модель загружается правильно со всеми своими текстурами. Если это не так, либо что-то не так с файлом материалов (решение ниже), либо что-то не так с файлом модели, и Assimp просто не может его загрузить (или что-то в корне не так с Assimp). Если он загружается правильно, вы должны увидеть названия диффузных текстур в правой части AssimpView.

Итак, если все это проверено и импортер Assimp в вашей программе все еще не распознает текстуры из вашей модели (даже если AssimpView это делает), то следующее, что вы хотите сделать, - это на самом деле открыть файл.MTL, используя что-то вроде блокнота. Вы увидите что-то вроде этого:

# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware
# File Created: 06.10.2013 19:40:35

newmtl 01___Default
Ns 10.0000
illum 2
Ka 0.0000 0.0000 0.0000
Kd 0.5882 0.5882 0.5882
Ks 0.0000 0.0000 0.0000
Ni 1
d 0
map_Kd MoonMap2_2500x1250.jpg

Существуют различные вещи, которые могут быть не так с этими файлами. Обратите внимание, что map_Kd определяет файл изображения, который будет использоваться для диффузной текстуры. Иногда вместо того, чтобы указывать правильный путь или просто имя файла, вы увидите полный путь к каталогу относительно компьютера, на котором была сделана модель (то есть он скажет что-то вроде C:/Users/blah blah blah/MoonMap2...). Вы можете легко исправить это, удалив путь к каталогу и сохранив только имя файла изображения (и сохранив изображение в той же папке, что и модель), или вы можете указать свой собственный путь и поместить туда текстуры.

Другая проблема, с которой вы можете столкнуться, - это то, что переменные перечислены в файле.MTL без фактических значений.

Например:

# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware
# File Created: 06.10.2013 19:40:35

newmtl 01___Default
Ns 10.0000
illum 2
Ka 0.0000 0.0000 0.0000
Kd 0.5882 0.5882 0.5882
Ks 0.0000 0.0000 0.0000
Ni 1
d 0
map_Kd MoonMap2_2500x1250.jpg
map_Ka 

Обратите внимание на "map_Ka" в конце там. Это не имеет ничего рядом с этим. Это не только предотвращает правильное распознавание текстур, но и вообще не позволяет AssimpView загружать модели. Просто удалите все свойства, которые вы видите, когда у них нет значений рядом с ними.

Наконец, если ничего из этого не работает, то вам, возможно, придется просто поэкспериментировать с файлом.MTL - в нем может быть свойство / переменная, которая по какой-то причине вызывает проблемы, поэтому попробуйте удалить строки, в которых вы абсолютно уверены, что не используете не нужно (обратите внимание, что Kd представляет диффузную текстуру, Ka будет представлять текстуру окружающей среды, Ks зеркальная и т. д.). Файл.MTL, который я использовал здесь в качестве примера, содержит то, что я считаю минимальными строками, которые должен иметь файл MTL, чтобы можно было загружать диффузную текстуру.

Надеюсь это поможет. Если ничего из этого не работает, я подозреваю, что с вашей библиотекой ASSIMP что-то не так. Если в вашем файле модели нет файла материалов... это ваша проблема.

Изучение источников assimp показывает, что в импортере OBJ нет mNumTextures ++. Так что это никогда не даст положительного результата при импорте OBJ-файлов.

Правильный метод загрузки текстур - добавить в конец apply_material() (вы можете получить исходные коды в репозитории assimp на github) следующий код (язык D):

aiString path;
if(aiReturn_SUCCESS == aiGetMaterialTexture(mtl, aiTextureType_DIFFUSE, 0, &path))
{
    string p = (cast(const(char)*)(path.data)).to!(string)();

    GLuint texture_name;
    glGenTextures(1, &texture_name);// generate GL-textures ID's
    glBindTexture(GL_TEXTURE_2D, texture_name);// Binding of texture name
    //
    //redefine standard texture values
    //
    // We will use linear interpolation for magnification filter
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    // tiling mode
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, true ? GL_REPEAT : GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, true ? GL_REPEAT : GL_CLAMP);

    auto image = IMG_Load(p.toStringz);
    if (!image)
    {
        throw new Exception(format("Error while loading texture: %s", p));
    }

    // Texture specification
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image.w, image.h, 0, GL_RGBA, GL_UNSIGNED_BYTE,
            image.pixels);
}

И для отображения этой текстуры добавьте в recursive_render() между glColor4fv и glNormal3fv следующую строку:

glTexCoord2f(mesh.mTextureCoords[0][index].x, 1.0-mesh.mTextureCoords[0][index].y);

Продолжая то, что Мэтт сказал о том, что файл материала действителен, я обнаружил еще одну возможную проблему с не загружаемыми материалами и решение для нее.

В файле obj есть ссылки на файл материала и название материала в этом файле. Если вы переименовали файл, они не будут совпадать, и материал не будет найден.

В файле obj вы найдете строку, которая выглядит следующим образом

mtllib deer-obj.mtl

Это имя файла материала. Если вы переименовали материал, вы должны переименовать его и здесь.

В этом же файле вы найдете ссылки на названия материалов, определенных в файле материалов, например:

usemtl deer

Это должно соответствовать названиям материалов в файле материалов. В файле MTL я определил это:

newmtl deer

Имя "usemtl" и "newmtl" должны совпадать, чтобы найти материал.

Другие вопросы по тегам