Support alpha and color gradients in circle overlays

This commit is contained in:
Brad Davis 2016-07-08 16:35:03 -07:00
parent e893b17047
commit 31948bce2d
4 changed files with 219 additions and 198 deletions

View file

@ -17,28 +17,7 @@
QString const Circle3DOverlay::TYPE = "circle3d";
Circle3DOverlay::Circle3DOverlay() :
_startAt(0.0f),
_endAt(360.0f),
_outerRadius(1.0f),
_innerRadius(0.0f),
_hasTickMarks(false),
_majorTickMarksAngle(0.0f),
_minorTickMarksAngle(0.0f),
_majorTickMarksLength(0.0f),
_minorTickMarksLength(0.0f),
_quadVerticesID(GeometryCache::UNKNOWN_ID),
_lineVerticesID(GeometryCache::UNKNOWN_ID),
_majorTicksVerticesID(GeometryCache::UNKNOWN_ID),
_minorTicksVerticesID(GeometryCache::UNKNOWN_ID),
_lastStartAt(-1.0f),
_lastEndAt(-1.0f),
_lastOuterRadius(-1.0f),
_lastInnerRadius(-1.0f)
{
_majorTickMarksColor.red = _majorTickMarksColor.green = _majorTickMarksColor.blue = (unsigned char)0;
_minorTickMarksColor.red = _minorTickMarksColor.green = _minorTickMarksColor.blue = (unsigned char)0;
}
Circle3DOverlay::Circle3DOverlay() { }
Circle3DOverlay::Circle3DOverlay(const Circle3DOverlay* circle3DOverlay) :
Planar3DOverlay(circle3DOverlay),
@ -56,11 +35,7 @@ Circle3DOverlay::Circle3DOverlay(const Circle3DOverlay* circle3DOverlay) :
_quadVerticesID(GeometryCache::UNKNOWN_ID),
_lineVerticesID(GeometryCache::UNKNOWN_ID),
_majorTicksVerticesID(GeometryCache::UNKNOWN_ID),
_minorTicksVerticesID(GeometryCache::UNKNOWN_ID),
_lastStartAt(-1.0f),
_lastEndAt(-1.0f),
_lastOuterRadius(-1.0f),
_lastInnerRadius(-1.0f)
_minorTicksVerticesID(GeometryCache::UNKNOWN_ID)
{
}
@ -70,36 +45,25 @@ void Circle3DOverlay::render(RenderArgs* args) {
}
float alpha = getAlpha();
if (alpha == 0.0f) {
return; // do nothing if our alpha is 0, we're not visible
}
// Create the circle in the coordinates origin
float outerRadius = getOuterRadius();
float innerRadius = getInnerRadius(); // only used in solid case
float startAt = getStartAt();
float endAt = getEndAt();
bool geometryChanged = (startAt != _lastStartAt || endAt != _lastEndAt ||
innerRadius != _lastInnerRadius || outerRadius != _lastOuterRadius);
bool geometryChanged = _dirty;
_dirty = false;
const float FULL_CIRCLE = 360.0f;
const float SLICES = 180.0f; // The amount of segment to create the circle
const float SLICE_ANGLE = FULL_CIRCLE / SLICES;
xColor colorX = getColor();
const float MAX_COLOR = 255.0f;
glm::vec4 color(colorX.red / MAX_COLOR, colorX.green / MAX_COLOR, colorX.blue / MAX_COLOR, alpha);
bool colorChanged = colorX.red != _lastColor.red || colorX.green != _lastColor.green || colorX.blue != _lastColor.blue;
_lastColor = colorX;
auto geometryCache = DependencyManager::get<GeometryCache>();
Q_ASSERT(args->_batch);
auto& batch = *args->_batch;
if (args->_pipeline) {
batch.setPipeline(args->_pipeline->pipeline);
}
// FIXME: THe line width of _lineWidth is not supported anymore, we ll need a workaround
@ -110,81 +74,89 @@ void Circle3DOverlay::render(RenderArgs* args) {
// for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise
// we just draw a line...
if (getIsSolid()) {
if (_quadVerticesID == GeometryCache::UNKNOWN_ID) {
if (!_quadVerticesID) {
_quadVerticesID = geometryCache->allocateID();
}
if (geometryChanged || colorChanged) {
if (geometryChanged) {
QVector<glm::vec2> points;
float angle = startAt;
float angleInRadians = glm::radians(angle);
glm::vec2 mostRecentInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius);
glm::vec2 mostRecentOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
while (angle < endAt) {
angleInRadians = glm::radians(angle);
glm::vec2 thisInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius);
glm::vec2 thisOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
points << mostRecentInnerPoint << mostRecentOuterPoint << thisOuterPoint; // first triangle
points << mostRecentInnerPoint << thisInnerPoint << thisOuterPoint; // second triangle
angle += SLICE_ANGLE;
QVector<glm::vec4> colors;
mostRecentInnerPoint = thisInnerPoint;
mostRecentOuterPoint = thisOuterPoint;
float pulseLevel = updatePulse();
vec4 pulseModifier = vec4(1);
if (_alphaPulse != 0.0) {
pulseModifier.a = (_alphaPulse >= 0.0f) ? pulseLevel : (1.0f - pulseLevel);
}
// get the last slice portion....
angle = endAt;
angleInRadians = glm::radians(angle);
glm::vec2 lastInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius);
glm::vec2 lastOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
if (_colorPulse != 0.0) {
float pulseValue = (_colorPulse >= 0.0f) ? pulseLevel : (1.0f - pulseLevel);
pulseModifier = vec4(vec3(pulseValue), pulseModifier.a);
}
vec4 innerStartColor = vec4(toGlm(_innerStartColor), _innerStartAlpha) * pulseModifier;
vec4 outerStartColor = vec4(toGlm(_outerStartColor), _outerStartAlpha) * pulseModifier;
vec4 innerEndColor = vec4(toGlm(_innerEndColor), _innerEndAlpha) * pulseModifier;
vec4 outerEndColor = vec4(toGlm(_outerEndColor), _outerEndAlpha) * pulseModifier;
points << mostRecentInnerPoint << mostRecentOuterPoint << lastOuterPoint; // first triangle
points << mostRecentInnerPoint << lastInnerPoint << lastOuterPoint; // second triangle
geometryCache->updateVertices(_quadVerticesID, points, color);
if (_innerRadius <= 0) {
_solidPrimitive = gpu::TRIANGLE_FAN;
points << vec2();
colors << innerStartColor;
for (float angle = _startAt; angle <= _endAt; angle += SLICE_ANGLE) {
float range = (angle - _startAt) / (_endAt - _startAt);
float angleRadians = glm::radians(angle);
points << glm::vec2(cos(angleRadians) * _outerRadius, sin(angleRadians) * _outerRadius);
colors << glm::mix(outerStartColor, outerEndColor, range);
}
} else {
_solidPrimitive = gpu::TRIANGLE_STRIP;
for (float angle = _startAt; angle <= _endAt; angle += SLICE_ANGLE) {
float range = (angle - _startAt) / (_endAt - _startAt);
float angleRadians = glm::radians(angle);
points << glm::vec2(cos(angleRadians) * _innerRadius, sin(angleRadians) * _innerRadius);
colors << glm::mix(innerStartColor, innerEndColor, range);
points << glm::vec2(cos(angleRadians) * _outerRadius, sin(angleRadians) * _outerRadius);
colors << glm::mix(outerStartColor, outerEndColor, range);
}
}
geometryCache->updateVertices(_quadVerticesID, points, colors);
}
geometryCache->renderVertices(batch, gpu::TRIANGLES, _quadVerticesID);
geometryCache->renderVertices(batch, _solidPrimitive, _quadVerticesID);
} else {
if (_lineVerticesID == GeometryCache::UNKNOWN_ID) {
if (!_lineVerticesID) {
_lineVerticesID = geometryCache->allocateID();
}
if (geometryChanged || colorChanged) {
if (geometryChanged) {
QVector<glm::vec2> points;
float angle = startAt;
float angle = _startAt;
float angleInRadians = glm::radians(angle);
glm::vec2 firstPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
glm::vec2 firstPoint(cosf(angleInRadians) * _outerRadius, sinf(angleInRadians) * _outerRadius);
points << firstPoint;
while (angle < endAt) {
while (angle < _endAt) {
angle += SLICE_ANGLE;
angleInRadians = glm::radians(angle);
glm::vec2 thisPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
glm::vec2 thisPoint(cosf(angleInRadians) * _outerRadius, sinf(angleInRadians) * _outerRadius);
points << thisPoint;
if (getIsDashedLine()) {
angle += SLICE_ANGLE / 2.0f; // short gap
angleInRadians = glm::radians(angle);
glm::vec2 dashStartPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
glm::vec2 dashStartPoint(cosf(angleInRadians) * _outerRadius, sinf(angleInRadians) * _outerRadius);
points << dashStartPoint;
}
}
// get the last slice portion....
angle = endAt;
angle = _endAt;
angleInRadians = glm::radians(angle);
glm::vec2 lastPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
glm::vec2 lastPoint(cosf(angleInRadians) * _outerRadius, sinf(angleInRadians) * _outerRadius);
points << lastPoint;
geometryCache->updateVertices(_lineVerticesID, points, color);
geometryCache->updateVertices(_lineVerticesID, points, vec4(toGlm(getColor()), getAlpha()));
}
if (getIsDashedLine()) {
@ -214,13 +186,13 @@ void Circle3DOverlay::render(RenderArgs* args) {
if (getMajorTickMarksAngle() > 0.0f && getMajorTickMarksLength() != 0.0f) {
float tickMarkAngle = getMajorTickMarksAngle();
float angle = startAt - fmodf(startAt, tickMarkAngle) + tickMarkAngle;
float angle = _startAt - fmodf(_startAt, tickMarkAngle) + tickMarkAngle;
float angleInRadians = glm::radians(angle);
float tickMarkLength = getMajorTickMarksLength();
float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius;
float startRadius = (tickMarkLength > 0.0f) ? _innerRadius : _outerRadius;
float endRadius = startRadius + tickMarkLength;
while (angle <= endAt) {
while (angle <= _endAt) {
angleInRadians = glm::radians(angle);
glm::vec2 thisPointA(cosf(angleInRadians) * startRadius, sinf(angleInRadians) * startRadius);
@ -236,13 +208,13 @@ void Circle3DOverlay::render(RenderArgs* args) {
if (getMinorTickMarksAngle() > 0.0f && getMinorTickMarksLength() != 0.0f) {
float tickMarkAngle = getMinorTickMarksAngle();
float angle = startAt - fmodf(startAt, tickMarkAngle) + tickMarkAngle;
float angle = _startAt - fmodf(_startAt, tickMarkAngle) + tickMarkAngle;
float angleInRadians = glm::radians(angle);
float tickMarkLength = getMinorTickMarksLength();
float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius;
float startRadius = (tickMarkLength > 0.0f) ? _innerRadius : _outerRadius;
float endRadius = startRadius + tickMarkLength;
while (angle <= endAt) {
while (angle <= _endAt) {
angleInRadians = glm::radians(angle);
glm::vec2 thisPointA(cosf(angleInRadians) * startRadius, sinf(angleInRadians) * startRadius);
@ -269,17 +241,10 @@ void Circle3DOverlay::render(RenderArgs* args) {
geometryCache->renderVertices(batch, gpu::LINES, _minorTicksVerticesID);
}
if (geometryChanged) {
_lastStartAt = startAt;
_lastEndAt = endAt;
_lastInnerRadius = innerRadius;
_lastOuterRadius = outerRadius;
}
}
const render::ShapeKey Circle3DOverlay::getShapeKey() {
auto builder = render::ShapeKey::Builder().withoutCullFace();
auto builder = render::ShapeKey::Builder().withoutCullFace().withUnlit();
if (getAlpha() != 1.0f) {
builder.withTranslucent();
}
@ -289,72 +254,102 @@ const render::ShapeKey Circle3DOverlay::getShapeKey() {
return builder.build();
}
template<typename T> T fromVariant(const QVariant& v, bool& valid) {
valid = v.isValid();
return qvariant_cast<T>(v);
}
template<> xColor fromVariant(const QVariant& v, bool& valid) {
return xColorFromVariant(v, valid);
}
template<typename T>
bool updateIfValid(const QVariantMap& properties, const char* key, T& output) {
bool valid;
T result = fromVariant<T>(properties[key], valid);
if (!valid) {
return false;
}
// Don't signal updates if the value was already set
if (result == output) {
return false;
}
output = result;
return true;
}
// Multicast, many outputs
template<typename T>
bool updateIfValid(const QVariantMap& properties, const char* key, std::initializer_list<std::reference_wrapper<T>> outputs) {
bool valid;
T value = fromVariant<T>(properties[key], valid);
if (!valid) {
return false;
}
bool updated = false;
for (T& output : outputs) {
if (output != value) {
output = value;
updated = true;
}
}
return updated;
}
// Multicast, multiple possible inputs, in order of preference
template<typename T>
bool updateIfValid(const QVariantMap& properties, const std::initializer_list<const char*> keys, T& output) {
for (const char* key : keys) {
if (updateIfValid<T>(properties, key, output)) {
return true;
}
}
return false;
}
void Circle3DOverlay::setProperties(const QVariantMap& properties) {
Planar3DOverlay::setProperties(properties);
_dirty |= updateIfValid<float>(properties, "alpha", { _innerStartAlpha, _innerEndAlpha, _outerStartAlpha, _outerEndAlpha });
_dirty |= updateIfValid<float>(properties, "Alpha", { _innerStartAlpha, _innerEndAlpha, _outerStartAlpha, _outerEndAlpha });
_dirty |= updateIfValid<float>(properties, "startAlpha", { _innerStartAlpha, _outerStartAlpha });
_dirty |= updateIfValid<float>(properties, "endAlpha", { _innerEndAlpha, _outerEndAlpha });
_dirty |= updateIfValid<float>(properties, "innerAlpha", { _innerStartAlpha, _innerEndAlpha });
_dirty |= updateIfValid<float>(properties, "outerAlpha", { _outerStartAlpha, _outerEndAlpha });
_dirty |= updateIfValid(properties, "innerStartAlpha", _innerStartAlpha);
_dirty |= updateIfValid(properties, "innerEndAlpha", _innerEndAlpha);
_dirty |= updateIfValid(properties, "outerStartAlpha", _outerStartAlpha);
_dirty |= updateIfValid(properties, "outerEndAlpha", _outerEndAlpha);
QVariant startAt = properties["startAt"];
if (startAt.isValid()) {
setStartAt(startAt.toFloat());
}
_dirty |= updateIfValid<xColor>(properties, "color", { _innerStartColor, _innerEndColor, _outerStartColor, _outerEndColor });
_dirty |= updateIfValid<xColor>(properties, "startColor", { _innerStartColor, _outerStartColor } );
_dirty |= updateIfValid<xColor>(properties, "endColor", { _innerEndColor, _outerEndColor } );
_dirty |= updateIfValid<xColor>(properties, "innerColor", { _innerStartColor, _innerEndColor } );
_dirty |= updateIfValid<xColor>(properties, "outerColor", { _outerStartColor, _outerEndColor } );
_dirty |= updateIfValid(properties, "innerStartColor", _innerStartColor);
_dirty |= updateIfValid(properties, "innerEndColor", _innerEndColor);
_dirty |= updateIfValid(properties, "outerStartColor", _outerStartColor);
_dirty |= updateIfValid(properties, "outerEndColor", _outerEndColor);
QVariant endAt = properties["endAt"];
if (endAt.isValid()) {
setEndAt(endAt.toFloat());
}
_dirty |= updateIfValid(properties, "startAt", _startAt);
_dirty |= updateIfValid(properties, "endAt", _endAt);
QVariant outerRadius = properties["radius"];
if (!outerRadius.isValid()) {
outerRadius = properties["outerRadius"];
}
if (outerRadius.isValid()) {
setOuterRadius(outerRadius.toFloat());
}
_dirty |= updateIfValid(properties, { "radius", "outerRadius" }, _outerRadius);
_dirty |= updateIfValid(properties, "innerRadius", _innerRadius);
_dirty |= updateIfValid(properties, "hasTickMarks", _hasTickMarks);
_dirty |= updateIfValid(properties, "majorTickMarksAngle", _majorTickMarksAngle);
_dirty |= updateIfValid(properties, "minorTickMarksAngle", _minorTickMarksAngle);
_dirty |= updateIfValid(properties, "majorTickMarksLength", _majorTickMarksLength);
_dirty |= updateIfValid(properties, "minorTickMarksLength", _minorTickMarksLength);
_dirty |= updateIfValid(properties, "majorTickMarksColor", _majorTickMarksColor);
_dirty |= updateIfValid(properties, "minorTickMarksColor", _minorTickMarksColor);
QVariant innerRadius = properties["innerRadius"];
if (innerRadius.isValid()) {
setInnerRadius(innerRadius.toFloat());
}
QVariant hasTickMarks = properties["hasTickMarks"];
if (hasTickMarks.isValid()) {
setHasTickMarks(hasTickMarks.toBool());
}
QVariant majorTickMarksAngle = properties["majorTickMarksAngle"];
if (majorTickMarksAngle.isValid()) {
setMajorTickMarksAngle(majorTickMarksAngle.toFloat());
}
QVariant minorTickMarksAngle = properties["minorTickMarksAngle"];
if (minorTickMarksAngle.isValid()) {
setMinorTickMarksAngle(minorTickMarksAngle.toFloat());
}
QVariant majorTickMarksLength = properties["majorTickMarksLength"];
if (majorTickMarksLength.isValid()) {
setMajorTickMarksLength(majorTickMarksLength.toFloat());
}
QVariant minorTickMarksLength = properties["minorTickMarksLength"];
if (minorTickMarksLength.isValid()) {
setMinorTickMarksLength(minorTickMarksLength.toFloat());
}
bool valid;
auto majorTickMarksColor = properties["majorTickMarksColor"];
if (majorTickMarksColor.isValid()) {
auto color = xColorFromVariant(majorTickMarksColor, valid);
if (valid) {
_majorTickMarksColor = color;
}
}
auto minorTickMarksColor = properties["minorTickMarksColor"];
if (minorTickMarksColor.isValid()) {
auto color = xColorFromVariant(majorTickMarksColor, valid);
if (valid) {
_minorTickMarksColor = color;
}
if (_innerStartAlpha < 1.0f || _innerEndAlpha < 1.0f || _outerStartAlpha < 1.0f || _outerEndAlpha < 1.0f) {
// Force the alpha to 0.5, since we'll ignore it in the presence of these other values, but we need
// it to be non-1 in order to get the right pipeline and non-0 in order to render at all.
_alpha = 0.5f;
}
}

View file

@ -59,28 +59,34 @@ public:
virtual Circle3DOverlay* createClone() const override;
protected:
float _startAt;
float _endAt;
float _outerRadius;
float _innerRadius;
bool _hasTickMarks;
float _majorTickMarksAngle;
float _minorTickMarksAngle;
float _majorTickMarksLength;
float _minorTickMarksLength;
xColor _majorTickMarksColor;
xColor _minorTickMarksColor;
int _quadVerticesID;
int _lineVerticesID;
int _majorTicksVerticesID;
int _minorTicksVerticesID;
float _startAt { 0 };
float _endAt { 360 };
float _outerRadius { 1 };
float _innerRadius { 0 };
xColor _lastColor;
float _lastStartAt;
float _lastEndAt;
float _lastOuterRadius;
float _lastInnerRadius;
xColor _innerStartColor;
xColor _innerEndColor;
xColor _outerStartColor;
xColor _outerEndColor;
float _innerStartAlpha;
float _innerEndAlpha;
float _outerStartAlpha;
float _outerEndAlpha;
bool _hasTickMarks { false };
float _majorTickMarksAngle { 0 };
float _minorTickMarksAngle { 0 };
float _majorTickMarksLength { 0 };
float _minorTickMarksLength { 0 };
xColor _majorTickMarksColor {};
xColor _minorTickMarksColor {};
gpu::Primitive _solidPrimitive { gpu::TRIANGLE_FAN };
int _quadVerticesID { 0 };
int _lineVerticesID { 0 };
int _majorTicksVerticesID { 0 };
int _minorTicksVerticesID { 0 };
bool _dirty { true };
};

View file

@ -432,7 +432,7 @@ void GeometryCache::renderGrid(gpu::Batch& batch, const glm::vec2& minCorner, co
renderQuad(batch, minCorner, maxCorner, MIN_TEX_COORD, MAX_TEX_COORD, color, id);
}
void GeometryCache::updateVertices(int id, const QVector<glm::vec2>& points, const glm::vec4& color) {
void GeometryCache::updateVertices(int id, const QVector<glm::vec2>& points, const QVector<glm::vec4>& colors) {
BatchItemDetails& details = _registeredVertices[id];
if (details.isCreated) {
@ -469,11 +469,6 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec2>& points, con
details.vertices = points.size();
details.vertexSize = FLOATS_PER_VERTEX;
int compactColor = ((int(color.x * 255.0f) & 0xFF)) |
((int(color.y * 255.0f) & 0xFF) << 8) |
((int(color.z * 255.0f) & 0xFF) << 16) |
((int(color.w * 255.0f) & 0xFF) << 24);
float* vertexData = new float[details.vertices * FLOATS_PER_VERTEX];
float* vertex = vertexData;
@ -481,16 +476,25 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec2>& points, con
int* colorDataAt = colorData;
const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f);
foreach(const glm::vec2& point, points) {
auto pointCount = points.size();
auto colorCount = colors.size();
int compactColor;
for (auto i = 0; i < pointCount; ++i) {
const auto& point = points[i];
*(vertex++) = point.x;
*(vertex++) = point.y;
*(vertex++) = NORMAL.x;
*(vertex++) = NORMAL.y;
*(vertex++) = NORMAL.z;
if (i < colorCount) {
const auto& color = colors[i];
compactColor = ((int(color.x * 255.0f) & 0xFF)) |
((int(color.y * 255.0f) & 0xFF) << 8) |
((int(color.z * 255.0f) & 0xFF) << 16) |
((int(color.w * 255.0f) & 0xFF) << 24);
}
*(colorDataAt++) = compactColor;
}
details.verticesBuffer->append(sizeof(float) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*) vertexData);
details.colorBuffer->append(sizeof(int) * details.vertices, (gpu::Byte*) colorData);
delete[] vertexData;
@ -501,7 +505,11 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec2>& points, con
#endif
}
void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, const glm::vec4& color) {
void GeometryCache::updateVertices(int id, const QVector<glm::vec2>& points, const glm::vec4& color) {
updateVertices(id, points, QVector<glm::vec4>({ color }));
}
void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, const QVector<glm::vec4>& colors) {
BatchItemDetails& details = _registeredVertices[id];
if (details.isCreated) {
details.clear();
@ -537,11 +545,8 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, con
details.vertices = points.size();
details.vertexSize = FLOATS_PER_VERTEX;
int compactColor = ((int(color.x * 255.0f) & 0xFF)) |
((int(color.y * 255.0f) & 0xFF) << 8) |
((int(color.z * 255.0f) & 0xFF) << 16) |
((int(color.w * 255.0f) & 0xFF) << 24);
// Default to white
int compactColor = 0xFFFFFFFF;
float* vertexData = new float[details.vertices * FLOATS_PER_VERTEX];
float* vertex = vertexData;
@ -549,14 +554,23 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, con
int* colorDataAt = colorData;
const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f);
foreach(const glm::vec3& point, points) {
auto pointCount = points.size();
auto colorCount = colors.size();
for (auto i = 0; i < pointCount; ++i) {
const glm::vec3& point = points[i];
if (i < colorCount) {
const glm::vec4& color = colors[i];
compactColor = ((int(color.x * 255.0f) & 0xFF)) |
((int(color.y * 255.0f) & 0xFF) << 8) |
((int(color.z * 255.0f) & 0xFF) << 16) |
((int(color.w * 255.0f) & 0xFF) << 24);
}
*(vertex++) = point.x;
*(vertex++) = point.y;
*(vertex++) = point.z;
*(vertex++) = NORMAL.x;
*(vertex++) = NORMAL.y;
*(vertex++) = NORMAL.z;
*(colorDataAt++) = compactColor;
}
@ -570,6 +584,10 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, con
#endif
}
void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, const glm::vec4& color) {
updateVertices(id, points, QVector<glm::vec4>({ color }));
}
void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, const QVector<glm::vec2>& texCoords, const glm::vec4& color) {
BatchItemDetails& details = _registeredVertices[id];

View file

@ -283,7 +283,9 @@ public:
const glm::vec4& color1, const glm::vec4& color2, int id = UNKNOWN_ID);
void updateVertices(int id, const QVector<glm::vec2>& points, const glm::vec4& color);
void updateVertices(int id, const QVector<glm::vec2>& points, const QVector<glm::vec4>& colors);
void updateVertices(int id, const QVector<glm::vec3>& points, const glm::vec4& color);
void updateVertices(int id, const QVector<glm::vec3>& points, const QVector<glm::vec4>& colors);
void updateVertices(int id, const QVector<glm::vec3>& points, const QVector<glm::vec2>& texCoords, const glm::vec4& color);
void renderVertices(gpu::Batch& batch, gpu::Primitive primitiveType, int id);
@ -360,7 +362,7 @@ private:
QHash<IntPair, VerticesIndices> _coneVBOs;
int _nextID{ 0 };
int _nextID{ 1 };
QHash<int, Vec3PairVec4Pair> _lastRegisteredQuad3DTexture;
QHash<Vec3PairVec4Pair, BatchItemDetails> _quad3DTextures;