Open3D (C++ API)  0.19.0
mikktspace.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - Open3D: www.open3d.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.open3d.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 /* # MikkTSpace
9 A common standard for tangent space used in baking tools to produce normal maps.
10 More information can be found at http://www.mikktspace.com/.
11 https://github.com/mmikk/MikkTSpace [Oct 2025]
12 */
36 #ifndef __MIKKTSPACE_H__
37 #define __MIKKTSPACE_H__
38 
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 
43 /* Author: Morten S. Mikkelsen
44  * Version: 1.0
45  *
46  * The files mikktspace.h and mikktspace.c are designed to be
47  * stand-alone files and it is important that they are kept this way.
48  * Not having dependencies on structures/classes/libraries specific
49  * to the program, in which they are used, allows them to be copied
50  * and used as is into any tool, program or plugin.
51  * The code is designed to consistently generate the same
52  * tangent spaces, for a given mesh, in any tool in which it is used.
53  * This is done by performing an internal welding step and subsequently an
54  * order-independent evaluation of tangent space for meshes consisting of
55  * triangles and quads. This means faces can be received in any order and the
56  * same is true for the order of vertices of each face. The generated result
57  * will not be affected by such reordering. Additionally, whether degenerate
58  * (vertices or texture coordinates) primitives are present or not will not
59  * affect the generated results either. Once tangent space calculation is done
60  * the vertices of degenerate primitives will simply inherit tangent space from
61  * neighboring non degenerate primitives. The analysis behind this
62  * implementation can be found in my master's thesis which is available for
63  * download --> http://image.diku.dk/projects/media/morten.mikkelsen.08.pdf Note
64  * that though the tangent spaces at the vertices are generated in an
65  * order-independent way, by this implementation, the interpolated tangent space
66  * is still affected by which diagonal is chosen to split each quad. A sensible
67  * solution is to have your tools pipeline always split quads by the shortest
68  * diagonal. This choice is order-independent and works with mirroring. If these
69  * have the same length then compare the diagonals defined by the texture
70  * coordinates. XNormal which is a tool for baking normal maps allows you to
71  * write your own tangent space plugin and also quad triangulator plugin.
72  */
73 
74 typedef int tbool;
76 
77 typedef struct {
78  // Returns the number of faces (triangles/quads) on the mesh to be
79  // processed.
80  int (*m_getNumFaces)(const SMikkTSpaceContext* pContext);
81 
82  // Returns the number of vertices on face number iFace
83  // iFace is a number in the range {0, 1, ..., getNumFaces()-1}
84  int (*m_getNumVerticesOfFace)(const SMikkTSpaceContext* pContext,
85  const int iFace);
86 
87  // returns the position/normal/texcoord of the referenced face of vertex
88  // number iVert. iVert is in the range {0,1,2} for triangles and {0,1,2,3}
89  // for quads.
90  void (*m_getPosition)(const SMikkTSpaceContext* pContext,
91  float fvPosOut[],
92  const int iFace,
93  const int iVert);
94  void (*m_getNormal)(const SMikkTSpaceContext* pContext,
95  float fvNormOut[],
96  const int iFace,
97  const int iVert);
98  void (*m_getTexCoord)(const SMikkTSpaceContext* pContext,
99  float fvTexcOut[],
100  const int iFace,
101  const int iVert);
102 
103  // either (or both) of the two setTSpace callbacks can be set.
104  // The call-back m_setTSpaceBasic() is sufficient for basic normal mapping.
105 
106  // This function is used to return the tangent and fSign to the application.
107  // fvTangent is a unit length vector.
108  // For normal maps it is sufficient to use the following simplified version
109  // of the bitangent which is generated at pixel/vertex level. bitangent =
110  // fSign * cross(vN, tangent); Note that the results are returned unindexed.
111  // It is possible to generate a new index list But averaging/overwriting
112  // tangent spaces by using an already existing index list WILL produce
113  // INCRORRECT results. DO NOT! use an already existing index list.
114  void (*m_setTSpaceBasic)(const SMikkTSpaceContext* pContext,
115  const float fvTangent[],
116  const float fSign,
117  const int iFace,
118  const int iVert);
119 
120  // This function is used to return tangent space results to the application.
121  // fvTangent and fvBiTangent are unit length vectors and fMagS and fMagT are
122  // their true magnitudes which can be used for relief mapping effects.
123  // fvBiTangent is the "real" bitangent and thus may not be perpendicular to
124  // fvTangent. However, both are perpendicular to the vertex normal. For
125  // normal maps it is sufficient to use the following simplified version of
126  // the bitangent which is generated at pixel/vertex level. fSign =
127  // bIsOrientationPreserving ? 1.0f : (-1.0f); bitangent = fSign * cross(vN,
128  // tangent); Note that the results are returned unindexed. It is possible to
129  // generate a new index list But averaging/overwriting tangent spaces by
130  // using an already existing index list WILL produce INCRORRECT results. DO
131  // NOT! use an already existing index list.
132  void (*m_setTSpace)(const SMikkTSpaceContext* pContext,
133  const float fvTangent[],
134  const float fvBiTangent[],
135  const float fMagS,
136  const float fMagT,
137  const tbool bIsOrientationPreserving,
138  const int iFace,
139  const int iVert);
141 
143  SMikkTSpaceInterface* m_pInterface; // initialized with callback functions
144  void* m_pUserData; // pointer to client side mesh data etc. (passed as the
145  // first parameter with every interface call)
146 };
147 
148 // these are both thread safe!
150  const SMikkTSpaceContext*
151  pContext); // Default (recommended) fAngularThreshold is 180
152  // degrees (which means threshold disabled)
153 tbool genTangSpace(const SMikkTSpaceContext* pContext,
154  const float fAngularThreshold);
155 
156 // To avoid visual errors (distortions/unwanted hard edges in lighting), when
157 // using sampled normal maps, the normal map sampler must use the exact inverse
158 // of the pixel shader transformation. The most efficient transformation we can
159 // possibly do in the pixel shader is achieved by using, directly, the
160 // "unnormalized" interpolated tangent, bitangent and vertex normal: vT, vB and
161 // vN. pixel shader (fast transform out) vNout = normalize( vNt.x * vT + vNt.y *
162 // vB + vNt.z * vN ); where vNt is the tangent space normal. The normal map
163 // sampler must likewise use the interpolated and "unnormalized" tangent,
164 // bitangent and vertex normal to be compliant with the pixel shader. sampler
165 // does (exact inverse of pixel shader): float3 row0 = cross(vB, vN); float3
166 // row1 = cross(vN, vT); float3 row2 = cross(vT, vB); float fSign = dot(vT,
167 // row0)<0 ? -1 : 1; vNt = normalize( fSign * float3(dot(vNout,row0),
168 // dot(vNout,row1), dot(vNout,row2)) ); where vNout is the sampled normal in
169 // some chosen 3D space.
170 //
171 // Should you choose to reconstruct the bitangent in the pixel shader instead
172 // of the vertex shader, as explained earlier, then be sure to do this in the
173 // normal map sampler also. Finally, beware of quad triangulations. If the
174 // normal map sampler doesn't use the same triangulation of quads as your
175 // renderer then problems will occur since the interpolated tangent spaces will
176 // differ eventhough the vertex level tangent spaces match. This can be solved
177 // either by triangulating before sampling/exporting or by using the
178 // order-independent choice of diagonal for splitting quads suggested earlier.
179 // However, this must be used both by the sampler and your tools/rendering
180 // pipeline.
181 
182 #ifdef __cplusplus
183 }
184 #endif
185 
186 #endif
int tbool
Definition: mikktspace.h:74
tbool genTangSpace(const SMikkTSpaceContext *pContext, const float fAngularThreshold)
Definition: mikktspace.c:229
tbool genTangSpaceDefault(const SMikkTSpaceContext *pContext)
Definition: mikktspace.c:224
const char const char value recording_handle imu_sample void
Definition: K4aPlugin.cpp:250
const char const char value recording_handle imu_sample recording_handle uint8_t size_t data_size k4a_record_configuration_t config target_format k4a_capture_t capture_handle k4a_imu_sample_t imu_sample playback_handle k4a_logging_message_cb_t void min_level device_handle k4a_imu_sample_t timeout_in_ms capture_handle capture_handle capture_handle image_handle temperature_c int
Definition: K4aPlugin.cpp:474
Definition: mikktspace.h:142
SMikkTSpaceInterface * m_pInterface
Definition: mikktspace.h:143
void * m_pUserData
Definition: mikktspace.h:144
Definition: mikktspace.h:77