Browse Source

Material initialization.
Fixes material initialization for texture and transparency assignments.
Lists all available material properties to console in debug builds.
Adds TORQUE_PBR_MATERIALS define for testing with PBR branches.

OTHGMars 6 years ago
parent
commit
ad29d3132e

+ 266 - 58
Engine/source/ts/assimp/assimpAppMaterial.cpp

@@ -19,6 +19,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
+//#define TORQUE_PBR_MATERIALS
 
 #include "platform/platform.h"
 #include "ts/loader/appSequence.h"
@@ -38,7 +39,7 @@ String AppMaterial::cleanString(const String& str)
    String cleanStr(str);
 
    // Replace invalid characters with underscores
-   const String badChars(" -,.+=*/");
+   const String badChars(" -,.+=*/[]");
    for (String::SizeType i = 0; i < badChars.length(); i++)
       cleanStr.replace(badChars[i], '_');
 
@@ -52,50 +53,27 @@ String AppMaterial::cleanString(const String& str)
 AssimpAppMaterial::AssimpAppMaterial(const char* matName)
 {
    name = matName;
-   diffuseColor = LinearColorF::ONE;
-   specularColor = LinearColorF::ONE;
-   specularPower = 0.8f;
-   doubleSided = false;
 
    // Set some defaults
    flags |= TSMaterialList::S_Wrap;
    flags |= TSMaterialList::T_Wrap;
 }
 
-AssimpAppMaterial::AssimpAppMaterial(const struct aiMaterial* mtl)
+AssimpAppMaterial::AssimpAppMaterial(aiMaterial* mtl) :
+   mAIMat(mtl)
 {
    aiString matName;
    mtl->Get(AI_MATKEY_NAME, matName);
    name = matName.C_Str();
-   if ( name.isEmpty() )
-      name = "defaultMaterial";
-   Con::printf("[ASSIMP] Loaded Material: %s", matName.C_Str());
-   
-   // Opacity
-   F32 opacity = 0.0f;
-   mtl->Get(AI_MATKEY_OPACITY, opacity);
-
-   // Diffuse color
-   aiColor3D diff_color (0.f, 0.f, 0.f);
-   mtl->Get(AI_MATKEY_COLOR_DIFFUSE, diff_color);
-   diffuseColor = LinearColorF(diff_color.r, diff_color.g, diff_color.b, opacity);
-
-   // Spec Color color
-   aiColor3D spec_color (0.f, 0.f, 0.f);
-   mtl->Get(AI_MATKEY_COLOR_DIFFUSE, spec_color );
-   specularColor = LinearColorF(spec_color.r, spec_color.g, spec_color.b, 1.0f);
-
-   // Specular Power
-   mtl->Get(AI_MATKEY_SHININESS_STRENGTH, specularPower);
-
-   // Double-Sided
-   S32 dbl_sided = 0;
-   mtl->Get(AI_MATKEY_TWOSIDED, dbl_sided);
-   doubleSided = (dbl_sided != 0);
-
-   // Set some defaults
-   flags |= TSMaterialList::S_Wrap;
-   flags |= TSMaterialList::T_Wrap;
+   if (name.isEmpty())
+   {
+      name = cleanString(TSShapeLoader::getShapePath().getFileName());;
+      name += "_defMat";
+   }
+   Con::printf("[ASSIMP] Loading Material: %s", name.c_str());
+#ifdef TORQUE_DEBUG
+   enumerateMaterialProperties(mtl);
+#endif
 }
 
 Material* AssimpAppMaterial::createMaterial(const Torque::Path& path) const
@@ -105,34 +83,264 @@ Material* AssimpAppMaterial::createMaterial(const Torque::Path& path) const
    String cleanFile = cleanString(TSShapeLoader::getShapePath().getFileName());
    String cleanName = cleanString(getName());
 
-   // Prefix the material name with the filename (if not done already by TSShapeConstructor prefix)
-   //if (!cleanName.startsWith(cleanFile))
-   //   cleanName = cleanFile + "_" + cleanName;
-
-   // Determine the blend operation for this material
-   Material::BlendOp blendOp = (flags & TSMaterialList::Translucent) ? Material::LerpAlpha : Material::None;
-   if (flags & TSMaterialList::Additive)
-      blendOp = Material::Add;
-   else if (flags & TSMaterialList::Subtractive)
-      blendOp = Material::Sub;
-
    // Create the Material definition
    const String oldScriptFile = Con::getVariable("$Con::File");
    Con::setVariable("$Con::File", path.getFullPath());   // modify current script path so texture lookups are correct
