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