Commit bbd65cd6 authored by Jan Möbius's avatar Jan Möbius
Browse files

Per face texturing works ... todo: sort textures to avoid rebinds

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@8476 383ad7c9-94d9-4d36-a494-682f7c89f535
parent 0003f630
......@@ -94,7 +94,9 @@ TriStripNodeT(Mesh& _mesh,
facePickingList_(0),
updateAnyPickingList_(true),
anyPickingBaseIndex_(0),
anyPickingList_(0)
anyPickingList_(0),
perFaceTextureIndexAvailable_(false),
textureMap_(0)
{
/// \todo : Handle vbo not supported
......@@ -181,6 +183,13 @@ availableDrawModes() const {
drawModes |= DrawModes::SOLID_TEXTURED_SHADED;
}
if ( perFaceTextureIndexAvailable_ ) {
drawModes |= DrawModes::SOLID_2DTEXTURED_FACE;
if (mesh_.has_face_normals())
drawModes |= DrawModes::SOLID_2DTEXTURED_FACE_SHADED;
}
return drawModes;
}
......@@ -377,6 +386,40 @@ draw(GLState& _state, unsigned int _drawMode) {
glDisable(GL_TEXTURE_2D);
}
// Textured by using coordinates stored in halfedges ... arrays generated by stripprocessor
if ( _drawMode & DrawModes::SOLID_2DTEXTURED_FACE )
{
glEnable(GL_TEXTURE_2D);
enable_arrays( PER_FACE_VERTEX_ARRAY | PER_FACE_TEXCOORD_ARRAY );
glDisable(GL_LIGHTING);
glShadeModel(GL_FLAT);
glDepthRange(0.01, 1.0);
draw_faces(PER_FACE);
glDepthRange(0.0, 1.0);
glDisable(GL_TEXTURE_2D);
}
// Textured by using coordinates stored in halfedges
if ( ( _drawMode & DrawModes::SOLID_2DTEXTURED_FACE_SHADED ) && mesh_.has_face_normals())
{
glEnable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
enable_arrays( PER_FACE_VERTEX_ARRAY | PER_FACE_TEXCOORD_ARRAY | PER_FACE_NORMAL_ARRAY );
glShadeModel(GL_FLAT);
glDepthRange(0.01, 1.0);
draw_faces(PER_FACE);
glDepthRange(0.0, 1.0);
glDisable(GL_TEXTURE_2D);
}
enable_arrays(0);
// Unbind all remaining buffers
......@@ -425,30 +468,56 @@ void
TriStripNodeT<Mesh>::
draw_faces(FaceMode _mode) {
if ( stripProcessor_.isValid() ) {
// If we have all properties per Vertex, we can render with index array from triangle strips!
if (_mode == PER_VERTEX) {
// Update strips if necessary
stripProcessor_.stripify();
typename StripProcessorT<Mesh>::StripsIterator strip_it = stripProcessor_.begin();
typename StripProcessorT<Mesh>::StripsIterator strip_last = stripProcessor_.end();
// If we have all properties per Vertex, we can render with index array from triangle strips!
if (_mode == PER_VERTEX) {
typename StripProcessorT<Mesh>::StripsIterator strip_it = stripProcessor_.begin();
typename StripProcessorT<Mesh>::StripsIterator strip_last = stripProcessor_.end();
for (; strip_it!=strip_last; ++strip_it) {
glDrawElements(GL_TRIANGLE_STRIP,
strip_it->indexArray.size(),
GL_UNSIGNED_INT,
&(strip_it->indexArray)[0] );
}
} else if ( _mode == PER_FACE ) {
if ( stripProcessor_.perFaceTextureIndexAvailable() && (textureMap_ != 0) ) {
int lastTexture = -1;
int texture = 0;
for (; strip_it!=strip_last; ++strip_it) {
if ( stripProcessor_.perFaceTextureIndexAvailable() )
std::cerr << "Todo : Set right texture before rendering this stip,Check for bound Arrays!" << std::endl;
for ( uint i = 0 ; i < stripProcessor_.textureRenderData()->size() ; ++i ) {
int texture = (*stripProcessor_.textureRenderData())[i].textureId;
if ( texture != lastTexture) {
if ( textureMap_->find(texture) == textureMap_->end() ) {
std::cerr << "Illegal texture index ... trying to access " << texture << std::endl;
lastTexture = -1;
continue;
}
glBindTexture( GL_TEXTURE_2D, (*textureMap_)[texture] );
lastTexture = texture;
}
glDrawElements(GL_TRIANGLE_STRIP,
strip_it->indexArray.size(),
GL_UNSIGNED_INT,
&(strip_it->indexArray)[0] );
// We need per face attributes so we have to use seperate vertices per face
glDrawArrays(GL_TRIANGLES, (*stripProcessor_.textureRenderData())[i].startOffset , (*stripProcessor_.textureRenderData())[i].faceCount * 3 );
}
} else if ( _mode == PER_FACE ) {
} else {
// We need per face attributes so we have to use seperate vertices per face
glDrawArrays(GL_TRIANGLES, 0, stripProcessor_.perFaceVertexBufferSize() );
}
} else {
std::cerr << "Error in draw Faces! No strip data available!" << std::endl;
}
}
template<class Mesh>
......@@ -688,6 +757,29 @@ enable_arrays(unsigned int _arrays) {
glDisableClientState(GL_COLOR_ARRAY);
}
//===================================================================
// per Face TexCoord Array
//===================================================================
// Check if we should enable the per face color array
if ( stripProcessor_.perFaceTextureCoordinateAvailable() && (_arrays & PER_FACE_TEXCOORD_ARRAY ) ) {
// Check if its already enabled
if (!(enabled_arrays_ & PER_FACE_TEXCOORD_ARRAY)) {
enabled_arrays_ |= PER_FACE_TEXCOORD_ARRAY;
// For this version we load the colors directly not from vbo
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glTexCoordPointer( stripProcessor_.perFacePerVertexTextureCoordBuffer() );
glEnableClientState(GL_TEXTURE_COORD_ARRAY );
}
} else if (enabled_arrays_ & PER_FACE_TEXCOORD_ARRAY) {
// Disable Texture Coordinate array
enabled_arrays_ &= ~PER_FACE_TEXCOORD_ARRAY;
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
//===================================================================
// Line Index Array
//===================================================================
......@@ -1264,8 +1356,8 @@ update_topology() {
// ==========================================================================
// Clear the strips and regenerate them!
// ==========================================================================
stripProcessor_.clear();
stripProcessor_.stripify();
// Mark strips as invalid to force an update
stripProcessor_.invalidateStrips();
// Set per face arrays to invalid as they have to be regenerated
stripProcessor_.invalidatePerFaceBuffers();
......@@ -1315,6 +1407,9 @@ void
TriStripNodeT<Mesh>::
setIndexPropertyName( std::string _indexPropertyName ) {
stripProcessor_.setIndexPropertyName(_indexPropertyName);
perFaceTextureIndexAvailable_ = stripProcessor_.perFaceTextureIndexAvailable();
};
template<class Mesh>
......
......@@ -491,16 +491,31 @@ public:
*/
void setHalfedgeTextcoordPropertyName( std::string _halfedgeTextcoordPropertyName );
public:
/** \brief Setup a mapping between internal texture ids on the mesh and the ids for the loaded textures in opengl
*
* @param _map maps between an int index stored in the Mesh describing which texture to use for a face,
* and the GluInt name of the texture bound by the TextureNode. \n
* If such a map is not available ( =0 ), assume TextureNode has already bound a texture
* And render without switching textures
*/
void setTextureMap( std::map< int, GLuint>* _map){ textureMap_ = _map; };
private:
/// This flag indicates if we have a per Face texture index property
bool perFaceTextureIndexAvailable_;
/// Mapping of mesh face texture indices to gltexture id ( has to be provided externally )
std::map< int, GLuint>* textureMap_;
/** @} */
/// \todo Remove all these functions afterwards!
public:
void set_texture_map( std::map< int, GLuint>* _map){ };
void set_property_map( std::map< int, std::string>* _map){ };
public:
void set_property_map( std::map< int, std::string>* _map){ };
......
......@@ -101,15 +101,6 @@ public:
ACG_CLASSNAME(MeshNode);
/** \brief Setup a mapping between internal texture ids on the mesh and the ids for the loaded textures in opengl
*
* @param _map maps between an int index stored in the Mesh describing which texture to use for a face,
* and the GluInt name of the texture bound by the TextureNode. \n
* If such a map is not available ( =0 ), assume TextureNode has already bound a texture
* And render without switching textures
*/
void set_texture_map( std::map< int, GLuint>* _map){ textureMap_ = _map; };
/** \brief Setup a mapping between internal texture ids on the mesh and the properties containing texture coordinates
*
* @param _map maps between an int index stored in the Mesh describing which texture to use
......@@ -163,8 +154,7 @@ private:
// Mapping of mesh face texture indices to gltexture id ( has to be provided externally )
std::map< int, GLuint>* textureMap_;
// Mapping of mesh face texture indices to coordinate property names ( has to be provided externally )
std::map< int, std::string>* propertyMap_;
......
......@@ -128,7 +128,7 @@ public:
* If such a map is not available ( =0 ), assume TextureNode has already bound a texture
* And render without switching textures
*/
void set_texture_map( std::map< int, GLuint>* _map){ textureMap_ = _map; };
void setTextureMap( std::map< int, GLuint>* _map){ textureMap_ = _map; };
/** \brief Setup a mapping between internal texture ids on the mesh and the properties containing texture coordinates
*
......
......@@ -128,12 +128,7 @@ availableDrawModes() const
drawModes |= DrawModes::SOLID_3DTEXTURED_SHADED;
}
if (mesh_.has_halfedge_texcoords2D())
{
drawModes |= DrawModes::SOLID_2DTEXTURED_FACE;
if (mesh_.has_face_normals())
drawModes |= DrawModes::SOLID_2DTEXTURED_FACE_SHADED;
}
return drawModes;
}
......@@ -295,33 +290,7 @@ draw(GLState& _state, unsigned int _drawMode)
glDisable(GL_TEXTURE_3D);
}
// Textured by using coordinates stored in halfedges
// TODO: Check not only mesh_.has_halfedge_texcoords2D but check if custom property is available
if ( ( _drawMode & DrawModes::SOLID_2DTEXTURED_FACE ) && mesh_.has_halfedge_texcoords2D())
{
glEnable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glShadeModel(GL_FLAT);
glDepthRange(0.01, 1.0);
draw_faces(FACE_HALFEDGE_TEXTURED);
glDepthRange(0.0, 1.0);
glDisable(GL_TEXTURE_2D);
}
// Textured by using coordinates stored in halfedges
// TODO: Check not only mesh_.has_halfedge_texcoords2D but check if custom property is available
if ( ( _drawMode & DrawModes::SOLID_2DTEXTURED_FACE_SHADED ) && mesh_.has_halfedge_texcoords2D() && mesh_.has_face_normals())
{
glEnable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
glShadeModel(GL_FLAT);
glDepthRange(0.01, 1.0);
draw_faces(FACE_HALFEDGE_TEXTURED);
glDepthRange(0.0, 1.0);
glDisable(GL_TEXTURE_2D);
}
// If in shader mode, just draw, as the shader has to be set by a shadernode above this node
if ( (_drawMode & DrawModes::SOLID_SHADER ) ) {
......
......@@ -66,6 +66,7 @@ template <class Mesh>
StripProcessorT<Mesh>::
StripProcessorT(Mesh& _mesh) :
mesh_(_mesh),
stripsValid_(false),
updatePerEdgeBuffers_(true),
updatePerFaceBuffers_(true),
textureIndexProperty_(-1),
......@@ -119,6 +120,11 @@ unsigned int
StripProcessorT<Mesh>::
stripify()
{
if ( stripsValid_)
return nStrips();
std::cerr << "Updating strips" << std::endl;
// preprocess: add new properties
mesh_.add_property( processed_ );
mesh_.add_property( used_ );
......@@ -133,6 +139,8 @@ stripify()
mesh_.remove_property(used_);
mesh_.release_face_status();
stripsValid_ = true;
return nStrips();
}
......@@ -525,7 +533,12 @@ buildStripTriMesh(typename Mesh::HalfedgeHandle _start_hh,
if ( perFaceTextureIndexAvailable() ) {
textureHandling = true;
_strip.textureIndex = mesh_.property(textureIndexProperty_,mesh_.face_handle(_start_hh));
}
std::cerr << "recorded strip texture : " << _strip.textureIndex << std::endl;
} else {
// Set to no texture!
// This is not really necessary but cleans up for debugging
_strip.textureIndex = 0;
}
/// \todo Implement texture processing here
......@@ -607,11 +620,13 @@ buildStripTriMesh(typename Mesh::HalfedgeHandle _start_hh,
if (flip) {
strip.push_front(strip.front());
faceMap.push_front(mesh_.face_handle(hh));
faceMap.push_front(mesh_.face_handle(0));
}
faceMap.push_front(mesh_.face_handle(hh));
faceMap.push_front(mesh_.face_handle(hh));
// Add two empty faces at the front. They will not be used to render anything as only the third one defines the
// face properties in the strip.
faceMap.push_front(mesh_.face_handle(0));
faceMap.push_front(mesh_.face_handle(0));
// copy final strip to _strip
_strip.indexArray.clear();
......@@ -709,6 +724,9 @@ template <class Mesh>
void
StripProcessorT<Mesh>::
updatePickingAny(ACG::GLState& _state ) {
// Update strip information if necessary
stripify();
updatePickingFaces(_state);
updatePickingEdges(_state,mesh_.n_faces());
updatePickingVertices(_state,mesh_.n_faces() + mesh_.n_edges());
......@@ -775,6 +793,8 @@ template <class Mesh>
void
StripProcessorT<Mesh>::
updatePerFaceBuffers() {
stripify();
// Only update buffers if they are invalid
if (!updatePerFaceBuffers_)
......@@ -808,8 +828,19 @@ updatePerFaceBuffers() {
else
perFaceTextureCoordArray_.clear();
textureRenderData_.clear();
if ( perFaceTextureIndexAvailable() )
textureRenderData_.reserve( strips_.size() );
// Process all strips
for ( unsigned int i = 0 ; i < strips_.size() ; ++i ) {
// Record strip information
if ( perFaceTextureIndexAvailable() ) {
textureRenderData_.push_back( TextureRenderInfo(strips_[i].textureIndex , strips_[ i ].indexArray.size() -2 ,bufferIndex) );
std::cerr << "Strip " << i << " texture " << strips_[i].textureIndex << " faces : " << strips_[ i ].indexArray.size() -2 << std::endl;
}
// The order of the vertices in the strip is alternating so we have to alter the directions as well
// or we get backfacing triangles although they are frontfacing
bool swap = true;
......@@ -821,7 +852,6 @@ updatePerFaceBuffers() {
// Handles and indices are collected during the strip generation.
for (unsigned int stripIndex = 2 ; stripIndex < strips_[ i ].indexArray.size() ; ++stripIndex) {
if ( mesh_.has_face_normals() ) {
const Vec3d normal = mesh_.normal( faceMaps_[i][ stripIndex ] );
perFaceNormalBuffer_[ bufferIndex + 0 ] = normal;
......@@ -847,7 +877,7 @@ updatePerFaceBuffers() {
for ( ; fhe_it ; ++fhe_it ) {
typename Mesh::VertexHandle cvh = mesh_.to_vertex_handle(fhe_it);
const Vec2f texcoord = mesh_.property(perFaceTextureCoordinateProperty_,fhe_it);
Vec2f texcoord = mesh_.property(perFaceTextureCoordinateProperty_,fhe_it);
if ( mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 2 ] ) == cvh ) {
perFaceTextureCoordArray_[ bufferIndex + 0 ] = texcoord;
......@@ -906,9 +936,11 @@ template <class Mesh>
ACG::Vec3f *
StripProcessorT<Mesh>::
perFaceVertexBuffer() {
// Force update of the buffers if required
if (updatePerFaceBuffers_)
updatePerFaceBuffers();
return &(perFaceVertexBuffer_)[0];
};
......@@ -919,6 +951,7 @@ perFaceNormalBuffer() {
// Force update of the buffers if required
if (updatePerFaceBuffers_)
updatePerFaceBuffers();
return &(perFaceNormalBuffer_)[0];
};
......@@ -959,6 +992,9 @@ setIndexPropertyName( std::string _indexPropertyName ) {
std::cerr << "StripProcessor: Unable to get per face texture Index property named " << _indexPropertyName << std::endl;
}
// mark strips as invalid ( have to be regenerated to collect texture index information)
stripsValid_ = false;
// mark the buffers as invalid as we have a new per face index array
invalidatePerFaceBuffers();
};
......
......@@ -87,6 +87,22 @@ public:
};
class TextureRenderInfo {
public:
TextureRenderInfo(int _textureId,int _faceCount,int _startOffset):
textureId(_textureId),
faceCount(_faceCount),
startOffset(_startOffset)
{};
/// Id of the texture to be rendered
int textureId;
/// Number of faces in the render step for this texture
int faceCount;
/// Start offset in the face buffer
int startOffset;
};
/** \class StripProcessorT StripProcessorT.hh <ACG/SceneGraph/StripProcessorT.hh>
......@@ -120,9 +136,6 @@ public:
/// returns number of strips
unsigned int nStrips() const { return strips_.size(); }
/// are strips computed?
bool isValid() const { return !strips_.empty(); }
/// Access strips
StripsIterator begin() const { return strips_.begin(); }
/// Access strips
......@@ -131,34 +144,8 @@ public:
private:
typedef std::vector<typename Mesh::FaceHandle> FaceHandles;
/// this method does the main work
void buildStrips();
/// This method generates strips for triangle meshes
void buildStripsTriMesh();
/** This method generates strips for polyMeshes meshes
*
* The strips generated in this function are triangle strips. The function
* takes arbitrary polygons as input and triangulates them.
*/
void buildStripsPolyMesh();
/// build a strip from a given halfedge (in both directions) of a triangle mesh
void buildStripTriMesh(typename Mesh::HalfedgeHandle _start_hh,
Strip& _strip,
FaceHandles& _faces,
FaceMap& _faceMap);
/// build a strip from a given halfedge (in both directions) of a polymesh
void buildStripPolyMesh(typename Mesh::HalfedgeHandle _start_hh,
Strip& _strip,
FaceHandles& _faces,
FaceMap& _faceMap);
/// Test whether face is convex
void convexityTest(FaceHandle _fh);
......@@ -180,6 +167,55 @@ private:
// This map contains for each vertex in the strips a handle to the face it closes
std::vector<FaceMap> faceMaps_;
//===========================================================================
/** @name Strip generation
* @{ */
//===========================================================================
public:
/** \brief Force a strip update
*
*
*/
void invalidateStrips() { stripsValid_ = false; };
private:
typedef std::vector<typename Mesh::FaceHandle> FaceHandles;
/// This flag shows if the strips have to be regenerated
bool stripsValid_;
/// this method does the main work
void buildStrips();
/// This method generates strips for triangle meshes
void buildStripsTriMesh();
/** This method generates strips for polyMeshes meshes
*
* The strips generated in this function are triangle strips. The function
* takes arbitrary polygons as input and triangulates them.
*/
void buildStripsPolyMesh();
/// build a strip from a given halfedge (in both directions) of a triangle mesh
void buildStripTriMesh(typename Mesh::HalfedgeHandle _start_hh,
Strip& _strip,
FaceHandles& _faces,
FaceMap& _faceMap);
/// build a strip from a given halfedge (in both directions) of a polymesh
void buildStripPolyMesh(typename Mesh::HalfedgeHandle _start_hh,
Strip& _strip,
FaceHandles& _faces,
FaceMap& _faceMap);
/** @} */
//===========================================================================
/** @name Per edge drawing arrays handling
* @{ */
......@@ -219,6 +255,7 @@ private:
/// This flag controls if an update is really necessary
bool updatePerEdgeBuffers_;
/** @} */
//===========================================================================
......@@ -442,6 +479,15 @@ public:
* This function will return a pointer to the first element of the buffer.
*/
ACG::Vec2f * perFacePerVertexTextureCoordBuffer(){ return &(perFaceTextureCoordArray_)[0]; };
/** \brief get rendering information for texture data
*
* This function returns a pointer to the texture render data produced by the stripprocessor
* each pair defines a texture index and te number of faces which have to be rendered for this
* texture before switching to the next one.
*
*/
std::vector< TextureRenderInfo >* textureRenderData(){ return &textureRenderData_; };
private:
......@@ -462,6 +508,8 @@ private:
OpenMesh::HPropHandleT< typename Mesh::TexCoord2D > perFaceTextureCoordinateProperty_;
std::vector< ACG::Vec2f > perFaceTextureCoordArray_;
std::vector< TextureRenderInfo > textureRenderData_;
/** @} */
......
Supports Markdown
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