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