/* * Copyright (C) 2017 Christopher J. Howard * * This file is part of Antkeeper Source Code. * * Antkeeper Source Code is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Antkeeper Source Code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Antkeeper Source Code. If not, see . */ #include "main-menu-state.hpp" #include "title-state.hpp" #include "../application.hpp" #include "../debug.hpp" #include "../camera-controller.hpp" void drawShaft(LineBatcher* lineBatcher, const Shaft* shaft); void drawChamber(LineBatcher* lineBatcher, const Chamber* chamber) { float helixAngle = chamber->parent->getHelixAngle(chamber->relativeDepth); float minAngle = helixAngle - chamber->centralAngle * 0.5f; float maxAngle = helixAngle + chamber->centralAngle * 0.5f; // Find position on helix Vector3 helixPosition = chamber->parent->getHelixPosition(chamber->relativeDepth); helixPosition.y = -helixPosition.y; // Move annulus toward helix by the inner radius Vector3 helixDirection = glm::normalize(Vector3(std::cos(helixAngle), 0.0f, std::sin(helixAngle))); Vector3 offset = helixPosition - helixDirection * (chamber->innerRadius - chamber->parent->shaftRadius); int stepCount = 10; float angleStep = chamber->centralAngle / (float)stepCount; for (int i = 0; i < stepCount; ++i) { float angle0 = minAngle + angleStep * (float)i; float angle1 = minAngle + angleStep * (float)(i + 1); float x0 = std::cos(angle0); float z0 = std::sin(angle0); float x1 = std::cos(angle1); float z1 = std::sin(angle1); Vector3 innerStart; innerStart.x = x0 * chamber->innerRadius; innerStart.y = 0.0f; innerStart.z = z0 * chamber->innerRadius; Vector3 outerStart; outerStart.x = x0 * chamber->outerRadius; outerStart.y = 0.0f; outerStart.z = z0 * chamber->outerRadius; Vector3 innerEnd; innerEnd.x = x1 * chamber->innerRadius; innerEnd.y = 0.0f; innerEnd.z = z1 * chamber->innerRadius; Vector3 outerEnd; outerEnd.x = x1 * chamber->outerRadius; outerEnd.y = 0.0f; outerEnd.z = z1 * chamber->outerRadius; lineBatcher->draw(offset + innerStart, offset + innerEnd); lineBatcher->draw(offset + outerStart, offset + outerEnd); } Vector3 leftWallStart; leftWallStart.x = std::cos(minAngle) * chamber->innerRadius; leftWallStart.y = 0.0f; leftWallStart.z = std::sin(minAngle) * chamber->innerRadius; Vector3 leftWallEnd; leftWallEnd.x = std::cos(minAngle) * chamber->outerRadius; leftWallEnd.y = 0.0f; leftWallEnd.z = std::sin(minAngle) * chamber->outerRadius; Vector3 rightWallStart; rightWallStart.x = std::cos(maxAngle) * chamber->innerRadius; rightWallStart.y = 0.0f; rightWallStart.z = std::sin(maxAngle) * chamber->innerRadius; Vector3 rightWallEnd; rightWallEnd.x = std::cos(maxAngle) * chamber->outerRadius; rightWallEnd.y = 0.0f; rightWallEnd.z = std::sin(maxAngle) * chamber->outerRadius; lineBatcher->draw(offset + leftWallStart, offset + leftWallEnd); lineBatcher->draw(offset + rightWallStart, offset + rightWallEnd); if (chamber->child != nullptr) { drawShaft(lineBatcher, chamber->child); } } void drawShaft(LineBatcher* lineBatcher, const Shaft* shaft) { // Draw helix int stepCount = 50; float depthStep = shaft->shaftDepth / (float)stepCount; for (int i = 0; i < stepCount; ++i) { Vector3 start = shaft->getHelixPosition((float)i * depthStep); Vector3 end = shaft->getHelixPosition((float)(i + 1) * depthStep); start.y = -start.y; end.y = -end.y; lineBatcher->draw(start, end); } // Draw children for (const Chamber* chamber: shaft->children) { drawChamber(lineBatcher, chamber); } } void MainMenuState::generateNest() { NestParameters params; params.randomSeed = std::rand(); params.maxShaftGeneration = 2; params.minShaftRadius = 0.0f; params.maxShaftRadius = 0.0f; params.minShaftDepth = 4.0f; params.maxShaftDepth = 6.0f; params.minShaftHelixRadius = 0.1f; params.maxShaftHelixRadius = 1.0f; params.minShaftHelixPitch = 0.25f; params.maxShaftHelixPitch = 0.75f; params.minShaftChamberCount = 1; params.maxShaftChamberCount = 5; params.minShaftChamberPitch = 0.5f; params.maxShaftChamberPitch = 2.0f; params.minChamberInnerRadius = 0.2f; params.maxChamberInnerRadius = 0.2f; params.minChamberOuterRadius = 0.5f; params.maxChamberOuterRadius = 0.5f; params.minChamberCentralAngle = glm::radians(240.0f); params.maxChamberCentralAngle = glm::radians(240.0f); nest.setParameters(params); nest.generate(); // Draw nest application->lineBatcher->setColor(Vector4(1.0f)); application->lineBatcher->setWidth(0.015f); application->lineBatcher->begin(); drawShaft(application->lineBatcher, nest.getRootShaft()); application->lineBatcher->end(); } MainMenuState::MainMenuState(Application* application): ApplicationState(application) {} MainMenuState::~MainMenuState() {} void MainMenuState::enter() { // Open main menu application->enterMenu(0); application->menuSelectorLabel->setVisible(true); // Start fade-in application->blackoutImage->setVisible(true); application->fadeInTween->start(); application->backgroundLayer->addObject(&application->bgCamera); application->backgroundLayer->addObject(&application->bgBatch); // Add nest application->defaultLayer->addObject(&application->nestModelInstance); application->surfaceCam->setCamera(&application->camera); application->surfaceCam->setFocalPoint(Vector3(-10.0f, -13.3f, 0.0f)); application->surfaceCam->setFocalDistance(89.5f); application->surfaceCam->setElevation(glm::radians(15.0f)); application->surfaceCam->setAzimuth(glm::radians(0.0f)); application->surfaceCam->setTargetFocalPoint(application->surfaceCam->getFocalPoint()); application->surfaceCam->setTargetFocalDistance(application->surfaceCam->getFocalDistance()); application->surfaceCam->setTargetElevation(application->surfaceCam->getElevation()); application->surfaceCam->setTargetAzimuth(application->surfaceCam->getAzimuth()); application->surfaceCam->update(0.0f); // 3D camera application->camera.setPerspective( glm::radians(25.0f), (float)application->width / (float)application->height, 0.1f, 1000.0f); } void MainMenuState::execute() { // Navigate menu if (application->menuDown.isTriggered() && !application->menuDown.wasTriggered()) { if (application->selectedMenuItemIndex < application->currentMenu->getItemCount() - 1) { application->selectMenuItem(application->selectedMenuItemIndex + 1); } else { application->selectMenuItem(0); } } else if (application->menuUp.isTriggered() && !application->menuUp.wasTriggered()) { if (application->selectedMenuItemIndex > 0) { application->selectMenuItem(application->selectedMenuItemIndex - 1); } else { application->selectMenuItem(application->currentMenu->getItemCount() - 1); } } if (application->menuSelect.isTriggered() && !application->menuSelect.wasTriggered()) { application->activateMenuItem(application->selectedMenuItemIndex); } else if (application->menuCancel.isTriggered() && !application->menuCancel.wasTriggered()) { application->changeState(application->titleState); } float lineHeight = application->menuFont->getMetrics().getHeight(); const UIContainer* container = application->menuContainers[application->currentMenuIndex]; application->menuSelectorLabel->setTranslation( Vector2(container->getPosition().x - application->menuSelectorLabel->getDimensions().x * 1.5f, container->getPosition().y + lineHeight * 0.5f - application->menuSelectorLabel->getDimensions().y * 0.5f + lineHeight * application->selectedMenuItemIndex)); // Move camera Vector2 movementVector(0.0f); if (application->cameraMoveLeft.isTriggered()) movementVector.x -= application->cameraMoveLeft.getCurrentValue(); if (application->cameraMoveRight.isTriggered()) movementVector.x += application->cameraMoveRight.getCurrentValue(); if (application->cameraMoveForward.isTriggered()) movementVector.y -= application->cameraMoveForward.getCurrentValue(); if (application->cameraMoveBack.isTriggered()) movementVector.y += application->cameraMoveBack.getCurrentValue(); if (movementVector.x != 0.0f || movementVector.y != 0.0f) { movementVector *= 0.005f * application->surfaceCam->getFocalDistance() * application->dt / (1.0f / 60.0f); application->surfaceCam->setTargetFocalPoint(application->surfaceCam->getTargetFocalPoint() + Vector3(movementVector.x, -movementVector.y, 0.0f)); Vector3 focal = application->surfaceCam->getFocalPoint(); std::cout << focal.x << ", " << focal.y << ", " << focal.z << "; " << application->surfaceCam->getFocalDistance() << std::endl; } // Zoom camera float zoomFactor = application->surfaceCam->getFocalDistance() / 20.0f * application->dt / (1.0f / 60.0f); if (application->cameraZoomIn.isTriggered()) application->surfaceCam->zoom(zoomFactor * application->cameraZoomIn.getCurrentValue()); if (application->cameraZoomOut.isTriggered()) application->surfaceCam->zoom(-zoomFactor * application->cameraZoomOut.getCurrentValue()); application->surfaceCam->update(application->dt); application->surfaceCam->setTargetAzimuth(application->surfaceCam->getTargetAzimuth() + glm::radians(2.0f) * application->dt); application->surfaceCam->update(application->dt); } void MainMenuState::exit() { // Hide UI application->menuSelectorLabel->setVisible(false); // Clear scene application->defaultLayer->removeObject(&application->nestModelInstance); application->backgroundLayer->removeObject(&application->bgCamera); application->backgroundLayer->removeObject(&application->bgBatch); } void MainMenuState::mouseButtonPressed(int button, int x, int y) { } void MainMenuState::mouseButtonReleased(int button, int x, int y) { }