Initial version for FBX layered textures.

Fixed assert during parsing UDP3DSMAX.
pull/249/head
attila-barsi 2014-03-24 11:46:36 +01:00
parent 7fc15c3713
commit ed9204ab1b
4 changed files with 251 additions and 12 deletions

View File

@ -23,7 +23,7 @@ following conditions are met:
derived from this software without specific prior
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
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
@ -766,6 +766,7 @@ private:
// find user defined properties (3ds Max)
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.
data->Set(index++, "IsNull", model.IsNull() ? true : false);
@ -1439,6 +1440,7 @@ private:
// texture assignments
SetTextureProperties(out_mat,material.Textures());
SetTextureProperties(out_mat,material.LayeredTextures());
return static_cast<unsigned int>(materials.size() - 1);
}
@ -1538,6 +1540,99 @@ private:
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;
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 SetTextureProperties(aiMaterial* out_mat, const TextureMap& textures)
@ -1554,6 +1649,20 @@ private:
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);
}
// ------------------------------------------------------------------------------------------------

View File

@ -14,7 +14,7 @@ following conditions are met:
following disclaimer.
* 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
materials provided with the distribution.
@ -176,6 +176,9 @@ const Object* LazyObject::Get(bool dieOnError)
else if (!strncmp(obtype,"Texture",length)) {
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)) {
object.reset(new AnimationStack(id,element,name,doc));
}

View File

@ -516,8 +516,6 @@ private:
boost::shared_ptr<const PropertyTable> props;
};
/** DOM class for generic FBX textures */
class Texture : public Object
{
@ -576,8 +574,73 @@ private:
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 LayeredTexture*> LayeredTextureMap;
/** DOM class for generic FBX materials */
@ -607,6 +670,10 @@ public:
return textures;
}
const LayeredTextureMap& LayeredTextures() const {
return layeredTextures;
}
private:
std::string shading;
@ -614,6 +681,7 @@ private:
boost::shared_ptr<const PropertyTable> props;
TextureMap textures;
LayeredTextureMap layeredTextures;
};

View File

@ -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);
if(!tex) {
DOMWarning("source object for texture link is not a texture, ignoring",&element);
continue;
const LayeredTexture* const layeredTexture = dynamic_cast<const LayeredTexture*>(ob);
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
} //!Assimp