src/gl/compiler.cpp

changeset 21
0133e565e072
parent 19
ed9685f44ab3
child 22
6da867fa5429
equal deleted inserted replaced
20:cef43609a374 21:0133e565e072
22 #include "gl/compiler.h" 22 #include "gl/compiler.h"
23 #include "documentmanager.h" 23 #include "documentmanager.h"
24 #include "invert.h" 24 #include "invert.h"
25 #include "ring.h" 25 #include "ring.h"
26 26
27 gl::Compiler::Compiler(QObject* parent) :
28 QObject{parent}
29 {
30 }
31
27 gl::Compiler::~Compiler() 32 gl::Compiler::~Compiler()
28 { 33 {
29 34
30 } 35 }
36
37 void gl::Compiler::build(Model* model, DocumentManager* context)
38 {
39 if (not this->initialized)
40 {
41 this->initializeVbo();
42 }
43 std::vector<GLfloat> vboData[gl::numVbos];
44 const std::vector<gl::Polygon> polygons = model->getPolygons(context);
45 for (const gl::Polygon& polygon : polygons)
46 {
47 this->buildPolygon(polygon, vboData);
48 }
49 for (int i = 0; i < gl::numVbos; i += 1)
50 {
51 this->upload(i, vboData[i]);
52 }
53 }
54
55 gl::VboClass classifyPolygon(const gl::Polygon& polygon)
56 {
57 switch (polygon.type)
58 {
59 case gl::Polygon::EdgeLine:
60 return gl::VboClass::Lines;
61 case gl::Polygon::Triangle:
62 return gl::VboClass::Triangles;
63 case gl::Polygon::Quadrilateral:
64 return gl::VboClass::Quads;
65 case gl::Polygon::ConditionalEdge:
66 return gl::VboClass::ConditionalLines;
67 }
68 return gl::VboClass::Lines;
69 }
70
71 QColor colorFromId(linetypes::Id id)
72 {
73 // Calculate a color based from this index. This method caters for
74 // 16777216 objects. I don't think that will be exceeded anytime soon.
75 const int r = (id.value / 0x10000) % 0x100;
76 const int g = (id.value / 0x100) % 0x100;
77 const int b = id.value % 0x100;
78 return {r, g, b};
79 }
80
81 void writeVertex(std::vector<GLfloat>& data, const Point3D& point)
82 {
83 data.push_back(point.x);
84 data.push_back(point.y);
85 data.push_back(point.z);
86 }
87
88 void gl::Compiler::buildPolygon(gl::Polygon polygon, std::vector<GLfloat>* vboData)
89 {
90 const gl::VboClass vboClass = classifyPolygon(polygon);
91 auto vboBuffer = [&](VboSubclass subclass) -> std::vector<GLfloat>&
92 {
93 return vboData[gl::vboIndex({vboClass, subclass})];
94 };
95 auto vertexRing = iter::ring(polygon.vertices, polygon.numPolygonVertices());
96 for (int i = 0; i < polygon.numPolygonVertices(); i += 1)
97 {
98 const Point3D& v1 = vertexRing[i - 1];
99 const Point3D& v2 = vertexRing[i];
100 const Point3D& v3 = vertexRing[i + 1];
101 const QVector3D normal = QVector3D::crossProduct(v3 - v2, v1 - v2).normalized();
102 std::vector<GLfloat>& data = vboBuffer(VboSubclass::Normals);
103 for (const GLfloat coord : {normal.x(), normal.y(), normal.z()})
104 data.push_back(coord);
105 }
106 vboBuffer(VboSubclass::Surfaces).reserve(vboBuffer(VboSubclass::Surfaces).size() + polygon.numPolygonVertices());
107 // Transform vertices so that they're suitable for GL rendering
108 for (int i = 0; i < polygon.numPolygonVertices(); i += 1)
109 {
110 polygon.vertices[i].y = -polygon.vertices[i].y;
111 polygon.vertices[i].z = -polygon.vertices[i].z;
112 #if 0
113 // Add these vertices to the bounding box (unless we're going to do it over
114 // from scratch afterwards anyway)
115 if (not this->needBoundingBoxRebuild)
116 {
117 this->boundingBox.consider(poly.vertices[i]);
118 }
119 #endif
120 writeVertex(vboBuffer(VboSubclass::Surfaces), polygon.vertices[i]);
121 }
122 this->writeColor(vboData, polygon, VboSubclass::RegularColors);
123 this->writeColor(vboData, polygon, VboSubclass::PickColors);
124 this->writeColor(vboData, polygon, VboSubclass::BfcFrontColors);
125 this->writeColor(vboData, polygon, VboSubclass::BfcBackColors);
126 }
127
128 QColor gl::Compiler::getColorForPolygon(const gl::Polygon& polygon, VboSubclass subclass)
129 {
130 QColor color;
131
132 switch (subclass)
133 {
134 case VboSubclass::Surfaces:
135 case VboSubclass::Normals:
136 case VboSubclass::InvertedNormals:
137 // Surface and normal VBOs contain vertex data, not colors. So we can't return anything meaningful.
138 return {};
139 case VboSubclass::BfcFrontColors:
140 // Use the constant green color for BFC front colors
141 return {64, 192, 80};
142 case VboSubclass::BfcBackColors:
143 // Use the constant red color for BFC back colors
144 return {208, 64, 64};
145 case VboSubclass::PickColors:
146 // For the picking scene, use unique picking colors provided by the model.
147 return colorFromId(polygon.id);
148 case VboSubclass::RandomColors:
149 // For the random color scene, the owner object has rolled up a random color. Use that.
150 color = {255, 64, 255}; // polygonOwner->randomColor();
151 break;
152 case VboSubclass::RegularColors:
153 // For normal colors, use the polygon's color.
154 if (polygon.color == colors::main)
155 {
156 color = {255, 255, 64}; // mainColorRepresentation();
157 }
158 else if (polygon.color == colors::edge)
159 {
160 // Edge color is black, unless we have a dark background, in which case lines need to be bright.
161 color = Qt::black; //luma(config::backgroundColor()) > 40 ? Qt::black : Qt::white;
162 }
163 else
164 {
165 // Not main or edge color, use the polygon's color as is.
166 color = {255, 255, 64}; //polygon.color.faceColor();
167 }
168 break;
169 }
170
171 if (color.isValid())
172 {
173 // We may wish to apply blending on the color to indicate selection or highlight.
174 /*
175 const double blendAlpha = 0.0;
176 if (blendAlpha != 0.0)
177 {
178 QColor selectedColor = config::selectColorBlend();
179 double denominator = blendAlpha + 1.0;
180 color.setRed((color.red() + (selectedColor.red() * blendAlpha)) / denominator);
181 color.setGreen((color.green() + (selectedColor.green() * blendAlpha)) / denominator);
182 color.setBlue((color.blue() + (selectedColor.blue() * blendAlpha)) / denominator);
183 }
184 */
185 }
186 else
187 {
188 if (polygon.numPolygonVertices() == 2)
189 color = Qt::black;
190 else
191 color = {255, 255, 64};
192 }
193
194 return color;
195 }
196
197 void gl::Compiler::writeColor(std::vector<GLfloat>* data, const gl::Polygon& polygon, VboSubclass subclass)
198 {
199 std::vector<GLfloat>& buffer = data[gl::vboIndex({classifyPolygon(polygon), subclass})];
200 const QColor color = this->getColorForPolygon(polygon, subclass);
201 buffer.reserve(data->size() + 4 * polygon.numPolygonVertices());
202 for (int i = 0; i < polygon.numPolygonVertices(); i += 1)
203 {
204 buffer.push_back(color.redF() / 255.0f);
205 buffer.push_back(color.greenF() / 255.0f);
206 buffer.push_back(color.blueF() / 255.0f);
207 buffer.push_back(color.alphaF() / 255.0f);
208 }
209 }
210
211 void gl::Compiler::initializeVbo()
212 {
213 this->initializeOpenGLFunctions();
214 glGenBuffers(countof(this->storedVbo), &this->storedVbo[0]);
215 this->initialized = true;
216 }
217
218 ///
219 /// \brief Uploads data to a vbo
220 /// \param vboAddress Which vbo to upload to
221 /// \param data Data to upload to vbo
222 ///
223 void gl::Compiler::upload(const int vboIndex, const std::vector<GLfloat>& data)
224 {
225 glBindBuffer(GL_ARRAY_BUFFER, this->storedVbo[vboIndex]);
226 glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof data[0], data.data(), GL_STATIC_DRAW);
227 glBindBuffer(GL_ARRAY_BUFFER, 0);
228 this->storedVboSizes[vboIndex] = data.size();
229 }
230
231 GLuint gl::Compiler::vbo(const VboAddress vboAddress) const
232 {
233 return this->storedVbo[gl::vboIndex(vboAddress)];
234 }
235
236 int gl::Compiler::vboSize(const VboAddress vboAddress) const
237 {
238 return this->storedVboSizes[gl::vboIndex(vboAddress)];
239 }
240
241 int gl::vboIndex(const VboAddress vboAddress)
242 {
243 return static_cast<std::uint8_t>(vboAddress.vboClass) * gl::numVboSubclasses
244 + static_cast<std::uint8_t>(vboAddress.vboSubclass);
245 }

mercurial