|
Blender
V2.59
|
00001 /* 00002 * $Id: LOD_NdQuadric.cpp 35147 2011-02-25 10:47:28Z jesterking $ 00003 * ***** BEGIN GPL LICENSE BLOCK ***** 00004 * 00005 * This program is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU General Public License 00007 * as published by the Free Software Foundation; either version 2 00008 * of the License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software Foundation, 00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 * 00019 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00020 * All rights reserved. 00021 * 00022 * The Original Code is: all of this file. 00023 * 00024 * Contributor(s): none yet. 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00034 #include "LOD_NdQuadric.h" 00035 00036 #include <iostream> 00037 00038 // for Lower Upper decompostion code. 00039 #include "TNT/lu.h" 00040 00041 //soon to be template parameter. 00042 #define MAT_SIZE 3 00043 00044 LOD_NdQuadric:: 00045 LOD_NdQuadric( 00046 const MT_Vector3 & vec, 00047 const MT_Scalar & offset 00048 ): 00049 m_q(vec,offset), 00050 m_prop_grad1(int(MAT_SIZE),MT_Scalar(0)), 00051 m_prop_grad2(int(MAT_SIZE),MT_Scalar(0)), 00052 m_prop_grad3(int(MAT_SIZE),MT_Scalar(0)), 00053 m_bbottom(int(MAT_SIZE),MT_Scalar(0)), 00054 m_diag (int(MAT_SIZE),MT_Scalar(0)) 00055 { 00056 // nothing to do 00057 } 00058 // Initialize a quadric from a linear functional describing 00059 // the property gradient.pos is the position where this 00060 // functional is placed in the array. 00061 00062 LOD_NdQuadric:: 00063 LOD_NdQuadric( 00064 const MT_Vector3 & vec, 00065 const MT_Scalar & offset, 00066 int pos 00067 ): 00068 m_q(vec,offset), 00069 m_prop_grad1(int(MAT_SIZE),MT_Scalar(0)), 00070 m_prop_grad2(int(MAT_SIZE),MT_Scalar(0)), 00071 m_prop_grad3(int(MAT_SIZE),MT_Scalar(0)), 00072 m_bbottom(int(MAT_SIZE),MT_Scalar(0)), 00073 m_diag (int(MAT_SIZE),MT_Scalar(0)) 00074 { 00075 m_prop_grad1[pos] = -vec[0]; 00076 m_prop_grad2[pos] = -vec[1]; 00077 m_prop_grad3[pos] = -vec[2]; 00078 00079 m_bbottom[pos] = -offset; 00080 m_diag[pos] = MT_Scalar(1); 00081 } 00082 00083 00084 LOD_NdQuadric:: 00085 LOD_NdQuadric( 00086 ): 00087 m_prop_grad1(int(MAT_SIZE),MT_Scalar(0)), 00088 m_prop_grad2(int(MAT_SIZE),MT_Scalar(0)), 00089 m_prop_grad3(int(MAT_SIZE),MT_Scalar(0)), 00090 m_bbottom(int(MAT_SIZE),MT_Scalar(0)), 00091 m_diag (int(MAT_SIZE),MT_Scalar(0)), 00092 m_q() 00093 { 00094 } 00095 00096 00097 00098 // This class also has the default copy constructors 00099 // available. 00100 00101 void 00102 LOD_NdQuadric:: 00103 Tensor( 00104 TNT::Matrix<MT_Scalar> &tensor 00105 ) const { 00106 00107 // Set the matrix to zero 00108 tensor = 0; 00109 00110 // Fill in the matrix values from d variables. 00111 00112 MT_Matrix3x3 tensor3x3 = m_q.Tensor(); 00113 int i,j; 00114 00115 for (j=0; j<=2; j++) { 00116 for (i=0; i<=2; i++) { 00117 tensor[j][i] = tensor3x3[j][i]; 00118 } 00119 } 00120 00121 // now the diagonal entry. 00122 00123 for (i=3;i <3+MAT_SIZE;++i) { 00124 tensor[i][i] = m_diag[i-3]; 00125 } 00126 00127 // now the property gradients rows and symmetrical columns 00128 00129 for (i=3; i < 3+MAT_SIZE; i++) { 00130 tensor[0][i] = m_prop_grad1[i-3]; 00131 tensor[i][0] = m_prop_grad1[i-3]; 00132 00133 tensor[1][i] = m_prop_grad2[i-3]; 00134 tensor[i][1] = m_prop_grad2[i-3]; 00135 00136 tensor[2][i] = m_prop_grad3[i-3]; 00137 tensor[i][2] = m_prop_grad3[i-3]; 00138 } 00139 00140 00141 } 00142 00143 void 00144 LOD_NdQuadric:: 00145 Vector( 00146 TNT::Vector<MT_Scalar> &vector 00147 ) const { 00148 int i; 00149 00150 MT_Vector3 q_vec = m_q.Vector(); 00151 00152 vector[0] = q_vec[0]; 00153 vector[1] = q_vec[1]; 00154 vector[2] = q_vec[2]; 00155 00156 for (i = 3; i < 3 + MAT_SIZE; ++i) { 00157 vector[i] = m_bbottom[i-3]; 00158 } 00159 } 00160 00161 void 00162 LOD_NdQuadric:: 00163 Clear( 00164 MT_Scalar val 00165 ) { 00166 m_q.Clear(val); 00167 m_prop_grad1 = val; 00168 m_prop_grad2 = val; 00169 m_prop_grad3 = val; 00170 m_bbottom = val; 00171 m_diag = val; 00172 }; 00173 00174 LOD_NdQuadric & 00175 LOD_NdQuadric:: 00176 operator=( 00177 const LOD_NdQuadric& Q 00178 ){ 00179 00180 m_q = Q.m_q; 00181 m_prop_grad1 = Q.m_prop_grad1; 00182 m_prop_grad2 = Q.m_prop_grad2; 00183 m_prop_grad3 = Q.m_prop_grad3; 00184 m_bbottom = Q.m_bbottom; 00185 m_diag = Q.m_diag; 00186 00187 return (*this); 00188 } 00189 00190 LOD_NdQuadric& 00191 LOD_NdQuadric:: 00192 operator+=( 00193 const LOD_NdQuadric& Q 00194 ){ 00195 m_q += Q.m_q; 00196 TNT::vectoradd(m_prop_grad1,Q.m_prop_grad1); 00197 TNT::vectoradd(m_prop_grad2,Q.m_prop_grad2); 00198 TNT::vectoradd(m_prop_grad3,Q.m_prop_grad3); 00199 TNT::vectoradd(m_bbottom,Q.m_bbottom); 00200 TNT::vectoradd(m_diag,Q.m_diag); 00201 00202 return (*this); 00203 } 00204 00205 LOD_NdQuadric& 00206 LOD_NdQuadric:: 00207 operator*=( 00208 const MT_Scalar & s 00209 ){ 00210 // multiply everything by s 00211 00212 m_q *= s; 00213 TNT::vectorscale(m_prop_grad1,s); 00214 TNT::vectorscale(m_prop_grad2,s); 00215 TNT::vectorscale(m_prop_grad3,s); 00216 TNT::vectorscale(m_bbottom,s); 00217 TNT::vectorscale(m_diag,s); 00218 00219 return (*this); 00220 } 00221 00222 MT_Scalar 00223 LOD_NdQuadric:: 00224 Evaluate( 00225 const TNT::Vector<MT_Scalar> & vec 00226 ) const { 00227 // compute the quadric error cost for the vector. 00228 00229 //FIXME very inefficient memory usage here 00230 //Way to many computations-these are symmetric! 00231 00232 TNT::Matrix<MT_Scalar> Atensor(3+MAT_SIZE,3+MAT_SIZE,MT_Scalar(0)); 00233 Tensor(Atensor); 00234 00235 TNT::Vector<MT_Scalar> Bvector(3+MAT_SIZE); 00236 Vector(Bvector); 00237 00238 TNT::Vector<MT_Scalar> temp1(3+MAT_SIZE); 00239 00240 TNT::matmult(temp1,Atensor,vec); 00241 00242 return TNT::dot_prod(vec,temp1) + 2*TNT::dot_prod(Bvector,vec) + m_q.Scalar(); 00243 } 00244 00245 00246 bool 00247 LOD_NdQuadric:: 00248 Optimize( 00249 TNT::Vector<MT_Scalar> & vec 00250 ) const { 00251 00252 // Return the solution to Tensor().invers() * Vector(); 00253 // Use lower upper decomposition --again we're creating 00254 // heap memory for this function. 00255 00256 TNT::Vector<TNT::Subscript> pivots(3+MAT_SIZE,0); 00257 TNT::Matrix<MT_Scalar> Atensor(3+MAT_SIZE,3+MAT_SIZE,MT_Scalar(0)); 00258 00259 Tensor(Atensor); 00260 Vector(vec); 00261 00262 // Find the decomposition of the matrix. If none available 00263 // matrix is singular return false. 00264 00265 if (TNT::LU_factor(Atensor,pivots)) { 00266 return false; 00267 } 00268 00269 if (TNT::LU_solve(Atensor,pivots,vec)) { 00270 return false; 00271 } 00272 00273 // Now we should return -Ainv(B)! 00274 00275 TNT::Vector<MT_Scalar>::iterator start = vec.begin(); 00276 TNT::Vector<MT_Scalar>::const_iterator end = vec.end(); 00277 00278 while (start != end) { 00279 *start = -(*start); 00280 ++start; 00281 } 00282 00283 #if 0 00284 std::cout << vec << "\n"; 00285 #endif 00286 return true; 00287 }; 00288 00289 00290 #undef MAT_SIZE