20 if (m_enableNormals ==
enable)
105void CapsuleGeometry::updateData()
109 constexpr float EPSILON = 0.001f;
110 const float radius = m_diameter * 0.5f;
113 int verifLats =
qMax(2, m_latitudes);
114 if (verifLats % 2 != 0) {
119 uint32_t verifLons =
qMax(3, m_longitudes);
120 uint32_t verifRings =
qMax(0, m_rings);
121 float verifDepth =
qMax(EPSILON, m_height);
122 float verifRad =
qMax(EPSILON, radius);
125 bool calcMiddle = verifRings > 0;
126 uint32_t halfLats = verifLats / 2;
127 uint32_t halfLatsn1 = halfLats - 1;
128 uint32_t halfLatsn2 = halfLats - 2;
129 uint32_t verifRingsp1 = verifRings + 1;
130 uint32_t verifLonsp1 = verifLons + 1;
131 uint32_t lonsHalfLatn1 = halfLatsn1 * verifLons;
132 uint32_t lonsRingsp1 = verifRingsp1 * verifLons;
133 float halfDepth = verifDepth * 0.5f;
134 float summit = halfDepth + verifRad;
137 uint32_t idxVNEquator = verifLonsp1 + verifLons * halfLatsn2;
138 uint32_t idxVCyl = idxVNEquator + verifLons;
139 uint32_t idxVSEquator = idxVCyl;
141 idxVSEquator += verifLons * verifRings;
143 uint32_t idxVSouth = idxVSEquator + verifLons;
144 uint32_t idxVSouthCap = idxVSouth + verifLons * halfLatsn2;
145 uint32_t idxVSouthPole = idxVSouthCap + verifLons;
148 uint32_t idxVtNEquator = verifLons + verifLonsp1 * halfLatsn1;
149 uint32_t idxVtCyl = idxVtNEquator + verifLonsp1;
150 uint32_t idxVtSEquator = idxVtCyl;
152 idxVtSEquator += verifLonsp1 * verifRings;
154 uint32_t idxVtSHemi = idxVtSEquator + verifLonsp1;
155 uint32_t idxVtSPolar = idxVtSHemi + verifLonsp1 * halfLatsn2;
156 uint32_t idxVtSCap = idxVtSPolar + verifLonsp1;
159 uint32_t idxVnSouth = idxVNEquator + verifLons;
160 uint32_t idxVnSouthCap = idxVnSouth + verifLons * halfLatsn2;
161 uint32_t idxVnSouthPole = idxVnSouthCap + verifLons;
164 uint32_t idxFsCyl = verifLons + lonsHalfLatn1 * 2;
165 uint32_t idxFsSouthEquat = idxFsCyl + lonsRingsp1 * 2;
166 uint32_t idxFsSouthHemi = idxFsSouthEquat + lonsHalfLatn1 * 2;
169 uint32_t verticesLen = idxVSouthPole + 1;
170 uint32_t texturesLen = idxVtSCap + verifLons;
171 uint32_t normalsLen = idxVnSouthPole + 1;
172 uint32_t facesLen = idxFsSouthHemi + verifLons;
184 vertices[0] =
QVector3D(-summit, 0.f, 0.f);
185 vertexNormals[0] =
QVector3D(-1.f, 0.f, 0.f);
188 vertices[idxVSouthPole] =
QVector3D(summit, 0.f, 0.f);
189 vertexNormals[idxVnSouthPole] =
QVector3D(1.f, 0.f, 0.f);
194 float toTheta = 2 *
M_PI / verifLons;
195 float toPhi =
M_PI / verifLats;
196 float toTexHorizontal = 1.f / verifLons;
197 float toTexVertical = 1.f / halfLats;
199 for (uint32_t
j = 0;
j < verifLons; ++
j) {
202 float theta =
j * toTheta;
203 float sinTheta = sin(theta);
204 float cosTheta = cos(theta);
205 sinThetaCache[
j] = sinTheta;
206 cosThetaCache[
j] = cosTheta;
209 float sTex = (
j + 0.5f) * toTexHorizontal;
211 vertexTextures[idxVtSCap +
j] =
QVector2D(sTex, 0.f);
214 float x = verifRad * cosTheta;
215 float z = verifRad * sinTheta;
218 vertices[idxVNEquator +
j] =
QVector3D(-halfDepth,
x, -
z);
219 vertices[idxVSEquator +
j] =
QVector3D(halfDepth,
x, -
z);
222 vertexNormals[idxVNEquator +
j] =
QVector3D(0.f, cosTheta, -sinTheta);
225 uint32_t jNextVt =
j + 1;
226 uint32_t jNextV = jNextVt % verifLons;
229 faces[
j] = {
Face { 0,
j, 0 },
Face { jNextVt, verifLons +
j, jNextVt },
230 Face { 1 + jNextV, verifLons + jNextVt, 1 + jNextV } };
233 faces[idxFsSouthHemi +
j] = {
234 Face { idxVSouthPole, idxVtSCap +
j, idxVnSouthPole },
235 Face { idxVSouthCap + jNextV, idxVtSPolar + jNextVt, idxVnSouthCap + jNextV },
236 Face { idxVSouthCap +
j, idxVtSPolar +
j, idxVnSouthCap +
j }
241 float vtAspectRatio = 0.f;
242 switch (m_uvProfile) {
243 case CapsuleGeometry::UvProfile::Fixed:
244 vtAspectRatio = 0.33333333f;
246 case CapsuleGeometry::UvProfile::Aspect:
247 vtAspectRatio = verifRad / (verifDepth + verifRad + verifRad);
249 case CapsuleGeometry::UvProfile::Uniform:
250 vtAspectRatio = (float)halfLats / (verifRingsp1 + verifLats);
253 float vtAspectSouth = vtAspectRatio;
254 float vtAspectNorth = 1.f - vtAspectRatio;
260 for (uint32_t
j = 0;
j < verifLonsp1; ++
j) {
261 float sTex =
j * toTexHorizontal;
263 vertexTextures[idxVtNEquator +
j] =
QVector2D(sTex, vtAspectNorth);
264 vertexTextures[idxVtSEquator +
j] =
QVector2D(sTex, vtAspectSouth);
268 uint32_t vHemiOffsetNorth = 1;
269 uint32_t vHemiOffsetSouth = idxVSouth;
270 uint32_t vtHemiOffsetNorth = verifLons;
271 uint32_t vtHemiOffsetSouth = idxVtSHemi;
272 uint32_t vnHemiOffsetSouth = idxVnSouth;
273 uint32_t fHemiOffsetNorth = verifLons;
274 uint32_t fHemiOffsetSouth = idxFsSouthEquat;
276 for (uint32_t
i = 0;
i < halfLatsn1; ++
i) {
277 uint32_t iLonsCurr =
i * verifLons;
278 float ip1f =
i + 1.f;
279 float phi = ip1f * toPhi;
280 float sinPhiSouth = sin(phi);
281 float cosPhiSouth = cos(phi);
285 float cosPhiNorth = sinPhiSouth;
286 float sinPhiNorth = -cosPhiSouth;
289 float rhoCosPhiNorth = verifRad * cosPhiNorth;
290 float rhoSinPhiNorth = verifRad * sinPhiNorth;
291 float yOffsetNorth = halfDepth - rhoSinPhiNorth;
294 float rhoCosPhiSouth = verifRad * cosPhiSouth;
295 float rhoSinPhiSouth = verifRad * sinPhiSouth;
296 float yOffsetSouth = -halfDepth - rhoSinPhiSouth;
299 uint32_t vCurrLatN = 1 + iLonsCurr;
300 uint32_t vNextLatN = vCurrLatN + verifLons;
303 uint32_t vCurrLatS = idxVSEquator + iLonsCurr;
304 uint32_t vNextLatS = vCurrLatS + verifLons;
307 uint32_t vtCurrLatN = verifLons +
i * verifLonsp1;
308 uint32_t vtNextLatN = vtCurrLatN + verifLonsp1;
311 uint32_t vtCurrLatS = idxVtSEquator +
i * verifLonsp1;
312 uint32_t vtNextLatS = vtCurrLatS + verifLonsp1;
315 uint32_t vnCurrLatN = 1 + iLonsCurr;
316 uint32_t vnNextLatN = vnCurrLatN + verifLons;
319 uint32_t vnCurrLatS = idxVNEquator + iLonsCurr;
320 uint32_t vnNextLatS = vnCurrLatS + verifLons;
323 for (uint32_t
j = 0;
j < verifLons; ++
j) {
324 float sinTheta = sinThetaCache[
j];
325 float cosTheta = cosThetaCache[
j];
328 vertices[vHemiOffsetNorth] =
329 QVector3D(-yOffsetNorth, rhoCosPhiNorth * cosTheta, -rhoCosPhiNorth * sinTheta);
332 vertexNormals[vHemiOffsetNorth] =
333 QVector3D(sinPhiNorth, cosPhiNorth * cosTheta, -cosPhiNorth * sinTheta);
336 vertices[vHemiOffsetSouth] =
337 QVector3D(-yOffsetSouth, rhoCosPhiSouth * cosTheta, -rhoCosPhiSouth * sinTheta);
340 vertexNormals[vnHemiOffsetSouth] =
341 QVector3D(sinPhiSouth, cosPhiSouth * cosTheta, -cosPhiSouth * sinTheta);
347 uint32_t jNextVt =
j + 1;
348 uint32_t jNextV = jNextVt % verifLons;
351 uint32_t vn00 = vCurrLatN +
j;
352 uint32_t vn01 = vNextLatN +
j;
353 uint32_t vn11 = vNextLatN + jNextV;
354 uint32_t vn10 = vCurrLatN + jNextV;
357 uint32_t vs00 = vCurrLatS +
j;
358 uint32_t vs01 = vNextLatS +
j;
359 uint32_t vs11 = vNextLatS + jNextV;
360 uint32_t vs10 = vCurrLatS + jNextV;
363 uint32_t vtn00 = vtCurrLatN +
j;
364 uint32_t vtn01 = vtNextLatN +
j;
365 uint32_t vtn11 = vtNextLatN + jNextVt;
366 uint32_t vtn10 = vtCurrLatN + jNextVt;
369 uint32_t vts00 = vtCurrLatS +
j;
370 uint32_t vts01 = vtNextLatS +
j;
371 uint32_t vts11 = vtNextLatS + jNextVt;
372 uint32_t vts10 = vtCurrLatS + jNextVt;
375 uint32_t vnn00 = vnCurrLatN +
j;
376 uint32_t vnn01 = vnNextLatN +
j;
377 uint32_t vnn11 = vnNextLatN + jNextV;
378 uint32_t vnn10 = vnCurrLatN + jNextV;
381 uint32_t vns00 = vnCurrLatS +
j;
382 uint32_t vns01 = vnNextLatS +
j;
383 uint32_t vns11 = vnNextLatS + jNextV;
384 uint32_t vns10 = vnCurrLatS + jNextV;
387 faces[fHemiOffsetNorth] = {
Face { vn00, vtn00, vnn00 },
Face { vn11, vtn11, vnn11 },
388 Face { vn10, vtn10, vnn10 } };
390 faces[fHemiOffsetNorth + 1] = {
Face { vn00, vtn00, vnn00 },
391 Face { vn01, vtn01, vnn01 },
392 Face { vn11, vtn11, vnn11 } };
395 faces[fHemiOffsetSouth] = {
Face { vs00, vts00, vns00 },
Face { vs11, vts11, vns11 },
396 Face { vs10, vts10, vns10 } };
398 faces[fHemiOffsetSouth + 1] = {
Face { vs00, vts00, vns00 },
399 Face { vs01, vts01, vns01 },
400 Face { vs11, vts11, vns11 } };
402 fHemiOffsetNorth += 2;
403 fHemiOffsetSouth += 2;
409 float tTexFac = ip1f * toTexVertical;
410 float tTexNorth = 1.f - tTexFac + tTexFac * vtAspectNorth;
411 float tTexSouth = vtAspectSouth * (1.f - tTexFac);
414 for (uint32_t
j = 0;
j < verifLonsp1; ++
j) {
415 float sTex = sTexCache[
j];
417 vertexTextures[vtHemiOffsetNorth] =
QVector2D(sTex, tTexNorth);
418 vertexTextures[vtHemiOffsetSouth] =
QVector2D(sTex, tTexSouth);
431 float toFac = 1.f / verifRingsp1;
432 uint32_t vCylOffset = idxVCyl;
433 uint32_t vtCylOffset = idxVtCyl;
434 for (uint32_t
m = 1;
m < verifRingsp1; ++
m) {
435 float fac =
m * toFac;
436 float cmplFac = 1.f - fac;
439 for (uint32_t
j = 0;
j < verifLons; ++
j) {
440 QVector3D vEquatorNorth = vertices[idxVNEquator +
j];
441 QVector3D vEquatorSouth = vertices[idxVSEquator +
j];
447 vertices[vCylOffset] =
448 QVector3D(cmplFac * vEquatorNorth.
x() + fac * vEquatorSouth.
x(),
449 cmplFac * vEquatorNorth.
y() + fac * vEquatorSouth.
y(),
450 cmplFac * vEquatorNorth.
z() + fac * vEquatorSouth.
z());
456 float tTex = cmplFac * vtAspectNorth + fac * vtAspectSouth;
457 for (uint32_t
j = 0;
j < verifLonsp1; ++
j) {
458 float sTex = sTexCache[
j];
459 vertexTextures[vtCylOffset] =
QVector2D(sTex, tTex);
466 uint32_t fCylOffset = idxFsCyl;
467 for (uint32_t
m = 0;
m < verifRingsp1; ++
m) {
468 uint32_t vCurrRing = idxVNEquator +
m * verifLons;
469 uint32_t vNextRing = vCurrRing + verifLons;
471 uint32_t vtCurrRing = idxVtNEquator +
m * verifLonsp1;
472 uint32_t vtNextRing = vtCurrRing + verifLonsp1;
474 for (uint32_t
j = 0;
j < verifLons; ++
j) {
475 uint32_t jNextVt =
j + 1;
476 uint32_t jNextV = jNextVt % verifLons;
479 uint32_t v00 = vCurrRing +
j;
480 uint32_t v01 = vNextRing +
j;
481 uint32_t v11 = vNextRing + jNextV;
482 uint32_t v10 = vCurrRing + jNextV;
485 uint32_t vt00 = vtCurrRing +
j;
486 uint32_t vt01 = vtNextRing +
j;
487 uint32_t vt11 = vtNextRing + jNextVt;
488 uint32_t vt10 = vtCurrRing + jNextVt;
491 uint32_t vn0 = idxVNEquator +
j;
492 uint32_t vn1 = idxVNEquator + jNextV;
494 faces[fCylOffset] = {
Face { v00, vt00, vn0 },
Face { v11, vt11, vn1 },
495 Face { v10, vt10, vn1 } };
497 faces[fCylOffset + 1] = {
Face { v00, vt00, vn0 },
Face { v01, vt01, vn0 },
498 Face { v11, vt11, vn1 } };
504 uint32_t
stride = 3 *
sizeof(float);
505 uint32_t strideNormal = 0;
506 uint32_t strideUV = 0;
508 if (m_enableNormals) {
510 stride += 3 *
sizeof(float);
514 stride += 2 *
sizeof(float);
520 const auto getVertexPtr = [&](
const int vertexIdx) {
523 const auto getNormalPtr = [&](
const int vertexIdx) {
526 const auto getTexturePtr = [&](
const int vertexIdx) {
530 uint32_t *indexPtr =
reinterpret_cast<uint32_t *
>(
indexData.
data());
533 *getVertexPtr(
i) = vertices[
i];
537 const auto vertexIndices =
538 std::array<uint32_t, 3> { faces[
i][0].vertexIdx, faces[
i][1].vertexIdx,
539 faces[
i][2].vertexIdx };
540 *indexPtr = vertexIndices[0];
542 *indexPtr = vertexIndices[1];
544 *indexPtr = vertexIndices[2];
547 if (m_enableNormals) {
548 const auto normalIndices =
549 std::array<uint32_t, 3> { faces[
i][0].normalIdx, faces[
i][1].normalIdx,
550 faces[
i][2].normalIdx };
551 *getNormalPtr(vertexIndices[0]) = vertexNormals[normalIndices[0]];
552 *getNormalPtr(vertexIndices[1]) = vertexNormals[normalIndices[1]];
553 *getNormalPtr(vertexIndices[2]) = vertexNormals[normalIndices[2]];
557 const auto textureIndices =
558 std::array<uint32_t, 3> { faces[
i][0].textureIdx, faces[
i][1].textureIdx,
559 faces[
i][2].textureIdx };
560 *getTexturePtr(vertexIndices[0]) = vertexTextures[textureIndices[0]];
561 *getTexturePtr(vertexIndices[1]) = vertexTextures[textureIndices[1]];
562 *getTexturePtr(vertexIndices[2]) = vertexTextures[textureIndices[2]];
568 if (m_enableNormals) {
584 QVector3D(radius + 0.5f * m_height, radius, radius));
void setLongitudes(int longitudes)
void setEnableNormals(bool enable)
void setHeight(float height)
void setLatitudes(int latitudes)
void setEnableUV(bool enable)
void enableNormalsChanged()
void setDiameter(float diameter)
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype length() const noexcept
Attribute::Semantic int int stride
Returns the byte stride of the vertex buffer.
void setStride(int stride)
Sets the stride of the vertex buffer to stride, measured in bytes.
void addAttribute(Attribute::Semantic semantic, int offset, Attribute::ComponentType componentType)
Adds vertex attribute description.
void setVertexData(const QByteArray &data)
Sets the vertex buffer data.
void clear()
Resets the geometry to its initial state, clearing previously set vertex and index data as well as at...
void setBounds(const QVector3D &min, const QVector3D &max)
Sets the bounding volume of the geometry to the cube defined by the points min and max.
QByteArray vertexData() const
Returns the vertex buffer data set by setVertexData.
QByteArray indexData() const
Returns the index buffer data.
void setIndexData(const QByteArray &data)
Sets the index buffer to data.
The QVector2D class represents a vector or vertex in 2D space.
The QVector3D class represents a vector or vertex in 3D space.
constexpr float y() const noexcept
Returns the y coordinate of this point.
constexpr float x() const noexcept
Returns the x coordinate of this point.
constexpr float z() const noexcept
Returns the z coordinate of this point.
Combined button and popup list for selecting options.
constexpr const T & qMax(const T &a, const T &b)
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLint GLint GLint GLint GLint x
[0]
GLint GLsizei GLsizei height
const void GLsizei GLsizei stride