00001 /*!@file GUI/SuperQuadric.C 3D rendering SuperQuadric */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Lior Elazary <elazary@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/GUI/SuperQuadric.C $ 00035 // $Id: SuperQuadric.C 13070 2010-03-28 15:59:21Z lior $ 00036 // 00037 00038 00039 #ifndef SuperQuadric_C_DEFINED 00040 #define SuperQuadric_C_DEFINED 00041 00042 #include "GUI/SuperQuadric.H" 00043 #include <math.h> 00044 #include <stdio.h> 00045 #include <stdlib.h> 00046 00047 namespace SuperQuadricFunc 00048 { 00049 00050 //Helper functions 00051 00052 /* Returns the sign of x */ 00053 float sgnf ( float x ) { 00054 if ( x < 0 ) 00055 return -1; 00056 if ( x > 0 ) 00057 return 1; 00058 return 0; 00059 } 00060 00061 /* Returns the absolute value of x */ 00062 float absf ( float x ) { 00063 if ( x < 0 ) 00064 return -x; 00065 return x; 00066 } 00067 00068 /* sqC (v, n) 00069 * This function implements the c(v,n) utility function 00070 * 00071 * c(v,n) = sgnf(cos(v)) * |cos(v)|^n 00072 */ 00073 float sqC ( float v, float n ) { 00074 return sgnf((float)cos(v)) * (float)powf(absf((float)cos(v)),n); 00075 } 00076 00077 /* sqCT (v, n, alpha) 00078 * This function implements the CT(v,n,alpha) utility function 00079 * 00080 * CT(v,n,alpha) = alpha + c(v,n) 00081 */ 00082 float sqCT ( float v, float n, float alpha ) { 00083 return alpha + sqC(v,n); 00084 } 00085 00086 /* sqS (v, n) 00087 * This function implements the s(v,n) utility function 00088 * 00089 * s(v,n) = sgnf(sin(v)) * |sin(v)|^n 00090 */ 00091 float sqS ( float v, float n ) { 00092 return sgnf((float)sin(v)) * (float)powf(absf((float)sin(v)),n); 00093 } 00094 00095 00096 void taper(float *x, float *y, float *z, 00097 float az, float Kx, float Ky) 00098 { 00099 00100 *x = ( (Kx/az) * *z + 1) * *x; 00101 *y = ( (Ky/az) * *z + 1) * *y; 00102 00103 } 00104 00105 00106 } 00107 // ###################################################################### 00108 SuperQuadric::SuperQuadric() 00109 { 00110 itsUseDisplayList = false; 00111 itsUseTexture = false; 00112 00113 its_u_segs = 20; 00114 its_v_segs = 20; 00115 } 00116 00117 SuperQuadric::~SuperQuadric() 00118 { 00119 } 00120 00121 00122 00123 void SuperQuadric::ellipsoid ( float a1, float a2, float a3, 00124 float u, float v, float n, float e, 00125 float *x, float *y, float *z, 00126 float *nx, float *ny, float *nz ) 00127 { 00128 *x = a1 * SuperQuadricFunc::sqC (u, n) * SuperQuadricFunc::sqC (v, e); 00129 *y = a2 * SuperQuadricFunc::sqC (u, n) * SuperQuadricFunc::sqS (v, e); 00130 *z = a3 * SuperQuadricFunc::sqS (u, n); 00131 00132 //taper(x, y, z, a3, 0, 0); 00133 00134 *nx= SuperQuadricFunc::sqC (u, 2 - n) * SuperQuadricFunc::sqC (v, 2 - e) / a1; 00135 *ny= SuperQuadricFunc::sqC (u, 2 - n) * SuperQuadricFunc::sqS (v, 2 - e) / a2; 00136 *nz= SuperQuadricFunc::sqS (u, 2 - n) / a3; 00137 } 00138 00139 void SuperQuadric::toroid ( float a1, float a2, float a3, 00140 float u, float v, 00141 float n, float e, float alpha, 00142 float *x, float *y, float *z, float *nx, float *ny, float *nz ) 00143 { 00144 float A1, A2, A3; 00145 A1 = 1 / (a1 + alpha); 00146 A2 = 1 / (a2 + alpha); 00147 A3 = 1 / (a3 + alpha); 00148 *x = A1 * SuperQuadricFunc::sqCT (u, e, alpha) * SuperQuadricFunc::sqC (v, n); 00149 *y = A2 * SuperQuadricFunc::sqCT (u, e, alpha) * SuperQuadricFunc::sqS (v, n); 00150 *z = A3 * SuperQuadricFunc::sqS (u, e); 00151 00152 *nx= SuperQuadricFunc::sqC (u, 2 - e) * SuperQuadricFunc::sqC (v, 2 - n) / A1; 00153 *ny= SuperQuadricFunc::sqC (u, 2 - e) * SuperQuadricFunc::sqS (v, 2 - n) / A2; 00154 *nz= SuperQuadricFunc::sqS (u, 2 - e) / A3; 00155 } 00156 00157 void SuperQuadric::solidEllipsoid () 00158 { 00159 //TODO: This can be made more effficent by using lookup tables 00160 //Since some vetices share the same calculation (4 calc for the same vertex), 00161 //they can be stored //into a temporary lookuptable and puuled when needed. 00162 //Use CULLing 00163 // 00164 float U, dU, V, dV; 00165 float S, dS, T, dT; 00166 int X, Y; /* for looping */ 00167 float x, y, z; 00168 float nx, ny, nz; 00169 00170 /* Calculate delta variables */ 00171 dU = (float)(its_u2 - its_u1) / (float)its_u_segs; 00172 dV = (float)(its_v2 - its_v1) / (float)its_v_segs; 00173 dS = (float)(its_s2 - its_s1) / (float)its_u_segs; 00174 dT = (float)(its_t2 - its_t1) / (float)its_v_segs; 00175 00176 glDisable (GL_CULL_FACE); //Disable cull for now, this will make things slower, and should eventually figured out 00177 glEnable (GL_NORMALIZE); //To normalize the normals for lightting conditions 00178 00179 /* If we're going to make a display list then start it */ 00180 if ( itsUseDisplayList ) 00181 glNewList ( itsGlListId, GL_COMPILE ); 00182 00183 /* Initialize variables for loop */ 00184 U = its_u1; 00185 S = its_s1; 00186 glBegin ( GL_QUADS ); 00187 for ( Y = 0; Y < its_u_segs; Y++ ) { 00188 /* Initialize variables for loop */ 00189 V = its_v1; 00190 T = its_t1; 00191 for ( X = 0; X < its_v_segs; X++ ) { 00192 /* VERTEX #1 */ 00193 ellipsoid (its_a1, its_a2, its_a3, 00194 U, V, 00195 its_n, its_e, 00196 &x, &y, &z, &nx, &ny, &nz ); 00197 glNormal3f ( nx, ny, nz ); 00198 glTexCoord2f ( S, T ); 00199 glVertex3f ( x, y, z ); 00200 00201 /* VERTEX #2 */ 00202 ellipsoid (its_a1, its_a2, its_a3, 00203 U + dU, V, 00204 its_n, its_e, 00205 &x, &y, &z, &nx, &ny, &nz ); 00206 glNormal3f ( nx, ny, nz ); 00207 glTexCoord2f ( S + dS, T ); 00208 glVertex3f ( x, y, z ); 00209 00210 /* VERTEX #3 */ 00211 ellipsoid (its_a1, its_a2, its_a3, 00212 U + dU, V + dV, 00213 its_n, its_e, 00214 &x, &y, &z, &nx, &ny, &nz ); 00215 glNormal3f ( nx, ny, nz ); 00216 glTexCoord2f ( S + dS, T + dT ); 00217 glVertex3f ( x, y, z ); 00218 00219 /* VERTEX #4 */ 00220 ellipsoid (its_a1, its_a2, its_a3, 00221 U, V + dV, 00222 its_n, its_e, 00223 &x, &y, &z, &nx, &ny, &nz ); 00224 glNormal3f ( nx, ny, nz ); 00225 glTexCoord2f ( S, T + dT ); 00226 glVertex3f ( x, y, z ); 00227 00228 /* Update variables for next loop */ 00229 V += dV; 00230 T += dT; 00231 } 00232 /* Update variables for next loop */ 00233 S += dS; 00234 U += dU; 00235 } 00236 glEnd ( ); 00237 00238 /* If we're making a display list then stop */ 00239 if ( itsUseDisplayList ) 00240 glEndList ( ); 00241 glEnable (GL_CULL_FACE); 00242 glDisable (GL_NORMALIZE); 00243 00244 } 00245 00246 void SuperQuadric::solidToroid () 00247 { 00248 float U, dU, V, dV; 00249 float S, dS, T, dT; 00250 int X, Y; /* for looping */ 00251 float x, y, z; 00252 float nx, ny, nz; 00253 00254 /* Calculate delta variables */ 00255 dU = (float)(its_u2 - its_u1) / its_u_segs; 00256 dV = (float)(its_v2 - its_v1) / its_v_segs; 00257 dS = (float)(its_s2 - its_s1) / its_u_segs; 00258 dT = (float)(its_t2 - its_t1) / its_v_segs; 00259 00260 glDisable (GL_CULL_FACE); //Disable cull for now, this will make things slower, and should eventually figured out 00261 00262 glEnable (GL_NORMALIZE); //To normalize the normals for lightting conditions 00263 00264 /* If we're going to make a display list then start it */ 00265 if (itsUseDisplayList ) 00266 glNewList ( itsGlListId, GL_COMPILE ); 00267 00268 /* Initialize variables for loop */ 00269 U = its_u1; 00270 S = its_s1; 00271 glBegin ( GL_QUADS ); 00272 for ( Y = 0; Y < its_u_segs; Y++ ) { 00273 /* Initialize variables for loop */ 00274 V = its_v1; 00275 T = its_t1; 00276 for ( X = 0; X < its_v_segs; X++ ) { 00277 /* VERTEX #1 */ 00278 toroid ( its_a1, its_a2, its_a3, 00279 U, V, 00280 its_n, its_e, its_alpha, 00281 &x, &y, &z, 00282 &nx, &ny, &nz ); 00283 00284 glNormal3f ( nx, ny, nz ); 00285 glTexCoord2f ( S, T ); 00286 glVertex3f ( x, y, z ); 00287 00288 /* VERTEX #2 */ 00289 toroid ( its_a1, its_a2, its_a3, 00290 U + dU, V, 00291 its_n, its_e, its_alpha, 00292 &x, &y, &z, &nx, &ny, &nz ); 00293 glNormal3f ( nx, ny, nz ); 00294 glTexCoord2f ( S + dS, T ); 00295 glVertex3f ( x, y, z ); 00296 00297 /* VERTEX #3 */ 00298 toroid ( its_a1, its_a2, its_a3, 00299 U + dU, V + dV, 00300 its_n, its_e, its_alpha, 00301 &x, &y, &z, &nx, &ny, &nz ); 00302 glNormal3f ( nx, ny, nz ); 00303 glTexCoord2f ( S + dS, T + dT ); 00304 glVertex3f ( x, y, z ); 00305 00306 /* VERTEX #4 */ 00307 toroid ( its_a1, its_a2, its_a3, 00308 U, V + dV, 00309 its_n, its_e, its_alpha, 00310 &x, &y, &z, &nx, &ny, &nz ); 00311 glNormal3f ( nx, ny, nz ); 00312 glTexCoord2f ( S, T + dT); 00313 glVertex3f ( x, y, z ); 00314 00315 /* Update variables for next loop */ 00316 V += dV; 00317 T += dT; 00318 } 00319 /* Update variables for next loop */ 00320 S += dS; 00321 U += dU; 00322 } 00323 glEnd ( ); 00324 00325 /* If we're making a display list then stop */ 00326 if ( itsUseDisplayList ) 00327 glEndList ( ); 00328 glEnable (GL_CULL_FACE); 00329 glDisable (GL_NORMALIZE); 00330 } 00331 00332 float SuperQuadric::ellipsoidInsideOut (float x, float y, float z ) 00333 { 00334 float result; 00335 result = powf ( powf ( x / its_a1, 2 / its_e ) + 00336 powf ( y / its_a2, 2 / its_e ), its_e / its_n ) + 00337 powf ( z / its_a3, 2 / its_n ); 00338 return result; 00339 } 00340 00341 float SuperQuadric::toroidInsideOut ( float x, float y, float z ) 00342 { 00343 float result; 00344 result = powf ( powf ( powf ( x / its_a1, 2 / its_e ) + powf ( y / its_a2, 2 / its_e ), 00345 its_e / 2 ) - its_alpha, 2 / its_n ) + powf ( z / its_a3, 2 / its_n ); 00346 return result; 00347 } 00348 00349 void SuperQuadric::solidSphere ( float radius ) { 00350 its_a1 = its_a2 = its_a3 = radius; 00351 its_n = 1.0f; 00352 its_e = 1.0f; 00353 its_u1 = -M_PI / 2; 00354 its_u2 = M_PI / 2; 00355 its_v1 = -M_PI; 00356 its_v2 = M_PI; 00357 its_s1 = 0.0f; 00358 its_t1 = 0.0f; 00359 its_s2 = 1.0f; 00360 its_t2 = 1.0f; 00361 solidEllipsoid (); 00362 } 00363 00364 void SuperQuadric::solidCylinder ( float radius ) { 00365 its_a1 = radius; 00366 its_a2 = radius; 00367 its_a3 = radius; 00368 its_n = 0.0f; 00369 its_e = 1.0f; 00370 its_u1 = -M_PI / 2; 00371 its_u2 = M_PI / 2; 00372 its_v1 = -M_PI; 00373 its_v2 = M_PI; 00374 its_s1 = 0.0f; 00375 its_t1 = 0.0f; 00376 its_s2 = 1.0f; 00377 its_t2 = 1.0f; 00378 solidEllipsoid(); 00379 } 00380 00381 void SuperQuadric::solidStar ( float radius ) { 00382 00383 its_a1 = its_a2 = its_a3 = radius; 00384 its_n = 4.0f; 00385 its_e = 4.0f; 00386 its_u1 = -M_PI / 2; 00387 its_u2 = M_PI / 2; 00388 its_v1 = -M_PI; 00389 its_v2 = M_PI; 00390 its_s1 = 0.0f; 00391 its_t1 = 0.0f; 00392 its_s2 = 1.0f; 00393 its_t2 = 1.0f; 00394 solidEllipsoid(); 00395 } 00396 00397 void SuperQuadric::solidDoublePyramid ( float radius ) { 00398 its_a1 = its_a2 = its_a3 = radius; 00399 its_n = 2.0f; 00400 its_e = 2.0f; 00401 its_u1 = -M_PI / 2; 00402 its_u2 = M_PI / 2; 00403 its_v1 = -M_PI; 00404 its_v2 = M_PI; 00405 its_s1 = 0.0f; 00406 its_t1 = 0.0f; 00407 its_s2 = 1.0f; 00408 its_t2 = 1.0f; 00409 solidEllipsoid(); 00410 } 00411 00412 void SuperQuadric::solidTorus ( float radius1, float radius2 ) 00413 { 00414 its_a1 = its_a2 = its_a3 = (radius1 + radius2)/2.0f; 00415 its_alpha = radius2; 00416 its_n = 1.0f; 00417 its_e = 1.0f; 00418 its_u1 = -M_PI; 00419 its_u2 = M_PI; 00420 its_v1 = -M_PI; 00421 its_v2 = M_PI; 00422 its_s1 = 0.0f; 00423 its_t1 = 0.0f; 00424 its_s2 = 1.0f; 00425 its_t2 = 1.0f; 00426 solidToroid(); 00427 } 00428 00429 void SuperQuadric::solidPineappleSlice ( float radius1, float radius2 ) 00430 { 00431 its_a1 = its_a2 = its_a3 = (radius1 + radius2)/2.0f; 00432 its_alpha = radius2; 00433 its_n = 0.0f; 00434 its_e = 1.0f; 00435 its_u1 = -M_PI; 00436 its_u2 = M_PI; 00437 its_v1 = -M_PI; 00438 its_v2 = M_PI; 00439 its_s1 = 0.0f; 00440 its_t1 = 0.0f; 00441 its_s2 = 1.0f; 00442 its_t2 = 1.0f; 00443 solidToroid(); 00444 } 00445 00446 void SuperQuadric::solidPillow ( float radius ) { 00447 its_a1 = its_a2 = its_a3 = radius; 00448 its_n = 1.0f; 00449 its_e = 0.0f; 00450 its_u1 = -M_PI / 2; 00451 its_u2 = M_PI / 2; 00452 its_v1 = -M_PI; 00453 its_v2 = M_PI; 00454 its_s1 = 0.0f; 00455 its_t1 = 0.0f; 00456 its_s2 = 1.0f; 00457 its_t2 = 1.0f; 00458 solidEllipsoid(); 00459 } 00460 00461 void SuperQuadric::solidSquareTorus ( float radius1, float radius2 ) 00462 { 00463 its_a1 = its_a2 = its_a3 = (radius1 + radius2)/2.0f; 00464 its_alpha = radius2; 00465 its_n = 0.2f; 00466 its_e = 0.2f; 00467 its_u1 = -M_PI; 00468 its_u2 = M_PI; 00469 its_v1 = -M_PI; 00470 its_v2 = M_PI; 00471 its_s1 = 0.0f; 00472 its_t1 = 0.0f; 00473 its_s2 = 1.0f; 00474 its_t2 = 1.0f; 00475 solidToroid(); 00476 } 00477 00478 void SuperQuadric::solidPinchedTorus ( float radius1, float radius2 ) 00479 { 00480 its_a1 = its_a2 = its_a3 = (radius1 + radius2)/2.0f; 00481 its_alpha = radius2; 00482 its_n = 1.0f; 00483 its_e = 4.0f; 00484 its_u1 = -M_PI; 00485 its_u2 = M_PI; 00486 its_v1 = -M_PI; 00487 its_v2 = M_PI; 00488 its_s1 = 0.0f; 00489 its_t1 = 0.0f; 00490 its_s2 = 1.0f; 00491 its_t2 = 1.0f; 00492 solidToroid(); 00493 } 00494 00495 void SuperQuadric::solidRoundCube ( float radius ) { 00496 its_a1 = its_a2 = its_a3 = radius; 00497 its_n = 0.2f; 00498 its_e = 0.2f; 00499 its_u1 = -M_PI / 2; 00500 its_u2 = M_PI / 2; 00501 its_v1 = -M_PI; 00502 its_v2 = M_PI; 00503 its_s1 = 0.0f; 00504 its_t1 = 0.0f; 00505 its_s2 = 1.0f; 00506 its_t2 = 1.0f; 00507 solidEllipsoid(); 00508 } 00509 00510 #endif