HDK
Main Page
Related Pages
Modules
Namespaces
Classes
Files
Examples
File List
File Members
All
Classes
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Friends
Macros
Groups
Pages
GU_MikkT.h
Go to the documentation of this file.
1
/*
2
* PROPRIETARY INFORMATION. This software is proprietary to
3
* Side Effects Software Inc., and is not to be reproduced,
4
* transmitted, or disclosed in any way without written permission.
5
*
6
* NAME: GU_MikkT.C
7
*
8
* COMMENTS: contains an implementation of Morten Mikkelsen's tangent space
9
* generation for normal mapping as well as an GU interface to the
10
* generator.
11
*/
12
13
/*
14
* Based on file mikktspace/mikktspace.c
15
*/
16
17
#ifndef __GU_MIKKTSPACE_H__
18
#define __GU_MIKKTSPACE_H__
19
20
#include "
GU_API.h
"
21
#include <
GA/GA_Handle.h
>
22
#include <
UT/UT_Vector3.h
>
23
24
namespace
GU
25
{
26
27
#define TFALSE 0
28
#define TTRUE 1
29
30
#define INTERNAL_RND_SORT_SEED 39871946
31
32
/* Based on the original source code in mikktspace.h and mikktspace.c
33
* and labeled as Version: 1.0, authored by Morten S. Mikkelsen.
34
* These files implement the thesis work described in:
35
* http://image.diku.dk/projects/media/morten.mikkelsen.08.pdf
36
*
37
* The original source code contains the following comments which are included
38
* here as a reminder that the algorithm a convention that is used across
39
* different digital content creation tool and needs to adhere to these
40
* conventions for correct interoperability.
41
*
42
* The files mikktspace.h and mikktspace.c are designed to be
43
* stand-alone files and it is important that they are kept this way.
44
* Not having dependencies on structures/classes/libraries specific
45
* to the program, in which they are used, allows them to be copied
46
* and used as is into any tool, program or plugin.
47
* The code is designed to consistently generate the same
48
* tangent spaces, for a given mesh, in any tool in which it is used.
49
* This is done by performing an internal welding step and subsequently an
50
* order-independent evaluation of tangent space for meshes consisting of
51
* triangles and quads. This means faces can be received in any order and the
52
* same is true for the order of vertices of each face. The generated result
53
* will not be affected by such reordering. Additionally, whether degenerate
54
* (vertices or texture coordinates) primitives are present or not will not
55
* affect the generated results either. Once tangent space calculation is done
56
* the vertices of degenerate primitives will simply inherit tangent space from
57
* neighboring non degenerate primitives. The analysis behind this
58
* implementation can be found in my master's thesis which is available for
59
* download --> http://image.diku.dk/projects/media/morten.mikkelsen.08.pdf Note
60
* that though the tangent spaces at the vertices are generated in an
61
* order-independent way, by this implementation, the interpolated tangent space
62
* is still affected by which diagonal is chosen to split each quad. A sensible
63
* solution is to have your tools pipeline always split quads by the shortest
64
* diagonal. This choice is order-independent and works with mirroring. If these
65
* have the same length then compare the diagonals defined by the texture
66
* coordinates. XNormal which is a tool for baking normal maps allows you to
67
* write your own tangent space plugin and also quad triangulator plugin.
68
*/
69
70
typedef
int
tbool
;
71
typedef
struct
SMikkTSpaceContext
SMikkTSpaceContext
;
72
73
typedef
struct
74
{
75
// Returns the number of faces (triangles/quads) on the mesh to be
76
// processed.
77
int
(*m_getNumFaces)(
const
SMikkTSpaceContext
*pContext);
78
79
// Returns the number of vertices on face number iFace
80
// iFace is a number in the range {0, 1, ..., getNumFaces()-1}
81
int
(*m_getNumVerticesOfFace)(
82
const
SMikkTSpaceContext
*pContext,
83
const
int
iFace);
84
85
// returns the position/normal/texcoord of the referenced face of vertex
86
// number iVert. iVert is in the range {0,1,2} for triangles and {0,1,2,3}
87
// for quads.
88
void
(*m_getPosition)(
89
const
SMikkTSpaceContext
*pContext,
90
float
fvPosOut[],
91
const
int
iFace,
92
const
int
iVert);
93
void
(*m_getNormal)(
94
const
SMikkTSpaceContext
*pContext,
95
float
fvNormOut[],
96
const
int
iFace,
97
const
int
iVert);
98
void
(*m_getTexCoord)(
99
const
SMikkTSpaceContext
*pContext,
100
float
fvTexcOut[],
101
const
int
iFace,
102
const
int
iVert);
103
104
// either (or both) of the two setTSpace callbacks can be set.
105
// The call-back m_setTSpaceBasic() is sufficient for basic normal mapping.
106
107
// This function is used to return the tangent and fSign to the application.
108
// fvTangent is a unit length vector.
109
// For normal maps it is sufficient to use the following simplified version
110
// of the bitangent which is generated at pixel/vertex level. bitangent =
111
// fSign * cross(vN, tangent); Note that the results are returned unindexed.
112
// It is possible to generate a new index list But averaging/overwriting
113
// tangent spaces by using an already existing index list WILL produce
114
// INCRORRECT results. DO NOT! use an already existing index list.
115
void
(*m_setTSpaceBasic)(
116
const
SMikkTSpaceContext
*pContext,
117
const
float
fvTangent[],
118
const
float
fSign,
119
const
int
iFace,
120
const
int
iVert);
121
122
// This function is used to return tangent space results to the application.
123
// fvTangent and fvBiTangent are unit length vectors and fMagS and fMagT are
124
// their true magnitudes which can be used for relief mapping effects.
125
// fvBiTangent is the "real" bitangent and thus may not be perpendicular to
126
// fvTangent. However, both are perpendicular to the vertex normal. For
127
// normal maps it is sufficient to use the following simplified version of
128
// the bitangent which is generated at pixel/vertex level. fSign =
129
// bIsOrientationPreserving ? 1.0f : (-1.0f); bitangent = fSign * cross(vN,
130
// tangent); Note that the results are returned unindexed. It is possible to
131
// generate a new index list But averaging/overwriting tangent spaces by
132
// using an already existing index list WILL produce INCRORRECT results. DO
133
// NOT! use an already existing index list.
134
void
(*m_setTSpace)(
135
const
SMikkTSpaceContext
*pContext,
136
const
float
fvTangent[],
137
const
float
fvBiTangent[],
138
const
float
fMagS,
139
const
float
fMagT,
140
const
tbool
bIsOrientationPreserving,
141
const
int
iFace,
142
const
int
iVert);
143
144
int
(*m_getPositionIndex)(
145
const
SMikkTSpaceContext
*pContext,
146
const
int
iVert);
147
int
(*m_getPositionVertex)(
148
const
SMikkTSpaceContext
*pContext,
149
const
int
iPoint,
150
const
int
iVert);
151
int
(*m_getPositionVertices)(
152
const
SMikkTSpaceContext
*pContext,
153
const
int
iPoint);
154
int
(*m_getPositionFaces)(
155
const
SMikkTSpaceContext
*pContext,
156
const
int
iPoint);
157
void
(*m_getPositionFacesArr)(
158
const
SMikkTSpaceContext
*pContext,
159
const
int
iPoint,
160
int
*&faces);
161
void
(*m_addPositionFace)(
162
const
SMikkTSpaceContext
*pContext,
163
const
int
iPoint,
164
int
face);
165
void
(*m_setPointFaceMapSize)(
166
const
SMikkTSpaceContext
*pContext,
167
const
int
size
);
168
169
// This flag is used to set whether or not UT_Hashmaps will be used when
170
// handling tangent space assignments for degenerate triangles
171
tbool
m_useHashmap
;
172
173
// This flag is used to set whether or not a point cache will be used
174
// when handling vertex merging. The point cache is expected to be
175
// set-up before calling genTangSpace() by calling initCache()
176
// from MikkTUserData
177
tbool
m_usePointCache
;
178
179
// This flag is used to set whether or not a point to face map will be
180
// used when building a list of neighboring triangles
181
tbool
m_usePointFaceMap
;
182
}
SMikkTSpaceInterface
;
183
184
struct
SMikkTSpaceContext
185
{
186
SMikkTSpaceInterface
*
m_pInterface
;
// initialized with callback functions
187
void
*
m_pUserData
;
// pointer to client side mesh data etc. (passed as the
188
// first parameter with every interface call)
189
};
190
191
// these are both thread safe!
192
GU_API
193
tbool
genTangSpaceDefault
(
194
const
SMikkTSpaceContext
195
*pContext);
// Default (recommended) fAngularThreshold is 180
196
// degrees (which means threshold disabled)
197
GU_API
198
tbool
genTangSpace
(
199
const
SMikkTSpaceContext
*pContext,
200
const
float
fAngularThreshold);
201
202
// To avoid visual errors (distortions/unwanted hard edges in lighting), when
203
// using sampled normal maps, the normal map sampler must use the exact inverse
204
// of the pixel shader transformation. The most efficient transformation we can
205
// possibly do in the pixel shader is achieved by using, directly, the
206
// "unnormalized" interpolated tangent, bitangent and vertex normal: vT, vB and
207
// vN. pixel shader (fast transform out) vNout = normalize( vNt.x * vT + vNt.y *
208
// vB + vNt.z * vN ); where vNt is the tangent space normal. The normal map
209
// sampler must likewise use the interpolated and "unnormalized" tangent,
210
// bitangent and vertex normal to be compliant with the pixel shader. sampler
211
// does (exact inverse of pixel shader): float3 row0 = cross(vB, vN); float3
212
// row1 = cross(vN, vT); float3 row2 = cross(vT, vB); float fSign = dot(vT,
213
// row0)<0 ? -1 : 1; vNt = normalize( fSign * float3(dot(vNout,row0),
214
// dot(vNout,row1), dot(vNout,row2)) ); where vNout is the sampled normal in
215
// some chosen 3D space.
216
//
217
// Should you choose to reconstruct the bitangent in the pixel shader instead
218
// of the vertex shader, as explained earlier, then be sure to do this in the
219
// normal map sampler also. Finally, beware of quad triangulations. If the
220
// normal map sampler doesn't use the same triangulation of quads as your
221
// renderer then problems will occur since the interpolated tangent spaces will
222
// differ eventhough the vertex level tangent spaces match. This can be solved
223
// either by triangulating before sampling/exporting or by using the
224
// order-independent choice of diagonal for splitting quads suggested earlier.
225
// However, this must be used both by the sampler and your tools/rendering
226
// pipeline.
227
228
}
// end namespace GU
229
230
class
GU_Detail
;
231
class
GA_PrimitiveGroup
;
232
class
GA_PointGroup
;
233
234
class
GU_API
GU_MikkT
235
{
236
public
:
237
238
//! Compute MikkT tangents
239
/// The result of the computation will be written out to per-vertex
240
/// attributes: tangents, bitangents, and signs. Not all output handles
241
/// need to be valid (invalid handles will be ignored).
242
static
bool
computeTangentsBasic(
const
GU_Detail
*gdp,
243
const
GA_PrimitiveGroup
*group,
244
const
UT_StringHolder
&uvattrname,
245
const
GA_RWHandleV3
&tangents,
246
const
GA_RWHandleV3
&bitangents,
247
const
GA_RWHandleF
&signs);
248
249
static
bool
computeTangentsBasic(
const
GU_Detail
*gdp,
250
const
GA_PrimitiveGroup
*group,
251
const
GA_PointGroup
*ptgroup,
252
const
UT_StringHolder
&uvattrname,
253
const
GA_RWHandleV3
&tangents,
254
const
GA_RWHandleV3
&bitangents,
255
const
GA_RWHandleF
&signs);
256
};
257
258
#endif
int
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
GA_PrimitiveGroup
Definition:
GA_ElementGroup.h:74
void
void
Definition:
png.h:1083
GU::SMikkTSpaceInterface::m_useHashmap
tbool m_useHashmap
Definition:
GU_MikkT.h:171
UT_Vector3.h
GU::SMikkTSpaceContext
Definition:
GU_MikkT.h:184
GU::SMikkTSpaceContext::m_pInterface
SMikkTSpaceInterface * m_pInterface
Definition:
GU_MikkT.h:186
GU::SMikkTSpaceContext::m_pUserData
void * m_pUserData
Definition:
GU_MikkT.h:187
GU::SMikkTSpaceInterface::m_usePointFaceMap
tbool m_usePointFaceMap
Definition:
GU_MikkT.h:181
GA_PointGroup
Definition:
GA_ElementGroup.h:33
GU_MikkT
Definition:
GU_MikkT.h:234
GU::genTangSpaceDefault
GU_API tbool genTangSpaceDefault(const SMikkTSpaceContext *pContext)
UT_StringHolder
Definition:
UT_StringHolder.h:1009
GA_RWHandleT< UT_Vector3F >
GA_Handle.h
GU_API
#define GU_API
Definition:
GU_API.h:14
size
GLsizeiptr size
Definition:
glcorearb.h:664
GU::SMikkTSpaceInterface::m_usePointCache
tbool m_usePointCache
Definition:
GU_MikkT.h:177
GU_Detail
Definition:
GU_Detail.h:154
GU::SMikkTSpaceInterface
Definition:
GU_MikkT.h:73
GU_API.h
GU::tbool
int tbool
Definition:
GU_MikkT.h:70
GU::genTangSpace
GU_API tbool genTangSpace(const SMikkTSpaceContext *pContext, const float fAngularThreshold)
GU
GU_MikkT.h
Generated on Wed Aug 27 2025 03:06:38 for HDK by
1.8.6