README screenshots.
							
								
								
									
										4
									
								
								.github/workflows/all-builds.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						@ -220,7 +220,7 @@ jobs:
 | 
				
			|||||||
        if: matrix.os == 'windows-latest'
 | 
					        if: matrix.os == 'windows-latest'
 | 
				
			||||||
        uses: actions/upload-artifact@v4
 | 
					        uses: actions/upload-artifact@v4
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          name: qtk-${{ matrix.os }}
 | 
					          name: libqtk-${{ matrix.os }}
 | 
				
			||||||
          path: |
 | 
					          path: |
 | 
				
			||||||
            build/packages/*.exe
 | 
					            build/packages/*.exe
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -235,7 +235,7 @@ jobs:
 | 
				
			|||||||
        if: matrix.os == 'macos-latest'
 | 
					        if: matrix.os == 'macos-latest'
 | 
				
			||||||
        uses: actions/upload-artifact@v4
 | 
					        uses: actions/upload-artifact@v4
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          name: qtk-${{ matrix.os }}
 | 
					          name: libqtk-${{ matrix.os }}
 | 
				
			||||||
          path: |
 | 
					          path: |
 | 
				
			||||||
            build/packages/*.tar.gz
 | 
					            build/packages/*.tar.gz
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										57
									
								
								README.md
									
									
									
									
									
								
							
							
						
						@ -9,38 +9,53 @@ that allow rendering geometry in 2D and 3D using custom GLSL shader programs.
 | 
				
			|||||||
The Qtk desktop application provides a model loader using [Assimp](https://assimp.org/) within a Qt widget application.
 | 
					The Qtk desktop application provides a model loader using [Assimp](https://assimp.org/) within a Qt widget application.
 | 
				
			||||||
You can fly around the scene using WASD while holding down the right mouse button.
 | 
					You can fly around the scene using WASD while holding down the right mouse button.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Object names can be double-clicked in the tree view panel for quick camera navigation.
 | 
				
			||||||
 | 
					Properties of the object, like shader code and translation / scale, can be viewed and modified in the side panel.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All side panels and toolbars are dockable widgets that can be popped out
 | 
				
			||||||
 | 
					and reorganized as needed. Panels can also be stacked to create a docked widget with
 | 
				
			||||||
 | 
					tabs. The central widget that provides the camera view into the scene cannot be
 | 
				
			||||||
 | 
					detached from the main window in this way.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The small triangles floating near 3D models represent the light source being used for the shader.
 | 
				
			||||||
 | 
					These appear on models using phong, specular, and diffuse lighting techniques.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The default scene contains basic examples like texture mapping to make a crate from basic cube geometry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Examples of Ambient, Diffuse, and Specular GLSL shaders.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					| Ambient                                               | Diffuse                                               | Specular                                               |
 | 
				
			||||||
 | 
					|-------------------------------------------------------|-------------------------------------------------------|--------------------------------------------------------|
 | 
				
			||||||
 | 
					| <img src="resources/screenshots/screen-ambient.png"/> | <img src="resources/screenshots/screen-diffuse.png"/> | <img src="resources/screenshots/screen-specular.png"/> |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					And more advanced techniques like Phong lighting (ambient + diffuse + specular) and normal mapping.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					| Normal Mapping Disabled                              | Normal Mapping Enabled                                 | 
 | 
				
			||||||
 | 
					|------------------------------------------------------|--------------------------------------------------------|
 | 
				
			||||||
 | 
					| <img src="resources/screenshots/spartan-phong.png"/> | <img src="resources/screenshots/spartan-normals.png"/> |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					See the `View` toolbar menu to enable debug console widgets for open scenes or reopen previously closed panels.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Key features that are planned:
 | 
					Key features that are planned:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- [x] Runtime loading of `.obj` or similar 3D models.
 | 
					- [x] Runtime loading of `.obj` or similar 3D models.
 | 
				
			||||||
- [x] Drag-and-drop interaction for adding objects to the scene.
 | 
					- [x] Drag-and-drop interaction for adding objects to the scene.
 | 
				
			||||||
 | 
					- [x] Shader / object properties panel to modify related settings.
 | 
				
			||||||
- [ ] Runtime reloading of modified GLSL shaders attached to objects within scenes.
 | 
					- [ ] Runtime reloading of modified GLSL shaders attached to objects within scenes.
 | 
				
			||||||
- [ ] Multiple views of a scene at one time.
 | 
					- [ ] Multiple views of a scene at one time.
 | 
				
			||||||
- [ ] Camera control modes such as panning, orbiting, or following objects.
 | 
					- [ ] Camera control modes such as panning, orbiting, or following objects.
 | 
				
			||||||
- [ ] Save / load for scene data. The current inheritance model is temporary.
 | 
					- [ ] Save / load for scene data. The current inheritance model is temporary.
 | 
				
			||||||
- [ ] Basic text editor for quickly modifying shaders attached to objects.
 | 
					- [ ] Basic text editor for quickly modifying shaders attached to objects.
 | 
				
			||||||
- [ ] Shader / object properties panel to modify related settings.
 | 
					 | 
				
			||||||
- [ ] Reduce size of application resources and git references.
 | 
					- [ ] Reduce size of application resources and git references.
 | 
				
			||||||
 | 
					
 | 
				
			||||||

 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Spartan with no normals -
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||

 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Spartan with normals -
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||

 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Object names can be double-clicked in the tree view panel for quick camera
 | 
					 | 
				
			||||||
navigation. All side panels and toolbars are dockable widgets that can be popped out
 | 
					 | 
				
			||||||
and reorganized as needed. Panels can also be stacked to create a docked widget with
 | 
					 | 
				
			||||||
tabs. The central widget that provides the camera view into the scene cannot be
 | 
					 | 
				
			||||||
detached from the main window in this way. See the `View` menu to enable debug
 | 
					 | 
				
			||||||
console widgets for open scenes or reopen previously closed panels.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The small triangles floating near 3D models represent the light source being used for the shader.
 | 
					 | 
				
			||||||
These appear on models using phong, specular, and diffuse lighting techniques.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
For examples of using the Qtk API, see the `example-app` project in the root of
 | 
					For examples of using the Qtk API, see the `example-app` project in the root of
 | 
				
			||||||
this repository.
 | 
					this repository.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -46,8 +46,8 @@
 | 
				
			|||||||
        <file alias="solid-phong.vert">shaders/vertex/solid-phong.vert</file>
 | 
					        <file alias="solid-phong.vert">shaders/vertex/solid-phong.vert</file>
 | 
				
			||||||
        <file alias="model-basic.frag">shaders/fragment/model-basic.frag</file>
 | 
					        <file alias="model-basic.frag">shaders/fragment/model-basic.frag</file>
 | 
				
			||||||
        <file alias="model-basic.vert">shaders/vertex/model-basic.vert</file>
 | 
					        <file alias="model-basic.vert">shaders/vertex/model-basic.vert</file>
 | 
				
			||||||
        <file alias="model-specular.frag">shaders/fragment/model-specular.frag</file>
 | 
					        <file alias="model-phong.frag">shaders/fragment/model-phong.frag</file>
 | 
				
			||||||
        <file alias="model-specular.vert">shaders/vertex/model-specular.vert</file>
 | 
					        <file alias="model-phong.vert">shaders/vertex/model-phong.vert</file>
 | 
				
			||||||
        <file alias="model-normals.frag">shaders/fragment/model-normals.frag</file>
 | 
					        <file alias="model-normals.frag">shaders/fragment/model-normals.frag</file>
 | 
				
			||||||
        <file alias="model-normals.vert">shaders/vertex/model-normals.vert</file>
 | 
					        <file alias="model-normals.vert">shaders/vertex/model-normals.vert</file>
 | 
				
			||||||
        <file alias="skybox.frag">skybox/skybox.frag</file>
 | 
					        <file alias="skybox.frag">skybox/skybox.frag</file>
 | 
				
			||||||
 | 
				
			|||||||
| 
		 Before Width: | Height: | Size: 316 KiB  | 
| 
		 Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB  | 
| 
		 Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 89 KiB  | 
| 
		 Before Width: | Height: | Size: 263 KiB After Width: | Height: | Size: 263 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/screenshots/screen-1.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 428 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/screenshots/screen-ambient.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 205 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/screenshots/screen-diffuse.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 188 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/screenshots/screen-phong.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 264 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/screenshots/screen-specular.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 176 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/screenshots/screen-texture.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 288 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/screenshots/screen.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 437 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/screenshots/spartan-normals.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 359 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/screenshots/spartan-phong.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 349 KiB  | 
| 
		 Before Width: | Height: | Size: 660 KiB  | 
| 
		 Before Width: | Height: | Size: 646 KiB  | 
@ -33,12 +33,14 @@ MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Add GUI 'view' toolbar option to show debug console.
 | 
					    // Add GUI 'view' toolbar option to show debug console.
 | 
				
			||||||
    ui_->menuView->addAction(qtkWidget->getActionToggleConsole());
 | 
					    ui_->menuView->addAction(qtkWidget->getActionToggleConsole());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Refresh GUI widgets when scene or objects are updated.
 | 
					    // Refresh GUI widgets when scene or objects are updated.
 | 
				
			||||||
    connect(qtkWidget->getScene(),
 | 
					    connect(qtkWidget->getScene(),
 | 
				
			||||||
            &Qtk::Scene::sceneUpdated,
 | 
					            &Qtk::Scene::sceneUpdated,
 | 
				
			||||||
            this,
 | 
					            this,
 | 
				
			||||||
            &MainWindow::refreshScene);
 | 
					            &MainWindow::refreshScene);
 | 
				
			||||||
    connect(qtkWidget, &Qtk::QtkWidget::objectFocusChanged,
 | 
					    connect(qtkWidget,
 | 
				
			||||||
 | 
					            &Qtk::QtkWidget::objectFocusChanged,
 | 
				
			||||||
            ui_->qtk__ToolBox,
 | 
					            ui_->qtk__ToolBox,
 | 
				
			||||||
            &Qtk::ToolBox::updateFocus);
 | 
					            &Qtk::ToolBox::updateFocus);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -71,8 +73,8 @@ MainWindow::~MainWindow()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
MainWindow * MainWindow::getMainWindow()
 | 
					MainWindow * MainWindow::getMainWindow()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  static MainWindow window;
 | 
					  static auto * window = new MainWindow;
 | 
				
			||||||
  return &window;
 | 
					  return window;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Qtk::QtkWidget * MainWindow::getQtkWidget(int64_t index)
 | 
					Qtk::QtkWidget * MainWindow::getQtkWidget(int64_t index)
 | 
				
			||||||
 | 
				
			|||||||
@ -48,10 +48,9 @@ namespace Ui
 | 
				
			|||||||
 * Any application using a QtkWidget can set a custom scene in their main
 | 
					 * Any application using a QtkWidget can set a custom scene in their main
 | 
				
			||||||
 * function. See the MainWindow::MainWindow constructor as an example.
 | 
					 * function. See the MainWindow::MainWindow constructor as an example.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class EmptyScene : public Qtk::Scene {
 | 
					class EmptyScene : public Qtk::Scene
 | 
				
			||||||
  void init() override {
 | 
					{
 | 
				
			||||||
    setSceneName("Empty Scene");
 | 
					    void init() override { setSceneName("Empty Scene"); }
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 | 
				
			|||||||
@ -260,8 +260,8 @@ void QtkScene::init()
 | 
				
			|||||||
  /* Test spartan Model with phong lighting, specular and normal mapping. */
 | 
					  /* Test spartan Model with phong lighting, specular and normal mapping. */
 | 
				
			||||||
  model = addObject(new Qtk::Model("spartanTest",
 | 
					  model = addObject(new Qtk::Model("spartanTest",
 | 
				
			||||||
                                   ":/models/models/spartan/spartan.obj",
 | 
					                                   ":/models/models/spartan/spartan.obj",
 | 
				
			||||||
                                   ":/shaders/model-normals.vert",
 | 
					                                   ":/shaders/model-phong.vert",
 | 
				
			||||||
                                   ":/shaders/model-normals.frag"));
 | 
					                                   ":/shaders/model-phong.frag"));
 | 
				
			||||||
  model->getTransform().setTranslation(0.0f, -1.0f, 10.0f);
 | 
					  model->getTransform().setTranslation(0.0f, -1.0f, 10.0f);
 | 
				
			||||||
  model->getTransform().scale(2.0f);
 | 
					  model->getTransform().scale(2.0f);
 | 
				
			||||||
  model->setUniform("uMaterial.ambient", QVector3D(1.0f, 1.0f, 1.0f));
 | 
					  model->setUniform("uMaterial.ambient", QVector3D(1.0f, 1.0f, 1.0f));
 | 
				
			||||||
 | 
				
			|||||||
