mirror of
https://github.com/overte-org/overte.git
synced 2025-04-13 18:42:11 +02:00
Support triangle and hexagon shapes, add shape support to overlays.
This commit is contained in:
parent
cf1c954edc
commit
03cb6175ab
10 changed files with 298 additions and 12 deletions
|
@ -22,6 +22,7 @@
|
|||
#include "Image3DOverlay.h"
|
||||
#include "Circle3DOverlay.h"
|
||||
#include "Cube3DOverlay.h"
|
||||
#include "Shape3DOverlay.h"
|
||||
#include "ImageOverlay.h"
|
||||
#include "Line3DOverlay.h"
|
||||
#include "LocalModelsOverlay.h"
|
||||
|
@ -157,6 +158,8 @@ unsigned int Overlays::addOverlay(const QString& type, const QVariant& propertie
|
|||
thisOverlay = std::make_shared<TextOverlay>();
|
||||
} else if (type == Text3DOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<Text3DOverlay>();
|
||||
} else if (type == Shape3DOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<Shape3DOverlay>();
|
||||
} else if (type == Cube3DOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<Cube3DOverlay>();
|
||||
} else if (type == Sphere3DOverlay::TYPE) {
|
||||
|
|
130
interface/src/ui/overlays/Shape3DOverlay.cpp
Normal file
130
interface/src/ui/overlays/Shape3DOverlay.cpp
Normal file
|
@ -0,0 +1,130 @@
|
|||
//
|
||||
// Shape3DOverlay.cpp
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "Shape3DOverlay.h"
|
||||
|
||||
#include <SharedUtil.h>
|
||||
#include <StreamUtils.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <DependencyManager.h>
|
||||
|
||||
QString const Shape3DOverlay::TYPE = "shape";
|
||||
|
||||
Shape3DOverlay::Shape3DOverlay(const Shape3DOverlay* Shape3DOverlay) :
|
||||
Volume3DOverlay(Shape3DOverlay)
|
||||
{
|
||||
}
|
||||
|
||||
void Shape3DOverlay::render(RenderArgs* args) {
|
||||
if (!_visible) {
|
||||
return; // do nothing if we're not visible
|
||||
}
|
||||
|
||||
float alpha = getAlpha();
|
||||
xColor color = getColor();
|
||||
const float MAX_COLOR = 255.0f;
|
||||
glm::vec4 cubeColor(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);
|
||||
|
||||
// TODO: handle registration point??
|
||||
glm::vec3 position = getPosition();
|
||||
glm::vec3 dimensions = getDimensions();
|
||||
glm::quat rotation = getRotation();
|
||||
|
||||
auto batch = args->_batch;
|
||||
|
||||
if (batch) {
|
||||
Transform transform;
|
||||
transform.setTranslation(position);
|
||||
transform.setRotation(rotation);
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
auto pipeline = args->_pipeline;
|
||||
if (!pipeline) {
|
||||
pipeline = _isSolid ? geometryCache->getShapePipeline() : geometryCache->getWireShapePipeline();
|
||||
}
|
||||
|
||||
transform.setScale(dimensions);
|
||||
batch->setModelTransform(transform);
|
||||
if (_isSolid) {
|
||||
geometryCache->renderSolidShapeInstance(*batch, _shape, cubeColor, pipeline);
|
||||
} else {
|
||||
geometryCache->renderWireShapeInstance(*batch, _shape, cubeColor, pipeline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const render::ShapeKey Shape3DOverlay::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder();
|
||||
if (getAlpha() != 1.0f) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
if (!getIsSolid()) {
|
||||
builder.withUnlit().withDepthBias();
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
Shape3DOverlay* Shape3DOverlay::createClone() const {
|
||||
return new Shape3DOverlay(this);
|
||||
}
|
||||
|
||||
|
||||
static const std::array<QString, GeometryCache::Shape::NUM_SHAPES> shapeStrings { {
|
||||
"Line",
|
||||
"Triangle",
|
||||
"Quad",
|
||||
"Hexagon",
|
||||
"Octagon",
|
||||
"Circle",
|
||||
"Cube",
|
||||
"Sphere",
|
||||
"Tetrahedron",
|
||||
"Octahedron",
|
||||
"Dodecahedron",
|
||||
"Icosahedron",
|
||||
"Torus",
|
||||
"Cone",
|
||||
"Cylinder"
|
||||
} };
|
||||
|
||||
|
||||
void Shape3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Volume3DOverlay::setProperties(properties);
|
||||
|
||||
auto shape = properties["shape"];
|
||||
if (shape.isValid()) {
|
||||
const QString shapeStr = shape.toString();
|
||||
for (size_t i = 0; i < shapeStrings.size(); ++i) {
|
||||
if (shapeStr == shapeStrings[i]) {
|
||||
this->_shape = static_cast<GeometryCache::Shape>(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto borderSize = properties["borderSize"];
|
||||
|
||||
if (borderSize.isValid()) {
|
||||
float value = borderSize.toFloat();
|
||||
setBorderSize(value);
|
||||
}
|
||||
}
|
||||
|
||||
QVariant Shape3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "borderSize") {
|
||||
return _borderSize;
|
||||
}
|
||||
|
||||
if (property == "shape") {
|
||||
return shapeStrings[_shape];
|
||||
}
|
||||
|
||||
return Volume3DOverlay::getProperty(property);
|
||||
}
|
46
interface/src/ui/overlays/Shape3DOverlay.h
Normal file
46
interface/src/ui/overlays/Shape3DOverlay.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// Shape3DOverlay.h
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_Shape3DOverlay_h
|
||||
#define hifi_Shape3DOverlay_h
|
||||
|
||||
#include "Volume3DOverlay.h"
|
||||
|
||||
#include <GeometryCache.h>
|
||||
|
||||
class Shape3DOverlay : public Volume3DOverlay {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static QString const TYPE;
|
||||
virtual QString getType() const override { return TYPE; }
|
||||
|
||||
Shape3DOverlay() {}
|
||||
Shape3DOverlay(const Shape3DOverlay* Shape3DOverlay);
|
||||
|
||||
virtual void render(RenderArgs* args) override;
|
||||
virtual const render::ShapeKey getShapeKey() override;
|
||||
|
||||
virtual Shape3DOverlay* createClone() const override;
|
||||
|
||||
float getBorderSize() const { return _borderSize; }
|
||||
|
||||
void setBorderSize(float value) { _borderSize = value; }
|
||||
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
|
||||
private:
|
||||
float _borderSize;
|
||||
GeometryCache::Shape _shape { GeometryCache::Hexagon };
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_Shape3DOverlay_h
|
|
@ -23,9 +23,11 @@
|
|||
// is a half unit sphere. However, the geometry cache renders a UNIT sphere, so we need to scale down.
|
||||
static const float SPHERE_ENTITY_SCALE = 0.5f;
|
||||
|
||||
static GeometryCache::Shape MAPPING[entity::NUM_SHAPES] = {
|
||||
static std::array<GeometryCache::Shape, entity::NUM_SHAPES> MAPPING { {
|
||||
GeometryCache::Triangle,
|
||||
GeometryCache::Quad,
|
||||
GeometryCache::Hexagon,
|
||||
GeometryCache::Octagon,
|
||||
GeometryCache::Circle,
|
||||
GeometryCache::Cube,
|
||||
GeometryCache::Sphere,
|
||||
|
@ -36,7 +38,7 @@ static GeometryCache::Shape MAPPING[entity::NUM_SHAPES] = {
|
|||
GeometryCache::Torus,
|
||||
GeometryCache::Cone,
|
||||
GeometryCache::Cylinder,
|
||||
};
|
||||
} };
|
||||
|
||||
|
||||
RenderableShapeEntityItem::Pointer RenderableShapeEntityItem::baseFactory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
|
|
|
@ -20,17 +20,19 @@
|
|||
#include "ShapeEntityItem.h"
|
||||
|
||||
namespace entity {
|
||||
static const std::vector<QString> shapeStrings { {
|
||||
static const std::array<QString, Shape::NUM_SHAPES> shapeStrings { {
|
||||
"Triangle",
|
||||
"Quad",
|
||||
"Circle",
|
||||
"Hexagon",
|
||||
"Octagon",
|
||||
"Circle",
|
||||
"Cube",
|
||||
"Sphere",
|
||||
"Tetrahedron",
|
||||
"Octahedron",
|
||||
"Dodecahedron",
|
||||
"Icosahedron",
|
||||
"Torus",
|
||||
"Torus",
|
||||
"Cone",
|
||||
"Cylinder"
|
||||
} };
|
||||
|
|
|
@ -15,6 +15,8 @@ namespace entity {
|
|||
enum Shape {
|
||||
Triangle,
|
||||
Quad,
|
||||
Hexagon,
|
||||
Octagon,
|
||||
Circle,
|
||||
Cube,
|
||||
Sphere,
|
||||
|
|
|
@ -97,7 +97,8 @@ public:
|
|||
ICEServerHeartbeatACK,
|
||||
NegotiateAudioFormat,
|
||||
SelectedAudioFormat,
|
||||
LAST_PACKET_TYPE = SelectedAudioFormat
|
||||
MoreEntityShapes,
|
||||
LAST_PACKET_TYPE = MoreEntityShapes
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -60,6 +60,18 @@ static const uint SHAPE_NORMALS_OFFSET = sizeof(glm::vec3);
|
|||
static const gpu::Type SHAPE_INDEX_TYPE = gpu::UINT32;
|
||||
static const uint SHAPE_INDEX_SIZE = sizeof(gpu::uint32);
|
||||
|
||||
template <size_t SIDES>
|
||||
std::vector<vec3> polygon() {
|
||||
std::vector<vec3> result;
|
||||
result.reserve(SIDES);
|
||||
double angleIncrement = 2.0 * M_PI / SIDES;
|
||||
for (size_t i = 0; i < SIDES; ++i) {
|
||||
double angle = (double)i * angleIncrement;
|
||||
result.push_back(vec3{ cos(angle) * 0.5, 0.0, sin(angle) * 0.5 });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void GeometryCache::ShapeData::setupVertices(gpu::BufferPointer& vertexBuffer, const geometry::VertexVector& vertices) {
|
||||
vertexBuffer->append(vertices);
|
||||
|
||||
|
@ -239,6 +251,75 @@ void setupSmoothShape(GeometryCache::ShapeData& shapeData, const geometry::Solid
|
|||
shapeData.setupIndices(indexBuffer, solidIndices, wireIndices);
|
||||
}
|
||||
|
||||
template <uint32_t N>
|
||||
void extrudePolygon(GeometryCache::ShapeData& shapeData, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer) {
|
||||
using namespace geometry;
|
||||
Index baseVertex = (Index)(vertexBuffer->getSize() / SHAPE_VERTEX_STRIDE);
|
||||
VertexVector vertices;
|
||||
IndexVector solidIndices, wireIndices;
|
||||
|
||||
// Top and bottom faces
|
||||
std::vector<vec3> shape = polygon<N>();
|
||||
for (const vec3& v : shape) {
|
||||
vertices.push_back(vec3(v.x, 0.5f, v.z));
|
||||
vertices.push_back(vec3(0, 1, 0));
|
||||
}
|
||||
for (const vec3& v : shape) {
|
||||
vertices.push_back(vec3(v.x, -0.5f, v.z));
|
||||
vertices.push_back(vec3(0, -1, 0));
|
||||
}
|
||||
for (uint32_t i = 2; i < N; ++i) {
|
||||
solidIndices.push_back(baseVertex + 0);
|
||||
solidIndices.push_back(baseVertex + i);
|
||||
solidIndices.push_back(baseVertex + i - 1);
|
||||
solidIndices.push_back(baseVertex + N);
|
||||
solidIndices.push_back(baseVertex + i + N - 1);
|
||||
solidIndices.push_back(baseVertex + i + N);
|
||||
}
|
||||
for (uint32_t i = 1; i <= N; ++i) {
|
||||
wireIndices.push_back(baseVertex + (i % N));
|
||||
wireIndices.push_back(baseVertex + i - 1);
|
||||
wireIndices.push_back(baseVertex + (i % N) + N);
|
||||
wireIndices.push_back(baseVertex + (i - 1) + N);
|
||||
}
|
||||
|
||||
// Now do the sides
|
||||
baseVertex += 2 * N;
|
||||
|
||||
for (uint32_t i = 0; i < N; ++i) {
|
||||
vec3 left = shape[i];
|
||||
vec3 right = shape[(i + 1) % N];
|
||||
vec3 normal = glm::normalize(left + right);
|
||||
vec3 topLeft = vec3(left.x, 0.5f, left.z);
|
||||
vec3 topRight = vec3(right.x, 0.5f, right.z);
|
||||
vec3 bottomLeft = vec3(left.x, -0.5f, left.z);
|
||||
vec3 bottomRight = vec3(right.x, -0.5f, right.z);
|
||||
|
||||
vertices.push_back(topLeft);
|
||||
vertices.push_back(normal);
|
||||
vertices.push_back(bottomLeft);
|
||||
vertices.push_back(normal);
|
||||
vertices.push_back(topRight);
|
||||
vertices.push_back(normal);
|
||||
vertices.push_back(bottomRight);
|
||||
vertices.push_back(normal);
|
||||
|
||||
solidIndices.push_back(baseVertex + 0);
|
||||
solidIndices.push_back(baseVertex + 2);
|
||||
solidIndices.push_back(baseVertex + 1);
|
||||
solidIndices.push_back(baseVertex + 1);
|
||||
solidIndices.push_back(baseVertex + 2);
|
||||
solidIndices.push_back(baseVertex + 3);
|
||||
wireIndices.push_back(baseVertex + 0);
|
||||
wireIndices.push_back(baseVertex + 1);
|
||||
wireIndices.push_back(baseVertex + 3);
|
||||
wireIndices.push_back(baseVertex + 2);
|
||||
baseVertex += 4;
|
||||
}
|
||||
|
||||
shapeData.setupVertices(vertexBuffer, vertices);
|
||||
shapeData.setupIndices(indexBuffer, solidIndices, wireIndices);
|
||||
}
|
||||
|
||||
// FIXME solids need per-face vertices, but smooth shaded
|
||||
// components do not. Find a way to support using draw elements
|
||||
|
@ -285,10 +366,13 @@ void GeometryCache::buildShapes() {
|
|||
// Not implememented yet:
|
||||
|
||||
//Triangle,
|
||||
extrudePolygon<3>(_shapes[Triangle], _shapeVertices, _shapeIndices);
|
||||
//Hexagon,
|
||||
extrudePolygon<6>(_shapes[Hexagon], _shapeVertices, _shapeIndices);
|
||||
//Octagon,
|
||||
extrudePolygon<8>(_shapes[Octagon], _shapeVertices, _shapeIndices);
|
||||
//Quad,
|
||||
//Circle,
|
||||
//Octahetron,
|
||||
//Dodecahedron,
|
||||
//Torus,
|
||||
//Cone,
|
||||
//Cylinder,
|
||||
|
@ -1757,6 +1841,11 @@ void GeometryCache::renderSolidShapeInstance(gpu::Batch& batch, GeometryCache::S
|
|||
renderInstances(batch, color, false, pipeline, shape);
|
||||
}
|
||||
|
||||
void GeometryCache::renderWireShapeInstance(gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
|
||||
renderInstances(batch, color, true, pipeline, shape);
|
||||
}
|
||||
|
||||
|
||||
void GeometryCache::renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
|
||||
renderInstances(batch, color, false, pipeline, GeometryCache::Sphere);
|
||||
}
|
||||
|
|
|
@ -132,6 +132,8 @@ public:
|
|||
Line,
|
||||
Triangle,
|
||||
Quad,
|
||||
Hexagon,
|
||||
Octagon,
|
||||
Circle,
|
||||
Cube,
|
||||
Sphere,
|
||||
|
@ -139,10 +141,9 @@ public:
|
|||
Octahedron,
|
||||
Dodecahedron,
|
||||
Icosahedron,
|
||||
Torus,
|
||||
Cone,
|
||||
Cylinder,
|
||||
|
||||
Torus, // not yet implemented
|
||||
Cone, // not yet implemented
|
||||
Cylinder, // not yet implemented
|
||||
NUM_SHAPES,
|
||||
};
|
||||
|
||||
|
@ -170,6 +171,13 @@ public:
|
|||
renderSolidShapeInstance(batch, shape, glm::vec4(color, 1.0f), pipeline);
|
||||
}
|
||||
|
||||
void renderWireShapeInstance(gpu::Batch& batch, Shape shape, const glm::vec4& color = glm::vec4(1),
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
||||
void renderWireShapeInstance(gpu::Batch& batch, Shape shape, const glm::vec3& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline) {
|
||||
renderWireShapeInstance(batch, shape, glm::vec4(color, 1.0f), pipeline);
|
||||
}
|
||||
|
||||
void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
||||
void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec3& color,
|
||||
|
|
|
@ -1354,6 +1354,9 @@
|
|||
<option value="Octahedron">Octahedron</option>
|
||||
<option value="Icosahedron">Icosahedron</option>
|
||||
<option value="Dodecahedron">Dodecahedron</option>
|
||||
<option value="Hexagon">Hexagon</option>
|
||||
<option value="Triangle">Triangle</option>
|
||||
<option value="Octagon">Octagon</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="property text">
|
||||
|
|
Loading…
Reference in a new issue