123 fColor = vColor; |
123 fColor = vColor; |
124 } |
124 } |
125 } |
125 } |
126 )"; |
126 )"; |
127 |
127 |
|
128 template<typename Fn> |
|
129 constexpr void pointsToRender(const PolygonElement& element, Fn func) |
|
130 { |
|
131 visitPolygon<void>( |
|
132 [&func](const LineSegment& edge) |
|
133 { |
|
134 func(edge.p1, glm::vec3{}); |
|
135 func(edge.p2, glm::vec3{}); |
|
136 }, |
|
137 [&func](const Triangle& tri) |
|
138 { |
|
139 func(tri.p1, normalVector({tri.p3, tri.p1, tri.p2})); |
|
140 func(tri.p2, normalVector({tri.p1, tri.p2, tri.p3})); |
|
141 func(tri.p3, normalVector({tri.p2, tri.p3, tri.p1})); |
|
142 }, |
|
143 [&func](const Quadrilateral& quad) |
|
144 { |
|
145 func(quad.p1, normalVector({quad.p4, quad.p1, quad.p2})); |
|
146 func(quad.p2, normalVector({quad.p1, quad.p2, quad.p3})); |
|
147 func(quad.p3, normalVector({quad.p2, quad.p3, quad.p4})); |
|
148 func(quad.p4, normalVector({quad.p3, quad.p4, quad.p1})); |
|
149 }, |
|
150 [&func](const ConditionalEdge& cedge) |
|
151 { |
|
152 func(cedge.p1, glm::vec3{}); |
|
153 func(cedge.p2, glm::vec3{}); |
|
154 }, |
|
155 element); |
|
156 } |
|
157 |
128 void gl::buildShaders( |
158 void gl::buildShaders( |
129 QOpenGLShaderProgram* shaderProgram, |
159 QOpenGLShaderProgram* shaderProgram, |
130 const char* vertexShaderSource, |
160 const char* vertexShaderSource, |
131 const char* fragmentShaderSource) |
161 const char* fragmentShaderSource) |
132 { |
162 { |
163 } |
193 } |
164 } |
194 } |
165 |
195 |
166 void gl::initializeModelShaders(gl::ModelShaders *modelShaders) |
196 void gl::initializeModelShaders(gl::ModelShaders *modelShaders) |
167 { |
197 { |
168 if (not modelShaders->initialized) |
198 if (not modelShaders->initialized) { |
169 { |
199 for (auto& shader : modelShaders->shaderObjects) { |
170 for (auto& shader : modelShaders->shaderObjects) |
|
171 { |
|
172 shader.program = std::make_unique<QOpenGLShaderProgram>(); |
200 shader.program = std::make_unique<QOpenGLShaderProgram>(); |
173 gl::buildShaders(shader.program.get(), ::vertexShaderSource, ::fragmentShaderSource); |
201 gl::buildShaders(shader.program.get(), ::vertexShaderSource, ::fragmentShaderSource); |
174 shader.program->bind(); |
202 shader.program->bind(); |
175 shader.buffer.create(); |
203 shader.buffer.create(); |
176 shader.buffer.bind(); |
204 shader.buffer.bind(); |
177 shader.buffer.setUsagePattern(QOpenGLBuffer::DynamicDraw); |
205 shader.buffer.setUsagePattern(QOpenGLBuffer::DynamicDraw); |
178 shader.vertexArray.create(); |
206 shader.vertexArray.create(); |
179 shader.vertexArray.bind(); |
207 shader.vertexArray.bind(); |
180 for (int k : {0, 1, 2, 3, 4}) |
208 for (int k : {0, 1, 2, 3, 4}) { |
181 { |
|
182 shader.program->enableAttributeArray(k); |
209 shader.program->enableAttributeArray(k); |
183 } |
210 } |
184 using Vertex = ModelShaders::Vertex; |
211 using Vertex = ModelShaders::Vertex; |
185 constexpr int stride = sizeof(Vertex); |
212 constexpr int stride = sizeof(Vertex); |
186 shader.program->setAttributeBuffer(0, GL_FLOAT, offsetof(Vertex, position), 3, stride); |
213 shader.program->setAttributeBuffer(0, GL_FLOAT, offsetof(Vertex, position), 3, stride); |
207 } |
234 } |
208 |
235 |
209 template<typename Fn> |
236 template<typename Fn> |
210 void iterateModelPolygons(Model* model, DocumentManager* context, Fn&& fn) |
237 void iterateModelPolygons(Model* model, DocumentManager* context, Fn&& fn) |
211 { |
238 { |
212 std::optional<ModelId> modelId = context->findIdForModel(model); |
239 PolygonCache* cache = findPolygonCacheForModel(model, context); |
213 if (modelId.has_value()) |
240 if (cache != nullptr) { |
214 { |
241 const PolygonCache::vector_type* polygons = getCachedPolygons(cache, model, context); |
215 PolygonCache* cache = context->getPolygonCacheForModel(modelId.value()); |
242 for (const WithId<PolygonElement>& polygon : *polygons) { |
216 if (cache != nullptr) |
243 fn(polygon); |
217 { |
|
218 for (const WithId<PolygonElement>& polygon : getCachedPolygons(cache, model, context)) |
|
219 { |
|
220 fn(polygon); |
|
221 } |
|
222 } |
244 } |
223 } |
245 } |
224 } |
246 } |
225 |
247 |
226 static QColor getColorForPolygon( |
248 static QColor getColorForPolygon( |
253 BoundingBox gl::boundingBoxForModel(Model* model, DocumentManager* context) |
275 BoundingBox gl::boundingBoxForModel(Model* model, DocumentManager* context) |
254 { |
276 { |
255 BoundingBox result = emptyBoundingBox; |
277 BoundingBox result = emptyBoundingBox; |
256 iterateModelPolygons(model, context, [&](const PolygonElement& polygon) |
278 iterateModelPolygons(model, context, [&](const PolygonElement& polygon) |
257 { |
279 { |
258 visitPoints( |
280 visitPoints([&result](const glm::vec3& p) { |
259 [&result](const glm::vec3& p) { addPointToBox(result, p); }, |
281 addPointToBox(result, p); |
260 polygon); |
282 }, polygon); |
261 }); |
283 }); |
262 return result; |
284 return result; |
263 } |
285 } |
264 |
286 |
265 /** |
287 /** |
273 const gl::RenderPreferences& preferences) |
295 const gl::RenderPreferences& preferences) |
274 { |
296 { |
275 for (gl::ModelShaders::ShaderObject& shader : shaders->shaderObjects) { |
297 for (gl::ModelShaders::ShaderObject& shader : shaders->shaderObjects) { |
276 shader.cachedData.clear(); |
298 shader.cachedData.clear(); |
277 } |
299 } |
278 iterateModelPolygons(model, context, [&](const PolygonElement& polygon) |
300 iterateModelPolygons(model, context, [&](const WithId<PolygonElement>& polygon) |
279 { |
301 { |
280 const int index = static_cast<int>(classifyPolygon(polygon)); |
302 const int index = static_cast<int>(classifyPolygon(polygon)); |
281 std::vector<gl::ModelShaders::Vertex>& vertexBuffer = shaders->shaderObjects[index].cachedData; |
303 std::vector<gl::ModelShaders::Vertex>& vertexBuffer = shaders->shaderObjects[index].cachedData; |
282 auto vertexRing = iter::ring(polygon.vertices, polygon.numPolygonVertices()); |
|
283 reserveMore(vertexBuffer, polygon.numPolygonVertices()); |
|
284 const QColor color = getColorForPolygon(polygon, preferences, colorTable); |
304 const QColor color = getColorForPolygon(polygon, preferences, colorTable); |
285 for (unsigned int i = 0; i < polygon.numPolygonVertices(); i += 1) |
305 pointsToRender(polygon, [&](const glm::vec3& point, const glm::vec3& normal){ |
286 { |
|
287 const glm::vec3& v1 = vertexRing[i - 1]; |
|
288 const glm::vec3& v2 = vertexRing[i]; |
|
289 const glm::vec3& v3 = vertexRing[i + 1]; |
|
290 gl::ModelShaders::Vertex& vertex = vertexBuffer.emplace_back(); |
306 gl::ModelShaders::Vertex& vertex = vertexBuffer.emplace_back(); |
291 vertex.position = polygon.vertices[i]; |
307 vertex.position = point; |
292 vertex.normal = glm::normalize(glm::cross(v1 - v2, v3 - v2)); |
308 vertex.normal = normal; |
293 vertex.color = glm::vec4{color.redF(), color.greenF(), color.blueF(), color.alphaF()}; |
309 vertex.color = glm::vec4{color.redF(), color.greenF(), color.blueF(), color.alphaF()}; |
294 vertex.id = polygon.id.value; |
310 vertex.id = polygon.id.value; |
295 } |
311 }); |
296 }); |
312 }); |
297 for (gl::ModelShaders::ShaderObject& shader : shaders->shaderObjects) |
313 for (gl::ModelShaders::ShaderObject& shader : shaders->shaderObjects) |
298 { |
314 { |
299 shader.vertexCount = shader.cachedData.size(); |
315 shader.vertexCount = shader.cachedData.size(); |
300 shader.buffer.bind(); |
316 shader.buffer.bind(); |