00001 #ifndef RT_GLES1
00002
00003 #include "ShadowProxy.h"
00004 #include "Error.h"
00005 #include "Camera.h"
00006 #include "Sampler.h"
00007 #include "Rendergroup.h"
00008 #include "Program.h"
00009 #include "RelationalNode.h"
00010 #include "Rendernode.h"
00011 #include "Stateset.h"
00012
00013 namespace RenderTools {
00014
00015 RelationalNodePtr ShadowProxy::s_model = RelationalNodePtr();
00016 ShadowProxyList ShadowProxy::s_proxies;
00017 GLfloat ShadowProxy::s_offset = 0.0f;
00018 CameraPtr ShadowProxy::s_camera = CameraPtr();
00019 GLfloat * ShadowProxy::s_data = 0;
00020 Mat4Ptr ShadowProxy::s_params = 0;
00021 GLint ShadowProxy::s_gridSize[2];
00022 GLint ShadowProxy::s_mapSize[2];
00023 GLint ShadowProxy::s_mapSize2[2];
00024 GLint ShadowProxy::s_cellSize[2];
00025 GLint ShadowProxy::s_numProxies;
00026 GLint ShadowProxy::s_maxProxiesPerCell;
00027 GLint ShadowProxy::s_maxUniqueProxies;
00028 SamplerPtr ShadowProxy::s_map = SamplerPtr();
00029
00030 PropertyPtr ShadowProxy::create( const XMLNodePtr & xml ){
00031 if( ! s_model ){
00032 s_model = RelationalNodePtr( new RelationalNode() );
00033 s_model->createProperties();
00034 createProperty( s_model.get(), "offset", & s_offset );
00035 s_model->setName( xml );
00036 s_model->setProperties( xml, false );
00037 }
00038 else {
00039 Error::error( Error::REINITIALIZATION, __FILE__, __LINE__ );
00040 }
00041 return( dynamic_pointer_cast< AbstractProperty, RelationalNode >( s_model ) );
00042 }
00043
00044 const string ShadowProxy::getTypeName( bool ofComponent ) const {
00045 return( "ShadowProxy" );
00046 }
00047
00048 SamplerPtr ShadowProxy::getMap( void ){
00049 return( s_map );
00050 }
00051
00052 Vec2 ShadowProxy::getMapSize( void ){
00053 return( Vec2( s_mapSize[0], s_mapSize[1] ) );
00054 }
00055
00056 Vec2 ShadowProxy::getMapSize2( void ){
00057 return( Vec2( s_mapSize2[0], s_mapSize2[1] ) );
00058 }
00059
00060 Vec2 ShadowProxy::getGridSize( void ){
00061 return( Vec2( s_gridSize[0], s_gridSize[1] ) );
00062 }
00063
00064 ShadowProxyPtr ShadowProxy::addProxy( ProxyType type, const Vec3 & size, const Vec3 & color, const RendernodePtr node, const Mat4 & matrix ){
00065 ShadowProxyPtr proxy = ShadowProxyPtr( new ShadowProxy( type, size, color, node, matrix ) );
00066 s_proxies.push_back( proxy );
00067 return( proxy );
00068 }
00069
00070 void ShadowProxy::setCamera( const CameraPtr camera ){
00071 s_camera = camera;
00072 }
00073
00074 void ShadowProxy::onInitialize( void ){
00075
00076 if( ! s_camera ){
00077 Error::error( Error::NULL_POINTER, __FILE__, __LINE__ );
00078 }
00079
00081 s_gridSize[0] = ( GLint )s_camera->getViewport()[2] / 16;
00082 s_gridSize[1] = ( GLint )s_camera->getViewport()[3] / 16;
00083
00086 s_mapSize[0] = s_gridSize[0] * 3;
00087 s_mapSize[1] = s_gridSize[1] * 3;
00088
00090 s_mapSize2[0] = 1;
00091 s_mapSize2[1] = 1;
00092 while( s_mapSize2[0] < s_mapSize[0] )s_mapSize2[0] *= 2;
00093 while( s_mapSize2[1] < s_mapSize[1] )s_mapSize2[1] *= 2;
00094
00096 s_cellSize[0] = ( GLint )s_camera->getViewport()[2] / s_gridSize[0];
00097 s_cellSize[1] = ( GLint )s_camera->getViewport()[3] / s_gridSize[1];
00098
00099 s_maxProxiesPerCell = ( s_mapSize[0] / s_gridSize[0] ) * ( s_mapSize[1] / s_gridSize[1] ) * 4;
00100 s_maxUniqueProxies = 100;
00101
00102 s_params = ( Mat4Ptr )realloc( s_params, s_maxUniqueProxies * sizeof( Mat4 ) );
00103
00104 s_data = ( GLfloat * )realloc( s_data, s_mapSize2[0] * s_mapSize2[1] * 4 * sizeof( GLfloat ) );
00105
00106 XMLNodePtr xml = XMLNodePtr( new XMLNode() );
00107 xml->setTagName( "Sampler" );
00108 xml->setAttrib<string>( "name", "ProxyMap" );
00109 xml->addChild( "width", toString( s_mapSize2[0] ) );
00110 xml->addChild( "height", toString( s_mapSize2[1] ) );
00111 xml->addChild( "mode", "GL_MODULATE" );
00112 xml->addChild( "wrap_mode", "GL_CLAMP" );
00113 xml->addChild( "filter", "GL_NEAREST" );
00114 xml->addChild( "mipmap", "GL_FALSE" );
00115 xml->addChild( "format", "GL_RGBA" );
00116 xml->addChild( "type", "GL_FLOAT" );
00117 xml->addChild( "internal_format", "GL_RGBA32F_ARB" );
00118
00119 s_map = dynamic_pointer_cast< Sampler, AbstractProperty >( Sampler::create( xml ) );
00120
00121 PropertyList unif;
00122 RendergroupList list = (RendergroupList)Rendergroup::findRendergroups();
00123 for( int li = 0; li < (int)list.size(); li++ ){
00124 RendergroupPtr group = list[ li ];
00125
00127 unif = group->findUniforms( "ProxyMap" );
00128 for( unsigned int i = 0; i < unif.size(); i++ ){
00129 unif[ i ]->setValue( toString( s_map ) );
00130 }
00132 unif = group->findUniforms( "proxy_map_size" );
00133 Vec2 v( s_mapSize[0], s_mapSize[1] );
00134 for( unsigned int i = 0; i < unif.size(); i++ ){
00135 unif[ i ]->setValue( toString( v ) );
00136 }
00137 unif = group->findUniforms( "proxy_map_size2" );
00138 v = Vec2( s_mapSize2[0], s_mapSize2[1] );
00139 for( unsigned int i = 0; i < unif.size(); i++ ){
00140 unif[ i ]->setValue( toString( v ) );
00141 }
00142 unif = group->findUniforms( "proxy_grid_size" );
00143 v = Vec2( s_gridSize[0], s_gridSize[1] );
00144 for( unsigned int i = 0; i < unif.size(); i++ ){
00145 unif[ i ]->setValue( toString( v ) );
00146 }
00147 }
00148 }
00149
00150 void ShadowProxy::project( void ){
00151 if( ! s_camera ){
00152 Error::error( Error::NULL_POINTER, __FILE__, __LINE__, string( "you MUST call ShadowProxy::initialize( camera ) first !" ) );
00153 }
00154 int i, k, m;
00155
00156
00157 for( i = 0; i < s_mapSize2[0] * s_mapSize2[1] * 4; i++ ){
00158 s_data[ i ] = -1.0;
00159 }
00160
00161 s_numProxies = 0;
00162
00164 if( ! Rendergroup::getActiveRendergroup() )return;
00165 PropertyPtr unif = Rendergroup::getActiveRendergroup()->findUniform( "proxyOffset" );
00167 if( ! unif )return;
00170 GLfloat proxyOffset;
00171 stringstream value( unif->getValue() );
00172 value >> proxyOffset;
00173
00174
00175 s_camera->bind();
00176
00177 for( i = 0; i < (int)s_proxies.size() && s_numProxies < s_maxUniqueProxies; i++ ){
00178
00179 ShadowProxyPtr proxy = s_proxies[ i ];
00180
00181 Mat4 matrix;
00182 matrix = proxy->getAssociatedRendernode()->getLocal();
00183
00184 matrix *= proxy->getLocal();
00185
00186 Vec4 position;
00187 Vec3 p3;
00188 p3 = matrix.getCol(3).xyz();
00189 position = Vec4( p3[0], p3[1], p3[2], 1.0 );
00190
00191 Vec4 rotation = matrix.toPolar();
00192
00193 Rectangle rect = s_camera->project( proxy->getAABB( Vec3( proxyOffset, proxyOffset, proxyOffset ) ), matrix );
00194
00195 GLint minx = ( GLint )floor( rect[0] / s_cellSize[0] );
00196 GLint maxx = ( GLint )floor( rect[1] / s_cellSize[0] );
00197 GLint miny = ( GLint )floor( rect[2] / s_cellSize[1] );
00198 GLint maxy = ( GLint )floor( rect[3] / s_cellSize[1] );
00201
00202 if( maxx < 0 )continue;
00203 if( maxy < 0 )continue;
00204 if( minx >= s_gridSize[0] )continue;
00205 if( miny >= s_gridSize[1] )continue;
00206
00207 if( minx < 0 )minx = 0;
00208 if( miny < 0 )miny = 0;
00209 if( maxx >= s_gridSize[0] )maxx = s_gridSize[0] - 1;
00210 if( maxy >= s_gridSize[1] )maxy = s_gridSize[1] - 1;
00211
00212
00213 Vec3 size = proxy->getSize( Vec3( proxyOffset, proxyOffset, proxyOffset ) );
00214
00215 const int type = proxy->getType();
00216
00217 const Vec3 & color = proxy->getColor();
00218
00219 int proxyIndex = addProxy( position, rotation, color, type, size );
00221 if( proxyIndex == -1 ){
00222
00223 Error::warning( Error::TOO_MANY_ITEMS, __FILE__, __LINE__, "maximum shadow proxies reached" );
00224 continue;
00225 }
00226
00227
00228 for( k = minx; k <= maxx; k++ ){
00229 for( m = miny; m <= maxy; m++ ){
00230 addIndex( k, m, proxyIndex );
00231 }
00232 }
00233 }
00234
00235 s_map->setData( s_data );
00236
00237 PropertyList uniforms = Rendergroup::getActiveRendergroup()->findUniforms( "proxyParams" );
00238 for( unsigned int i = 0; i < uniforms.size(); i++ ){
00239 for( int j = 0; j < s_numProxies; j++ ){
00240 uniforms[ i ]->setValue( toString( s_params[ j ] ), j );
00241 }
00242 }
00243 Error::assertNoErrors( __FILE__, __LINE__ );
00244 }
00245
00246 void ShadowProxy::deleteAssociatedProxies( const RendernodePtr node ){
00247 for( int i = 0; i < (int)s_proxies.size(); i++ ){
00248 if( s_proxies[ i ]->getAssociatedRendernode() == node ){
00249 s_proxies[ i ] = s_proxies[ s_proxies.size() - 1 ];
00250 s_proxies.pop_back();
00251 i--;
00252 }
00253 }
00254 }
00255
00256 void ShadowProxy::deleteAssociatedProxies( string path ){
00257 for( int i = 0; i < (int)s_proxies.size(); i++ ){
00258 if( s_proxies[ i ]->getAssociatedRendernode()->getPath() == path ){
00259 s_proxies[ i ] = s_proxies[ s_proxies.size() - 1 ];
00260 s_proxies.pop_back();
00261 i--;
00262 }
00263 }
00264 }
00265
00266 int ShadowProxy::retrieveIndex( const RendernodePtr node ){
00267 for( int i = 0; i < (int)s_proxies.size(); i++ ){
00268 if( s_proxies[ i ]->getAssociatedRendernode() == node ){
00269 return( i );
00270 }
00271 }
00272 return( -1 );
00273 }
00274
00275 void ShadowProxy::render( bool showGrid ){
00276 #ifndef RT_GLES2
00277 glMatrixMode( GL_MODELVIEW );
00278 glPushMatrix();
00279 glLoadIdentity();
00280
00281 s_camera->bind();
00282
00283
00284 glEnable( GL_BLEND );
00285 #ifdef GL_ALPHA_TEST
00286 glEnable( GL_ALPHA_TEST );
00287 #endif
00288 #ifdef GL_SRC_ALPHA
00289 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00290 #endif
00291 glLineWidth( 1.0 );
00292
00293 for( int i = 0; i < (int)s_proxies.size(); i++ ){
00294 s_proxies[ i ]->render( );
00295 }
00296
00297 if( showGrid ){
00298
00299 glDisable( GL_TEXTURE_2D );
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 }
00344
00345 glMatrixMode( GL_MODELVIEW );
00346 glPopMatrix();
00347 #endif
00348 }
00349
00350 int ShadowProxy::getNumProxies( int x, int y ){
00351 if( ! s_camera ){
00352 Error::error( Error::NULL_POINTER, __FILE__, __LINE__, string( "you MUST call ShadowProxy::initialize( camera ) first !" ) );
00353 }
00354 int ncx = s_gridSize[0];
00355 int ncy = s_gridSize[1];
00356 int csx = s_mapSize[0] / ncx;
00357 int csy = s_mapSize[1] / ncy;
00358
00359 int rowlen = s_mapSize2[0] * 4;
00360
00361 int count = 0;
00362
00363 int offset1 = y * rowlen * csy + x * csx * 4;
00364
00365 int i, j;
00366 for( j = 0; j < csy; j++ ){
00367 for( i = 0; i < csx * 4; i++ ){
00368 int offset2 = offset1 + j * rowlen + i;
00369 if( s_data[ offset2 ] >= 0.0 ){
00370 count++;
00371 }
00372 else{
00373 break;
00374 }
00375 }
00376 }
00377
00378 return( count );
00379
00380 }
00381
00382 void ShadowProxy::addIndex( int x, int y, int idx ){
00383 if( ! s_camera ){
00384 Error::error( Error::NULL_POINTER, __FILE__, __LINE__, string( "you MUST call ShadowProxy::initialize( camera ) first !" ) );
00385 }
00386 int ncx = s_gridSize[0];
00387 int ncy = s_gridSize[1];
00388 int csx = s_mapSize[0] / ncx;
00389 int csy = s_mapSize[1] / ncy;
00390
00391 int rowlen = s_mapSize2[0] * 4;
00392
00393 int offset1 = y * rowlen * csy + x * csx * 4;
00394
00395 int i, j;
00396 for( j = 0; j < csy; j++ ){
00397 for( i = 0; i < csx * 4; i++ ){
00398 int offset2 = offset1 + j * rowlen + i;
00399 if( s_data[ offset2 ] < 0.0 ){
00400 s_data[ offset2 ] = (float)idx;
00401 return;
00402 }
00403 }
00404 }
00405 }
00406
00407 int ShadowProxy::addProxy( const Vec4 & position, const Vec4 & rotation, const Vec3 & color, int type, const Vec3 & size ){
00408 if( ! s_camera ){
00409 Error::error( Error::NULL_POINTER, __FILE__, __LINE__, string( "you MUST call ShadowProxy::initialize( camera ) first !" ) );
00410 }
00411 if( s_numProxies >= s_maxUniqueProxies )return( -1 );
00412
00413 GLfloat glm[16];
00414 glm[0] = position[0];
00415 glm[1] = position[1];
00416 glm[2] = position[2];
00417 glm[3] = position[3];
00418
00419 glm[4] = rotation[0];
00420 glm[5] = rotation[1];
00421 glm[6] = rotation[2];
00422 glm[7] = rotation[3];
00423
00424 glm[8] = color[0];
00425 glm[9] = color[1];
00426 glm[10] = color[2];
00427 glm[11] = type;
00428
00429 glm[12] = size[0];
00430 glm[13] = size[1];
00431 glm[14] = size[2];
00432 glm[15] = 0.0;
00433
00434 for( int i = 0; i < s_numProxies; i++ ){
00435 if( s_params[i].equals( glm, 0.0001 ) )return( i );
00436 }
00437 s_params[ s_numProxies ] = Mat4( glm );
00438
00439 return( s_numProxies++ );
00440 }
00441
00442 ShadowProxy::ShadowProxy( ProxyType type,
00443 const Vec3 & size,
00444 const Vec3 & color,
00445 const RendernodePtr node,
00446 const Mat4 & local ):
00447 m_type( type ),
00448 m_size( size ),
00449 m_color( color ),
00450 m_associatedRendernode( node ),
00451 m_local( local ){
00452
00453 }
00454
00455 const int ShadowProxy::getType() const {
00456 return( m_type );
00457 }
00458
00459 Vec3 ShadowProxy::getSize( const Vec3 & offset ) const {
00460 return( m_size + offset );
00461 }
00462
00463 void ShadowProxy::setSize( const Vec3 & size ){
00464 m_size = size;
00465 }
00466
00467 const Vec3 & ShadowProxy::getColor( void ) const {
00468 return( m_color );
00469 }
00470
00471 const Mat4 & ShadowProxy::getLocal( void ) const {
00472 return( m_local );
00473 }
00474
00475 AABB ShadowProxy::getAABB( const Vec3 & offset ){
00476 return( AABB( m_size + offset ) );
00477 }
00478
00479 const RendernodePtr ShadowProxy::getAssociatedRendernode( void ) const {
00480 return( m_associatedRendernode );
00481 }
00482
00483 void ShadowProxy::render( void ){
00484
00485 #ifndef RT_GLES2
00486
00487 glMatrixMode( GL_MODELVIEW );
00488 glPushMatrix();
00489
00490 Mat4 ogl( m_associatedRendernode->getLocal() * m_local );
00491 glLoadMatrixf( * ogl );
00492
00493 if( ! Rendergroup::getActiveRendergroup() )return;
00494
00495 PropertyPtr unif = Rendergroup::getActiveRendergroup()->findUniform( "proxyOffset" );
00496
00497 if( ! unif )return;
00498
00499 GLfloat proxyOffset;
00500 stringstream value( unif->getValue() );
00501 value >> proxyOffset;
00502
00503 Vec3 sizeFactor = ( m_size + Vec3( proxyOffset, proxyOffset, proxyOffset ) ) / m_size;
00504
00505 glLineWidth( 1.0 );
00506
00507 switch( m_type ){
00508 case SPHERE:
00509 #if glScalef
00510 glScalef( m_size[0], m_size[1], m_size[2] );
00511 #endif
00512 glColor4f( 1,0,0,0.5 );
00513 wireSphere( 1.0, 12, 12 );
00514
00515 #if glScalef
00516 glScalef( sizeFactor[0], sizeFactor[1], sizeFactor[2] );
00517 #endif
00518 glColor4f( 1,0,0,0.2 );
00519 wireSphere( 1.0, 12, 12 );
00520 break;
00521 case CYLINDER:
00522
00523 #ifdef GL_QUAD_STRIP
00524 glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
00525 glColor4f( 1,0,0,0.5 );
00526 glBegin( GL_QUAD_STRIP );
00527 for( int i = 0; i <= 24; i++ ){
00528 float a = ( (float)i / 24.0 ) * 2.0 * M_PI;
00529 float x = cos( a ) * m_size[0];
00530 float y = sin( a ) * m_size[1];
00531 float z = m_size[2];
00532 glVertex3f( x, y, z );
00533 glVertex3f( x, y, -z );
00534 }
00535 glEnd();
00536 glColor4f( 1,0,0,0.2 );
00537 glBegin( GL_QUAD_STRIP );
00538 for( int i = 0; i <= 24; i++ ){
00539 float a = ( (float)i / 24.0 ) * 2.0 * M_PI;
00540 float x = cos( a ) * m_size[0] * sizeFactor[0];
00541 float y = sin( a ) * m_size[1] * sizeFactor[1];
00542 float z = m_size[2] * sizeFactor[2];
00543 glVertex3f( x, y, z );
00544 glVertex3f( x, y, -z );
00545 }
00546 glEnd();
00547 #endif
00548
00549
00550 break;
00551 case BOX:
00552 #if glScalef
00553 glScalef( m_size[0], m_size[1], m_size[2] );
00554 #endif
00555 glColor4f( 1,0,0,0.5 );
00556 wireCube( 2.0 );
00557
00558 glColor4f( 1,0,0,0.2 );
00559 #if glScalef
00560 glScalef( sizeFactor[0], sizeFactor[1], sizeFactor[2] );
00561 #endif
00562 wireCube( 2.0 );
00563 break;
00564 }
00565 glPopMatrix();
00566 #endif // OpenGL|ES 2.0
00567 }
00568
00569 };
00570
00571 #endif // OpenGL|ES 1.0
00572
00573 int ______forced_public_symbol = 0;