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