Commit 67cb884a authored by Christopher Tenter's avatar Christopher Tenter

render polylines with colors

parent a87a8e5a
......@@ -663,7 +663,7 @@ void initializeDefaultDrawModes( void )
EDGES_COLORED. setDrawModeProperties(DrawModeProperties(PRIMITIVE_EDGE, LIGHTSTAGE_UNLIT, NORMAL_NONE, COLOR_PER_VERTEX));
WIREFRAME. setDrawModeProperties(DrawModeProperties(PRIMITIVE_EDGE));
EDGES_COLORED. setDrawModeProperties(DrawModeProperties(PRIMITIVE_EDGE, LIGHTSTAGE_UNLIT, NORMAL_NONE, COLOR_PER_VERTEX));
EDGES_COLORED. setDrawModeProperties(DrawModeProperties(PRIMITIVE_EDGE, LIGHTSTAGE_UNLIT, NORMAL_NONE, COLOR_PER_EDGE));
WIREFRAME. setDrawModeProperties(DrawModeProperties(PRIMITIVE_WIREFRAME));
......
......@@ -141,6 +141,7 @@ namespace DrawModes {
{
COLOR_NONE, /**< Use material colors only */
COLOR_PER_VERTEX, /**< Load per vertex colors and modulate with material color */
COLOR_PER_EDGE, /**< Load per edge colors and modulate with material color */
COLOR_PER_HALFEDGE, /**< Load per halfedge colors and modulate with material color */
COLOR_PER_FACE /**< Load per face colors and modulate with material color */
};
......
......@@ -92,7 +92,7 @@ PolyLineNodeT<PolyLine>::PolyLineNodeT(PolyLine& _pl, BaseNode* _parent, std::st
POINTS_SPHERES_SCREEN = DrawModes::DrawMode(ACG::SceneGraph::DrawModes::addDrawMode("Points (as Spheres, constant screen size)",
ACG::SceneGraph::DrawModes::DrawModeProperties(ACG::SceneGraph::DrawModes::PRIMITIVE_POLYGON,
ACG::SceneGraph::DrawModes::LIGHTSTAGE_SMOOTH,
ACG::SceneGraph::DrawModes::NORMAL_PER_VERTEX)));;
ACG::SceneGraph::DrawModes::NORMAL_PER_VERTEX)));
// Initial default draw mode
drawMode(DrawModes::WIREFRAME | DrawModes::POINTS );
......@@ -100,6 +100,14 @@ PolyLineNodeT<PolyLine>::PolyLineNodeT(PolyLine& _pl, BaseNode* _parent, std::st
//----------------------------------------------------------------------------
template <class PolyLine>
PolyLineNodeT<PolyLine>::~PolyLineNodeT()
{
delete sphere_;
}
//----------------------------------------------------------------------------
template <class PolyLine>
void
PolyLineNodeT<PolyLine>::
......@@ -121,7 +129,7 @@ DrawModes::DrawMode
PolyLineNodeT<PolyLine>::
availableDrawModes() const
{
return (DrawModes::WIREFRAME | DrawModes::POINTS | POINTS_SPHERES | POINTS_SPHERES_SCREEN );
return (DrawModes::WIREFRAME | DrawModes::POINTS | DrawModes::POINTS_COLORED | POINTS_SPHERES | POINTS_SPHERES_SCREEN | DrawModes::EDGES_COLORED);
}
......@@ -147,24 +155,13 @@ draw(GLState& _state, const DrawModes::DrawMode& _drawMode)
// Bind the vertex array
ACG::GLState::bindBuffer(GL_ARRAY_BUFFER_ARB, vbo_);
// We have to define the correct stride here, as the array ay be interleaved with normals
// or binormals
int stride = 0;
if ( polyline_.vertex_normals_available() )
stride = 24;
ACG::GLState::vertexPointer(3, GL_FLOAT , stride, 0);
ACG::GLState::enableClientState(GL_VERTEX_ARRAY);
ACG::Vec4f color = _state.ambient_color() + _state.diffuse_color();
// draw points
if (_drawMode & DrawModes::POINTS)
if (_drawMode & DrawModes::POINTS || _drawMode & DrawModes::POINTS_COLORED)
{
vertexDecl_.activateFixedFunction();
// draw selection
if( polyline_.vertex_selections_available() && !selectedVertexIndexBuffer_.empty())
{
......@@ -180,13 +177,25 @@ draw(GLState& _state, const DrawModes::DrawMode& _drawMode)
_state.set_color( color );
if (_drawMode & DrawModes::POINTS_COLORED)
{
vertexDecl_.deactivateFixedFunction();
vertexDeclVCol_.activateFixedFunction();
}
// Draw all vertices (don't care about selection)
glDrawArrays(GL_POINTS,0,polyline_.n_vertices());
glDrawArrays(GL_POINTS, 0, polyline_.n_vertices());
if (_drawMode & DrawModes::POINTS_COLORED)
vertexDeclVCol_.deactivateFixedFunction();
else
vertexDecl_.deactivateFixedFunction();
}
// draw line segments
if (_drawMode & DrawModes::WIREFRAME) {
vertexDecl_.activateFixedFunction();
// draw selection
if (polyline_.edge_selections_available() && !selectedEdgeIndexBuffer_.empty()) {
......@@ -207,6 +216,37 @@ draw(GLState& _state, const DrawModes::DrawMode& _drawMode)
else
glDrawArrays(GL_LINE_STRIP, 0, polyline_.n_vertices());
vertexDecl_.deactivateFixedFunction();
}
if (_drawMode & DrawModes::EDGES_COLORED) {
vertexDecl_.activateFixedFunction();
// draw selection
if (polyline_.edge_selections_available() && !selectedEdgeIndexBuffer_.empty()) {
// save old values
float line_width_old = _state.line_width();
_state.set_color(Vec4f(1, 0, 0, 1));
_state.set_line_width(2 * line_width_old);
glDrawElements(GL_LINES, selectedEdgeIndexBuffer_.size(), GL_UNSIGNED_INT, &(selectedEdgeIndexBuffer_[0]));
_state.set_line_width(line_width_old);
}
vertexDecl_.deactivateFixedFunction();
_state.set_color(color);
vertexDeclECol_.activateFixedFunction();
if (polyline_.is_closed())
glDrawArrays(GL_LINE_STRIP, 0, polyline_.n_vertices() + 1);
else
glDrawArrays(GL_LINE_STRIP, 0, polyline_.n_vertices());
vertexDeclECol_.deactivateFixedFunction();
}
......@@ -320,9 +360,6 @@ draw(GLState& _state, const DrawModes::DrawMode& _drawMode)
}
}
}
//----------------------------------------------------------------------------
......@@ -520,6 +557,59 @@ pick_edges( GLState& _state, unsigned int _offset)
//----------------------------------------------------------------------------
template <class PolyLine>
void
PolyLineNodeT<PolyLine>::
setupVertexDeclaration(VertexDeclaration* _dst, int _colorSource) const {
// Update the vertex declaration based on the input data:
_dst->clear();
// We always output vertex positions
_dst->addElement(GL_FLOAT, 3, ACG::VERTEX_USAGE_POSITION);
// current byte offset
size_t curOffset = 12;
// Use the normals if available
if (polyline_.vertex_normals_available())
{
_dst->addElement(GL_FLOAT, 3, ACG::VERTEX_USAGE_NORMAL, curOffset);
curOffset += 12;
}
// colors
if (polyline_.vertex_colors_available())
{
if (_colorSource == 1)
_dst->addElement(GL_UNSIGNED_BYTE, 4, ACG::VERTEX_USAGE_COLOR, curOffset);
curOffset += 4;
}
if (polyline_.edge_colors_available())
{
if (_colorSource == 2)
_dst->addElement(GL_UNSIGNED_BYTE, 4, ACG::VERTEX_USAGE_COLOR, curOffset);
curOffset += 4;
}
// Add custom vertex elements to declaration
for (size_t i = 0; i < customBuffers_.size(); ++i) {
ACG::VertexElement tmp = customBuffers_[i].first;
tmp.pointer_ = 0;
tmp.usage_ = ACG::VERTEX_USAGE_SHADER_INPUT;
tmp.setByteOffset(curOffset);
_dst->addElement(&tmp);
curOffset += VertexDeclaration::getElementSize(&tmp);
}
_dst->setVertexStride(curOffset);
}
//----------------------------------------------------------------------------
template <class PolyLine>
void
PolyLineNodeT<PolyLine>::
......@@ -557,30 +647,19 @@ updateVBO() {
}
// Update the vertex declaration based on the input data:
vertexDecl_.clear();
// We always output vertex positions
vertexDecl_.addElement(GL_FLOAT, 3, ACG::VERTEX_USAGE_POSITION);
// Use the normals if available
if ( polyline_.vertex_normals_available() )
vertexDecl_.addElement(GL_FLOAT, 3 , ACG::VERTEX_USAGE_NORMAL);
// Update vertex declarations
setupVertexDeclaration(&vertexDecl_, 0);
setupVertexDeclaration(&vertexDeclVCol_, 1);
setupVertexDeclaration(&vertexDeclECol_, 2);
// Add custom vertex elements to declaration
for (size_t i = 0; i < customBuffers_.size(); ++i) {
ACG::VertexElement tmp = customBuffers_[i].first;
tmp.pointer_ = 0;
tmp.usage_ = ACG::VERTEX_USAGE_SHADER_INPUT;
vertexDecl_.addElement(&tmp);
}
const unsigned int stride = vertexDecl_.getVertexStride();
// create vbo if it does not exist
if (!vbo_)
GLState::genBuffersARB(1, &vbo_);
// size in bytes of vbo, create additional vertex for closed loop indexing
unsigned int bufferSize = vertexDecl_.getVertexStride() * (polyline_.n_vertices() + 1);
unsigned int bufferSize = stride * (polyline_.n_vertices() + 1);
// Create the required array
char* vboData_ = new char[bufferSize];
......@@ -593,7 +672,7 @@ updateVBO() {
for (unsigned int i = 0 ; i < polyline_.n_vertices(); ++i) {
writeVertex(i, vboData_ + i * vertexDecl_.getVertexStride());
writeVertex(i, vboData_ + i * stride);
// Create an ibo in system memory for vertex selection
if ( polyline_.vertex_selections_available() && polyline_.vertex_selected(i) )
......@@ -608,7 +687,7 @@ updateVBO() {
}
// First point is added to the end for a closed loop
writeVertex(0, vboData_ + polyline_.n_vertices() * vertexDecl_.getVertexStride());
writeVertex(0, vboData_ + polyline_.n_vertices() * stride);
// Move data to the buffer in gpu memory
GLState::bindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_);
......@@ -623,6 +702,31 @@ updateVBO() {
//----------------------------------------------------------------------------
template <class PolyLine>
void
PolyLineNodeT<PolyLine>::
writeVertexColor(unsigned int _vertex, bool _colorSourceVertex, void* _dst) const
{
const VertexDeclaration* declToUse = _colorSourceVertex ? &vertexDeclVCol_ : &vertexDeclECol_;
unsigned int byteOffset = declToUse->findElementByUsage(VERTEX_USAGE_COLOR)->getByteOffset();
unsigned char* ucdata = ((unsigned char*)_dst) + byteOffset;
Point col = _colorSourceVertex ? polyline_.vertex_color(_vertex) : polyline_.edge_color(_vertex % polyline_.n_edges());
// rgb
for (int i = 0; i < 3; ++i)
{
// convert to normalized ubyte
int ival = int(col[i] * 255.0);
ival = std::min(std::max(ival, 0), 255);
ucdata[i] = ival;
}
ucdata[3] = 0xff; // alpha
}
//----------------------------------------------------------------------------
template <class PolyLine>
void
PolyLineNodeT<PolyLine>::
......@@ -640,30 +744,35 @@ writeVertex(unsigned int _vertex, void* _dst) {
for ( unsigned int j = 0 ; j < 3 ; ++j)
*(fdata++) = polyline_.vertex_normal(_vertex)[j];
// id offset of custom elements in the vertex declaration
unsigned int customElementOffset = 1;
if ( polyline_.vertex_normals_available() )
customElementOffset++;
if (polyline_.vertex_colors_available())
writeVertexColor(_vertex, true, _dst);
// copy custom data byte-wise
for (unsigned int i = 0; i < customBuffers_.size(); ++i) {
if (polyline_.edge_colors_available())
writeVertexColor(_vertex, false, _dst);
// element in custom input buffer
const ACG::VertexElement* veInput = &customBuffers_[i].first;
unsigned int elementInputStride = veInput->getByteOffset();
unsigned int elementSize = ACG::VertexDeclaration::getElementSize(veInput);
int customElementOffset = vertexDeclVCol_.findElementIdByUsage(VERTEX_USAGE_SHADER_INPUT);
if (!elementInputStride)
elementInputStride = elementSize;
if (customElementOffset >= 0)
{
// copy custom data byte-wise
for (unsigned int i = 0; i < customBuffers_.size(); ++i) {
// element in vertex buffer
const ACG::VertexElement* ve = vertexDecl_.getElement(i + customElementOffset);
// element in custom input buffer
const ACG::VertexElement* veInput = &customBuffers_[i].first;
unsigned int elementInputStride = veInput->getByteOffset();
unsigned int elementSize = ACG::VertexDeclaration::getElementSize(veInput);
const char* src = (const char*)customBuffers_[i].second;
if (!elementInputStride)
elementInputStride = elementSize;
memcpy((char*)_dst + ve->getByteOffset(), src + elementInputStride * _vertex, elementSize);
}
// element in vertex buffer
const ACG::VertexElement* ve = vertexDeclVCol_.getElement(i + static_cast<unsigned int>(customElementOffset));
const char* src = (const char*)customBuffers_[i].second;
memcpy((char*)_dst + ve->getByteOffset(), src + elementInputStride * _vertex, elementSize);
}
}
}
//----------------------------------------------------------------------------
......@@ -696,9 +805,6 @@ getRenderObjects(ACG::IRenderer* _renderer, ACG::GLState& _state , const ACG::S
// Set to the right vbo
ro.vertexBuffer = vbo_;
// decl must be static or member, renderer does not make a copy
ro.vertexDecl = &vertexDecl_;
// Set style
ro.debugName = "PolyLine";
ro.blending = false;
......@@ -718,6 +824,7 @@ getRenderObjects(ACG::IRenderer* _renderer, ACG::GLState& _state , const ACG::S
ro.setupShaderGenFromDrawmode(props);
ro.shaderDesc.shadeMode = SG_SHADE_UNLIT;
ro.vertexDecl = &vertexDecl_;
//---------------------------------------------------
// No lighting!
......@@ -726,7 +833,7 @@ getRenderObjects(ACG::IRenderer* _renderer, ACG::GLState& _state , const ACG::S
localMaterial.baseColor(defaultColor);
ro.setMaterial(&localMaterial);
switch (props->primitive()) {
case ACG::SceneGraph::DrawModes::PRIMITIVE_POINT:
......@@ -738,6 +845,9 @@ getRenderObjects(ACG::IRenderer* _renderer, ACG::GLState& _state , const ACG::S
// Point Size geometry shader
ro.setupPointRendering(_mat->pointSize(), screenSize);
// selection without colors
ro.shaderDesc.vertexColors = false;
if (!selectedVertexIndexBuffer_.empty())
{
......@@ -754,6 +864,13 @@ getRenderObjects(ACG::IRenderer* _renderer, ACG::GLState& _state , const ACG::S
ro.setMaterial(&localMaterial);
ro.glDrawArrays(GL_POINTS, 0, polyline_.n_vertices());
if (props->colored() && polyline_.vertex_colors_available())
{
ro.vertexDecl = &vertexDeclVCol_;
ro.shaderDesc.vertexColors = true;
}
// Point Size geometry shader
ro.setupPointRendering(_mat->pointSize(), screenSize);
......@@ -764,6 +881,7 @@ getRenderObjects(ACG::IRenderer* _renderer, ACG::GLState& _state , const ACG::S
break;
case ACG::SceneGraph::DrawModes::PRIMITIVE_WIREFRAME:
case ACG::SceneGraph::DrawModes::PRIMITIVE_EDGE:
// Render all edges which are selected via an index buffer
ro.debugName = "polyline.Wireframe.selected";
......@@ -773,6 +891,9 @@ getRenderObjects(ACG::IRenderer* _renderer, ACG::GLState& _state , const ACG::S
// Line Width geometry shader
ro.setupLineRendering(_state.line_width(), screenSize);
// selection without colors
ro.shaderDesc.vertexColors = false;
if (!selectedEdgeIndexBuffer_.empty())
{
ro.glDrawElements(GL_LINES, selectedEdgeIndexBuffer_.size(), GL_UNSIGNED_INT, &(selectedEdgeIndexBuffer_[0]));
......@@ -793,6 +914,12 @@ getRenderObjects(ACG::IRenderer* _renderer, ACG::GLState& _state , const ACG::S
else
ro.glDrawArrays(GL_LINE_STRIP, 0, polyline_.n_vertices());
if (props->colored() && polyline_.edge_colors_available())
{
ro.vertexDecl = &vertexDeclECol_;
ro.shaderDesc.vertexColors = true;
}
// Line Width geometry shader
ro.setupLineRendering(_state.line_width(), screenSize);
......
......@@ -102,7 +102,7 @@ public:
PolyLineNodeT(PolyLine& _pl, BaseNode* _parent = 0, std::string _name = "<PolyLineNode>");
/// Destructor
~PolyLineNodeT() {}
~PolyLineNodeT();
PolyLine& polyline() { return polyline_; }
......@@ -189,9 +189,15 @@ private:
/// Assignment operator (not used)
PolyLineNodeT& operator=(const PolyLineNodeT& _rhs);
/// Buffer organization
/// Vertex layout without vertex colors
ACG::VertexDeclaration vertexDecl_;
/// Vertex layout with vertex colors
ACG::VertexDeclaration vertexDeclVCol_;
/// Vertex layout with edge colors
ACG::VertexDeclaration vertexDeclECol_;
/// Custom vertex data for shader based rendering
std::vector< std::pair<ACG::VertexElement, const void*> > customBuffers_;
......@@ -205,6 +211,16 @@ private:
*/
void updateVBO();
/** \brief Create the vertex declaration
*
* The vertex data in the vbo contains both vertex and edge colors,
* so the vertex declaration decides which bytes to use for colored rendering (if any).
* @param _dst Vertex declaration to initialize
* @param _colorSource 0 - no colors, 1 - vertex colors, 2 - edge colors
*
*/
void setupVertexDeclaration(VertexDeclaration* _dst, int _colorSource) const;
/** \brief Write vertex data for rendering to a buffer
*
* @param _vertex index of polyline vertex
......@@ -212,6 +228,14 @@ private:
*/
void writeVertex(unsigned int _vertex, void* _dst);
/** \brief Write color for rendering to a buffer
*
* @param _vertex index of polyline vertex
* @param _colorSourceVertex vertex or edge color?
* @param _dst address of vertex in buffer
*/
void writeVertexColor(unsigned int _vertex, bool _colorSourceVertex, void* _dst) const;
private:
/// The associated poly line
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment