Blender V2.61 - r43446

subd_patch.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 /* Parts adapted from code in the public domain in NVidia Mesh Tools. */
00020 
00021 #include "mesh.h"
00022 
00023 #include "subd_patch.h"
00024 
00025 #include "util_math.h"
00026 #include "util_types.h"
00027 
00028 CCL_NAMESPACE_BEGIN
00029 
00030 /* De Casteljau Evaluation */
00031 
00032 static float3 decasteljau_quadratic(float t, const float3 cp[3])
00033 {
00034     float3 d0 = cp[0] + t*(cp[1] - cp[0]);
00035     float3 d1 = cp[1] + t*(cp[2] - cp[1]);
00036 
00037     return d0 + t*(d1 - d0);
00038 }
00039 
00040 static void decasteljau_cubic(float3 *P, float3 *dt, float t, const float3 cp[4])
00041 {
00042     float3 d0 = cp[0] + t*(cp[1] - cp[0]);
00043     float3 d1 = cp[1] + t*(cp[2] - cp[1]);
00044     float3 d2 = cp[2] + t*(cp[3] - cp[2]);
00045 
00046     d0 += t*(d1 - d0);
00047     d1 += t*(d2 - d1);
00048 
00049     *P = d0 + t*(d1 - d0);
00050     if(dt) *dt = d1 - d0;
00051 }
00052 
00053 static void decasteljau_bicubic(float3 *P, float3 *du, float3 *dv, const float3 cp[16], float u, float v)
00054 {
00055     float3 ucp[4], utn[4];
00056 
00057     /* interpolate over u */
00058     decasteljau_cubic(ucp+0, utn+0, u, cp);
00059     decasteljau_cubic(ucp+1, utn+1, u, cp+4);
00060     decasteljau_cubic(ucp+2, utn+2, u, cp+8);
00061     decasteljau_cubic(ucp+3, utn+3, u, cp+12);
00062 
00063     /* interpolate over v */
00064     decasteljau_cubic(P, dv, v, ucp);
00065     if(du) decasteljau_cubic(du, NULL, v, utn);
00066 }
00067 
00068 static float3 decasteljau_tangent(const float3 cp[12], float u, float v)
00069 {
00070     float3 ucp[3];
00071 
00072     decasteljau_cubic(ucp+0, NULL, v, cp);
00073     decasteljau_cubic(ucp+1, NULL, v, cp+4);
00074     decasteljau_cubic(ucp+2, NULL, v, cp+8);
00075 
00076     return decasteljau_quadratic(u, ucp);
00077 }
00078 
00079 /* Linear Quad Patch */
00080 
00081 void LinearQuadPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
00082 {
00083     float3 d0 = interp(hull[0], hull[1], u);
00084     float3 d1 = interp(hull[2], hull[3], u);
00085 
00086     *P = interp(d0, d1, v);
00087 
00088     if(dPdu && dPdv) {
00089         *dPdu = interp(hull[1] - hull[0], hull[3] - hull[2], v);
00090         *dPdv = interp(hull[2] - hull[0], hull[3] - hull[1], u);
00091     }
00092 }
00093 
00094 BoundBox LinearQuadPatch::bound()
00095 {
00096     BoundBox bbox;
00097 
00098     for(int i = 0; i < 4; i++)
00099         bbox.grow(hull[i]);
00100     
00101     return bbox;
00102 }
00103 
00104 /* Linear Triangle Patch */
00105 
00106 void LinearTrianglePatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
00107 {
00108     *P = u*hull[0] + v*hull[1] + (1.0f - u - v)*hull[2];
00109 
00110     if(dPdu && dPdv) {
00111         *dPdu = hull[0] - hull[2];
00112         *dPdv = hull[1] - hull[2];
00113     }
00114 }
00115 
00116 BoundBox LinearTrianglePatch::bound()
00117 {
00118     BoundBox bbox;
00119 
00120     for(int i = 0; i < 3; i++)
00121         bbox.grow(hull[i]);
00122     
00123     return bbox;
00124 }
00125 
00126 /* Bicubic Patch */
00127 
00128 void BicubicPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
00129 {
00130     decasteljau_bicubic(P, dPdu, dPdv, hull, u, v);
00131 }
00132 
00133 BoundBox BicubicPatch::bound()
00134 {
00135     BoundBox bbox;
00136 
00137     for(int i = 0; i < 16; i++)
00138         bbox.grow(hull[i]);
00139     
00140     return bbox;
00141 }
00142 
00143 /* Bicubic Patch with Tangent Fields */
00144 
00145 void BicubicTangentPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
00146 {
00147     decasteljau_bicubic(P, NULL, NULL, hull, u, v);
00148 
00149     if(dPdu) *dPdu = decasteljau_tangent(utan, u, v);
00150     if(dPdv) *dPdv = decasteljau_tangent(vtan, v, u);
00151 }
00152 
00153 BoundBox BicubicTangentPatch::bound()
00154 {
00155     BoundBox bbox;
00156 
00157     for(int i = 0; i < 16; i++)
00158         bbox.grow(hull[i]);
00159     
00160     return bbox;
00161 }
00162 
00163 /* Gregory Patch */
00164 
00165 static float no_zero_div(float f)
00166 {
00167     if(f == 0.0f) return 1.0f;
00168     return f;
00169 }
00170 
00171 void GregoryQuadPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
00172 {
00173     float3 bicubic[16];
00174 
00175     float U = 1 - u;
00176     float V = 1 - v;
00177 
00178     /*  8     9     10     11
00179      * 12   0\1     2/3    13
00180      * 14   4/5     6\7    15
00181      * 16    17     18     19
00182      */
00183 
00184     bicubic[5] = (u*hull[1] + v*hull[0])/no_zero_div(u + v);
00185     bicubic[6] = (U*hull[2] + v*hull[3])/no_zero_div(U + v);
00186     bicubic[9] = (u*hull[5] + V*hull[4])/no_zero_div(u + V);
00187     bicubic[10] = (U*hull[6] + V*hull[7])/no_zero_div(U + V);
00188 
00189     // Map gregory control points to bezier control points.
00190     bicubic[0] = hull[8];
00191     bicubic[1] = hull[9];
00192     bicubic[2] = hull[10];
00193     bicubic[3] = hull[11];
00194     bicubic[4] = hull[12];
00195     bicubic[7] = hull[13];
00196     bicubic[8] = hull[14];
00197     bicubic[11] = hull[15];
00198     bicubic[12] = hull[16];
00199     bicubic[13] = hull[17];
00200     bicubic[14] = hull[18];
00201     bicubic[15] = hull[19];
00202 
00203     decasteljau_bicubic(P, dPdu, dPdv, bicubic, u, v);
00204 }
00205 
00206 BoundBox GregoryQuadPatch::bound()
00207 {
00208     BoundBox bbox;
00209 
00210     for(int i = 0; i < 20; i++)
00211         bbox.grow(hull[i]);
00212     
00213     return bbox;
00214 }
00215 
00216 void GregoryTrianglePatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
00217 {
00218     /*            6
00219      *            
00220      *      14   0/1   7
00221      *                        
00222      *    13   5/4     3\2   8
00223      *             
00224      * 12      11       10      9
00225      */
00226 
00227     float w = 1 - u - v;
00228     float uu = u * u;
00229     float vv = v * v;
00230     float ww = w * w;
00231     float uuu = uu * u;
00232     float vvv = vv * v;
00233     float www = ww * w;
00234 
00235     float U = 1 - u;
00236     float V = 1 - v;
00237     float W = 1 - w;
00238 
00239     float3 C0 = ( v*U * hull[5] + u*V * hull[4] ) / no_zero_div(v*U + u*V);
00240     float3 C1 = ( w*V * hull[3] + v*W * hull[2] ) / no_zero_div(w*V + v*W);
00241     float3 C2 = ( u*W * hull[1] + w*U * hull[0] ) / no_zero_div(u*W + w*U);
00242 
00243     *P =
00244         (hull[12] * www + 3*hull[11] * ww*u + 3*hull[10] * w*uu + hull[ 9]*uuu) * (w + u) +
00245         (hull[ 9] * uuu + 3*hull[ 8] * uu*v + 3*hull[ 7] * u*vv + hull[ 6]*vvv) * (u + v) +
00246         (hull[ 6] * vvv + 3*hull[14] * vv*w + 3*hull[13] * v*ww + hull[12]*www) * (v + w) -
00247         (hull[12] * www*w + hull[ 9] * uuu*u + hull[ 6] * vvv*v) +
00248         12*(C0 * u*v*ww + C1 * uu*v*w   + C2 * u*vv*w);
00249 
00250     if(dPdu || dPdv) {
00251         float3 E1 = (hull[12]*www + 3*hull[11]*ww*u + 3*hull[10]*w*uu + hull[ 9]*uuu);
00252         float3 E2 = (hull[ 9]*uuu + 3*hull[ 8]*uu*v + 3*hull[ 7]*u*vv + hull[ 6]*vvv);
00253         float3 E3 = (hull[ 6]*vvv + 3*hull[14]*vv*w + 3*hull[13]*v*ww + hull[12]*www);
00254 
00255         if(dPdu) {
00256             float3 E1u = 3*( - hull[12]*ww + hull[11]*(ww-2*u*w) +   hull[10]*(2*u*w-uu) + hull[ 9]*uu);
00257             float3 E2u = 3*(   hull[ 9]*uu + 2*hull[ 8]*u*v      +   hull[ 7]*vv         );
00258             float3 E3u = 3*(            - hull[14]*vv        - 2*hull[13]*v*w       - hull[12]*ww);
00259             float3 Su  = 4*( -hull[12]*www + hull[9]*uuu);
00260             float3 Cu  = 12*( C0*(ww*v-2*u*v*w) + C1*(2*u*v*w-uu*v) + C2*vv*(w-u) );
00261 
00262             *dPdu = E1u*(w+u) + (E2+E2u*(u+v)) + (E3u*(v+w)-E3) - Su + Cu;
00263         }
00264 
00265         if(dPdv) {
00266             float3 E1v = 3*(-hull[12]*ww  - 2*hull[11]*w*u       -   hull[10]*uu         );
00267             float3 E2v = 3*(              hull[ 8]*uu        + 2*hull[ 7]*u*v       + hull[ 6]*vv);
00268             float3 E3v = 3*( hull[ 6]*vv  +  hull[14]*(2*w*v-vv) +   hull[13]*(ww-2*w*v) - hull[12]*ww);
00269             float3 Sv  = 4*(-hull[12]*www +  hull[ 6]*vvv);
00270             float3 Cv  = 12*(C0*(u*ww-2*u*v*w) + C1*uu*(w-v) + C2*(2*u*v*w-u*vv));
00271 
00272             *dPdv = ((E1v*(w+u)-E1) + (E2+E2v*(u+v)) + E3v*(v+w) - Sv + Cv );
00273         }
00274     }
00275 }
00276 
00277 BoundBox GregoryTrianglePatch::bound()
00278 {
00279     BoundBox bbox;
00280 
00281     for(int i = 0; i < 20; i++)
00282         bbox.grow(hull[i]);
00283     
00284     return bbox;
00285 }
00286 
00287 CCL_NAMESPACE_END
00288