Blender V2.61 - r43446

subd_split.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright 2011, Blender Foundation.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 #include "camera.h"
00020 #include "mesh.h"
00021 
00022 #include "subd_dice.h"
00023 #include "subd_patch.h"
00024 #include "subd_split.h"
00025 
00026 #include "util_debug.h"
00027 #include "util_math.h"
00028 #include "util_types.h"
00029 
00030 CCL_NAMESPACE_BEGIN
00031 
00032 /* DiagSplit */
00033 
00034 DiagSplit::DiagSplit()
00035 {
00036     test_steps = 3;
00037     split_threshold = 1;
00038     dicing_rate = 0.1f;
00039     camera = NULL;
00040 }
00041 
00042 void DiagSplit::dispatch(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef)
00043 {
00044     subpatches_quad.push_back(sub);
00045     edgefactors_quad.push_back(ef);
00046 }
00047 
00048 void DiagSplit::dispatch(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef)
00049 {
00050     subpatches_triangle.push_back(sub);
00051     edgefactors_triangle.push_back(ef);
00052 }
00053 
00054 float3 DiagSplit::project(Patch *patch, float2 uv)
00055 {
00056     float3 P;
00057 
00058     patch->eval(&P, NULL, NULL, uv.x, uv.y);
00059     if(camera)
00060         P = transform(&camera->worldtoraster, P);
00061 
00062     return P;
00063 }
00064 
00065 int DiagSplit::T(Patch *patch, float2 Pstart, float2 Pend)
00066 {
00067     float3 Plast = make_float3(0.0f, 0.0f, 0.0f);
00068     float Lsum = 0.0f;
00069     float Lmax = 0.0f;
00070 
00071     for(int i = 0; i < test_steps; i++) {
00072         float t = i/(float)(test_steps-1);
00073 
00074         float3 P = project(patch, Pstart + t*(Pend - Pstart));
00075 
00076         if(i > 0) {
00077             float L = len(P - Plast);
00078             Lsum += L;
00079             Lmax = max(L, Lmax);
00080         }
00081 
00082         Plast = P;
00083     }
00084 
00085     int tmin = (int)ceil(Lsum/dicing_rate);
00086     int tmax = (int)ceil((test_steps-1)*Lmax/dicing_rate); // XXX paper says N instead of N-1, seems wrong?
00087 
00088     if(tmax - tmin > split_threshold)
00089         return DSPLIT_NON_UNIFORM;
00090     
00091     return tmax;
00092 }
00093 
00094 void DiagSplit::partition_edge(Patch *patch, float2 *P, int *t0, int *t1, float2 Pstart, float2 Pend, int t)
00095 {
00096     if(t == DSPLIT_NON_UNIFORM) {
00097         *P = (Pstart + Pend)*0.5f;
00098         *t0 = T(patch, Pstart, *P);
00099         *t1 = T(patch, *P, Pend);
00100     }
00101     else {
00102         int I = floor(t*0.5f);
00103         *P = interp(Pstart, Pend, (t == 0)? 0: I/(float)t); /* XXX is t faces or verts */
00104         *t0 = I;
00105         *t1 = t - I;
00106     }
00107 }
00108 
00109 void DiagSplit::split(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef, int depth)
00110 {
00111     assert(ef.tu == T(sub.patch, sub.Pv, sub.Pw));
00112     assert(ef.tv == T(sub.patch, sub.Pw, sub.Pu));
00113     assert(ef.tw == T(sub.patch, sub.Pu, sub.Pv));
00114 
00115     if(depth == 0) {
00116         dispatch(sub, ef);
00117         return;
00118     }
00119 
00120     if(ef.tu == DSPLIT_NON_UNIFORM) {
00121         /* partition edges */
00122         TriangleDice::EdgeFactors ef0, ef1;
00123         float2 Psplit;
00124 
00125         partition_edge(sub.patch,
00126             &Psplit, &ef1.tu, &ef0.tu, sub.Pv, sub.Pw, ef.tu);
00127 
00128         /* split */
00129         int tsplit = T(sub.patch, sub.Pu, Psplit);
00130         ef0.tv = ef.tv;
00131         ef0.tw = tsplit;
00132 
00133         ef1.tv = tsplit;
00134         ef1.tw = ef.tw;
00135 
00136         /* create subpatches */
00137         TriangleDice::SubPatch sub0 = {sub.patch, sub.Pu, Psplit, sub.Pw};
00138         TriangleDice::SubPatch sub1 = {sub.patch, sub.Pu, sub.Pv, Psplit};
00139 
00140         split(sub0, ef0, depth+1);
00141         split(sub1, ef1, depth+1);
00142     }
00143     else if(ef.tv == DSPLIT_NON_UNIFORM) {
00144         /* partition edges */
00145         TriangleDice::EdgeFactors ef0, ef1;
00146         float2 Psplit;
00147 
00148         partition_edge(sub.patch,
00149             &Psplit, &ef1.tu, &ef0.tu, sub.Pw, sub.Pu, ef.tv);
00150 
00151         /* split */
00152         int tsplit = T(sub.patch, sub.Pv, Psplit);
00153         ef0.tv = ef.tw;
00154         ef0.tw = tsplit;
00155 
00156         ef1.tv = tsplit;
00157         ef1.tw = ef.tu;
00158 
00159         /* create subpatches */
00160         TriangleDice::SubPatch sub0 = {sub.patch, sub.Pv, Psplit, sub.Pu};
00161         TriangleDice::SubPatch sub1 = {sub.patch, sub.Pv, sub.Pw, Psplit};
00162 
00163         split(sub0, ef0, depth+1);
00164         split(sub1, ef1, depth+1);
00165     }
00166     else if(ef.tw == DSPLIT_NON_UNIFORM) {
00167         /* partition edges */
00168         TriangleDice::EdgeFactors ef0, ef1;
00169         float2 Psplit;
00170 
00171         partition_edge(sub.patch,
00172             &Psplit, &ef1.tu, &ef0.tu, sub.Pu, sub.Pv, ef.tw);
00173 
00174         /* split */
00175         int tsplit = T(sub.patch, sub.Pw, Psplit);
00176         ef0.tv = ef.tu;
00177         ef0.tw = tsplit;
00178 
00179         ef1.tv = tsplit;
00180         ef1.tw = ef.tv;
00181 
00182         /* create subpatches */
00183         TriangleDice::SubPatch sub0 = {sub.patch, sub.Pw, Psplit, sub.Pv};
00184         TriangleDice::SubPatch sub1 = {sub.patch, sub.Pw, sub.Pu, Psplit};
00185 
00186         split(sub0, ef0, depth+1);
00187         split(sub1, ef1, depth+1);
00188     }
00189     else
00190         dispatch(sub, ef);
00191 }
00192 
00193 void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int depth)
00194 {
00195     if((ef.tu0 == DSPLIT_NON_UNIFORM || ef.tu1 == DSPLIT_NON_UNIFORM)) {
00196         /* partition edges */
00197         QuadDice::EdgeFactors ef0, ef1;
00198         float2 Pu0, Pu1;
00199 
00200         partition_edge(sub.patch,
00201             &Pu0, &ef0.tu0, &ef1.tu0, sub.P00, sub.P10, ef.tu0);
00202         partition_edge(sub.patch,
00203             &Pu1, &ef0.tu1, &ef1.tu1, sub.P01, sub.P11, ef.tu1);
00204 
00205         /* split */
00206         int tsplit = T(sub.patch, Pu0, Pu1);
00207         ef0.tv0 = ef.tv0;
00208         ef0.tv1 = tsplit;
00209 
00210         ef1.tv0 = tsplit;
00211         ef1.tv1 = ef.tv1;
00212 
00213         /* create subpatches */
00214         QuadDice::SubPatch sub0 = {sub.patch, sub.P00, Pu0, sub.P01, Pu1};
00215         QuadDice::SubPatch sub1 = {sub.patch, Pu0, sub.P10, Pu1, sub.P11};
00216 
00217         split(sub0, ef0, depth+1);
00218         split(sub1, ef1, depth+1);
00219     }
00220     else if(ef.tv0 == DSPLIT_NON_UNIFORM || ef.tv1 == DSPLIT_NON_UNIFORM) {
00221         /* partition edges */
00222         QuadDice::EdgeFactors ef0, ef1;
00223         float2 Pv0, Pv1;
00224 
00225         partition_edge(sub.patch,
00226             &Pv0, &ef0.tv0, &ef1.tv0, sub.P00, sub.P01, ef.tv0);
00227         partition_edge(sub.patch,
00228             &Pv1, &ef0.tv1, &ef1.tv1, sub.P10, sub.P11, ef.tv1);
00229 
00230         /* split */
00231         int tsplit = T(sub.patch, Pv0, Pv1);
00232         ef0.tu0 = ef.tu0;
00233         ef0.tu1 = tsplit;
00234 
00235         ef1.tu0 = tsplit;
00236         ef1.tu1 = ef.tu1;
00237 
00238         /* create subpatches */
00239         QuadDice::SubPatch sub0 = {sub.patch, sub.P00, sub.P10, Pv0, Pv1};
00240         QuadDice::SubPatch sub1 = {sub.patch, Pv0, Pv1, sub.P01, sub.P11};
00241 
00242         split(sub0, ef0, depth+1);
00243         split(sub1, ef1, depth+1);
00244     }
00245     else
00246         dispatch(sub, ef);
00247 }
00248 
00249 void DiagSplit::split_triangle(Mesh *mesh, Patch *patch, int shader, bool smooth)
00250 {
00251     TriangleDice::SubPatch sub;
00252     TriangleDice::EdgeFactors ef;
00253 
00254     sub.patch = patch;
00255     sub.Pu = make_float2(1.0f, 0.0f);
00256     sub.Pv = make_float2(0.0f, 1.0f);
00257     sub.Pw = make_float2(0.0f, 0.0f);
00258 
00259     ef.tu = T(patch, sub.Pv, sub.Pw);
00260     ef.tv = T(patch, sub.Pw, sub.Pu);
00261     ef.tw = T(patch, sub.Pu, sub.Pv);
00262 
00263     split(sub, ef);
00264 
00265     TriangleDice dice(mesh, shader, smooth, dicing_rate);
00266     dice.camera = camera;
00267 
00268     for(size_t i = 0; i < subpatches_triangle.size(); i++) {
00269         TriangleDice::SubPatch& sub = subpatches_triangle[i];
00270         TriangleDice::EdgeFactors& ef = edgefactors_triangle[i];
00271 
00272         ef.tu = 4;
00273         ef.tv = 4;
00274         ef.tw = 4;
00275 
00276         ef.tu = max(ef.tu, 1);
00277         ef.tv = max(ef.tv, 1);
00278         ef.tw = max(ef.tw, 1);
00279 
00280         dice.dice(sub, ef);
00281     }
00282 
00283     subpatches_triangle.clear();
00284     edgefactors_triangle.clear();
00285 }
00286 
00287 void DiagSplit::split_quad(Mesh *mesh, Patch *patch, int shader, bool smooth)
00288 {
00289     QuadDice::SubPatch sub;
00290     QuadDice::EdgeFactors ef;
00291 
00292     sub.patch = patch;
00293     sub.P00 = make_float2(0.0f, 0.0f);
00294     sub.P10 = make_float2(1.0f, 0.0f);
00295     sub.P01 = make_float2(0.0f, 1.0f);
00296     sub.P11 = make_float2(1.0f, 1.0f);
00297 
00298     ef.tu0 = T(patch, sub.P00, sub.P10);
00299     ef.tu1 = T(patch, sub.P01, sub.P11);
00300     ef.tv0 = T(patch, sub.P00, sub.P01);
00301     ef.tv1 = T(patch, sub.P10, sub.P11);
00302 
00303     split(sub, ef);
00304 
00305     QuadDice dice(mesh, shader, smooth, dicing_rate);
00306     dice.camera = camera;
00307 
00308     for(size_t i = 0; i < subpatches_quad.size(); i++) {
00309         QuadDice::SubPatch& sub = subpatches_quad[i];
00310         QuadDice::EdgeFactors& ef = edgefactors_quad[i];
00311 
00312         ef.tu0 = max(ef.tu0, 1);
00313         ef.tu1 = max(ef.tu1, 1);
00314         ef.tv0 = max(ef.tv0, 1);
00315         ef.tv1 = max(ef.tv1, 1);
00316 
00317         dice.dice(sub, ef);
00318     }
00319 
00320     subpatches_quad.clear();
00321     edgefactors_quad.clear();
00322 }
00323 
00324 CCL_NAMESPACE_END
00325