|     44 	this->setMouseTracking(true); | 
    44 	this->setMouseTracking(true); | 
|     45 	connect(model, &Model::rowsInserted, [&]{ | 
    45 	connect(model, &Model::rowsInserted, [&]{ | 
|     46 		this->needBuild = true; | 
    46 		this->needBuild = true; | 
|     47 	}); | 
    47 	}); | 
|     48 	connect(model, &Model::rowsRemoved, [&]{ this->needBuild = true; }); | 
    48 	connect(model, &Model::rowsRemoved, [&]{ this->needBuild = true; }); | 
|         | 
    49 	const auto updateLayerMvpMatrix = [this]{ | 
|         | 
    50 		const glm::mat4 newMvpMatrix = this->projectionMatrix * this->viewMatrix * this->modelMatrix; | 
|         | 
    51 		for (RenderLayer* layer : this->activeRenderLayers) { | 
|         | 
    52 			layer->mvpMatrixChanged(newMvpMatrix); | 
|         | 
    53 		} | 
|         | 
    54 		for (RenderLayer* layer : this->inactiveRenderLayers) { | 
|         | 
    55 			layer->mvpMatrixChanged(newMvpMatrix); | 
|         | 
    56 		} | 
|         | 
    57 	}; | 
|         | 
    58 	connect(this, &PartRenderer::modelMatrixChanged, updateLayerMvpMatrix); | 
|         | 
    59 	connect(this, &PartRenderer::viewMatrixChanged, updateLayerMvpMatrix); | 
|         | 
    60 	connect(this, &PartRenderer::projectionMatrixChanged, updateLayerMvpMatrix); | 
|     49 } | 
    61 } | 
|     50  | 
    62  | 
|     51 PartRenderer::~PartRenderer() | 
    63 PartRenderer::~PartRenderer() | 
|     52 { | 
    64 { | 
|     53 } | 
    65 } | 
|     67 	if (glGetError() != GL_NO_ERROR) | 
    79 	if (glGetError() != GL_NO_ERROR) | 
|     68 	{ | 
    80 	{ | 
|     69 		abort(); | 
    81 		abort(); | 
|     70 	} | 
    82 	} | 
|     71 	gl::initializeModelShaders(&this->shaders); | 
    83 	gl::initializeModelShaders(&this->shaders); | 
|         | 
    84 	for (RenderLayer* layer : this->activeRenderLayers) { | 
|         | 
    85 		layer->initializeGL(); | 
|         | 
    86 	} | 
|         | 
    87 	for (RenderLayer* layer : this->inactiveRenderLayers) { | 
|         | 
    88 		layer->initializeGL(); | 
|         | 
    89 	} | 
|     72 	connect(this->model, &Model::dataChanged, this, &PartRenderer::build); | 
    90 	connect(this->model, &Model::dataChanged, this, &PartRenderer::build); | 
|     73 	this->initialized = true; | 
    91 	this->initialized = true; | 
|     74 	this->modelQuaternion = glm::angleAxis(glm::radians(30.0f), glm::vec3{-1, 0, 0}); | 
    92 	this->modelQuaternion = glm::angleAxis(glm::radians(30.0f), glm::vec3{-1, 0, 0}); | 
|     75 	this->modelQuaternion *= glm::angleAxis(glm::radians(225.0f), glm::vec3{-0, 1, 0}); | 
    93 	this->modelQuaternion *= glm::angleAxis(glm::radians(225.0f), glm::vec3{-0, 1, 0}); | 
|     76 	this->updateModelMatrix(); | 
    94 	this->updateModelMatrix(); | 
|    294 	this->zoom = std::clamp(this->zoom + move, MIN_ZOOM, MAX_ZOOM); | 
   315 	this->zoom = std::clamp(this->zoom + move, MIN_ZOOM, MAX_ZOOM); | 
|    295 	this->updateViewMatrix(); | 
   316 	this->updateViewMatrix(); | 
|    296 	this->update(); | 
   317 	this->update(); | 
|    297 } | 
   318 } | 
|    298  | 
   319  | 
|         | 
   320 void PartRenderer::addRenderLayer(RenderLayer* layer) | 
|         | 
   321 { | 
|         | 
   322 	this->activeRenderLayers.push_back(layer); | 
|         | 
   323 	this->update(); | 
|         | 
   324 } | 
|         | 
   325  | 
|         | 
   326 void PartRenderer::setLayerEnabled(RenderLayer* layer, bool enabled) | 
|         | 
   327 { | 
|         | 
   328 	auto& from = enabled ? this->inactiveRenderLayers : this->activeRenderLayers; | 
|         | 
   329 	auto& to = enabled ? this->activeRenderLayers : this->inactiveRenderLayers; | 
|         | 
   330 	auto it = std::find(from.begin(), from.end(), layer); | 
|         | 
   331 	if (it != from.end()) { | 
|         | 
   332 		from.erase(it); | 
|         | 
   333 		to.push_back(layer); | 
|         | 
   334 	} | 
|         | 
   335 } | 
|         | 
   336  | 
|    299 /** | 
   337 /** | 
|    300  * @brief Converts the specified on the screen into the 3D world. The point is unprojected twice into 3D and the | 
   338  * @brief Converts the specified on the screen into the 3D world. The point is unprojected twice into 3D and the | 
|    301  * intersection of the resulting line with the specified plane is returned. If the intersection point lies behind | 
   339  * intersection of the resulting line with the specified plane is returned. If the intersection point lies behind | 
|    302  * the camera, no value is returned. | 
   340  * the camera, no value is returned. | 
|    303  * @param point 2D window co-ordinates to convert. | 
   341  * @param point 2D window co-ordinates to convert. |