-   Material *newMat = MATMGR->allocateAndRegister( cleanName, getName() );
+   Material *newMat = MATMGR->allocateAndRegister(cleanName, getName());
    Con::setVariable("$Con::File", oldScriptFile);        // restore script path
 
-   newMat->mDiffuseMapFilename[0] = "";
-   newMat->mNormalMapFilename[0] = "";
-   newMat->mSpecularMapFilename[0] = "";
+   initMaterial(path, newMat);
 
-   newMat->mDiffuse[0] = diffuseColor;
-   //newMat->mSpecular[0] = specularColor;
-   //newMat->mSpecularPower[0] = specularPower;
+   return newMat;
+}
 
-   newMat->mDoubleSided = doubleSided;
-   newMat->mTranslucent = (bool)(flags & TSMaterialList::Translucent);
-   newMat->mTranslucentBlendOp = blendOp;
+void AssimpAppMaterial::initMaterial(const Torque::Path& path, Material* mat) const
+{
+   String cleanFile = cleanString(TSShapeLoader::getShapePath().getFileName());
+   String cleanName = cleanString(getName());
 
-   return newMat;
-}
+   // Determine the blend mode and transparency for this material
+   Material::BlendOp blendOp = Material::None;
+   bool translucent = false;
+   float opacity = 1.0f;
+   if (AI_SUCCESS == mAIMat->Get(AI_MATKEY_OPACITY, opacity))
+   {
+      if (opacity != 1.0f)
+      {
+         translucent = true;
+         int blendInt;
+         blendOp = Material::LerpAlpha;
+         if (AI_SUCCESS == mAIMat->Get(AI_MATKEY_BLEND_FUNC, blendInt))
+         {
+            if (blendInt == aiBlendMode_Additive)
+               blendOp = Material::Add;
+         }
+      }
+   }
+   else
+   {  // No opacity key, see if it's defined as a gltf property
+      aiString opacityMode;
+      if (AI_SUCCESS == mAIMat->Get("$mat.gltf.alphaMode", 0, 0, opacityMode))
+      {
+         if (dStrcmp("MASK", opacityMode.C_Str()) == 0)
+         {
+            translucent = true;
+            blendOp = Material::LerpAlpha;
+
+            float cutoff;
+            if (AI_SUCCESS == mAIMat->Get("$mat.gltf.alphaCutoff", 0, 0, cutoff))
+            {
+               mat->mAlphaRef = (U32)(cutoff * 255);  // alpha ref 0-255
+               mat->mAlphaTest = true;
+            }
+         }
+         else if (dStrcmp("OPAQUE", opacityMode.C_Str()) != 0)
+         {
+            translucent = true;
+            blendOp = Material::LerpAlpha;
+         }
+      }
+   }
+   mat->mTranslucent = translucent;
+   mat->mTranslucentBlendOp = blendOp;
+
+   // Assign color values.
+   LinearColorF diffuseColor(1.0f, 1.0f, 1.0f, 1.0f);
+   aiColor3D read_color(1.f, 1.f, 1.f);
+   if (AI_SUCCESS == mAIMat->Get(AI_MATKEY_COLOR_DIFFUSE, read_color))
+      diffuseColor.set(read_color.r, read_color.g, read_color.b, opacity);
+   mat->mDiffuse[0] = diffuseColor;
+
+   aiString texName;
+   String torquePath;
+   if (AI_SUCCESS == mAIMat->Get(AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0), texName))
+   {
+      torquePath = texName.C_Str();
+      if (!torquePath.isEmpty())
+         mat->mDiffuseMapFilename[0] = cleanTextureName(torquePath, cleanFile);
+   }
+
+   if (AI_SUCCESS == mAIMat->Get(AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0), texName))
+   {
+      torquePath = texName.C_Str();
+      if (!torquePath.isEmpty())
+         mat->mNormalMapFilename[0] = cleanTextureName(torquePath, cleanFile);
+   }
+
+#ifdef TORQUE_PBR_MATERIALS
+   float floatVal;
+   if (AI_SUCCESS == mAIMat->Get("$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0, floatVal))
+   {  // The shape has pbr material definitions
+      String aoName, rmName; // occlusion and roughness/metalness maps
+      if (AI_SUCCESS == mAIMat->Get(AI_MATKEY_TEXTURE(aiTextureType_LIGHTMAP, 0), texName))
+         aoName = texName.C_Str();
+      if (AI_SUCCESS == mAIMat->Get(AI_MATKEY_TEXTURE(aiTextureType_UNKNOWN, 0), texName))
+         rmName = texName.C_Str();
+
+      //if (aoName.isNotEmpty() && (aoName == rmName))
+      //   mat->mOrmMapFilename[0] = cleanTextureName(aoName, cleanFile); // It's an ORM map
+      //else if (aoName.isNotEmpty() || rmName.isNotEmpty())
+      if (aoName.isNotEmpty() || rmName.isNotEmpty())
+      {  // If we have either map, fill all three slots
+         if (rmName.isNotEmpty())
+         {
+            mat->mRoughMapFilename[0] = cleanTextureName(rmName, cleanFile); // Roughness
+            mat->mSmoothnessChan[0] = 1.0f;
+            mat->mInvertSmoothness = (floatVal == 1.0f);
+            mat->mMetalMapFilename[0] = cleanTextureName(rmName, cleanFile); // Metallic
+            mat->mMetalChan[0] = 2.0f;
+         }
+         if (aoName.isNotEmpty())
+         {
+            mat->mAOMapFilename[0] = cleanTextureName(aoName, cleanFile); // occlusion
+            mat->mAOChan[0] = 0.0f;
+         }
+         else
+         {
+            mat->mAOMapFilename[0] = cleanTextureName(rmName, cleanFile); // occlusion
+            mat->mAOChan[0] = 0.0f;
+         }
+      }
+   }
+#else
+   if (AI_SUCCESS == mAIMat->Get(AI_MATKEY_TEXTURE(aiTextureType_SPECULAR, 0), texName))
+   {
+      torquePath = texName.C_Str();
+      if (!torquePath.isEmpty())
+         mat->mSpecularMapFilename[0] = cleanTextureName(torquePath, cleanFile);
+   }
+
+   LinearColorF specularColor(1.0f, 1.0f, 1.0f, 1.0f);
+   if (AI_SUCCESS == mAIMat->Get(AI_MATKEY_COLOR_SPECULAR, read_color))
+      specularColor.set(read_color.r, read_color.g, read_color.b, opacity);
+   mat->mSpecular[0] = specularColor;
+
+   // Specular Power
+   F32 specularPower = 1.0f;
+   if (AI_SUCCESS == mAIMat->Get(AI_MATKEY_SHININESS_STRENGTH, specularPower))
+      mat->mSpecularPower[0] = specularPower;
+
+   // Specular
+   F32 specularStrength = 0.0f;
+   if (AI_SUCCESS == mAIMat->Get(AI_MATKEY_SHININESS, specularStrength))
+      mat->mSpecularStrength[0] = specularStrength;
+#endif
+
+   // Double-Sided
+   bool doubleSided = false;
+   S32 dbl_sided = 0;
+   if (AI_SUCCESS == mAIMat->Get(AI_MATKEY_TWOSIDED, dbl_sided))
+      doubleSided = (dbl_sided != 0);
+   mat->mDoubleSided = doubleSided;
+}
+
+String AssimpAppMaterial::cleanTextureName(String& texName, String& shapeName)
+{
+   String cleanStr;
+
+   if (texName[0] == '*')
+   {
+      cleanStr = shapeName;
+      cleanStr += "_cachedTex";
+      cleanStr += texName.substr(1);
+   }
+   else
+   {
+      cleanStr = texName;
+      cleanStr.replace('\\', '/');
+   }
+
+   return cleanStr;
+}
+
+#ifdef TORQUE_DEBUG
+void AssimpAppMaterial::enumerateMaterialProperties(aiMaterial* mtl)
+{
+   for (U32 i = 0; i < mtl->mNumProperties; ++i)
+   {
+      aiMaterialProperty* matProp = mtl->mProperties[i];
+      String outText;
+      if (matProp)
+      {
+         outText = String::ToString(" Key: %s, Index: %d, Semantic: ", matProp->mKey.C_Str(), matProp->mIndex);
+         switch (matProp->mSemantic)
+         {
+         case aiTextureType_NONE:
+            outText += "aiTextureType_NONE";
+            break;
+         case aiTextureType_DIFFUSE:
+            outText += "aiTextureType_DIFFUSE";
+            break;
+         case aiTextureType_SPECULAR:
+            outText += "aiTextureType_SPECULAR";
+            break;
+         case aiTextureType_AMBIENT:
+            outText += "aiTextureType_AMBIENT";
+            break;
+         case aiTextureType_EMISSIVE:
+            outText += "aiTextureType_EMISSIVE";
+            break;
+         case aiTextureType_HEIGHT:
+            outText += "aiTextureType_HEIGHT";
+            break;
+         case aiTextureType_NORMALS:
+            outText += "aiTextureType_NORMALS";
+            break;
+         case aiTextureType_SHININESS:
+            outText += "aiTextureType_SHININESS";
+            break;
+         case aiTextureType_OPACITY:
+            outText += "aiTextureType_OPACITY";
+            break;
+         case aiTextureType_DISPLACEMENT:
+            outText += "aiTextureType_DISPLACEMENT";
+            break;
+         case aiTextureType_LIGHTMAP:
+            outText += "aiTextureType_LIGHTMAP";
+            break;
+         case aiTextureType_REFLECTION:
+            outText += "aiTextureType_REFLECTION";
+            break;
+         default:
+            outText += "aiTextureType_UNKNOWN";
+            break;
+         }
+
+         aiString stringProp;
+         F32* floatProp;
+         double* doubleProp;
+         S32* intProp;
+
+         switch (matProp->mType)
+         {
+         case aiPTI_Float:
+            floatProp = (F32*)matProp->mData;
+            for (U32 j = 0; j < matProp->mDataLength / sizeof(F32); ++j)
+               outText += String::ToString(", %0.4f", floatProp[j]);
+            break;
+         case aiPTI_Double:
+            doubleProp = (double*)matProp->mData;
+            for (U32 j = 0; j < matProp->mDataLength / sizeof(double); ++j)
+               outText += String::ToString(", %0.4lf", doubleProp[j]);
+            break;
+         case aiPTI_String:
+            aiGetMaterialString(mtl, matProp->mKey.C_Str(), matProp->mSemantic, matProp->mIndex, &stringProp);
+            outText += String::ToString(", %s", stringProp.C_Str());
+            break;
+         case aiPTI_Integer:
+            intProp = (S32*)matProp->mData;
+            for (U32 j = 0; j < matProp->mDataLength / sizeof(S32); ++j)
+               outText += String::ToString(", %d", intProp[j]);
+            break;
+         case aiPTI_Buffer:
+            outText += ", aiPTI_Buffer format data";
+            break;
+         default:
+            outText += ", Unknown data type";
+         }
+
+         Con::printf("%s", outText.c_str());
+      }
+   }
+}
+#endif

+ 10 - 5
Engine/source/ts/assimp/assimpAppMaterial.h

@@ -26,6 +26,7 @@
 #ifndef _APPMATERIAL_H_
 #include "ts/loader/appMaterial.h"
 #endif
+#include <assimp/scene.h>
 
 class Material;
 
@@ -34,18 +35,22 @@ class AssimpAppMaterial : public AppMaterial
    typedef AppMaterial Parent;
 
    String   name; 
-   LinearColorF   diffuseColor;
-   LinearColorF   specularColor;
-   F32      specularPower;
-   bool     doubleSided;
+   aiMaterial* mAIMat;
+
+#ifdef TORQUE_DEBUG
+   void enumerateMaterialProperties(aiMaterial* mtl);
+#endif
+   static String cleanTextureName(String& texName, String& shapeName);
+
 public:
 
    AssimpAppMaterial(const char* matName);
-   AssimpAppMaterial(const struct aiMaterial* mtl);
+   AssimpAppMaterial(aiMaterial* mtl);
    ~AssimpAppMaterial() { }
 
    String getName() const { return name; }
    Material* createMaterial(const Torque::Path& path) const;
+   void initMaterial(const Torque::Path& path, Material* mat) const;
 };
 
 #endif // _ASSIMP_APPMATERIAL_H_