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