mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 07:53:53 +00:00
Better handle material texture layers
This commit is contained in:
parent
ffb133c862
commit
f6f165852d
1 changed files with 67 additions and 43 deletions
|
@ -538,16 +538,51 @@ static std::map<size_t,std::string> MaterialMap;
|
|||
|
||||
static void warn(const std::string &msg)
|
||||
{
|
||||
std::cerr << "NIFMeshLoader: Warn: " << msg << std::endl;
|
||||
std::cerr << "NIFMaterialLoader: Warn: " << msg << std::endl;
|
||||
}
|
||||
|
||||
static void fail(const std::string &msg)
|
||||
{
|
||||
std::cerr << "NIFMeshLoader: Fail: "<< msg << std::endl;
|
||||
std::cerr << "NIFMaterialLoader: Fail: "<< msg << std::endl;
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
static std::string findTextureName(const std::string &filename)
|
||||
{
|
||||
/* Bethesda at some point converted all their BSA
|
||||
* textures from tga to dds for increased load speed, but all
|
||||
* texture file name references were kept as .tga.
|
||||
*/
|
||||
static const char path[] = "textures\\";
|
||||
|
||||
std::string texname = filename;
|
||||
Misc::StringUtils::toLower(texname);
|
||||
|
||||
if(texname.compare(0, sizeof(path)-1, path) != 0)
|
||||
texname = path + texname;
|
||||
|
||||
Ogre::String::size_type pos = texname.rfind('.');
|
||||
if(pos != Ogre::String::npos && texname.compare(pos, texname.length() - pos, ".dds") != 0)
|
||||
{
|
||||
// since we know all (GOTY edition or less) textures end
|
||||
// in .dds, we change the extension
|
||||
texname.replace(pos, texname.length(), ".dds");
|
||||
|
||||
// if it turns out that the above wasn't true in all cases (not for vanilla, but maybe mods)
|
||||
// verify, and revert if false (this call succeeds quickly, but fails slowly)
|
||||
if(!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(texname))
|
||||
{
|
||||
texname = filename;
|
||||
Misc::StringUtils::toLower(texname);
|
||||
if(texname.compare(0, sizeof(path)-1, path) != 0)
|
||||
texname = path + texname;
|
||||
}
|
||||
}
|
||||
|
||||
return texname;
|
||||
}
|
||||
|
||||
public:
|
||||
static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String &name, const Ogre::String &group,
|
||||
const Nif::NiTexturingProperty *texprop,
|
||||
|
@ -575,47 +610,29 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String
|
|||
int depthFlags = 3;
|
||||
// Default should be 1, but Bloodmoon's models are broken
|
||||
int specFlags = 0;
|
||||
Ogre::String texName;
|
||||
Ogre::String texName[7];
|
||||
|
||||
bool vertexColour = (shape->data->colors.size() != 0);
|
||||
|
||||
// Texture
|
||||
if(texprop && texprop->textures[0].inUse)
|
||||
if(texprop)
|
||||
{
|
||||
const Nif::NiSourceTexture *st = texprop->textures[0].texture.getPtr();
|
||||
if(st->external)
|
||||
for(int i = 0;i < 7;i++)
|
||||
{
|
||||
/* Bethesda at some point converted all their BSA
|
||||
* textures from tga to dds for increased load speed, but all
|
||||
* texture file name references were kept as .tga.
|
||||
*/
|
||||
static const char path[] = "textures\\";
|
||||
|
||||
texName = st->filename;
|
||||
Misc::StringUtils::toLower(texName);
|
||||
|
||||
if(texName.compare(0, sizeof(path)-1, path) != 0)
|
||||
texName = path + texName;
|
||||
|
||||
Ogre::String::size_type pos = texName.rfind('.');
|
||||
if(pos != Ogre::String::npos && texName.compare(pos, texName.length() - pos, ".dds") != 0)
|
||||
if(!texprop->textures[i].inUse)
|
||||
continue;
|
||||
if(texprop->textures[i].texture.empty())
|
||||
{
|
||||
// since we know all (GOTY edition or less) textures end
|
||||
// in .dds, we change the extension
|
||||
texName.replace(pos, texName.length(), ".dds");
|
||||
|
||||
// if it turns out that the above wasn't true in all cases (not for vanilla, but maybe mods)
|
||||
// verify, and revert if false (this call succeeds quickly, but fails slowly)
|
||||
if(!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(texName))
|
||||
{
|
||||
texName = st->filename;
|
||||
Misc::StringUtils::toLower(texName);
|
||||
if(texName.compare(0, sizeof(path)-1, path) != 0)
|
||||
texName = path + texName;
|
||||
}
|
||||
warn("Texture layer "+Ogre::StringConverter::toString(i)+" is in use but empty in "+name+"\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
const Nif::NiSourceTexture *st = texprop->textures[0].texture.getPtr();
|
||||
if(st->external)
|
||||
texName[i] = findTextureName(st->filename);
|
||||
else
|
||||
warn("Found internal texture, ignoring.");
|
||||
}
|
||||
else warn("Found internal texture, ignoring.");
|
||||
}
|
||||
|
||||
// Alpha modifiers
|
||||
|
@ -655,8 +672,6 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String
|
|||
alpha = matprop->data.alpha;
|
||||
}
|
||||
|
||||
Ogre::String matname = name;
|
||||
if(matprop || !texName.empty())
|
||||
{
|
||||
// Generate a hash out of all properties that can affect the material.
|
||||
size_t h = 0;
|
||||
|
@ -672,7 +687,11 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String
|
|||
boost::hash_combine(h, emissive.x);
|
||||
boost::hash_combine(h, emissive.y);
|
||||
boost::hash_combine(h, emissive.z);
|
||||
boost::hash_combine(h, texName);
|
||||
for(int i = 0;i < 7;i++)
|
||||
{
|
||||
if(!texName[i].empty())
|
||||
boost::hash_combine(h, texName[i]);
|
||||
}
|
||||
boost::hash_combine(h, vertexColour);
|
||||
boost::hash_combine(h, alphaFlags);
|
||||
boost::hash_combine(h, alphaTest);
|
||||
|
@ -687,11 +706,11 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String
|
|||
return itr->second;
|
||||
}
|
||||
// not found, create a new one
|
||||
MaterialMap.insert(std::make_pair(h, matname));
|
||||
MaterialMap.insert(std::make_pair(h, name));
|
||||
}
|
||||
|
||||
// No existing material like this. Create a new one.
|
||||
sh::MaterialInstance* instance = sh::Factory::getInstance ().createMaterialInstance (matname, "openmw_objects_base");
|
||||
sh::MaterialInstance *instance = sh::Factory::getInstance().createMaterialInstance(name, "openmw_objects_base");
|
||||
if(vertMode == 0 || !vertexColour)
|
||||
{
|
||||
instance->setProperty("ambient", sh::makeProperty(new sh::Vector4(ambient.x, ambient.y, ambient.z, 1)));
|
||||
|
@ -722,13 +741,18 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String
|
|||
new sh::Vector4(specular.x, specular.y, specular.z, glossiness)));
|
||||
}
|
||||
|
||||
instance->setProperty("diffuseMap", sh::makeProperty(texName));
|
||||
instance->setProperty("diffuseMap", sh::makeProperty(texName[0]));
|
||||
for(int i = 1;i < 7;i++)
|
||||
{
|
||||
if(!texName[i].empty())
|
||||
warn("Ignored texture "+texName[i]+" on layer "+Ogre::StringConverter::toString(i)+"\n");
|
||||
}
|
||||
|
||||
if (vertexColour)
|
||||
instance->setProperty("has_vertex_colour", sh::makeProperty(new sh::BooleanValue(true)));
|
||||
|
||||
// Add transparency if NiAlphaProperty was present
|
||||
NifOverrides::TransparencyResult result = NifOverrides::Overrides::getTransparencyOverride(texName);
|
||||
NifOverrides::TransparencyResult result = NifOverrides::Overrides::getTransparencyOverride(texName[0]);
|
||||
if (result.first)
|
||||
{
|
||||
alphaFlags = (1<<9) | (6<<10); /* alpha_rejection enabled, greater_equal */
|
||||
|
@ -763,8 +787,8 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String
|
|||
instance->setProperty("depth_write", sh::makeProperty(new sh::StringValue(((depthFlags>>1)&1) ? "on" : "off")));
|
||||
// depth_func???
|
||||
|
||||
sh::Factory::getInstance()._ensureMaterial(matname, "Default");
|
||||
return matname;
|
||||
sh::Factory::getInstance()._ensureMaterial(name, "Default");
|
||||
return name;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue