Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Heng Liu
OpenFlipper
Commits
7e51db75
Commit
7e51db75
authored
Apr 25, 2017
by
Martin Schultz
Browse files
Manually added changes from pre submodule merge request Faster Vertex
Update branch meshcompiler_fast_update
parent
8b1648d7
Changes
6
Hide whitespace changes
Inline
Side-by-side
libs_required/ACG/GL/DrawMesh.hh
View file @
7e51db75
...
...
@@ -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
*/
...
...
libs_required/ACG/GL/DrawMeshT.cc
View file @
7e51db75
...
...
@@ -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,15 @@ 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 +647,16 @@ 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
...
...
libs_required/ACG/GL/MeshCompiler.cc
View file @
7e51db75
...
...
@@ -1533,6 +1533,64 @@ void MeshCompiler::triangulate()
}
bool
MeshCompiler
::
reconstructTriangulation
(
int
_face
,
std
::
vector
<
int
>&
_triangulation
)
const
{
int
fsize
=
getFaceSize
(
_face
);
int
ftris
=
fsize
-
2
;
if
(
int
(
_triangulation
.
size
())
<
ftris
*
3
)
_triangulation
.
resize
(
ftris
*
3
);
if
(
fsize
==
3
)
{
// fast version for triangles
int
drawTriID
=
mapToDrawTriID
(
_face
);
// first vertex of the triangle
int
drawVertexID
=
mapToDrawVertexID
(
_face
,
0
);
// account for rotation in the index buffer
for
(
int
k
=
0
;
k
<
3
;
++
k
)
{
if
(
indices_
[
drawTriID
*
3
+
k
]
==
drawVertexID
)
{
_triangulation
[
k
]
=
0
;
_triangulation
[(
k
+
1
)
%
3
]
=
1
;
_triangulation
[(
k
+
2
)
%
3
]
=
2
;
return
true
;
}
}
return
false
;
}
else
{
// map from drawVertexID -> local corner id in face
std
::
map
<
int
,
int
>
cornerMap
;
// potential optimization: find better data structure to store this info
// init cornerMap
for
(
int
k
=
0
;
k
<
fsize
;
++
k
)
{
int
drawVertexID
=
mapToDrawVertexID
(
_face
,
k
);
cornerMap
[
drawVertexID
]
=
k
;
}
// use cornerMap for simple reconstruction
for
(
int
t
=
0
;
t
<
ftris
;
++
t
)
{
int
drawTriID
=
mapToDrawTriID
(
_face
,
t
);
for
(
int
k
=
0
;
k
<
3
;
++
k
)
{
// get vertexID from index buffer
int
drawVertexID
=
indices_
[
drawTriID
*
3
+
k
];
#ifdef _DEBUG
if
(
!
cornerMap
.
count
(
drawVertexID
))
{
std
::
cerr
<<
"error: MeshCompiler::reconstructTriangulation - invalid mappings for face "
<<
_face
<<
std
::
endl
;
return
false
;
}
#endif // _DEBUG
int
cornerID
=
cornerMap
[
drawVertexID
];
_triangulation
[
t
*
3
+
k
]
=
cornerID
;
}
}
}
return
true
;
}
void
MeshCompiler
::
resolveTriangulation
()
{
...
...
@@ -1893,7 +1951,96 @@ 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.
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
);
std
::
vector
<
char
>
vdata1
(
vstride
,
0
);
int
numReferencedVertices
=
numDrawVerts_
-
numIsolatedVerts_
;
int
numSplits
=
0
;
// keep references from vertexID -> (face, corner) as they are in mapToOriginalVertexID at the moment
for
(
int
faceID
=
0
;
faceID
<
numFaces_
;
++
faceID
)
{
int
fsize
=
getFaceSize
(
faceID
);
// only reconstruct triangulation when necessary
bool
triangulationReady
=
false
;
for
(
int
cornerID
=
0
;
cornerID
<
fsize
;
++
cornerID
)
{
int
vertexID
=
mapToDrawVertexID
(
faceID
,
cornerID
);
int
refFaceID
,
refCornerID
;
mapToOriginalVertexID
(
vertexID
,
refFaceID
,
refCornerID
);
if
(
faceID
!=
refFaceID
)
{
// this is a shared vertex
// compare vertex data with the reference
// get data of existing reference
getInputFaceVertexData
(
refFaceID
,
refCornerID
,
&
vdata0
[
0
]);
// get data of new vertex
getInputFaceVertexData
(
faceID
,
cornerID
,
&
vdata1
[
0
]);
if
(
!
vertexCompare_
->
equalVertex
(
&
vdata0
[
0
],
&
vdata1
[
0
],
&
decl_
))
{
// split
++
numSplits
;
// update mapToDrawVertexID:
const
int
newVertexID
=
numReferencedVertices
;
const
int
indexOffset
=
getInputIndexOffset
(
faceID
,
cornerID
);
faceBufSplit_
[
indexOffset
]
=
newVertexID
;
++
numReferencedVertices
;
numDrawVerts_
=
numReferencedVertices
+
numIsolatedVerts_
;
// update mapToOriginalVertexID:
// - this is done in createVertexMap() later
// update index buffer (indices_), which contains a triangulation of the polygon :
// 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
);
for
(
int
triCorner
=
0
;
triCorner
<
3
;
++
triCorner
)
{
int
triIndexOffset
=
drawTriID
*
3
+
triCorner
;
int
triVertex
=
indices_
[
triIndexOffset
];
if
(
triVertex
==
vertexID
)
{
// 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
}
}
}
}
if
(
numSplits
)
{
// fix isolated vertices
// resolve overlapping indices from the split vertices and isolates
numDrawVerts_
=
numReferencedVertices
;
// isolated vertices are fixed in createVertexMap()
// update vertex -> (face, corner) map
createVertexMap
(
numIsolatedVerts_
>
0
);
}
}
...
...
libs_required/ACG/GL/MeshCompiler.hh
View file @
7e51db75
...
...
@@ -513,6 +513,14 @@ public:
*/
void
build
(
bool
_weldVertices
=
false
,
bool
_optimizeVCache
=
true
,
bool
_needPerFaceAttribute
=
false
,
bool
_keepIsolatedVertices
=
false
);
/** \brief Fast update of vertices
*
* Use this if some attributes of vertices have changed, but the face topology is unchanged.
* This might introduce new vertex splits, which are added to the end of the vertex buffer.
* In that case the mappings are also updated.
*/
void
fastVertexUpdate
();
/** Get number of vertices in final buffer.
*/
int
getNumVertices
()
const
{
return
numDrawVerts_
;}
...
...
@@ -618,6 +626,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
;
/** @} */
...
...
widgets/optionsWidget/optionsWidget.cc
View file @
7e51db75
...
...
@@ -340,6 +340,8 @@ void OptionsWidget::showEvent ( QShowEvent * /*event*/ ) {
// debugging
slotDebugging
->
setChecked
(
OpenFlipper
::
Options
::
doSlotDebugging
());
fastVertexUpdate
->
setChecked
(
OpenFlipperSettings
().
value
(
"Core/Debug/FastVertexUpdate"
,
false
).
toBool
());
//keyBindings
initKeyTree
();
...
...
@@ -667,6 +669,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
++
){
...
...
widgets/optionsWidget/optionsWidget.ui
View file @
7e51db75
...
...
@@ -50,7 +50,7 @@
<string/>
</property>
<property
name=
"currentIndex"
>
<number>
0
</number>
<number>
1
</number>
</property>
<property
name=
"usesScrollButtons"
>
<bool>
true
</bool>
...
...
@@ -1773,6 +1773,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"
>
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment