Merge branch 'blender2.7'
[blender.git] / source / blender / blenkernel / intern / CCGSubSurf_inline.h
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file blender/blenkernel/intern/CCGSubSurf_inline.h
22  *  \ingroup bke
23  */
24
25 #ifndef __CCGSUBSURF_INLINE_H__
26 #define __CCGSUBSURF_INLINE_H__
27
28 BLI_INLINE int ccg_gridsize(int level)
29 {
30         BLI_assert(level > 0);
31         BLI_assert(level <= CCGSUBSURF_LEVEL_MAX + 1);
32         return (1 << (level - 1)) + 1;
33 }
34
35 BLI_INLINE int ccg_edgesize(int level)
36 {
37         BLI_assert(level > 0);
38         BLI_assert(level <= CCGSUBSURF_LEVEL_MAX + 1);
39         return 1 + (1 << level);
40 }
41
42 BLI_INLINE int ccg_spacing(int high_level, int low_level)
43 {
44         BLI_assert(high_level > 0 && low_level > 0);
45         BLI_assert(high_level >= low_level);
46         BLI_assert((high_level - low_level) <= CCGSUBSURF_LEVEL_MAX);
47         return 1 << (high_level - low_level);
48 }
49
50 BLI_INLINE int ccg_edgebase(int level)
51 {
52         BLI_assert(level > 0);
53         BLI_assert(level <= CCGSUBSURF_LEVEL_MAX + 1);
54         return level + (1 << level) - 1;
55 }
56
57 /* **** */
58
59 BLI_INLINE byte *VERT_getLevelData(CCGVert *v)
60 {
61     return (byte *)(&(v)[1]);
62 }
63
64 BLI_INLINE byte *EDGE_getLevelData(CCGEdge *e)
65 {
66     return (byte *)(&(e)[1]);
67 }
68
69 BLI_INLINE CCGVert **FACE_getVerts(CCGFace *f)
70 {
71     return (CCGVert **)(&f[1]);
72 }
73
74 BLI_INLINE CCGEdge **FACE_getEdges(CCGFace *f)
75 {
76     return (CCGEdge **)(&(FACE_getVerts(f)[f->numVerts]));
77 }
78
79 BLI_INLINE byte *FACE_getCenterData(CCGFace *f)
80 {
81     return (byte *)(&(FACE_getEdges(f)[(f)->numVerts]));
82 }
83
84 /* **** */
85
86 BLI_INLINE void *ccg_vert_getCo(CCGVert *v, int lvl, int dataSize)
87 {
88         return &VERT_getLevelData(v)[lvl * dataSize];
89 }
90
91 BLI_INLINE float *ccg_vert_getNo(CCGVert *v,
92                                  int lvl,
93                                  int dataSize,
94                                  int normalDataOffset)
95 {
96     return (float *) &VERT_getLevelData(v)[lvl * dataSize + normalDataOffset];
97 }
98
99 BLI_INLINE void *ccg_edge_getCo(CCGEdge *e, int lvl, int x, int dataSize)
100 {
101         int levelBase = ccg_edgebase(lvl);
102         return &EDGE_getLevelData(e)[dataSize * (levelBase + x)];
103 }
104
105 BLI_INLINE float *ccg_edge_getNo(CCGEdge *e,
106                                  int lvl,
107                                  int x,
108                                  int dataSize,
109                                  int normalDataOffset)
110 {
111         int levelBase = ccg_edgebase(lvl);
112         return (float *) &EDGE_getLevelData(e)[dataSize * (levelBase + x) + normalDataOffset];
113 }
114
115 BLI_INLINE void *ccg_face_getIECo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize)
116 {
117         int maxGridSize = ccg_gridsize(levels);
118         int spacing = ccg_spacing(levels, lvl);
119         byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize));
120         return &gridBase[dataSize * x * spacing];
121 }
122
123 BLI_INLINE void *ccg_face_getIENo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize, int normalDataOffset)
124 {
125         int maxGridSize = ccg_gridsize(levels);
126         int spacing = ccg_spacing(levels, lvl);
127         byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize));
128         return &gridBase[dataSize * x * spacing + normalDataOffset];
129 }
130
131 BLI_INLINE void *ccg_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize)
132 {
133         int maxGridSize = ccg_gridsize(levels);
134         int spacing = ccg_spacing(levels, lvl);
135         byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize));
136         return &gridBase[dataSize * (maxGridSize + (y * maxGridSize + x) * spacing)];
137 }
138
139 BLI_INLINE float *ccg_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize, int normalDataOffset)
140 {
141         int maxGridSize = ccg_gridsize(levels);
142         int spacing = ccg_spacing(levels, lvl);
143         byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize));
144         return (float *) &gridBase[dataSize * (maxGridSize + (y * maxGridSize + x) * spacing) + normalDataOffset];
145 }
146
147
148 BLI_INLINE int ccg_face_getVertIndex(CCGFace *f, CCGVert *v)
149 {
150         int i;
151         for (i = 0; i < f->numVerts; i++)
152                 if (FACE_getVerts(f)[i] == v)
153                         return i;
154         return -1;
155 }
156
157 BLI_INLINE int ccg_face_getEdgeIndex(CCGFace *f, CCGEdge *e)
158 {
159         int i;
160         for (i = 0; i < f->numVerts; i++)
161                 if (FACE_getEdges(f)[i] == e)
162                         return i;
163         return -1;
164 }
165
166 BLI_INLINE void *ccg_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int f_ed_idx, int lvl, int eX, int eY, int levels, int dataSize)
167 {
168         int maxGridSize = ccg_gridsize(levels);
169         int spacing = ccg_spacing(levels, lvl);
170         int x, y, cx, cy;
171
172         BLI_assert(f_ed_idx == ccg_face_getEdgeIndex(f, e));
173
174         eX = eX * spacing;
175         eY = eY * spacing;
176         if (e->v0 != FACE_getVerts(f)[f_ed_idx]) {
177                 eX = (maxGridSize * 2 - 1) - 1 - eX;
178         }
179         y = maxGridSize - 1 - eX;
180         x = maxGridSize - 1 - eY;
181         if (x < 0) {
182                 f_ed_idx = (f_ed_idx + f->numVerts - 1) % f->numVerts;
183                 cx = y;
184                 cy = -x;
185         }
186         else if (y < 0) {
187                 f_ed_idx = (f_ed_idx + 1) % f->numVerts;
188                 cx = -y;
189                 cy = x;
190         }
191         else {
192                 cx = x;
193                 cy = y;
194         }
195         return ccg_face_getIFCo(f, levels, f_ed_idx, cx, cy, levels, dataSize);
196 }
197
198 BLI_INLINE void Normalize(float no[3])
199 {
200         const float length = sqrtf(no[0] * no[0] + no[1] * no[1] + no[2] * no[2]);
201
202         if (length > EPSILON) {
203                 const float length_inv = 1.0f / length;
204
205                 no[0] *= length_inv;
206                 no[1] *= length_inv;
207                 no[2] *= length_inv;
208         }
209         else {
210                 NormZero(no);
211         }
212 }
213
214 /* Data layers mathematics. */
215
216 BLI_INLINE int VertDataEqual(const float a[], const float b[], const CCGSubSurf *ss)
217 {
218         int i;
219         for (i = 0; i < ss->meshIFC.numLayers; i++) {
220                 if (a[i] != b[i])
221                         return 0;
222         }
223         return 1;
224 }
225
226 BLI_INLINE void VertDataZero(float v[], const CCGSubSurf *ss)
227 {
228         memset(v, 0, sizeof(float) * ss->meshIFC.numLayers);
229 }
230
231 BLI_INLINE void VertDataCopy(float dst[], const float src[], const CCGSubSurf *ss)
232 {
233         int i;
234         for (i = 0; i < ss->meshIFC.numLayers; i++)
235                 dst[i] = src[i];
236 }
237
238 BLI_INLINE void VertDataAdd(float a[], const float b[], const CCGSubSurf *ss)
239 {
240         int i;
241         for (i = 0; i < ss->meshIFC.numLayers; i++)
242                 a[i] += b[i];
243 }
244
245 BLI_INLINE void VertDataSub(float a[], const float b[], const CCGSubSurf *ss)
246 {
247         int i;
248         for (i = 0; i < ss->meshIFC.numLayers; i++)
249                 a[i] -= b[i];
250 }
251
252 BLI_INLINE void VertDataMulN(float v[], float f, const CCGSubSurf *ss)
253 {
254         int i;
255         for (i = 0; i < ss->meshIFC.numLayers; i++)
256                 v[i] *= f;
257 }
258
259 BLI_INLINE void VertDataAvg4(float v[],
260                              const float a[], const float b[],
261                              const float c[], const float d[],
262                              const CCGSubSurf *ss)
263 {
264         int i;
265         for (i = 0; i < ss->meshIFC.numLayers; i++)
266                 v[i] = (a[i] + b[i] + c[i] + d[i]) * 0.25f;
267 }
268
269 #endif  /* __CCGSUBSURF_INLINE_H__ */