1/****************************************************************************************
2
3 Copyright (C) 2015 Autodesk, Inc.
4 All rights reserved.
5
6 Use of this software is subject to the terms of the Autodesk license agreement
7 provided at the time of installation or download, or which otherwise accompanies
8 this software in either electronic or hard copy form.
9
10****************************************************************************************/
11
12//! \file fbxgeometryconverter.h
13#ifndef _FBXSDK_UTILS_GEOMETRY_CONVERTER_H_
14#define _FBXSDK_UTILS_GEOMETRY_CONVERTER_H_
15
16#include <fbxsdk/fbxsdk_def.h>
17
18#include <fbxsdk/core/base/fbxarray.h>
19
20#include <fbxsdk/fbxsdk_nsbegin.h>
21
22class FbxManager;
23class FbxMesh;
24class FbxPatch;
25class FbxNurbs;
26class FbxNurbsSurface;
27class FbxNurbsCurve;
28class FbxWeightedMapping;
29class FbxSurfaceEvaluator;
30class FbxScene;
31class FbxNode;
32class FbxNodeAttribute;
33class FbxGeometry;
34
35/**
36* This class provides the functionality to convert geometry nodes
37* attributes (FbxMesh, FbxNurbs and FbxPatch) and mainly focuses on the two
38* major categories: Triangulation and conversion between NURBS and Patches surfaces.
39* \nosubgrouping
40*/
41class FBXSDK_DLL FbxGeometryConverter
42{
43public:
44 /** \name Triangulation Utilities */
45 //@{
46 /** Triangulate all node attributes in the scene that can be triangulated.
47 * \param pScene The scene to iterate through to triangulate meshes.
48 * \param pReplace If \c true, replace the original meshes with the new triangulated meshes on all the nodes, and delete the original meshes. Otherwise, original meshes are left untouched.
49 * \param pLegacy If \c true, use legacy triangulation method that does not support holes in geometry. Provided for backward compatibility.
50 * \return \c true if all node attributes that can be triangulated were triangulated successfully.
51 * \remark The function will still iterate through all meshes regardless if one fails to triangulate, but will return false in that case. This function
52 * currently only supports node attribute of type eMesh, ePatch, eNurbs or eNurbsSurface. */
53 bool Triangulate(FbxScene* pScene, bool pReplace, bool pLegacy=false);
54
55 /** Triangulate a node attribute, if supported, and preserve the skins and shapes animation channels.
56 * \param pNodeAttribute Pointer to the node containing the geometry to triangulate.
57 * \param pReplace If \c true, replace the original geometry with the new triangulated geometry on the nodes, and delete the original geometry.
58 * Otherwise, the original geometry is left untouched, the new one is added to the nodes, and becomes the default one.
59 * \param pLegacy If \c true, use legacy triangulation method that does not support holes in geometry. Provided for backward compatibility.
60 * \return The newly created node attribute if successful, otherwise NULL. If node attribute type is not supported by triangulation, it returns the original node attribute.
61 * \remark This function currently only supports node attribute of type eMesh, ePatch, eNurbs or eNurbsSurface. If the node attribute does not support triangulation,
62 * or if it is already triangulated, this function will return pNodeAttribute. */
63 FbxNodeAttribute* Triangulate(FbxNodeAttribute* pNodeAttribute, bool pReplace, bool pLegacy=false);
64
65 /** Compute a "vertex-correspondence" table that helps passing from source to destination geometry.
66 * \param pSrcGeom Pointer to the source geometry.
67 * \param pDstGeom Pointer to the destination geometry.
68 * \param pSrcToDstWeightedMapping Pointer to the weighted mapping table.
69 * \param pSwapUV Set to \c true to swap UVs.
70 * \return \c true on success, \c false if the function fails to compute the correspondence.
71 * \remark Skins and shapes are also converted to fit the alternate geometry. */
72 bool ComputeGeometryControlPointsWeightedMapping(FbxGeometry* pSrcGeom, FbxGeometry* pDstGeom, FbxWeightedMapping* pSrcToDstWeightedMapping, bool pSwapUV=false);
73 //@}
74
75 /**
76 * \name Geometry Conversion
77 */
78 //@{
79 /** Convert from patch to nurb.
80 * \param pPatch Pointer to the patch to convert.
81 * \return Created nurb or \c NULL if the conversion fails.
82 * \remarks The patch must be of type eBSpline, eBezier or eLinear.
83 */
84 FbxNurbs* ConvertPatchToNurbs(FbxPatch *pPatch);
85
86 /** Convert a patch contained in a node to a nurb. Use this function to preserve the patch's
87 * skins and shapes animation channels.
88 * \param pNode Pointer to the node containing the patch.
89 * \return \c true on success, \c false if the node attribute is not a patch.
90 * \remarks The patch must be of type eBSpline, eBezier or eLinear.
91 */
92 bool ConvertPatchToNurbsInPlace(FbxNode* pNode);
93
94 /** Convert a patch to nurb surface.
95 * \param pPatch Pointer to the patch to convert.
96 * \return Created nurb surface or \c NULL if conversion fails.
97 * \remarks The patch must be of type eBSpline, eBezier or eLinear.
98 */
99 FbxNurbsSurface* ConvertPatchToNurbsSurface(FbxPatch *pPatch);
100
101 /** Convert a patch contained in a node to a nurb surface. Use this function to preserve
102 * the patch's skins and shapes animation channels.
103 * \param pNode Pointer to the node containing the patch.
104 * \return \c true on success, \c false if the node attribute is not a patch.
105 * \remarks The patch must be of type eBSpline, eBezier or eLinear.
106 */
107 bool ConvertPatchToNurbsSurfaceInPlace(FbxNode* pNode);
108
109 /** Convert a FbxNurbs to a FbxNurbsSurface
110 * \param pNurbs Pointer to the original nurb
111 * \return A FbxNurbsSurface that is equivalent to the original nurb.
112 */
113 FbxNurbsSurface* ConvertNurbsToNurbsSurface( FbxNurbs* pNurbs );
114
115 /** Convert a FbxNurbsSurface to a FbxNurbs
116 * \param pNurbs Pointer to the original nurbs surface
117 * \return A FbxNurbs that is equivalent to the original nurbs surface.
118 */
119 FbxNurbs* ConvertNurbsSurfaceToNurbs( FbxNurbsSurface* pNurbs );
120
121 /** Convert a nurb, contained in a node, to a nurbs surface. Use this function to preserve
122 * the nurb's skins and shapes animation channels.
123 * \param pNode Pointer to the node containing the nurb.
124 * \return \c true on success, \c false otherwise
125 */
126 bool ConvertNurbsToNurbsSurfaceInPlace(FbxNode* pNode);
127
128 /** Convert a nurb contained in a node to a nurbs surface. Use this function to preserve
129 * the nurb's skins and shapes animation channels.
130 * \param pNode Pointer to the node containing the nurbs surface.
131 * \return \c true on success, \c false otherwise
132 */
133 bool ConvertNurbsSurfaceToNurbsInPlace(FbxNode* pNode);
134 //@}
135
136 /**
137 * \name Nurb UV and Links Swapping
138 */
139 //@{
140 /** Flip UV and/or skin clusters of a nurb.
141 * \param pNurbs Pointer to the Source nurb.
142 * \param pSwapUV Set to \c true to swap the UVs.
143 * \param pSwapClusters Set to \c true to swap the control point indices of clusters.
144 * \return A flipped FbxNurbs, or \c NULL if the function fails.
145 */
146 FbxNurbs* FlipNurbs(FbxNurbs* pNurbs, bool pSwapUV, bool pSwapClusters);
147
148 /** Flip UV and/or skin clusters of a nurb surface.
149 * \param pNurbs Pointer to the Source nurb surface.
150 * \param pSwapUV Set to \c true to swap the UVs.
151 * \param pSwapClusters Set to \c true to swap the control point indices of clusters.
152 * \return A flipped FbxNurbsSurface, or \c NULL if the function fails.
153 */
154 FbxNurbsSurface* FlipNurbsSurface(FbxNurbsSurface* pNurbs, bool pSwapUV, bool pSwapClusters);
155 //@}
156
157 /**
158 * \name Normals By Polygon Vertex Emulation
159 */
160 //@{
161 /** Emulate normals by polygon vertex mode for a mesh.
162 * \param pMesh Pointer to the mesh object.
163 * \return \c true on success, \c false if the number of normals in the
164 * mesh and in its associated shapes don't match the number of polygon
165 * vertices.
166 * \remarks For applications that only supports normals by control points,
167 * this function duplicates control points to equal the
168 * number of polygon vertices. skins and shapes are also converted.
169 * As preconditions:
170 * -# polygons must have been created
171 * -# the number of normals in the mesh and in its associated shapes must match the
172 * number of polygon vertices.
173 */
174 bool EmulateNormalsByPolygonVertex(FbxMesh* pMesh);
175
176 /** Create edge smoothing information from polygon-vertex mapped normals.
177 * Existing smoothing information is removed and edge data is created if
178 * none exists on the mesh.
179 * \param pMesh The mesh used to generate edge smoothing.
180 * \return \c true on success, \c false otherwise.
181 * \remarks The edge smoothing data is placed on Layer 0 of the mesh.
182 * Normals do not need to be on Layer 0, since the first layer with
183 * per polygon vertex normals is used.
184 */
185 bool ComputeEdgeSmoothingFromNormals( FbxMesh* pMesh ) const;
186
187 /** Convert edge smoothing to polygon smoothing group.
188 * Existing smoothing information is replaced.
189 *
190 * \param pMesh The mesh that contains the smoothing to be converted.
191 * \param pIndex The index of the layer smoothing to be converted.
192 * \return \c true on success, \c false otherwise.
193 * \remarks The smoothing group is bitwise. Each bit of the integer represents
194 * one smoothing group. Therefore, there is a maximum of 32 smoothing groups.
195 */
196 bool ComputePolygonSmoothingFromEdgeSmoothing( FbxMesh* pMesh, int pIndex=0 ) const;
197
198 /** Convert polygon smoothing group to edge smoothing.
199 * Existing smoothing information is replaced.
200 *
201 * \param pMesh The mesh that contains the smoothing to be converted.
202 * \param pIndex The index of the layer smoothing to be converted
203 * \return \c true on success, \c false otherwise.
204 */
205 bool ComputeEdgeSmoothingFromPolygonSmoothing( FbxMesh* pMesh, int pIndex=0 ) const;
206 //@}
207
208 /** \name Split Mesh Per Materials */
209 //@{
210 /** Split all the mesh in the scene per material.
211 * \param pScene The scene to iterate through to split meshes.
212 * \param pReplace If \c true, replace the original mesh with new ones and delete the original meshes, but *only* if they got split into multiple meshes, otherwise they are left untouched.
213 * \return \c true if all splitable mesh were successfully split, \c false otherwise.
214 * \remark The function will still iterate through all meshes regardless if one fails to split, but will return false in that case. */
215 bool SplitMeshesPerMaterial(FbxScene* pScene, bool pReplace);
216
217 /** Split mesh per material.
218 * \param pMesh The mesh that will be split if it has multiple materials assigned.
219 * \param pReplace If \c true, replace the original mesh with new one and delete the original mesh, but *only* if they got split into multiple meshes, otherwise left untouched.
220 * \return \c true on success, \c false otherwise.
221 * \remark The function will fail if the mapped material is not per face (FbxLayerElement::eByPolygon) or if a material is multi-layered. It will create as many meshes as
222 * there are materials applied to it. If one mesh have some polygons with material A, some polygons with material B, and some polygons with NO material, 3 meshes distinct
223 * will be created. The newly created meshes will be automatically attached to the same FbxNode that holds the original FbxMesh. If the original mesh have tangents, they will
224 * be regenerated on the new meshes. */
225 bool SplitMeshPerMaterial(FbxMesh* pMesh, bool pReplace);
226 //@}
227
228 /** Re-parent nodes at root node level under a new node to re-center them at world center.
229 * Basically, this function calculates the scene bounding box in world coordinates, and test if the center of that bounding box distance from the
230 * world center is larger or equal than the threshold. If true, a new node with the proper negative offset position will become the new parent of all nodes at root node level.
231 * \param pScene The scene to process.
232 * \param pThreshold Threshold at which all nodes will be re-centered.
233 * \return \c true if any nodes were re-centered, otherwise \c false. */
234 bool RecenterSceneToWorldCenter(FbxScene* pScene, FbxDouble pThreshold);
235
236 /**
237 * Merge multiple meshes to one mesh.
238 * The method will merge:
239 * a) mesh vertex;
240 * b) mesh polygon;
241 * c) mesh edge;
242 * d) all mesh elements; only the layer 0 elements is merged.
243 * e) if there are skins for old mesh, merge these skins. The new skin clusters link to old skeletons.
244 *
245 * \param pMeshNodes FBX nodes that hold multiple meshes. These meshes will be merged.
246 * \param pNodeName Name of new mesh node.
247 * \param pScene The scene that will contain the new mesh node.
248 * \return The new mesh node if merge successfully, otherwise NULL is returned.
249 * \remarks This method creates a new mesh, leaving the source mesh unchanged.
250 * The transform of new mesh node is: translate (0, 0, 0), rotation (0, 0, 0), scale (1, 1, 1).
251 * For layer element material, normal, smoothing, UV set, vertex color, binormal, tangent and polygon group,
252 * if any mesh misses these element, the merge for this kind of element is skipped.
253 * For layer element crease, hole, visibility and user data, if any mesh has such element, the kind of element
254 * will be merged. The missing element will be filled with default values.
255 * For meshes with skin binding, if the pose of frame 0 is different with bind pose, the new mesh will be distorted.
256 */
257 FbxNode* MergeMeshes(FbxArray<FbxNode*>& pMeshNodes, const char* pNodeName, FbxScene* pScene);
258
259 /**
260 * Cleanup or remove degenerated meshes.
261 * \param pScene The scene to process.
262 * \param pAffectedNodes The list of nodes that have been affected by this operation.
263 * \remarks If the cleaned-up mesh becomes invalid, it is removed entirely.
264 */
265 void RemoveBadPolygonsFromMeshes(FbxScene* pScene, FbxArray<FbxNode*>* pAffectedNodes = NULL);
266
267/*****************************************************************************************************************************
268** WARNING! Anything beyond these lines is for internal use, may not be documented and is subject to change without notice! **
269*****************************************************************************************************************************/
270#ifndef DOXYGEN_SHOULD_SKIP_THIS
271 FbxGeometryConverter(FbxManager* pManager);
272 ~FbxGeometryConverter();
273
274private:
275 FbxMesh* TriangulateMeshInternal(const FbxMesh* pMesh);
276 FbxMesh* TriangulateMeshInternalLegacy(const FbxMesh* pMesh);
277 FbxMesh* TriangulatePatchInternal(const FbxPatch* pPatch);
278 FbxMesh* TriangulateNurbsInternal(const FbxNurbs* pNurbs);
279
280 bool AddAlternateGeometry(FbxNode* pNode, FbxGeometry* pSrcGeom, FbxGeometry* pAltGeom, FbxWeightedMapping* pSrcToAltWeightedMapping, bool pConvertDeformations);
281 bool ConvertGeometryAnimation(FbxNode* pNode, FbxGeometry* pSrcGeom, FbxGeometry* pDstGeom);
282 void ReplaceNodeAttribute(FbxNode* pNode, FbxNodeAttribute* pNewNodeAttr);
283 bool AddTriangulatedMeshGeometry(FbxNode* pNode, int pUVStepCoeff);
284 bool CreateAndCopyLayerElement(FbxMesh *pNewMesh, FbxMesh *pRefMesh);
285 bool SetLayerElements(FbxMesh *pNewMesh, FbxMesh *pMesh, int pPolygonIndex, int pPolyPointIndex, int pLoopIndex, bool pIsSearched, bool pIsEndPolygon);
286
287 /** FbxTriangulation
288 * \param Index Output array of triangle indices
289 * \param pNumSide Input number of sides of the polygon to triangulate
290 * -- Triangulation algorithm is strip, Sorting vertex index for strip in clockwise.
291 *
292 * 2 3 4
293 * 0----------0---------0
294 * / `
295 * / ` 5
296 * 1 / 0
297 * 0 /
298 * ` /
299 * ` /
300 * 0 0-----0-------------0 6
301 * 7
302 * The result of this one will be [{0,1,2},{2,3,0},{0,3,7},{3,4,7},{7,4,6},{4,5,6}]
303 */
304 static void FbxTriangulation(int *Index, int pNumSide);
305
306 bool ComputePatchToMeshControlPointsWeightedMapping(FbxPatch* pSrcPatch, FbxMesh* pDstMesh, FbxWeightedMapping* pMapping, bool pSwapUV=false);
307 bool ComputeNurbsToMeshControlPointsWeightedMapping(FbxNurbsSurface* pSrcNurbs, FbxMesh* pDstMesh, FbxWeightedMapping* pMapping, bool pRescaleUVs=false, bool pSwapUV=false);
308
309 void InitializeWeightInControlPoints(FbxGeometryBase* pGeometry);
310 void InitializeWeightInNormals(FbxLayerContainer* pLayerContainer);
311 void TriangulateContinuousSurface(FbxMesh* pMesh, FbxSurfaceEvaluator* pSurface, FbxUInt pPointCountX, FbxUInt pPointCountY, bool ClockWise=false);
312 void CheckForZeroWeightInShape(FbxGeometry *pGeometry);
313 FbxMesh* CreateMeshFromParametricSurface(const FbxGeometry* pGeometry);
314 FbxNurbs* CreateNurbsFromPatch(FbxPatch* pPatch);
315 FbxNurbsSurface* CreateNurbsSurfaceFromPatch(FbxPatch* pPatch);
316
317 void ConvertShapes(const FbxGeometry* pSource, FbxGeometry* pDestination, FbxSurfaceEvaluator* pEvaluator, int pUCount, int pVCount);
318 void ConvertShapes(const FbxGeometry* pSource, FbxGeometry* pDestination, FbxWeightedMapping* pSourceToDestinationMapping);
319 void ConvertClusters(const FbxGeometry* pSource, FbxGeometry* pDestination, FbxWeightedMapping* pSourceToDestinationMapping);
320 void ConvertClusters(FbxArray<FbxCluster*> const& pSourceClusters, int pSourceControlPointsCount, FbxArray<FbxCluster*>& pDestinationClusters, int pDestinationControlPointsCount, FbxWeightedMapping* pSourceToDestinationMapping);
321 void BuildClusterToSourceMapping(FbxArray<FbxCluster*> const& pSourceClusters, FbxWeightedMapping* pClusterToSourceMapping);
322 void CheckClusterToSourceMapping(FbxWeightedMapping* pClusterToSourceMapping);
323 void ConvertCluster(int pSourceClusterIndex, FbxWeightedMapping* pClusterToSourceMapping, FbxWeightedMapping* pSourceToDestinationMapping, FbxCluster* pDestinationCluster);
324 void DuplicateControlPoints(FbxArray<FbxVector4>& pControlPoints, FbxArray<int>& pPolygonVertices);
325 void UpdatePolygon(FbxMesh *pNewMesh, FbxMesh const *pRefMesh, int pPolygonIndex, int* pNewIndex, int &pVerticeIndexMeshTriangulated, int &pPolygonIndexMeshTriangulated);
326 void UpdatePolygon(FbxMesh *pNewMesh, FbxMesh const *pRefMesh, int pPolygonIndex, int* pNewIndex, int &pVerticeIndexMeshTriangulated, int &pPolygonIndexMeshTriangulated, int pTriangleNum);
327 void ResizePolygon(FbxMesh *pNewMesh, int pNewCountVertices = 0, int pNewCountPolygons =0, bool pClearFlag = true);
328
329 template <class T1, class T2> void ConvertNurbs(T1* pNewNurbs, T2* pOldNurb);
330
331 bool CopyAnimationCurves(FbxNode* pNode, FbxGeometry* pNewGeometry);
332 bool FlipNurbsCurve(FbxNurbsCurve* pCurve) const;
333 void FlipControlPoints(FbxGeometryBase* pPoints, int pUCount, int pVCount) const;
334 bool ConvertMaterialReferenceMode(FbxMesh* pMeshRef) const;
335 void RevertMaterialReferenceModeConversion(FbxMesh* pMeshRef) const;
336
337 FbxManager* mManager;
338
339 friend class FbxWriter3ds;
340#endif /* !DOXYGEN_SHOULD_SKIP_THIS *****************************************************************************************/
341};
342
343#include <fbxsdk/fbxsdk_nsend.h>
344
345#endif /* _FBXSDK_UTILS_GEOMETRY_CONVERTER_H_ */
346