00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "engine.h"
00024
00025 #include <QtCore/QMutex>
00026 #include <QtOpenGL/QGLFramebufferObject>
00027
00028 #include <core/gluon_global.h>
00029
00030 #include "camera.h"
00031 #include "item.h"
00032 #include "material.h"
00033 #include "materialinstance.h"
00034 #include "mesh.h"
00035 #include "texture.h"
00036 #include "viewport.h"
00037
00038 using namespace GluonGraphics;
00039
00040 template<> Engine* GluonCore::Singleton<Engine>::m_instance = 0;
00041
00042 class Engine::EnginePrivate
00043 {
00044 public:
00045 EnginePrivate() : fbo( 0 ), fboShader( 0 ), camera( 0 ) { }
00046
00047 template <typename T>
00048 T* createObject( const QString& type, const QString& name );
00049
00050 void destroyObject( const QString& type, const QString& name );
00051
00052 bool hasObject( const QString& type, const QString& name );
00053
00054 template <typename T>
00055 T* object( const QString& type, const QString& name );
00056
00057 bool addObject( const QString& type, const QString& name, QObject* value );
00058
00059 void removeObject( const QString& type, const QString& name );
00060
00061 QGLFramebufferObject* fbo;
00062 MaterialInstance* fboShader;
00063
00064 Camera* camera;
00065 Viewport* viewport;
00066
00067 QVector<Item*> items;
00068 QHash<QString, QObject*> objects;
00069
00070 QMutex objectMutex;
00071 QMutex itemMutex;
00072
00073 };
00074
00075 template <typename T> T*
00076 Engine::EnginePrivate::createObject( const QString& type, const QString& name )
00077 {
00078 T* newObject;
00079 QString typeName = QString( "%1/%2" ).arg( type, name );
00080
00081 objectMutex.lock();
00082
00083 if( !objects.contains( typeName ) )
00084 {
00085 newObject = new T;
00086 objects.insert( typeName, newObject );
00087 }
00088 else
00089 {
00090 newObject = qobject_cast<T*>( objects.value( typeName ) );
00091 }
00092
00093 objectMutex.unlock();
00094
00095 return newObject;
00096 }
00097
00098 void
00099 Engine::EnginePrivate::destroyObject( const QString& type, const QString& name )
00100 {
00101 QString typeName = QString( "%1/%2" ).arg( type, name );
00102 QMutexLocker locker( &objectMutex );
00103
00104 if( objects.contains( typeName ) )
00105 {
00106 QObject* obj = objects.value( typeName );
00107 objects.remove( typeName );
00108 delete obj;
00109 }
00110 }
00111
00112 bool
00113 Engine::EnginePrivate::hasObject( const QString& type, const QString& name )
00114 {
00115 QString typeName = QString( "%1/%2" ).arg( type, name );
00116
00117 return objects.contains( typeName );
00118 }
00119
00120 template <typename T> T*
00121 Engine::EnginePrivate::object( const QString& type, const QString& name )
00122 {
00123 QString typeName = QString( "%1/%2" ).arg( type, name );
00124
00125 if( objects.contains( typeName ) )
00126 return qobject_cast<T*>( objects.value( typeName ) );
00127
00128 return 0;
00129 }
00130
00131 bool Engine::EnginePrivate::addObject( const QString& type, const QString& name, QObject* value )
00132 {
00133 QString typeName = QString( "%1/%2" ).arg( type, name );
00134 QMutexLocker locker( &objectMutex );
00135
00136 if( !objects.contains( typeName ) )
00137 {
00138 objects.insert( typeName, value );
00139 return true;
00140 }
00141
00142 return false;
00143 }
00144
00145 void Engine::EnginePrivate::removeObject( const QString& type, const QString& name )
00146 {
00147 QString typeName = QString( "%1/%2" ).arg( type, name );
00148 QMutexLocker locker( &objectMutex );
00149
00150 if( objects.contains( typeName ) )
00151 objects.remove( typeName );
00152 }
00153
00154 void Engine::initialize()
00155 {
00156 Material* material = createMaterial( "default" );
00157 material->build();
00158 material->instance( "default" )->setProperty( "materialColor", Qt::white );
00159 material->instance( "default" )->setProperty( "texture0", QString( "default" ) );
00160
00161 Texture* tex = createTexture( "default" );
00162 tex->load( QUrl( GluonCore::Global::dataDirectory() + "/gluon/defaults/default.png" ) );
00163
00164 Mesh* mesh = createMesh( "default" );
00165 mesh->load( QString() );
00166 }
00167
00168 Item*
00169 Engine::createItem( const QString& mesh )
00170 {
00171 QMutexLocker locker( &d->itemMutex );
00172
00173 Item* newItem = new Item( this );
00174 newItem->setMesh( d->createObject<Mesh>( "Mesh", mesh ) );
00175 d->items << newItem;
00176
00177 return newItem;
00178 }
00179
00180 void
00181 Engine::destroyItem( Item* item )
00182 {
00183 QMutexLocker locker( &d->itemMutex );
00184
00185 d->items.remove( d->items.indexOf( item ) );
00186 delete item;
00187 }
00188
00189 Material*
00190 Engine::createMaterial( const QString& name )
00191 {
00192 Material* newMaterial = d->createObject<Material>( "Material", name );
00193 newMaterial->setName( name );
00194 return newMaterial;
00195 }
00196
00197 void Engine::destroyMaterial( const QString& name )
00198 {
00199 d->destroyObject( "Material", name );
00200 }
00201
00202 bool Engine::hasMaterial( const QString& name )
00203 {
00204 return d->hasObject( "Material", name );
00205 }
00206
00207 Material*
00208 Engine::material( const QString& name )
00209 {
00210 return d->object<Material>( "Material", name );
00211 }
00212
00213 bool
00214 Engine::addMaterial( const QString& name, Material* material )
00215 {
00216 return d->addObject( "Material", name, material );
00217 }
00218
00219 void
00220 Engine::removeMaterial( const QString& name )
00221 {
00222 d->removeObject( "Material", name );
00223 }
00224
00225 Mesh*
00226 Engine::createMesh( const QString& name )
00227 {
00228 return d->createObject<Mesh>( "Mesh", name );
00229 }
00230
00231 void
00232 Engine::destroyMesh( const QString& name )
00233 {
00234 d->destroyObject( "Mesh", name );
00235 }
00236
00237 bool
00238 Engine::hasMesh( const QString& name )
00239 {
00240 return d->hasObject( "Mesh", name );
00241 }
00242
00243 Mesh*
00244 Engine::mesh( const QString& name )
00245 {
00246 return d->object<Mesh>( "Mesh", name );
00247 }
00248
00249 bool
00250 Engine::addMesh( const QString& name, Mesh* mesh )
00251 {
00252 return d->addObject( "Mesh", name, mesh );
00253 }
00254
00255 void
00256 Engine::removeMesh( const QString& name )
00257 {
00258 d->removeObject( "Mesh", name );
00259 }
00260
00261 Texture*
00262 Engine::createTexture( const QString& name )
00263 {
00264 return d->createObject<Texture>( "Texture", name );
00265 }
00266
00267 void
00268 Engine::destroyTexture( const QString& name )
00269 {
00270 d->destroyObject( "Texture", name );
00271 }
00272
00273 bool
00274 Engine::hasTexture( const QString& name )
00275 {
00276 return d->hasObject( "Texture", name );
00277 }
00278
00279 Texture*
00280 Engine::texture( const QString& name )
00281 {
00282 return d->object<Texture>( "Texture", name );
00283 }
00284
00285 bool
00286 Engine::addTexture( const QString& name, Texture* texture )
00287 {
00288 return d->addObject( "Texture", name, texture );
00289 }
00290
00291 void
00292 Engine::removeTexture( const QString& name )
00293 {
00294 d->removeObject( "Texture", name );
00295 }
00296
00297 Camera*
00298 Engine::activeCamera()
00299 {
00300 return d->camera;
00301 }
00302
00303 Viewport*
00304 Engine::currentViewport()
00305 {
00306 return d->viewport;
00307 }
00308
00309 void
00310 Engine::render()
00311 {
00312 d->objectMutex.lock();
00313
00314
00315
00316
00317
00318 const int size = d->items.size();
00319 for( int i = 0; i < size; ++i )
00320 {
00321 d->items.at( i )->render();
00322 }
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 d->objectMutex.unlock();
00333 }
00334
00335 void
00336 Engine::setFramebufferSize( int width, int height )
00337 {
00338 if( width <= 0 || height <= 0 )
00339 return;
00340
00341 d->objectMutex.lock();
00342
00343 delete d->fbo;
00344 d->fbo = new QGLFramebufferObject( width, height, QGLFramebufferObject::Depth );
00345
00346 d->objectMutex.unlock();
00347 }
00348
00349 void
00350 Engine::setActiveCamera( Camera* camera )
00351 {
00352 d->objectMutex.lock();
00353 d->camera = camera;
00354 d->objectMutex.unlock();
00355 emit activeCameraChanged( camera );
00356 }
00357
00358 void
00359 Engine::setViewport( Viewport* viewport )
00360 {
00361 d->objectMutex.lock();
00362 d->viewport = viewport;
00363 d->objectMutex.unlock();
00364 }
00365
00366 Engine::Engine()
00367 : d( new EnginePrivate() )
00368 {
00369 d->viewport = new Viewport();
00370 connect( this, SIGNAL( activeCameraChanged( Camera* ) ), d->viewport, SLOT( update() ) );
00371 }
00372
00373 Engine::~Engine()
00374 {
00375 delete d->fbo;
00376 delete d;
00377 }
00378
00379 #include "engine.moc"