// ------------------------------------------------------------------------------------------------ AnimationStack::AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc) : Object(id, element, name) { const Scope& sc = GetRequiredScope(element); // note: we don't currently use any of these properties so we shouldn't bother if it is missing props = GetPropertyTable(doc,"AnimationStack.FbxAnimStack",element,sc, true); // resolve attached animation layers const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationLayer"); layers.reserve(conns.size()); for(const Connection* con : conns) { // link should not go to a property if (con->PropertyName().length()) { continue; } const Object* const ob = con->SourceObject(); if(!ob) { DOMWarning("failed to read source object for AnimationLayer->AnimationStack link, ignoring",&element); continue; } const AnimationLayer* const anim = dynamic_cast<const AnimationLayer*>(ob); if(!anim) { DOMWarning("source object for ->AnimationStack link is not an AnimationLayer",&element); continue; } layers.push_back(anim); } }
// ------------------------------------------------------------------------------------------------ void Model::ResolveLinks(const Element& element, const Document& doc) { const char* const arr[] = {"Geometry","Material","NodeAttribute"}; // resolve material const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),arr, 3); materials.reserve(conns.size()); geometry.reserve(conns.size()); attributes.reserve(conns.size()); for(const Connection* con : conns) { // material and geometry links should be Object-Object connections if (con->PropertyName().length()) { continue; } const Object* const ob = con->SourceObject(); if(!ob) { DOMWarning("failed to read source object for incoming Model link, ignoring",&element); continue; } const Material* const mat = dynamic_cast<const Material*>(ob); if(mat) { materials.push_back(mat); continue; } const Geometry* const geo = dynamic_cast<const Geometry*>(ob); if(geo) { geometry.push_back(geo); continue; } const NodeAttribute* const att = dynamic_cast<const NodeAttribute*>(ob); if(att) { attributes.push_back(att); continue; } DOMWarning("source object for model link is neither Material, NodeAttribute nor Geometry, ignoring",&element); continue; } }
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); textures.push_back(tex); } }
// ------------------------------------------------------------------------------------------------ Cluster::Cluster(uint64_t id, const Element& element, const Document& doc, const std::string& name) : Deformer(id,element,doc,name) , node() { const Scope& sc = GetRequiredScope(element); const Element* const Indexes = sc["Indexes"]; const Element* const Weights = sc["Weights"]; const Element& Transform = GetRequiredElement(sc,"Transform",&element); const Element& TransformLink = GetRequiredElement(sc,"TransformLink",&element); transform = ReadMatrix(Transform); transformLink = ReadMatrix(TransformLink); // it is actually possible that there be Deformer's with no weights if (!!Indexes != !!Weights) { DOMError("either Indexes or Weights are missing from Cluster",&element); } if(Indexes) { ParseVectorDataArray(indices,*Indexes); ParseVectorDataArray(weights,*Weights); } if(indices.size() != weights.size()) { DOMError("sizes of index and weight array don't match up",&element); } // read assigned node const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Model"); for(const Connection* con : conns) { const Model* const mod = ProcessSimpleConnection<Model>(*con, false, "Model -> Cluster", element); if(mod) { node = mod; break; } } if (!node) { DOMError("failed to read target Node for Cluster",&element); } }
// ------------------------------------------------------------------------------------------------ Skin::Skin(uint64_t id, const Element& element, const Document& doc, const std::string& name) : Deformer(id,element,doc,name) , accuracy( 0.0f ) { const Scope& sc = GetRequiredScope(element); const Element* const Link_DeformAcuracy = sc["Link_DeformAcuracy"]; if(Link_DeformAcuracy) { accuracy = ParseTokenAsFloat(GetRequiredToken(*Link_DeformAcuracy,0)); } // resolve assigned clusters const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Deformer"); clusters.reserve(conns.size()); for(const Connection* con : conns) { const Cluster* const cluster = ProcessSimpleConnection<Cluster>(*con, false, "Cluster -> Skin", element); if(cluster) { clusters.push_back(cluster); continue; } } }
// ------------------------------------------------------------------------------------------------ Material::Material(uint64_t id, const Element& element, const Document& doc, const std::string& name) : Object(id,element,name) { const Scope& sc = GetRequiredScope(element); const Element* const ShadingModel = sc["ShadingModel"]; const Element* const MultiLayer = sc["MultiLayer"]; if(MultiLayer) { multilayer = !!ParseTokenAsInt(GetRequiredToken(*MultiLayer,0)); } if(ShadingModel) { shading = ParseTokenAsString(GetRequiredToken(*ShadingModel,0)); } else { DOMWarning("shading mode not specified, assuming phong",&element); shading = "phong"; } std::string templateName; // lower-case shading because Blender (for example) writes "Phong" std::transform(shading.begin(), shading.end(), shading.begin(), ::tolower); if(shading == "phong") { templateName = "Material.FbxSurfacePhong"; } else if(shading == "lambert") { templateName = "Material.FbxSurfaceLambert"; } else { DOMWarning("shading mode not recognized: " + shading,&element); } props = GetPropertyTable(doc,templateName,element,sc); // resolve texture links const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID()); for(const Connection* con : conns) { // texture link to properties, not objects if (!con->PropertyName().length()) { continue; } 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); if(!tex) { 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; } } }
// ------------------------------------------------------------------------------------------------ Texture::Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name) : Object(id,element,name) , uvScaling(1.0f,1.0f) , media(0) { const Scope& sc = GetRequiredScope(element); const Element* const Type = sc["Type"]; const Element* const FileName = sc["FileName"]; const Element* const RelativeFilename = sc["RelativeFilename"]; const Element* const ModelUVTranslation = sc["ModelUVTranslation"]; const Element* const ModelUVScaling = sc["ModelUVScaling"]; const Element* const Texture_Alpha_Source = sc["Texture_Alpha_Source"]; const Element* const Cropping = sc["Cropping"]; if(Type) { type = ParseTokenAsString(GetRequiredToken(*Type,0)); } if(FileName) { fileName = ParseTokenAsString(GetRequiredToken(*FileName,0)); } if(RelativeFilename) { relativeFileName = ParseTokenAsString(GetRequiredToken(*RelativeFilename,0)); } if(ModelUVTranslation) { uvTrans = aiVector2D(ParseTokenAsFloat(GetRequiredToken(*ModelUVTranslation,0)), ParseTokenAsFloat(GetRequiredToken(*ModelUVTranslation,1)) ); } if(ModelUVScaling) { uvScaling = aiVector2D(ParseTokenAsFloat(GetRequiredToken(*ModelUVScaling,0)), ParseTokenAsFloat(GetRequiredToken(*ModelUVScaling,1)) ); } if(Cropping) { crop[0] = ParseTokenAsInt(GetRequiredToken(*Cropping,0)); crop[1] = ParseTokenAsInt(GetRequiredToken(*Cropping,1)); crop[2] = ParseTokenAsInt(GetRequiredToken(*Cropping,2)); crop[3] = ParseTokenAsInt(GetRequiredToken(*Cropping,3)); } else { // vc8 doesn't support the crop() syntax in initialization lists // (and vc9 WARNS about the new (i.e. compliant) behaviour). crop[0] = crop[1] = crop[2] = crop[3] = 0; } if(Texture_Alpha_Source) { alphaSource = ParseTokenAsString(GetRequiredToken(*Texture_Alpha_Source,0)); } props = GetPropertyTable(doc,"Texture.FbxFileTexture",element,sc); // resolve video links if(doc.Settings().readTextures) { const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID()); for(const Connection* con : conns) { const Object* const ob = con->SourceObject(); if(!ob) { DOMWarning("failed to read source object for texture link, ignoring",&element); continue; } const Video* const video = dynamic_cast<const Video*>(ob); if(video) { media = video; } } } }