Commit 2bb6f70e authored by Christopher Tenter's avatar Christopher Tenter

added custom vertex elements in PolyLineNode refs #2244

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@19303 383ad7c9-94d9-4d36-a494-682f7c89f535
parent 365bdb93
......@@ -528,26 +528,21 @@ updateVBO() {
if ( polyline_.vertex_normals_available() )
vertexDecl_.addElement(GL_FLOAT, 3 , ACG::VERTEX_USAGE_NORMAL);
// Add custom vertex elements to declaration
for (size_t i = 0; i < customBuffers_.size(); ++i) {
const ACG::VertexElement* ve = &customBuffers_[i].first;
vertexDecl_.addElement(ve->type_, ve->numElements_, ACG::VERTEX_USAGE_SHADER_INPUT, 0u, ve->shaderInputName_);
}
// create vbo if it does not exist
if (!vbo_)
GLState::genBuffersARB(1, &vbo_);
// Temporary float array we need to convert doubles to this type
float* vboData_ = NULL;
// size in bytes of vbo, create additional vertex for closed loop indexing
unsigned int bufferSize = vertexDecl_.getVertexStride() * (polyline_.n_vertices() + 1);
// Number of points in buffer (Initialized without normals)
unsigned int bufferPoints = polyline_.n_vertices() + 1;
// We need twice as much space, as we need to store the normals along with the points
if ( polyline_.vertex_normals_available() )
bufferPoints *= 2;
// Create the required array ( 3 coordinates of 4 floats per vertex )
// First vertex is replicated for closed loop polylines
vboData_ = new float[3 * (bufferPoints) * 4];
// Pointer to it for easier copy operation
float* pBuffer = &vboData_[0];
// Create the required array
char* vboData_ = new char[bufferSize];
// Index buffer for selected vertices
selectedVertexIndexBuffer_.clear();
......@@ -557,14 +552,7 @@ updateVBO() {
for (unsigned int i = 0 ; i < polyline_.n_vertices(); ++i) {
// Copy from internal storage to VBO in CPU memory
for ( unsigned int j = 0 ; j < 3 ; ++j)
*(pBuffer++) = polyline_.point(i)[j];
// Also write normal into buffer if available
if ( polyline_.vertex_normals_available() )
for ( unsigned int j = 0 ; j < 3 ; ++j)
*(pBuffer++) = polyline_.vertex_normal(i)[j];
writeVertex(i, vboData_ + i * vertexDecl_.getVertexStride());
// Create an ibo in system memory for vertex selection
if ( polyline_.vertex_selections_available() && polyline_.vertex_selected(i) )
......@@ -579,17 +567,11 @@ updateVBO() {
}
// First point is added to the end for a closed loop
for ( unsigned int j = 0 ; j < 3 ; ++j)
*(pBuffer++) = polyline_.point(0)[j];
// First normal is added to the end for a closed loop
if ( polyline_.vertex_normals_available() )
for ( unsigned int j = 0 ; j < 3 ; ++j)
*(pBuffer++) = polyline_.vertex_normal(0)[j];
writeVertex(0, vboData_ + polyline_.n_vertices() * vertexDecl_.getVertexStride());
// Move data to the buffer in gpu memory
GLState::bindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_);
GLState::bufferDataARB(GL_ARRAY_BUFFER_ARB, 3 * bufferPoints * 4 , vboData_ , GL_STATIC_DRAW_ARB);
GLState::bufferDataARB(GL_ARRAY_BUFFER_ARB, bufferSize , vboData_ , GL_STATIC_DRAW_ARB);
// Remove the local storage
delete[] vboData_;
......@@ -600,6 +582,51 @@ updateVBO() {
//----------------------------------------------------------------------------
template <class PolyLine>
void
PolyLineNodeT<PolyLine>::
writeVertex(unsigned int _vertex, void* _dst) {
// position and normal in float
float* fdata = (float*)_dst;
// Copy from internal storage to VBO in CPU memory
for ( unsigned int j = 0 ; j < 3 ; ++j)
*(fdata++) = polyline_.point(_vertex)[j];
// Also write normal into buffer if available
if ( polyline_.vertex_normals_available() )
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++;
// copy custom data byte-wise
for (unsigned int i = 0; i < customBuffers_.size(); ++i) {
// element in custom input buffer
const ACG::VertexElement* veInput = &customBuffers_[i].first;
unsigned int elementInputStride = veInput->getByteOffset();
unsigned int elementSize = ACG::VertexDeclaration::getElementSize(veInput);
if (!elementInputStride)
elementInputStride = elementSize;
// element in vertex buffer
const ACG::VertexElement* ve = vertexDecl_.getElement(i + customElementOffset);
const char* src = (const char*)customBuffers_[i].second;
memcpy((char*)_dst + ve->getByteOffset(), src + elementInputStride * _vertex, elementSize);
}
}
//----------------------------------------------------------------------------
template <class PolyLine>
void
PolyLineNodeT<PolyLine>::
......@@ -621,6 +648,7 @@ getRenderObjects(ACG::IRenderer* _renderer, ACG::GLState& _state , const ACG::S
// draw after scene-meshes
ro.priority = 1;
// Update the vbo only if required.
if ( updateVBO_ )
updateVBO();
......@@ -735,6 +763,7 @@ getRenderObjects(ACG::IRenderer* _renderer, ACG::GLState& _state , const ACG::S
// Line Width geometry shader
ro.shaderDesc.geometryTemplateFile = geomTemplateLineWidth;
ro.setUniform("screenSize", Vec2f((float)_state.viewport_width(), (float)_state.viewport_height()));
ro.setUniform("lineWidth", _state.line_width());
......@@ -749,6 +778,36 @@ getRenderObjects(ACG::IRenderer* _renderer, ACG::GLState& _state , const ACG::S
}
//----------------------------------------------------------------------------
template <class PolyLine>
int
PolyLineNodeT<PolyLine>::
addCustomBuffer( const ACG::VertexElement& _desc, const void* _buffer) {
if (_buffer) {
customBuffers_.push_back( std::pair<ACG::VertexElement, const void*>(_desc, _buffer) );
update();
return int(customBuffers_.size()-1);
}
else
{
std::cerr << "PolyLineNodeT::addCustomBuffer - null pointer buffer" << std::endl;
return -1;
}
}
//----------------------------------------------------------------------------
template <class PolyLine>
void
PolyLineNodeT<PolyLine>::
setCustomBuffer( int _id, const void* _buffer) {
customBuffers_[_id].second = _buffer;
update();
}
//=============================================================================
} // namespace SceneGraph
......
......@@ -126,6 +126,49 @@ public:
/// Trigger an update of the vbo
void update() { updateVBO_ = true; };
/** Add custom data to the vertex buffer for rendering with shaders
*
* The element description declares the type of data and the name in the shader.
* The provided buffer has to store data for each vertex: num elements in buffer = polyline().n_vertices()
* If the stride offset in _desc.pointer_ is 0, it is assumed that the buffer stores the data without memory alignment.
* This function does not create a local copy of the buffer, so the provided memory address
* has to be valid whenever an internal vbo update is triggered.
* Custom attributes are then available in the vertex shader by accessing the input with name tangentElement.shaderInputName_.
*
* Example:
*
* in plugin:
* have allocated buffer: tangentData_ of type Vec3f* (member of a class)
*
* ACG::VertexElement tangentDesc;
* tangentDesc.type_ = GL_FLOAT;
* tangentDesc.numElements_ = 3;
* tangentDesc.usage_ = ACG::VERTEX_USAGE_USER_DEFINED;
* tangentDesc.shaderInputName_ = "myTangent";
* tangentDesc.pointer_ = 0;
*
* polylineNode->addCustomBuffer(tangentDesc, tangentData_);
*
* in vertex shader:
* in vec3 myTangent;
* ..
*
*
* @param _desc type description of an element in the buffer
* @param _buffer pointer to data buffer, has to be a valid address for the remaining time
* @return id of custom buffer
*/
int addCustomBuffer(const ACG::VertexElement& _desc, const void* _buffer);
/** Update pointer to custom data
*
* @param _id id of the custom buffer; return value of addCustomBuffer
* @param _buffer pointer to data buffer, has to be a valid address for the remaining time
*/
void setCustomBuffer(int _id, const void* _buffer);
private:
void pick_vertices ( GLState& _state );
......@@ -142,6 +185,9 @@ private:
/// Buffer organization
ACG::VertexDeclaration vertexDecl_;
/// Custom vertex data for shader based rendering
std::vector< std::pair<ACG::VertexElement, const void*> > customBuffers_;
/** \brief Trigger an update of the vbo
*
* If the polyLine is changed, you have to call this function to update the buffers.
......@@ -149,6 +195,13 @@ private:
*/
void updateVBO();
/** \brief Write vertex data for rendering to a buffer
*
* @param _vertex index of polyline vertex
* @param _dst address of vertex in buffer
*/
void writeVertex(unsigned int _vertex, void* _dst);
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