Merge pull request #249 from attila-barsi/master
Initial version for FBX layered textures.pull/251/head
commit
a6044e125e
|
@ -23,7 +23,7 @@ following conditions are met:
|
||||||
derived from this software without specific prior
|
derived from this software without specific prior
|
||||||
written permission of the assimp team.
|
written permission of the assimp team.
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
@ -767,6 +767,7 @@ private:
|
||||||
|
|
||||||
// find user defined properties (3ds Max)
|
// find user defined properties (3ds Max)
|
||||||
data->Set(index++, "UserProperties", aiString(PropertyGet<std::string>(props, "UDP3DSMAX", "")));
|
data->Set(index++, "UserProperties", aiString(PropertyGet<std::string>(props, "UDP3DSMAX", "")));
|
||||||
|
unparsedProperties.erase("UDP3DSMAX");
|
||||||
// preserve the info that a node was marked as Null node in the original file.
|
// preserve the info that a node was marked as Null node in the original file.
|
||||||
data->Set(index++, "IsNull", model.IsNull() ? true : false);
|
data->Set(index++, "IsNull", model.IsNull() ? true : false);
|
||||||
|
|
||||||
|
@ -1440,6 +1441,7 @@ private:
|
||||||
|
|
||||||
// texture assignments
|
// texture assignments
|
||||||
SetTextureProperties(out_mat,material.Textures());
|
SetTextureProperties(out_mat,material.Textures());
|
||||||
|
SetTextureProperties(out_mat,material.LayeredTextures());
|
||||||
|
|
||||||
return static_cast<unsigned int>(materials.size() - 1);
|
return static_cast<unsigned int>(materials.size() - 1);
|
||||||
}
|
}
|
||||||
|
@ -1456,7 +1458,103 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
const Texture* const tex = (*it).second;
|
const Texture* const tex = (*it).second;
|
||||||
|
if(tex !=0 )
|
||||||
|
{
|
||||||
|
aiString path;
|
||||||
|
path.Set(tex->RelativeFilename());
|
||||||
|
|
||||||
|
out_mat->AddProperty(&path,_AI_MATKEY_TEXTURE_BASE,target,0);
|
||||||
|
|
||||||
|
aiUVTransform uvTrafo;
|
||||||
|
// XXX handle all kinds of UV transformations
|
||||||
|
uvTrafo.mScaling = tex->UVScaling();
|
||||||
|
uvTrafo.mTranslation = tex->UVTranslation();
|
||||||
|
out_mat->AddProperty(&uvTrafo,1,_AI_MATKEY_UVTRANSFORM_BASE,target,0);
|
||||||
|
|
||||||
|
const PropertyTable& props = tex->Props();
|
||||||
|
|
||||||
|
int uvIndex = 0;
|
||||||
|
|
||||||
|
bool ok;
|
||||||
|
const std::string& uvSet = PropertyGet<std::string>(props,"UVSet",ok);
|
||||||
|
if(ok) {
|
||||||
|
// "default" is the name which usually appears in the FbxFileTexture template
|
||||||
|
if(uvSet != "default" && uvSet.length()) {
|
||||||
|
// this is a bit awkward - we need to find a mesh that uses this
|
||||||
|
// material and scan its UV channels for the given UV name because
|
||||||
|
// assimp references UV channels by index, not by name.
|
||||||
|
|
||||||
|
// XXX: the case that UV channels may appear in different orders
|
||||||
|
// in meshes is unhandled. A possible solution would be to sort
|
||||||
|
// the UV channels alphabetically, but this would have the side
|
||||||
|
// effect that the primary (first) UV channel would sometimes
|
||||||
|
// be moved, causing trouble when users read only the first
|
||||||
|
// UV channel and ignore UV channel assignments altogether.
|
||||||
|
|
||||||
|
const unsigned int matIndex = static_cast<unsigned int>(std::distance(materials.begin(),
|
||||||
|
std::find(materials.begin(),materials.end(),out_mat)
|
||||||
|
));
|
||||||
|
|
||||||
|
uvIndex = -1;
|
||||||
|
BOOST_FOREACH(const MeshMap::value_type& v,meshes_converted) {
|
||||||
|
const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*> (v.first);
|
||||||
|
if(!mesh) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MatIndexArray& mats = mesh->GetMaterialIndices();
|
||||||
|
if(std::find(mats.begin(),mats.end(),matIndex) == mats.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = -1;
|
||||||
|
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
|
||||||
|
if(mesh->GetTextureCoords(i).empty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const std::string& name = mesh->GetTextureCoordChannelName(i);
|
||||||
|
if(name == uvSet) {
|
||||||
|
index = static_cast<int>(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(index == -1) {
|
||||||
|
FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(uvIndex == -1) {
|
||||||
|
uvIndex = index;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
FBXImporter::LogWarn("the UV channel named " + uvSet +
|
||||||
|
" appears at different positions in meshes, results will be wrong");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(uvIndex == -1) {
|
||||||
|
FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel");
|
||||||
|
uvIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out_mat->AddProperty(&uvIndex,1,_AI_MATKEY_UVWSRC_BASE,target,0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void TrySetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures,
|
||||||
|
const std::string& propName,
|
||||||
|
aiTextureType target)
|
||||||
|
{
|
||||||
|
LayeredTextureMap::const_iterator it = layeredTextures.find(propName);
|
||||||
|
if(it == layeredTextures.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Texture* const tex = (*it).second->getTexture();
|
||||||
|
|
||||||
aiString path;
|
aiString path;
|
||||||
path.Set(tex->RelativeFilename());
|
path.Set(tex->RelativeFilename());
|
||||||
|
|
||||||
|
@ -1490,7 +1588,7 @@ private:
|
||||||
|
|
||||||
const unsigned int matIndex = static_cast<unsigned int>(std::distance(materials.begin(),
|
const unsigned int matIndex = static_cast<unsigned int>(std::distance(materials.begin(),
|
||||||
std::find(materials.begin(),materials.end(),out_mat)
|
std::find(materials.begin(),materials.end(),out_mat)
|
||||||
));
|
));
|
||||||
|
|
||||||
uvIndex = -1;
|
uvIndex = -1;
|
||||||
BOOST_FOREACH(const MeshMap::value_type& v,meshes_converted) {
|
BOOST_FOREACH(const MeshMap::value_type& v,meshes_converted) {
|
||||||
|
@ -1539,7 +1637,6 @@ private:
|
||||||
out_mat->AddProperty(&uvIndex,1,_AI_MATKEY_UVWSRC_BASE,target,0);
|
out_mat->AddProperty(&uvIndex,1,_AI_MATKEY_UVWSRC_BASE,target,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void SetTextureProperties(aiMaterial* out_mat, const TextureMap& textures)
|
void SetTextureProperties(aiMaterial* out_mat, const TextureMap& textures)
|
||||||
{
|
{
|
||||||
|
@ -1555,6 +1652,20 @@ private:
|
||||||
TrySetTextureProperties(out_mat, textures, "ShininessExponent", aiTextureType_SHININESS);
|
TrySetTextureProperties(out_mat, textures, "ShininessExponent", aiTextureType_SHININESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void SetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures)
|
||||||
|
{
|
||||||
|
TrySetTextureProperties(out_mat, layeredTextures, "DiffuseColor", aiTextureType_DIFFUSE);
|
||||||
|
TrySetTextureProperties(out_mat, layeredTextures, "AmbientColor", aiTextureType_AMBIENT);
|
||||||
|
TrySetTextureProperties(out_mat, layeredTextures, "EmissiveColor", aiTextureType_EMISSIVE);
|
||||||
|
TrySetTextureProperties(out_mat, layeredTextures, "SpecularColor", aiTextureType_SPECULAR);
|
||||||
|
TrySetTextureProperties(out_mat, layeredTextures, "TransparentColor", aiTextureType_OPACITY);
|
||||||
|
TrySetTextureProperties(out_mat, layeredTextures, "ReflectionColor", aiTextureType_REFLECTION);
|
||||||
|
TrySetTextureProperties(out_mat, layeredTextures, "DisplacementColor", aiTextureType_DISPLACEMENT);
|
||||||
|
TrySetTextureProperties(out_mat, layeredTextures, "NormalMap", aiTextureType_NORMALS);
|
||||||
|
TrySetTextureProperties(out_mat, layeredTextures, "Bump", aiTextureType_HEIGHT);
|
||||||
|
TrySetTextureProperties(out_mat, layeredTextures, "ShininessExponent", aiTextureType_SHININESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -14,7 +14,7 @@ following conditions are met:
|
||||||
following disclaimer.
|
following disclaimer.
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above
|
* Redistributions in binary form must reproduce the above
|
||||||
copyright notice, this list of conditions and the
|
copyright notice, this list of conditions and the*
|
||||||
following disclaimer in the documentation and/or other
|
following disclaimer in the documentation and/or other
|
||||||
materials provided with the distribution.
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
@ -176,6 +176,9 @@ const Object* LazyObject::Get(bool dieOnError)
|
||||||
else if (!strncmp(obtype,"Texture",length)) {
|
else if (!strncmp(obtype,"Texture",length)) {
|
||||||
object.reset(new Texture(id,element,doc,name));
|
object.reset(new Texture(id,element,doc,name));
|
||||||
}
|
}
|
||||||
|
else if (!strncmp(obtype,"LayeredTexture",length)) {
|
||||||
|
object.reset(new LayeredTexture(id,element,doc,name));
|
||||||
|
}
|
||||||
else if (!strncmp(obtype,"AnimationStack",length)) {
|
else if (!strncmp(obtype,"AnimationStack",length)) {
|
||||||
object.reset(new AnimationStack(id,element,name,doc));
|
object.reset(new AnimationStack(id,element,name,doc));
|
||||||
}
|
}
|
||||||
|
|
|
@ -516,8 +516,6 @@ private:
|
||||||
boost::shared_ptr<const PropertyTable> props;
|
boost::shared_ptr<const PropertyTable> props;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** DOM class for generic FBX textures */
|
/** DOM class for generic FBX textures */
|
||||||
class Texture : public Object
|
class Texture : public Object
|
||||||
{
|
{
|
||||||
|
@ -576,8 +574,73 @@ private:
|
||||||
unsigned int crop[4];
|
unsigned int crop[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** DOM class for layered FBX textures */
|
||||||
|
class LayeredTexture : public Object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
LayeredTexture(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
||||||
|
~LayeredTexture();
|
||||||
|
|
||||||
|
//Can only be called after construction of the layered texture object due to construction flag.
|
||||||
|
void fillTexture(const Document& doc);
|
||||||
|
|
||||||
|
enum BlendMode
|
||||||
|
{
|
||||||
|
BlendMode_Translucent,
|
||||||
|
BlendMode_Additive,
|
||||||
|
BlendMode_Modulate,
|
||||||
|
BlendMode_Modulate2,
|
||||||
|
BlendMode_Over,
|
||||||
|
BlendMode_Normal,
|
||||||
|
BlendMode_Dissolve,
|
||||||
|
BlendMode_Darken,
|
||||||
|
BlendMode_ColorBurn,
|
||||||
|
BlendMode_LinearBurn,
|
||||||
|
BlendMode_DarkerColor,
|
||||||
|
BlendMode_Lighten,
|
||||||
|
BlendMode_Screen,
|
||||||
|
BlendMode_ColorDodge,
|
||||||
|
BlendMode_LinearDodge,
|
||||||
|
BlendMode_LighterColor,
|
||||||
|
BlendMode_SoftLight,
|
||||||
|
BlendMode_HardLight,
|
||||||
|
BlendMode_VividLight,
|
||||||
|
BlendMode_LinearLight,
|
||||||
|
BlendMode_PinLight,
|
||||||
|
BlendMode_HardMix,
|
||||||
|
BlendMode_Difference,
|
||||||
|
BlendMode_Exclusion,
|
||||||
|
BlendMode_Subtract,
|
||||||
|
BlendMode_Divide,
|
||||||
|
BlendMode_Hue,
|
||||||
|
BlendMode_Saturation,
|
||||||
|
BlendMode_Color,
|
||||||
|
BlendMode_Luminosity,
|
||||||
|
BlendMode_Overlay,
|
||||||
|
BlendMode_BlendModeCount
|
||||||
|
};
|
||||||
|
|
||||||
|
const Texture* getTexture() const
|
||||||
|
{
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
BlendMode GetBlendMode()
|
||||||
|
{
|
||||||
|
return blendMode;
|
||||||
|
}
|
||||||
|
float Alpha()
|
||||||
|
{
|
||||||
|
return alpha;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
const Texture* texture;
|
||||||
|
BlendMode blendMode;
|
||||||
|
float alpha;
|
||||||
|
};
|
||||||
|
|
||||||
typedef std::fbx_unordered_map<std::string, const Texture*> TextureMap;
|
typedef std::fbx_unordered_map<std::string, const Texture*> TextureMap;
|
||||||
|
typedef std::fbx_unordered_map<std::string, const LayeredTexture*> LayeredTextureMap;
|
||||||
|
|
||||||
|
|
||||||
/** DOM class for generic FBX materials */
|
/** DOM class for generic FBX materials */
|
||||||
|
@ -607,6 +670,10 @@ public:
|
||||||
return textures;
|
return textures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const LayeredTextureMap& LayeredTextures() const {
|
||||||
|
return layeredTextures;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::string shading;
|
std::string shading;
|
||||||
|
@ -614,6 +681,7 @@ private:
|
||||||
boost::shared_ptr<const PropertyTable> props;
|
boost::shared_ptr<const PropertyTable> props;
|
||||||
|
|
||||||
TextureMap textures;
|
TextureMap textures;
|
||||||
|
LayeredTextureMap layeredTextures;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -110,16 +110,29 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
|
||||||
|
|
||||||
const Texture* const tex = dynamic_cast<const Texture*>(ob);
|
const Texture* const tex = dynamic_cast<const Texture*>(ob);
|
||||||
if(!tex) {
|
if(!tex) {
|
||||||
DOMWarning("source object for texture link is not a texture, ignoring",&element);
|
const LayeredTexture* const layeredTexture = dynamic_cast<const LayeredTexture*>(ob);
|
||||||
continue;
|
if(!layeredTexture) {
|
||||||
|
DOMWarning("source object for texture link is not a texture or layered texture, ignoring",&element);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const std::string& prop = con->PropertyName();
|
||||||
|
if (layeredTextures.find(prop) != layeredTextures.end()) {
|
||||||
|
DOMWarning("duplicate layered texture link: " + prop,&element);
|
||||||
|
}
|
||||||
|
|
||||||
|
layeredTextures[prop] = layeredTexture;
|
||||||
|
((LayeredTexture*)layeredTexture)->fillTexture(doc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const std::string& prop = con->PropertyName();
|
||||||
|
if (textures.find(prop) != textures.end()) {
|
||||||
|
DOMWarning("duplicate texture link: " + prop,&element);
|
||||||
|
}
|
||||||
|
|
||||||
|
textures[prop] = tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& prop = con->PropertyName();
|
|
||||||
if (textures.find(prop) != textures.end()) {
|
|
||||||
DOMWarning("duplicate texture link: " + prop,&element);
|
|
||||||
}
|
|
||||||
|
|
||||||
textures[prop] = tex;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,6 +207,52 @@ Texture::~Texture()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& doc, const std::string& name)
|
||||||
|
: Object(id,element,name)
|
||||||
|
,texture(0)
|
||||||
|
,blendMode(BlendMode_Modulate)
|
||||||
|
,alpha(1)
|
||||||
|
{
|
||||||
|
const Scope& sc = GetRequiredScope(element);
|
||||||
|
|
||||||
|
const Element* const BlendModes = sc["BlendModes"];
|
||||||
|
const Element* const Alphas = sc["Alphas"];
|
||||||
|
|
||||||
|
|
||||||
|
if(BlendModes!=0)
|
||||||
|
{
|
||||||
|
blendMode = (BlendMode)ParseTokenAsInt(GetRequiredToken(*BlendModes,0));
|
||||||
|
}
|
||||||
|
if(Alphas!=0)
|
||||||
|
{
|
||||||
|
alpha = ParseTokenAsFloat(GetRequiredToken(*Alphas,0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LayeredTexture::~LayeredTexture()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void LayeredTexture::fillTexture(const Document& doc)
|
||||||
|
{
|
||||||
|
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
|
||||||
|
for(size_t i = 0; i < conns.size();++i)
|
||||||
|
{
|
||||||
|
const Connection* con = conns.at(i);
|
||||||
|
|
||||||
|
const Object* const ob = con->SourceObject();
|
||||||
|
if(!ob) {
|
||||||
|
DOMWarning("failed to read source object for texture link, ignoring",&element);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Texture* const tex = dynamic_cast<const Texture*>(ob);
|
||||||
|
|
||||||
|
texture = tex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} //!FBX
|
} //!FBX
|
||||||
} //!Assimp
|
} //!Assimp
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue