/* Copyright (C) 2005-2007 Feeling Software Inc. Portions of the code are: Copyright (C) 2005-2007 Sony Computer Entertainment America MIT License: http://www.opensource.org/licenses/mit-license.php */ #include "StdAfx.h" #include "FArchiveXML.h" #include "FCDocument/FCDocument.h" #include "FCDocument/FCDAnimated.h" #include "FCDocument/FCDEffect.h" #include "FCDocument/FCDEffectCode.h" #include "FCDocument/FCDEffectParameterSampler.h" #include "FCDocument/FCDEffectParameterSurface.h" #include "FCDocument/FCDEffectParameter.h" #include "FCDocument/FCDEffectPass.h" #include "FCDocument/FCDEffectPassShader.h" #include "FCDocument/FCDEffectPassState.h" #include "FCDocument/FCDEffectProfile.h" #include "FCDocument/FCDEffectProfileFX.h" #include "FCDocument/FCDEffectStandard.h" #include "FCDocument/FCDEffectTechnique.h" #include "FCDocument/FCDEntityReference.h" #include "FCDocument/FCDExtra.h" #include "FCDocument/FCDImage.h" #include "FCDocument/FCDLibrary.h" #include "FCDocument/FCDMaterial.h" #include "FCDocument/FCDTexture.h" bool FArchiveXML::LoadMaterial(FCDObject* object, xmlNode* materialNode) { if (!FArchiveXML::LoadEntity(object, materialNode)) return false; bool status = true; FCDMaterial* material = (FCDMaterial*)object; while (material->GetEffectParameterCount() > 0) { material->GetEffectParameter(material->GetEffectParameterCount() - 1)->Release(); } if (!IsEquivalent(materialNode->name, DAE_MATERIAL_ELEMENT)) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOWN_MAT_LIB_ELEMENT, materialNode->line); return status; } // Read in the effect pointer node xmlNode* effectNode = FindChildByType(materialNode, DAE_INSTANCE_EFFECT_ELEMENT); if (effectNode == NULL) { FUError::Error(FUError::WARNING_LEVEL, FUError::ERROR_MISSING_ELEMENT, materialNode->line); } FUUri url = ReadNodeUrl(effectNode); material->GetEffectReference()->SetUri(url); // Read in the parameter modifications for (xmlNode* child = effectNode->children; child != NULL; child = child->next) { if (child->type != XML_ELEMENT_NODE) continue; if (IsEquivalent(child->name, DAE_FXCMN_SETPARAM_ELEMENT)) { FCDEffectParameter* parameter = material->AddEffectParameter(FArchiveXML::GetEffectParameterType(child)); status &= FArchiveXML::LoadSwitch(parameter, ¶meter->GetObjectType(), child); } else if (IsEquivalent(child->name, DAE_FXCMN_HINT_ELEMENT)) { FCDMaterialTechniqueHint& hint = *(material->GetTechniqueHints().insert(material->GetTechniqueHints().end(), FCDMaterialTechniqueHint())); hint.platform = TO_FSTRING(ReadNodeProperty(child, DAE_PLATFORM_ATTRIBUTE)); hint.technique = ReadNodeProperty(child, DAE_REF_ATTRIBUTE); } } if (material->GetEffectReference()->IsLocal() && material->GetEffectReference()->GetEntity() == NULL) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_EFFECT_MISSING, materialNode->line); return status; } material->SetDirtyFlag(); return status; } bool FArchiveXML::LoadEffectCode(FCDObject* object, xmlNode* codeNode) { FCDEffectCode* effectCode = (FCDEffectCode*)object; bool status = true; if (IsEquivalent(codeNode->name, DAE_FXCMN_INCLUDE_ELEMENT)) effectCode->SetType(FCDEffectCode::INCLUDE); else if (IsEquivalent(codeNode->name, DAE_FXCMN_CODE_ELEMENT)) effectCode->SetType(FCDEffectCode::CODE); else { //return status.Fail(FS("Unknown effect code type."), codeNode->line); FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_UNKNOWN_EFFECT_CODE, codeNode->line); return status; } // Read in the code identifier and the actual code or filename effectCode->SetSubId(ReadNodeProperty(codeNode, DAE_SID_ATTRIBUTE)); if (effectCode->GetType() == FCDEffectCode::INCLUDE && effectCode->GetSubId().empty()) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_SID_MISSING, codeNode->line); } if (effectCode->GetType() == FCDEffectCode::INCLUDE) { effectCode->SetFilename(ReadNodeUrl(codeNode).GetAbsolutePath()); effectCode->SetFilename(effectCode->GetDocument()->GetFileManager()->CleanUri(FUUri(effectCode->GetFilename()))); } else { effectCode->SetCode(TO_FSTRING(ReadNodeContentFull(codeNode))); } effectCode->SetDirtyFlag(); return status; } bool FArchiveXML::LoadEffectParameter(FCDObject* object, xmlNode* parameterNode) { FCDEffectParameter* effectParameter = (FCDEffectParameter*)object; bool status = true; // Retrieves the annotations xmlNodeList annotationNodes; FindChildrenByType(parameterNode, DAE_ANNOTATE_ELEMENT, annotationNodes); for (xmlNodeList::iterator itN = annotationNodes.begin(); itN != annotationNodes.end(); ++itN) { xmlNode* annotateNode = (*itN); FCDEffectParameterAnnotation* annotation = effectParameter->AddAnnotation(); annotation->name = TO_FSTRING(ReadNodeProperty(annotateNode, DAE_NAME_ATTRIBUTE)); for (xmlNode* valueNode = annotateNode->children; valueNode != NULL; valueNode = valueNode->next) { if (valueNode->type != XML_ELEMENT_NODE) continue; if (IsEquivalent(valueNode->name, DAE_FXCMN_STRING_ELEMENT)) { annotation->type = FCDEffectParameter::STRING; annotation->value = TO_FSTRING(ReadNodeContentFull(valueNode)); } else if (IsEquivalent(valueNode->name, DAE_FXCMN_BOOL_ELEMENT)) { annotation->type = FCDEffectParameter::BOOLEAN; annotation->value = TO_FSTRING(ReadNodeContentDirect(valueNode)); } else if (IsEquivalent(valueNode->name, DAE_FXCMN_INT_ELEMENT)) { annotation->type = FCDEffectParameter::INTEGER; annotation->value = TO_FSTRING(ReadNodeContentDirect(valueNode)); } else if (IsEquivalent(valueNode->name, DAE_FXCMN_FLOAT_ELEMENT)) { annotation->type = FCDEffectParameter::FLOAT; annotation->value = TO_FSTRING(ReadNodeContentDirect(valueNode)); } else {FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_INVALID_ANNO_TYPE, valueNode->line);} break; } } // This parameter is a generator if this is a element. Otherwise, it modifies // an existing parameter (, or . if (IsEquivalent(parameterNode->name, DAE_FXCMN_NEWPARAM_ELEMENT)) effectParameter->SetGenerator(); else if (IsEquivalent(parameterNode->name, DAE_PARAMETER_ELEMENT)) effectParameter->SetAnimator(); else if (IsEquivalent(parameterNode->name, DAE_FXCMN_SETPARAM_ELEMENT)) effectParameter->SetModifier(); if (effectParameter->IsGenerator()) { effectParameter->SetReference(ReadNodeProperty(parameterNode, DAE_SID_ATTRIBUTE)); if (effectParameter->GetReference().empty()) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_GEN_REF_ATTRIBUTE_MISSING, parameterNode->line); return status; } } else if (effectParameter->IsModifier()) { effectParameter->SetReference(ReadNodeProperty(parameterNode, DAE_REF_ATTRIBUTE)); if (effectParameter->GetReference().empty()) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_MOD_REF_ATTRIBUTE_MISSING, parameterNode->line); return status; } } else if (effectParameter->IsAnimator()) { effectParameter->SetReference(ReadNodeProperty(parameterNode, DAE_SID_ATTRIBUTE)); if (effectParameter->GetReference().empty()) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_GEN_REF_ATTRIBUTE_MISSING, parameterNode->line); } effectParameter->SetSemantic(ReadNodeProperty(parameterNode, DAE_SEMANTIC_ATTRIBUTE)); if (effectParameter->GetSemantic().empty()) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_GEN_REF_ATTRIBUTE_MISSING, parameterNode->line); } } if (!effectParameter->IsAnimator()) { xmlNode* valueNode = FindChildByType(parameterNode, DAE_FXCMN_SEMANTIC_ELEMENT); if (valueNode != NULL) { effectParameter->SetSemantic(ReadNodeContentFull(valueNode)); } } effectParameter->SetDirtyFlag(); return status; } bool FArchiveXML::LoadEffectParameterBool(FCDObject* object, xmlNode* parameterNode) { if (!FArchiveXML::LoadEffectParameter(object, parameterNode)) return false; bool status = true; FCDEffectParameterBool* effectParameterBool = (FCDEffectParameterBool*)object; xmlNode* valueNode = FindChildByType(parameterNode, DAE_FXCMN_BOOL_ELEMENT); const char* valueString = ReadNodeContentDirect(valueNode); if (valueString == NULL || *valueString == 0) { //return status.Fail(FS("Bad value for boolean parameter in effect: ") + TO_FSTRING(GetReference()), parameterNode->line); FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_BAD_BOOLEAN_VALUE, parameterNode->line); } effectParameterBool->SetValue(FUStringConversion::ToBoolean(valueString)); effectParameterBool->SetDirtyFlag(); return status; } bool FArchiveXML::LoadEffectParameterFloat(FCDObject* object, xmlNode* parameterNode) { if (!FArchiveXML::LoadEffectParameter(object, parameterNode)) return false; bool status = true; FCDEffectParameterFloat* effectParameterFloat = (FCDEffectParameterFloat*)object; if (!effectParameterFloat->IsAnimator()) { xmlNode* valueNode = FindChildByType(parameterNode, DAE_FXCMN_FLOAT_ELEMENT); if (valueNode == NULL) { valueNode = FindChildByType(parameterNode, DAE_FXCMN_HALF_ELEMENT); effectParameterFloat->SetFloatType(FCDEffectParameterFloat::HALF); } else effectParameterFloat->SetFloatType(FCDEffectParameterFloat::FLOAT); const char* valueString = ReadNodeContentDirect(valueNode); if (valueString == NULL || *valueString == 0) { //return status.Fail(FS("Bad float value for float parameter: ") + TO_FSTRING(GetReference()), parameterNode->line); FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_BAD_FLOAT_PARAM, parameterNode->line); } effectParameterFloat->SetValue(FUStringConversion::ToFloat(valueString)); } FArchiveXML::LoadAnimatable(&effectParameterFloat->GetValue(), parameterNode); effectParameterFloat->SetDirtyFlag(); return status; } bool FArchiveXML::LoadEffectParameterFloat2(FCDObject* object, xmlNode* parameterNode) { if (!FArchiveXML::LoadEffectParameter(object, parameterNode)) return false; bool status = true; FCDEffectParameterFloat2* effectParameterFloat2 = (FCDEffectParameterFloat2*)object; xmlNode* valueNode = FindChildByType(parameterNode, DAE_FXCMN_FLOAT2_ELEMENT); if (valueNode == NULL) { valueNode = FindChildByType(parameterNode, DAE_FXCMN_HALF2_ELEMENT); effectParameterFloat2->SetFloatType(FCDEffectParameterFloat2::HALF); } else effectParameterFloat2->SetFloatType(FCDEffectParameterFloat2::FLOAT); const char* valueString = ReadNodeContentDirect(valueNode); if (valueString == NULL || *valueString == 0) { //return status.Fail(FS("Bad value for float2 parameter: ") + TO_FSTRING(GetReference()), parameterNode->line); FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_BAD_FLOAT_PARAM2, parameterNode->line); } effectParameterFloat2->SetValue(FUStringConversion::ToVector2(&valueString)); effectParameterFloat2->SetDirtyFlag(); return status; } bool FArchiveXML::LoadEffectParameterFloat3(FCDObject* object, xmlNode* parameterNode) { if (!FArchiveXML::LoadEffectParameter(object, parameterNode)) return false; bool status = true; FCDEffectParameterFloat3* effectParameterFloat3 = (FCDEffectParameterFloat3*)object; if (!effectParameterFloat3->IsAnimator()) { xmlNode* valueNode = FindChildByType(parameterNode, DAE_FXCMN_FLOAT3_ELEMENT); if (valueNode == NULL) { valueNode = FindChildByType(parameterNode, DAE_FXCMN_HALF3_ELEMENT); effectParameterFloat3->SetFloatType(FCDEffectParameterFloat3::HALF); } else effectParameterFloat3->SetFloatType(FCDEffectParameterFloat3::FLOAT); const char* valueString = ReadNodeContentDirect(valueNode); if (valueString == NULL || *valueString == 0) { //return status.Fail(FS("Bad value for float3 parameter: ") + TO_FSTRING(GetReference()), parameterNode->line); FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_BAD_FLOAT_PARAM3, parameterNode->line); } effectParameterFloat3->SetValue(FUStringConversion::ToVector3(valueString)); } FArchiveXML::LoadAnimatable(&effectParameterFloat3->GetValue(), parameterNode); effectParameterFloat3->SetDirtyFlag(); return status; } bool FArchiveXML::LoadEffectParameterInt(FCDObject* object, xmlNode* parameterNode) { if (!FArchiveXML::LoadEffectParameter(object, parameterNode)) return false; bool status = true; FCDEffectParameterInt* effectParameterInt = (FCDEffectParameterInt*)object; xmlNode* valueNode = FindChildByType(parameterNode, DAE_FXCMN_INT_ELEMENT); const char* valueString = ReadNodeContentDirect(valueNode); if (valueString == NULL || *valueString == 0) { //return status.Fail(FS("Bad value for float parameter in integer parameter: ") + TO_FSTRING(GetReference()), parameterNode->line); FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_BAD_FLOAT_VALUE, parameterNode->line); } effectParameterInt->SetValue(FUStringConversion::ToInt32(valueString)); effectParameterInt->SetDirtyFlag(); return status; } bool FArchiveXML::LoadEffectParameterMatrix(FCDObject* object, xmlNode* parameterNode) { if (!FArchiveXML::LoadEffectParameter(object, parameterNode)) return false; bool status = true; FCDEffectParameterMatrix* effectParameterMatrix = (FCDEffectParameterMatrix*)object; xmlNode* valueNode = FindChildByType(parameterNode, DAE_FXCMN_FLOAT4X4_ELEMENT); if (valueNode == NULL) { valueNode = FindChildByType(parameterNode, DAE_FXCMN_HALF4X4_ELEMENT); effectParameterMatrix->SetFloatType(FCDEffectParameterMatrix::HALF); } else effectParameterMatrix->SetFloatType(FCDEffectParameterMatrix::FLOAT); const char* valueString = ReadNodeContentDirect(valueNode); if (valueString == NULL || *valueString == 0) { //return status.Fail(FS("Bad value for matrix parameter: ") + TO_FSTRING(GetReference()), parameterNode->line); FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_BAD_MATRIX, parameterNode->line); } FUStringConversion::ToMatrix(valueString, effectParameterMatrix->GetValue()); effectParameterMatrix->SetDirtyFlag(); return status; } bool FArchiveXML::LoadEffectParameterString(FCDObject* object, xmlNode* parameterNode) { if (!FArchiveXML::LoadEffectParameter(object, parameterNode)) return false; bool status = true; FCDEffectParameterString* effectParameterString = (FCDEffectParameterString*)object; xmlNode* valueNode = FindChildByType(parameterNode, DAE_FXCMN_STRING_ELEMENT); effectParameterString->SetValue(ReadNodeContentFull(valueNode)); effectParameterString->SetDirtyFlag(); return status; } bool FArchiveXML::LoadEffectParameterVector(FCDObject* object, xmlNode* parameterNode) { if (!FArchiveXML::LoadEffectParameter(object, parameterNode)) return false; bool status = true; FCDEffectParameterVector* effectParameterVector = (FCDEffectParameterVector*)object; if (!effectParameterVector->IsAnimator()) { xmlNode* valueNode = FindChildByType(parameterNode, DAE_FXCMN_FLOAT4_ELEMENT); if (valueNode == NULL) { valueNode = FindChildByType(parameterNode, DAE_FXCMN_HALF4_ELEMENT); effectParameterVector->SetFloatType(FCDEffectParameterVector::HALF); } else effectParameterVector->SetFloatType(FCDEffectParameterVector::FLOAT); const char* valueString = ReadNodeContentDirect(valueNode); if (valueString == NULL || *valueString == 0) { //return status.Fail(FS("Bad value for float4 parameter: ") + TO_FSTRING(GetReference()), parameterNode->line); FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_BAD_FLOAT_PARAM4, parameterNode->line); } FMVector4 value; value.x = FUStringConversion::ToFloat(&valueString); value.y = FUStringConversion::ToFloat(&valueString); value.z = FUStringConversion::ToFloat(&valueString); value.w = FUStringConversion::ToFloat(&valueString); effectParameterVector->SetValue(value); } FArchiveXML::LoadAnimatable(&effectParameterVector->GetValue(), parameterNode); effectParameterVector->SetDirtyFlag(); return status; } bool FArchiveXML::LoadEffectParameterSampler(FCDObject* object, xmlNode* parameterNode) { if (!FArchiveXML::LoadEffectParameter(object, parameterNode)) return false; bool status = true; FCDEffectParameterSampler* effectParameterSampler = (FCDEffectParameterSampler*)object; FCDEffectParameterSamplerData& data = FArchiveXML::documentLinkDataMap[effectParameterSampler->GetDocument()].effectParameterSamplerDataMap[effectParameterSampler]; // Find the sampler node xmlNode* samplerNode = NULL; for (xmlNode* child = parameterNode->children; child != NULL; child = child->next) { if (child->type != XML_ELEMENT_NODE) continue; if (IsEquivalent(child->name, DAE_FXCMN_SAMPLER1D_ELEMENT)) { effectParameterSampler->SetSamplerType(FCDEffectParameterSampler::SAMPLER1D); samplerNode = child; break; } else if (IsEquivalent(child->name, DAE_FXCMN_SAMPLER2D_ELEMENT)) { effectParameterSampler->SetSamplerType(FCDEffectParameterSampler::SAMPLER2D); samplerNode = child; break; } else if (IsEquivalent(child->name, DAE_FXCMN_SAMPLER3D_ELEMENT)) { effectParameterSampler->SetSamplerType(FCDEffectParameterSampler::SAMPLER3D); samplerNode = child; break; } else if (IsEquivalent(child->name, DAE_FXCMN_SAMPLERCUBE_ELEMENT)) { effectParameterSampler->SetSamplerType(FCDEffectParameterSampler::SAMPLERCUBE); samplerNode = child; break; } } if (samplerNode == NULL) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_SAMPLER_NODE_MISSING, parameterNode->line); return status; } xmlNode* wrapNode = FindChildByType(samplerNode, DAE_WRAP_S_ELEMENT); if (wrapNode) effectParameterSampler->SetWrapS(FUDaeTextureWrapMode::FromString(ReadNodeContentDirect(wrapNode))); wrapNode = FindChildByType(samplerNode, DAE_WRAP_T_ELEMENT); if (wrapNode) effectParameterSampler->SetWrapT(FUDaeTextureWrapMode::FromString(ReadNodeContentDirect(wrapNode))); wrapNode = FindChildByType(samplerNode, DAE_WRAP_P_ELEMENT); if (wrapNode) effectParameterSampler->SetWrapP(FUDaeTextureWrapMode::FromString(ReadNodeContentDirect(wrapNode))); xmlNode* filterNode = FindChildByType(samplerNode, DAE_MIN_FILTER_ELEMENT); if (filterNode) effectParameterSampler->SetMinFilter(FUDaeTextureFilterFunction::FromString(ReadNodeContentDirect(filterNode))); filterNode = FindChildByType(samplerNode, DAE_MAG_FILTER_ELEMENT); if (filterNode) effectParameterSampler->SetMagFilter(FUDaeTextureFilterFunction::FromString(ReadNodeContentDirect(filterNode))); filterNode = FindChildByType(samplerNode, DAE_MIP_FILTER_ELEMENT); if (filterNode) effectParameterSampler->SetMipFilter(FUDaeTextureFilterFunction::FromString(ReadNodeContentDirect(filterNode))); // Parse the source node xmlNode* sourceNode = FindChildByType(samplerNode, DAE_SOURCE_ELEMENT); data.surfaceSid = ReadNodeContentDirect(sourceNode); if (data.surfaceSid.empty()) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_EMPTY_SURFACE_SOURCE, parameterNode->line); return status; } else { data.surfaceSid = FCDObjectWithId::CleanSubId(data.surfaceSid); } return status; } bool FArchiveXML::LoadEffectParameterSurface(FCDObject* object, xmlNode* parameterNode) { if (!FArchiveXML::LoadEffectParameter(object, parameterNode)) return false; bool status = true; FCDEffectParameterSurface* effectParameterSurface = (FCDEffectParameterSurface*)object; xmlNode* surfaceNode = FindChildByType(parameterNode, DAE_FXCMN_SURFACE_ELEMENT); // Process the type attribute, as a string, since its usefulness is marginal. fm::string typeAttr = ReadNodeProperty(surfaceNode, DAE_TYPE_ATTRIBUTE); if (!typeAttr.empty()) effectParameterSurface->SetSurfaceType(typeAttr); bool initialized = false; xmlNode* valueNode = NULL; //The surface can now contain many init_from elements (1.4.1) xmlNodeList valueNodes; FindChildrenByType(surfaceNode, DAE_INITFROM_ELEMENT, valueNodes); for (xmlNodeList::iterator it = valueNodes.begin(); it != valueNodes.end(); ++it) { initialized = true; if (!effectParameterSurface->GetInitMethod()) effectParameterSurface->SetInitMethod(new FCDEffectParameterSurfaceInitFrom()); FCDEffectParameterSurfaceInitFrom* ptrInit = (FCDEffectParameterSurfaceInitFrom*)effectParameterSurface->GetInitMethod(); //StringList names; FUStringConversion::ToStringList(ReadNodeContentDirect(*it), effectParameterSurface->GetNames()); if (effectParameterSurface->GetNames().size() == 0 || effectParameterSurface->GetNames()[0].empty()) { effectParameterSurface->GetNames().clear(); FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_EMPTY_INIT_FROM, surfaceNode->line); } if (effectParameterSurface->GetNames().size() == 1) //might be 1.4.1, so allow the attributes mip, slice, face { if (HasNodeProperty(*it, DAE_MIP_ATTRIBUTE)) { fm::string mip = ReadNodeProperty(*it, DAE_MIP_ATTRIBUTE); ptrInit->mip.push_back(mip); } if (HasNodeProperty(*it, DAE_SLICE_ATTRIBUTE)) { fm::string slice = ReadNodeProperty(*it, DAE_SLICE_ATTRIBUTE); ptrInit->slice.push_back(slice); } if (HasNodeProperty(*it, DAE_FACE_ATTRIBUTE)) { fm::string face = ReadNodeProperty(*it, DAE_FACE_ATTRIBUTE); ptrInit->face.push_back(face); } } } //Check if it's initialized AS NULL if (!initialized) { valueNode = FindChildByType(surfaceNode, DAE_INITASNULL_ELEMENT); if (valueNode) { initialized = true; effectParameterSurface->SetInitMethod(FCDEffectParameterSurfaceInitFactory::Create(FCDEffectParameterSurfaceInitFactory::AS_NULL)); } } //Check if it's initialized AS TARGET if (!initialized) { valueNode = FindChildByType(surfaceNode, DAE_INITASTARGET_ELEMENT); if (valueNode) { initialized = true; effectParameterSurface->SetInitMethod(FCDEffectParameterSurfaceInitFactory::Create(FCDEffectParameterSurfaceInitFactory::AS_TARGET)); } } //Check if it's initialized AS CUBE if (!initialized) { valueNode = FindChildByType(surfaceNode, DAE_INITCUBE_ELEMENT); if (valueNode) { initialized = true; effectParameterSurface->SetInitMethod(FCDEffectParameterSurfaceInitFactory::Create(FCDEffectParameterSurfaceInitFactory::CUBE)); FCDEffectParameterSurfaceInitCube* ptrInit = (FCDEffectParameterSurfaceInitCube*) effectParameterSurface->GetInitMethod(); //Check if it's an ALL reference xmlNode* refNode = FindChildByType(valueNode, DAE_ALL_ELEMENT); if (refNode) { ptrInit->cubeType = FCDEffectParameterSurfaceInitCube::ALL; fm::string name = ReadNodeProperty(refNode, DAE_REF_ATTRIBUTE); if (name.empty()) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_EMPTY_IMAGE_NAME, surfaceNode->line); } else effectParameterSurface->GetNames().push_back(name); } //Check if it's a PRIMARY reference if (!refNode) { refNode = FindChildByType(valueNode, DAE_PRIMARY_ELEMENT); if (refNode) { ptrInit->cubeType = FCDEffectParameterSurfaceInitCube::PRIMARY; fm::string name = ReadNodeProperty(refNode, DAE_REF_ATTRIBUTE); if (name.empty()) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_EMPTY_IMAGE_NAME, surfaceNode->line); } else effectParameterSurface->GetNames().push_back(name); xmlNode* orderNode = FindChildByType(refNode, DAE_ORDER_ELEMENT); if (orderNode) { //FIXME: complete when the spec has more info } } } //Check if it's a FACE reference if (!refNode) { xmlNodeList faceNodes; FindChildrenByType(valueNode, DAE_FACE_ELEMENT, faceNodes); if (faceNodes.size()==6) { ptrInit->cubeType = FCDEffectParameterSurfaceInitCube::FACE; for (uint8 ii=0; iiline); } else effectParameterSurface->GetNames().push_back(name); } } } } } //Check if it's initialized AS VOLUME if (!initialized) { valueNode = FindChildByType(surfaceNode, DAE_INITVOLUME_ELEMENT); if (valueNode) { initialized = true; effectParameterSurface->SetInitMethod(FCDEffectParameterSurfaceInitFactory::Create(FCDEffectParameterSurfaceInitFactory::VOLUME)); FCDEffectParameterSurfaceInitVolume* ptrInit = (FCDEffectParameterSurfaceInitVolume*) effectParameterSurface->GetInitMethod(); //Check if it's an ALL reference xmlNode* refNode = FindChildByType(valueNode, DAE_ALL_ELEMENT); if (refNode) { ptrInit->volumeType = FCDEffectParameterSurfaceInitVolume::ALL; fm::string name = ReadNodeProperty(refNode, DAE_REF_ATTRIBUTE); if (name.empty()) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_EMPTY_IMAGE_NAME, surfaceNode->line); } else effectParameterSurface->GetNames().push_back(name); } //Check if it's a PRIMARY reference if (!refNode) { refNode = FindChildByType(valueNode, DAE_PRIMARY_ELEMENT); if (refNode) { ptrInit->volumeType = FCDEffectParameterSurfaceInitVolume::PRIMARY; fm::string name = ReadNodeProperty(refNode, DAE_REF_ATTRIBUTE); if (name.empty()) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_EMPTY_IMAGE_NAME, surfaceNode->line); } else effectParameterSurface->GetNames().push_back(name); } } } } //Check if it's initialized as PLANAR if (!initialized) { valueNode = FindChildByType(surfaceNode, DAE_INITPLANAR_ELEMENT); if (valueNode) { initialized = true; effectParameterSurface->SetInitMethod(FCDEffectParameterSurfaceInitFactory::Create(FCDEffectParameterSurfaceInitFactory::PLANAR)); //Check if it's an ALL reference xmlNode* refNode = FindChildByType(valueNode, DAE_ALL_ELEMENT); if (refNode) { fm::string name = ReadNodeProperty(refNode, DAE_REF_ATTRIBUTE); if (name.empty()) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_EMPTY_IMAGE_NAME, surfaceNode->line); } else effectParameterSurface->GetNames().push_back(name); } } } // It is acceptable for a surface not to have an initialization option //but we should flag a warning if (!initialized) { WARNING_OUT("Warning: surface %s not initialized", effectParameterSurface->GetReference().c_str()); } xmlNode* sizeNode = FindChildByType(surfaceNode, DAE_SIZE_ELEMENT); effectParameterSurface->SetSize(FUStringConversion::ToVector3(ReadNodeContentDirect(sizeNode))); xmlNode* viewportRatioNode = FindChildByType(surfaceNode, DAE_VIEWPORT_RATIO); effectParameterSurface->SetViewportRatio(FUStringConversion::ToFloat(ReadNodeContentDirect(viewportRatioNode))); xmlNode* mipLevelsNode = FindChildByType(surfaceNode, DAE_MIP_LEVELS); effectParameterSurface->SetMipLevelCount((uint16) FUStringConversion::ToInt32(ReadNodeContentDirect(mipLevelsNode))); xmlNode* mipmapGenerateNode = FindChildByType(surfaceNode, DAE_MIPMAP_GENERATE); effectParameterSurface->SetGenerateMipMaps(FUStringConversion::ToBoolean(ReadNodeContentDirect(mipmapGenerateNode))); xmlNode* formatNode = FindChildByType(surfaceNode, DAE_FORMAT_ELEMENT); if (formatNode) effectParameterSurface->SetFormat(FUStringConversion::ToString(ReadNodeContentDirect(formatNode))); xmlNode* formatHintNode = FindChildByType(surfaceNode, DAE_FORMAT_HINT_ELEMENT); if (formatHintNode) { FCDFormatHint* formatHint = effectParameterSurface->AddFormatHint(); xmlNode* hintChild = FindChildByType(formatHintNode, DAE_CHANNELS_ELEMENT); if (!hintChild) { WARNING_OUT("Warning: surface %s misses channel information in its format hint.", effectParameterSurface->GetReference().c_str()); formatHint->channels = FCDFormatHint::CHANNEL_UNKNOWN; } else { fm::string contents = FUStringConversion::ToString(ReadNodeContentDirect(hintChild)); if (IsEquivalent(contents, DAE_FORMAT_HINT_RGB_VALUE)) formatHint->channels = FCDFormatHint::CHANNEL_RGB; else if (IsEquivalent(contents, DAE_FORMAT_HINT_RGBA_VALUE)) formatHint->channels = FCDFormatHint::CHANNEL_RGBA; else if (IsEquivalent(contents, DAE_FORMAT_HINT_L_VALUE)) formatHint->channels = FCDFormatHint::CHANNEL_L; else if (IsEquivalent(contents, DAE_FORMAT_HINT_LA_VALUE)) formatHint->channels = FCDFormatHint::CHANNEL_LA; else if (IsEquivalent(contents, DAE_FORMAT_HINT_D_VALUE)) formatHint->channels = FCDFormatHint::CHANNEL_D; else if (IsEquivalent(contents, DAE_FORMAT_HINT_XYZ_VALUE)) formatHint->channels = FCDFormatHint::CHANNEL_XYZ; else if (IsEquivalent(contents, DAE_FORMAT_HINT_XYZW_VALUE)) formatHint->channels = FCDFormatHint::CHANNEL_XYZW; else { WARNING_OUT("Warning: surface %s contains an invalid channel description %s in its format hint.", effectParameterSurface->GetReference().c_str(), contents.c_str()); formatHint->channels = FCDFormatHint::CHANNEL_UNKNOWN; } } hintChild = FindChildByType(formatHintNode, DAE_RANGE_ELEMENT); if (!hintChild) { WARNING_OUT("Warning: surface %s misses range information in its format hint.", effectParameterSurface->GetReference().c_str()); formatHint->range = FCDFormatHint::RANGE_UNKNOWN; } else { fm::string contents = FUStringConversion::ToString(ReadNodeContentDirect(hintChild)); if (IsEquivalent(contents, DAE_FORMAT_HINT_SNORM_VALUE)) formatHint->range = FCDFormatHint::RANGE_SNORM; else if (IsEquivalent(contents, DAE_FORMAT_HINT_UNORM_VALUE)) formatHint->range = FCDFormatHint::RANGE_UNORM; else if (IsEquivalent(contents, DAE_FORMAT_HINT_SINT_VALUE)) formatHint->range = FCDFormatHint::RANGE_SINT; else if (IsEquivalent(contents, DAE_FORMAT_HINT_UINT_VALUE)) formatHint->range = FCDFormatHint::RANGE_UINT; else if (IsEquivalent(contents, DAE_FORMAT_HINT_FLOAT_VALUE)) formatHint->range = FCDFormatHint::RANGE_FLOAT; else if (IsEquivalent(contents, DAE_FORMAT_HINT_LOW_VALUE)) formatHint->range = FCDFormatHint::RANGE_LOW; else { WARNING_OUT("Warning: surface %s contains an invalid range description %s in its format hint.", effectParameterSurface->GetReference().c_str(), contents.c_str()); formatHint->range= FCDFormatHint::RANGE_UNKNOWN; } } hintChild = FindChildByType(formatHintNode, DAE_PRECISION_ELEMENT); if (hintChild) { fm::string contents = FUStringConversion::ToString(ReadNodeContentDirect(hintChild)); if (IsEquivalent(contents, DAE_FORMAT_HINT_LOW_VALUE)) formatHint->precision = FCDFormatHint::PRECISION_LOW; else if (IsEquivalent(contents, DAE_FORMAT_HINT_MID_VALUE)) formatHint->precision = FCDFormatHint::PRECISION_MID; else if (IsEquivalent(contents, DAE_FORMAT_HINT_HIGH_VALUE)) formatHint->precision = FCDFormatHint::PRECISION_HIGH; else { WARNING_OUT("Warning: surface %s contains an invalid precision description %s in its format hint.", effectParameterSurface->GetReference().c_str(), contents.c_str()); formatHint->precision = FCDFormatHint::PRECISION_UNKNOWN; } } xmlNodeList optionNodes; FindChildrenByType(formatHintNode, DAE_OPTION_ELEMENT, optionNodes); for (xmlNodeList::iterator it = optionNodes.begin(); it != optionNodes.end(); ++it) { fm::string contents = FUStringConversion::ToString(ReadNodeContentDirect(*it)); if (IsEquivalent(contents, DAE_FORMAT_HINT_SRGB_GAMMA_VALUE)) formatHint->options.push_back(FCDFormatHint::OPT_SRGB_GAMMA); else if (IsEquivalent(contents, DAE_FORMAT_HINT_NORMALIZED3_VALUE)) formatHint->options.push_back(FCDFormatHint::OPT_NORMALIZED3); else if (IsEquivalent(contents, DAE_FORMAT_HINT_NORMALIZED4_VALUE)) formatHint->options.push_back(FCDFormatHint::OPT_NORMALIZED4); else if (IsEquivalent(contents, DAE_FORMAT_HINT_COMPRESSABLE_VALUE)) formatHint->options.push_back(FCDFormatHint::OPT_COMPRESSABLE); else { WARNING_OUT("Warning: surface %s contains an invalid option description %s in its format hint.", effectParameterSurface->GetReference().c_str(), contents.c_str()); } } } effectParameterSurface->SetDirtyFlag(); return status; } bool FArchiveXML::LoadEffectPass(FCDObject* object, xmlNode* passNode) { FCDEffectPass* effectPass = (FCDEffectPass*)object; bool status = true; if (!IsEquivalent(passNode->name, DAE_PASS_ELEMENT)) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOWN_PASS_ELEMENT, passNode->line); return status; } effectPass->SetPassName(TO_FSTRING(ReadNodeProperty(passNode, DAE_SID_ATTRIBUTE))); // Iterate over the pass nodes, looking for render states and elements, in any order. for (xmlNode* child = passNode->children; child != NULL; child = child->next) { if (child->type != XML_ELEMENT_NODE) continue; // Check for a render state type. FUDaePassState::State stateType = FUDaePassState::FromString((const char*) child->name); if (stateType != FUDaePassState::INVALID) { FCDEffectPassState* state = effectPass->AddRenderState(stateType); status &= FArchiveXML::LoadEffectPassState(state, child); } // Look for the element. else if (IsEquivalent(child->name, DAE_SHADER_ELEMENT)) { FCDEffectPassShader* shader = effectPass->AddShader(); status &= FArchiveXML::LoadEffectPassShader(shader, child); } } effectPass->SetDirtyFlag(); return status; } bool FArchiveXML::LoadEffectPassShader(FCDObject* object, xmlNode* shaderNode) { FCDEffectPassShader* effectPassShader = (FCDEffectPassShader*)object; bool status = true; if (!IsEquivalent(shaderNode->name, DAE_SHADER_ELEMENT)) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOWN_PASS_SHADER_ELEMENT, shaderNode->line); return status; } // Read in the shader's name and stage xmlNode* nameNode = FindChildByType(shaderNode, DAE_FXCMN_NAME_ELEMENT); effectPassShader->SetName(ReadNodeContentFull(nameNode)); fm::string codeSource = ReadNodeProperty(nameNode, DAE_SOURCE_ATTRIBUTE); if (effectPassShader->GetName().empty()) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNAMED_EFFECT_PASS_SHADER, shaderNode->line); return status; } fm::string stage = ReadNodeStage(shaderNode); bool isFragment = (stage == DAE_FXCMN_FRAGMENT_SHADER) || (stage == DAE_FXGLSL_FRAGMENT_SHADER); bool isVertex = (stage == DAE_FXCMN_VERTEX_SHADER) || (stage == DAE_FXGLSL_VERTEX_SHADER); if (isFragment) effectPassShader->AffectsFragments(); else if (isVertex) effectPassShader->AffectsVertices(); else { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOWN_EPS_STAGE, shaderNode->line); return status; } // Look-up the code filename for this shader, if available effectPassShader->SetCode(effectPassShader->GetParent()->GetParent()->FindCode(codeSource)); if (effectPassShader->GetCode() == NULL) effectPassShader->SetCode(effectPassShader->GetParent()->GetParent()->GetParent()->FindCode(codeSource)); // Read in the compiler-related elements xmlNode* compilerTargetNode = FindChildByType(shaderNode, DAE_FXCMN_COMPILERTARGET_ELEMENT); effectPassShader->SetCompilerTarget(TO_FSTRING(ReadNodeContentFull(compilerTargetNode))); xmlNode* compilerOptionsNode = FindChildByType(shaderNode, DAE_FXCMN_COMPILEROPTIONS_ELEMENT); effectPassShader->SetCompilerOptions(TO_FSTRING(ReadNodeContentFull(compilerOptionsNode))); // Read in the bind parameters xmlNodeList bindNodes; FindChildrenByType(shaderNode, DAE_FXCMN_BIND_ELEMENT, bindNodes); for (xmlNodeList::iterator itB = bindNodes.begin(); itB != bindNodes.end(); ++itB) { xmlNode* paramNode = FindChildByType(*itB, DAE_PARAMETER_ELEMENT); FCDEffectPassBind* bind = effectPassShader->AddBinding(); bind->symbol = ReadNodeProperty((*itB), DAE_SYMBOL_ATTRIBUTE); bind->reference = ReadNodeProperty(paramNode, DAE_REF_ATTRIBUTE); } effectPassShader->SetDirtyFlag(); return status; } bool FArchiveXML::LoadEffectPassState(FCDObject* object, xmlNode* stateNode) { FCDEffectPassState* effectPassState = (FCDEffectPassState*)object; bool status = true; #define NODE_TYPE(offset, node, valueType, convFn) \ if (node != NULL && HasNodeProperty(node, DAE_VALUE_ATTRIBUTE)) { \ *((valueType*)(effectPassState->GetData() + offset)) = (valueType) FUStringConversion::convFn(ReadNodeProperty(node, DAE_VALUE_ATTRIBUTE)); } #define NODE_INDEX(offset, node) \ if (node != NULL && HasNodeProperty(node, DAE_INDEX_ATTRIBUTE)) { \ *((uint8*)(effectPassState->GetData() + offset)) = (uint8) FUStringConversion::ToUInt32(ReadNodeProperty(node, DAE_INDEX_ATTRIBUTE)); } #define NODE_ENUM(offset, node, nameSpace) \ if (node != NULL && HasNodeProperty(node, DAE_VALUE_ATTRIBUTE)) { \ *((uint32*)(effectPassState->GetData() + offset)) = (uint32) nameSpace::FromString(ReadNodeProperty(node, DAE_VALUE_ATTRIBUTE)); } #define CHILD_NODE_TYPE(offset, elementName, valueType, convFn) { \ xmlNode* node = FindChildByType(stateNode, elementName); \ NODE_TYPE(offset, node, valueType, convFn); } #define CHILD_NODE_ENUM(offset, elementName, nameSpace) { \ xmlNode* node = FindChildByType(stateNode, elementName); \ NODE_ENUM(offset, node, nameSpace); } switch (effectPassState->GetType()) { case FUDaePassState::ALPHA_FUNC: CHILD_NODE_ENUM(0, DAE_FXSTD_STATE_FUNC_ELEMENT, FUDaePassStateFunction); CHILD_NODE_TYPE(4, DAE_FXSTD_STATE_VALUE_ELEMENT, float, ToFloat); break; case FUDaePassState::BLEND_FUNC: CHILD_NODE_ENUM(0, DAE_FXSTD_STATE_SRC_ELEMENT, FUDaePassStateBlendType); CHILD_NODE_ENUM(4, DAE_FXSTD_STATE_DEST_ELEMENT, FUDaePassStateBlendType); break; case FUDaePassState::BLEND_FUNC_SEPARATE: CHILD_NODE_ENUM(0, DAE_FXSTD_STATE_SRCRGB_ELEMENT, FUDaePassStateBlendType); CHILD_NODE_ENUM(4, DAE_FXSTD_STATE_DESTRGB_ELEMENT, FUDaePassStateBlendType); CHILD_NODE_ENUM(8, DAE_FXSTD_STATE_SRCALPHA_ELEMENT, FUDaePassStateBlendType); CHILD_NODE_ENUM(12, DAE_FXSTD_STATE_DESTALPHA_ELEMENT, FUDaePassStateBlendType); break; case FUDaePassState::BLEND_EQUATION: NODE_ENUM(0, stateNode, FUDaePassStateBlendEquation); break; case FUDaePassState::BLEND_EQUATION_SEPARATE: CHILD_NODE_ENUM(0, DAE_FXSTD_STATE_RGB_ELEMENT, FUDaePassStateBlendEquation); CHILD_NODE_ENUM(4, DAE_FXSTD_STATE_ALPHA_ELEMENT, FUDaePassStateBlendEquation); break; case FUDaePassState::COLOR_MATERIAL: CHILD_NODE_ENUM(0, DAE_FXSTD_STATE_FACE_ELEMENT, FUDaePassStateFaceType); CHILD_NODE_ENUM(4, DAE_FXSTD_STATE_MODE_ELEMENT, FUDaePassStateMaterialType); break; case FUDaePassState::CULL_FACE: NODE_ENUM(0, stateNode, FUDaePassStateFaceType); break; case FUDaePassState::DEPTH_FUNC: NODE_ENUM(0, stateNode, FUDaePassStateFunction); break; case FUDaePassState::FOG_MODE: NODE_ENUM(0, stateNode, FUDaePassStateFogType); break; case FUDaePassState::FOG_COORD_SRC: NODE_ENUM(0, stateNode, FUDaePassStateFogCoordinateType); break; case FUDaePassState::FRONT_FACE: NODE_ENUM(0, stateNode, FUDaePassStateFrontFaceType); break; case FUDaePassState::LIGHT_MODEL_COLOR_CONTROL: NODE_ENUM(0, stateNode, FUDaePassStateLightModelColorControlType); break; case FUDaePassState::LOGIC_OP: NODE_ENUM(0, stateNode, FUDaePassStateLogicOperation); break; case FUDaePassState::POLYGON_MODE: CHILD_NODE_ENUM(0, DAE_FXSTD_STATE_FACE_ELEMENT, FUDaePassStateFaceType); CHILD_NODE_ENUM(4, DAE_FXSTD_STATE_MODE_ELEMENT, FUDaePassStatePolygonMode); break; case FUDaePassState::SHADE_MODEL: NODE_ENUM(0, stateNode, FUDaePassStateShadeModel); break; case FUDaePassState::STENCIL_FUNC: CHILD_NODE_ENUM(0, DAE_FXSTD_STATE_FUNC_ELEMENT, FUDaePassStateFunction); CHILD_NODE_TYPE(4, DAE_FXSTD_STATE_REF_ELEMENT, uint8, ToUInt32); CHILD_NODE_TYPE(5, DAE_FXSTD_STATE_MASK_ELEMENT, uint8, ToUInt32); break; case FUDaePassState::STENCIL_OP: CHILD_NODE_ENUM(0, DAE_FXSTD_STATE_FAIL_ELEMENT, FUDaePassStateStencilOperation); CHILD_NODE_ENUM(4, DAE_FXSTD_STATE_ZFAIL_ELEMENT, FUDaePassStateStencilOperation); CHILD_NODE_ENUM(8, DAE_FXSTD_STATE_ZPASS_ELEMENT, FUDaePassStateStencilOperation); break; case FUDaePassState::STENCIL_FUNC_SEPARATE: CHILD_NODE_ENUM(0, DAE_FXSTD_STATE_FRONT_ELEMENT, FUDaePassStateFunction); CHILD_NODE_ENUM(4, DAE_FXSTD_STATE_BACK_ELEMENT, FUDaePassStateFunction); CHILD_NODE_TYPE(8, DAE_FXSTD_STATE_REF_ELEMENT, uint8, ToUInt32); CHILD_NODE_TYPE(9, DAE_FXSTD_STATE_MASK_ELEMENT, uint8, ToUInt32); break; case FUDaePassState::STENCIL_OP_SEPARATE: CHILD_NODE_ENUM(0, DAE_FXSTD_STATE_FACE_ELEMENT, FUDaePassStateFaceType); CHILD_NODE_ENUM(4, DAE_FXSTD_STATE_FAIL_ELEMENT, FUDaePassStateStencilOperation); CHILD_NODE_ENUM(8, DAE_FXSTD_STATE_ZFAIL_ELEMENT, FUDaePassStateStencilOperation); CHILD_NODE_ENUM(12, DAE_FXSTD_STATE_ZPASS_ELEMENT, FUDaePassStateStencilOperation); break; case FUDaePassState::STENCIL_MASK_SEPARATE: CHILD_NODE_ENUM(0, DAE_FXSTD_STATE_FACE_ELEMENT, FUDaePassStateFaceType); CHILD_NODE_TYPE(4, DAE_FXSTD_STATE_MASK_ELEMENT, uint8, ToUInt32); break; case FUDaePassState::LIGHT_AMBIENT: case FUDaePassState::LIGHT_DIFFUSE: case FUDaePassState::LIGHT_SPECULAR: case FUDaePassState::LIGHT_POSITION: case FUDaePassState::TEXTURE_ENV_COLOR: case FUDaePassState::CLIP_PLANE: NODE_INDEX(0, stateNode); NODE_TYPE(1, stateNode, FMVector4, ToVector4); break; case FUDaePassState::LIGHT_CONSTANT_ATTENUATION: case FUDaePassState::LIGHT_LINEAR_ATTENUATION: case FUDaePassState::LIGHT_QUADRATIC_ATTENUATION: case FUDaePassState::LIGHT_SPOT_CUTOFF: case FUDaePassState::LIGHT_SPOT_EXPONENT: NODE_INDEX(0, stateNode); NODE_TYPE(1, stateNode, float, ToFloat); break; case FUDaePassState::LIGHT_SPOT_DIRECTION: NODE_INDEX(0, stateNode); NODE_TYPE(1, stateNode, FMVector3, ToVector3); break; case FUDaePassState::TEXTURE1D: case FUDaePassState::TEXTURE2D: case FUDaePassState::TEXTURE3D: case FUDaePassState::TEXTURECUBE: case FUDaePassState::TEXTURERECT: case FUDaePassState::TEXTUREDEPTH: NODE_INDEX(0, stateNode); NODE_TYPE(1, stateNode, uint32, ToUInt32); break; case FUDaePassState::LIGHT_ENABLE: case FUDaePassState::TEXTURE1D_ENABLE: case FUDaePassState::TEXTURE2D_ENABLE: case FUDaePassState::TEXTURE3D_ENABLE: case FUDaePassState::TEXTURECUBE_ENABLE: case FUDaePassState::TEXTURERECT_ENABLE: case FUDaePassState::TEXTUREDEPTH_ENABLE: case FUDaePassState::CLIP_PLANE_ENABLE: NODE_INDEX(0, stateNode); NODE_TYPE(1, stateNode, bool, ToBoolean); break; case FUDaePassState::TEXTURE_ENV_MODE: { NODE_INDEX(0, stateNode); fm::string value = ReadNodeProperty(stateNode, DAE_VALUE_ATTRIBUTE); memcpy(effectPassState->GetData() + 1, value.c_str(), min(value.size(), (size_t) 255)); effectPassState->GetData()[255] = 0; break; } case FUDaePassState::BLEND_COLOR: case FUDaePassState::CLEAR_COLOR: case FUDaePassState::FOG_COLOR: case FUDaePassState::LIGHT_MODEL_AMBIENT: case FUDaePassState::MATERIAL_AMBIENT: case FUDaePassState::MATERIAL_DIFFUSE: case FUDaePassState::MATERIAL_EMISSION: case FUDaePassState::MATERIAL_SPECULAR: case FUDaePassState::SCISSOR: NODE_TYPE(0, stateNode, FMVector4, ToVector4); break; case FUDaePassState::POINT_DISTANCE_ATTENUATION: NODE_TYPE(0, stateNode, FMVector3, ToVector3); break; case FUDaePassState::DEPTH_BOUNDS: case FUDaePassState::DEPTH_RANGE: case FUDaePassState::POLYGON_OFFSET: NODE_TYPE(0, stateNode, FMVector2, ToVector2); break; case FUDaePassState::CLEAR_STENCIL: case FUDaePassState::STENCIL_MASK: NODE_TYPE(0, stateNode, uint32, ToUInt32); break; case FUDaePassState::CLEAR_DEPTH: case FUDaePassState::FOG_DENSITY: case FUDaePassState::FOG_START: case FUDaePassState::FOG_END: case FUDaePassState::LINE_WIDTH: case FUDaePassState::MATERIAL_SHININESS: case FUDaePassState::POINT_FADE_THRESHOLD_SIZE: case FUDaePassState::POINT_SIZE: case FUDaePassState::POINT_SIZE_MIN: case FUDaePassState::POINT_SIZE_MAX: NODE_TYPE(0, stateNode, float, ToFloat); break; case FUDaePassState::COLOR_MASK: { fm::string value = ReadNodeProperty(stateNode, DAE_VALUE_ATTRIBUTE); BooleanList values; FUStringConversion::ToBooleanList(value, values); if (values.size() >= 4) { *(bool*)(effectPassState->GetData() + 0) = values[0]; *(bool*)(effectPassState->GetData() + 1) = values[1]; *(bool*)(effectPassState->GetData() + 2) = values[2]; *(bool*)(effectPassState->GetData() + 3) = values[3]; } break; } case FUDaePassState::LINE_STIPPLE: { fm::string value = ReadNodeProperty(stateNode, DAE_VALUE_ATTRIBUTE); UInt32List values; FUStringConversion::ToUInt32List(value, values); if (values.size() >= 2) { *(uint16*)(effectPassState->GetData() + 0) = (uint16) values[0]; *(uint16*)(effectPassState->GetData() + 2) = (uint16) values[1]; } break; } case FUDaePassState::MODEL_VIEW_MATRIX: case FUDaePassState::PROJECTION_MATRIX: NODE_TYPE(0, stateNode, FMMatrix44, ToMatrix); break; case FUDaePassState::LIGHTING_ENABLE: case FUDaePassState::ALPHA_TEST_ENABLE: case FUDaePassState::AUTO_NORMAL_ENABLE: case FUDaePassState::BLEND_ENABLE: case FUDaePassState::COLOR_LOGIC_OP_ENABLE: case FUDaePassState::COLOR_MATERIAL_ENABLE: case FUDaePassState::CULL_FACE_ENABLE: case FUDaePassState::DEPTH_BOUNDS_ENABLE: case FUDaePassState::DEPTH_CLAMP_ENABLE: case FUDaePassState::DEPTH_TEST_ENABLE: case FUDaePassState::DITHER_ENABLE: case FUDaePassState::FOG_ENABLE: case FUDaePassState::LIGHT_MODEL_LOCAL_VIEWER_ENABLE: case FUDaePassState::LIGHT_MODEL_TWO_SIDE_ENABLE: case FUDaePassState::LINE_SMOOTH_ENABLE: case FUDaePassState::LINE_STIPPLE_ENABLE: case FUDaePassState::LOGIC_OP_ENABLE: case FUDaePassState::MULTISAMPLE_ENABLE: case FUDaePassState::NORMALIZE_ENABLE: case FUDaePassState::POINT_SMOOTH_ENABLE: case FUDaePassState::POLYGON_OFFSET_FILL_ENABLE: case FUDaePassState::POLYGON_OFFSET_LINE_ENABLE: case FUDaePassState::POLYGON_OFFSET_POINT_ENABLE: case FUDaePassState::POLYGON_SMOOTH_ENABLE: case FUDaePassState::POLYGON_STIPPLE_ENABLE: case FUDaePassState::RESCALE_NORMAL_ENABLE: case FUDaePassState::SAMPLE_ALPHA_TO_COVERAGE_ENABLE: case FUDaePassState::SAMPLE_ALPHA_TO_ONE_ENABLE: case FUDaePassState::SAMPLE_COVERAGE_ENABLE: case FUDaePassState::SCISSOR_TEST_ENABLE: case FUDaePassState::STENCIL_TEST_ENABLE: case FUDaePassState::DEPTH_MASK: NODE_TYPE(0, stateNode, bool, ToBoolean); break; default: status = false; break; } #undef NODE_TYPE #undef NODE_INDEX #undef NODE_ENUM #undef CHILD_NODE_TYPE #undef CHILD_NODE_ENUM return status; } bool FArchiveXML::LoadEffectProfile(FCDObject* object, xmlNode* profileNode) { FCDEffectProfile* effectProfile = (FCDEffectProfile*)object; bool status = true; // Verify that we are given a valid XML input node. const char* profileName = FUDaeProfileType::ToString(effectProfile->GetType()); if (!IsEquivalent(profileNode->name, profileName)) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_INVALID_PROFILE_INPUT_NODE, profileNode->line); return status; } // Parse in the child elements: parameters and techniques for (xmlNode* child = profileNode->children; child != NULL; child = child->next) { if (child->type != XML_ELEMENT_NODE) continue; if (IsEquivalent(child->name, DAE_FXCMN_NEWPARAM_ELEMENT)) { FCDEffectParameter* parameter = effectProfile->AddEffectParameter(FArchiveXML::GetEffectParameterType(child)); status &= FArchiveXML::LoadSwitch(parameter, ¶meter->GetObjectType(), child); } else if (IsEquivalent(child->name, DAE_IMAGE_ELEMENT)) { // You can create images in the profile: tell the image library about it. FCDImage* image = effectProfile->GetDocument()->GetImageLibrary()->AddEntity(); status &= (FArchiveXML::LoadImage(image, child)); } else if (IsEquivalent(child->name, DAE_EXTRA_ELEMENT)) { FArchiveXML::LoadExtra(effectProfile->GetExtra(), child); } } effectProfile->SetDirtyFlag(); return status; } bool FArchiveXML::LoadEffectProfileFX(FCDObject* object, xmlNode* profileNode) { if (!FArchiveXML::LoadEffectProfile(object, profileNode)) return false; bool status = true; FCDEffectProfileFX* effectProfileFX = (FCDEffectProfileFX*)object; // Read in the target platform for this effect profile effectProfileFX->SetPlatform(TO_FSTRING(ReadNodeProperty(profileNode, DAE_PLATFORM_ATTRIBUTE))); // Parse in the child technique/code/include elements. for (xmlNode* child = profileNode->children; child != NULL; child = child->next) { if (child->type != XML_ELEMENT_NODE) continue; if (IsEquivalent(child->name, DAE_TECHNIQUE_ELEMENT)) { FCDEffectTechnique* technique = effectProfileFX->AddTechnique(); status &= (FArchiveXML::LoadEffectTechnique(technique, child)); } else if (IsEquivalent(child->name, DAE_FXCMN_CODE_ELEMENT) || IsEquivalent(child->name, DAE_FXCMN_INCLUDE_ELEMENT)) { FCDEffectCode* code = effectProfileFX->AddCode(); status &= (FArchiveXML::LoadEffectCode(code, child)); } } effectProfileFX->SetDirtyFlag(); return status; } bool FArchiveXML::LoadEffectStandard(FCDObject* object, xmlNode* baseNode) { if (!FArchiveXML::LoadEffectProfile(object, baseNode)) return false; bool status = true; FCDEffectStandard* effectStandard = (FCDEffectStandard*)object; // Find the node with the Max/Maya/FC-specific parameters xmlNode* maxParameterNode = NULL; xmlNode* mayaParameterNode = NULL; xmlNode* fcParameterNode = NULL; // Bump the base node up the first element xmlNode* techniqueNode = FindChildByType(baseNode, DAE_TECHNIQUE_ELEMENT); if (techniqueNode == NULL) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_TECHNIQUE_MISSING, baseNode->line); return status; } baseNode = techniqueNode; //Look for 's at this level also, and add them to the profile's parameters list for (xmlNode* child = baseNode->children; child != NULL; child = child->next) { if (child->type != XML_ELEMENT_NODE) continue; if (IsEquivalent(child->name, DAE_FXCMN_NEWPARAM_ELEMENT)) { FCDEffectParameter* parameter = effectStandard->AddEffectParameter(FArchiveXML::GetEffectParameterType(child)); status &= FArchiveXML::LoadSwitch(parameter, ¶meter->GetObjectType(), child); } } // 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); fcParameterNode = FindTechnique(extraNode, DAE_FCOLLADA_PROFILE); // Parse the material's program node and figure out the correct shader type // Either , or are expected xmlNode* commonParameterNode = NULL; for (commonParameterNode = baseNode->children; commonParameterNode != NULL; commonParameterNode = commonParameterNode->next) { if (commonParameterNode->type != XML_ELEMENT_NODE) continue; if (IsEquivalent(commonParameterNode->name, DAE_FXSTD_CONSTANT_ELEMENT)) { effectStandard->SetLightingType(FCDEffectStandard::CONSTANT); break; } else if (IsEquivalent(commonParameterNode->name, DAE_FXSTD_LAMBERT_ELEMENT)) { effectStandard->SetLightingType(FCDEffectStandard::LAMBERT); break; } else if (IsEquivalent(commonParameterNode->name, DAE_FXSTD_PHONG_ELEMENT)) { effectStandard->SetLightingType(FCDEffectStandard::PHONG); break; } else if (IsEquivalent(commonParameterNode->name, DAE_FXSTD_BLINN_ELEMENT)) { effectStandard->SetLightingType(FCDEffectStandard::BLINN); break; } } if (commonParameterNode == NULL) { //return status.Fail(FS("Unable to find the program node for standard effect: ") + TO_FSTRING(GetDaeId()), baseNode->line); FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_PROG_NODE_MISSING, baseNode->line); } bool hasTranslucency = false, hasReflectivity = false; bool hasRefractive = false; // 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); FindParameters(fcParameterNode, parameterNames, parameterNodes); size_t parameterCount = parameterNodes.size(); for (size_t i = 0; i < parameterCount; ++i) { xmlNode* parameterNode = parameterNodes[i]; const fm::string& parameterName = parameterNames[i]; const char* parameterContent = ReadNodeContentDirect(parameterNode); if (parameterName == DAE_EMISSION_MATERIAL_PARAMETER) { status &= (FArchiveXML::ParseColorTextureParameter(effectStandard, parameterNode, effectStandard->GetEmissionColorParam(), FUDaeTextureChannel::EMISSION)); } else if (parameterName == DAE_DIFFUSE_MATERIAL_PARAMETER) { status &= (FArchiveXML::ParseColorTextureParameter(effectStandard, parameterNode, effectStandard->GetDiffuseColorParam(), FUDaeTextureChannel::DIFFUSE)); } else if (parameterName == DAE_AMBIENT_MATERIAL_PARAMETER) { status &= (FArchiveXML::ParseColorTextureParameter(effectStandard, parameterNode, effectStandard->GetAmbientColorParam(), FUDaeTextureChannel::AMBIENT)); } else if (parameterName == DAE_TRANSPARENT_MATERIAL_PARAMETER) { fm::string opaque = ReadNodeProperty(parameterNode, DAE_OPAQUE_MATERIAL_ATTRIBUTE); if (IsEquivalentI(opaque, DAE_RGB_ZERO_ELEMENT)) effectStandard->SetTransparencyMode(FCDEffectStandard::RGB_ZERO); else if (IsEquivalentI(opaque, DAE_A_ONE_ELEMENT)) effectStandard->SetTransparencyMode(FCDEffectStandard::A_ONE); status &= (FArchiveXML::ParseColorTextureParameter(effectStandard, parameterNode, effectStandard->GetTranslucencyColorParam(), FUDaeTextureChannel::TRANSPARENT)); hasTranslucency = true; } else if (parameterName == DAE_TRANSPARENCY_MATERIAL_PARAMETER) { status &= (FArchiveXML::ParseFloatTextureParameter(effectStandard, parameterNode, effectStandard->GetTranslucencyFactorParam(), FUDaeTextureChannel::UNKNOWN)); hasTranslucency = true; } else if (parameterName == DAE_SPECULAR_MATERIAL_PARAMETER) { status &= (FArchiveXML::ParseColorTextureParameter(effectStandard, parameterNode, effectStandard->GetSpecularColorParam(), FUDaeTextureChannel::SPECULAR)); } else if (parameterName == DAE_SHININESS_MATERIAL_PARAMETER) { status &= (FArchiveXML::ParseFloatTextureParameter(effectStandard, parameterNode, effectStandard->GetShininessParam(), FUDaeTextureChannel::SHININESS)); } else if (parameterName == DAE_REFLECTIVE_MATERIAL_PARAMETER) { status &= (FArchiveXML::ParseColorTextureParameter(effectStandard, parameterNode, effectStandard->GetReflectivityColorParam(), FUDaeTextureChannel::REFLECTION)); hasReflectivity = true; } else if (parameterName == DAE_REFLECTIVITY_MATERIAL_PARAMETER) { status &= (FArchiveXML::ParseFloatTextureParameter(effectStandard, parameterNode, effectStandard->GetReflectivityFactorParam(), FUDaeTextureChannel::UNKNOWN)); hasReflectivity = true; } else if (parameterName == DAE_INDEXOFREFRACTION_MATERIAL_PARAMETER) { status &= (FArchiveXML::ParseFloatTextureParameter(effectStandard, parameterNode, effectStandard->GetIndexOfRefractionParam(), FUDaeTextureChannel::REFRACTION)); hasRefractive = true; } else if (parameterName == DAE_BUMP_MATERIAL_PARAMETER) { status &= (FArchiveXML::ParseSimpleTextureParameter(effectStandard, parameterNode, FUDaeTextureChannel::BUMP)); } else if (parameterName == DAEMAX_SPECLEVEL_MATERIAL_PARAMETER) { status &= (FArchiveXML::ParseFloatTextureParameter(effectStandard, parameterNode, effectStandard->GetSpecularFactorParam(), FUDaeTextureChannel::SPECULAR_LEVEL)); } else if (parameterName == DAEMAX_EMISSIONLEVEL_MATERIAL_PARAMETER) { status &= (FArchiveXML::ParseFloatTextureParameter(effectStandard, parameterNode, effectStandard->GetEmissionFactorParam(), FUDaeTextureChannel::EMISSION)); effectStandard->SetIsEmissionFactor(true); } else if (parameterName == DAEMAX_FACETED_MATERIAL_PARAMETER) { effectStandard->AddExtraAttribute(DAEMAX_MAX_PROFILE, DAEMAX_FACETED_MATERIAL_PARAMETER, TO_FSTRING(parameterContent).c_str()); } else if (parameterName == DAESHD_DOUBLESIDED_PARAMETER) { effectStandard->AddExtraAttribute(DAEMAX_MAX_PROFILE, DAESHD_DOUBLESIDED_PARAMETER, TO_FSTRING(parameterContent).c_str()); } else if (parameterName == DAEMAX_WIREFRAME_MATERIAL_PARAMETER) { effectStandard->AddExtraAttribute(DAEMAX_MAX_PROFILE, DAEMAX_WIREFRAME_MATERIAL_PARAMETER, TO_FSTRING(parameterContent).c_str()); } else if (parameterName == DAEMAX_FACEMAP_MATERIAL_PARAMETER) { effectStandard->AddExtraAttribute(DAEMAX_MAX_PROFILE, DAEMAX_FACEMAP_MATERIAL_PARAMETER, TO_FSTRING(parameterContent).c_str()); } else if (parameterName == DAEMAX_DISPLACEMENT_MATERIAL_PARAMETER) { status &= (FArchiveXML::ParseSimpleTextureParameter(effectStandard, parameterNode, FUDaeTextureChannel::DISPLACEMENT)); } else if (parameterName == DAEMAX_FILTERCOLOR_MATERIAL_PARAMETER) { status &= (FArchiveXML::ParseSimpleTextureParameter(effectStandard, parameterNode, FUDaeTextureChannel::FILTER)); } else { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOWN_MAT_PARAM_NAME, parameterNode->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) { effectStandard->SetTranslucencyColor((effectStandard->GetTransparencyMode() == FCDEffectStandard::RGB_ZERO) ? FMVector4::Zero : FMVector4::One); effectStandard->SetTranslucencyFactor((effectStandard->GetTransparencyMode() == FCDEffectStandard::RGB_ZERO) ? 0.0f : 1.0f); } if (!hasReflectivity) { effectStandard->SetReflectivityColor(FMVector4::Zero); effectStandard->SetReflectivityFactor(0.0f); } effectStandard->SetReflective(hasReflectivity); effectStandard->SetRefractive(hasRefractive); effectStandard->SetDirtyFlag(); return status; } bool FArchiveXML::LoadEffectTechnique(FCDObject* object, xmlNode* techniqueNode) { FCDEffectTechnique* effectTechnique = (FCDEffectTechnique*)object; bool status = true; if (!IsEquivalent(techniqueNode->name, DAE_TECHNIQUE_ELEMENT)) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOWN_TECHNIQUE_ELEMENT, techniqueNode->line); return status; } fm::string techniqueName = ReadNodeProperty(techniqueNode, DAE_SID_ATTRIBUTE); effectTechnique->SetName(TO_FSTRING(techniqueName)); // Clear any old parameters. while (effectTechnique->GetEffectParameterCount() > 0) { effectTechnique->GetEffectParameter(effectTechnique->GetEffectParameterCount() - 1)->Release(); } // Look for the pass and parameter elements for (xmlNode* child = techniqueNode->children; child != NULL; child = child->next) { if (child->type != XML_ELEMENT_NODE) continue; if (IsEquivalent(child->name, DAE_PASS_ELEMENT)) { FCDEffectPass* pass = effectTechnique->AddPass(); status &= (FArchiveXML::LoadEffectPass(pass, child)); } else if (IsEquivalent(child->name, DAE_FXCMN_NEWPARAM_ELEMENT) || IsEquivalent(child->name, DAE_FXCMN_SETPARAM_ELEMENT)) { FCDEffectParameter* parameter = effectTechnique->AddEffectParameter(FArchiveXML::GetEffectParameterType(child)); status &= FArchiveXML::LoadSwitch(parameter, ¶meter->GetObjectType(), child); } else if (IsEquivalent(child->name, DAE_FXCMN_CODE_ELEMENT) || IsEquivalent(child->name, DAE_FXCMN_INCLUDE_ELEMENT)) { FCDEffectCode* code = effectTechnique->AddCode(); status &= (FArchiveXML::LoadEffectCode(code, child)); } else if (IsEquivalent(child->name, DAE_IMAGE_ELEMENT)) { FCDImage* image = effectTechnique->GetDocument()->GetImageLibrary()->AddEntity(); status &= (FArchiveXML::LoadImage(image, child)); } } effectTechnique->SetDirtyFlag(); return status; } bool FArchiveXML::LoadEffect(FCDObject* object, xmlNode* effectNode) { if (!FArchiveXML::LoadEntity(object, effectNode)) return false; bool status = true; FCDEffect* effect = (FCDEffect*)object; // Clear any old parameters. while (effect->GetEffectParameterCount() > 0) { effect->GetEffectParameter(effect->GetEffectParameterCount() - 1)->Release(); } // Accept solely elements at this point. if (!IsEquivalent(effectNode->name, DAE_EFFECT_ELEMENT)) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOWN_EFFECT_ELEMENT, effectNode->line); } for (xmlNode* child = effectNode->children; child != NULL; child = child->next) { if (child->type != XML_ELEMENT_NODE) continue; if (IsEquivalent(child->name, DAE_IMAGE_ELEMENT)) { FCDImage* image = effect->GetDocument()->GetImageLibrary()->AddEntity(); status &= (FArchiveXML::LoadImage(image, child)); } else if (IsEquivalent(child->name, DAE_FXCMN_SETPARAM_ELEMENT) || IsEquivalent(child->name, DAE_FXCMN_NEWPARAM_ELEMENT)) { FCDEffectParameter* parameter = effect->AddEffectParameter(FArchiveXML::GetEffectParameterType(child)); status &= FArchiveXML::LoadSwitch(parameter, ¶meter->GetObjectType(), child); } else if (IsEquivalent(child->name, DAE_EXTRA_ELEMENT)) {} // processed by FCDEntity. else { // Check for a valid profile element. FUDaeProfileType::Type type = FUDaeProfileType::FromString((const char*) child->name); if (type != FUDaeProfileType::UNKNOWN) { FCDEffectProfile* profile = effect->AddProfile(type); status &= (FArchiveXML::LoadSwitch(profile, &profile->GetObjectType(), child)); } else { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNSUPPORTED_PROFILE, child->line); } } } effect->SetDirtyFlag(); return status; } bool FArchiveXML::LoadImage(FCDObject* object, xmlNode* imageNode) { if (!FArchiveXML::LoadEntity(object, imageNode)) return false; bool status = true; FCDImage* image = (FCDImage*)object; if (!IsEquivalent(imageNode->name, DAE_IMAGE_ELEMENT)) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOWN_IMAGE_LIB_ELEMENT, imageNode->line); return status; } if (HasNodeProperty(imageNode, DAE_WIDTH_ELEMENT)) image->SetWidth(FUStringConversion::ToUInt32(ReadNodeProperty(imageNode, DAE_WIDTH_ELEMENT))); if (HasNodeProperty(imageNode, DAE_HEIGHT_ELEMENT)) image->SetHeight(FUStringConversion::ToUInt32(ReadNodeProperty(imageNode, DAE_HEIGHT_ELEMENT))); if (HasNodeProperty(imageNode, DAE_DEPTH_ELEMENT)) image->SetDepth(FUStringConversion::ToUInt32(ReadNodeProperty(imageNode, DAE_DEPTH_ELEMENT))); // Read in the image's filename, within the element: binary images are not supported. xmlNode* filenameSourceNode = FindChildByType(imageNode, DAE_INITFROM_ELEMENT); image->SetFilename(TO_FSTRING(ReadNodeContentFull(filenameSourceNode))); // Convert the filename to something the OS can use fstring fileName = FUUri(image->GetFilename()).GetAbsoluteUri(); image->SetFilename(fileName); if (image->GetFilename().empty()) { FUError::Error(FUError::WARNING_LEVEL, FUError::ERROR_INVALID_IMAGE_FILENAME, imageNode->line); } image->SetDirtyFlag(); return status; } bool FArchiveXML::LoadTexture(FCDObject* object, xmlNode* textureNode) { FCDTexture* texture = (FCDTexture*)object; FCDTextureData& data = FArchiveXML::documentLinkDataMap[texture->GetDocument()].textureDataMap[texture]; bool status = true; // Verify that this is a sampler node if (!IsEquivalent(textureNode->name, DAE_FXSTD_TEXTURE_ELEMENT)) { //return status.Fail(FS("Unknown texture sampler element."), textureNode->line); FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_UNKNOWN_TEXTURE_SAMPLER, textureNode->line); } // Read in the 'texture' attribute: points to an image(early 1.4.0) or a sampler(late 1.4.0) // Will be resolved at link-time. data.samplerSid = ReadNodeProperty(textureNode, DAE_FXSTD_TEXTURE_ATTRIBUTE); if (!data.samplerSid.empty()) data.samplerSid = FCDObjectWithId::CleanSubId(data.samplerSid); // Read in the 'texcoord' attribute: a texture coordinate set identifier fm::string semantic = ReadNodeProperty(textureNode, DAE_FXSTD_TEXTURESET_ATTRIBUTE); if (!semantic.empty()) { texture->GetSet()->SetSemantic(semantic); //[GLaforte 06-01-2006] Also attempt to convert the value to a signed integer // since that was done quite a bit in COLLADA 1.4 preview exporters. texture->GetSet()->SetValue(FUStringConversion::ToInt32(semantic)); } // Parse in the extra trees xmlNodeList extraNodes; FindChildrenByType(textureNode, DAE_EXTRA_ELEMENT, extraNodes); for (xmlNodeList::iterator itX = extraNodes.begin(); itX != extraNodes.end(); ++itX) { status &= (FArchiveXML::LoadExtra(texture->GetExtra(), *itX)); } texture->SetDirtyFlag(); return status; } // Parse in the different standard effect parameters, bucketing the textures bool FArchiveXML::ParseColorTextureParameter(FCDEffectStandard* effectStandard, xmlNode* parameterNode, FCDEffectParameterColor4* value, uint32 bucketIndex) { bool status = true; // Look for elements, they pre-empt everything else if (bucketIndex != FUDaeTextureChannel::UNKNOWN) { size_t originalSize = effectStandard->GetTextureCount(bucketIndex); FArchiveXML::ParseSimpleTextureParameter(effectStandard, parameterNode, bucketIndex); if (originalSize < effectStandard->GetTextureCount(bucketIndex)) { value->SetValue(FMVector4::One); return status; } } // Try to find a element xmlNode* colorNode = NULL; xmlNode* paramNode = FindChildByType(parameterNode, DAE_PARAMETER_ELEMENT); if (paramNode != NULL) { fm::string name = ReadNodeProperty(paramNode, DAE_REF_ATTRIBUTE); //If there's no reference attribute, read in the content. if (name.empty()) { colorNode = paramNode->children; if (!colorNode) { FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_MISSING_INPUT, paramNode->line); } else { name = ReadNodeContentFull(colorNode); if (name.empty()) { FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_MISSING_INPUT, colorNode->line); } AddAttribute(colorNode, DAE_SID_ATTRIBUTE, name); } } else { colorNode = paramNode; AddAttribute(colorNode, DAE_SID_ATTRIBUTE, name); } value->SetReference(name); value->SetReferencer(); //The parameter isn't linked here. } else { // Look for a element colorNode = FindChildByType(parameterNode, DAE_FXSTD_COLOR_ELEMENT); const char* content = ReadNodeContentDirect(colorNode); // Parse the color value and allow for an animation of it value->SetValue(FUStringConversion::ToVector4(content)); } FArchiveXML::LoadAnimatable(&value->GetValue(), colorNode); return status; } bool FArchiveXML::ParseFloatTextureParameter(FCDEffectStandard* effectStandard, xmlNode* parameterNode, FCDEffectParameterFloat* value, uint32 bucketIndex) { bool status = true; // Look for elements, they pre-empt everything else if (bucketIndex != FUDaeTextureChannel::UNKNOWN) { size_t originalSize = effectStandard->GetTextureCount(bucketIndex); FArchiveXML::ParseSimpleTextureParameter(effectStandard, parameterNode, bucketIndex); if (originalSize < effectStandard->GetTextureCount(bucketIndex)) { value->SetValue(1.0f); return status; } } // Next, look for a element xmlNode* floatNode = NULL; xmlNode* paramNode = FindChildByType(parameterNode, DAE_PARAMETER_ELEMENT); if (paramNode) { fm::string name = ReadNodeProperty(paramNode, DAE_REF_ATTRIBUTE); //If there's no reference attribute, read in the content. if (name.empty()) { floatNode = paramNode->children; if (!floatNode) { FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_MISSING_INPUT, paramNode->line); } else { name = ReadNodeContentFull(floatNode); if (name.empty()) { FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_MISSING_INPUT, floatNode->line); } AddAttribute(floatNode, DAE_SID_ATTRIBUTE, name); } } else { floatNode = paramNode; AddAttribute(floatNode, DAE_SID_ATTRIBUTE, name); } value->SetReference(name); value->SetReferencer(); } else { // Next, look for a element floatNode = FindChildByType(parameterNode, DAE_FXSTD_FLOAT_ELEMENT); const char* content = ReadNodeContentDirect(floatNode); // Parse the value and register it for an animation. value->SetValue(FUStringConversion::ToFloat(content)); } FArchiveXML::LoadAnimatable(&value->GetValue(), floatNode); return status; } bool FArchiveXML::ParseSimpleTextureParameter(FCDEffectStandard* effectStandard, xmlNode* parameterNode, uint32 bucketIndex) { FUAssert(bucketIndex != FUDaeTextureChannel::UNKNOWN, return false); bool status = true; // Parse in all the elements as standard effect samplers xmlNodeList samplerNodes; FindChildrenByType(parameterNode, DAE_FXSTD_TEXTURE_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 = effectStandard->AddTexture(bucketIndex); status &= (FArchiveXML::LoadTexture(texture, *itS)); if (!status) { SAFE_RELEASE(texture); } } } return status; } uint32 FArchiveXML::GetEffectParameterType(xmlNode* parameterNode) { // If the parent is bind_material, the format is slightly different, there is no children node. if (parameterNode->children == NULL) { xmlNode* parent = parameterNode->parent; if (IsEquivalent(parent->name, DAE_BINDMATERIAL_ELEMENT)) { // Find out of the type= ... what type of parameter to create. fm::string type = ReadNodeProperty(parameterNode, DAE_TYPE_ATTRIBUTE); if (IsEquivalent(type, DAE_FXCMN_BOOL_ELEMENT)) return FCDEffectParameter::BOOLEAN; else if (IsEquivalent(type, DAE_FXCMN_FLOAT_ELEMENT)) return FCDEffectParameter::FLOAT; else if (IsEquivalent(type, DAE_FXCMN_FLOAT2_ELEMENT)) return FCDEffectParameter::FLOAT2; else if (IsEquivalent(type, DAE_FXCMN_FLOAT3_ELEMENT)) return FCDEffectParameter::FLOAT3; else if (IsEquivalent(type, DAE_FXCMN_FLOAT4_ELEMENT)) return FCDEffectParameter::VECTOR; else if (IsEquivalent(type, DAE_FXCMN_FLOAT4X4_ELEMENT)) return FCDEffectParameter::MATRIX; else if (IsEquivalent(type, DAE_FXCMN_HALF_ELEMENT)) return FCDEffectParameter::FLOAT; else if (IsEquivalent(type, DAE_FXCMN_HALF2_ELEMENT)) return FCDEffectParameter::FLOAT2; else if (IsEquivalent(type, DAE_FXCMN_HALF3_ELEMENT)) return FCDEffectParameter::FLOAT3; else if (IsEquivalent(type, DAE_FXCMN_HALF4_ELEMENT)) return FCDEffectParameter::VECTOR; else if (IsEquivalent(type, DAE_FXCMN_HALF4X4_ELEMENT)) return FCDEffectParameter::MATRIX; else if (IsEquivalent(type, DAE_FXCMN_INT_ELEMENT)) return FCDEffectParameter::INTEGER; else if (IsEquivalent(type, DAE_FXCMN_SAMPLER1D_ELEMENT)) return FCDEffectParameter::SAMPLER; else if (IsEquivalent(type, DAE_FXCMN_SAMPLER2D_ELEMENT)) return FCDEffectParameter::SAMPLER; else if (IsEquivalent(type, DAE_FXCMN_SAMPLER3D_ELEMENT)) return FCDEffectParameter::SAMPLER; else if (IsEquivalent(type, DAE_FXCMN_SAMPLERCUBE_ELEMENT)) return FCDEffectParameter::SAMPLER; else if (IsEquivalent(type, DAE_FXCMN_SURFACE_ELEMENT)) return FCDEffectParameter::SURFACE; else if (IsEquivalent(type, DAE_FXCMN_STRING_ELEMENT)) return FCDEffectParameter::STRING; } } else { for (xmlNode* child = parameterNode->children; child != NULL; child = child->next) { if (child->type != XML_ELEMENT_NODE) continue; if (IsEquivalent(child->name, DAE_FXCMN_BOOL_ELEMENT)) return FCDEffectParameter::BOOLEAN; else if (IsEquivalent(child->name, DAE_FXCMN_FLOAT_ELEMENT)) return FCDEffectParameter::FLOAT; else if (IsEquivalent(child->name, DAE_FXCMN_FLOAT2_ELEMENT)) return FCDEffectParameter::FLOAT2; else if (IsEquivalent(child->name, DAE_FXCMN_FLOAT3_ELEMENT)) return FCDEffectParameter::FLOAT3; else if (IsEquivalent(child->name, DAE_FXCMN_FLOAT4_ELEMENT)) return FCDEffectParameter::VECTOR; else if (IsEquivalent(child->name, DAE_FXCMN_FLOAT4X4_ELEMENT)) return FCDEffectParameter::MATRIX; else if (IsEquivalent(child->name, DAE_FXCMN_HALF_ELEMENT)) return FCDEffectParameter::FLOAT; else if (IsEquivalent(child->name, DAE_FXCMN_HALF2_ELEMENT)) return FCDEffectParameter::FLOAT2; else if (IsEquivalent(child->name, DAE_FXCMN_HALF3_ELEMENT)) return FCDEffectParameter::FLOAT3; else if (IsEquivalent(child->name, DAE_FXCMN_HALF4_ELEMENT)) return FCDEffectParameter::VECTOR; else if (IsEquivalent(child->name, DAE_FXCMN_HALF4X4_ELEMENT)) return FCDEffectParameter::MATRIX; else if (IsEquivalent(child->name, DAE_FXCMN_INT_ELEMENT)) return FCDEffectParameter::INTEGER; else if (IsEquivalent(child->name, DAE_FXCMN_SAMPLER1D_ELEMENT)) return FCDEffectParameter::SAMPLER; else if (IsEquivalent(child->name, DAE_FXCMN_SAMPLER2D_ELEMENT)) return FCDEffectParameter::SAMPLER; else if (IsEquivalent(child->name, DAE_FXCMN_SAMPLER3D_ELEMENT)) return FCDEffectParameter::SAMPLER; else if (IsEquivalent(child->name, DAE_FXCMN_SAMPLERCUBE_ELEMENT)) return FCDEffectParameter::SAMPLER; else if (IsEquivalent(child->name, DAE_FXCMN_SURFACE_ELEMENT)) return FCDEffectParameter::SURFACE; else if (IsEquivalent(child->name, DAE_FXCMN_STRING_ELEMENT)) return FCDEffectParameter::STRING; } } FUError::Error(FUError::WARNING_LEVEL, FUError::ERROR_UNKNOWN_CHILD, parameterNode->line); return FCDEffectParameter::FLOAT; }