| 9 | } |
| 10 | |
| 11 | void TrackRenderer::renderTrack(const Camera &mainCamera, const Light &sunLight, const Light &cameraLight, std::vector<int> activeTrackBlockIDs, const ParamData &userParams, uint64_t engineTicks, GLuint depthTextureID, const glm::mat4 &lightSpaceMatrix, float ambientFactor) { |
| 12 | trackShader.use(); |
| 13 | |
| 14 | // This shader state doesnt change during a track renderpass |
| 15 | trackShader.setClassic(userParams.use_classic_graphics); |
| 16 | trackShader.loadProjectionViewMatrices(mainCamera.ProjectionMatrix, mainCamera.ViewMatrix); |
| 17 | trackShader.loadLightSpaceMatrix(lightSpaceMatrix); |
| 18 | trackShader.loadSpecular(userParams.trackSpecDamper, userParams.trackSpecReflectivity); |
| 19 | trackShader.bindTextureArray(track->textureArrayID); |
| 20 | trackShader.loadShadowMapTexture(depthTextureID); |
| 21 | trackShader.loadAmbientFactor(ambientFactor); |
| 22 | |
| 23 | std::vector<Light> globalLights; |
| 24 | globalLights.emplace_back(sunLight); |
| 25 | // Maybe put the camera light in here too? |
| 26 | |
| 27 | // Render the per-trackblock data |
| 28 | for (int activeTrackBlockID : activeTrackBlockIDs) { |
| 29 | TrackBlock active_track_Block = track->track_blocks[activeTrackBlockID]; |
| 30 | // TODO: Merge lighting contributions across track block, must use a smarter Track structure, also must be a better way of building this from the Entities. This will be too slow. |
| 31 | std::vector<Light> contributingLights; |
| 32 | contributingLights.insert(contributingLights.begin(), globalLights.begin(), globalLights.end()); |
| 33 | for (auto &light_entity : active_track_Block.lights) { |
| 34 | contributingLights.emplace_back(boost::get<Light>(light_entity.glMesh)); |
| 35 | } |
| 36 | // TODO: Merge lighting contributions across track block, must use a smarter Track structure, also must be a better way of building this from the Entities. This will be too slow. |
| 37 | trackShader.loadLights(contributingLights); |
| 38 | for (auto &track_block_entity : active_track_Block.track) { |
| 39 | trackShader.loadTransformMatrix(boost::get<Track>(track_block_entity.glMesh).ModelMatrix); |
| 40 | boost::get<Track>(track_block_entity.glMesh).render(); |
| 41 | } |
| 42 | for (auto &track_block_entity : active_track_Block.objects) { |
| 43 | trackShader.loadTransformMatrix(boost::get<Track>(track_block_entity.glMesh).ModelMatrix); |
| 44 | boost::get<Track>(track_block_entity.glMesh).render(); |
| 45 | } |
| 46 | // Could render Lanes with a simpler shader set, straight vert MVP transform w/ one texture sample on bound lane texture |
| 47 | // Probably not worth the overhead of switching GL state |
| 48 | for (auto &track_block_entity : active_track_Block.lanes) { |
| 49 | trackShader.loadTransformMatrix(boost::get<Track>(track_block_entity.glMesh).ModelMatrix); |
| 50 | boost::get<Track>(track_block_entity.glMesh).render(); |
| 51 | } |
| 52 | } |
| 53 | |
| 54 | // Render the global data, animations go here. |
| 55 | for (auto &global_object : track->global_objects) { |
| 56 | if (track->tag == NFS_4 || track->tag == NFS_3) { |
| 57 | uint32_t globalObjIdx = 4 * track->nBlocks; //Global Objects |
| 58 | NFS3_4_DATA::XOBJDATA animObject = boost::get<shared_ptr<NFS3_4_DATA::TRACK>>(track->trackData)->xobj[globalObjIdx].obj[global_object.entityID]; |
| 59 | if (animObject.type3 == 3) { |
| 60 | if (animMap[global_object.entityID] < animObject.nAnimLength) { |
| 61 | boost::get<Track>(global_object.glMesh).position = glm::normalize(glm::quat(glm::vec3(glm::radians(-90.f), 0, 0))) * glm::vec3((animObject.animData[animMap[global_object.entityID]].pt.x / 65536.0) / 10, (animObject.animData[animMap[global_object.entityID]].pt.y / 65536.0) / 10, (animObject.animData[animMap[global_object.entityID]].pt.z / 65536.0) / 10); |
| 62 | boost::get<Track>(global_object.glMesh).orientation = glm::normalize(glm::quat(glm::vec3(glm::radians(-180.f), glm::radians(-180.f), 0))) * glm::normalize(glm::quat(-animObject.animData[animMap[global_object.entityID]].od1, animObject.animData[animMap[global_object.entityID]].od2, animObject.animData[animMap[global_object.entityID]].od3, animObject.animData[animMap[global_object.entityID]].od4)); |
| 63 | animMap[global_object.entityID]++; |
| 64 | } else { |
| 65 | animMap[global_object.entityID] = 0; |
| 66 | } |
| 67 | } |
| 68 | } else if (track->tag == NFS_2 || track->tag == NFS_2_SE || track->tag == NFS_3_PS1) { |
no test coverage detected