mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 11:45:36 +02:00
Show heightfield cursor.
This commit is contained in:
parent
4e1886dfcb
commit
0fc34a47aa
6 changed files with 204 additions and 22 deletions
|
@ -0,0 +1,20 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// metavoxel_heightfield_cursor.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 8/7/14.
|
||||
// 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
|
||||
//
|
||||
|
||||
// the cursor texture
|
||||
uniform sampler2D cursorMap;
|
||||
|
||||
void main(void) {
|
||||
// just multiply the color by the cursor texture
|
||||
gl_FragColor = gl_Color * texture2D(cursorMap, gl_TexCoord[0].st);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// metavoxel_heighfield_cursor.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 8/7/14.
|
||||
// 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
|
||||
//
|
||||
|
||||
// the height texture
|
||||
uniform sampler2D heightMap;
|
||||
|
||||
// the distance between height points in texture space
|
||||
uniform float heightScale;
|
||||
|
||||
void main(void) {
|
||||
// compute the view space coordinates
|
||||
float height = texture2D(heightMap, gl_MultiTexCoord0.st).r;
|
||||
vec4 viewPosition = gl_ModelViewMatrix * (gl_Vertex + vec4(0.0, height, 0.0, 0.0));
|
||||
gl_Position = gl_ProjectionMatrix * viewPosition;
|
||||
|
||||
// generate the texture coordinates from the view position
|
||||
gl_TexCoord[0] = vec4(dot(viewPosition, gl_EyePlaneS[4]), dot(viewPosition, gl_EyePlaneT[4]), 0.0, 1.0);
|
||||
|
||||
// the zero height should be invisible
|
||||
gl_FrontColor = vec4(1.0, 1.0, 1.0, 1.0 - step(height, 0.0));
|
||||
}
|
|
@ -31,6 +31,10 @@ REGISTER_META_OBJECT(StaticModelRenderer)
|
|||
|
||||
static int bufferPointVectorMetaTypeId = qRegisterMetaType<BufferPointVector>();
|
||||
|
||||
MetavoxelSystem::MetavoxelSystem() :
|
||||
_cursorTexture(QOpenGLTexture::Target2D) {
|
||||
}
|
||||
|
||||
void MetavoxelSystem::init() {
|
||||
MetavoxelClientManager::init();
|
||||
DefaultMetavoxelRendererImplementation::init();
|
||||
|
@ -118,6 +122,105 @@ void MetavoxelSystem::render() {
|
|||
guideToAugmented(renderVisitor);
|
||||
}
|
||||
|
||||
class HeightfieldCursorRenderVisitor : public MetavoxelVisitor {
|
||||
public:
|
||||
|
||||
HeightfieldCursorRenderVisitor(const MetavoxelLOD& lod, const Box& bounds);
|
||||
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
|
||||
private:
|
||||
|
||||
Box _bounds;
|
||||
};
|
||||
|
||||
HeightfieldCursorRenderVisitor::HeightfieldCursorRenderVisitor(const MetavoxelLOD& lod, const Box& bounds) :
|
||||
MetavoxelVisitor(QVector<AttributePointer>() <<
|
||||
Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector<AttributePointer>(), lod),
|
||||
_bounds(bounds) {
|
||||
}
|
||||
|
||||
int HeightfieldCursorRenderVisitor::visit(MetavoxelInfo& info) {
|
||||
if (!info.getBounds().intersects(_bounds)) {
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
if (!info.isLeaf) {
|
||||
return DEFAULT_ORDER;
|
||||
}
|
||||
BufferDataPointer buffer = info.inputValues.at(0).getInlineValue<BufferDataPointer>();
|
||||
if (buffer) {
|
||||
buffer->render(true);
|
||||
}
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
|
||||
void MetavoxelSystem::renderHeightfieldCursor(const glm::vec3& position, float radius) {
|
||||
// create the cursor texture lazily
|
||||
if (!_cursorTexture.isCreated()) {
|
||||
const int CURSOR_TEXTURE_SIZE = 512;
|
||||
QImage cursorImage(CURSOR_TEXTURE_SIZE, CURSOR_TEXTURE_SIZE, QImage::Format_ARGB32_Premultiplied);
|
||||
cursorImage.fill(0x0);
|
||||
{
|
||||
QPainter painter(&cursorImage);
|
||||
const int ELLIPSE_EDGE = 10;
|
||||
const int OUTER_WIDTH = 10;
|
||||
QPen outerPen;
|
||||
outerPen.setWidth(OUTER_WIDTH);
|
||||
painter.setPen(outerPen);
|
||||
const int HALF_TEXTURE_SIZE = CURSOR_TEXTURE_SIZE / 2;
|
||||
painter.drawEllipse(QPoint(HALF_TEXTURE_SIZE, HALF_TEXTURE_SIZE), HALF_TEXTURE_SIZE - ELLIPSE_EDGE,
|
||||
HALF_TEXTURE_SIZE - ELLIPSE_EDGE);
|
||||
QPen innerPen(Qt::white);
|
||||
const int INNER_WIDTH = 6;
|
||||
innerPen.setWidth(INNER_WIDTH);
|
||||
painter.setPen(innerPen);
|
||||
painter.drawEllipse(QPoint(HALF_TEXTURE_SIZE, HALF_TEXTURE_SIZE), HALF_TEXTURE_SIZE - ELLIPSE_EDGE,
|
||||
HALF_TEXTURE_SIZE - ELLIPSE_EDGE);
|
||||
}
|
||||
_cursorTexture.setData(cursorImage, QOpenGLTexture::DontGenerateMipMaps);
|
||||
_cursorTexture.setWrapMode(QOpenGLTexture::ClampToEdge);
|
||||
_cursorTexture.setMinificationFilter(QOpenGLTexture::Linear);
|
||||
}
|
||||
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
glPolygonOffset(-1.0f, -1.0f);
|
||||
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
DefaultMetavoxelRendererImplementation::getHeightfieldCursorProgram().bind();
|
||||
|
||||
glActiveTexture(GL_TEXTURE4);
|
||||
float scale = 1.0f / radius;
|
||||
glm::vec4 sCoefficients(scale, 0.0f, 0.0f, 0.5f - scale * position.x);
|
||||
glm::vec4 tCoefficients(0.0f, 0.0f, scale, 0.5f - scale * position.z);
|
||||
glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&sCoefficients);
|
||||
glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&tCoefficients);
|
||||
|
||||
_cursorTexture.bind(1);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glm::vec3 extents(radius, radius, radius);
|
||||
HeightfieldCursorRenderVisitor visitor(getLOD(), Box(position - extents, position + extents));
|
||||
guideToAugmented(visitor);
|
||||
|
||||
_cursorTexture.release(1);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
DefaultMetavoxelRendererImplementation::getHeightfieldCursorProgram().release();
|
||||
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDepthFunc(GL_LESS);
|
||||
}
|
||||
|
||||
void MetavoxelSystem::deleteTextures(int heightID, int colorID) {
|
||||
glDeleteTextures(1, (GLuint*)&heightID);
|
||||
glDeleteTextures(1, (GLuint*)&colorID);
|
||||
|
@ -239,7 +342,7 @@ PointBuffer::PointBuffer(const BufferPointVector& points) :
|
|||
_points(points) {
|
||||
}
|
||||
|
||||
void PointBuffer::render() {
|
||||
void PointBuffer::render(bool cursor) {
|
||||
// initialize buffer, etc. on first render
|
||||
if (!_buffer.isCreated()) {
|
||||
_buffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
|
||||
|
@ -294,7 +397,7 @@ public:
|
|||
glm::vec3 vertex;
|
||||
};
|
||||
|
||||
void HeightfieldBuffer::render() {
|
||||
void HeightfieldBuffer::render(bool cursor) {
|
||||
// initialize textures, etc. on first render
|
||||
if (_heightTextureID == 0) {
|
||||
glGenTextures(1, &_heightTextureID);
|
||||
|
@ -385,17 +488,24 @@ void HeightfieldBuffer::render() {
|
|||
|
||||
glBindTexture(GL_TEXTURE_2D, _heightTextureID);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, _colorTextureID);
|
||||
int heightScaleLocation;
|
||||
if (cursor) {
|
||||
heightScaleLocation = DefaultMetavoxelRendererImplementation::getCursorHeightScaleLocation();
|
||||
} else {
|
||||
heightScaleLocation = DefaultMetavoxelRendererImplementation::getHeightScaleLocation();
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, _colorTextureID);
|
||||
}
|
||||
|
||||
DefaultMetavoxelRendererImplementation::getHeightfieldProgram().setUniformValue(
|
||||
DefaultMetavoxelRendererImplementation::getHeightScaleLocation(), 1.0f / _heightSize);
|
||||
DefaultMetavoxelRendererImplementation::getHeightfieldProgram().setUniformValue(heightScaleLocation, 1.0f / _heightSize);
|
||||
|
||||
glDrawRangeElements(GL_QUADS, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
if (!cursor) {
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glPopMatrix();
|
||||
|
@ -475,6 +585,18 @@ void DefaultMetavoxelRendererImplementation::init() {
|
|||
_heightfieldProgram.setUniformValue("diffuseMap", 1);
|
||||
_heightScaleLocation = _heightfieldProgram.uniformLocation("heightScale");
|
||||
_heightfieldProgram.release();
|
||||
|
||||
_heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +
|
||||
"shaders/metavoxel_heightfield_cursor.vert");
|
||||
_heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
|
||||
"shaders/metavoxel_heightfield_cursor.frag");
|
||||
_heightfieldCursorProgram.link();
|
||||
|
||||
_heightfieldCursorProgram.bind();
|
||||
_heightfieldCursorProgram.setUniformValue("heightMap", 0);
|
||||
_heightfieldCursorProgram.setUniformValue("cursorMap", 1);
|
||||
_cursorHeightScaleLocation = _heightfieldCursorProgram.uniformLocation("heightScale");
|
||||
_heightfieldCursorProgram.release();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -771,6 +893,8 @@ ProgramObject DefaultMetavoxelRendererImplementation::_pointProgram;
|
|||
int DefaultMetavoxelRendererImplementation::_pointScaleLocation;
|
||||
ProgramObject DefaultMetavoxelRendererImplementation::_heightfieldProgram;
|
||||
int DefaultMetavoxelRendererImplementation::_heightScaleLocation;
|
||||
ProgramObject DefaultMetavoxelRendererImplementation::_heightfieldCursorProgram;
|
||||
int DefaultMetavoxelRendererImplementation::_cursorHeightScaleLocation;
|
||||
|
||||
static void enableClipPlane(GLenum plane, float x, float y, float z, float w) {
|
||||
GLdouble coefficients[] = { x, y, z, w };
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <QList>
|
||||
#include <QOpenGLBuffer>
|
||||
#include <QOpenGLTexture>
|
||||
#include <QReadWriteLock>
|
||||
#include <QVector>
|
||||
|
||||
|
@ -31,6 +32,8 @@ class MetavoxelSystem : public MetavoxelClientManager {
|
|||
|
||||
public:
|
||||
|
||||
MetavoxelSystem();
|
||||
|
||||
virtual void init();
|
||||
|
||||
virtual MetavoxelLOD getLOD();
|
||||
|
@ -43,6 +46,8 @@ public:
|
|||
void simulate(float deltaTime);
|
||||
void render();
|
||||
|
||||
void renderHeightfieldCursor(const glm::vec3& position, float radius);
|
||||
|
||||
Q_INVOKABLE void deleteTextures(int heightID, int colorID);
|
||||
|
||||
protected:
|
||||
|
@ -59,6 +64,8 @@ private:
|
|||
MetavoxelLOD _lod;
|
||||
QReadWriteLock _lodLock;
|
||||
Frustum _frustum;
|
||||
|
||||
QOpenGLTexture _cursorTexture;
|
||||
};
|
||||
|
||||
/// Describes contents of a point in a point buffer.
|
||||
|
@ -105,7 +112,7 @@ public:
|
|||
|
||||
virtual ~BufferData();
|
||||
|
||||
virtual void render() = 0;
|
||||
virtual void render(bool cursor = false) = 0;
|
||||
};
|
||||
|
||||
typedef QExplicitlySharedDataPointer<BufferData> BufferDataPointer;
|
||||
|
@ -116,7 +123,7 @@ public:
|
|||
|
||||
PointBuffer(const BufferPointVector& points);
|
||||
|
||||
virtual void render();
|
||||
virtual void render(bool cursor = false);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -140,7 +147,7 @@ public:
|
|||
const QByteArray& getHeight() const { return _height; }
|
||||
const QByteArray& getColor() const { return _color; }
|
||||
|
||||
virtual void render();
|
||||
virtual void render(bool cursor = false);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -193,6 +200,9 @@ public:
|
|||
static ProgramObject& getHeightfieldProgram() { return _heightfieldProgram; }
|
||||
static int getHeightScaleLocation() { return _heightScaleLocation; }
|
||||
|
||||
static ProgramObject& getHeightfieldCursorProgram() { return _heightfieldCursorProgram; }
|
||||
static int getCursorHeightScaleLocation() { return _cursorHeightScaleLocation; }
|
||||
|
||||
Q_INVOKABLE DefaultMetavoxelRendererImplementation();
|
||||
|
||||
virtual void augment(MetavoxelData& data, const MetavoxelData& previous, MetavoxelInfo& info, const MetavoxelLOD& lod);
|
||||
|
@ -206,6 +216,9 @@ private:
|
|||
|
||||
static ProgramObject _heightfieldProgram;
|
||||
static int _heightScaleLocation;
|
||||
|
||||
static ProgramObject _heightfieldCursorProgram;
|
||||
static int _cursorHeightScaleLocation;
|
||||
};
|
||||
|
||||
/// Base class for spanner renderers; provides clipping.
|
||||
|
|
|
@ -1105,15 +1105,7 @@ void HeightfieldBrushTool::render() {
|
|||
return;
|
||||
}
|
||||
glm::vec3 point = origin + distance * direction;
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(point.x, point.y, point.z);
|
||||
|
||||
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
glutSolidSphere(1.0f, 8, 8);
|
||||
|
||||
glPopMatrix();
|
||||
Application::getInstance()->getMetavoxels()->renderHeightfieldCursor(point, _radius->value());
|
||||
}
|
||||
|
||||
HeightBrushTool::HeightBrushTool(MetavoxelEditor* editor) :
|
||||
|
|
|
@ -194,7 +194,8 @@ int RayHeightfieldIntersectionVisitor::visit(MetavoxelInfo& info, float distance
|
|||
glm::vec3 intersection = relativeEntry + planeDistance * _direction;
|
||||
if (intersection.x >= 0.0f && intersection.x <= 1.0f && intersection.z >= 0.0f && intersection.z <= 1.0f &&
|
||||
intersection.z >= intersection.x) {
|
||||
intersectionDistance = distance + (accumulatedDistance + planeDistance) * (info.size / highest);
|
||||
intersectionDistance = qMin(intersectionDistance, distance +
|
||||
(accumulatedDistance + planeDistance) * (info.size / highest));
|
||||
return SHORT_CIRCUIT;
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +208,8 @@ int RayHeightfieldIntersectionVisitor::visit(MetavoxelInfo& info, float distance
|
|||
glm::vec3 intersection = relativeEntry + planeDistance * _direction;
|
||||
if (intersection.x >= 0.0f && intersection.x <= 1.0f && intersection.z >= 0.0f && intersection.z <= 1.0f &&
|
||||
intersection.x >= intersection.z) {
|
||||
intersectionDistance = distance + (accumulatedDistance + planeDistance) * (info.size / highest);
|
||||
intersectionDistance = qMin(intersectionDistance, distance +
|
||||
(accumulatedDistance + planeDistance) * (info.size / highest));
|
||||
return SHORT_CIRCUIT;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue