#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace ACGL::OpenGL; using namespace ACGL::Base; using namespace ACGL::Utils; void AtmosphereTestScene::switchConsole() { if (isInterpolatingCamera) return; m_player->setHasControl(false); if (isFocusedOnConsole) { camStartPos = m_player->getCockpitPosition(); camTargetPos = { 0, 0 , 0 }; camStartRot = glm::quat_cast(m_player->getRotation()); camTargetRot = glm::quat(); m_console.pause(); m_renderer->setRenderPassActive("Main"_sh, true); m_renderer->setRenderPassActive("Skybox"_sh, true); cockpitSoundSource->setVolume(0); cockpitSoundSource->play(); } else { // TODO: Fix returning to console! return; camStartPos = m_player->getCockpitPosition(); camTargetPos = CAM_CONSOLE_POS; camStartRot = glm::quat_cast(m_player->getRotation()); camTargetRot = glm::quat_cast(CAM_CONSOLE_ROT); m_console.play(); } isFocusedOnConsole = !isFocusedOnConsole; interpolationTime = 0; totalInterpolationTime = 4; isInterpolatingCamera = true; } bool AtmosphereTestScene::startup() { if (!Scene::startup()) { return false; } RESOLVE_DEPENDENCY(m_player); RESOLVE_DEPENDENCY(m_orbitals); m_renderer->addEffect(); consoleCamera = m_sceneGraph->create(); consoleCamera.assign(); consoleCamera.assign(50, 0.1, 50); m_audio->setListener(consoleCamera); m_renderer->setRenderPassActive("Main"_sh, false); m_renderer->setRenderPassActive("Skybox"_sh, false); m_renderer->addRenderPass(consoleCamera, "Console"_sh); m_console.m_events = m_events; m_console.m_renderer = m_renderer; m_console.m_sceneGraph = m_sceneGraph; m_console.m_audio = m_audio; auto textTexture = Texture2DFileManager::the()->get(Texture2DCreator("none.png")); auto textGeom = Geometry{ VertexArrayObjectCreator("loading_text.obj").create() }; textGeom.vao->setMode(GL_PATCHES); auto textShader = ShaderProgramFileManager::the()->get(ShaderProgramCreator("console/Title") .attributeLocations(textGeom.vao->getAttributeLocations()) .fragmentDataLocations(m_renderer->getGBufferLocations())); loadingText = m_sceneGraph->create(); loadingText.assign(textGeom, Material{ glm::vec4{ 1, 1, 1, 1 }, glm::vec4{ 1, 1, 1, 1 } * 10, textTexture, nullptr, nullptr, textShader, false, RenderQueue::OPAQUE, GL_BACK }, 0, m_renderer->getRenderPassId("Console"_sh)); auto textTransform = loadingText.assign(); textTransform->position = { 0, -3, -11 }; loadingText.assign(glm::vec4(0, 0.2, 1.0, 5), glm::vec3(1, 0, 0), false, LightType::POINT, m_renderer->getRenderPassId("Console"_sh)); SDL_SetRelativeMouseMode(SDL_TRUE); m_player->setHasControl(false); m_player->setCockpitPosition(CAM_CONSOLE_POS); m_player->setRotation(CAM_CONSOLE_ROT); m_events->subscribe([this](const SimulateEvent &e) { if (didOneFrame && !resourceLoadingFinished) { loadMainSceneResources(); switchToMainScene(); m_renderer->setRenderPassOnlyTexture("Console"_sh, true); m_console.startup(); } didOneFrame = true; if (!resourceLoadingFinished) { return; } sunLight->dir = -glm::normalize(m_player->getWorldPosition()); cockpitSunLight->dir = glm::vec3(glm::dvec4(sunLight->dir, 0) * m_player->getRotation()); if (isFocusedOnConsole) { if (m_console.update(e, m_player->getKeyTable())) { switchConsole(); } } if (isInterpolatingCamera) { double interpolationPercent = 1.0 - glm::pow(1 - interpolationTime / totalInterpolationTime, 2); m_player->setCockpitPosition(camStartPos + (camTargetPos-camStartPos)*interpolationPercent); interpolationPercent = 1.0 - glm::pow(1 - interpolationTime / totalInterpolationTime, 5); consoleSoundSource->setVolume((1.0f - interpolationTime / totalInterpolationTime) * 0.5); cockpitSoundSource->setVolume(interpolationTime / totalInterpolationTime); glm::quat rot = glm::slerp(camStartRot, camTargetRot, (float)interpolationPercent); m_player->setRotation(glm::mat4_cast(rot)); interpolationTime += e.dt; if (interpolationTime >= totalInterpolationTime) { m_player->setCockpitPosition(camTargetPos); m_player->setRotation(glm::mat4_cast(camTargetRot)); isInterpolatingCamera = false; m_player->setHasControl(true); m_renderer->setRenderPassActive("Console"_sh, false); consoleSoundSource->setVolume(0); cockpitSoundSource->setVolume(1); } } }); m_events->subscribe([this](const KeyboardEvent &e) { switch (e.originalEvent.key.keysym.scancode) { case SDL_SCANCODE_TAB: if (e.originalEvent.key.type == SDL_KEYDOWN) { m_player->attachToParent(earth); float r = earth.component()->scale.x; m_player->setPosition(glm::vec3(0, 0, r * 1.2)); m_player->setRotation(glm::mat4()); } break; case SDL_SCANCODE_RETURN: if (e.originalEvent.key.type == SDL_KEYDOWN) { switchConsole(); } case SDL_SCANCODE_R: if (e.originalEvent.key.type == SDL_KEYDOWN) { ShaderProgramFileManager::the()->updateAll(); } default: break; } }); // Subscribe to the UI drawing event. // This is called once per frame m_events->subscribe<"DrawUI"_sh>([this]() { ImGui::Begin("Camera Control", 0, ImGuiWindowFlags_::ImGuiWindowFlags_AlwaysAutoResize); float r; if (ImGui::Button("Sun/Global", glm::vec2(100, 20))) { // Reset the camera to sun coords m_player->attachToParent(sun); r = sun.component()->scale.x; m_player->setPosition(glm::dvec3(0, 0, r * 1.2)); m_player->setRotation(glm::dmat4()); } if (ImGui::Button("Earth", glm::vec2(100, 20))) { m_player->attachToParent(earth); r = earth.component()->scale.x; m_player->setPosition(glm::dvec3(0, 0, r * 1.2)); m_player->setRotation(glm::dmat4()); } ImGui::End(); }); return true; } void AtmosphereTestScene::switchToMainScene() { { auto skyboxPassId = m_renderer->getRenderPassId("Skybox"_sh); skybox = m_sceneGraph->create(); skybox.assign(); skybox.assign(skyboxGeometry, skyboxMaterial, 0, skyboxPassId); skybox.assign(glm::vec4(1, 1, 1, 1), glm::vec3(1, 0, 0), false, LightType::POINT, skyboxPassId); } { auto mainPassId = m_renderer->getRenderPassId("Main"_sh); // Let's create a placeholder sun sun = m_sceneGraph->create(); // Add a transform component to it so we are able to position it in space auto sunTransform = sun.assign(); // Add a Drawable component to it so the renderer has something to draw sun.assign(sunGeometry, sunMaterial, 0, mainPassId); float scale = m_orbitals->solarRadius * m_orbitals->scaleFactor * 0.1; sunTransform->scale = glm::dvec3(scale); sunLight = sun.assign(glm::vec4(1, 1, 1, 3), glm::vec3(1, 0, 0), false, LightType::DIRECTIONAL, mainPassId); // create a planet! // Mass in solar masses, Radius in solar radii, Eccentricity, Semimajor // axis, Inclination, Ascending Node, Arg. of Periapsis, time at perihelion // mass radius //e // a i N w earth = m_orbitals->addPlanet(sunTransform, "Earth", 0.000002988, 0.009153735632184, 0.016713, 1.000000, 0.0000000, 0.00000, 4.93533, 0); m_player->attachToParent(earth); double r = earth.component()->scale.x; m_player->setPosition(glm::dvec3(0, 0, r * 1.2)); } { auto cockpitPassId = m_renderer->getRenderPassId("Cockpit"_sh); cockpit = m_sceneGraph->create(); auto cockpitDrawable = cockpit.assign( cockpitGeometry, cockpitMaterial, 0, cockpitPassId); auto cockpitTransform = cockpit.assign(); cockpitTransform->position = glm::dvec3(0, 0, 0); cockpitDrawable->visible = true; auto cockpitLight = cockpit.assign(glm::vec4(1, 1, 1, 0.2), glm::vec3(1, 0, 0), false, LightType::POINT, cockpitPassId); auto soundTrack = m_audio->createSound("chipzel - Spectra - 04 Formed in the Clouds (Interlude).mp3", SoundMode::MODE_2D); cockpitSoundSource = cockpit.assign(soundTrack); cockpitSun = m_sceneGraph->create(); cockpitSun.assign(); cockpitSunLight = cockpitSun.assign(glm::vec4(1, 1, 1, 3), glm::vec3(1, 0, 0), true, LightType::DIRECTIONAL, cockpitPassId); auto blinkButton = m_sceneGraph->create(); blinkButton.assign(glm::vec4(1, 0.2, 0.2, 5), glm::vec3(1, 0, 0), false, LightType::POINT, cockpitPassId); auto transform = blinkButton.assign(); transform->parent = cockpitTransform; transform->position = {0.7655, -0.4545, -1.643}; blinkButton = m_sceneGraph->create(); blinkButton.assign(glm::vec4(0, 0.2, 1.0, 5), glm::vec3(1, 0, 0), false, LightType::POINT, cockpitPassId); transform = blinkButton.assign(); transform->parent = cockpitTransform; transform->position = {-0.7655, -0.4545, -1.643}; auto console = m_sceneGraph->create(); auto consoleGeom = Geometry{ VertexArrayObjectCreator("console.obj").create() }; consoleGeom.vao->setMode(GL_PATCHES); console.assign( consoleGeom, Material{glm::vec4{1, 1, 1, 1}, glm::vec4{1, 1, 1, 1}, m_renderer->getRenderPassTarget("Console"_sh), nullptr, nullptr, skyboxMaterial.prog, false, RenderQueue::OPAQUE, GL_BACK}, 0, cockpitPassId); auto consoleTransform = console.assign(); soundTrack = m_audio->createSound("chipzel - Spectra - 01 Spectra.mp3", SoundMode::MODE_2D); consoleSoundSource = console.assign(soundTrack); consoleSoundSource->setVolume(0.5); consoleSoundSource->play(); } loadingText.component()->visible = false; loadingText.destroy(); } void AtmosphereTestScene::loadMainSceneResources() { { auto vaoSkybox = VertexArrayObjectCreator("skybox.obj").create(); auto skyboxShader = ShaderProgramFileManager::the()->get( ShaderProgramCreator("Skybox") .attributeLocations(vaoSkybox->getAttributeLocations()) .fragmentDataLocations(m_renderer->getGBufferLocations())); auto skyboxTexture = Texture2DFileManager::the()->get(Texture2DCreator("skybox.png")); skyboxGeometry = {vaoSkybox}; skyboxGeometry.vao->setMode(GL_PATCHES); skyboxMaterial = {glm::vec4{1, 1, 1, 1}, glm::vec4{1, 1, 1, 1}, skyboxTexture, nullptr, nullptr, skyboxShader, false, RenderQueue::OPAQUE, GL_BACK}; } { auto vaoSun = VertexArrayObjectCreator("uvsphere.obj").create(); auto checkboardTexture = Texture2DFileManager::the()->get(Texture2DCreator("checkerboard.png")); auto sunShader = ShaderProgramCreator("PBR") .attributeLocations(vaoSun->getAttributeLocations()) .fragmentDataLocations(m_renderer->getGBufferLocations()) .create(); sunGeometry = {vaoSun}; sunGeometry.vao->setMode(GL_PATCHES); sunMaterial = {glm::vec4{1, 1, 1, 1}, glm::vec4{2, 2, 1, 20}, checkboardTexture, nullptr, nullptr, sunShader, false, RenderQueue::OPAQUE, GL_BACK}; } { // create cockpit auto vaoCockpit = VertexArrayObjectCreator("cockpit.obj").create(); auto cockpitShader = ShaderProgramCreator("PBR") .attributeLocations(vaoCockpit->getAttributeLocations()) .fragmentDataLocations(m_renderer->getGBufferLocations()) .create(); cockpitMaterial = { glm::vec4{0.4, 0.4, 0.4, 1}, glm::vec4{0, 0, 0, 1}, Texture2DFileManager::the()->get(Texture2DCreator( "cockpit/cockpit_DefaultMaterial_AlbedoTransparency.png")), Texture2DFileManager::the()->get( Texture2DCreator("cockpit/cockpit_DefaultMaterial_Normal.png")), Texture2DFileManager::the()->get(Texture2DCreator( "cockpit/cockpit_DefaultMaterial_SpecularSmoothness.png")), cockpitShader, true, RenderQueue::OPAQUE, GL_BACK}; cockpitGeometry = {vaoCockpit}; cockpitGeometry.vao->setMode(GL_PATCHES); } resourceLoadingFinished = true; } void AtmosphereTestScene::shutdown() {}