Menu

How do materials reference embedded textures?

Help
Vinnie
2017-04-21
2017-04-21
  • Vinnie

    Vinnie - 2017-04-21

    Hi Guys (Kim)

    I realise this is a repeated questions, but I'm simply not getting it. I've looked at both the aiTexture and aiMaterial structures and are unable to work out how the aiMaterial reference embedded textures, i.e. those in Scene::mTextures[]. (I'm assuming the aiMaterial structure has knowlege of which embedded texture relates to it?)

    I'm currently using GetTextureCount() and GetTexture() to determine the path to the external textures, but how do I find the index into the Scene::mTextures[] array for the embedded textures that matches the material for a particular texture stack?

    Cheers
    -Vinnie

     
  • Vinnie

    Vinnie - 2017-04-22

    Hi Guys

    I found this: https://github.com/assimp/assimp/issues/408

    However looking through the code I get how the textures are created, but then when the textures are used for rendering I see this:

    if(mesh->HasTextureCoords(0))
    {
        // get current texture ID and check if need to enable new texture
        if(mesh->mTextureCoords[1][t].x != prev_tex_id_idx)
        {
            prev_tex_id_idx = mesh->mTextureCoords[1][t].x;
            glBindTexture(GL_TEXTURE_2D, textureIds[prev_tex_id_idx]);
        }
    }
    

    This seems to imply that the first value in the texture coordinates array is used to indicate the index of the embedded texture in the array.

    Now the question become, is this right? There are no reference in any of the documentation (that I can see) about this mechanism nor does it indicate how to determine when the first value indicate the index into the textures array or when it indicates the x component of a texture coordinate for an external texture.

    I'll have a read through the .mdl importer code later today and see if there is more info.

    Cheers
    -Vinnie

     
  • Vinnie

    Vinnie - 2017-04-22

    Hi Guys

    Looking at the MDLLoader.cpp code file, it seems that a special file name is created for embedded textures. In particular, the macro looks like:

    /** @def AI_MAKE_EMBEDDED_TEXNAME
     *  Used to build the reserved path name used by the material system to
     *  reference textures that are embedded into their corresponding
     *  model files. The parameter specifies the index of the texture
     *  (zero-based, in the aiScene::mTextures array)
     */
    #if (!defined AI_MAKE_EMBEDDED_TEXNAME)
    #   define AI_MAKE_EMBEDDED_TEXNAME(_n_) "*" # _n_
    #endif
    

    So I would expect the file names to look like: "0", "1", etc. This is just a string parsing exercise at this point. I've run a test on a Quake level with embedded textures and I think this is the answer. The following C++ code show what I did:

      // Print the number of embedded textures.
      std::cout << "Num Embedded Texture: " << scene->mNumTextures << std::endl;
    
      // The regular expression to find the index of the texture if it's an
      // embedded texture.
      std::regex regexExpress("^\\*\\d+");
      std::cmatch regexMatches;
    
      // Print out the name of all the textures.
      for(size_t i = 0; i < scene->mNumMaterials; i++)
      {
        // The handle to the material.
        aiMaterial * material = scene->mMaterials[i];
    
        std::cout << "LIGHTMAP TEXTURES\n=================" << std::endl;
    
        // Get all the diffuse meshes.
        for(size_t j = 0; j < material->GetTextureCount(aiTextureType_LIGHTMAP); j++)
        {
          // The path to the texture.
          aiString texturePath;
    
          // Get the path to the texture.
          if(material->GetTexture(aiTextureType_LIGHTMAP, j, &texturePath) ==
             aiReturn_SUCCESS)
          {
            // Check if it's an embedded or external  texture.
            if(std::regex_search(texturePath.C_Str(), regexMatches, regexExpress))
            {
              // Get the index str.
              std::string indexStr = *(regexMatches.begin());
    
              // Drop the "*" character.
              indexStr = indexStr.erase(0,1);
    
              // Convert the string to an integer. (This is the index in the
              // Scene::mTextures[] array.
              int index = std::stoi(indexStr);
    
              // Print the index.
              std::cout << "Scene::mTextures[" << index << "]." << std::endl;
            }
            else
            {
              // Print the texture file path.
              std::cout << "File Path: " << texturePath.C_Str() << std::endl;
            }
          }
        }
      }
    

    The output is as follow (yes this quake level has 1000+ lightmap textures):

    =================
    Scene::mTextures[1100].
    LIGHTMAP TEXTURES
    =================
    Scene::mTextures[1102].
    LIGHTMAP TEXTURES
    =================
    Scene::mTextures[1104].
    LIGHTMAP TEXTURES
    =================
    Scene::mTextures[1106].
    LIGHTMAP TEXTURES
    =================
    Scene::mTextures[1108].
    LIGHTMAP TEXTURES
    =================
    Scene::mTextures[1110].
    LIGHTMAP TEXTURES
    =================
    Scene::mTextures[1112].
    

    Anyway, as per my second post, I still think the code example provided at https://github.com/assimp/assimp/issues/408 is wrong (or maybe outdated?). This code in this post seems to work perfectly at this time. Perhaps the documentation (http://www.assimp.org/lib_html/materials.html) can be updated to reflect this information?

    Cheers
    -Vinnie

     

Log in to post a comment.