Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/ogre_src_v1-9-0/OgreMain/include/OgreTangentSpaceCalc.h @ 148

Last change on this file since 148 was 148, checked in by patricwi, 6 years ago

Added new dependencies for ogre1.9 and cegui0.8

File size: 10.3 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4(Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2013 Torus Knot Software Ltd
8
9Permission is hereby granted, free of charge, to any person obtaining a copy
10of this software and associated documentation files (the "Software"), to deal
11in the Software without restriction, including without limitation the rights
12to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13copies of the Software, and to permit persons to whom the Software is
14furnished to do so, subject to the following conditions:
15
16The above copyright notice and this permission notice shall be included in
17all copies or substantial portions of the Software.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25THE SOFTWARE.
26-----------------------------------------------------------------------------
27*/
28#ifndef _OgreTangentSpaceCalc_H_
29#define _OgreTangentSpaceCalc_H_
30
31#include "OgrePrerequisites.h"
32#include "OgreRenderOperation.h"
33#include "OgreVector2.h"
34#include "OgreVector3.h"
35#include "OgreVertexIndexData.h"
36#include "OgreHeaderPrefix.h"
37
38namespace Ogre
39{
40
41        /** \addtogroup Core
42        *  @{
43        */
44        /** \addtogroup Math
45        *  @{
46        */
47        /** Class for calculating a tangent space basis.
48        */
49        class _OgreExport TangentSpaceCalc
50        {
51        public:
52                TangentSpaceCalc();
53                virtual ~TangentSpaceCalc();
54
55                typedef std::pair<size_t, size_t> VertexSplit;
56
57                /// Information about a remapped index
58                struct IndexRemap
59                {
60                        /// Index data set (can be >0 if more than one index data was added)
61                        size_t indexSet;
62                        /// The position in the index buffer that's affected
63                        size_t faceIndex;
64                        /// The old and new vertex index
65                        VertexSplit splitVertex;
66               
67                        IndexRemap() {} // to keep container happy
68                        IndexRemap(size_t i, size_t f, const VertexSplit& s) : indexSet(i), faceIndex(f), splitVertex(s) {}
69                };
70                /** List of indexes that were remapped (split vertices).
71                */
72                typedef list<IndexRemap>::type IndexRemapList;
73
74                typedef list<VertexSplit>::type VertexSplits;
75
76                /// The result of having built a tangent space basis
77                struct Result
78                {
79                        /** A list of vertex indices which were split off into new vertices
80                                because of mirroring. First item in each pair is the source vertex
81                                index, the second value is the split vertex index.
82                        */
83                        VertexSplits vertexSplits;
84                        /** A list of indexes which were affected by splits. You can use this if you have other
85                                triangle-based data which you will need to alter to match. */
86                        IndexRemapList indexesRemapped;
87                };
88
89                /// Reset the calculation object
90                void clear();
91
92                /** Set the incoming vertex data (which will be modified) */
93                void setVertexData(VertexData* v_in);
94
95                /** Add a set of index data that references the vertex data.
96                        This might be modified if there are vertex splits.
97                */
98                void addIndexData(IndexData* i_in, RenderOperation::OperationType opType = RenderOperation::OT_TRIANGLE_LIST);
99
100                /** Sets whether to store tangent space parity in the W of a 4-component tangent or not.
101                @remarks
102                        The default element format to use is VET_FLOAT3 which is enough to accurately
103                        deal with tangents that do not involve any texture coordinate mirroring.
104                        If you wish to allow UV mirroring in your model, you must enable 4-component
105                        tangents using this method, and the 'w' co-ordinate will be populated
106                        with the parity of the triangle (+1 or -1), which will allow you to generate
107                        the bitangent properly.
108                @param enabled true to enable 4-component tangents (default false). If you enable
109                        this, you will probably also want to enable mirror splitting (see setSplitMirrored),
110                        and your shader must understand how to deal with the parity.
111                */
112                void setStoreParityInW(bool enabled) { mStoreParityInW = enabled; }
113
114                /**  Gets whether to store tangent space parity in the W of a 4-component tangent or not. */
115                bool getStoreParityInW() const { return mStoreParityInW; }
116
117                /** Sets whether or not to split vertices when a mirrored tangent space
118                        transition is detected (matrix parity differs).
119                @remarks
120                        This defaults to 'off' because it's the safest option; tangents will be
121                        interpolated in all cases even if they don't agree around a vertex, so
122                        artefacts will be smoothed out. When you're using art assets of
123                        unknown quality this can avoid extra seams on the visible surface.
124                        However, if your artists are good, they will be hiding texture seams
125                        in folds of the model and thus you can turn this option on, which will
126                        prevent the results of those seams from getting smoothed into other
127                        areas, which is exactly what you want.
128                @note This option is automatically disabled if you provide any strip or
129                        fan based geometry.
130                */
131                void setSplitMirrored(bool split) { mSplitMirrored = split; }
132               
133                /** Gets whether or not to split vertices when a mirrored tangent space
134                        transition is detected.
135                */
136                bool getSplitMirrored() const { return mSplitMirrored; }
137
138                /** Sets whether or not to split vertices when tangent space rotates
139                        more than 90 degrees around a vertex.
140                @remarks
141                        This defaults to 'off' because it's the safest option; tangents will be
142                        interpolated in all cases even if they don't agree around a vertex, so
143                        artefacts will be smoothed out. When you're using art assets of
144                        unknown quality this can avoid extra seams on the visible surface.
145                        However, if your artists are good, they will be hiding texture inconsistencies
146                        in folds of the model and thus you can turn this option on, which will
147                        prevent the results of those seams from getting smoothed into other
148                        areas, which is exactly what you want.
149                @note This option is automatically disabled if you provide any strip or
150                        fan based geometry.
151                */
152                void setSplitRotated(bool split) { mSplitRotated = split; }
153                /** Sets whether or not to split vertices when tangent space rotates
154                more than 90 degrees around a vertex.
155                */
156                bool getSplitRotated() const { return mSplitRotated; }
157
158                /** Build a tangent space basis from the provided data.
159                @remarks
160                        Only indexed triangle lists are allowed. Strips and fans cannot be
161                        supported because it may be necessary to split the geometry up to
162                        respect deviances in the tangent space basis better.
163                @param targetSemantic The semantic to store the tangents in. Defaults to
164                        the explicit tangent binding, but note that this is only usable on more
165                        modern hardware (Shader Model 2), so if you need portability with older
166                        cards you should change this to a texture coordinate binding instead.
167        @param sourceTexCoordSet The texture coordinate index which should be used as the source
168            of 2D texture coordinates, with which to calculate the tangents.
169        @param index The element index, ie the texture coordinate set which should be used to store the 3D
170            coordinates representing a tangent vector per vertex, if targetSemantic is
171                        VES_TEXTURE_COORDINATES. If this already exists, it will be overwritten.
172                @return
173                        A structure containing the results of the tangent space build. Vertex data
174                        will always be modified but it's also possible that the index data
175                        could be adjusted. This happens when mirroring is used on a mesh, which
176                        causes the tangent space to be inverted on opposite sides of an edge.
177                        This is discontinuous, therefore the vertices have to be split along
178                        this edge, resulting in new vertices.
179                */
180                Result build(VertexElementSemantic targetSemantic = VES_TANGENT,
181                        unsigned short sourceTexCoordSet = 0, unsigned short index = 1);
182
183
184        protected:
185
186                VertexData* mVData;
187                typedef vector<IndexData*>::type IndexDataList;
188                typedef vector<RenderOperation::OperationType>::type OpTypeList;
189                IndexDataList mIDataList;
190                OpTypeList mOpTypes;
191                bool mSplitMirrored;
192                bool mSplitRotated;
193                bool mStoreParityInW;
194
195
196                struct VertexInfo
197                {
198                        Vector3 pos;
199                        Vector3 norm;
200                        Vector2 uv;
201                        Vector3 tangent;
202                        Vector3 binormal;
203                        // Which way the tangent space is oriented (+1 / -1) (set on first time found)
204                        int parity;
205                        // What index the opposite parity vertex copy is at (0 if not created yet)
206                        size_t oppositeParityIndex;
207
208                        VertexInfo() : tangent(Vector3::ZERO), binormal(Vector3::ZERO), 
209                                parity(0), oppositeParityIndex(0) {}
210                };
211                typedef vector<VertexInfo>::type VertexInfoArray;
212                VertexInfoArray mVertexArray;
213
214                void extendBuffers(VertexSplits& splits);
215                void insertTangents(Result& res,
216                        VertexElementSemantic targetSemantic, 
217                        unsigned short sourceTexCoordSet, unsigned short index);
218
219                void populateVertexArray(unsigned short sourceTexCoordSet);
220                void processFaces(Result& result);
221                /// Calculate face tangent space, U and V are weighted by UV area, N is normalised
222                void calculateFaceTangentSpace(const size_t* vertInd, Vector3& tsU, Vector3& tsV, Vector3& tsN);
223                Real calculateAngleWeight(size_t v0, size_t v1, size_t v2);
224                int calculateParity(const Vector3& u, const Vector3& v, const Vector3& n);
225                void addFaceTangentSpaceToVertices(size_t indexSet, size_t faceIndex, size_t *localVertInd, 
226                        const Vector3& faceTsU, const Vector3& faceTsV, const Vector3& faceNorm, Result& result);
227                void normaliseVertices();
228                void remapIndexes(Result& res);
229                template <typename T>
230                void remapIndexes(T* ibuf, size_t indexSet, Result& res)
231                {
232                        for (IndexRemapList::iterator i = res.indexesRemapped.begin();
233                                i != res.indexesRemapped.end(); ++i)
234                        {
235                                IndexRemap& remap = *i;
236
237                                // Note that because this is a vertex split situation, and vertex
238                                // split is only for some faces, it's not a case of replacing all
239                                // instances of vertex index A with vertex index B
240                                // It actually matters which triangle we're talking about, so drive
241                                // the update from the face index
242
243                                if (remap.indexSet == indexSet)
244                                {
245                                        T* pBuf;
246                                        pBuf = ibuf + remap.faceIndex * 3;
247
248                                        for (int v = 0; v < 3; ++v, ++pBuf)
249                                        {
250                                                if (*pBuf == remap.splitVertex.first)
251                                                {
252                                                        *pBuf = (T)remap.splitVertex.second;
253                                                }
254                                        }
255                                }
256
257
258                        }
259                }
260               
261
262        };
263        /** @} */
264        /** @} */
265
266}
267
268#include "OgreHeaderSuffix.h"
269
270#endif
Note: See TracBrowser for help on using the repository browser.