diff --git a/src/app/qtkscene.cpp b/src/app/qtkscene.cpp index 527c226..2fe1d71 100644 --- a/src/app/qtkscene.cpp +++ b/src/app/qtkscene.cpp @@ -426,6 +426,7 @@ void QtkScene::draw() // WARNING: We must call the base class draw() function first. // + This will handle rendering core scene components like the Skybox. Scene::draw(); + const QVector3D cameraPosition = getCamera().getTransform().getTranslation(); mTestPhong->bindShaders(); mTestPhong->setUniform("uModelInverseTransposed", @@ -433,14 +434,12 @@ void QtkScene::draw() mTestPhong->setUniform( "uLightPosition", MeshRenderer::getInstance("phongLight")->getTransform().getTranslation()); - mTestPhong->setUniform("uCameraPosition", - QtkScene::getCamera().getTransform().getTranslation()); + mTestPhong->setUniform("uCameraPosition", cameraPosition); mTestPhong->releaseShaders(); mTestPhong->draw(); mTestAmbient->bindShaders(); - mTestAmbient->setUniform( - "uCameraPosition", QtkScene::getCamera().getTransform().getTranslation()); + mTestAmbient->setUniform("uCameraPosition", cameraPosition); mTestAmbient->releaseShaders(); mTestAmbient->draw(); @@ -452,8 +451,7 @@ void QtkScene::draw() MeshRenderer::getInstance("diffuseLight") ->getTransform() .getTranslation()); - mTestDiffuse->setUniform( - "uCameraPosition", QtkScene::getCamera().getTransform().getTranslation()); + mTestDiffuse->setUniform("uCameraPosition", cameraPosition); mTestDiffuse->releaseShaders(); mTestDiffuse->draw(); @@ -465,67 +463,82 @@ void QtkScene::draw() MeshRenderer::getInstance("specularLight") ->getTransform() .getTranslation()); - mTestSpecular->setUniform( - "uCameraPosition", QtkScene::getCamera().getTransform().getTranslation()); + mTestSpecular->setUniform("uCameraPosition", cameraPosition); mTestSpecular->releaseShaders(); mTestSpecular->draw(); } void QtkScene::update() { - auto mySpartan = Model::getInstance("My spartan"); - mySpartan->getTransform().rotate(0.75f, 0.0f, 1.0f, 0.0f); + auto getModel = Model::getInstance; + const QVector3D cameraPosition = getCamera().getTransform().getTranslation(); - auto myCube = MeshRenderer::getInstance("My cube"); - myCube->getTransform().rotate(-0.75f, 0.0f, 1.0f, 0.0f); + // Models may have failed to load, so we should check before accessing. + if (auto mySpartan = getModel("My spartan"); mySpartan) { + mySpartan->getTransform().rotate(0.75f, 0.0f, 1.0f, 0.0f); + } - auto position = MeshRenderer::getInstance("alienTestLight") - ->getTransform() - .getTranslation(); - auto alien = Model::getInstance("alienTest"); - alien->setUniform("uLight.position", position); - alien->setUniform("uCameraPosition", - QtkScene::getCamera().getTransform().getTranslation()); - auto posMatrix = alien->getTransform().toMatrix(); - alien->setUniform("uMVP.normalMatrix", posMatrix.normalMatrix()); - alien->setUniform("uMVP.model", posMatrix); - alien->setUniform("uMVP.view", QtkScene::getCamera().toMatrix()); - alien->setUniform("uMVP.projection", QtkScene::getProjectionMatrix()); - alien->getTransform().rotate(0.75f, 0.0f, 1.0f, 0.0f); + if (auto myCube = getModel("My cube"); myCube) { + myCube->getTransform().rotate(-0.75f, 0.0f, 1.0f, 0.0f); + } - position = MeshRenderer::getInstance("spartanTestLight") - ->getTransform() - .getTranslation(); - auto spartan = Model::getInstance("spartanTest"); - spartan->setUniform("uLight.position", position); - spartan->setUniform("uCameraPosition", - QtkScene::getCamera().getTransform().getTranslation()); - posMatrix = spartan->getTransform().toMatrix(); - spartan->setUniform("uMVP.normalMatrix", posMatrix.normalMatrix()); - spartan->setUniform("uMVP.model", posMatrix); - spartan->setUniform("uMVP.view", QtkScene::getCamera().toMatrix()); - spartan->setUniform("uMVP.projection", QtkScene::getProjectionMatrix()); - spartan->getTransform().rotate(0.75f, 0.0f, 1.0f, 0.0f); + // Helper lambda to set the light position used by GLSL shaders on the model. + // TODO: This could be a helper function on the Model class. + auto setLightPosition = [](const std::string & lightName, Model * model) { + if (auto light = Model::getInstance(lightName.c_str()); light) { + QVector3D position = light->getTransform().getTranslation(); + model->setUniform("uLight.position", position); + } else { + qDebug() << "[QtkScene] Failed to set light position: " + << lightName.c_str(); + } + }; - auto phong = MeshRenderer::getInstance("testPhong"); - phong->getTransform().rotate(0.75f, 1.0f, 0.5f, 0.0f); - phong->bindShaders(); - position = - MeshRenderer::getInstance("testLight")->getTransform().getTranslation(); - phong->setUniform("uLight.position", position); - phong->setUniform("uCameraPosition", - QtkScene::getCamera().getTransform().getTranslation()); - posMatrix = phong->getTransform().toMatrix(); - phong->setUniform("uMVP.normalMatrix", posMatrix.normalMatrix()); - phong->setUniform("uMVP.model", posMatrix); - phong->setUniform("uMVP.view", QtkScene::getCamera().toMatrix()); - phong->setUniform("uMVP.projection", QtkScene::getProjectionMatrix()); - phong->releaseShaders(); + QMatrix4x4 posMatrix; + if (auto alien = getModel("alienTest"); alien) { + setLightPosition("alienTestLight", alien); + + alien->setUniform("uCameraPosition", cameraPosition); + posMatrix = alien->getTransform().toMatrix(); + alien->setUniform("uMVP.normalMatrix", posMatrix.normalMatrix()); + alien->setUniform("uMVP.model", posMatrix); + alien->setUniform("uMVP.view", QtkScene::getCamera().toMatrix()); + alien->setUniform("uMVP.projection", QtkScene::getProjectionMatrix()); + alien->getTransform().rotate(0.75f, 0.0f, 1.0f, 0.0f); + } + + if (auto spartan = getModel("spartanTest"); spartan) { + setLightPosition("spartanTestLight", spartan); + + spartan->setUniform("uCameraPosition", cameraPosition); + posMatrix = spartan->getTransform().toMatrix(); + spartan->setUniform("uMVP.normalMatrix", posMatrix.normalMatrix()); + spartan->setUniform("uMVP.model", posMatrix); + spartan->setUniform("uMVP.view", QtkScene::getCamera().toMatrix()); + spartan->setUniform("uMVP.projection", QtkScene::getProjectionMatrix()); + spartan->getTransform().rotate(0.75f, 0.0f, 1.0f, 0.0f); + } + + if (auto phong = getModel("testPhong"); phong) { + setLightPosition("testLight", phong); + + phong->getTransform().rotate(0.75f, 1.0f, 0.5f, 0.0f); + phong->bindShaders(); + phong->setUniform("uCameraPosition", cameraPosition); + posMatrix = phong->getTransform().toMatrix(); + phong->setUniform("uMVP.normalMatrix", posMatrix.normalMatrix()); + phong->setUniform("uMVP.model", posMatrix); + phong->setUniform("uMVP.view", QtkScene::getCamera().toMatrix()); + phong->setUniform("uMVP.projection", QtkScene::getProjectionMatrix()); + phong->releaseShaders(); + } + + // MeshRenderers are lower level opengl objects baked into the source code. + auto getMesh = MeshRenderer::getInstance; // Rotate lighting example cubes mTestPhong->getTransform().rotate(0.75f, 0.5f, 0.3f, 0.2f); - MeshRenderer::getInstance("noLight")->getTransform().rotate( - 0.75f, 0.5f, 0.3f, 0.2f); + getMesh("noLight")->getTransform().rotate(0.75f, 0.5f, 0.3f, 0.2f); mTestAmbient->getTransform().rotate(0.75f, 0.5f, 0.3f, 0.2f); mTestDiffuse->getTransform().rotate(0.75f, 0.5f, 0.3f, 0.2f); mTestSpecular->getTransform().rotate(0.75f, 0.5f, 0.3f, 0.2f); @@ -533,46 +546,27 @@ void QtkScene::update() // Examples of various translations and rotations // Rotate in multiple directions simultaneously - MeshRenderer::getInstance("rgbNormalsCube") - ->getTransform() - .rotate(0.75f, 0.2f, 0.4f, 0.6f); + getMesh("rgbNormalsCube")->getTransform().rotate(0.75f, 0.2f, 0.4f, 0.6f); // Pitch forward and roll sideways - MeshRenderer::getInstance("leftTriangle") - ->getTransform() - .rotate(0.75f, 1.0f, 0.0f, 0.0f); - MeshRenderer::getInstance("rightTriangle") - ->getTransform() - .rotate(0.75f, 0.0f, 0.0f, 1.0f); + getMesh("leftTriangle")->getTransform().rotate(0.75f, 1.0f, 0.0f, 0.0f); + getMesh("rightTriangle")->getTransform().rotate(0.75f, 0.0f, 0.0f, 1.0f); // Move between two positions over time static float translateX = 0.025f; float limit = -9.0f; // Origin position.x - 2.0f - float posX = MeshRenderer::getInstance("topTriangle") - ->getTransform() - .getTranslation() - .x(); + float posX = getMesh("topTriangle")->getTransform().getTranslation().x(); if (posX < limit || posX > limit + 4.0f) { translateX = -translateX; } - MeshRenderer::getInstance("topTriangle") - ->getTransform() - .translate(translateX, 0.0f, 0.0f); - MeshRenderer::getInstance("bottomTriangle") - ->getTransform() - .translate(-translateX, 0.0f, 0.0f); + getMesh("topTriangle")->getTransform().translate(translateX, 0.0f, 0.0f); + getMesh("bottomTriangle")->getTransform().translate(-translateX, 0.0f, 0.0f); // And lets rotate the triangles in two directions at once - MeshRenderer::getInstance("topTriangle") - ->getTransform() - .rotate(0.75f, 0.2f, 0.0f, 0.4f); - MeshRenderer::getInstance("bottomTriangle") - ->getTransform() - .rotate(0.75f, 0.0f, 0.2f, 0.4f); + getMesh("topTriangle")->getTransform().rotate(0.75f, 0.2f, 0.0f, 0.4f); + getMesh("bottomTriangle")->getTransform().rotate(0.75f, 0.0f, 0.2f, 0.4f); // And make the bottom triangle green, instead of RGB // Rotate center cube in several directions simultaneously // + Not subject to gimbal lock since we are using quaternions :) - MeshRenderer::getInstance("centerCube") - ->getTransform() - .rotate(0.75f, 0.2f, 0.4f, 0.6f); + getMesh("centerCube")->getTransform().rotate(0.75f, 0.2f, 0.4f, 0.6f); }