Code cleanup: Add -Werror=float-conversion to Cycles
[blender.git] / intern / cycles / subd / subd_split.cpp
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16
17 #include "camera.h"
18 #include "mesh.h"
19
20 #include "subd_dice.h"
21 #include "subd_patch.h"
22 #include "subd_split.h"
23
24 #include "util_debug.h"
25 #include "util_math.h"
26 #include "util_types.h"
27
28 CCL_NAMESPACE_BEGIN
29
30 /* DiagSplit */
31
32 DiagSplit::DiagSplit(const SubdParams& params_)
33 : params(params_)
34 {
35 }
36
37 void DiagSplit::dispatch(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef)
38 {
39         subpatches_quad.push_back(sub);
40         edgefactors_quad.push_back(ef);
41 }
42
43 void DiagSplit::dispatch(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef)
44 {
45         subpatches_triangle.push_back(sub);
46         edgefactors_triangle.push_back(ef);
47 }
48
49 float3 DiagSplit::project(Patch *patch, float2 uv)
50 {
51         float3 P;
52
53         patch->eval(&P, NULL, NULL, uv.x, uv.y);
54         if(params.camera)
55                 P = transform_perspective(&params.camera->worldtoraster, P);
56
57         return P;
58 }
59
60 int DiagSplit::T(Patch *patch, float2 Pstart, float2 Pend)
61 {
62         float3 Plast = make_float3(0.0f, 0.0f, 0.0f);
63         float Lsum = 0.0f;
64         float Lmax = 0.0f;
65
66         for(int i = 0; i < params.test_steps; i++) {
67                 float t = i/(float)(params.test_steps-1);
68
69                 float3 P = project(patch, Pstart + t*(Pend - Pstart));
70
71                 if(i > 0) {
72                         float L = len(P - Plast);
73                         Lsum += L;
74                         Lmax = max(L, Lmax);
75                 }
76
77                 Plast = P;
78         }
79
80         int tmin = (int)ceil(Lsum/params.dicing_rate);
81         int tmax = (int)ceil((params.test_steps-1)*Lmax/params.dicing_rate); // XXX paper says N instead of N-1, seems wrong?
82
83         if(tmax - tmin > params.split_threshold)
84                 return DSPLIT_NON_UNIFORM;
85         
86         return tmax;
87 }
88
89 void DiagSplit::partition_edge(Patch *patch, float2 *P, int *t0, int *t1, float2 Pstart, float2 Pend, int t)
90 {
91         if(t == DSPLIT_NON_UNIFORM) {
92                 *P = (Pstart + Pend)*0.5f;
93                 *t0 = T(patch, Pstart, *P);
94                 *t1 = T(patch, *P, Pend);
95         }
96         else {
97                 int I = (int)floor((float)t*0.5f);
98                 *P = interp(Pstart, Pend, (t == 0)? 0: I/(float)t); /* XXX is t faces or verts */
99                 *t0 = I;
100                 *t1 = t - I;
101         }
102 }
103
104 void DiagSplit::split(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef, int depth)
105 {
106         assert(ef.tu == T(sub.patch, sub.Pv, sub.Pw));
107         assert(ef.tv == T(sub.patch, sub.Pw, sub.Pu));
108         assert(ef.tw == T(sub.patch, sub.Pu, sub.Pv));
109
110         if(depth == 0) {
111                 dispatch(sub, ef);
112                 return;
113         }
114
115         if(ef.tu == DSPLIT_NON_UNIFORM) {
116                 /* partition edges */
117                 TriangleDice::EdgeFactors ef0, ef1;
118                 float2 Psplit;
119
120                 partition_edge(sub.patch,
121                         &Psplit, &ef1.tu, &ef0.tu, sub.Pv, sub.Pw, ef.tu);
122
123                 /* split */
124                 int tsplit = T(sub.patch, sub.Pu, Psplit);
125                 ef0.tv = ef.tv;
126                 ef0.tw = tsplit;
127
128                 ef1.tv = tsplit;
129                 ef1.tw = ef.tw;
130
131                 /* create subpatches */
132                 TriangleDice::SubPatch sub0 = {sub.patch, sub.Pu, Psplit, sub.Pw};
133                 TriangleDice::SubPatch sub1 = {sub.patch, sub.Pu, sub.Pv, Psplit};
134
135                 split(sub0, ef0, depth+1);
136                 split(sub1, ef1, depth+1);
137         }
138         else if(ef.tv == DSPLIT_NON_UNIFORM) {
139                 /* partition edges */
140                 TriangleDice::EdgeFactors ef0, ef1;
141                 float2 Psplit;
142
143                 partition_edge(sub.patch,
144                         &Psplit, &ef1.tu, &ef0.tu, sub.Pw, sub.Pu, ef.tv);
145
146                 /* split */
147                 int tsplit = T(sub.patch, sub.Pv, Psplit);
148                 ef0.tv = ef.tw;
149                 ef0.tw = tsplit;
150
151                 ef1.tv = tsplit;
152                 ef1.tw = ef.tu;
153
154                 /* create subpatches */
155                 TriangleDice::SubPatch sub0 = {sub.patch, sub.Pv, Psplit, sub.Pu};
156                 TriangleDice::SubPatch sub1 = {sub.patch, sub.Pv, sub.Pw, Psplit};
157
158                 split(sub0, ef0, depth+1);
159                 split(sub1, ef1, depth+1);
160         }
161         else if(ef.tw == DSPLIT_NON_UNIFORM) {
162                 /* partition edges */
163                 TriangleDice::EdgeFactors ef0, ef1;
164                 float2 Psplit;
165
166                 partition_edge(sub.patch,
167                         &Psplit, &ef1.tu, &ef0.tu, sub.Pu, sub.Pv, ef.tw);
168
169                 /* split */
170                 int tsplit = T(sub.patch, sub.Pw, Psplit);
171                 ef0.tv = ef.tu;
172                 ef0.tw = tsplit;
173
174                 ef1.tv = tsplit;
175                 ef1.tw = ef.tv;
176
177                 /* create subpatches */
178                 TriangleDice::SubPatch sub0 = {sub.patch, sub.Pw, Psplit, sub.Pv};
179                 TriangleDice::SubPatch sub1 = {sub.patch, sub.Pw, sub.Pu, Psplit};
180
181                 split(sub0, ef0, depth+1);
182                 split(sub1, ef1, depth+1);
183         }
184         else
185                 dispatch(sub, ef);
186 }
187
188 void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int depth)
189 {
190         if((ef.tu0 == DSPLIT_NON_UNIFORM || ef.tu1 == DSPLIT_NON_UNIFORM)) {
191                 /* partition edges */
192                 QuadDice::EdgeFactors ef0, ef1;
193                 float2 Pu0, Pu1;
194
195                 partition_edge(sub.patch,
196                         &Pu0, &ef0.tu0, &ef1.tu0, sub.P00, sub.P10, ef.tu0);
197                 partition_edge(sub.patch,
198                         &Pu1, &ef0.tu1, &ef1.tu1, sub.P01, sub.P11, ef.tu1);
199
200                 /* split */
201                 int tsplit = T(sub.patch, Pu0, Pu1);
202                 ef0.tv0 = ef.tv0;
203                 ef0.tv1 = tsplit;
204
205                 ef1.tv0 = tsplit;
206                 ef1.tv1 = ef.tv1;
207
208                 /* create subpatches */
209                 QuadDice::SubPatch sub0 = {sub.patch, sub.P00, Pu0, sub.P01, Pu1};
210                 QuadDice::SubPatch sub1 = {sub.patch, Pu0, sub.P10, Pu1, sub.P11};
211
212                 split(sub0, ef0, depth+1);
213                 split(sub1, ef1, depth+1);
214         }
215         else if(ef.tv0 == DSPLIT_NON_UNIFORM || ef.tv1 == DSPLIT_NON_UNIFORM) {
216                 /* partition edges */
217                 QuadDice::EdgeFactors ef0, ef1;
218                 float2 Pv0, Pv1;
219
220                 partition_edge(sub.patch,
221                         &Pv0, &ef0.tv0, &ef1.tv0, sub.P00, sub.P01, ef.tv0);
222                 partition_edge(sub.patch,
223                         &Pv1, &ef0.tv1, &ef1.tv1, sub.P10, sub.P11, ef.tv1);
224
225                 /* split */
226                 int tsplit = T(sub.patch, Pv0, Pv1);
227                 ef0.tu0 = ef.tu0;
228                 ef0.tu1 = tsplit;
229
230                 ef1.tu0 = tsplit;
231                 ef1.tu1 = ef.tu1;
232
233                 /* create subpatches */
234                 QuadDice::SubPatch sub0 = {sub.patch, sub.P00, sub.P10, Pv0, Pv1};
235                 QuadDice::SubPatch sub1 = {sub.patch, Pv0, Pv1, sub.P01, sub.P11};
236
237                 split(sub0, ef0, depth+1);
238                 split(sub1, ef1, depth+1);
239         }
240         else
241                 dispatch(sub, ef);
242 }
243
244 void DiagSplit::split_triangle(Patch *patch)
245 {
246         TriangleDice::SubPatch sub_split;
247         TriangleDice::EdgeFactors ef_split;
248
249         sub_split.patch = patch;
250         sub_split.Pu = make_float2(1.0f, 0.0f);
251         sub_split.Pv = make_float2(0.0f, 1.0f);
252         sub_split.Pw = make_float2(0.0f, 0.0f);
253
254         ef_split.tu = T(patch, sub_split.Pv, sub_split.Pw);
255         ef_split.tv = T(patch, sub_split.Pw, sub_split.Pu);
256         ef_split.tw = T(patch, sub_split.Pu, sub_split.Pv);
257
258         split(sub_split, ef_split);
259
260         TriangleDice dice(params);
261
262         for(size_t i = 0; i < subpatches_triangle.size(); i++) {
263                 TriangleDice::SubPatch& sub = subpatches_triangle[i];
264                 TriangleDice::EdgeFactors& ef = edgefactors_triangle[i];
265
266                 ef.tu = 4;
267                 ef.tv = 4;
268                 ef.tw = 4;
269
270                 ef.tu = max(ef.tu, 1);
271                 ef.tv = max(ef.tv, 1);
272                 ef.tw = max(ef.tw, 1);
273
274                 dice.dice(sub, ef);
275         }
276
277         subpatches_triangle.clear();
278         edgefactors_triangle.clear();
279 }
280
281 void DiagSplit::split_quad(Patch *patch)
282 {
283         QuadDice::SubPatch sub_split;
284         QuadDice::EdgeFactors ef_split;
285
286         sub_split.patch = patch;
287         sub_split.P00 = make_float2(0.0f, 0.0f);
288         sub_split.P10 = make_float2(1.0f, 0.0f);
289         sub_split.P01 = make_float2(0.0f, 1.0f);
290         sub_split.P11 = make_float2(1.0f, 1.0f);
291
292         ef_split.tu0 = T(patch, sub_split.P00, sub_split.P10);
293         ef_split.tu1 = T(patch, sub_split.P01, sub_split.P11);
294         ef_split.tv0 = T(patch, sub_split.P00, sub_split.P01);
295         ef_split.tv1 = T(patch, sub_split.P10, sub_split.P11);
296
297         split(sub_split, ef_split);
298
299         QuadDice dice(params);
300
301         for(size_t i = 0; i < subpatches_quad.size(); i++) {
302                 QuadDice::SubPatch& sub = subpatches_quad[i];
303                 QuadDice::EdgeFactors& ef = edgefactors_quad[i];
304
305                 ef.tu0 = max(ef.tu0, 1);
306                 ef.tu1 = max(ef.tu1, 1);
307                 ef.tv0 = max(ef.tv0, 1);
308                 ef.tv1 = max(ef.tv1, 1);
309
310                 dice.dice(sub, ef);
311         }
312
313         subpatches_quad.clear();
314         edgefactors_quad.clear();
315 }
316
317 CCL_NAMESPACE_END
318