/* Copyright (C) 2005-2006 Feeling Software Inc. MIT License: http://www.opensource.org/licenses/mit-license.php */ /* Based on the FS Import classes: Copyright (C) 2005-2006 Feeling Software Inc Copyright (C) 2005-2006 Autodesk Media Entertainment MIT License: http://www.opensource.org/licenses/mit-license.php */ #include "StdAfx.h" #include "FCDocument/FCDocument.h" #include "FCDocument/FCDAnimated.h" #include "FCDocument/FCDEffect.h" #include "FCDocument/FCDEffectStandard.h" #include "FCDocument/FCDMaterial.h" #include "FCDocument/FCDTexture.h" #include "FUtils/FUDaeEnum.h" #include "FUtils/FUDaeParser.h" #include "FUtils/FUDaeWriter.h" #include "FUtils/FUStringConversion.h" using namespace FUDaeParser; using namespace FUDaeWriter; FCDEffectStandard::FCDEffectStandard(FCDocument* document, FCDEffect* _parent) : FCDEffectProfile(document, _parent) { emissionColor = translucencyColor = diffuseColor = ambientColor = specularColor = FMVector3::Origin; reflectivityFactor = translucencyFactor = specularFactor = emissionFactor = 1.0f; reflectivityColor = translucencyColor = FMVector3(1.0f, 1.0f, 1.0f); shininess = 20.0f; type = CONSTANT; isWireframe = isFaceMap = isDoubleSided = isFaceted = isEmissionFactor = false; textureBuckets = new FCDTextureList[FUDaeTextureChannel::COUNT]; } FCDEffectStandard::~FCDEffectStandard() { for (uint32 i = 0; i < FUDaeTextureChannel::COUNT; ++i) { FCDTextureList& t = textureBuckets[i]; CLEAR_POINTER_VECTOR(t); } SAFE_DELETE_ARRAY(textureBuckets); } // Retrieve one of the buckets const FCDTextureList& FCDEffectStandard::GetTextureBucket(uint32 bucket) const { if (bucket < FUDaeTextureChannel::COUNT) return textureBuckets[bucket]; else return textureBuckets[FUDaeTextureChannel::FILTER]; // Because I think this one will almost always be empty. ;) } // Adds a texture to a specific channel. FCDTexture* FCDEffectStandard::AddTexture(uint32 bucket) { FUAssert(bucket < FUDaeTextureChannel::COUNT, return NULL); FCDTexture* texture = new FCDTexture(GetDocument()); textureBuckets[bucket].push_back(texture); return texture; } // Releases a texture contained within this effect profile. void FCDEffectStandard::ReleaseTexture(FCDTexture* texture) { for (uint32 i = 0; i < FUDaeTextureChannel::COUNT; ++i) { FCDTextureList::iterator it = std::find(textureBuckets[i].begin(), textureBuckets[i].end(), texture); if (it != textureBuckets[i].end()) { delete *it; textureBuckets[i].erase(it); break; } } } // Calculate the opacity for this material float FCDEffectStandard::GetOpacity() const { return 1.0f - (translucencyColor.x + translucencyColor.y + translucencyColor.z) / 3.0f * translucencyFactor; } // Calculate the overall reflectivity for this material float FCDEffectStandard::GetReflectivity() const { return (reflectivityColor.x + reflectivityColor.y + reflectivityColor.z) / 3.0f * reflectivityFactor; } // Look for the effect parameter with the correct semantic, in order to bind/set its value FCDEffectParameter* FCDEffectStandard::FindParameterBySemantic(const string& semantic) { // Check only the texture buckets, for now. for (uint32 i = 0; i < FUDaeTextureChannel::COUNT; ++i) { for (FCDTextureList::iterator itT = textureBuckets[i].begin(); itT != textureBuckets[i].end(); ++itT) { FCDEffectParameter* p = (*itT)->FindParameterBySemantic(semantic); if (p != NULL) return p; } } return NULL; } void FCDEffectStandard::FindParametersBySemantic(const string& semantic, FCDEffectParameterList& parameters) { // Check only the texture buckets, for now. for (uint32 i = 0; i < FUDaeTextureChannel::COUNT; ++i) { for (FCDTextureList::iterator itT = textureBuckets[i].begin(); itT != textureBuckets[i].end(); ++itT) { (*itT)->FindParametersBySemantic(semantic, parameters); } } } void FCDEffectStandard::FindParametersByReference(const string& reference, FCDEffectParameterList& parameters) { // Check only the texture buckets, for now. for (uint32 i = 0; i < FUDaeTextureChannel::COUNT; ++i) { for (FCDTextureList::iterator itT = textureBuckets[i].begin(); itT != textureBuckets[i].end(); ++itT) { (*itT)->FindParametersByReference(reference, parameters); } } } // Clone the standard effect FCDEffectProfile* FCDEffectStandard::Clone(FCDEffect* newParent) { FCDEffectStandard* clone = new FCDEffectStandard(GetDocument(), newParent); clone->type = type; for (uint32 i = 0; i < FUDaeTextureChannel::COUNT; ++i) { for (FCDTextureList::iterator itT = textureBuckets[i].begin(); itT != textureBuckets[i].end(); ++itT) { clone->textureBuckets[i].push_back((*itT)->Clone()); } } # define CLONE_ANIMATED_F(flt) clone->flt = flt; FCDAnimatedFloat::Clone(GetDocument(), &flt, &clone->flt); # define CLONE_ANIMATED_C(flt) clone->flt = flt; FCDAnimatedColor::Clone(GetDocument(), &flt, &clone->flt); CLONE_ANIMATED_C(emissionColor); CLONE_ANIMATED_F(emissionFactor); clone->isEmissionFactor = isEmissionFactor; CLONE_ANIMATED_C(translucencyColor); CLONE_ANIMATED_F(translucencyFactor); CLONE_ANIMATED_C(diffuseColor); CLONE_ANIMATED_C(ambientColor); CLONE_ANIMATED_C(specularColor); CLONE_ANIMATED_F(specularFactor); CLONE_ANIMATED_F(shininess); CLONE_ANIMATED_C(reflectivityColor); CLONE_ANIMATED_F(reflectivityFactor); clone->isFaceted = isFaceted; clone->isDoubleSided = isDoubleSided; clone->isWireframe = isWireframe; clone->isFaceMap = isFaceMap; # undef CLONE_ANIMATED_F # undef CLONE_ANIMATED_C return clone; } // Read in a node from the COLLADA document FUStatus FCDEffectStandard::LoadFromXML(xmlNode* baseNode) { FUStatus status; // support is for COLLADA 1.3 backward compatibility bool isCollada1_3 = IsEquivalent(baseNode->name, DAE_SHADER_ELEMENT); if (!isCollada1_3 && !IsEquivalent(baseNode->name, DAE_FX_PROFILE_COMMON_ELEMENT)) { return status.Warning(FS("Unknown element as standard material base."), baseNode->line); } // For COLLADA 1.3 backward compatibility: find the correct base node for the profile. // While we're digging, find the node with the Max-specific parameters xmlNode* maxParameterNode = NULL; xmlNode* mayaParameterNode = NULL; if (isCollada1_3) { // COLLADA 1.3 backward compatibility: the base node is // and the Max-specific parameters are in . xmlNode* commonTechniqueNode = FindTechnique(baseNode, DAE_COMMON_PROFILE); xmlNode* maxTechniqueNode = FindTechnique(baseNode, DAEMAX_MAX_PROFILE); baseNode = FindChildByType(commonTechniqueNode, DAE_PASS_ELEMENT); xmlNode* maxPassNode = FindChildByType(maxTechniqueNode, DAE_PASS_ELEMENT); maxParameterNode = FindChildByType(maxPassNode, DAE_PROGRAM_ELEMENT); } else { // Bump the base node up the first element xmlNode* techniqueNode = FindChildByType(baseNode, DAE_TECHNIQUE_ELEMENT); if (techniqueNode == NULL) { return status.Warning(FS("Expecting within the element for effect: ") + TO_FSTRING(GetDaeId()), baseNode->line); } baseNode = techniqueNode; // Look for an node for Max-specific parameter xmlNode* extraNode = FindChildByType(baseNode, DAE_EXTRA_ELEMENT); maxParameterNode = FindTechnique(extraNode, DAEMAX_MAX_PROFILE); mayaParameterNode = FindTechnique(extraNode, DAEMAYA_MAYA_PROFILE); } if (isCollada1_3) { // COLLADA 1.3 backward compatibility: look for elements pointing to textures xmlNodeList textureInputNodes; FindChildrenByType(baseNode, DAE_INPUT_ELEMENT, textureInputNodes); for (xmlNodeList::iterator it = textureInputNodes.begin(); it != textureInputNodes.end(); ++it) { string semantic = ReadNodeSemantic(*it); if (semantic != DAE_TEXTURE_INPUT) { status.Warning(FS("Unknown input semantic in material: ") + TO_FSTRING(GetDaeId()), (*it)->line); continue; } // Retrieve the texture and bucket it string textureId = ReadNodeSource(*it); FCDTexture* texture = GetDocument()->FindTexture(textureId); if (texture != NULL) { uint32 channel = (uint32) texture->GetTextureChannel(); textureBuckets[(uint32) channel].push_back(texture->Clone()); } else { status.Warning(FS("Unknown input texture '") + TO_FSTRING(textureId) + FS("' in material: ") + TO_FSTRING(GetDaeId()), (*it)->line); } } } // Parse the material's program node and figure out the correct shader type xmlNode* commonParameterNode = NULL; if (isCollada1_3) { // COLLADA 1.3 backward compatibility: read in the type attribute of the node commonParameterNode = FindChildByType(baseNode, DAE_PROGRAM_ELEMENT); FUUri programUrl = ReadNodeUrl(commonParameterNode); string materialType = FUStringConversion::ToString(programUrl.prefix); if (materialType == DAE_CONSTANT_MATERIAL_PROGRAM) type = CONSTANT; else if (materialType == DAE_LAMBERT_MATERIAL_PROGRAM) type = LAMBERT; else if (materialType == DAE_PHONG_MATERIAL_PROGRAM) type = PHONG; else { return status.Warning(FS("Unsupported shader program type: '") + programUrl.prefix + FS("' in material: ") + TO_FSTRING(GetDaeId()), commonParameterNode->line); } } else { // Either , or are expected for (commonParameterNode = baseNode->children; commonParameterNode != NULL; commonParameterNode = commonParameterNode->next) { if (commonParameterNode->type != XML_ELEMENT_NODE) continue; if (IsEquivalent(commonParameterNode->name, DAE_FXSTD_CONSTANT_ELEMENT)) { type = CONSTANT; break; } else if (IsEquivalent(commonParameterNode->name, DAE_FXSTD_LAMBERT_ELEMENT)) { type = LAMBERT; break; } else if (IsEquivalent(commonParameterNode->name, DAE_FXSTD_PHONG_ELEMENT)) { type = PHONG; break; } else if (IsEquivalent(commonParameterNode->name, DAE_FXSTD_BLINN_ELEMENT)) { type = BLINN; break; } } } if (commonParameterNode == NULL) { return status.Fail(FS("Unable to find the program node for standard effect: ") + TO_FSTRING(GetDaeId()), baseNode->line); } bool hasTranslucency = false, hasReflectivity = false; FCDTextureList emptyBucket; // Read in the parameters for the common program types and apply them to the shader StringList parameterNames; xmlNodeList parameterNodes; FindParameters(commonParameterNode, parameterNames, parameterNodes); FindParameters(maxParameterNode, parameterNames, parameterNodes); FindParameters(mayaParameterNode, parameterNames, parameterNodes); size_t parameterCount = parameterNodes.size(); for (size_t i = 0; i < parameterCount; ++i) { xmlNode* parameterNode = parameterNodes[i]; const string& parameterName = parameterNames[i]; const char* parameterContent = ReadNodeContentDirect(parameterNode); if (parameterName == DAE_EMISSION_MATERIAL_PARAMETER || parameterName == DAE_EMISSION_MATERIAL_PARAMETER1_3) { status.AppendStatus(ParseColorTextureParameter(parameterNode, emissionColor, textureBuckets[FUDaeTextureChannel::EMISSION])); } else if (parameterName == DAE_DIFFUSE_MATERIAL_PARAMETER || parameterName == DAE_DIFFUSE_MATERIAL_PARAMETER1_3) { status.AppendStatus(ParseColorTextureParameter(parameterNode, diffuseColor, textureBuckets[FUDaeTextureChannel::DIFFUSE])); } else if (parameterName == DAE_AMBIENT_MATERIAL_PARAMETER || parameterName == DAE_AMBIENT_MATERIAL_PARAMETER1_3) { status.AppendStatus(ParseColorTextureParameter(parameterNode, ambientColor, textureBuckets[FUDaeTextureChannel::AMBIENT])); } else if (parameterName == DAE_TRANSPARENT_MATERIAL_PARAMETER || parameterName == DAE_TRANSPARENT_MATERIAL_PARAMETER1_3) { status.AppendStatus(ParseColorTextureParameter(parameterNode, translucencyColor, textureBuckets[FUDaeTextureChannel::TRANSPARENT])); hasTranslucency = true; } else if (parameterName == DAE_TRANSPARENCY_MATERIAL_PARAMETER || parameterName == DAE_TRANSPARENCY_MATERIAL_PARAMETER1_3) { status.AppendStatus(ParseFloatTextureParameter(parameterNode, translucencyFactor, textureBuckets[FUDaeTextureChannel::OPACITY])); hasTranslucency = true; } else if (parameterName == DAE_SPECULAR_MATERIAL_PARAMETER || parameterName == DAE_SPECULAR_MATERIAL_PARAMETER1_3) { status.AppendStatus(ParseColorTextureParameter(parameterNode, specularColor, textureBuckets[FUDaeTextureChannel::SPECULAR])); } else if (parameterName == DAE_SPECULAR_MATERIAL_PARAMETER || parameterName == DAE_SPECULAR_MATERIAL_PARAMETER1_3) { status.AppendStatus(ParseColorTextureParameter(parameterNode, specularColor, textureBuckets[FUDaeTextureChannel::SPECULAR])); } else if (parameterName == DAE_SHININESS_MATERIAL_PARAMETER || parameterName == DAE_SHININESS_MATERIAL_PARAMETER1_3) { status.AppendStatus(ParseFloatTextureParameter(parameterNode, shininess, textureBuckets[FUDaeTextureChannel::SHININESS])); } else if (parameterName == DAE_REFLECTIVE_MATERIAL_PARAMETER || parameterName == DAE_REFLECTIVE_MATERIAL_PARAMETER1_3) { status.AppendStatus(ParseColorTextureParameter(parameterNode, reflectivityColor, textureBuckets[FUDaeTextureChannel::REFLECTION])); hasReflectivity = true; } else if (parameterName == DAE_REFLECTIVITY_MATERIAL_PARAMETER || parameterName == DAE_REFLECTIVITY_MATERIAL_PARAMETER1_3) { status.AppendStatus(ParseFloatTextureParameter(parameterNode, reflectivityFactor, emptyBucket)); hasReflectivity = true; } else if (parameterName == DAE_BUMP_MATERIAL_PARAMETER) { status.AppendStatus(ParseSimpleTextureParameter(parameterNode, textureBuckets[FUDaeTextureChannel::BUMP])); } else if (parameterName == DAEMAX_SPECLEVEL_MATERIAL_PARAMETER || parameterName == DAEMAX_SPECLEVEL_MATERIAL_PARAMETER1_3) { status.AppendStatus(ParseFloatTextureParameter(parameterNode, specularFactor, textureBuckets[FUDaeTextureChannel::SPECULAR_LEVEL])); } else if (parameterName == DAEMAX_EMISSIONLEVEL_MATERIAL_PARAMETER || parameterName == DAEMAX_EMISSIONLEVEL_MATERIAL_PARAMETER1_3) { status.AppendStatus(ParseFloatTextureParameter(parameterNode, emissionFactor, textureBuckets[FUDaeTextureChannel::EMISSION])); isEmissionFactor = true; } else if (parameterName == DAEMAX_FACETED_MATERIAL_PARAMETER || parameterName == DAEMAX_FACETED_MATERIAL_PARAMETER1_3) { isFaceted = FUStringConversion::ToBoolean(parameterContent); } else if (parameterName == DAESHD_DOUBLESIDED_PARAMETER) { isDoubleSided = FUStringConversion::ToBoolean(parameterContent); } else if (parameterName == DAEMAX_WIREFRAME_MATERIAL_PARAMETER) { isWireframe = FUStringConversion::ToBoolean(parameterContent); } else if (parameterName == DAEMAX_FACEMAP_MATERIAL_PARAMETER) { isFaceMap = FUStringConversion::ToBoolean(parameterContent); } else if (parameterName == DAEMAX_INDEXOFREFRACTION_MATERIAL_PARAMETER) { status.AppendStatus(ParseSimpleTextureParameter(parameterNode, textureBuckets[FUDaeTextureChannel::REFRACTION])); } else if (parameterName == DAEMAX_DISPLACEMENT_MATERIAL_PARAMETER) { status.AppendStatus(ParseSimpleTextureParameter(parameterNode, textureBuckets[FUDaeTextureChannel::DISPLACEMENT])); } else if (parameterName == DAEMAX_FILTERCOLOR_MATERIAL_PARAMETER) { status.AppendStatus(ParseSimpleTextureParameter(parameterNode, textureBuckets[FUDaeTextureChannel::FILTER])); } else { status.Warning(FS("Unknown parameter name for material ") + TO_FSTRING(GetDaeId()), parameterNode->line); } } bool isEmptyBucketEmpty = emptyBucket.empty(); CLEAR_POINTER_VECTOR(emptyBucket); if (!isEmptyBucketEmpty) { return status.Fail(FS("Unexpected texture sampler on some parameters for material ") + TO_FSTRING(GetDaeId()), baseNode->line); } // Although the default COLLADA materials gives, wrongly, a transparent material, // when neither the TRANSPARENT or TRANSPARENCY parameters are set, assume an opaque material. // Similarly for reflectivity if (!hasTranslucency) { translucencyColor = FMVector3::Origin; translucencyFactor = 0.0f; } if (!hasReflectivity) { reflectivityColor = FMVector3::Origin; reflectivityFactor = 0.0f; } // Convert some of the values that may appear in different formats if (!isEmissionFactor) { emissionFactor = (emissionColor.x + emissionColor.y + emissionColor.z) / 3.0f; } return status; } xmlNode* FCDEffectStandard::WriteToXML(xmlNode* parentNode) const { xmlNode* profileCommonNode = AddChild(parentNode, DAE_FX_PROFILE_COMMON_ELEMENT); xmlNode* techniqueCommonNode = AddChild(profileCommonNode, DAE_TECHNIQUE_ELEMENT); AddNodeSid(techniqueCommonNode, "common"); const char* materialName; switch (type) { case CONSTANT: materialName = DAE_FXSTD_CONSTANT_ELEMENT; break; case LAMBERT: materialName = DAE_FXSTD_LAMBERT_ELEMENT; break; case PHONG: materialName = DAE_FXSTD_PHONG_ELEMENT; break; case BLINN: materialName = DAE_FXSTD_BLINN_ELEMENT; break; case UNKNOWN: default: materialName = DAEERR_UNKNOWN_ELEMENT; break; } xmlNode* materialNode = AddChild(techniqueCommonNode, materialName); xmlNode* techniqueNode = AddExtraTechniqueChild(techniqueCommonNode, DAEMAYA_MAYA_PROFILE); // Export the color/float parameters FCDTextureList emptyBucket; float emptyValue = 0.0f; FMVector3 emptyColor; WriteColorTextureParameterToXML(materialNode, DAE_EMISSION_MATERIAL_PARAMETER, emissionColor, textureBuckets[FUDaeTextureChannel::EMISSION]); if (type != CONSTANT) { WriteColorTextureParameterToXML(materialNode, DAE_AMBIENT_MATERIAL_PARAMETER, emissionColor, textureBuckets[FUDaeTextureChannel::AMBIENT]); WriteColorTextureParameterToXML(materialNode, DAE_DIFFUSE_MATERIAL_PARAMETER, diffuseColor, textureBuckets[FUDaeTextureChannel::DIFFUSE]); if (type != LAMBERT) { WriteColorTextureParameterToXML(materialNode, DAE_SPECULAR_MATERIAL_PARAMETER, specularColor, textureBuckets[FUDaeTextureChannel::SPECULAR]); WriteFloatTextureParameterToXML(materialNode, DAE_SHININESS_MATERIAL_PARAMETER, shininess, emptyBucket); if (!textureBuckets[FUDaeTextureChannel::SHININESS].empty()) { WriteFloatTextureParameterToXML(techniqueNode, DAE_SHININESS_MATERIAL_PARAMETER, shininess, textureBuckets[FUDaeTextureChannel::SHININESS]); WriteFloatTextureParameterToXML(techniqueNode, DAEMAX_SPECLEVEL_MATERIAL_PARAMETER, specularFactor, textureBuckets[FUDaeTextureChannel::SPECULAR_LEVEL]); } } } WriteColorTextureParameterToXML(materialNode, DAE_REFLECTIVE_MATERIAL_PARAMETER, reflectivityColor, textureBuckets[FUDaeTextureChannel::REFLECTION]); WriteFloatTextureParameterToXML(materialNode, DAE_REFLECTIVITY_MATERIAL_PARAMETER, reflectivityFactor, emptyBucket); // Translucency includes both transparent and opacity textures FCDTextureList translucencyBucket = textureBuckets[FUDaeTextureChannel::TRANSPARENT]; translucencyBucket.insert(translucencyBucket.end(), textureBuckets[FUDaeTextureChannel::OPACITY].begin(), textureBuckets[FUDaeTextureChannel::OPACITY].end()); WriteColorTextureParameterToXML(materialNode, DAE_TRANSPARENT_MATERIAL_PARAMETER, translucencyColor, translucencyBucket); WriteFloatTextureParameterToXML(materialNode, DAE_TRANSPARENCY_MATERIAL_PARAMETER, translucencyFactor, emptyBucket); WriteFloatTextureParameterToXML(materialNode, DAEMAX_INDEXOFREFRACTION_MATERIAL_PARAMETER, emptyValue, textureBuckets[FUDaeTextureChannel::REFRACTION]); // Non-COLLADA parameters if (!textureBuckets[FUDaeTextureChannel::BUMP].empty()) { WriteFloatTextureParameterToXML(techniqueNode, DAE_BUMP_MATERIAL_PARAMETER, emptyValue, textureBuckets[FUDaeTextureChannel::BUMP]); } if (!textureBuckets[FUDaeTextureChannel::DISPLACEMENT].empty()) { WriteFloatTextureParameterToXML(techniqueNode, DAEMAX_DISPLACEMENT_MATERIAL_PARAMETER, emptyValue, textureBuckets[FUDaeTextureChannel::DISPLACEMENT]); } if (!textureBuckets[FUDaeTextureChannel::FILTER].empty()) { WriteColorTextureParameterToXML(techniqueNode, DAEMAX_FILTERCOLOR_MATERIAL_PARAMETER, emptyColor, textureBuckets[FUDaeTextureChannel::FILTER]); } return profileCommonNode; } xmlNode* FCDEffectStandard::WriteColorTextureParameterToXML(xmlNode* parentNode, const char* parameterNodeName, const FMVector3& value, const FCDTextureList& textureBucket) const { xmlNode* parameterNode = AddChild(parentNode, parameterNodeName); if (WriteTextureParameterToXML(parameterNode, textureBucket) == NULL) { // The color value expected by the profile_COMMON element has four floating-point values. string colorValue = FUStringConversion::ToString(value) + " 1.0"; xmlNode* valueNode = AddChild(parameterNode, DAE_FXSTD_COLOR_ELEMENT, colorValue); GetDocument()->WriteAnimatedValueToXML(&value.x, valueNode, parameterNodeName); } return parameterNode; } xmlNode* FCDEffectStandard::WriteFloatTextureParameterToXML(xmlNode* parentNode, const char* parameterNodeName, const float& value, const FCDTextureList& textureBucket) const { xmlNode* parameterNode = AddChild(parentNode, parameterNodeName); if (WriteTextureParameterToXML(parameterNode, textureBucket) == NULL) { xmlNode* valueNode = AddChild(parameterNode, DAE_FXSTD_FLOAT_ELEMENT, value); GetDocument()->WriteAnimatedValueToXML(&value, valueNode, parameterNodeName); } return parameterNode; } xmlNode* FCDEffectStandard::WriteTextureParameterToXML(xmlNode* parentNode, const FCDTextureList& textureBucket) const { xmlNode* textureNode = NULL; for (FCDTextureList::const_iterator itT = textureBucket.begin(); itT != textureBucket.end(); ++itT) { xmlNode* newTextureNode = (*itT)->WriteToXML(parentNode); if (newTextureNode != NULL && textureNode == NULL) textureNode = newTextureNode; } return textureNode; } // Parse in the different standard effect parameters, bucketing the textures FUStatus FCDEffectStandard::ParseColorTextureParameter(xmlNode* parameterNode, FMVector3& value, FCDTextureList& textureBucket) { FUStatus status; // Look for elements, they pre-empt everything else size_t originalSize = textureBucket.size(); ParseSimpleTextureParameter(parameterNode, textureBucket); if (originalSize < textureBucket.size()) { value = FMVector3(1.0f, 1.0f, 1.0f); return status; } // Next, look for a element // COLLADA 1.3 backward compatibility: also look for the color value directly inside the parameter node. xmlNode* colorNode = FindChildByType(parameterNode, DAE_FXSTD_COLOR_ELEMENT); const char* content = ReadNodeContentDirect(colorNode); if (content == NULL || *content == 0) content = ReadNodeContentDirect(parameterNode); // Parse the color value and allow for an animation of it value = FUStringConversion::ToPoint(content); if (HasNodeProperty(colorNode, DAE_ID_ATTRIBUTE) || HasNodeProperty(colorNode, DAE_SID_ATTRIBUTE)) FCDAnimatedColor::Create(GetDocument(), colorNode, &value); else FCDAnimatedColor::Create(GetDocument(), parameterNode, &value); return status; } FUStatus FCDEffectStandard::ParseFloatTextureParameter(xmlNode* parameterNode, float& value, FCDTextureList& textureBucket) { FUStatus status; // Look for elements, they pre-empt everything else size_t originalSize = textureBucket.size(); ParseSimpleTextureParameter(parameterNode, textureBucket); if (originalSize < textureBucket.size()) { value = 1.0f; return status; } // Next, look for a element // COLLADA 1.3 backward compatibility: also look for the value directly inside the parameter node. xmlNode* floatNode = FindChildByType(parameterNode, DAE_FXSTD_FLOAT_ELEMENT); const char* content = ReadNodeContentDirect(floatNode); if (content == NULL || *content == 0) content = ReadNodeContentDirect(parameterNode); // Parse the value and register it for an animation. value = FUStringConversion::ToFloat(content); if (HasNodeProperty(floatNode, DAE_ID_ATTRIBUTE) || HasNodeProperty(floatNode, DAE_SID_ATTRIBUTE)) FCDAnimatedFloat::Create(GetDocument(), floatNode, &value); else FCDAnimatedFloat::Create(GetDocument(), parameterNode, &value); return status; } FUStatus FCDEffectStandard::ParseSimpleTextureParameter(xmlNode* parameterNode, FCDTextureList& textureBucket) { FUStatus status; // Parse in all the elements as standard effect samplers xmlNodeList samplerNodes; FindChildrenByType(parameterNode, DAE_FXSTD_SAMPLER_ELEMENT, samplerNodes); if (!samplerNodes.empty()) { for (xmlNodeList::iterator itS = samplerNodes.begin(); itS != samplerNodes.end(); ++itS) { // Parse in the texture element and bucket them FCDTexture* texture = new FCDTexture(GetDocument()); status.AppendStatus(texture->LoadFromTextureXML(*itS)); if (status) textureBucket.push_back(texture); else { SAFE_DELETE(texture); } } } return status; }