Blender V2.61 - r43446
|
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