@ -83,7 +83,11 @@ void QtkWidget::initializeGL()
 | 
				
			|||||||
  // Connect the frameSwapped signal to call the update() function
 | 
					  // Connect the frameSwapped signal to call the update() function
 | 
				
			||||||
  connect(this, SIGNAL(frameSwapped()), this, SLOT(update()));
 | 
					  connect(this, SIGNAL(frameSwapped()), this, SLOT(update()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  toggleConsole();
 | 
					  // Add the debug console widget to the window and set its hidden state.
 | 
				
			||||||
 | 
					  MainWindow::getMainWindow()->addDockWidget(
 | 
				
			||||||
 | 
					      Qt::DockWidgetArea::BottomDockWidgetArea, mConsole);
 | 
				
			||||||
 | 
					  mConsole->setHidden(!mConsoleActive);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Initialize OpenGL debug context
 | 
					  // Initialize OpenGL debug context
 | 
				
			||||||
  mDebugLogger = new QOpenGLDebugLogger(this);
 | 
					  mDebugLogger = new QOpenGLDebugLogger(this);
 | 
				
			||||||
  if (mDebugLogger->initialize()) {
 | 
					  if (mDebugLogger->initialize()) {
 | 
				
			||||||
@ -144,15 +148,8 @@ void QtkWidget::setScene(Scene * scene)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void QtkWidget::toggleConsole()
 | 
					void QtkWidget::toggleConsole()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  if (mConsoleActive) {
 | 
					  mConsole->setHidden(mConsoleActive);
 | 
				
			||||||
    mConsole->setHidden(true);
 | 
					  mConsoleActive = !mConsoleActive;
 | 
				
			||||||
    mConsoleActive = false;
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    MainWindow::getMainWindow()->addDockWidget(
 | 
					 | 
				
			||||||
        Qt::DockWidgetArea::BottomDockWidgetArea, mConsole);
 | 
					 | 
				
			||||||
    mConsole->setHidden(false);
 | 
					 | 
				
			||||||
    mConsoleActive = true;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*******************************************************************************
 | 
					/*******************************************************************************
 | 
				
			||||||
 | 
				
			|||||||
@ -210,7 +210,7 @@ namespace Qtk
 | 
				
			|||||||
      QOpenGLDebugLogger * mDebugLogger;
 | 
					      QOpenGLDebugLogger * mDebugLogger;
 | 
				
			||||||
      Qtk::Scene * mScene;
 | 
					      Qtk::Scene * mScene;
 | 
				
			||||||
      Qtk::DebugConsole * mConsole;
 | 
					      Qtk::DebugConsole * mConsole;
 | 
				
			||||||
      bool mConsoleActive = false;
 | 
					      bool mConsoleActive = true;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
}  // namespace Qtk
 | 
					}  // namespace Qtk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -41,36 +41,33 @@ void Qtk::TreeView::updateView(const Qtk::Scene * scene)
 | 
				
			|||||||
  mSceneName = scene->getSceneName();
 | 
					  mSceneName = scene->getSceneName();
 | 
				
			||||||
  auto objects = scene->getObjects();
 | 
					  auto objects = scene->getObjects();
 | 
				
			||||||
  for (const auto & object : objects) {
 | 
					  for (const auto & object : objects) {
 | 
				
			||||||
    auto item =
 | 
					    QStringList list(QStringList(QString(object->getName().c_str())));
 | 
				
			||||||
        new QTreeWidgetItem(QStringList(QString(object->getName().c_str())));
 | 
					    ui->treeWidget->insertTopLevelItem(0, new QTreeWidgetItem(list));
 | 
				
			||||||
    ui->treeWidget->insertTopLevelItem(0, item);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Qtk::TreeView::itemFocus(QTreeWidgetItem * item, int column)
 | 
					void Qtk::TreeView::itemFocus(QTreeWidgetItem * item, int column)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  QString name = item->text(column);
 | 
					  const QString & name = item->text(column);
 | 
				
			||||||
  auto scene = MainWindow::getMainWindow()->getQtkWidget()->getScene();
 | 
					  auto scene = MainWindow::getMainWindow()->getQtkWidget()->getScene();
 | 
				
			||||||
  auto & transform = Qtk::Scene::getCamera().getTransform();
 | 
					 | 
				
			||||||
  auto object = scene->getObject(name);
 | 
					  auto object = scene->getObject(name);
 | 
				
			||||||
  Transform3D * objectTransform;
 | 
					 | 
				
			||||||
  // If the object is a mesh or model, focus the camera on it.
 | 
					  // If the object is a mesh or model, focus the camera on it.
 | 
				
			||||||
  if (object == Q_NULLPTR) {
 | 
					  if (object == Q_NULLPTR) {
 | 
				
			||||||
    qDebug() << "Attempt to get non-existing object with name '" << name
 | 
					    qDebug() << "Attempt to get non-existing object with name '" << name
 | 
				
			||||||
             << "'\n";
 | 
					             << "'\n";
 | 
				
			||||||
  } else if (object->getType() == Object::QTK_MESH) {
 | 
					    return;
 | 
				
			||||||
    objectTransform = &dynamic_cast<MeshRenderer *>(object)->getTransform();
 | 
					 | 
				
			||||||
  } else if (object->getType() == Object::QTK_MODEL) {
 | 
					 | 
				
			||||||
    objectTransform = &dynamic_cast<Model *>(object)->getTransform();
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  auto focusScale = objectTransform->getScale();
 | 
					  const Transform3D & objectTransform = object->getTransform();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  auto & camera_transform = Qtk::Scene::getCamera().getTransform();
 | 
				
			||||||
 | 
					  auto focusScale = objectTransform.getScale();
 | 
				
			||||||
  float width = focusScale.x() / 2.0f;
 | 
					  float width = focusScale.x() / 2.0f;
 | 
				
			||||||
  float height = focusScale.y() / 2.0f;
 | 
					  float height = focusScale.y() / 2.0f;
 | 
				
			||||||
  QVector3D pos = objectTransform->getTranslation();
 | 
					  QVector3D pos = objectTransform.getTranslation();
 | 
				
			||||||
  // pos.setX(pos.x() + width);
 | 
					  // pos.setX(pos.x() + width);
 | 
				
			||||||
  pos.setY(pos.y() + height);
 | 
					  pos.setY(pos.y() + height);
 | 
				
			||||||
  transform.setTranslation(pos);
 | 
					  camera_transform.setTranslation(pos);
 | 
				
			||||||
  transform.translate(0.0f, 0.0f, 3.0f);
 | 
					  camera_transform.translate(0.0f, 0.0f, 3.0f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Emit signal from qtk widget for new object focus. Triggers GUI updates.
 | 
					  // Emit signal from qtk widget for new object focus. Triggers GUI updates.
 | 
				
			||||||
  emit MainWindow::getMainWindow() -> getQtkWidget()->objectFocusChanged(name);
 | 
					  emit MainWindow::getMainWindow() -> getQtkWidget()->objectFocusChanged(name);
 | 
				
			||||||
 | 
				
			|||||||
@ -216,7 +216,7 @@ namespace Qtk
 | 
				
			|||||||
      /**
 | 
					      /**
 | 
				
			||||||
       * @return Transform3D attached to this MeshRenderer.
 | 
					       * @return Transform3D attached to this MeshRenderer.
 | 
				
			||||||
       */
 | 
					       */
 | 
				
			||||||
      inline Transform3D & getTransform() { return mTransform; }
 | 
					      inline Transform3D & getTransform() override { return mTransform; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      [[nodiscard]] inline std::string getVertexShader() const override
 | 
					      [[nodiscard]] inline std::string getVertexShader() const override
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
 | 
				
			|||||||
@ -129,7 +129,7 @@ namespace Qtk
 | 
				
			|||||||
      /**
 | 
					      /**
 | 
				
			||||||
       * @return Transform3D attached to this Model.
 | 
					       * @return Transform3D attached to this Model.
 | 
				
			||||||
       */
 | 
					       */
 | 
				
			||||||
      inline Transform3D & getTransform() { return mTransform; }
 | 
					      inline Transform3D & getTransform() override { return mTransform; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      [[nodiscard]] inline std::string getVertexShader() const override
 | 
					      [[nodiscard]] inline std::string getVertexShader() const override
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
 | 
				
			|||||||
@ -111,6 +111,11 @@ namespace Qtk
 | 
				
			|||||||
        return mTransform;
 | 
					        return mTransform;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      [[nodiscard]] inline virtual Transform3D & getTransform()
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        return mTransform;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      [[nodiscard]] inline virtual std::string getVertexShader() const
 | 
					      [[nodiscard]] inline virtual std::string getVertexShader() const
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        return "Base Object has no vertex shader.";
 | 
					        return "Base Object has no vertex shader.";
 | 
				
			||||||
 | 
				
			|||||||
@ -118,11 +118,9 @@ void Scene::setSkybox(Skybox * skybox)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void Scene::initSceneObjectName(Object * object)
 | 
					void Scene::initSceneObjectName(Object * object)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  if (!mObjectCount.count(object->getName())) {
 | 
					  mObjectCount[object->getName()] = mObjectCount.count(object->getName()) + 1;
 | 
				
			||||||
    mObjectCount[object->getName()] = 1;
 | 
					
 | 
				
			||||||
  } else {
 | 
					  // If the object exists make it's name unique.
 | 
				
			||||||
    mObjectCount[object->getName()]++;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  auto count = mObjectCount[object->getName()];
 | 
					  auto count = mObjectCount[object->getName()];
 | 
				
			||||||
  if (count > 1) {
 | 
					  if (count > 1) {
 | 
				
			||||||
    object->setName(object->getName() + " (" + std::to_string(count) + ")");
 | 
					    object->setName(object->getName() + " (" + std::to_string(count) + ")");
 | 
				
			||||||
 | 
				
			|||||||