00001 #include "Ellipsoid.h"
00002 #include "Error.h"
00003 #include "Types.h"
00004 #include "Rendergroup.h"
00005 #include "Program.h"
00006 #include "Stateset.h"
00007 #include "Sampler.h"
00008 #include "Vertexbuffer.h"
00009
00010 namespace RenderTools {
00011
00012
00013
00014 Ellipsoid::Ellipsoid( void ):
00015 Quadric(){
00016
00017 }
00018
00019 Ellipsoid::~Ellipsoid( void ){
00020
00021 }
00022
00023 PropertyPtr Ellipsoid::create( const XMLNodePtr & xml ){
00024 EllipsoidPtr p( new Ellipsoid() );
00025 p->setName( xml );
00026 p->createProperties();
00027 p->setProperties( xml, false );
00028 return( dynamic_pointer_cast< AbstractProperty, Ellipsoid >( p ) );
00029 }
00030
00031 void Ellipsoid::createProperties( void ){
00032 Quadric::createProperties();
00033 createProperty( this, "type", EllipsoidTypeStruct( & m_ellipsoidType ), getEllipsoidTypeEnums() );
00034 createProperty( this, "size", & m_size );
00035 createProperty( this, "exponents", & m_exponents );
00036 createProperty( this, "subdivisions", & m_subdiv );
00037 createProperty( this, "roundness", & m_roundness );
00038 createProperty( this, "normalizedUVCoords", BooleanStruct( & m_correctUV ) );
00039
00040 }
00041
00042 const string Ellipsoid::getTypeName( bool ofComponent ) const {
00043 return( "Ellipsoid" );
00044 }
00045
00046 void Ellipsoid::onInitialize( void ){
00047
00048 Quadric::onInitialize();
00049
00050 switch( m_ellipsoidType ){
00051 case SPHERE:
00052 m_exponents[0] = 1.0f;
00053 m_exponents[1] = 1.0f;
00054 break;
00055 case CYLINDER:
00056 m_exponents[0] = 0.1f;
00057 m_exponents[1] = 1.0f;
00058 break;
00059 case STAR:
00060 m_exponents[0] = 4.0f;
00061 m_exponents[1] = 4.0f;
00062 break;
00063 case DOUBLEPYRAMID:
00064 m_exponents[0] = 2.0f;
00065 m_exponents[1] = 2.0f;
00066 break;
00067 case PILLOW:
00068 m_exponents[0] = 1.0f;
00069 m_exponents[1] = 0.1f;
00070 break;
00071 case ROUNDCUBE:
00072 m_exponents[0] = 0.1f;
00073 m_exponents[1] = 0.1f;
00074 break;
00075 default:
00076 break;
00077 }
00078 m_exponents += m_roundness;
00079
00080 if( m_exponents[0] < 0.01f )m_exponents[0] = 0.01f;
00081 if( m_exponents[1] < 0.01f )m_exponents[1] = 0.01f;
00082
00083 if( m_correctUV ){
00084 solidEllipsoidWithUV();
00085 }
00086 else{
00087 solidEllipsoid();
00088 }
00089 }
00090
00093 void Ellipsoid::ellipsoid( double u, double v, double n, double e, Vec3 & pos, Vec3 & nor ) {
00095 u = - M_PI + u * 2.0 * M_PI;
00096 v = - 0.5 * M_PI + v * M_PI;
00097
00098 pos[0] = cvn( v, n ) * cvn( u, e );
00099 pos[1] = cvn( v, n ) * svn( u, e );
00100 pos[2] = svn( v, n );
00101
00102 Vec3 nx1,nx2,ny1,ny2;
00103 u -= 0.01;
00104 nx1[0] = cvn( v, n ) * cvn( u, e );
00105 nx1[1] = cvn( v, n ) * svn( u, e );
00106 nx1[2] = svn( v, n );
00107 u += 0.02;
00108 nx2[0] = cvn( v, n ) * cvn( u, e );
00109 nx2[1] = cvn( v, n ) * svn( u, e );
00110 nx2[2] = svn( v, n );
00111 v -= 0.01;
00112 ny1[0] = cvn( v, n ) * cvn( u, e );
00113 ny1[1] = cvn( v, n ) * svn( u, e );
00114 ny1[2] = svn( v, n );
00115 v += 0.02;
00116 ny2[0] = cvn( v, n ) * cvn( u, e );
00117 ny2[1] = cvn( v, n ) * svn( u, e );
00118 ny2[2] = svn( v, n );
00119
00120 Vec3 x = normalize( ( nx2 - nx1 ) );
00121 Vec3 y = normalize( ( ny2 - ny1 ) );
00122 Vec3 z = cross( x, y );
00123 nor[0] = z[0];
00124 nor[1] = z[1];
00125 nor[2] = z[2];
00126 }
00127
00131 void Ellipsoid::solidEllipsoid( ) {
00132
00133 GLint numQuadVertices = (GLint)m_subdiv[0] * ( (GLint)m_subdiv[1] - 2 ) * 4;
00134 GLint numTriFanVertices = (GLint)m_subdiv[0] + 2;
00135 GLuint vertex = 0;
00136
00137 VertexbufferPtr buffer( new Vertexbuffer() );
00138 buffer->addAttribute( 3, "vertex" );
00139 buffer->addAttribute( 2, "texcoord" );
00140 buffer->addAttribute( 3, "normal" );
00141 buffer->setUsage( GL_DYNAMIC_DRAW );
00142 buffer->setMode( GL_TRIANGLES );
00143 #ifdef GL_STATIC_DRAW
00144 buffer->setUsage( GL_STATIC_DRAW );
00145 #endif
00146 #ifdef GL_QUADS
00147 buffer->setMode( GL_QUADS );
00148 #endif
00149 buffer->setNumVertices( numQuadVertices );
00150 buffer->initialize();
00151
00152 double fx1, fy1, fx2, fy2;
00153 Vec3 nor[4], pos[4], uv[4];
00154 for( int y = 1; y < m_subdiv[ 1 ] - 1; y++ ) {
00155
00156 fy1 = (double)y / (double)m_subdiv[ 1 ];
00157 fy2 = (double)( y + 1 ) / (double)m_subdiv[ 1 ];
00158 for( int x = 0; x < m_subdiv[ 0 ]; x++ ) {
00159 fx1 = (double)x / (double)m_subdiv[ 0 ];
00160 fx2 = (double)( x + 1 ) / (double)m_subdiv[ 0 ];
00161
00162 ellipsoid( fx1, fy1, m_exponents[0], m_exponents[1], pos[0], nor[0] );
00163 uv[0] = Vec3( fx1, fy1, 0.0 );
00164 ellipsoid( fx2, fy1, m_exponents[0], m_exponents[1], pos[1], nor[1] );
00165 uv[1] = Vec3( fx2, fy1, 0.0 );
00166 ellipsoid( fx2, fy2, m_exponents[0], m_exponents[1], pos[2], nor[2] );
00167 uv[2] = Vec3( fx2, fy2, 0.0 );
00168 ellipsoid( fx1, fy2, m_exponents[0], m_exponents[1], pos[3], nor[3] );
00169 uv[3] = Vec3( fx1, fy2, 0.0 );
00170
00171 buffer->setVertexAttribute( vertex, 0, * ( pos[ 0 ] * m_size.xyz() ) );
00172 buffer->setVertexAttribute( vertex, 1, * uv[ 0 ] );
00173 buffer->setVertexAttribute( vertex, 2, * nor[ 0 ] );
00174 vertex++;
00175
00176 buffer->setVertexAttribute( vertex, 0, * ( pos[ 1 ] * m_size.xyz() ) );
00177 buffer->setVertexAttribute( vertex, 1, * uv[ 1 ] );
00178 buffer->setVertexAttribute( vertex, 2, * nor[ 1 ] );
00179 vertex++;
00180
00181 buffer->setVertexAttribute( vertex, 0, * ( pos[ 2 ] * m_size.xyz() ) );
00182 buffer->setVertexAttribute( vertex, 1, * uv[ 2 ] );
00183 buffer->setVertexAttribute( vertex, 2, * nor[ 2 ] );
00184 vertex++;
00185
00186 buffer->setVertexAttribute( vertex, 0, * ( pos[ 3 ] * m_size.xyz() ) );
00187 buffer->setVertexAttribute( vertex, 1, * uv[ 3 ] );
00188 buffer->setVertexAttribute( vertex, 2, * nor[ 3 ] );
00189 vertex++;
00190 }
00191 }
00192
00193 addVertexBuffer( buffer );
00194
00195 buffer = VertexbufferPtr( new Vertexbuffer() );
00196 buffer->addAttribute( 3, "vertex" );
00197 buffer->addAttribute( 2, "texcoord" );
00198 buffer->addAttribute( 3, "normal" );
00199 buffer->addAttribute( 4, "color" );
00200 #ifdef GL_STATIC_DRAW
00201 buffer->setUsage( GL_STATIC_DRAW );
00202 #endif
00203 #ifdef GL_TRIANGLE_FAN
00204 buffer->setMode( GL_TRIANGLE_FAN );
00205 #endif
00206 buffer->setNumVertices( numTriFanVertices );
00207 buffer->initialize();
00208
00209 vertex = 0;
00210
00211
00212
00213 ellipsoid( 0.0, 0.0, m_exponents[0], m_exponents[1], pos[0], nor[0] );
00214 uv[0] = Vec3( 0, 0, 0 );
00215 buffer->setVertexAttribute( vertex, 0, * ( pos[ 0 ] * m_size.xyz() ) );
00216 buffer->setVertexAttribute( vertex, 1, * uv[ 0 ] );
00217 buffer->setVertexAttribute( vertex, 2, * nor[ 0 ] );
00218 vertex++;
00219
00220 fy1 = (double)1.0 / (double)m_subdiv[ 1 ];
00221
00222 for( int x = (int)m_subdiv[ 0 ]; x >= 0; x-- ){
00223 fx1 = (double)x / (double)m_subdiv[ 0 ];
00224
00225 if( x == m_subdiv[ 0 ] ){
00226 fx1 = 0.0;
00227 }
00228
00229 ellipsoid( fx1, fy1 , m_exponents[0], m_exponents[1], pos[0], nor[0] );
00230 uv[0] = Vec3( fx1, fy1, 0 );
00231 buffer->setVertexAttribute( vertex, 0, * ( pos[ 0 ] * m_size.xyz() ) );
00232 buffer->setVertexAttribute( vertex, 1, * uv[ 0 ] );
00233 buffer->setVertexAttribute( vertex, 2, * nor[ 0 ] );
00234
00235 vertex++;
00236 }
00237
00238 addVertexBuffer( buffer );
00239
00240 buffer = VertexbufferPtr( new Vertexbuffer() );
00241 buffer->addAttribute( 3, "vertex" );
00242 buffer->addAttribute( 2, "texcoord" );
00243 buffer->addAttribute( 3, "normal" );
00244 buffer->addAttribute( 4, "color" );
00245 #ifdef GL_STATIC_DRAW
00246 buffer->setUsage( GL_STATIC_DRAW );
00247 #endif
00248 #ifdef GL_TRIANGLE_FAN
00249 buffer->setMode( GL_TRIANGLE_FAN );
00250 #endif
00251 buffer->setNumVertices( numTriFanVertices );
00252 buffer->initialize();
00253
00254 vertex = 0;
00255
00256
00257 ellipsoid( 0.0, 1.0, m_exponents[0], m_exponents[1], pos[0], nor[0] );
00258 uv[0] = Vec3( 0, 1, 0 );
00259 buffer->setVertexAttribute( vertex, 0, * ( pos[ 0 ] * m_size.xyz() ) );
00260 buffer->setVertexAttribute( vertex, 1, * uv[ 0 ] );
00261 buffer->setVertexAttribute( vertex, 2, * nor[ 0 ] );
00262 vertex++;
00263
00264 fy1 = (double) 1.0 - ( (double)1.0 / (double)m_subdiv[ 1 ] );
00265 for( int x = 0; x <= m_subdiv[ 0 ]; x++ ) {
00266 fx1 = (double)x / (double)m_subdiv[ 0 ];
00267
00268 if( x == m_subdiv[ 0 ] ){
00269 fx1 = 0.0;
00270 }
00271 ellipsoid( fx1, fy1 , m_exponents[0], m_exponents[1], pos[0], nor[0] );
00272 uv[0] = Vec3( fx1, fy1, 0 );
00273 buffer->setVertexAttribute( vertex, 0, * ( pos[ 0 ] * m_size.xyz() ) );
00274 buffer->setVertexAttribute( vertex, 1, * uv[ 0 ] );
00275 buffer->setVertexAttribute( vertex, 2, * nor[ 0 ] );
00276 vertex++;
00277 }
00278
00279 addVertexBuffer( buffer );
00280 }
00281
00282
00283 void Ellipsoid::solidEllipsoidWithUV( ) {
00284
00285 int X = (int)m_subdiv[0];
00286 int Y = (int)m_subdiv[1];
00287 int Z = (int)m_subdiv[2];
00288
00289 static const double cube[8][3] = { { -1.0, -1.0, -1.0 },
00290 { 1.0, -1.0, -1.0 },
00291 { 1.0, 1.0, -1.0 },
00292 { -1.0, 1.0, -1.0 },
00293 { -1.0, -1.0, 1.0 },
00294 { 1.0, -1.0, 1.0 },
00295 { 1.0, 1.0, 1.0 },
00296 { -1.0, 1.0, 1.0 } };
00297 static const int faces[6][4] = { { 3, 2, 1, 0 },
00298 { 1, 2, 6, 5 },
00299 { 4, 5, 6, 7 },
00300 { 4, 7, 3, 0 },
00301 { 0, 1, 5, 4 },
00302 { 2, 3, 7, 6 } };
00303 int subdiv[6][2] = { { X, Y },
00304 { Y, Z },
00305 { X, Y },
00306 { Y, Z },
00307 { X, Z },
00308 { X, Z } };
00309
00323
00324
00325 int numVertices = ( 2 * X * Y + 2 * Y * Z + 2 * X * Z ) * 4;
00326
00327 Patch * patch[6];
00328 float u, v;
00329 int s[2];
00330 Vec3 p[4];
00331 Vec3 q;
00332
00333 VertexbufferPtr buffer( new Vertexbuffer() );
00334 buffer->addAttribute( 3, "vertex" );
00335 buffer->addAttribute( 2, "texcoord" );
00336 buffer->addAttribute( 3, "normal" );
00337 #ifdef GL_STATIC_DRAW
00338 buffer->setUsage( GL_STATIC_DRAW );
00339 #endif
00340 #ifdef GL_QUADS
00341 buffer->setMode( GL_QUADS );
00342 #endif
00343 buffer->setNumVertices( numVertices );
00344 buffer->initialize();
00345 GLuint vertex = 0;
00346
00347
00348 for( int face = 0; face < 6; face++ ){
00349 s[0] = subdiv[face][0];
00350 s[1] = subdiv[face][1];
00351 patch[face] = new Patch( s[0] + 1, s[1] + 1 );
00352
00353
00354 for( int i = 0; i < 4; i++ ){
00355 p[i] = Vec3( cube[faces[face][i]][0], cube[faces[face][i]][1], cube[faces[face][i]][2] );
00356 }
00357 for( int x = 0; x <= s[0]; x++ ) {
00358 u = (float)x / (float)s[0];
00359 for( int y = 0; y <= s[1]; y++ ) {
00360 v = (float)y / (float)s[1];
00361 q = p[0] + ( p[1] - p[0] ) * u + ( p[3] - p[0] ) * v;
00362
00363 q[0] *= m_size[0];
00364 q[1] *= m_size[1];
00365 q[2] *= m_size[2];
00366
00367
00368 patch[face]->setVertex( x, y, findSurfaceLocal( q ), Vec2( u, v ) );
00369 }
00370 }
00371 }
00372 Mat4 m[5];
00373 Vec2 uv[5];
00375 for( int face = 0; face < 6; face++ ){
00376 s[0] = subdiv[face][0];
00377 s[1] = subdiv[face][1];
00378 for( int x = 1; x < s[0]; x++ ) {
00379 for( int y = 1; y < s[1]; y++ ) {
00380 patch[face]->getVertex( x, y, m[0], uv[0] );
00381 patch[face]->getVertex( x - 1, y, m[1], uv[1] );
00382 patch[face]->getVertex( x + 1, y, m[2], uv[2] );
00383 patch[face]->getVertex( x, y - 1, m[3], uv[3] );
00384 patch[face]->getVertex( x, y + 1, m[4], uv[4] );
00385 Vec3 n;
00386 for( int i = 0; i < 5; i++ ){
00387 n += m[i].getCol(2).xyz();
00388 }
00389 n /= 5.0f;
00390 m[0].setCol( 2, Vec4( n, 0.0f ) );
00391 patch[face]->setVertex( x, y, m[0], uv[0] );
00392 }
00393 }
00394 }
00396 for( int face = 0; face < 6; face++ ){
00397 s[0] = subdiv[face][0];
00398 s[1] = subdiv[face][1];
00399 for( int x = 0; x < s[0]; x++ ) {
00400 for( int y = 0; y < s[1]; y++ ) {
00401 patch[face]->getVertex( x, y, m[0], uv[0] );
00402 patch[face]->getVertex( x + 1, y, m[1], uv[1] );
00403 patch[face]->getVertex( x + 1, y + 1, m[2], uv[2] );
00404 patch[face]->getVertex( x, y + 1, m[3], uv[3] );
00405 for( int i = 0; i < 4; i++ ){
00406 buffer->setVertexAttribute( vertex, 0, * m[ i ].getCol(2) );
00407 buffer->setVertexAttribute( vertex, 1, * uv[ i ] );
00408 buffer->setVertexAttribute( vertex, 2, * m[i].getCol(3) );
00409 vertex++;
00410 }
00411 }
00412 }
00413 }
00415 for( int i = 0; i < 6; i++ ){
00416 delete patch[i];
00417 }
00418
00419 addVertexBuffer( buffer );
00420
00421 }
00422
00428 double Ellipsoid::ellipsoidInsideOut( double x, double y, double z ){
00429 double result;
00430 result = pow( pow( x / (double)m_size[0], 2.0 / (double)m_exponents[1] ) +
00431 pow( y / (double)m_size[1], 2.0 / (double)m_exponents[1] ), (double)m_exponents[1] / (double)m_exponents[0] ) +
00432 pow( z / (double)m_size[2], 2.0 / (double)m_exponents[0] );
00433 return result;
00434 }
00435
00436 Mat4 Ellipsoid::findSurfaceGlobal( const Vec3 & global, int iterations ) const{
00437
00438
00439
00440 Mat4 inv;
00441 inv = m_local.inverse();
00442 Vec3 local = ( inv * Vec4( global, 0.0 ) ).xyz();
00443
00444 return( m_local * findSurfaceLocal( local, iterations ) );
00445 }
00446
00447 Mat4 Ellipsoid::findSurfaceLocal( const Vec3 & local, int iterations ) const{
00448
00449 Mat4 normalBasis;
00450 Vec3 start;
00451 start[0] = local[0] / m_size[0];
00452 start[1] = local[1] / m_size[1];
00453 start[2] = local[2] / m_size[2];
00454
00455 Mat4 direction = Mat4::fromDirectionalAxis( normalize( start ), 'x' );
00456
00457 Vec3 x[5];
00458 for( int n = 0; n < 5; n++ ){
00459
00461 if( n == 1 ){
00462 start = direction.getCol(0).xyz() - 0.01f * direction.getCol(1).xyz();
00463 }
00464 else if( n == 2 ){
00465 start = direction.getCol(0).xyz() + 0.01f * direction.getCol(1).xyz();
00466 }
00467 else if( n == 3 ){
00468 start = direction.getCol(0).xyz() - 0.01f * direction.getCol(2).xyz();
00469 }
00470 else if( n == 4 ){
00471 start = direction.getCol(0).xyz() + 0.01f * direction.getCol(2).xyz();
00472 }
00473
00474
00475 Vec3 p3 = normalize( start ) * 2.0f;
00476
00477 Vec3 p1 = Vec3( 0, 0, 0 );
00478
00479 Vec3 p2 = p3 / 2.0f;
00480
00481
00482
00483 double te = 2.0 / m_exponents[1];
00484 double en = m_exponents[1] / m_exponents[0];
00485 double tn = 2.0 / m_exponents[0];
00486
00487
00488 Vec3 x1 = p1.abs();
00489 Vec3 x2 = p2.abs();
00490 Vec3 x3 = p3.abs();
00491
00492
00493 Vec3 sp2 = p2.sgn();
00494
00495
00496 float io1, io2, io3;
00497
00498
00499 io1 = powf( powf( (float)x1[0], te ) + powf( (float)x1[1], te ), en ) + powf( (float)x1[2], tn );
00500 io2 = powf( powf( (float)x2[0], te ) + powf( (float)x2[1], te ), en ) + powf( (float)x2[2], tn );
00501 io3 = powf( powf( (float)x3[0], te ) + powf( (float)x3[1], te ), en ) + powf( (float)x3[2], tn );
00502
00503 for( int i = 0; i < iterations; i++ ){
00504 float p1p2 = float( io1 <= 1.0 && io2 >= 1.0 || io2 <= 1.0 && io1 >= 1.0 );
00505 float p2p3 = float( ! p1p2 );
00506
00507 x3 = x2 * p1p2 + x3 * p2p3;
00508 io3 = io2 * p1p2 + io3 * p2p3;
00509
00510 x1 = x2 * p2p3 + x1 * p1p2;
00511 io1 = io2 * p2p3 + io1 * p1p2;
00512
00513 x2 = p1p2 * ( ( x1 + x2 ) * 0.5f ) + p2p3 * ( ( x2 + x3 ) * 0.5f );
00514
00515 io2 = powf( powf( (float)x2[0], te ) + powf( (float)x2[1], te ), en ) + powf( (float)x2[2], tn );
00516 }
00517
00518 x[n] = x2 * sp2 * Vec3( m_size[0], m_size[1], m_size[2] );
00519 }
00520
00521 normalBasis.setCol( 0, Vec4( normalize( x[2] - x[1] ), 0.0 ) );
00522 normalBasis.setCol( 1, Vec4( normalize( x[4] - x[3] ), 0.0 ) );
00523 normalBasis.setCol( 2, Vec4( normalize( cross( normalBasis.getCol(0).xyz(), normalBasis.getCol(1).xyz() ) ), 0.0 ) );
00524 normalBasis.setCol( 3, Vec4( x[0] ) );
00525 return( normalBasis );
00526 }
00527
00528 Ellipsoid::EllipsoidType Ellipsoid::getEllipsoidType( void ) const {
00529 return( m_ellipsoidType );
00530 }
00531
00532 void Ellipsoid::setEllipsoidType( Ellipsoid::EllipsoidType t, bool send ){
00533 m_ellipsoidType = t;
00535 }
00536
00537
00538 };