RendererScene.cpp 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400
  1. #include "RendererScene.h"
  2. #include "RendererSystem.h"
  3. RendererScene::RendererScene(RendererSystem *p_system, SceneLoader *p_sceneLoader) : SystemScene(p_system, p_sceneLoader)
  4. {
  5. m_renderTask = new RenderTask(this, p_system->getRenderer());
  6. m_camera = nullptr;
  7. m_skybox = nullptr;
  8. }
  9. RendererScene::~RendererScene()
  10. {
  11. delete m_camera;
  12. }
  13. ErrorCode RendererScene::init()
  14. {
  15. ErrorCode returnError = ErrorCode::Success;
  16. // Create a default camera, in case it is not created upon loading a scene
  17. m_camera = new CameraObject(this, "Default Camera");
  18. // Create a default directional light, in case it is not created upon loading a scene
  19. m_directionalLight = new DirectionalLightObject(this, "Default Directional Light", DirectionalLightDataSet());
  20. // Create a default static environment map, so it can be used while a real one hasn't been loaded yet
  21. //m_sceneObjects.m_staticSkybox = new EnvironmentMapObject(this, "default", Loaders::textureCubemap().load());
  22. return returnError;
  23. }
  24. ErrorCode RendererScene::setup(const PropertySet &p_properties)
  25. {
  26. // Get default object pool size
  27. decltype(m_graphicsObjPool.getPoolSize()) objectPoolSize = Config::objectPoolVar().object_pool_size;
  28. for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
  29. {
  30. switch(p_properties[i].getPropertyID())
  31. {
  32. case Properties::ObjectPoolSize:
  33. objectPoolSize = p_properties[i].getInt();
  34. break;
  35. }
  36. }
  37. // Initialize object pools
  38. m_graphicsObjPool.init(objectPoolSize);
  39. m_objectsLoadingToMemory.reserve(objectPoolSize);
  40. m_objectsToDestroy.reserve(objectPoolSize);
  41. return ErrorCode::Success;
  42. }
  43. ErrorCode RendererScene::preload()
  44. {
  45. // Implementation note: use number of allocated objects as an early bail - this method is most
  46. // likely called after populating pools, which means objects are lined at the start of the pools)
  47. /*/ Start loading Model Objects
  48. for(decltype(m_modelObjPool.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_modelObjPool.getNumAllocated(),
  49. size = m_modelObjPool.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
  50. {
  51. // If current object is allocated and is not loaded to memory already
  52. if(m_modelObjPool[i].allocated() && !(m_modelObjPool[i].getObject()->isLoadedToMemory()))
  53. {
  54. // Add the object to be loaded later
  55. //m_objectsBeingLoaded.push_back(LoadableGraphicsObjectAndIndex(m_modelObjPool[i].getObject(), m_modelObjPool[i].getIndex()));
  56. m_objectsBeingLoaded.emplace_back(m_modelObjPool[i].getObject(), m_modelObjPool[i].getIndex());
  57. // Increment the number of allocated objects (early bail mechanism)
  58. numAllocObjecs++;
  59. }
  60. }
  61. // Start loading ShaderModel Objects
  62. for(decltype(m_shaderObjPool.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_shaderObjPool.getNumAllocated(),
  63. size = m_shaderObjPool.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
  64. {
  65. // If current object is allocated and is not loaded to memory already
  66. if(m_shaderObjPool[i].allocated() && !(m_shaderObjPool[i].getObject()->isLoadedToMemory()))
  67. {
  68. // Add the object to be loaded later
  69. //m_objectsBeingLoaded.push_back(LoadableGraphicsObjectAndIndex(m_shaderObjPool[i].getObject(), m_shaderObjPool[i].getIndex()));
  70. m_objectsBeingLoaded.emplace_back(m_shaderObjPool[i].getObject(), m_shaderObjPool[i].getIndex());
  71. // Increment the number of allocated objects (early bail mechanism)
  72. numAllocObjecs++;
  73. }
  74. }
  75. // Start loading Environment Map Objects
  76. for(decltype(m_envMapPool.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_envMapPool.getNumAllocated(),
  77. size = m_envMapPool.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
  78. {
  79. // If current object is allocated and is not loaded to memory already
  80. if (m_envMapPool[i].allocated() && !(m_envMapPool[i].getObject()->isLoadedToMemory()))
  81. {
  82. // Add the object to be loaded later
  83. //m_objectsBeingLoaded.push_back(LoadableGraphicsObjectAndIndex(m_envMapPool[i].getObject(), m_shaderObjPool[i].getIndex()));
  84. m_objectsBeingLoaded.emplace_back(m_envMapPool[i].getObject(), m_shaderObjPool[i].getIndex());
  85. // Increment the number of allocated objects (early bail mechanism)
  86. numAllocObjecs++;
  87. }
  88. }
  89. // Load every object to memory. It still works in parallel, however,
  90. // it returns only when all objects have finished loading (simulating sequential call)
  91. TaskManagerLocator::get().parallelFor(size_t(0), m_objectsBeingLoaded.size(), size_t(1), [=](size_t i)
  92. {
  93. m_objectsBeingLoaded[i].LoadToMemory();
  94. });*/
  95. // Go over each graphics object and add it to the loading array
  96. for(decltype(m_graphicsObjPool.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_graphicsObjPool.getNumAllocated(),
  97. size = m_graphicsObjPool.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
  98. {
  99. // Check if the graphics object is allocated inside the pool container
  100. if(m_graphicsObjPool[i].allocated())
  101. {
  102. // Increment the number of allocated objects (early bail mechanism)
  103. numAllocObjecs++;
  104. auto graphicsObject = m_graphicsObjPool[i].getObject();
  105. m_objectsLoadingToMemory.push_back(graphicsObject);
  106. }
  107. }
  108. // Load every object to memory. It still works in parallel, however,
  109. // it returns only when all objects have finished loading (simulating sequential call)
  110. TaskManagerLocator::get().parallelFor(size_t(0), m_objectsLoadingToMemory.size(), size_t(1), [=](size_t i)
  111. {
  112. m_objectsLoadingToMemory[i]->loadToMemory();
  113. });
  114. return ErrorCode::Success;
  115. }
  116. void RendererScene::loadInBackground()
  117. {
  118. // Implementation note: use number of allocated objects as an early bail - this method is most
  119. // likely called after populating pools, which means objects are lined up at the start of the pools)
  120. // Go over each graphics object
  121. for(decltype(m_graphicsObjPool.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_graphicsObjPool.getNumAllocated(),
  122. size = m_graphicsObjPool.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
  123. {
  124. // Check if the graphics object is allocated inside the pool container
  125. if(m_graphicsObjPool[i].allocated())
  126. {
  127. // Increment the number of allocated objects (early bail mechanism)
  128. numAllocObjecs++;
  129. auto graphicsObject = m_graphicsObjPool[i].getObject();
  130. // Add the graphics object to the loading array and start loading it in the background
  131. m_objectsLoadingToMemory.push_back(graphicsObject);
  132. TaskManagerLocator::get().startBackgroundThread(std::bind(&GraphicsObject::loadToMemory, graphicsObject));
  133. }
  134. }
  135. }
  136. PropertySet RendererScene::exportObject()
  137. {
  138. // Create the root property set
  139. PropertySet propertySet(Properties::Graphics);
  140. /*
  141. // Add root property set for scene values
  142. auto &scene = propertySet.addPropertySet(Properties::Scene);
  143. // Add individual scene values
  144. scene.addProperty(Properties::ModelPoolSize, (int)m_modelObjPool.getPoolSize());
  145. scene.addProperty(Properties::PointLightPoolSize, (int)m_pointLightPool.getPoolSize());
  146. scene.addProperty(Properties::SpotLightPoolSize, (int)m_spotLightPool.getPoolSize());
  147. // Add root property set for all the objects
  148. auto &objects = propertySet.addPropertySet(Properties::Objects);
  149. // Add camera object property set
  150. objects.addPropertySet(m_camera->exportObject());
  151. // Add directional light property set
  152. objects.addPropertySet(m_directionalLight->exportObject());
  153. // Add static environment map property set
  154. objects.addPropertySet(m_skybox->exportObject());
  155. // Add model object property sets
  156. for(decltype(m_modelObjPool.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_modelObjPool.getNumAllocated(),
  157. size = m_modelObjPool.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
  158. {
  159. if(m_modelObjPool[i].allocated())
  160. objects.addPropertySet(m_modelObjPool[i].getObject()->exportObject());
  161. }
  162. // Add custom shader object property sets
  163. for(decltype(m_shaderObjPool.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_shaderObjPool.getNumAllocated(),
  164. size = m_shaderObjPool.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
  165. {
  166. if(m_shaderObjPool[i].allocated())
  167. objects.addPropertySet(m_shaderObjPool[i].getObject()->exportObject());
  168. }
  169. // Add point light property sets
  170. for(decltype(m_pointLightPool.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_pointLightPool.getNumAllocated(),
  171. size = m_pointLightPool.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
  172. {
  173. if(m_pointLightPool[i].allocated())
  174. objects.addPropertySet(m_pointLightPool[i].getObject()->exportObject());
  175. }
  176. // Add spot light property sets
  177. for(decltype(m_spotLightPool.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_spotLightPool.getNumAllocated(),
  178. size = m_spotLightPool.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
  179. {
  180. if(m_spotLightPool[i].allocated())
  181. objects.addPropertySet(m_spotLightPool[i].getObject()->exportObject());
  182. }
  183. */
  184. return propertySet;
  185. }
  186. void RendererScene::update(const float p_deltaTime)
  187. {
  188. // Clear variables
  189. m_sceneObjects.m_staticSkybox = nullptr;
  190. m_sceneObjects.m_directionalLight = nullptr;
  191. // Clear arrays from previous frame
  192. m_sceneObjects.m_pointLights.clear();
  193. m_sceneObjects.m_spotLights.clear();
  194. m_sceneObjects.m_modelData.clear();
  195. m_sceneObjects.m_modelDataWithShaders.clear();
  196. m_sceneObjects.m_loadToVideoMemory.clear();
  197. // _______________________________
  198. // | |
  199. // | Objects to be destroyed |
  200. // |_______________________________|
  201. //
  202. // Iterate over objects that are queued to be destroyed
  203. if(!m_objectsToDestroy.empty())
  204. for(decltype(m_objectsToDestroy.size()) i = 0, size = m_objectsToDestroy.size(); i < size;)
  205. {
  206. // Check if the object isn't being currently loaded
  207. if(getCurrentlyLoadingObject(*m_objectsToDestroy[i]) == nullptr)
  208. {
  209. // Delete the object as it's not being loaded = not in use
  210. delete m_objectsToDestroy[i];
  211. // Remove the object from the destroy list
  212. m_objectsToDestroy.erase(m_objectsToDestroy.begin() + i);
  213. }
  214. // If current object is still loading, advance the index
  215. else
  216. i++;
  217. }
  218. // _______________________________
  219. // | |
  220. // | Currently Loading Objects |
  221. // |_______________________________|
  222. //
  223. // Iterate over currently loading objects
  224. for(decltype(m_objectsLoadingToMemory.size()) i = 0, size = m_objectsLoadingToMemory.size(),
  225. maxObjects = Config::rendererVar().objects_loaded_per_frame; i < size;)
  226. {
  227. // Perform a check that marks an object if it is loaded to memory
  228. m_objectsLoadingToMemory[i]->performCheckIsLoadedToMemory();
  229. // If the object has loaded to memory already, add to load queue
  230. if(m_objectsLoadingToMemory[i]->isLoadedToMemory())
  231. {
  232. // If object should be activated after loading (for example wasn't set to be deleted while loading)
  233. //if(m_objectsBeingLoaded[i].isActivatedAfterLoading())
  234. //{
  235. // Make object active, so it is passed to the renderer for drawing
  236. m_objectsLoadingToMemory[i]->setActive(true);
  237. if(m_objectsLoadingToMemory[i]->modelComponentPresent())
  238. {
  239. // Get all loadable objects from the model component
  240. auto loadableObjectsFromModel = m_objectsLoadingToMemory[i]->getModelComponent()->getLoadableObjects();
  241. // Iterate over all loadable objects from the model component, and if any of them are not loaded to video memory already, add them to the to-load list
  242. for(decltype(loadableObjectsFromModel.size()) size = loadableObjectsFromModel.size(), i = 0; i < size; i++)
  243. if(!loadableObjectsFromModel[i].isLoadedToVideoMemory())
  244. m_sceneObjects.m_loadToVideoMemory.emplace_back(loadableObjectsFromModel[i]);
  245. }
  246. if(m_objectsLoadingToMemory[i]->shaderComponentPresent())
  247. {
  248. // Get all loadable objects from the model component
  249. auto loadableObjectsFromShader = m_objectsLoadingToMemory[i]->getShaderComponent()->getLoadableObjects();
  250. // Iterate over all loadable objects from the model component, and if any of them are not loaded to video memory already, add them to the to-load list
  251. for(decltype(loadableObjectsFromShader.size()) size = loadableObjectsFromShader.size(), i = 0; i < size; i++)
  252. if(!loadableObjectsFromShader[i].isLoadedToVideoMemory())
  253. m_sceneObjects.m_loadToVideoMemory.emplace_back(loadableObjectsFromShader[i]);
  254. }
  255. // Remove the object from the current list
  256. m_objectsLoadingToMemory.erase(m_objectsLoadingToMemory.begin() + i);
  257. // If the max number of object to be processed per frame has been reached, break from the loop
  258. if(--maxObjects == 0)
  259. break;
  260. }
  261. // If current object is still loading, advance the index
  262. else
  263. i++;
  264. }
  265. // ___________________________
  266. // | |
  267. // | Graphics Objects |
  268. // |___________________________|
  269. //
  270. // Iterate over all graphics object and process them to be rendered
  271. for(decltype(m_graphicsObjPool.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_graphicsObjPool.getNumAllocated(),
  272. size = m_graphicsObjPool.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
  273. {
  274. // Check if the graphics object is allocated inside the pool container
  275. if(m_graphicsObjPool[i].allocated())
  276. {
  277. auto *graphicsObject = m_graphicsObjPool[i].getObject();
  278. // Increment the number of allocated objects (early bail mechanism)
  279. numAllocObjecs++;
  280. // Check if the graphics object is enabled
  281. if(graphicsObject->isObjectActive())
  282. {
  283. // Update the object
  284. graphicsObject->update(p_deltaTime);
  285. // Check if the graphics object is already loaded to video memory (GPU)
  286. if(graphicsObject->isLoadedToVideoMemory())
  287. {
  288. // Check if the graphics object contains a model component
  289. if(graphicsObject->modelComponentPresent())
  290. {
  291. auto modelComponent = graphicsObject->getModelComponent();
  292. // Check if the graphics object contains a shader component
  293. if(graphicsObject->shaderComponentPresent())
  294. {
  295. // Loop over each model and add it to the render list of models with custom shaders
  296. for(decltype(modelComponent->m_modelData.size()) size = modelComponent->m_modelData.size(), i = 0; i < size; i++)
  297. m_sceneObjects.m_modelDataWithShaders.emplace_back(modelComponent->m_modelData[i], graphicsObject->getShaderComponent()->m_shaderData->m_shader, graphicsObject->getSpatialDataManagerReference().getWorldSpaceData().m_transformMat);
  298. }
  299. else
  300. {
  301. // Loop over each model and add it to the render list of models with default shaders
  302. for(decltype(modelComponent->m_modelData.size()) size = modelComponent->m_modelData.size(), i = 0; i < size; i++)
  303. m_sceneObjects.m_modelData.emplace_back(modelComponent->m_modelData[i], graphicsObject->getSpatialDataManagerReference().getWorldSpaceData().m_transformMat);
  304. }
  305. }
  306. // Check if the graphics object contains a light component
  307. if(graphicsObject->lightComponentPresent())
  308. {
  309. auto lightComponent = graphicsObject->getLightComponent();
  310. // Check if the light is enabled
  311. if(lightComponent->isObjectActive())
  312. {
  313. // Add the light data to the corresponding array, based on the light type
  314. switch(lightComponent->getLightType())
  315. {
  316. case LightComponent::LightComponentType_point:
  317. m_sceneObjects.m_pointLights.push_back(*lightComponent->getPointLight());
  318. break;
  319. case LightComponent::LightComponentType_spot:
  320. m_sceneObjects.m_spotLights.push_back(*lightComponent->getSpotLight());
  321. break;
  322. case LightComponent::LightComponentType_directional:
  323. m_sceneObjects.m_directionalLight = lightComponent->getDirectionalLight();
  324. break;
  325. }
  326. }
  327. }
  328. // Check if the graphics object contains a camera component
  329. if(graphicsObject->cameraComponentPresent())
  330. {
  331. m_sceneObjects.m_camera.m_viewData = graphicsObject->getSpatialDataManagerReference().getWorldSpaceData();
  332. /*Math::Vec3f m_positionVec(0.0f, 0.0f, 0.0f);
  333. Math::Vec3f m_targetVec(0.0f, 0.0f, 0.0f);
  334. Math::Vec3f m_upVector(0.0f, 1.0f, 0.0f);
  335. Math::Vec3f m_horizontalVec(0.0f, 0.0f, 0.0f);
  336. float m_verticalAngle = 0.5f;
  337. float m_horizontalAngle = 3.14f;
  338. // Calculate camera's rotation
  339. m_targetVec.target(m_verticalAngle, m_horizontalAngle);
  340. m_horizontalVec.horizontal(m_horizontalAngle);
  341. // Calculate camera's position based on the pressed movement keys
  342. m_upVector = Math::cross(m_horizontalVec, m_targetVec);
  343. m_sceneObjects.m_camera.m_viewData.m_transformMat.initCamera(m_positionVec, m_targetVec + m_positionVec, m_upVector);
  344. // Set the target vector variable, so it can be retrieved later by listeners
  345. m_targetVec = Math::Vec3f(0.0f);
  346. m_targetVec.y = m_verticalAngle;
  347. m_targetVec.z = m_horizontalAngle;
  348. m_sceneObjects.m_camera.m_viewData.m_spatialData.m_position = m_positionVec;
  349. m_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler = m_targetVec;*/
  350. //m_sceneObjects.m_camera.m_viewData.m_transformMat.initCamera(m_positionVec, m_targetVec + m_positionVec, m_upVector);
  351. //m_sceneObjects.m_camera.m_viewData.m_transformMat.initCamera(m_positionVec, m_targetVec + m_positionVec, m_upVector);
  352. }
  353. }
  354. }
  355. else
  356. {
  357. }
  358. }
  359. }
  360. /*/ ___________________________
  361. // | |
  362. // | Model Objects |
  363. // |___________________________|
  364. //
  365. // Update objects and put them into scene object list (use number of allocated objects as early bail)
  366. for(decltype(m_modelObjPool.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_modelObjPool.getNumAllocated(),
  367. size = m_modelObjPool.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
  368. {
  369. if(m_modelObjPool[i].allocated())
  370. {
  371. auto *object = m_modelObjPool[i].getObject();
  372. // Increment the number of allocated objects (early bail mechanism)
  373. numAllocObjecs++;
  374. // Check if object is active, if so, update it and assign it to 'to-be-rendered' array
  375. if(object->isObjectActive())
  376. {
  377. // Update object
  378. object->update(p_deltaTime);
  379. // Place the object to the appropriate array
  380. if(object->isAffectedByLighting())
  381. m_sceneObjects.m_modelObjects.push_back(&object->getRenderableObjectData());
  382. else
  383. m_sceneObjects.m_postLightingObjects.push_back(&object->getRenderableObjectData());
  384. // Put the object in the appropriate array
  385. //m_sceneObjects.m_modelObjects.push_back(&object->getRenderableObjectData());
  386. }
  387. }
  388. }
  389. // ___________________________
  390. // | |
  391. // | Shader Objects |
  392. // |___________________________|
  393. //
  394. // Update custom shader objects and put them into scene object list (use number of allocated objects as early bail)
  395. for(decltype(m_shaderObjPool.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_shaderObjPool.getNumAllocated(),
  396. size = m_shaderObjPool.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
  397. {
  398. if(m_shaderObjPool[i].allocated())
  399. {
  400. auto *object = m_shaderObjPool[i].getObject();
  401. // Increment the number of allocated objects (early bail mechanism)
  402. numAllocObjecs++;
  403. // Check if object is active, if so, update it and assign it to 'to-be-rendered' array
  404. if(object->isObjectActive())
  405. {
  406. // Update object
  407. object->update(p_deltaTime);
  408. // Place the object to the appropriate array
  409. if(object->isAffectedByLighting())
  410. m_sceneObjects.m_customShaderObjects.push_back(&object->getRenderableObjectData());
  411. else
  412. m_sceneObjects.m_postLightingObjects.push_back(&object->getRenderableObjectData());
  413. }
  414. }
  415. }
  416. // TODO make isActive a part of system object
  417. if(m_directionalLight->active())
  418. m_directionalLight->update(p_deltaTime);
  419. // ___________________________
  420. // | |
  421. // | Point Lights |
  422. // |___________________________|
  423. //
  424. // Put all the active point lights into scene object list
  425. for(decltype(m_pointLightPool.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_pointLightPool.getNumAllocated(),
  426. size = m_pointLightPool.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
  427. {
  428. if(m_pointLightPool[i].allocated())
  429. {
  430. auto *light = m_pointLightPool[i].getObject();
  431. // Increment the number of allocated lights (early bail mechanism)
  432. numAllocObjecs++;
  433. if(light->active())
  434. {
  435. m_sceneObjects.m_pointLights.push_back(light->getLightDataSet());
  436. }
  437. }
  438. }
  439. // ___________________________
  440. // | |
  441. // | Spot Lights |
  442. // |___________________________|
  443. //
  444. // Put all the active spot lights into scene object list
  445. for(decltype(m_spotLightPool.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_spotLightPool.getNumAllocated(),
  446. size = m_spotLightPool.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
  447. {
  448. if(m_spotLightPool[i].allocated())
  449. {
  450. auto *light = m_spotLightPool[i].getObject();
  451. // Increment the number of allocated lights (early bail mechanism)
  452. numAllocObjecs++;
  453. if(light->active())
  454. {
  455. m_sceneObjects.m_spotLights.push_back(light->getLightDataSet());
  456. }
  457. }
  458. }*/
  459. /*/ ___________________________
  460. // | |
  461. // | Light Components |
  462. // |___________________________|
  463. //
  464. // Put all the active lights into scene object lists, separate by light-type
  465. for(decltype(m_lightComponents.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_lightComponents.getNumAllocated(),
  466. size = m_lightComponents.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
  467. {
  468. // Check if the light component object is allocated inside the pool container
  469. if(m_lightComponents[i].allocated())
  470. {
  471. auto* lightComponent = m_lightComponents[i].getObject();
  472. // Increment the number of allocated lights (early bail mechanism)
  473. numAllocObjecs++;
  474. // Check if the light is enabled
  475. if(lightComponent->isObjectActive())
  476. {
  477. // Add the light data to the corresponding array, based on the light type
  478. switch(lightComponent->getLightType())
  479. {
  480. case LightComponent::LightComponentType_point:
  481. m_sceneObjects.m_pointLights.push_back(*lightComponent->getPointLight());
  482. break;
  483. case LightComponent::LightComponentType_spot:
  484. m_sceneObjects.m_spotLights.push_back(*lightComponent->getSpotLight());
  485. break;
  486. case LightComponent::LightComponentType_directional:
  487. m_sceneObjects.m_directionalLight = lightComponent->getDirectionalLight();
  488. break;
  489. }
  490. }
  491. }
  492. }*/
  493. // Update camera spatial data
  494. calculateCamera(m_sceneObjects.m_camera.m_viewData);
  495. //std::cout << GetString(static_cast<Properties::PropertyID>(10)) << std::endl;
  496. //m_sceneObjects.m_camera.m_spatialData.m_rotationEuler = Math::toRadian(p_viewData.m_spatialData.m_rotationEuler);
  497. /*m_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler.y = 0.5f;
  498. m_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler.z = 3.14f;
  499. //const Math::Vec3f upVector = Math::cross(m_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler.z, m_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler.y);
  500. //const Math::Vec3f targetVector(0.0f, m_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler.y, m_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler.z);
  501. //m_sceneObjects.m_camera.m_viewData.m_transformMat.initCamera(m_sceneObjects.m_camera.m_viewData.m_spatialData.m_position, targetVector + m_sceneObjects.m_camera.m_viewData.m_spatialData.m_position, upVector);
  502. Math::Vec3f m_positionVec(0.0f, 0.0f, 0.0f);
  503. Math::Vec3f m_targetVec(0.0f, 0.0f, 0.0f);
  504. Math::Vec3f m_upVector(0.0f, 1.0f, 0.0f);
  505. Math::Vec3f m_horizontalVec(0.0f, 0.0f, 0.0f);
  506. float m_verticalAngle = 0.0f;
  507. float m_horizontalAngle = 3.14f;
  508. // Calculate camera's rotation
  509. m_targetVec.target(m_verticalAngle, m_horizontalAngle);
  510. m_horizontalVec.horizontal(m_horizontalAngle);
  511. // Calculate camera's position based on the pressed movement keys
  512. m_upVector = Math::cross(m_horizontalVec, m_targetVec);
  513. m_sceneObjects.m_camera.m_viewData.m_transformMat.initCamera(m_positionVec, m_targetVec + m_positionVec, m_upVector);
  514. // Set the target vector variable, so it can be retrieved later by listeners
  515. m_targetVec = Math::Vec3f(0.0f);
  516. m_targetVec.y = m_verticalAngle;
  517. m_targetVec.z = m_horizontalAngle;
  518. m_sceneObjects.m_camera.m_viewData.m_spatialData.m_position = m_positionVec;
  519. m_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler = m_targetVec;
  520. m_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler = Math::Vec3f(0.0f);
  521. m_sceneObjects.m_camera.m_viewData.m_transformMat = Math::createTransformMat(
  522. Math::Vec3f(0.0f),
  523. Math::Vec3f(0.0f, 0.0f, 45.0f),
  524. Math::Vec3f(1.0f));
  525. Math::Vec3f rotation(30.0f, 30.0f, 0.0f);
  526. rotation = Math::toRadian(rotation);
  527. float cosY = cosf(rotation.y); // Yaw
  528. float sinY = sinf(rotation.y);
  529. float cosP = cosf(rotation.x); // Pitch
  530. float sinP = sinf(rotation.x);
  531. float cosR = cosf(rotation.z); // Roll
  532. float sinR = sinf(rotation.z);
  533. Math::Mat4f mat;
  534. mat.identity();
  535. mat.m[0] = cosY * cosR + sinY * sinP * sinR;
  536. mat.m[1] = cosR * sinY * sinP - sinR * cosY;
  537. mat.m[2] = cosP * sinY;
  538. mat.m[4] = cosP * sinR;
  539. mat.m[5] = cosR * cosP;
  540. mat.m[6] = -sinP;
  541. mat.m[8] = sinR * cosY * sinP - sinY * cosR;
  542. mat.m[9] = sinY * sinR + cosR * cosY * sinP;
  543. mat.m[10] = cosP * cosY;
  544. m_sceneObjects.m_camera.m_viewData.m_transformMat = mat * Math::Mat4f();*/
  545. m_sceneObjects.m_staticSkybox = m_skybox;
  546. m_sceneObjects.m_directionalLight = &m_directionalLight->getLightDataSet();
  547. }
  548. SystemObject *RendererScene::createObject(const PropertySet &p_properties)
  549. {
  550. // Check if property set node is present
  551. if(p_properties)
  552. {
  553. // Check if the rendering property is present
  554. auto &renderingProperty = p_properties.getPropertySetByID(Properties::Rendering);
  555. if(renderingProperty)
  556. {
  557. // Get the object name
  558. auto &nameProperty = p_properties.getPropertyByID(Properties::Name);
  559. // Find a place for the new object in the pool
  560. auto graphicsObjectFromPool = m_graphicsObjPool.newObject();
  561. // Check if the pool wasn't full
  562. if(graphicsObjectFromPool != nullptr)
  563. {
  564. std::string name;
  565. // If the name property is missing, generate a unique name based on the object's index in the pool
  566. if(nameProperty)
  567. name = nameProperty.getString();
  568. else
  569. name = GetString(Properties::GraphicsObject) + Utilities::toString(graphicsObjectFromPool->getIndex());
  570. // Construct the GraphicsObject
  571. graphicsObjectFromPool->construct(this, name);
  572. auto graphicsObject = graphicsObjectFromPool->getObject();
  573. //graphicsObject->importObject(renderingProperty);
  574. // Start importing the newly created object in a background thread
  575. //TaskManagerLocator::get().startBackgroundThread(std::bind(&GraphicsObject::importObject, graphicsObject, renderingProperty));
  576. graphicsObject->importObject(renderingProperty);
  577. return graphicsObject;
  578. }
  579. else
  580. {
  581. ErrHandlerLoc::get().log(ErrorCode::ObjectPool_full, ErrorSource::Source_RendererScene, "Failed to add GraphicsObject - \'" + nameProperty.getString() + "\'");
  582. }
  583. }
  584. }
  585. // If valid type was not specified, or object creation failed, return a null object instead
  586. return g_nullSystemBase.getScene()->createObject(p_properties);
  587. }
  588. ErrorCode RendererScene::destroyObject(SystemObject *p_systemObject)
  589. {
  590. // Check if object is valid and belongs to graphics system
  591. if(p_systemObject != nullptr && p_systemObject->getSystemType() == Systems::Graphics)
  592. {
  593. // Cast the system object to graphics object, as it belongs to the renderer scene
  594. GraphicsObject *objectToDestroy = static_cast<GraphicsObject *>(p_systemObject);
  595. // Check if the object is being currently loaded
  596. auto loadingObject = getCurrentlyLoadingObject(*p_systemObject);
  597. if(loadingObject != nullptr)
  598. {
  599. // If it is currently being loaded, add it to the destroy list, as it cannot be deleted now while it is being used
  600. m_objectsToDestroy.push_back(objectToDestroy);
  601. return ErrorCode::Success;
  602. }
  603. else
  604. {
  605. // Try to destroy the object; return success if it succeeds
  606. if(removeObjectFromPool(*objectToDestroy))
  607. return ErrorCode::Success;
  608. }
  609. }
  610. // If this point is reached, no object was found, return an appropriate error
  611. return ErrorCode::Destroy_obj_not_found;
  612. }
  613. void RendererScene::changeOccurred(ObservedSubject *p_subject, BitMask p_changeType)
  614. {
  615. //std::cout << "change occurred" << std::endl;
  616. }
  617. BitMask RendererScene::getDesiredSystemChanges()
  618. {
  619. return Systems::Changes::Generic::All;
  620. }
  621. BitMask RendererScene::getPotentialSystemChanges()
  622. {
  623. return Systems::Changes::None;
  624. }
  625. MaterialData RendererScene::loadMaterialData(PropertySet &p_materialProperty, Model::MaterialArrays &p_materialArraysFromModel, MaterialType p_materialType, std::size_t p_meshIndex)
  626. {
  627. // Declare the material data that is to be returned and a flag showing whether the material data was loaded successfully
  628. MaterialData newMaterialData;
  629. bool materialWasLoaded = false;
  630. /*/ Try to load the material from the filename retrieved from properties
  631. if (p_materialProperty)
  632. {
  633. // Get texture filename property, check if it is valid
  634. auto filenameProperty = p_materialProperty.getPropertyByID(Properties::Filename);
  635. if (filenameProperty.isVariableTypeString())
  636. {
  637. // Get texture filename string, check if it is valid
  638. auto filename = filenameProperty.getString();
  639. if (!filename.empty())
  640. {
  641. // Get the texture and load it to memory
  642. auto materialHandle = Loaders::texture2D().load(filename, p_materialType, false);
  643. auto materialLoadError = materialHandle.loadToMemory();
  644. // Check if the texture was loaded successfully
  645. if (materialLoadError == ErrorCode::Success)
  646. {
  647. newMaterialData.m_texture = materialHandle;
  648. materialWasLoaded = true;
  649. }
  650. else
  651. {
  652. ErrHandlerLoc::get().log(materialLoadError, ErrorSource::Source_Renderer);
  653. }
  654. }
  655. }
  656. }
  657. // Try to load the material from the filename retrieved from the model
  658. if (!materialWasLoaded)
  659. {
  660. // Check if there are enough materials, and if the material isn't default
  661. if (p_materialArraysFromModel.m_numMaterials > p_meshIndex
  662. && !p_materialArraysFromModel.m_materials[p_materialType][p_meshIndex].isEmpty()
  663. && !p_materialArraysFromModel.m_materials[p_materialType][p_meshIndex].isDefaultMaterial())
  664. {
  665. // Get the texture and load it to memory
  666. auto materialHandle = Loaders::texture2D().load(p_materialArraysFromModel.m_materials[p_materialType][p_meshIndex].m_filename, p_materialType, false);
  667. auto materialLoadError = materialHandle.loadToMemory();
  668. // Check if the texture was loaded successfully
  669. if (materialLoadError == ErrorCode::Success)
  670. {
  671. newMaterialData.m_texture = materialHandle;
  672. materialWasLoaded = true;
  673. }
  674. else
  675. {
  676. ErrHandlerLoc::get().log(materialLoadError, ErrorSource::Source_Renderer);
  677. }
  678. }
  679. }
  680. // All attempts to load the material were unsuccessful, so load a default material
  681. if (!materialWasLoaded)
  682. {
  683. newMaterialData.m_texture = Loaders::texture2D().getDefaultTexture(p_materialType);
  684. }
  685. */
  686. // Return the newly loaded material data
  687. return newMaterialData;
  688. }
  689. ModelComponent *RendererScene::loadModelComponent(const PropertySet &p_properties)
  690. {
  691. ModelComponent *newComponent = nullptr;
  692. // Check if models node is present
  693. if(p_properties)
  694. {
  695. // Create the model component
  696. newComponent = new ModelComponent(this, "");
  697. // Loop over each model entry in the node
  698. for(decltype(p_properties.getNumProperties()) iModel = 0, numModels = p_properties.getNumProperties(); iModel < numModels; iModel++)
  699. {
  700. // Get model filename
  701. auto modelName = p_properties.getPropertySet(iModel).getPropertyByID(Properties::Filename).getString();
  702. // Add a new model data entry, and get a reference to it
  703. newComponent->m_modelData.push_back(ModelData(Loaders::model().load(modelName, false)));
  704. auto &newModelData = newComponent->m_modelData.back();
  705. // Load the model to memory, to be able to access all of its meshes
  706. newModelData.m_model.loadToMemory();
  707. // Get the meshes array
  708. auto meshesInModelArray = newModelData.m_model.getMeshArray();
  709. // Get the meshes array
  710. auto meshesProperty = p_properties.getPropertySet(iModel).getPropertySetByID(Properties::Meshes);
  711. // Check if the meshes array node is present;
  712. // If it is present, only add the meshes included in the meshes node
  713. // If it is not present, add all the meshes included in the model
  714. if(meshesProperty)
  715. {
  716. // Loop over each mesh entry in the model node
  717. for(decltype(meshesProperty.getNumProperties()) iMesh = 0, numMeshes = meshesProperty.getNumProperties(); iMesh < numMeshes; iMesh++)
  718. {
  719. // Try to get the mesh index property node and check if it is present
  720. auto meshIndexProperty = meshesProperty.getPropertySet(iMesh).getPropertyByID(Properties::Index);
  721. if(meshIndexProperty)
  722. {
  723. // Get the mesh index, check if it is valid and within the range of mesh array that was loaded from the model
  724. const int meshDataIndex = meshIndexProperty.getInt();
  725. if(meshDataIndex > 0 && meshDataIndex < meshesInModelArray.size())
  726. {
  727. // Get material properties
  728. auto materialsProperty = meshesProperty.getPropertySet(iMesh).getPropertySetByID(Properties::Materials);
  729. // Define material data and material properties
  730. MaterialData materials[MaterialType::MaterialType_NumOfTypes];
  731. PropertySet materialProperties[MaterialType::MaterialType_NumOfTypes] =
  732. {
  733. materialsProperty.getPropertySetByID(Properties::Diffuse),
  734. materialsProperty.getPropertySetByID(Properties::Normal),
  735. materialsProperty.getPropertySetByID(Properties::Emissive),
  736. materialsProperty.getPropertySetByID(Properties::RMHAO)
  737. };
  738. // Go over each material type
  739. for(unsigned int iMatType = 0; iMatType < MaterialType::MaterialType_NumOfTypes; iMatType++)
  740. {
  741. // Check if an entry for the current material type was present within the properties
  742. if(materialProperties[iMatType])
  743. {
  744. // Load the material data
  745. materials[iMatType] = loadMaterialData(materialProperties[iMatType], newModelData.m_model.getMaterialArrays(), static_cast<MaterialType>(iMatType), meshDataIndex);
  746. }
  747. }
  748. /*if(materialsProperty)
  749. {
  750. auto diffuseMatProperty = materialsProperty.getPropertySetByID(Properties::Diffuse);
  751. materials[MaterialType_Diffuse] = loadMaterialData(diffuseMatProperty, newModelData.m_model.getMaterialArrays(), MaterialType_Diffuse, meshDataIndex);
  752. //newModelData.m_model.getMaterialArrays()
  753. //materials[MaterialType_Diffuse] = &materialProperty.getPropertySetByID(Properties::Diffuse);
  754. //materials[MaterialType_Normal] = &materialProperty.getPropertySetByID(Properties::Normal);
  755. //materials[MaterialType_Emissive] = &materialProperty.getPropertySetByID(Properties::Emissive);
  756. //materials[MaterialType_Combined] = &materialProperty.getPropertySetByID(Properties::RMHAO);
  757. }*/
  758. newModelData.m_meshes.push_back(MeshData(meshesInModelArray[iMesh], materials));
  759. }
  760. }
  761. }
  762. }
  763. else
  764. {
  765. // Get the material arrays that were loaded from the model file
  766. auto &materialArrayFromModel = newModelData.m_model.getMaterialArrays();
  767. // Iterate over every mesh in the model
  768. for(decltype(meshesInModelArray.size()) iMesh = 0, numMeshes = meshesInModelArray.size(); iMesh < numMeshes; iMesh++)
  769. {
  770. // Define material data and material properties
  771. MaterialData materials[MaterialType::MaterialType_NumOfTypes];
  772. // Go over each mesh in the model
  773. if(iMesh > materialArrayFromModel.m_numMaterials)
  774. {
  775. // Go over each material type
  776. for(unsigned int iMatType = 0; iMatType < MaterialType::MaterialType_NumOfTypes; iMatType++)
  777. {
  778. // Get the texture filename and load it to memory
  779. auto textureFromModel = Loaders::texture2D().load(materialArrayFromModel.m_materials[iMatType][iMesh].m_filename, static_cast<MaterialType>(iMatType), false);
  780. auto materialLoadError = textureFromModel.loadToMemory();
  781. // Check if the texture was loaded successfully
  782. if(materialLoadError == ErrorCode::Success)
  783. {
  784. materials[MaterialType::MaterialType_Diffuse].m_texture = textureFromModel;
  785. }
  786. else
  787. {
  788. ErrHandlerLoc::get().log(materialLoadError, ErrorSource::Source_Renderer);
  789. }
  790. }
  791. // Add the data for this mesh. Include materials loaded from the model itself, if they were present, otherwise, include default textures instead
  792. newModelData.m_meshes.push_back(MeshData(meshesInModelArray[iMesh], materials));
  793. }
  794. }
  795. }
  796. }
  797. }
  798. return newComponent;
  799. }
  800. ShaderComponent *RendererScene::loadShaderComponent(const PropertySet &p_properties)
  801. {
  802. ShaderComponent *newComponent = nullptr;
  803. // Check if shaders node is valid
  804. if(p_properties)
  805. {
  806. // Get nodes for different shader types
  807. auto fragmentShaderNode = p_properties.getPropertyByID(Properties::FragmentShader);
  808. auto vertexShaderNode = p_properties.getPropertyByID(Properties::VertexShader);
  809. // Check if any of the shader nodes are present
  810. if(fragmentShaderNode || vertexShaderNode)
  811. {
  812. // Load shader program
  813. auto shaderProgram = Loaders::shader().load(p_properties);
  814. // If shader is not default (i.e. at least one of the shader types was loaded)
  815. if(!shaderProgram->isDefaultProgram())
  816. {
  817. // Load the shader to memory and assign it to the new shader component
  818. shaderProgram->loadToMemory();
  819. newComponent = new ShaderComponent(this, "", *shaderProgram);
  820. }
  821. }
  822. }
  823. return newComponent;
  824. }
  825. LightComponent *RendererScene::loadLightComponent(const PropertySet &p_properties)
  826. {
  827. LightComponent *newComponent = nullptr;
  828. // Check if the property node is valid
  829. if(p_properties)
  830. {
  831. Math::Vec3f color;
  832. float intensity = 0.0f,
  833. cutoffAngle = 0.0f;
  834. Properties::PropertyID type = Properties::PropertyID::Null;
  835. // Load property data
  836. for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
  837. {
  838. switch(p_properties[i].getPropertyID())
  839. {
  840. case Properties::Color:
  841. color = p_properties[i].getVec3f();
  842. break;
  843. case Properties::CutoffAngle:
  844. // Convert to radians
  845. cutoffAngle = cosf(Math::toRadian(p_properties[i].getFloat()));
  846. break;
  847. case Properties::Intensity:
  848. intensity = p_properties[i].getFloat();
  849. break;
  850. case Properties::Type:
  851. type = p_properties[i].getID();
  852. break;
  853. }
  854. }
  855. // Create light component based on light type
  856. switch(type)
  857. {
  858. case Properties::DirectionalLight:
  859. {
  860. // Create and setup the directional light data set
  861. DirectionalLightDataSet dirLightDataSet;
  862. dirLightDataSet.m_color = color;
  863. dirLightDataSet.m_intensity = intensity;
  864. // Create the component of the directional light type
  865. newComponent = new LightComponent(this, "", dirLightDataSet);
  866. }
  867. break;
  868. case Properties::PointLight:
  869. {
  870. // Create and setup the point light data set
  871. PointLightDataSet pointLightDataSet;
  872. pointLightDataSet.m_color = color;
  873. pointLightDataSet.m_intensity = intensity;
  874. // Create the component of the point light type
  875. newComponent = new LightComponent(this, "",pointLightDataSet);
  876. }
  877. break;
  878. case Properties::SpotLight:
  879. {
  880. // Create and setup the spot light data set
  881. SpotLightDataSet spotLightDataSet;
  882. spotLightDataSet.m_color = color;
  883. spotLightDataSet.m_cutoffAngle = cutoffAngle;
  884. spotLightDataSet.m_intensity = intensity;
  885. // Create the component of the spot light type
  886. newComponent = new LightComponent(this, "", spotLightDataSet);
  887. }
  888. break;
  889. }
  890. }
  891. return newComponent;
  892. }
  893. ModelObject *RendererScene::loadModelObject(const PropertySet &p_properties)
  894. {
  895. // Get model properties
  896. auto &models = p_properties.getPropertySetByID(Properties::Models);
  897. auto &shaderProperty = p_properties.getPropertySetByID(Properties::Shaders);
  898. ErrorCode objPoolError = ErrorCode::Failure;
  899. ModelObject *newObject = nullptr;
  900. /*
  901. // If shaders are present
  902. if(shaderProperty)
  903. {
  904. // Try to add a new object to the pool
  905. objPoolError = m_shaderObjPool.add(
  906. this, p_properties.getPropertyByID(Properties::Name).getString(),
  907. Loaders::model().load(models.getPropertyByID(Properties::Filename).getString(), false),
  908. Loaders::shader().load(shaderProperty));
  909. // The newly added object in the pool
  910. newObject = m_shaderObjPool.getLastRawObject();
  911. newObject->getRenderableObjectData().m_shader->loadToMemory();
  912. }
  913. else
  914. {
  915. // Try to add a new object to the pool
  916. objPoolError = m_modelObjPool.add(
  917. this, p_properties.getPropertyByID(Properties::Name).getString(),
  918. Loaders::model().load(models.getPropertyByID(Properties::Filename).getString(), false));
  919. // The newly added object in the pool
  920. newObject = m_modelObjPool.getLastRawObject();
  921. }
  922. // If adding a new object was successful, continue to load data
  923. if(objPoolError == ErrorCode::Success)
  924. {
  925. // Load property data
  926. for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
  927. {
  928. switch(p_properties[i].getPropertyID())
  929. {
  930. case Properties::OffsetPosition:
  931. newObject->setOffsetPosition(p_properties[i].getVec3f());
  932. break;
  933. case Properties::OffsetRotation:
  934. newObject->setOffsetRotation(p_properties[i].getVec3f());
  935. break;
  936. case Properties::LocalPosition:
  937. newObject->setPosition(p_properties[i].getVec3f());
  938. break;
  939. case Properties::LocalRotation:
  940. newObject->setRotation(p_properties[i].getVec3f());
  941. break;
  942. case Properties::LocalScale:
  943. newObject->setScale(p_properties[i].getVec3f());
  944. break;
  945. case Properties::Lighting:
  946. newObject->setLighting(p_properties[i].getBool());
  947. break;
  948. case Properties::AlphaThreshold:
  949. newObject->setAlphaThreshold(p_properties[i].getFloat());
  950. break;
  951. case Properties::HeightScale:
  952. newObject->setHeightScale(p_properties[i].getFloat());
  953. break;
  954. case Properties::TextureTilingFactor:
  955. newObject->setTextureTilingFactor(p_properties[i].getFloat());
  956. break;
  957. }
  958. }
  959. // Adjust the position and rotation by offset
  960. newObject->setPosition(newObject->getBaseObjectData().m_position + newObject->getBaseObjectData().m_offsetPosition);
  961. newObject->setRotation(newObject->getBaseObjectData().m_rotation + newObject->getBaseObjectData().m_offsetRotation);
  962. // Get material parent property
  963. auto &materialProperty = p_properties.getPropertySetByID(Properties::Materials);
  964. // Get material properties
  965. const PropertySet *materials[MaterialType_NumOfTypes];
  966. materials[MaterialType_Diffuse] = &materialProperty.getPropertySetByID(Properties::Diffuse);
  967. materials[MaterialType_Normal] = &materialProperty.getPropertySetByID(Properties::Normal);
  968. materials[MaterialType_Emissive] = &materialProperty.getPropertySetByID(Properties::Emissive);
  969. materials[MaterialType_Combined] = &materialProperty.getPropertySetByID(Properties::RMHAO);
  970. // Process all materials
  971. // For every type of material
  972. for(unsigned int matType = 0; matType < MaterialType_NumOfTypes; matType++)
  973. // Check if material property is valid
  974. if(*materials[matType])
  975. // For every property set in the material property
  976. for(decltype(materials[matType]->getNumPropertySets()) i = 0, size = materials[matType]->getNumPropertySets(); i < size; i++)
  977. // Add the material to the new object
  978. newObject->addMaterial(static_cast<MaterialType>(matType),
  979. materials[matType]->getPropertySet(i).getPropertyByID(Properties::Filename).getString(),
  980. materials[matType]->getPropertySet(i).getPropertyByID(Properties::Index).getInt());
  981. // Get default material properties
  982. // Default materials replace any missing materials from the model file
  983. auto &defaultMaterials = materialProperty.getPropertySetByID(Properties::Default);
  984. if(defaultMaterials)
  985. {
  986. // Get individual default materials
  987. const PropertySet *defaulMaterials[MaterialType_NumOfTypes];
  988. defaulMaterials[MaterialType_Diffuse] = &defaultMaterials.getPropertySetByID(Properties::Diffuse);
  989. defaulMaterials[MaterialType_Normal] = &defaultMaterials.getPropertySetByID(Properties::Normal);
  990. defaulMaterials[MaterialType_Emissive] = &defaultMaterials.getPropertySetByID(Properties::Emissive);
  991. defaulMaterials[MaterialType_Combined] = &defaultMaterials.getPropertySetByID(Properties::RMHAO);
  992. // Process default materials by assigning them to the model object
  993. for(unsigned int matType = 0; matType < MaterialType_NumOfTypes; matType++)
  994. if(*defaulMaterials[matType])
  995. newObject->setDefaultMaterial(matType, defaulMaterials[matType]->getPropertyByID(Properties::Filename).getString());
  996. }
  997. return newObject;
  998. }
  999. // If adding a new object failed, log an error and return a nullptr
  1000. else
  1001. {
  1002. ErrHandlerLoc::get().log(objPoolError, ErrorSource::Source_SceneLoader);
  1003. return nullptr;
  1004. }*/
  1005. return newObject;
  1006. }
  1007. CameraObject *RendererScene::loadCameraObject(const PropertySet & p_properties)
  1008. {
  1009. // Delete an existing camera
  1010. if(m_camera != nullptr)
  1011. delete m_camera;
  1012. // Create a new camera
  1013. m_camera = new CameraObject(this, p_properties.getPropertyByID(Properties::Name).getString());
  1014. return m_camera;
  1015. }
  1016. EnvironmentMapObject *RendererScene::loadEnvironmentMap(const PropertySet &p_properties)
  1017. {
  1018. EnvironmentMapObject *newObject = nullptr;
  1019. /*ErrorCode objPoolError = ErrorCode::Failure;
  1020. bool staticEnvMap = false;
  1021. auto &materials = p_properties.getPropertySetByID(Properties::Materials);
  1022. std::string filenames[CubemapFace_NumOfFaces];
  1023. if(materials.getNumPropertySets() >= CubemapFace_NumOfFaces)
  1024. for(unsigned int face = CubemapFace_PositiveX; face < CubemapFace_NumOfFaces; face++)
  1025. filenames[face] = materials.getPropertySet(face).getPropertyByID(Properties::Filename).getString();
  1026. // Check if the environment map should be a static one
  1027. staticEnvMap = p_properties.getPropertyByID(Properties::Static).getBool();
  1028. if(staticEnvMap)
  1029. {
  1030. //newObject = new EnvironmentMapObject(this,
  1031. // p_properties.getPropertyByID(Properties::Name).getString(),
  1032. // Loaders::textureCubemap().load(filenames, false));
  1033. m_skybox = newObject;
  1034. }
  1035. else
  1036. {
  1037. objPoolError = m_envMapPool.add(this,
  1038. p_properties.getPropertyByID(Properties::Name).getString(),
  1039. Loaders::textureCubemap().load(filenames, false));
  1040. // If adding a new object failed, log an error and return a nullptr
  1041. if (objPoolError == ErrorCode::Success)
  1042. {
  1043. ErrHandlerLoc::get().log(objPoolError, ErrorSource::Source_SceneLoader);
  1044. return nullptr;
  1045. }
  1046. }
  1047. // Load property data
  1048. for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
  1049. {
  1050. //switch(p_properties[i].getPropertyID())
  1051. //{
  1052. //case Properties::Position:
  1053. // newObject->setPosition(p_properties[i].getVec3f());
  1054. // break;
  1055. //}
  1056. }*/
  1057. return newObject;
  1058. }
  1059. DirectionalLightObject *RendererScene::loadDirectionalLight(const PropertySet &p_properties)
  1060. {
  1061. // Since only one directional light is supported at a time, delete the old one first
  1062. delete m_directionalLight;
  1063. m_directionalLight = new DirectionalLightObject(this,
  1064. p_properties.getPropertyByID(Properties::Name).getString(),
  1065. DirectionalLightDataSet());
  1066. // Load property data
  1067. for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
  1068. {
  1069. switch(p_properties[i].getPropertyID())
  1070. {
  1071. case Properties::Color:
  1072. m_directionalLight->setColor(p_properties[i].getVec3f());
  1073. break;
  1074. case Properties::Direction:
  1075. // Need to normalize the light direction
  1076. m_directionalLight->setDirection(Math::normalize(p_properties[i].getVec3f()));
  1077. break;
  1078. case Properties::Intensity:
  1079. m_directionalLight->setIntensity(p_properties[i].getFloat());
  1080. break;
  1081. }
  1082. }
  1083. m_directionalLight->init();
  1084. return m_directionalLight;
  1085. }
  1086. PointLightObject *RendererScene::loadPointLight(const PropertySet &p_properties)
  1087. {
  1088. ErrorCode objPoolError = ErrorCode::Failure;
  1089. PointLightObject *newObject = nullptr;
  1090. /*
  1091. // Try to add a new object to the pool
  1092. objPoolError = m_pointLightPool.add(
  1093. this, p_properties.getPropertyByID(Properties::Name).getString(), PointLightDataSet());
  1094. // Get the newly added object in the pool
  1095. newObject = m_pointLightPool.getLastRawObject();
  1096. // If adding a new object was successful, continue to load data
  1097. if(objPoolError == ErrorCode::Success)
  1098. {
  1099. // Load property data
  1100. for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
  1101. {
  1102. switch(p_properties[i].getPropertyID())
  1103. {
  1104. case Properties::Attenuation:
  1105. newObject->setAttenuation(p_properties[i].getVec3f());
  1106. break;
  1107. case Properties::Color:
  1108. newObject->setColor(p_properties[i].getVec3f());
  1109. break;
  1110. case Properties::Intensity:
  1111. newObject->setIntensity(p_properties[i].getFloat());
  1112. break;
  1113. case Properties::OffsetPosition:
  1114. newObject->setOffsetPosition(p_properties[i].getVec3f());
  1115. break;
  1116. case Properties::Position:
  1117. newObject->setPosition(p_properties[i].getVec3f());
  1118. break;
  1119. }
  1120. }
  1121. // Adjust the position and rotation by offset
  1122. newObject->setPosition(newObject->getLightDataSet().m_position + newObject->getOffsetPosition());
  1123. }
  1124. // If adding a new object failed, log an error and return a nullptr
  1125. else
  1126. {
  1127. ErrHandlerLoc::get().log(objPoolError, ErrorSource::Source_SceneLoader);
  1128. return nullptr;
  1129. }
  1130. */
  1131. return newObject;
  1132. }
  1133. SpotLightObject *RendererScene::loadSpotLight(const PropertySet &p_properties)
  1134. {
  1135. ErrorCode objPoolError = ErrorCode::Failure;
  1136. SpotLightObject *newObject = nullptr;
  1137. /*
  1138. // Try to add a new object to the pool
  1139. objPoolError = m_spotLightPool.add(
  1140. this, p_properties.getPropertyByID(Properties::Name).getString(), SpotLightDataSet());
  1141. // Get the newly added object in the pool
  1142. newObject = m_spotLightPool.getLastRawObject();
  1143. // If adding a new object was successful, continue to load data
  1144. if(objPoolError == ErrorCode::Success)
  1145. {
  1146. // Load property data
  1147. for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
  1148. {
  1149. switch(p_properties[i].getPropertyID())
  1150. {
  1151. case Properties::Attenuation:
  1152. newObject->setAttenuation(p_properties[i].getVec3f());
  1153. break;
  1154. case Properties::CutoffAngle:
  1155. // Convert to radians
  1156. newObject->setCutoffAngle(cosf(Math::toRadian(p_properties[i].getFloat())));
  1157. break;
  1158. case Properties::Color:
  1159. newObject->setColor(p_properties[i].getVec3f());
  1160. break;
  1161. case Properties::Direction:
  1162. newObject->setDirection(p_properties[i].getVec3f());
  1163. break;
  1164. case Properties::Intensity:
  1165. newObject->setIntensity(p_properties[i].getFloat());
  1166. break;
  1167. case Properties::OffsetPosition:
  1168. newObject->setOffsetPosition(p_properties[i].getVec3f());
  1169. break;
  1170. case Properties::OffsetRotation:
  1171. newObject->setOffsetRotation(p_properties[i].getVec3f());
  1172. break;
  1173. case Properties::Position:
  1174. newObject->setPosition(p_properties[i].getVec3f());
  1175. break;
  1176. }
  1177. }
  1178. // Adjust the position and rotation by offset (and normalize the direction)
  1179. newObject->setPosition(newObject->getLightDataSet().m_position + newObject->getOffsetPosition());
  1180. newObject->setDirection(Math::normalize(newObject->getLightDataSet().m_direction + newObject->getOffsetRotation()));
  1181. }
  1182. // If adding a new object failed, log an error and return a nullptr
  1183. else
  1184. {
  1185. ErrHandlerLoc::get().log(objPoolError, ErrorSource::Source_SceneLoader);
  1186. return nullptr;
  1187. }
  1188. */
  1189. return newObject;
  1190. }