fbxcolladaelement.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /****************************************************************************************
  2. Copyright (C) 2015 Autodesk, Inc.
  3. All rights reserved.
  4. Use of this software is subject to the terms of the Autodesk license agreement
  5. provided at the time of installation or download, or which otherwise accompanies
  6. this software in either electronic or hard copy form.
  7. ****************************************************************************************/
  8. //! \file fbxcolladaelement.h
  9. #ifndef _FBXSDK_FILEIO_COLLADA_ELEMENT_H_
  10. #define _FBXSDK_FILEIO_COLLADA_ELEMENT_H_
  11. #include <fbxsdk.h>
  12. #include <fbxsdk/fbxsdk_nsbegin.h>
  13. // Utility functions to convert type to array tag used in COLLADA source element
  14. template <typename T>
  15. inline const FbxString TypeToArrayTag()
  16. {
  17. return COLLADA_FLOAT_ARRAY_STRUCTURE;
  18. }
  19. template <>
  20. inline const FbxString TypeToArrayTag<bool>()
  21. {
  22. return COLLADA_BOOL_ARRAY_STRUCTURE;
  23. }
  24. template <>
  25. inline const FbxString TypeToArrayTag<int>()
  26. {
  27. return COLLADA_INT_ARRAY_STRUCTURE;
  28. }
  29. template <>
  30. inline const FbxString TypeToArrayTag<FbxString>()
  31. {
  32. return COLLADA_NAME_ARRAY_STRUCTURE;
  33. }
  34. // Utility functions to convert type to parameter tag used in COLLADA source element
  35. template <typename T>
  36. inline const FbxString TypeToParameterTag()
  37. {
  38. return COLLADA_FLOAT_TYPE;
  39. }
  40. template <>
  41. inline const FbxString TypeToParameterTag<bool>()
  42. {
  43. return COLLADA_BOOL_TYPE;
  44. }
  45. template <>
  46. inline const FbxString TypeToParameterTag<int>()
  47. {
  48. return COLLADA_INT_TYPE;
  49. }
  50. template <>
  51. inline const FbxString TypeToParameterTag<FbxString>()
  52. {
  53. return COLLADA_NAME_TYPE;
  54. }
  55. //----------------------------------------------------------------------------//
  56. /** A struct for convenient access to the content of common COLLADA element.
  57. */
  58. struct ElementContentAccessor
  59. {
  60. ElementContentAccessor();
  61. ElementContentAccessor(xmlNode * pElement);
  62. virtual ~ElementContentAccessor();
  63. template <typename TYPE>
  64. bool GetNext(TYPE * pData)
  65. {
  66. return FromString(pData, mPointer, &mPointer);
  67. }
  68. template <typename TYPE>
  69. int GetArray(TYPE * pArray,
  70. int pSourceUnitOffset = 0, int pSourceUnitValidCount = 1, int pSourceUnitSize = 1,
  71. int pDestUnitOffset = 0, int pDestUnitValidCount = 1, int pDestUnitSize = 1,
  72. TYPE pDefaultValue = TYPE())
  73. {
  74. if (pArray)
  75. {
  76. return FromStringToArray(mPointer, pArray,
  77. pSourceUnitOffset, pSourceUnitValidCount, pSourceUnitSize,
  78. pDestUnitOffset, pDestUnitValidCount, pDestUnitSize, pDefaultValue);
  79. }
  80. return 0;
  81. }
  82. xmlChar * mContent;
  83. const char * mPointer;
  84. };
  85. //----------------------------------------------------------------------------//
  86. /** A struct for convenient access to the content of COLLADA source element.
  87. */
  88. template <typename TYPE>
  89. struct SourceElementContentAccessor : public ElementContentAccessor
  90. {
  91. SourceElementContentAccessor(xmlNode * pSourceElement)
  92. : mCount(0), mStride(1), mOffset(0)
  93. {
  94. bool lReadCount = true;
  95. xmlNode* lTechniqueElement = DAE_FindChildElementByTag(pSourceElement, COLLADA_TECHNIQUE_COMMON_ELEMENT);
  96. if (lTechniqueElement)
  97. {
  98. xmlNode* lAccessorElement = DAE_FindChildElementByTag(lTechniqueElement, COLLADA_ACCESSOR_STRUCTURE);
  99. FBX_ASSERT(lAccessorElement);
  100. if (!lAccessorElement)
  101. return;
  102. DAE_GetElementAttributeValue(lAccessorElement, COLLADA_COUNT_PROPERTY, mCount);
  103. DAE_GetElementAttributeValue(lAccessorElement, COLLADA_STRIDE_PROPERTY, mStride);
  104. DAE_GetElementAttributeValue(lAccessorElement, COLLADA_OFFSET_PROPERTY, mOffset);
  105. lReadCount = false;
  106. }
  107. xmlNode * lDataArrayElement = DAE_FindChildElementByTag(pSourceElement,
  108. TypeToArrayTag<TYPE>());
  109. // Some COLLADA exporters use IDREF_array instead of Name_array
  110. if (!lDataArrayElement && TypeToArrayTag<TYPE>() == COLLADA_NAME_ARRAY_STRUCTURE)
  111. lDataArrayElement = DAE_FindChildElementByTag(pSourceElement, COLLADA_IDREF_ARRAY_STRUCTURE);
  112. FBX_ASSERT(lDataArrayElement);
  113. if (lDataArrayElement && lReadCount)
  114. DAE_GetElementAttributeValue(lDataArrayElement, COLLADA_COUNT_PROPERTY, mCount);
  115. mContent = xmlNodeGetContent(lDataArrayElement);
  116. mPointer = (const char *)mContent;
  117. }
  118. int mCount;
  119. int mStride;
  120. int mOffset;
  121. };
  122. //----------------------------------------------------------------------------//
  123. /** Representing a common COLLADA element.
  124. */
  125. class ElementBase
  126. {
  127. public:
  128. enum
  129. {
  130. MATRIX_STRIDE = 16,
  131. };
  132. // The name of user property in FBX which is used to preserve the ID of COLLADA element
  133. static const char* smID_PROPERTY_NAME;
  134. /** Constructor & Destructor.
  135. */
  136. ElementBase();
  137. virtual ~ElementBase();
  138. /** Access for XML element.
  139. */
  140. void SetXMLElement(xmlNode * pElement) { mXMLElement = pElement; }
  141. xmlNode * GetXMLElement() const { return mXMLElement; }
  142. /** Get the ID of the element.
  143. * \return Return the ID string.
  144. */
  145. const FbxString & GetID() const;
  146. /** Get the unit of the element,
  147. * which takes effect in this element and its children elements.
  148. * \return Return the unit.
  149. */
  150. const FbxSystemUnit * GetUnit() const;
  151. private:
  152. xmlNode * mXMLElement;
  153. mutable FbxString * mID;
  154. mutable FbxSystemUnit * mUnit;
  155. };
  156. /** Convert from ID to URL, just add a prefix "#".
  157. * \param pID The ID string.
  158. * \return Return the URL string.
  159. */
  160. inline const FbxString URL(const FbxString & pID)
  161. {
  162. return FbxString("#") + pID;
  163. }
  164. /** Convert the array data to a source element under specific parent element.
  165. * \param pParentElement The parent element.
  166. * \param pID The ID of the new source element.
  167. * \param pData The array data.
  168. * \param pCount The length of the array.
  169. * \param pStride The stride of each unit in the array. For example, when you
  170. * export an array of FbxDouble3 of size 10, you convert it to a double array
  171. * of size 30 with a stride 3 and call this method.
  172. * \return The new source element.
  173. */
  174. template <typename T>
  175. xmlNode * AddSourceElement(xmlNode * pParentElement, const char * pID,
  176. const T * pData, int pCount, int pStride = 1)
  177. {
  178. FBX_ASSERT(pParentElement && pData);
  179. if (!pParentElement || !pData)
  180. return NULL;
  181. xmlNode * lSourceElement = DAE_AddChildElement(pParentElement, COLLADA_SOURCE_STRUCTURE);
  182. DAE_AddAttribute(lSourceElement, COLLADA_ID_PROPERTY, pID);
  183. FbxString lContent;
  184. const int lDataCount = pCount * pStride;
  185. for (int lIndex = 0; lIndex < lDataCount; ++lIndex)
  186. {
  187. lContent += ToString(pData[lIndex]);
  188. if (lIndex != lDataCount - 1)
  189. lContent += " ";
  190. }
  191. const FbxString lArrayID = FbxString(pID) + "-array";
  192. xmlNode * lArrayElement = DAE_AddChildElement(lSourceElement, TypeToArrayTag<T>(), lContent);
  193. DAE_AddAttribute(lArrayElement, COLLADA_ID_PROPERTY, lArrayID);
  194. DAE_AddAttribute(lArrayElement, COLLADA_COUNT_PROPERTY, lDataCount);
  195. xmlNode * lTechniqueCommonElement = DAE_AddChildElement(lSourceElement,
  196. COLLADA_TECHNIQUE_COMMON_ELEMENT);
  197. xmlNode * lAccessElement = DAE_AddChildElement(lTechniqueCommonElement,
  198. COLLADA_ACCESSOR_STRUCTURE);
  199. DAE_AddAttribute(lAccessElement, COLLADA_SOURCE_PROPERTY, URL(lArrayID));
  200. DAE_AddAttribute(lAccessElement, COLLADA_COUNT_PROPERTY, pCount);
  201. DAE_AddAttribute(lAccessElement, COLLADA_STRIDE_PROPERTY, pStride);
  202. for (int lStrideIndex = 0; lStrideIndex < pStride; ++lStrideIndex)
  203. {
  204. xmlNode * lParamElement = DAE_AddChildElement(lAccessElement, COLLADA_PARAMETER_STRUCTURE);
  205. DAE_AddAttribute(lParamElement, COLLADA_TYPE_PROPERTY, TypeToParameterTag<T>());
  206. }
  207. return lSourceElement;
  208. }
  209. /** Populate the layer element with direct array and return index array for later use.
  210. * \param pLayerElement The layer element to be populated.
  211. * \param pSourceElement The source element containing the direct array data.
  212. * \param pSize The count of double data of direct array element.
  213. * \return Return the index array of the layer element.
  214. */
  215. template <typename TYPE> FbxLayerElementArray * PopulateLayerElementDirectArray(FbxLayerElement * pLayerElement, xmlNode * pSourceElement, int pSize)
  216. {
  217. SourceElementContentAccessor<TYPE> lSourceElementAccessor(pSourceElement);
  218. FbxLayerElementTemplate<TYPE> * lLayerElement = (FbxLayerElementTemplate<TYPE> *)pLayerElement;
  219. lLayerElement->SetMappingMode(FbxLayerElement::eByPolygonVertex);
  220. lLayerElement->SetReferenceMode(FbxLayerElement::eIndexToDirect);
  221. lLayerElement->GetDirectArray().SetCount(lSourceElementAccessor.mCount);
  222. TYPE * lArray = NULL;
  223. lArray = lLayerElement->GetDirectArray().GetLocked(lArray);
  224. lSourceElementAccessor.GetArray((double *)lArray, 0, pSize,
  225. lSourceElementAccessor.mStride, 0, pSize, sizeof(TYPE)/sizeof(double), 1.0);
  226. lLayerElement->GetDirectArray().Release(&lArray, lArray);
  227. return &(lLayerElement->GetIndexArray());
  228. }
  229. #include <fbxsdk/fbxsdk_nsend.h>
  230. #endif /* _FBXSDK_FILEIO_COLLADA_ELEMENT_H_ */