Commit 29392f85 authored by Christopher Tenter's avatar Christopher Tenter
Browse files

add option to enable fast update in settings widget

parent 9b90d891
Pipeline #750 failed with stage
......@@ -293,6 +293,21 @@ public:
*/
void updateFull() {rebuild_ |= REBUILD_FULL;}
/** \brief enable fast update for vertex-only changes
*
* Updates after changing halfedge attributes might introduce new vertex splits.
* In that case the fast update mode adds these splits to the end of the vbo.
* This might introduce more splits than necessary in favor for speed.
*
*/
void enableFastVertexUpdate() { enableFastVertexUpdate_ = true; }
/** \brief disable fast update for vertex-only changes
*
* Do a full rebuild if per halfedge attributes are changed.
*/
void disableFastVertexUpdate() { enableFastVertexUpdate_ = false; }
/** \brief returns the number of used textured of this mesh
*
* @return Number of different textures used in the mesh
......@@ -828,6 +843,9 @@ private:
/// hint on what to rebuild
unsigned int rebuild_;
/// fast updates are possible at the cost of potentially more splits
bool enableFastVertexUpdate_;
/** used to track mesh changes, that require a full rebuild
* values directly taken from Mesh template
*/
......
......@@ -81,6 +81,7 @@ template <class Mesh>
DrawMeshT<Mesh>::DrawMeshT(Mesh& _mesh)
: mesh_(_mesh),
rebuild_(REBUILD_NONE),
enableFastVertexUpdate_(false),
prevNumFaces_(0), prevNumVerts_(0),
colorMode_(1),
curVBOColorMode_(1),
......@@ -542,9 +543,14 @@ DrawMeshT<Mesh>::rebuild()
}
// full rebuild:
delete meshComp_;
meshComp_ = new MeshCompiler(*vertexDecl_);
bool doFastUpdate = !(rebuild_ & (REBUILD_TOPOLOGY | REBUILD_FULL)) && enableFastVertexUpdate_ && meshComp_ != 0;
if (!doFastUpdate)
{
// full rebuild:
delete meshComp_;
meshComp_ = new MeshCompiler(*vertexDecl_);
}
// search for convenient attribute indices
......@@ -640,8 +646,17 @@ DrawMeshT<Mesh>::rebuild()
}
// compile draw buffers
meshComp_->build(true, true, true, true);
if (doFastUpdate)
{
// just update vertices
meshComp_->fastVertexUpdate();
}
else
{
// compile draw buffers
meshComp_->build(true, true, true, true);
}
// create inverse vertex map
......
......@@ -1539,7 +1539,7 @@ bool MeshCompiler::reconstructTriangulation(int _face, std::vector<int>& _triang
int fsize = getFaceSize(_face);
int ftris = fsize - 2;
if (int(_triangulation.size() < ftris) * 3)
if (int(_triangulation.size()) < ftris * 3)
_triangulation.resize(ftris * 3);
if (fsize == 3)
......@@ -1930,24 +1930,23 @@ void MeshCompiler::build(bool _weldVertices, bool _optimizeVCache, bool _needPer
void MeshCompiler::fastVertexUpdate()
{
/*
basic idea:
Check if the current index mapping for each (face, corner) has conflicting vertex data.
Resolve conflicts by adding new split vertices at the end of the vbo.
1. alloc vertex array that stores which (face, corner) is using it. init to all 0 (unused)
2. for each face and each corner
vertexID = mapToDrawVertex(face, corner);
if (unused[vertexID])
writeVertexData(vertexID, face, corner)
else
char oldVertexData[] = getVertexDataFromVBO(vertexID)
char newVertexData[] = getInputVertexData(face, corner)
if (!compareVertex(oldVertexData, newVertexData))
add new vertex // might be optimized to reduce split count.
// use VertexSplitter to check if there is no previous split with the same vertex data
update mappings
The mapping given by mapToOriginalVertexID is not changed for all old vertices.
Those (face, corner) pairs that make use of the vertex but aren't returned by mapToOriginalVertexID,
will have new vertex ids if there is a conflict.
Conflicts are found by comparing full vertex data.
*/
// potential optimizations:
// - let user provide vbo data instead of querying it with getInputFaceVertexData (bottleneck)
// - skip comparison of position elements for each vertex
// memory storage for comparing two vertices
int vstride = getVertexDeclaration()->getVertexStride();
std::vector<char> vdata0(vstride, 0);
......@@ -1958,9 +1957,6 @@ void MeshCompiler::fastVertexUpdate()
int numSplits = 0;
// alloc buffer to store the triangulation of a polygon
std::vector<int> triangulation((maxFaceSize_ - 2) * 3);
// keep references from vertexID -> (face, corner) as they are in mapToOriginalVertexID at the moment
for (int faceID = 0; faceID < numFaces_; ++faceID)
......@@ -2005,52 +2001,13 @@ void MeshCompiler::fastVertexUpdate()
// - this is done in createVertexMap() later
// update indices_ :
// need to know which indices are associated with the (face, corner)
// -> there might be more than one!
// this is no easy task because of the triangulation of n-polys
// might have to precompute this information somehow
// mapToDrawTriID();
// if (!triangulationReady)
// {
// if (!reconstructTriangulation(faceID, triangulation))
// {
// std::cerr << "error: MeshCompiler::partialVertexUpdate() can't reconstruct triangulation for face " << faceID << std::endl;
//
// // todo: error handling and rollback
// }
// else
// triangulationReady = true;
// }
//
//
// // compute mapping corner -> index offsets into ibo
//
// // there is probably a better solution than doing a linear search in the triangulation here
// for (int tri = 0; tri < fsize - 2; ++tri)
// {
// for (int triCorner = 0; triCorner < 3; ++triCorner)
// {
// int triFaceCorner = triangulation[tri * 3 + triCorner];
//
// if (triFaceCorner == cornerID)
// {
// int drawTriID = mapToDrawTriID(faceID, tri);
//
// // offset into index buffer of the corner of the triangle
// int triFaceCornerOffset = drawTriID * 3 + triCorner;
//
// assert(indices_[triFaceCornerOffset] == vertexID);
// indices_[triFaceCornerOffset] = ;
// }
// }
// }
// update index buffer (indices_), which contains a triangulation of the polygon :
// without reconstructing the triangulation:
// the current (face, corner) vertex might have multiple instances!
// this depends on the triangulation result
// search for these instances without reconstructing the triangulation
int numChangedIndices = 0;
for (int tri = 0; tri < fsize - 2; ++tri)
{
int drawTriID = mapToDrawTriID(faceID, tri);
......@@ -2064,10 +2021,15 @@ void MeshCompiler::fastVertexUpdate()
{
// change index to to new split vertex
indices_[triIndexOffset] = newVertexID;
++numChangedIndices;
}
}
}
#ifdef _DEBUG
if (!numChangedIndices)
std::cout << "error: MeshCompiler::fastVertexUpdate - failed to update index buffer with new split id" << std::endl;
#endif
}
}
}
......
......@@ -628,6 +628,16 @@ public:
*/
int getIndex(int _i) const;
/** Get the triangulation of a face
*
* The triangulation is an array of 3 local corner ids for each triangle of the face.
* This data is not directly available, but has to be reconstructed from the final index buffer.
* This is done by matching the vertex ids with the (face, corner) mapping, so there is some overhead.
* @param _face face ID in input data
* @param _triangulation target buffer receiving the triangulation
* @return report if matching was successful
*/
bool reconstructTriangulation(int _face, std::vector<int>& _triangulation) const;
/** @} */
......@@ -1027,10 +1037,6 @@ private:
// resolve triangulation
void resolveTriangulation();
// reconstruct triangulation of a face from the final index buffer.
// the triangulation is an array of 3 local corner ids for each triangle of the face.
bool reconstructTriangulation(int _face, std::vector<int>& _triangulation) const;
// sort input faces by group ids
void sortFacesByGroup();
......
......@@ -221,6 +221,15 @@
meshNode_ = new ACG::SceneGraph::MeshNodeT<MeshT>(*mesh_, shaderNode_, "NEW MeshNode");
if (meshNode_->getDrawMesh())
{
bool fastUpdate = OpenFlipperSettings().value("Core/Debug/FastVertexUpdate", false).toBool();
if (fastUpdate)
meshNode_->getDrawMesh()->enableFastVertexUpdate();
else
meshNode_->getDrawMesh()->disableFastVertexUpdate();
}
QString shaderDir = OpenFlipper::Options::shaderDirStr() + OpenFlipper::Options::dirSeparator();
std::string shaderDirectory = std::string( shaderDir.toUtf8() );
......
......@@ -341,6 +341,8 @@ void OptionsWidget::showEvent ( QShowEvent * /*event*/ ) {
// debugging
slotDebugging->setChecked(OpenFlipper::Options::doSlotDebugging());
fastVertexUpdate->setChecked(OpenFlipperSettings().value("Core/Debug/FastVertexUpdate", false).toBool());
//keyBindings
initKeyTree();
......@@ -666,6 +668,7 @@ void OptionsWidget::slotApply() {
// Debugging
OpenFlipper::Options::doSlotDebugging(slotDebugging->isChecked());
OpenFlipperSettings().setValue("Core/Debug/FastVertexUpdate", fastVertexUpdate->isChecked());
//viewer defaults
for (int i=0; i < PluginFunctions::viewers(); i++){
......
......@@ -50,7 +50,7 @@
<string/>
</property>
<property name="currentIndex">
<number>1</number>
<number>0</number>
</property>
<property name="usesScrollButtons">
<bool>true</bool>
......@@ -1744,6 +1744,13 @@ p, li { white-space: pre-wrap; }
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="fastVertexUpdate">
<property name="text">
<string>Enable Fast Vertex Update (experimental)</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
......
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