42 this->initializeOpenGLFunctions(); |
42 this->initializeOpenGLFunctions(); |
43 if (glGetError() != GL_NO_ERROR) |
43 if (glGetError() != GL_NO_ERROR) |
44 { |
44 { |
45 abort(); |
45 abort(); |
46 } |
46 } |
47 glEnableClientState(GL_NORMAL_ARRAY); |
|
48 glEnableClientState(GL_VERTEX_ARRAY); |
|
49 this->compiler->initialize(); |
47 this->compiler->initialize(); |
50 this->compiler->build(this->model, this->documents); |
48 this->compiler->build(this->model, this->documents); |
51 this->initializeLighting(); |
49 this->initializeLighting(); |
52 this->initialized = true; |
50 this->initialized = true; |
53 this->rotation = QQuaternion::fromAxisAndAngle({1, 0, 0}, 30); |
51 this->rotation = QQuaternion::fromAxisAndAngle({1, 0, 0}, 30); |
54 this->rotation *= QQuaternion::fromAxisAndAngle({0, 1, 0}, 330); |
52 this->rotation *= QQuaternion::fromAxisAndAngle({0, 1, 0}, 330); |
55 glLineWidth(2.0); |
53 glLineWidth(2.0); |
|
54 this->update(); |
56 } |
55 } |
57 |
|
58 /* |
|
59 * Pads a 3×3 matrix into a 4×4 one by adding cells from the identity matrix. |
|
60 */ |
|
61 static QMatrix4x4 padMatrix(const QMatrix3x3& stub) |
|
62 { |
|
63 return { |
|
64 stub(0, 0), stub(0, 1), stub(0, 2), 0, |
|
65 stub(1, 0), stub(1, 1), stub(1, 2), 0, |
|
66 stub(2, 0), stub(2, 1), stub(2, 2), 0, |
|
67 0, 0, 0, 1 |
|
68 }; |
|
69 } |
|
70 |
|
71 |
56 |
72 void PartRenderer::initializeLighting() |
57 void PartRenderer::initializeLighting() |
73 { |
58 { |
74 GLfloat materialShininess[] = {5.0}; |
59 GLfloat materialShininess[] = {5.0}; |
75 GLfloat lightPosition[] = {1.0, 1.0, 1.0, 0.0}; |
60 GLfloat lightPosition[] = {1.0, 1.0, 1.0, 0.0}; |
126 |
111 |
127 void PartRenderer::renderScene() |
112 void PartRenderer::renderScene() |
128 { |
113 { |
129 glClearColor(0.8f, 0.8f, 0.8f, 1.0f); |
114 glClearColor(0.8f, 0.8f, 0.8f, 1.0f); |
130 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
115 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
131 glMatrixMode(GL_MODELVIEW); |
|
132 glEnable(GL_DEPTH_TEST); |
116 glEnable(GL_DEPTH_TEST); |
133 glEnable(GL_LIGHTING); |
117 glEnable(GL_LIGHTING); |
134 glLoadIdentity(); |
|
135 //glTranslated(0.0, 0.0, -4.5 * this->compiler->modelDistance()); |
|
136 //glTranslated(0.0, 0.0, -4.5); |
|
137 //glMultMatrixf(padMatrix(this->rotation.toRotationMatrix()).constData()); |
|
138 //xyz(glTranslatef, -this->compiler->modelCenter()); |
|
139 auto rotationMatrix = padMatrix(this->rotation.toRotationMatrix()); |
|
140 rotationMatrix(2, 3) = 0; |
|
141 glEnable(GL_POLYGON_OFFSET_FILL); |
118 glEnable(GL_POLYGON_OFFSET_FILL); |
142 glPolygonOffset(1.0f, 1.0f); |
119 glPolygonOffset(1.0f, 1.0f); |
143 switch (this->renderStyle) |
120 switch (this->renderStyle) |
144 { |
121 { |
145 case gl::RenderStyle::Normal: |
122 case gl::RenderStyle::Normal: |
148 break; |
125 break; |
149 case gl::RenderStyle::Wireframe: |
126 case gl::RenderStyle::Wireframe: |
150 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); |
127 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); |
151 break; |
128 break; |
152 } |
129 } |
153 this->compiler->setUniform("CameraTransformation", gl::toQMatrix(this->projectionMatrix * this->viewMatrix)); |
130 this->compiler->setUniformMatrix("CameraTransformation", this->projectionMatrix * this->viewMatrix); |
154 // Lines need to be rendered last so that anti-aliasing does not interfere with polygon rendering. |
131 // Lines need to be rendered last so that anti-aliasing does not interfere with polygon rendering. |
155 renderVao(gl::ArrayClass::Triangles); |
132 renderVao(gl::ArrayClass::Triangles); |
156 renderVao(gl::ArrayClass::Quads); |
133 renderVao(gl::ArrayClass::Quads); |
157 renderVao(gl::ArrayClass::Lines); |
134 renderVao(gl::ArrayClass::Lines); |
158 glDisable(GL_POLYGON_OFFSET_FILL); |
135 glDisable(GL_POLYGON_OFFSET_FILL); |
189 { |
166 { |
190 const bool left = event->buttons() & Qt::LeftButton; |
167 const bool left = event->buttons() & Qt::LeftButton; |
191 const QPointF move = pointToPointF(event->pos()) - this->lastMousePosition; |
168 const QPointF move = pointToPointF(event->pos()) - this->lastMousePosition; |
192 if (left and not move.isNull()) |
169 if (left and not move.isNull()) |
193 { |
170 { |
|
171 // FIXME: find a more elegant way to do this |
194 const QQuaternion versor = QQuaternion::fromAxisAndAngle( |
172 const QQuaternion versor = QQuaternion::fromAxisAndAngle( |
195 QVector3D{static_cast<float>(move.y()), static_cast<float>(move.x()), 0.0f}, |
173 QVector3D{static_cast<float>(-move.y()), static_cast<float>(move.x()), 0.0f}, |
196 0.6f * static_cast<float>(std::hypot(move.x(), move.y())) |
174 0.6f * static_cast<float>(std::hypot(move.x(), move.y())) |
197 ); |
175 ); |
198 this->rotation = versor * this->rotation; |
176 this->rotation = versor * this->rotation; |
199 QVector3D cameraPosition = this->rotation.rotatedVector({0, 0, 4.5}); |
177 QVector3D cameraPosition = this->rotation.rotatedVector({0, 0, static_cast<float>(2 + 2 * this->compiler->modelDistance())}); |
200 glm::vec3 cameraPosition_glm = {cameraPosition.x(), cameraPosition.y(), cameraPosition.z()}; |
178 glm::vec3 cameraPosition_glm = {cameraPosition.x(), cameraPosition.y(), cameraPosition.z()}; |
201 this->viewMatrix = glm::lookAt(cameraPosition_glm, {0, 0, 0}, {0, -1, 0}); |
179 this->viewMatrix = glm::lookAt(cameraPosition_glm, {0, 0, 0}, {0, -1, 0}); |
202 this->update(); |
180 this->update(); |
203 } |
181 } |
204 this->lastMousePosition = pointToPointF(event->pos()); |
182 this->lastMousePosition = pointToPointF(event->pos()); |
205 } |
|
206 |
|
207 void PartRenderer::setCompiler(gl::Compiler* compiler) |
|
208 { |
|
209 this->compiler = compiler; |
|
210 } |
183 } |
211 |
184 |
212 void PartRenderer::setRenderStyle(const gl::RenderStyle newStyle) |
185 void PartRenderer::setRenderStyle(const gl::RenderStyle newStyle) |
213 { |
186 { |
214 this->renderStyle = newStyle; |
187 this->renderStyle = newStyle; |