The joy of computer graphics programming

Bruno Levy
Bruno LevySenior researcher, chargé de mission à INRIA Saclay / Laboratoire de Mathématiques d'Orsay
Mathématiques - Informatique
Eurographics 2017
Bruno Lévy
ALICE Géométrie & Lumière
CENTRE INRIA Nancy Grand-Est
The Joy of
Computer Graphics Programming
Bruno Lévy, Inria researcher
Introducing myself…
First name: Bruno
Familly name: Lévy
Age: approaching 45
Occupation: Inria ALICE team lead (since 2004)
ALICE = Geometry processing + Fabrication (S. Lefebvre)
Research: navigating between graphics, math. and physics
Code: open-source (geogram),commercial (GOCAD, Vorpaline)
Introducing myself…
First name: Bruno
Familly name: Lévy
Age: approaching 45 (born in 1972 = 4004+1)
Occupation: Inria ALICE team lead (since 2004)
ALICE = Geometry processing + Fabrication (S. Lefebvre)
Research: navigating between graphics, math. and physics
Code: open-source (geogram),commercial (GOCAD, Vorpaline)
OVERVIEW
1. Introduction, let s talk about programming
2. Graphics: eye candy with GLUP
3. Numerics: cranking the number cruncher
4. Geometry: predicates without the agonizing pain
What s next ? Physics+Mathematics+Computing=?
Introduction
1
Part. 1 On Software Design
War stories on the design and implementation
of geogram, graphite and vorpaline
Part. 1 On Software Design
War stories on the design and implementation
of geogram, graphite and vorpaline
Documented open-source* implementations of reference algos.
+ the most important results from my group (2000 to 2017)
Algorithms from >20 research articles
and two ERC projects (GOODSHAPE and VORPALINE)
*Geogram (BSD) and Graphite (GLP), Vorpaline is proprietary
Part. 1 On Software Design
War stories on the design and implementation
of geogram, graphite and vorpaline
Documented open-source* implementations of reference algos.,
+ the most important results from my group (2000 to 2017)
Algorithms from >20 research articles
and two ERC projects (GOODSHAPE and VORPALINE)
•Mesh parameterization (LSCM, ABF++, PGP)
•Spectral mesh processing (Manifold Harmonics)
•Newton Centroidal Voronoi Tesselation (surfaces and volumes)
•Remeshing, reconstruction, Optimal Transport
•Low-level algorithms (Delaunay, Voronoi, predicates) …
*Geogram (BSD) and Graphite (GLP), Vorpaline is proprietary
Part. 1 On Software Design
From my attic: my first computer !
Part. 1 On Software Design
1979 Apple ][
6502 processor, 1MHz
64Kb RAM
Approx. 10 FLOPs
Part. 1 On Software Design
1979 Apple ][
6502 processor, 1MHz
64Kb RAM
Approx. 10 FLOPs
2017 PC
Core i7 gen3, 3 GHz
16Gb RAM
Approx. 100 GFLOPs
Part. 1 On Software Design
1979 Apple ][
6502 processor, 1MHz
64Kb RAM
Approx. 10 FLOPs
2017 PC
Core i7 gen3, 3 GHz
16Gb RAM
Approx. 100 GFLOPs
X 1 million !!!!
38 years
Part. 1 On Software Design
Boots in 20 seconds Boots in 3 minutes
Part. 1 On Software Design
Boots in 20 seconds Boots in 3 minutes
Where did the 1 million acceleration factor go ?
Part. 1 On Software Design
What can you do in 20 seconds ?
3 GHz, 4 cores = 240 billions instructions !!
Part. 1 On Software Design
If you cannot do the job in less than 20 seconds
on a modern PC, then there is probably a
problem somewhere
What can you do in 20 seconds ?
3 GHz, 4 cores = 240 billions instructions !!
Part. 1 On Software Design
Boots in 20 seconds Boots in 3 minutes
Where did the 1 million acceleration factor go ?
- Lost in abstraction -
Part. 1 On Software Design
Abstraction in Programming:
+ Separates concepts
+ Separates specification from Implementation
Part. 1 On Software Design
Abstraction in Programming:
+ Separates concepts
+ Separates specification from Implementation
- Sometimes separates things
that should be considered together !!
Part. 1 On Software Design
Background on Futuristic Programming
Paul Haeberli - 1994
www.graficaobscura.com/future/index.html
Part. 1 On Software Design
Background on Futuristic Programming
Paul Haeberli - 1994
Part. 1 On Software Design
Futuristic Programming Priorities
Paul Haeberli - 1994
1. It is something that has NEVER BEEN DONE BEFORE.
2. The USER LIKES to use the program.
3. The program is as FAST as it can be.
4. The program is as SMALL as it can be.
5. The program is BUG-FREE.
6. The program needs NO USER MAINTENANCE.
7. The program requires NO USER DOCUMENTATION.
8. The program requires NO SYSTEM ADMINISTRATOR
Part. 1 On Software Design
Geogram/Graphite Programming Priorities
1. Make it as simple as possible (but not simpler)
Part. 1 On Software Design
1. Make it as simple as possible (but not simpler)
2. Make it as easy to use as possible
Geogram/Graphite Programming Priorities
Part. 1 On Software Design
1. Make it as simple as possible (but not simpler)
2. Make it as easy to use as possible
3. Make it as easy to compile as possible
Geogram/Graphite Programming Priorities
Part. 1 On Software Design
1. Make it as simple as possible (but not simpler)
2. Make it as easy to use as possible
3. Make it as easy to compile as possible
4. Maximize speed
Geogram/Graphite Programming Priorities
Part. 1 On Software Design
1. Make it as simple as possible (but not simpler)
2. Make it as easy to use as possible
3. Make it as easy to compile as possible
4. Maximize speed
5. Minimize memory consumption
Geogram/Graphite Programming Priorities
Part. 1 On Software Design
1. Make it as simple as possible (but not simpler)
2. Make it as easy to use as possible
3. Make it as easy to compile as possible
4. Maximize speed
5. Minimize memory consumption
6. Minimize number of lines of code
Geogram/Graphite Programming Priorities
Part. 1 On Software Design
1. Make it as simple as possible (but not simpler)
2. Make it as easy to use as possible
3. Make it as easy to compile as possible
4. Maximize speed
5. Minimize memory consumption
6. Minimize number of lines of code
7. Minimize number of C++ classes
Geogram/Graphite Programming Priorities
Part. 1 On Software Design
1. Make it as simple as possible (but not simpler)
2. Make it as easy to use as possible
3. Make it as easy to compile as possible
4. Maximize speed
5. Minimize memory consumption
6. Minimize number of lines of code
7. Minimize number of C++ classes
Geogram/Graphite Programming Priorities
Simplicity is the
ultimate sophistication
Part. 1 On Software Design
1. Make it as simple as possible (but not simpler)
2. Make it as easy to use as possible
3. Make it as easy to compile as possible
4. Maximize speed
5. Minimize memory consumption
6. Minimize number of lines of code
7. Minimize number of C++ classes
Geogram/Graphite Programming Priorities
Simplicity is the
ultimate sophistication
Part. 1 On Software Design
1. Make it as simple as possible (but not simpler)
2. Make it as easy to use as possible
3. Make it as easy to compile as possible
4. Maximize speed
5. Minimize memory consumption
6. Minimize number of lines of code
7. Minimize number of C++ classes
8. Systematically document all classes, all functions, [+Biblio.]
9. Systematically document the implementation of all algorithms
10. Assertion checks everywhere
11. Zero warnings with all compilers / platforms
12. Perform systematic non-regression testing and mem. check.
Geogram/Graphite Programming Priorities
Part. 1 On Software Design
Futuristic programming
Usefullness (and coolness) are primary !
Part. 1 On Software Design
• Jonathan Shewchuk s Triangle and exact predicates
• Tetgen, MGTetra, MMG3d
• Omar Cornut s ImGUI library
• David Mount s ANN library
• The LUA prog. language
Futuristic programming
Examples of Futuristic codes
Usefullness (and coolness) are primary !
Part. 1 On Software Design
Case study: mesh data structures
From several Computer Graphics / Mesh Processing 101 courses
- including (earlier versions of) mine -
Halfedges Design Principles
1. Individual combinatorial elements
can be created/destroyed at any time
in constant time
2. Basic operations (collapse, split, )
3. Higher-level operations on top of them
Part. 1 On Software Design
Case study: mesh data structures
Halfedges and edgeuses, harmful or useful ?
+ Benefit of abstraction: layered design
Part. 1 On Software Design
Case study: mesh data structures
Halfedges Design Principles
1. Individual combinatorial elements
can be created/destroyed at any time
in constant time
2. Basic operations (collapse, split, )
3. Higher-level operations on top of them
Halfedges and edgeuses, harmful or useful ?
+ Benefit of abstraction: layered design
- Separates things that should have been considered together
Part. 1 On Software Design
Case study: mesh data structures
Halfedges and edgeuses, harmful or useful ?
Halfedges Design Principles
1. Individual combinatorial elements
can be created/destroyed at any time
in constant time
2. Basic operations (collapse, split, )
3. Higher-level operations on top of them
+ Benefit of abstraction: layered design
- Separates things that should have been considered together
Not the optimal level of granularity
Part. 1 On Software Design
Case study: mesh data structures
Halfedges and edgeuses, harmful or useful ?
Halfedges Design Principles
1. Individual combinatorial elements
can be created/destroyed at any time
in constant time
2. Basic operations (collapse, split, )
3. Higher-level operations on top of them
Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
Objection ! (?) Deletion of one individual element is O(n) instead of constant
In fact: deleting 1 element = wrong granularity level !
Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
Deleting a bunch of elements
Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
Deleting a bunch of elements
Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
Deleting a bunch of elements
Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
Deleting a bunch of elements – operates also in O(n) – right granularity
Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
Deleting a bunch of elements – operates also in O(n) – right granularity
Part. 1 On Software Design
Case study: mesh data structures
Needs array permutation (not in the STL unfortunately,
but easy to implement, see GEOGRAM::permutation).
Indexed Mesh data structure (no data structure)
Indexed Mesh data structure (no data structure)
Summary:
•An array of vertices coordinates
•An array of triangle vertices indices
Part. 1 On Software Design
Case study: mesh data structures
•An array of vertices coordinates
•An array of triangle vertices indices
•An array of triangle adjacencies (optional)
•An array of facet first indices (optional)
Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
Summary:
Benefits of such a
non-datastructure, non-object, non-oriented, (non-)programming
1. Simpler code
Part. 1 On Software Design
Case study: mesh data structures
Benefits of such a
non-datastructure, non-object, non-oriented, (non-)programming
1. Simpler code
2. Less memory;
Part. 1 On Software Design
Case study: mesh data structures
Benefits of such a
non-datastructure, non-object, non-oriented, (non-)programming
1. Simpler code
2. Less memory;
3. Parallelization #pragma omp parallel for
Part. 1 On Software Design
Case study: mesh data structures
Benefits of such a
non-datastructure, non-object, non-oriented, (non-)programming
1. Simpler code
2. Less memory;
3. Parallelization #pragma omp parallel for
4. Easy copy: memcpy()
Part. 1 On Software Design
Case study: mesh data structures
Benefits of such a
non-datastructure, non-object, non-oriented, (non-)programming
1. Simpler code
2. Less memory;
3. Parallelization #pragma omp parallel for
4. Easy copy: memcpy()
5. Easy I/O: fread()/fwrite()
Part. 1 On Software Design
Case study: mesh data structures
Benefits of such a
non-datastructure, non-object, non-oriented, (non-)programming
1. Simpler code
2. Less memory;
3. Parallelization #pragma omp parallel for
4. Easy copy: memcpy()
5. Easy I/O: fread()/fwrite()
6. Properties/attributes are simply additional arrays
Part. 1 On Software Design
Case study: mesh data structures
Benefits of such a
non-datastructure, non-object, non-oriented, (non-)programming
1. Simpler code
2. Less memory;
3. Parallelization #pragma omp parallel for
4. Easy copy: memcpy()
5. Easy I/O: fread()/fwrite()
6. Properties/attributes are simply additional arrays
7. Directly understood by OpenGL: VertexBufferObject
Part. 1 On Software Design
Case study: mesh data structures
A mesh = a bunch of arrays (std::vectors)
Part. 1 On Software Design
Case study: mesh data structures
A mesh = a bunch of arrays (std::vectors)
How do you iterate on a vector ?
Part. 1 On Software Design
Case study: mesh data structures
Pre-2011:
for(std::vector<Thing>::iterator it = V.begin(); it!=V.end(); ++it) {
do something with *it
}
Part. 1 On Software Design
Case study: mesh data structures
How do you iterate on a vector ?
Pre-2011:
for(std::vector<Thing>::iterator it = V.begin(); it!=V.end(); ++it) {
do something with *it
}
Part. 1 On Software Design
Case study: mesh data structures
How do you iterate on a vector ?
It s a pain to type
Clutters the source-code (less legible)
Pre-2011:
for(std::vector<Thing>::iterator it = V.begin(); it!=V.end(); ++it) {
do something with *it
}
2011:
for(auto it = V.begin(); it!=V.end(); ++it) {
do something with *it
}
Part. 1 On Software Design
Case study: mesh data structures
How do you iterate on a vector ?
Pre-2011:
for(std::vector<Thing>::iterator it = V.begin(); it!=V.end(); ++it) {
do something with *it
}
2011:
for(auto it = V.begin(); it!=V.end(); ++it) {
do something with *it
}
now:
for(auto&& i : V) {
do something with i
}
Part. 1 On Software Design
Case study: mesh data structures
How do you iterate on a vector ?
A mesh = a bunch of arrays (std::vectors)
How do you iterate on a vector ?
Part. 1 On Software Design
Case study: mesh data structures
Warning: flying tomatoes alert ahead,
(modern C++ lovers might throw tomatoes at me)!
Pre-2011:
for(std::vector<Thing>::iterator it = V.begin(); it!=V.end(); ++it) {
do something with *it
}
2011:
for(auto it = V.begin(); it!=V.end(); ++it) {
do something with *it
}
now:
for(auto&& i : V) {
do something with I
}
Part. 1 On Software Design
Case study: mesh data structures
How do you iterate on a vector ?
How I iterate on a vector:
for(uint i=0; i<V.size(); ++i) {
do something with V[i];
}
Part. 1 On Software Design
Case study: mesh data structures
How do you iterate on a vector ?
How I iterate on a vector:
for(uint i=0; i<V.size(); ++i) {
do something with V[i];
}
Part. 1 On Software Design
Case study: mesh data structures
+ Easy to understand, even by C-only and Fortran programmers
+ Compatible with all compilers
+ #pragma omp parallel-for friendly* (and also better vectorization)
- 15 additional keystrokes as compared to modern C++ range-for
How do you iterate on a vector ?
*But use ints instead of uints, omp does not like uints
How I iterate on a vector:
for(uint i=0; i<V.size(); ++i) {
do something with V[i];
}
Part. 1 On Software Design
Case study: mesh data structures
+ Easy to understand, even by C-only programmers
+ Compatible with all compilers
+ #pragma omp parallel-for friendly
- 15 additional keystrokes as compared to modern C++ range-for
The following code has been approved for
APPROPRIATE AUDIENCES
PG-13
How I iterate on a vector:
for(uint i=0; i<V.size(); ++i) {
do something with V[i];
}
Part. 1 On Software Design
Case study: mesh data structures
+ Easy to understand, even by C-only programmers
+ Compatible with all compilers
+ #pragma omp parallel-for friendly
- 15 additional keystrokes as compared to modern C++ range-for
#define FOR(i,N) for(uint i=0; i<(N); ++i)
FOR(i,V.size()) {
do something with V[i];
}
+ Easy to understand, legible
+ Trivial iterations easy to spot
- Macros are evil
[Nicolas Ray]
Part. 1 On Software Design
Case study: mesh data structures
Objection:
It is bad because it is not flexible,
what if you want to adapt your algorithm to another container ?
Part. 1 On Software Design
Case study: mesh data structures
Objection:
It is bad because it is not flexible,
what if you want to adapt your algorithm to another container ?
Answer:
I m not going to use something else than a vector, because it is the best
choice for the mesh data structure. Why keeping a tuning knob on the
dash board if it is always on the same position ?
modern/generic != futuristic
Part. 1 On Software Design
Case study: mesh data structures
Objection:
It is bad because it is not flexible,
what if you want to adapt your algorithm to another container ?
Answer:
I m not going to use something else than a vector, because it is the best
choice for the mesh data structure. Why keeping a tuning knob on the
dash board if it is always on the same position ? (think of the I-Phone)
The Nokia N95, a
modern/generic phone.
The I-phone,
a futuristic phone.
modern/generic != futuristic
Part. 1 On Software Design
Case study: mesh data structures
modern/generic != futuristic
It is good because it has
everything that you need
The Nokia N95, a
modern/generic phone.
The I-phone,
a futuristic phone.
Part. 1 On Software Design
Case study: mesh data structures
modern/generic != futuristic
It is good because it has
everything that you need
It is even better because it has
nothing else than what you need
The Nokia N95, a
modern/generic phone.
The I-phone,
a futuristic phone.
Part. 1 On Software Design
Case study: mesh data structures
modern/generic != futuristic
It is good because it has
everything that you need
It is even better because it has
nothing else than what you need
Work is finished when you have
nothing to add and nothing to remove !
The Nokia N95, a
modern/generic phone.
The I-phone,
a futuristic phone.
Part. 1 On Software Design
Case study: mesh data structures
Why keeping a tuning knob on the dash board if it is always
on the same position ? (think of the I-Phone)
A parameter that always has the same value is not a parameter and should be
removed from the API.
A template that is instanced only once should not be a template.
Part. 1 On Software Design
Case study: mesh data structures
A parameter that always has the same value is not a parameter and should be
removed from the API.
A template that is instanced only once should not be a template.
Objection: but we loose genericity if we do that ???
Why keeping a tuning knob on the dash board if it is always
on the same position ? (think of the I-Phone)
Part. 1 On Software Design
Case study: mesh data structures
A parameter that always has the same value is not a parameter and should be
removed from the API.
A template that is instanced only once should not be a template.
Objection: but we loose genericity if we do that ???
Answer to objection: but we gain a lot, it declutters the
code, makes it more legible, reduces compilation times,
makes C++ compilation error messages more legible.
Why keeping a tuning knob on the dash board if it is always
on the same position ? (think of the I-Phone)
Part. 1 On Software Design
Case study: mesh data structures
Rule of thumb:
Make it a parameter not before you need it with at least two different values.
Make it a template not before you need at least two different instanciations.
*regarding compilation time, legibiity of error messages and run-time flex.
Part. 1 On Software Design
Case study: mesh data structures
Rule of thumb:
Make it a parameter not before you need it with at least two different values.
Make it a template not before you need at least two different instanciations.
About templates, consider less annoying* alternatives, such as
(1) object oriented programming / virtual functions
(2) or simply a parameter and if() statements
*regarding compilation time, legibility of error messages and run-time flex.
Graphics
2
Fast and Easy eye-candy with GLUP
Part. 2 Graphics – endangered species
The Windows start menu The I-Phone jack
glBegin(GL_TRIANGLES)
glVertex(… )
glEnd()
OpenGL immediate mode
glPush/Pop/MultMatrix()
glLight()
OpenGL fixed functionality pipeline
Part. 2 Graphics – endangered species
glBegin(GL_TRIANGLES)
glVertex(… )
glEnd()
OpenGL immediate mode
glPush/Pop/MultMatrix()
glLight()
OpenGL fixed functionality pipeline
Difficulties for an undergraduate who starts:
(1) Assemble vertex buffer objects
(2) Design vertex and fragment shaders
(3) (+ the Professor, I see nothing syndrom, nothing new here)
R.I.P. R.I.P.
Part. 2 Graphics – GLUP
Immediate mode + fixed functionality pipeline implemented
in modern OpenGL (4.x) (nearly source-compatible)
glupBegin(), glupEnd(), glupVertex(), glupPushMatrix()…
Part. 2 Graphics – GLUP
Immediate mode + fixed functionality pipeline implemented
in modern OpenGL (4.x) (nearly source-compatible)
glupBegin(), glupEnd(), glupVertex(), glupPushMatrix()…
normals not needed (per-fragment shading)
Part. 2 Graphics – GLUP
Immediate mode + fixed functionality pipeline implemented
in modern OpenGL (4.x) (nearly source-compatible)
glupBegin(), glupEnd(), glupVertex(), glupPushMatrix()…
normals not needed (per-fragment shading)
new volumetric primitives:
GLUP_TETRAHEDRA, GLUP_HEXAHEDRA,
GLUP_PRISMS, GLUP_PYRAMIDS, GLUP_SPHERES
Part. 2 Graphics – GLUP
Immediate mode + fixed functionality pipeline implemented
in modern OpenGL (4.x) (nearly source-compatible)
glupBegin(), glupEnd(), glupVertex(), glupPushMatrix()…
normals not needed (per-fragment shading)
new volumetric primitives:
GLUP_TETRAHEDRA, GLUP_HEXAHEDRA,
GLUP_PRISMS, GLUP_PYRAMIDS, GLUP_SPHERES
new clipping modes (on-GPU marching cells algorithm)
Part. 2 Graphics – GLUP
Immediate mode + fixed functionality pipeline implemented
in modern OpenGL (4.x) (nearly source-compatible)
glupBegin(), glupEnd(), glupVertex(), glupPushMatrix()…
normals not needed (per-fragment shading)
new volumetric primitives:
GLUP_TETRAHEDRA, GLUP_HEXAHEDRA,
GLUP_PRISMS, GLUP_PYRAMIDS, GLUP_SPHERES
new clipping modes (on-GPU marching cells algorithm)
glupEnable(GLUP_DRAW_MESH)
Part. 2 Graphics – GLUP
glupDrawArrays(), glupDrawElements(), VBOs
VanillaGL (1.x)
OpenGL ES,
WebGL
GLSL 1.5 (GL3.3)
GLSL 4.4 (GL4.4)
POINTS LINES TRGLS QUADS SPHERES T ETS PRISMS HEXES PYRAMIDS
glupDrawArrays()/glupDrawElements()/VBOs and immediate mode
Immediate mode only
Part. 2 Graphics – GLUP
Part. 2 Graphics – GLUP
Part. 2 Graphics – GLUP
glupDrawElements(GLUP_TETRAHEDRA)
1 single draw call with VBOs, everything occurs on GPU
glupSetClippingMode(GLUP_CLIP_SLICE)
Part. 2 Graphics – GLUP
Part. 2 Graphics – GLUP
glupDrawElements(GLUP_SPHERES)
1 single draw call with VBOs, everything occurs on GPU
(GLUP + screen-space ambient occlusion in Graphite)
Part. 2 Graphics – GLUP
Part. 2 Graphics – GLUP
glupDrawElements(GLUP_HEXAHEDRA)
glupDrawElements(GLUP_TETRAHEDRA)
2 draw calls with VBOs, everything occurs on GPU
(GLUP + screen-space ambient occlusion in Graphite)
Hexahedral-dominant mesh [Ray, Sokolov, Unterreiner, L 2016]
Part. 2 Graphics – GLUP
glupDrawElements(GLUP_HEXAHEDRA)
glupDrawElements(GLUP_TETRAHEDRA)
2 draw calls with VBOs, everything occurs on GPU
(GLUP + screen-space ambient occlusion in Graphite)
Cross-section computed with on-GPU marching cells with interpolated attrib.
Numerics
3
Cranking the number cruncher
Part. 3. Numerics
Numerical problems: neighborhoods
F = sum of terms, attached to neighborhoods
Discrete fairing
[Kobbelt98, Mallet95]
Parameterization
[Desbrun02]
Deformations
[CohenOr], [Sorkine]
Curv. Estimation
[Cohen-Steiner 03]
Texture mapping
[L01]
Discrete fairing
[Desbrun], ...
Parameterization
[Haker00]
[L02]
[Eck]
Part. 3. Numerics
Numerical problems: mesh parameterization
i
j1
j2
j…
Ui = ai,jUj
j  Ni
 i,j ai,j > 0
ai,i = -  ai,j
The border is mapped to
a convex polygon
[Tutte], [Floater]
Part. 3. Numerics
Numerical problems: mesh fairing
i
j1
j2
j…
F(p)=  pi - ai,jpj
2
j  Nii
[Mallet], [Kobbelt], [Sorkine]
Part. 3. Numerics
Numerical problems: mesh fairing
Part. 3. Numerics
Numerical problems: mesh fairing
F(x) =
2A x - b
Part. 3. Numerics
Numerical problems: mesh fairing
F(xf) =
xf
xl
[ Af Al] - b
2
F(x) =
2A x - b
Part. 3. Numerics
Numerical problems: least squares
F(xf) = A.x - d = Al.xl + Af.xf - d
2 2
Part. 3. Numerics
Numerical problems: least squares
F(xf) = A.x - d = Al.xl + Af.xf - d
2 2
F(xf) minimum Af
t.Af.xf = Af
t.d - Af
tAl.xl
M.x = b
}
}
Part. 3. Numerics
Numerical problems: least squares
F(xf) = A.x - d = Al.xl + Af.xf - d
2 2
F(xf) minimum Af
t.Af.xf = Af
t.d - Af
tAl.xl
M.x = b
}
}
The problem:
(1) construct the linear system (assembly)
(2) solve a linear system
Part. 3. Numerics – the OpenNL library.
Numerical problems: least squares
The problem:
(1) construct the linear system (assembly)
(2) solve a linear system
Part. 3. Numerics – the OpenNL library.
Numerical problems: least squares
The problem:
(1) construct the linear system (assembly)
(2) solve a linear system
Similarity between a mesh and a sparse matrix:
Part. 3. Numerics – the OpenNL library.
Numerical problems: least squares
The problem:
(1) construct the linear system (assembly)
(2) solve a linear system
nlBegin(NL_ROW)
nlAddCoefficient(I,j,val)
nlRightHandSide(val)
nlEnd(NL_ROW)
Similarity between a mesh and a sparse matrix:
OpenNL: API inspired by OpenGL immediate mode.
(+ automatic construction of AtA for least-squares)
Part. 3. Numerics – the OpenNL library.
Numerical problems: least squares
The problem:
(1) construct the linear system (assembly)
(2) solve a linear system
NLSparseMatrix: dynamic data structure (can grow)
OpenNL internals
…
…
…
…
…
Part. 3. Numerics – the OpenNL library.
Numerical problems: least squares
The problem:
(1) construct the linear system (assembly)
(2) solve a linear system
NLSparseMatrix NLCRSMatrix
OpenNL internals
nlCompress()
Part. 3. Numerics – the OpenNL library.
Numerical problems: least squares
The problem:
(1) construct the linear system (assembly)
(2) solve a linear system
NLSparseMatrix NLCRSMatrix NLCusparseMatrix
OpenNL internals GPU
nlCompress() (optionnal)
Part. 3. Numerics – the OpenNL library
Numerical problems: least squares
The problem:
(1) construct the linear system (assembly)
(2) solve a linear system
nlSolve() Iterative solvers
CG
GMRes
BiCGStab
CPU/GPU
Abstraction layer
OpenMP
multicore
CUDA
CuBLAS
CuSparse
Part. 3. Numerics – the OpenNL library
Numerical problems: least squares
The problem:
(1) construct the linear system (assembly)
(2) solve a linear system
nlSolve() Iterative solvers
Direct solvers
CG
GMRes
BiCGStab
SuperLU
CHOLDMOD
CPU/GPU
Abstraction layer
OpenMP
multicore
CUDA
CuBLAS
CuSparse
Part. 3. Numerics – the OpenNL library
Numerical problems: least squares
The problem:
(1) construct the linear system (assembly)
(2) solve a linear system
nlSolve()
Iterative solvers
Direct solvers
CG
GMRes
BiCGStab
SuperLU
CHOLDMOD
CPU/GPU
Abstraction layer
OpenMP
multicore
CUDA
CuBLAS
CuSparse
Eigen solver ARPACK
Part. 3. Numerics – the OpenNL library
OpenNL as a pluggable software module
Following futuristic programming principles:
* OpenNL also available as a single .c,.h pair, portable
to all architectures, easy to compile.
* Object-Oriented abstract matrix interface in C (achieves
run-time CPU/GPU flexibility)
* Dynamically loads CUDA CuBLAS and CuSparse
on demand (as well as CHOLMOD, SUPERLU,ARPACK)
* Double precision (and no single precision).
Part. 3. Numerics – the OpenNL library
OpenNL at work Everything available in geogram
GUI in graphite
Part. 3. Numerics – the OpenNL library
OpenNL at work
LSCM,
Spectral parameterization.
(600 lines of code for both)
ABF++ (800 lines of code)
PGP, QuadCover, MIP.
(700 lines of code)
Manifold Harmonics, HKS, ADF. (400 lines of code)
Everything available in geogram
GUI in graphite
Part. 3. Numerics – the OpenNL library
OpenNL at work Everything available in geogram
GUI in graphite
Baby groot © Marvel (this version by Byambaa on Thingyverse)
Part. 3. Numerics – the OpenNL library
OpenNL at work Everything available in geogram
GUI in graphite
Automatic decimation and normal
map generation.
Baby groot © Marvel (this version by Byambaa on Thingyverse)
Geometry
4
Predicates without the agonizing pain*
*Section title is a tribute to Jonathan Shewchuk.
The joy of computer graphics programming
4. Geometry - Motivations
[Martinez, Dumas, Lefebvre]
4. Geometry - Motivations
1. Motivations
4.Geometry Motivations
René Descartes
Wonder
Shapes
Structures
Symmetry
Part. 4. Geometry
Computing (restricted) Voronoi diagrams
Part. 4. Geometry
Computing (restricted) Voronoi diagrams
Part. 4 Geometry
Pointset X Simplicial complex S
either triangulated surface
or tetrahedralized solid
The input
Part. 4 Geometry
Vor(X)|S (Intersection between Vor(X) and S)
The output
Part 4. Geometry – a difficult dataset
Lots of degeneracies:
Voronoi diagram with degree 4 vertices.
Voronoi cell faces match exactly facets of the initial surface.
Part. 4 Geometry
Voronoi cells as iterative convex clipping
Half-space clipping
xi
x1
x2
x3
x4
x5
x6
x7
x8
x9
x10
x11
Part. 4 Difficulties – predicates
xi
xj
Elementary operation: cut a polygon
(or polyhedron) with a bisector
Part. 4 Difficulties – predicates
xi
xj
Elementary operation: cut a polygon
(or polyhedron) with a bisector
Classify the vertices of the polygon
Part. 4 Difficulties – predicates
xi
xj
Elementary operation: cut a polygon
(or polyhedron) with a bisector
Classify the vertices of the polygon
Sign( d(p,xj) – d(p,xi)) > 0
Part. 4 Difficulties – predicates
xi
xj
Elementary operation: cut a polygon
(or polyhedron) with a bisector
Classify the vertices of the polygon
Sign( d(p,xj) – d(p,xi)) > 0
Sign( d(p,xj) – d(p,xi)) < 0
Part. 4 Difficulties – predicates
xi
xj
Elementary operation: cut a polygon
(or polyhedron) with a bisector
Classify the vertices of the polygon
Compute the intersections
Sign( d(p,xj) – d(p,xi)) > 0
Sign( d(p,xj) – d(p,xi)) < 0
Part. 4 Difficulties – predicates
xi
xj
Sign( d(p,xj) – d(p,xi)) > 0
Sign( d(p,xj) – d(p,xi)) < 0
Elementary operation: cut a polygon
(or polyhedron) with a bisector
Classify the vertices of the polygon
Compute the intersections - discard
Part. 4 Difficulties – predicates
xi
xj
xk Now clipping with the bisector of (xi, xk)
Part. 4 Difficulties – predicates
xi
xj
xk Now clipping with the bisector of (xi, xk)
We need to classify all the points, including
these ones !
Part. 4 Difficulties – predicates
xi
xj
xk Now clipping with the bisector of (xi, xk)
We need to classify all the points, including
these ones !
(they are intersections between a
segment and a bisector)
Part. 4 Difficulties – predicates
xi
xj
xk Now clipping with the bisector of (xi, xk)
We need to classify all the points, including
these ones !
(they are intersections between a
segment and a bisector)
This generates a new intersection
(between a facet and two bisector)
Part. 4 Difficulties – predicates
Three configurations
1) Side(xi,xj,q) where q is a vertex of S
Part. 4 Difficulties – predicates
Three configurations
1) Side1(xi,xj,q)
Part. 4 Difficulties – predicates
Three configurations
1) Side1(xi,xj,q)
2) Side(xi,xj,q) where q = π(i,k) ∩ [p1,p2]
Part. 4 Difficulties – predicates
Three configurations
1) Side1(xi,xj,q)
2) Side2(xi,xj,xk,p1,p2)
Part. 4 Difficulties – predicates
Three configurations
1) Side1(xi,xj,q)
2) Side2(xi,xj,xk,p1,p2)
3) Side(xi,xj,q) where
q = π(i,k) ∩ π(i,l) ∩ [p1,p2,p3]
Part. 4 Difficulties – predicates
Three configurations
1) Side1(xi,xj,q)
2) Side2(xi,xj,xk,p1,p2)
3) Side3(xi,xj,xk, xl,p1,p2,p3)
Part. 4 Difficulties – predicates
Three configurations
1) Side1(xi,xj,q)
2) Side2(xi,xj,xk,p1,p2)
3) Side3(xi,xj,xk, xl,p1,p2,p3)
Implementations of exact predicates:
- J. Shewchuk s code
- CGAL (Pion, Meyer)
Part. 4 Difficulties – predicates
Three configurations
1) Side1(xi,xj,q)
2) Side2(xi,xj,xk,p1,p2)
3) Side3(xi,xj,xk, xl,p1,p2,p3)
Implementations of exact predicates:
- J. Shewchuk s code
- CGAL (Pion, Meyer)
They do not have Side1(), Side2(), Side3() ( exotic predicates )
Part. 4 Difficulties – predicates
Three configurations
1) Side1(xi,xj,q)
2) Side2(xi,xj,xk,p1,p2)
3) Side3(xi,xj,xk, xl,p1,p2,p3)
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Wish list:
• Easy to use
(no Guru needed for each new predicate)
• Reasonably efficient
• Easy to compile/integrate ( Futuristic programming )
(multi_precision.h, multi_precision.cpp and that s all)
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #1: (dense) multi-precision (GMP)
a0a1a2a3
x 20
x 21*32x 22*32x 23*32
…
Each number is an array of (32 bits) integers:
Implement +,-,* (reasonably easy)
Sign: look at the leading non-zero component
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #1: (dense) multi-precision (GMP)
a limitation :
c = a10 * 210*32 + b0
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #1: (dense) multi-precision (GMP)
a limitation :
b000a10
x 20x 210*32
c = a10 * 210*32 + b0
…
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #2: (sparse) multi-precision
b0 | 0a10 | 10
c = a10 * 210*32 + b0
Store the exponents of the components
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #2: (sparse) multi-precision
b0 | 0a10 | 10
c = a10 * 210*32 + b0
Exp. Exp.
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #2: (sparse) multi-precision
b0 | 0a10 | 10
c = a10 * 210*32 + b0
Exp. Exp.mantissa mantissa
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #2: (sparse) multi-precision
b0 | 0a10 | 10
c = a10 * 210*32 + b0
Exp. Exp.mantissa mantissa
These are floating point numbers !!!
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
x3 x2 x1
…
Each number is represented by the sum of an array of components
These are floating point numbers !!!
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
x3 x2 x1
…
Each number is represented by the sum of an array of components
They are sorted in decreasing exponents
These are floating point numbers !!!
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
x3 x2 x1
…
Each number is represented by the sum of an array of components
They are sorted in decreasing exponents
They are non-overlapping
These are floating point numbers !!!
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
x3 x2 x1
…
Each number is represented by the sum of an array of components
They are sorted in decreasing exponents
They are non-overlapping
The sign is determined by the first component (highest exponent)
These are floating point numbers !!!
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
x2 x1Two_sum(double a, double b)
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
x2 x1Two_sum(double a, double b)
+
Length:
l+m
Length l Length m
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
x2 x1Two_sum(double a, double b)
+
*
Length:
l+m
Length:
2*l
A double
Length l
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
* …
Length: 2*l*m
Expansion * Expansion product implemented by a recursive function
( distillation )
Length l Length m
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
* …
Expansion * Expansion product implemented by a recursive function
( distillation )
Performance ? 10 to 40 times slower than standard doubles
Length: 2*l*mLength l Length m
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
* …
Expansion * Expansion product implemented by a recursive function
( distillation )
Performance ? 10 to 40 times slower than standard doubles
Use arithmetic filters
Adaptive precision [Shewchuk] ? Too complicated to get right
Length: 2*l*mLength l Length m
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
* …
Expansion * Expansion product implemented by a recursive function
( distillation )
Performance ? 10 to 40 times slower than standard doubles
Use arithmetic filters
Adaptive precision [Shewchuk] ? Too complicated to get right
Quasi-static filters [Meyer and Pion] – FPG generator (easy to use)
Length: 2*l*mLength l Length m
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
PCK (Predicate Construction Kit)
multi_precision.h / multi_precision.cpp
A low-level expansion class (allocates expansions on stack)
A high-level C++ number type (+,-,*,Sign overloads)
a compiler that generates the filter with FPG [Meyer and Pion] and the
exact precision version with expansions
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
PCK (Predicate Construction Kit)
multi_precision.h / multi_precision.cpp
A low-level expansion class (allocates expansions on stack)
A high-level C++ number type (+,-,*,Sign overloads)
a compiler that generates the filter with FPG [Meyer and Pion] and the
exact precision version with expansions
(why not templates / metaprogramming ?
would be possible, but specialized language is much better here).
Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
PCK (Predicate Construction Kit)
multi_precision.h / multi_precision.cpp
A low-level expansion class (allocates expansions on stack)
A high-level C++ number type (+,-,*,Sign overloads)
a compiler that generates the filter with FPG [Meyer and Pion] and the
exact precision version with expansions
So we are done ?
Part. 4 Symbolic Perturbation
How to implement Side1(), Side2(), Side3() ?
xi
xj
Not yet !!
Part. 4 Symbolic Perturbation
How to implement Side1(), Side2(), Side3() ?
xi
xj
Not yet !!
Part. 4 Symbolic Perturbation
Part. 4 Symbolic Perturbation
Part. 4 Symbolic Perturbation
Part. 4 Symbolic Perturbation
Part. 4 Symbolic Perturbation
Part. 4 Symbolic Perturbation
Part. 4 Symbolic Perturbation
Part. 4 Symbolic Perturbation
Part. 4 Symbolic Perturbation
Part. 4 Symbolic Perturbation
Part. 4 Symbolic Perturbation
Part. 4 Symbolic Perturbation
Part. 4 Symbolic Perturbation
Part. 4 Symbolic Perturbation
Part. 4 Symbolic Perturbation
Part. 4 Symbolic Perturbation
[Voronoi]
[Edelsbrunner et.al]
[Devillers et.al]
Part. 4 Symbolic Perturbation
[Voronoi]
[Edelsbrunner et.al]
[Devillers et.al]
Part. 4 Symbolic Perturbation
Each point pi is replaced
by a trajectory pi(ε)
xi(ε) = xi + ε3i
yi(ε) = yi + ε3i+1
zi(ε) = zi + ε3i+2
For instance:
[Voronoi]
[Edelsbrunner et.al]
[Devillers et.al]
Part. 4 Symbolic Perturbation
Each point pi is replaced
by a trajectory pi(ε)
Take the limit when
ε tends to 0
xi
xj
π(i,j) = {p | d2(p,xi) = d2(p,xj)}
[Voronoi]
[Edelsbrunner et.al]
[Devillers et.al]
Part. 4 Symbolic Perturbation
In our case, perturb the
weights of a power diagram.
xi
xj
πw(i,j) = {p | d2(p,xi) - wi = d2(p,xj) - wj}
[Voronoi]
[Edelsbrunner et.al]
[Devillers et.al]
Part. 4 Symbolic Perturbation
In our case, perturb the
weights of a power diagram.
xi
xj
πw(i,j) = {p | d2(p,xi) - wi = d2(p,xj) - wj}
[Voronoi]
[Edelsbrunner et.al]
[Devillers et.al]
The Voronoi diagram is replaced with a power diagram
Part. 4 Symbolic Perturbation
xi
xj
πw(i,j) = {p | d2(p,xi) - wi = d2(p,xj) - wj}
[Voronoi]
[Edelsbrunner et.al]
[Devillers et.al]
The Voronoi diagram is replaced with a power diagram
Symbolic perturbation – Simulation of Simplicity:
Define the weight as a function of ε: wi = εi
Part. 4 Symbolic Perturbation
xi
xj
πw(i,j) = {p | d2(p,xi) - wi = d2(p,xj) - wj}
[Voronoi]
[Edelsbrunner et.al]
[Devillers et.al]
The Voronoi diagram is replaced with a power diagram
Symbolic perturbation – Simulation of Simplicity:
Define the weight as a function of ε: wi = εi
The combinatorics is determined by the limit ε →0
Part. 4 Symbolic Perturbation
How to write side1(), side2(), side3(), side4() ?
d2(q,pj)-wj – d2(q,pi) + wi where:
q = πw(i,k1) ∩ …πw(i,kd) ∩ [p1,p2,p3…pd]
Part. 4 Symbolic Perturbation
How to write side1(), side2(), side3(), side4() ?
d2(q,pj)-wj – d2(q,pi) + wi where:
q = πw(i,k1) ∩ …πw(i,kd) ∩ [p1,p2,p3…pd]
Solve for q in:
q Є πw(i,k1)
…
q Є πw(i,kd)
q Є [p1,p2,p3…pd]
{
Part. 4 Symbolic Perturbation
How to write side1(), side2(), side3(), side4() ?
d2(q,pj)-wj – d2(q,pi) + wi where:
q = πw(i,k1) ∩ …πw(i,kd) ∩ [p1,p2,p3…pd]
q = (1/d) Q
Keep numerator and denom.
separate (remember, we are
not allowed to divide)
Solve for q in:
q Є πw(i,k1)
…
q Є πw(i,kd)
q Є [p1,p2,p3…pd]
{
Part. 4 Symbolic Perturbation
How to write side1(), side2(), side3(), side4() ?
d2(q,pj)-wj – d2(q,pi) + wi where:
q = πw(i,k1) ∩ …πw(i,kd) ∩ [p1,p2,p3…pd]
q = (1/d) Q
Keep numerator and denom.
separate (remember, we are
not allowed to divide)
Inject q=(1/d) Q in side1() and mutliply by d to remove the division
Solve for q in:
q Є πw(i,k1)
…
q Є πw(i,kd)
q Є [p1,p2,p3…pd]
{
Part. 4 Symbolic Perturbation
How to write side1(), side2(), side3(), side4() ?
d2(q,pj)-wj – d2(q,pi) + wi where:
q = πw(i,k1) ∩ …πw(i,kd) ∩ [p1,p2,p3…pd]
q = (1/d) Q
Keep numerator and denom.
separate (remember, we are
not allowed to divide)
Inject q=(1/d) Q in side1() and mutliply by d to remove the division
Order the terms in wi = εi
Solve for q in:
q Є πw(i,k1)
…
q Є πw(i,kd)
q Є [p1,p2,p3…pd]
{
Part. 4 Symbolic Perturbation
How to write side1(), side2(), side3(), side4() ?
d2(q,pj)-wj – d2(q,pi) + wi where:
q = πw(i,k1) ∩ …πw(i,kd) ∩ [p1,p2,p3…pd]
q = (1/d) Q
Keep numerator and denom.
separate (remember, we are
not allowed to divide)
Inject q=(1/d) Q in side1() and mutliply by d to remove the division
Order the terms in wi = εi the constant one is non-perturbed predicate
if zero, the first non-zero one determines the sign
Solve for q in:
q Є πw(i,k1)
…
q Є πw(i,kd)
q Є [p1,p2,p3…pd]
{
Part. 4 Symbolic Perturbation
Part. 4 Symbolic Perturbation – side1
#include "kernel.pckh"
Sign predicate(side1)(
point(p0), point(p1), point(q0) DIM
) {
scalar r = sq_dist(p0,p1) ;
r -= 2*dot_at(p1,q0,p0) ;
generic_predicate_result(sign(r)) ;
begin_sos2(p0,p1)
sos(p0,POSITIVE)
sos(p1,NEGATIVE)
end_sos
}
Source PCK
Part. 4 Symbolic Perturbation – side1
#include "kernel.pckh"
Sign predicate(side1)(
point(p0), point(p1), point(q0) DIM
) {
scalar r = sq_dist(p0,p1) ;
r -= 2*dot_at(p1,q0,p0) ;
generic_predicate_result(sign(r)) ;
begin_sos2(p0,p1)
sos(p0,POSITIVE)
sos(p1,NEGATIVE)
end_sos
}
Source PCK
(p1-p0).(q0-p0)
Part. 4 Symbolic Perturbation – side2
#include "kernel.pckh“
Sign predicate(side2)( point(p0), point(p1), point(p2), point(q0), point(q1) DIM) {
scalar l1 = 1*sq_dist(p1,p0) ;
scalar l2 = 1*sq_dist(p2,p0) ;
scalar a10 = 2*dot_at(p1,q0,p0);
scalar a11 = 2*dot_at(p1,q1,p0);
scalar a20 = 2*dot_at(p2,q0,p0);
scalar a21 = 2*dot_at(p2,q1,p0);
scalar Delta = a11 - a10 ;
scalar DeltaLambda0 = a11 - l1 ;
scalar DeltaLambda1 = l1 - a10 ;
scalar r = Delta*l2 - a20*DeltaLambda0 - a21*DeltaLambda1 ;
Sign Delta_sign = sign(Delta) ;
Sign r_sign = sign(r) ;
generic_predicate_result(Delta_sign*r_sign) ;
begin_sos3(p0,p1,p2)
sos(p0, Sign(Delta_sign*sign(Delta-a21+a20)))
sos(p1, Sign(Delta_sign*sign(a21-a20)))
sos(p2, NEGATIVE)
end_sos
} Source PCK
Part. 4 Symbolic Perturbation – side2
#include "kernel.pckh“
Sign predicate(side2)( point(p0), point(p1), point(p2), point(q0), point(q1) DIM) {
scalar l1 = 1*sq_dist(p1,p0) ;
scalar l2 = 1*sq_dist(p2,p0) ;
scalar a10 = 2*dot_at(p1,q0,p0);
scalar a11 = 2*dot_at(p1,q1,p0);
scalar a20 = 2*dot_at(p2,q0,p0);
scalar a21 = 2*dot_at(p2,q1,p0);
scalar Delta = a11 - a10 ;
scalar DeltaLambda0 = a11 - l1 ;
scalar DeltaLambda1 = l1 - a10 ;
scalar r = Delta*l2 - a20*DeltaLambda0 - a21*DeltaLambda1 ;
Sign Delta_sign = sign(Delta) ;
Sign r_sign = sign(r) ;
generic_predicate_result(Delta_sign*r_sign) ;
begin_sos3(p0,p1,p2)
sos(p0, Sign(Delta_sign*sign(Delta-a21+a20)))
sos(p1, Sign(Delta_sign*sign(a21-a20)))
sos(p2, NEGATIVE)
end_sos
} Source PCK
Denominator
Part. 4 Symbolic Perturbation – side2
#include "kernel.pckh“
Sign predicate(side2)( point(p0), point(p1), point(p2), point(q0), point(q1) DIM) {
scalar l1 = 1*sq_dist(p1,p0) ;
scalar l2 = 1*sq_dist(p2,p0) ;
scalar a10 = 2*dot_at(p1,q0,p0);
scalar a11 = 2*dot_at(p1,q1,p0);
scalar a20 = 2*dot_at(p2,q0,p0);
scalar a21 = 2*dot_at(p2,q1,p0);
scalar Delta = a11 - a10 ;
scalar DeltaLambda0 = a11 - l1 ;
scalar DeltaLambda1 = l1 - a10 ;
scalar r = Delta*l2 - a20*DeltaLambda0 - a21*DeltaLambda1 ;
Sign Delta_sign = sign(Delta) ;
Sign r_sign = sign(r) ;
generic_predicate_result(Delta_sign*r_sign) ;
begin_sos3(p0,p1,p2)
sos(p0, Sign(Delta_sign*sign(Delta-a21+a20)))
sos(p1, Sign(Delta_sign*sign(a21-a20)))
sos(p2, NEGATIVE)
end_sos
} Source PCK
Barycentric
coords. of q
Part. 4 Symbolic Perturbation – side2
#include "kernel.pckh“
Sign predicate(side2)( point(p0), point(p1), point(p2), point(q0), point(q1) DIM) {
scalar l1 = 1*sq_dist(p1,p0) ;
scalar l2 = 1*sq_dist(p2,p0) ;
scalar a10 = 2*dot_at(p1,q0,p0);
scalar a11 = 2*dot_at(p1,q1,p0);
scalar a20 = 2*dot_at(p2,q0,p0);
scalar a21 = 2*dot_at(p2,q1,p0);
scalar Delta = a11 - a10 ;
scalar DeltaLambda0 = a11 - l1 ;
scalar DeltaLambda1 = l1 - a10 ;
scalar r = Delta*l2 - a20*DeltaLambda0 - a21*DeltaLambda1 ;
Sign Delta_sign = sign(Delta) ;
Sign r_sign = sign(r) ;
generic_predicate_result(Delta_sign*r_sign) ;
begin_sos3(p0,p1,p2)
sos(p0, Sign(Delta_sign*sign(Delta-a21+a20)))
sos(p1, Sign(Delta_sign*sign(a21-a20)))
sos(p2, NEGATIVE)
end_sos
} Source PCK
Barycentric
coords. of q
Solely depend
on dot products
between input
points
Part. 4 Symbolic Perturbation – side2
#include "kernel.pckh“
Sign predicate(side2)( point(p0), point(p1), point(p2), point(q0), point(q1) DIM) {
scalar l1 = 1*sq_dist(p1,p0) ;
scalar l2 = 1*sq_dist(p2,p0) ;
scalar a10 = 2*dot_at(p1,q0,p0);
scalar a11 = 2*dot_at(p1,q1,p0);
scalar a20 = 2*dot_at(p2,q0,p0);
scalar a21 = 2*dot_at(p2,q1,p0);
scalar Delta = a11 - a10 ;
scalar DeltaLambda0 = a11 - l1 ;
scalar DeltaLambda1 = l1 - a10 ;
scalar r = Delta*l2 - a20*DeltaLambda0 - a21*DeltaLambda1 ;
Sign Delta_sign = sign(Delta) ;
Sign r_sign = sign(r) ;
generic_predicate_result(Delta_sign*r_sign) ;
begin_sos3(p0,p1,p2)
sos(p0, Sign(Delta_sign*sign(Delta-a21+a20)))
sos(p1, Sign(Delta_sign*sign(a21-a20)))
sos(p2, NEGATIVE)
end_sos
} Source PCK
Result when in
generic position
Part. 4 Symbolic Perturbation – side2
#include "kernel.pckh“
Sign predicate(side2)( point(p0), point(p1), point(p2), point(q0), point(q1) DIM) {
scalar l1 = 1*sq_dist(p1,p0) ;
scalar l2 = 1*sq_dist(p2,p0) ;
scalar a10 = 2*dot_at(p1,q0,p0);
scalar a11 = 2*dot_at(p1,q1,p0);
scalar a20 = 2*dot_at(p2,q0,p0);
scalar a21 = 2*dot_at(p2,q1,p0);
scalar Delta = a11 - a10 ;
scalar DeltaLambda0 = a11 - l1 ;
scalar DeltaLambda1 = l1 - a10 ;
scalar r = Delta*l2 - a20*DeltaLambda0 - a21*DeltaLambda1 ;
Sign Delta_sign = sign(Delta) ;
Sign r_sign = sign(r) ;
generic_predicate_result(Delta_sign*r_sign) ;
begin_sos3(p0,p1,p2)
sos(p0, Sign(Delta_sign*sign(Delta-a21+a20)))
sos(p1, Sign(Delta_sign*sign(a21-a20)))
sos(p2, NEGATIVE)
end_sos
} Source PCK
Symbolic
perturbation
Part. 4 Symbolic Perturbation – side2
Sign side2_exact_SOS(
const double* p0, const double* p1, const double* p2,
const double* q0, const double* q1,
coord_index_t dim
) {
const expansion& l1 = expansion_sq_dist(p1, p0, dim);
const expansion& l2 = expansion_sq_dist(p2, p0, dim);
const expansion& a10 = expansion_dot_at(p1, q0, p0, dim).scale_fast(2.0);
const expansion& a11 = expansion_dot_at(p1, q1, p0, dim).scale_fast(2.0);
const expansion& a20 = expansion_dot_at(p2, q0, p0, dim).scale_fast(2.0);
const expansion& a21 = expansion_dot_at(p2, q1, p0, dim).scale_fast(2.0);
const expansion& Delta = expansion_diff(a11, a10);
Sign Delta_sign = Delta.sign();
vor_assert(Delta_sign != ZERO);
const expansion& DeltaLambda0 = expansion_diff(a11, l1);
const expansion& DeltaLambda1 = expansion_diff(l1, a10);
const expansion& r0 = expansion_product(Delta, l2);
const expansion& r1 = expansion_product(a20, DeltaLambda0).negate();
const expansion& r2 = expansion_product(a21, DeltaLambda1).negate();
const expansion& r = expansion_sum3(r0, r1, r2);
Sign r_sign = r.sign();
………..
Exact version with expansions
Part. 4 Symbolic Perturbation – side2
if(r_sign == ZERO) {
const double* p_sort[3];
p_sort[0] = p0;
p_sort[1] = p1;
p_sort[2] = p2;
std::sort(p_sort, p_sort + 3);
for(index_t i = 0; i < 3; ++i) {
if(p_sort[i] == p0) {
const expansion& z1 = expansion_diff(Delta, a21);
const expansion& z = expansion_sum(z1, a20);
Sign z_sign = z.sign();
len_side2_SOS = vor_max(len_side2_SOS, z.length());
if(z_sign != ZERO) {
return Sign(Delta_sign * z_sign);
}
}
if(p_sort[i] == p1) {
const expansion& z = expansion_diff(a21, a20);
Sign z_sign = z.sign();
len_side2_SOS = vor_max(len_side2_SOS, z.length());
if(z_sign != ZERO) {
return Sign(Delta_sign * z_sign);
}
}
if(p_sort[i] == p2) {
return NEGATIVE;
}
}
vor_assert_not_reached;
}
return Sign(Delta_sign * r_sign);
} Exact version with expansions
Part. 4 Symbolic Perturbation – side3
#include "kernel.pckh"
Sign predicate(side3)(
point(p0), point(p1), point(p2), point(p3),
point(q0), point(q1), point(q2) DIM
) {
scalar l1 = 1*sq_dist(p1,p0);
scalar l2 = 1*sq_dist(p2,p0);
scalar l3 = 1*sq_dist(p3,p0);
scalar a10 = 2*dot_at(p1,q0,p0);
scalar a11 = 2*dot_at(p1,q1,p0);
scalar a12 = 2*dot_at(p1,q2,p0);
scalar a20 = 2*dot_at(p2,q0,p0);
scalar a21 = 2*dot_at(p2,q1,p0);
scalar a22 = 2*dot_at(p2,q2,p0);
scalar a30 = 2*dot_at(p3,q0,p0);
scalar a31 = 2*dot_at(p3,q1,p0);
scalar a32 = 2*dot_at(p3,q2,p0);
scalar b00 = a11*a22-a12*a21;
scalar b01 = a21-a22;
scalar b02 = a12-a11;
scalar b10 = a12*a20-a10*a22;
scalar b11 = a22-a20;
scalar b12 = a10-a12;
scalar b20 = a10*a21-a11*a20;
scalar b21 = a20-a21;
scalar b22 = a11-a10;
scalar Delta = b00+b10+b20;
scalar DeltaLambda0 =
b01*l1+b02*l2+b00 ;
scalar DeltaLambda1 =
b11*l1+b12*l2+b10 ;
scalar DeltaLambda2 =
b21*l1+b22*l2+b20 ;
scalar r = Delta*l3 - (
a30 * DeltaLambda0 +
a31 * DeltaLambda1 +
a32 * DeltaLambda2
) ;
Sign Delta_sign = sign(Delta) ;
Sign r_sign = sign(r) ;
generic_predicate_result(
Delta_sign*r_sign
) ;
begin_sos4(p0,p1,p2,p3)
sos(p0, Sign(Delta_sign*sign(
Delta-((b01+b02)*a30+
(b11+b12)*a31+
(b21+b22)*a32)
)))
sos(p1, Sign(Delta_sign*
sign((a30*b01)+
(a31*b11)+
(a32*b21))))
sos(p2, Sign(Delta_sign*sign(
(a30*b02)+
(a31*b12)+
(a32*b22))))
sos(p3, NEGATIVE)
end_sos
}
Source PCK
Part. 4 Symbolic Perturbation – side4
……….
scalar b00= det3x3(a11,a12,a13,a21,a22,a23,a31,a32,a33);
scalar b01=-det_111_2x3(a21,a22,a23,a31,a32,a33);
scalar b02= det_111_2x3(a11,a12,a13,a31,a32,a33);
scalar b03=-det_111_2x3(a11,a12,a13,a21,a22,a23);
scalar b10=-det3x3(a10,a12,a13,a20,a22,a23,a30,a32,a33);
scalar b11= det_111_2x3(a20,a22,a23,a30,a32,a33);
scalar b12=-det_111_2x3(a10,a12,a13,a30,a32,a33);
scalar b13= det_111_2x3(a10,a12,a13,a20,a22,a23);
scalar b20= det3x3(a10,a11,a13,a20,a21,a23,a30,a31,a33);
scalar b21=-det_111_2x3(a20,a21,a23,a30,a31,a33);
scalar b22= det_111_2x3(a10,a11,a13,a30,a31,a33);
scalar b23=-det_111_2x3(a10,a11,a13,a20,a21,a23);
scalar b30=-det3x3(a10,a11,a12,a20,a21,a22,a30,a31,a32);
scalar b31= det_111_2x3(a20,a21,a22,a30,a31,a32);
scalar b32=-det_111_2x3(a10,a11,a12,a30,a31,a32);
scalar b33= det_111_2x3(a10,a11,a12,a20,a21,a22);
scalar Delta=b00+b10+b20+b30;
scalar DeltaLambda0 = b01*l1+b02*l2+b03*l3+b00;
scalar DeltaLambda1 = b11*l1+b12*l2+b13*l3+b10;
scalar DeltaLambda2 = b21*l1+b22*l2+b23*l3+b20;
scalar DeltaLambda3 = b31*l1+b32*l2+b33*l3+b30;
……….
scalar r = Delta*l4 - (
a40*DeltaLambda0+
a41*DeltaLambda1+
a42*DeltaLambda2+
a43*DeltaLambda3
);
Sign Delta_sign = sign(Delta);
generic_predicate_result(Delta_sign*sign(r)) ;
begin_sos5(p0,p1,p2,p3,p4)
sos(p0, Sign( Delta_sign*sign(Delta - (
(b01+b02+b03)*a30 +
(b11+b12+b13)*a31 +
(b21+b22+b23)*a32 +
(b31+b32+b33)*a33
)))
)
sos(p1, Sign( Delta_sign*sign(a30*b01+a31*b11+a32*b21+a33*b31)))
sos(p2, Sign( Delta_sign*sign(a30*b02+a31*b12+a32*b22+a33*b32)))
sos(p3, Sign( Delta_sign*sign(a30*b03+a31*b13+a32*b23+a33*b33)))
sos(p4, NEGATIVE)
end_sos
}
q is the intersection of three bisectors and a tetrahedron embedded in nD
Note: There is a special case in 3d (no need for the tetrahedron) = insphere3d()
The code of the general
nD version (excerpt) :
Source PCK
Part 4. Geometry – Crash test 1/2
Part 4. Geometry – Crash test 1/2
Part 4. Geometry – Crash test 1/2
Part 4. Geometry – Crash test 1/2
Part 4. Geometry – Crash test 2/2
Part 4. Geometry – Crash test 2/2
Part 4. Geometry - RVD
Part 4. Geometry - RVD
Part 4. Geometry - RVD
Part 4. Geometry - RVD
Part 4. Geometry - RVD
If we eliminate the zero components during computations, the length of the
expansions remain reasonable (see observation in Shewchuk’s paper)
Part 4. Clipped Voronoi diagram
Part 4. Clipped Voronoi diagram
Polyhedral elements for
Finite Elements Analysis
>vorpaline/vorpalite profile=poly fusee.meshb
Part 4. Geometry – 3D Anisotropic VD
Part 4. Geometry – 3D Anisotropic VD
The PCK (Predicate Construction Kit)
Features:
• Expansion number type – low level API (allocation on stack, efficient)
• High level API with operators (easy to use, less efficient)
• Script to generate FPG filter and exact version with SOS
• Standard predicates (orient2d, 3d, insphere3d, orient4d)
• More exotic predicates for RVD (side1, side2, side3, side 4 in dim 3,4,6,7)
• 3D Delaunay triangulation
• 3D weighted Delaunay triangulation
• Only 6 source files
• multi_precision.(h,cpp)
• predicates.(h,cpp)
• delaunay3d.(h,cpp)
• Fully documented
• No dependency (compiles and runs everywhere*, I got a version on my phone :-)
BSD license (do what you want with it, including business)
*In the IEEE754 world
What s next
5
Physics + Mathematics + Computing = ?
?
T
ρ1 ρ2
Minimize C(T) =
∫Ω
|| x – T(x) ||2 dx
Subject to: T is measure-preserving
ρ1(x)
Optimal Transport
A map T is a transport map between μ and ν if
μ(T-1(B)) = ν(B) for any Borel subset B
B
(X;μ) (Y;ν)
Optimal Transport
A map T is a transport map between μ and ν if
μ(T-1(B)) = ν(B) for any Borel subset B
B
T-1(B)
(X;μ) (Y;ν)
Optimal Transport
Continuous
(X;μ) (Y;ν)
Optimal Transport : probability measures
Continuous
Semi-discrete
Discrete
(X;μ) (Y;ν)
Optimal Transport : probability measures
Continuous
Semi-discrete
Discrete
(X;μ) (Y;ν)
Optimal Transport : probability measures
Optimal Transport – semi-discrete
∫X ψc (x)dμ + ∫Y ψ(y)dν
Sup
ψ Є ψc
(DMK)
∑j ∫Lagψ(yj) || x – yj ||2 - ψ(yj) dμ
∫X inf yj ЄY [ || x – yj ||2 - ψ(yj) ] dμ
∑j ψ(yj) vj
Voronoi diagram: Vor(xi) = { x | d2(x,xi) < d2(x,xj) }
Power Diagrams
Power diagram: Pow(xi) = { x | d2(x,xi) – ψi < d2(x,xj) – ψj }
Voronoi diagram: Vor(xi) = { x | d2(x,xi) < d2(x,xj) }
Power Diagrams
Shape Interpolation
Shape Interpolation
Shape Fitting
Shape Fitting
TopOpt2FEA
<<<<
<<
Scan2FEA
3D scan from ARTEC
Remesh with CVT
Scan2FEA
Periodic Global Parameterization
Scan2FEA
Subd control mesh
Scan2FEA
Subd surface fitted using Optimal Transport
Scan2FEA
Finite Element Analysis (vibration modes)
Scan2FEA
Think Big
Think Big: Simulating the entire universe
The millenium simulation project, Max Planck Institute fur Astrophysik
pc/h : parsec (= 3.2 années lumières)Large-Scale structure
Optimal Transport
Early Universe Reconstruction
The Data
Optimal Transport
Invert Newton Einstein Eqn to go back 14 milliards years in time
The millenium simulation project,
Max Planck Institute fur Astrophysik
pc/h : parsec (= 3.2 light years)
Optimal Transport
The millenium simulation project,
Max Planck Institute fur Astrophysik
pc/h : parsec (= 3.2 années lumières)
In 2002, 5 hours of computation
with a supercomputer / 5000 points
Optimal Transport
The millenium simulation project,
Max Planck Institute fur Astrophysik
pc/h : parsec (= 3.2 années lumières)
In 2002, 5 hours of computation
with a supercomputer / 5000 points
Can we do it with 1 000 000 points ?
Optimal Transport
The millenium simulation project,
Max Planck Institute fur Astrophysik
pc/h : parsec (= 3.2 années lumières)
In 2002, 5 hours of computation
with a supercomputer / 5000 points
Can we do it with 1 000 000 points ?
Yes, if we wait 4500 years
Optimal Transport
In 2002, 5 hours of computation
with a supercomputer / 5000 points
Can we do it with 1 000 000 points ?
Yes, if we wait 4500 years
Optimal Transport
In 2002, 5 hours of computation
with a supercomputer / 5000 points
Can we do it with 1 000 000 points ?
Yes, if we wait 4500 years
We need a new algorithm.
Towards Early Universe Reconstruction
Numerical Experiment: Performances
2002: several hours of supercomputer time were needed
for computing OT with a few thousand Dirac masses, with a combinatorial
algorithm in O(n2log(n))
Towards Early Universe Reconstruction
Numerical Experiment: Performances
2002: several hours of supercomputer time were needed
for computing OT with a few thousand Dirac masses, with a combinatorial
algorithm in O(n2log(n))
2015:
3D version of [Mérigot] (multilevel + BFGS) + several tricks [L 2015]
Towards Early Universe Reconstruction
Numerical Experiment: Performances
2002: several hours of supercomputer time were needed
for computing OT with a few thousand Dirac masses, with a combinatorial
algorithm in O(n2log(n))
2015:
3D version of [Mérigot] (multilevel + BFGS) + several tricks [L 2015]
Towards Early Universe Reconstruction
Numerical Experiment: Performances
2002: several hours of supercomputer time were needed
for computing OT with a few thousand Dirac masses, with a combinatorial
algorithm in O(n2log(n))
2015:
3D version of [Mérigot] (multilevel + BFGS) + several tricks [L 2015]
2016: Damped Newton [Mérigot, Thibert] + several tricks for 3D:
1 million Dirac masses in 240 seconds
Towards Early Universe Reconstruction
Numerical Experiment: Performances
2002: several hours of supercomputer time were needed
for computing OT with a few thousand Dirac masses, with a combinatorial
algorithm in O(n2log(n))
2015:
3D version of [Mérigot] (multilevel + BFGS) + several tricks [L 2015]
2016: Damped Newton [Mérigot, Thibert] + several tricks for 3D:
1 million Dirac masses in 240 seconds
10 million Dirac masses in 90 minutes
Towards Early Universe Reconstruction
Numerical Experiment: Performances
2002: several hours of supercomputer time were needed
for computing OT with a few thousand Dirac masses, with a combinatorial
algorithm in O(n2log(n))
2015:
3D version of [Mérigot] (multilevel + BFGS) + several tricks [L 2015]
2016: Damped Newton [Mérigot, Thibert] + several tricks for 3D:
1 million Dirac masses in 240 seconds
10 million Dirac masses in 90 minutes
2017: 10 million Dirac masses in 2 minutes (for specific configurations)
Semi-discrete OT is now scalable ! (new tool in Num. Ana. Toolbox)
Some concluding words
Take-home message
Programming is a great source of fun
Take-home message
Programming is a great source of fun
Futuristic programming principles
(make it fun for your users as well)
Take-home message
Programming is a great source of fun
Futuristic programming principles
Program speed
Low memory consumption
Lines of code
Classes
Templates
Take-home message
Programming is a great source of fun
Futuristic programming principles
Program speed
Low memory consumption
Lines of code
Classes
Templates
Gains Costs
Take-home message
Programming is a great source of fun
Futuristic programming principles
Program speed
Low memory consumption
Lines of code
Classes
Templates
Gains Costs
Measure it !
(profiler, continuous integration)
Take-home message: Usefulness is primary
.h, .cpp
.h, .cpp
.h, .cpp
.h, .cpp
.h, .cpp
.h, .cpp
.h, .cpp
Object-oriented design
Generic design
Take-home message: Usefulness is primary
.h, .cpp
.h, .cpp
.h, .cpp
.h, .cpp
.h, .cpp
.h, .cpp
.h, .cpp
Object-oriented design
Generic design
Take-home message: Usefulness is primary
Futuristic design
.cpp
.h
void the_functionality(Data& )
Take-home message: Usefulness is primary
Futuristic design
.cpp
.h
void the_functionality(Data& )
* Make it easy to compile
* Do not bother the user
with internal details (even if
you are proud of them)
Take-home message: Usefulness is primary
.cpp
GLUP.h – C API
glupBegin(), glupEnd(), glupVertex()
GLUP state
variablesVanillaGL
OpenGL ES /
WebGL
GLSL 1.5
GLSL 4.4
matrix stacks
buffers
Shaders
OpenNL.h – C API
nlBegin(), nlEnd(), nlCoeff(), nlSolve()
.c
CG
GMRes
BiCGStab
SuperLU
CHOLDM
OD
CPU/GPU
Abstraction layer
OpenMP
multicore
CUDA
CuBLAS
CuSparse
ARPACK
NLSparseMatrix NLCRSMatrix
nlCompress()
Take-home message: Usefulness is primary
.cpp
GLUP.h – C API
glupBegin(), glupEnd(), glupVertex()
GLUP state
variablesVanillaGL
OpenGL ES /
WebGL
GLSL 1.5
GLSL 4.4
matrix stacks
buffers
Shaders
OpenNL.h – C API
nlBegin(), nlEnd(), nlCoeff(), nlSolve()
.cpp
CG
GMRes
BiCGStab
SuperLU
CHOLDM
OD
CPU/GPU
Abstraction layer
OpenMP
multicore
CUDA
CuBLAS
CuSparse
ARPACK
NLSparseMatrix NLCRSMatrix
nlCompress()
Algorithms and Data Structures
Mostly arrays (std::vector) and for() loops
Object oriented / virtual functions
Run-time selection of algorithm
Generic programming
For dimension-independent code (RVD)
If() statements
Predicates
Futuristic programming – the product
GLUP.h – C API
glupBegin(), glupEnd(), glupVertex()
OpenNL.h – C API
nlBegin(), nlEnd(), nlCoeff(), nlSolve()
Geogram – C++ API
Mesh class, Delaunay, Voronoi,
Remesh, param., repair, reconstruct.
Predicate Construction Kit
Compiler for arbitrary precision
Geometric predicates (C/C++ API)
Graphite: Qt GUI + LUA scripting
Download from gforge.inria.fr, see also links on my webpage
Acknowledgements
Eurographics Association
European Research Council
GOODSHAPE ERC-StG-205693
VORPALINE ERC-PoC-334829
ANR MORPHO (Vision), ANR BECASIM (Physics)
ANR MAGA (P.I.: Q. Merigot),
ANR ROOT (P.I.: N. Bonneel) Optimal Transport stuff.
Inria EXPLORAGRAM
Key contributors to Geogram/Graphite:
N. Ray, W.-C. Li, B. Vallet, D. Sokolov, N. Bonneel, R. Zayer, A. Sheffer
MOKA team (Monge-Ampere-Kantorovich)
The joy of computer graphics programming
1 sur 288

Contenu connexe

Similaire à The joy of computer graphics programming(20)

DebuggingDebugging
Debugging
Olivier Teytaud332 vues
Ch01lect1 etCh01lect1 et
Ch01lect1 et
AhmedHassanHaji148 vues
10 Ways To Improve Your Code10 Ways To Improve Your Code
10 Ways To Improve Your Code
ConSanFrancisco1231.4K vues
Raising the BarRaising the Bar
Raising the Bar
Alexandru Bolboaca164 vues
From open source labs to ceo methods and advice by sysferaFrom open source labs to ceo methods and advice by sysfera
From open source labs to ceo methods and advice by sysfera
fOSSa - Free Open Source Software Academia Conference1K vues
Open frameworks 101_fitcOpen frameworks 101_fitc
Open frameworks 101_fitc
benDesigning2K vues
TxJS 2011TxJS 2011
TxJS 2011
Brian LeRoux1.2K vues
FEC2017-Introduction-to-programmingFEC2017-Introduction-to-programming
FEC2017-Introduction-to-programming
Henrikki Tenkanen269 vues
Is Python still production ready ? Ludovic GascIs Python still production ready ? Ludovic Gasc
Is Python still production ready ? Ludovic Gasc
Pôle Systematic Paris-Region649 vues
SE-TEXT-BOOK_Material.docSE-TEXT-BOOK_Material.doc
SE-TEXT-BOOK_Material.doc
DrPreethiD16 vues
SE-TEXT-BOOK_Material.docSE-TEXT-BOOK_Material.doc
SE-TEXT-BOOK_Material.doc
DrPreethiD13 vues
Smart+Shanghai+2008 09 05Smart+Shanghai+2008 09 05
Smart+Shanghai+2008 09 05
guestaa42e9258 vues

Plus de Bruno Levy(11)

The joy of computer graphics programming

  • 1. Mathématiques - Informatique Eurographics 2017 Bruno Lévy ALICE Géométrie & Lumière CENTRE INRIA Nancy Grand-Est The Joy of Computer Graphics Programming Bruno Lévy, Inria researcher
  • 2. Introducing myself… First name: Bruno Familly name: Lévy Age: approaching 45 Occupation: Inria ALICE team lead (since 2004) ALICE = Geometry processing + Fabrication (S. Lefebvre) Research: navigating between graphics, math. and physics Code: open-source (geogram),commercial (GOCAD, Vorpaline)
  • 3. Introducing myself… First name: Bruno Familly name: Lévy Age: approaching 45 (born in 1972 = 4004+1) Occupation: Inria ALICE team lead (since 2004) ALICE = Geometry processing + Fabrication (S. Lefebvre) Research: navigating between graphics, math. and physics Code: open-source (geogram),commercial (GOCAD, Vorpaline)
  • 4. OVERVIEW 1. Introduction, let s talk about programming 2. Graphics: eye candy with GLUP 3. Numerics: cranking the number cruncher 4. Geometry: predicates without the agonizing pain What s next ? Physics+Mathematics+Computing=?
  • 6. Part. 1 On Software Design War stories on the design and implementation of geogram, graphite and vorpaline
  • 7. Part. 1 On Software Design War stories on the design and implementation of geogram, graphite and vorpaline Documented open-source* implementations of reference algos. + the most important results from my group (2000 to 2017) Algorithms from >20 research articles and two ERC projects (GOODSHAPE and VORPALINE) *Geogram (BSD) and Graphite (GLP), Vorpaline is proprietary
  • 8. Part. 1 On Software Design War stories on the design and implementation of geogram, graphite and vorpaline Documented open-source* implementations of reference algos., + the most important results from my group (2000 to 2017) Algorithms from >20 research articles and two ERC projects (GOODSHAPE and VORPALINE) •Mesh parameterization (LSCM, ABF++, PGP) •Spectral mesh processing (Manifold Harmonics) •Newton Centroidal Voronoi Tesselation (surfaces and volumes) •Remeshing, reconstruction, Optimal Transport •Low-level algorithms (Delaunay, Voronoi, predicates) … *Geogram (BSD) and Graphite (GLP), Vorpaline is proprietary
  • 9. Part. 1 On Software Design From my attic: my first computer !
  • 10. Part. 1 On Software Design 1979 Apple ][ 6502 processor, 1MHz 64Kb RAM Approx. 10 FLOPs
  • 11. Part. 1 On Software Design 1979 Apple ][ 6502 processor, 1MHz 64Kb RAM Approx. 10 FLOPs 2017 PC Core i7 gen3, 3 GHz 16Gb RAM Approx. 100 GFLOPs
  • 12. Part. 1 On Software Design 1979 Apple ][ 6502 processor, 1MHz 64Kb RAM Approx. 10 FLOPs 2017 PC Core i7 gen3, 3 GHz 16Gb RAM Approx. 100 GFLOPs X 1 million !!!! 38 years
  • 13. Part. 1 On Software Design Boots in 20 seconds Boots in 3 minutes
  • 14. Part. 1 On Software Design Boots in 20 seconds Boots in 3 minutes Where did the 1 million acceleration factor go ?
  • 15. Part. 1 On Software Design What can you do in 20 seconds ? 3 GHz, 4 cores = 240 billions instructions !!
  • 16. Part. 1 On Software Design If you cannot do the job in less than 20 seconds on a modern PC, then there is probably a problem somewhere What can you do in 20 seconds ? 3 GHz, 4 cores = 240 billions instructions !!
  • 17. Part. 1 On Software Design Boots in 20 seconds Boots in 3 minutes Where did the 1 million acceleration factor go ? - Lost in abstraction -
  • 18. Part. 1 On Software Design Abstraction in Programming: + Separates concepts + Separates specification from Implementation
  • 19. Part. 1 On Software Design Abstraction in Programming: + Separates concepts + Separates specification from Implementation - Sometimes separates things that should be considered together !!
  • 20. Part. 1 On Software Design Background on Futuristic Programming Paul Haeberli - 1994 www.graficaobscura.com/future/index.html
  • 21. Part. 1 On Software Design Background on Futuristic Programming Paul Haeberli - 1994
  • 22. Part. 1 On Software Design Futuristic Programming Priorities Paul Haeberli - 1994 1. It is something that has NEVER BEEN DONE BEFORE. 2. The USER LIKES to use the program. 3. The program is as FAST as it can be. 4. The program is as SMALL as it can be. 5. The program is BUG-FREE. 6. The program needs NO USER MAINTENANCE. 7. The program requires NO USER DOCUMENTATION. 8. The program requires NO SYSTEM ADMINISTRATOR
  • 23. Part. 1 On Software Design Geogram/Graphite Programming Priorities 1. Make it as simple as possible (but not simpler)
  • 24. Part. 1 On Software Design 1. Make it as simple as possible (but not simpler) 2. Make it as easy to use as possible Geogram/Graphite Programming Priorities
  • 25. Part. 1 On Software Design 1. Make it as simple as possible (but not simpler) 2. Make it as easy to use as possible 3. Make it as easy to compile as possible Geogram/Graphite Programming Priorities
  • 26. Part. 1 On Software Design 1. Make it as simple as possible (but not simpler) 2. Make it as easy to use as possible 3. Make it as easy to compile as possible 4. Maximize speed Geogram/Graphite Programming Priorities
  • 27. Part. 1 On Software Design 1. Make it as simple as possible (but not simpler) 2. Make it as easy to use as possible 3. Make it as easy to compile as possible 4. Maximize speed 5. Minimize memory consumption Geogram/Graphite Programming Priorities
  • 28. Part. 1 On Software Design 1. Make it as simple as possible (but not simpler) 2. Make it as easy to use as possible 3. Make it as easy to compile as possible 4. Maximize speed 5. Minimize memory consumption 6. Minimize number of lines of code Geogram/Graphite Programming Priorities
  • 29. Part. 1 On Software Design 1. Make it as simple as possible (but not simpler) 2. Make it as easy to use as possible 3. Make it as easy to compile as possible 4. Maximize speed 5. Minimize memory consumption 6. Minimize number of lines of code 7. Minimize number of C++ classes Geogram/Graphite Programming Priorities
  • 30. Part. 1 On Software Design 1. Make it as simple as possible (but not simpler) 2. Make it as easy to use as possible 3. Make it as easy to compile as possible 4. Maximize speed 5. Minimize memory consumption 6. Minimize number of lines of code 7. Minimize number of C++ classes Geogram/Graphite Programming Priorities Simplicity is the ultimate sophistication
  • 31. Part. 1 On Software Design 1. Make it as simple as possible (but not simpler) 2. Make it as easy to use as possible 3. Make it as easy to compile as possible 4. Maximize speed 5. Minimize memory consumption 6. Minimize number of lines of code 7. Minimize number of C++ classes Geogram/Graphite Programming Priorities Simplicity is the ultimate sophistication
  • 32. Part. 1 On Software Design 1. Make it as simple as possible (but not simpler) 2. Make it as easy to use as possible 3. Make it as easy to compile as possible 4. Maximize speed 5. Minimize memory consumption 6. Minimize number of lines of code 7. Minimize number of C++ classes 8. Systematically document all classes, all functions, [+Biblio.] 9. Systematically document the implementation of all algorithms 10. Assertion checks everywhere 11. Zero warnings with all compilers / platforms 12. Perform systematic non-regression testing and mem. check. Geogram/Graphite Programming Priorities
  • 33. Part. 1 On Software Design Futuristic programming Usefullness (and coolness) are primary !
  • 34. Part. 1 On Software Design • Jonathan Shewchuk s Triangle and exact predicates • Tetgen, MGTetra, MMG3d • Omar Cornut s ImGUI library • David Mount s ANN library • The LUA prog. language Futuristic programming Examples of Futuristic codes Usefullness (and coolness) are primary !
  • 35. Part. 1 On Software Design Case study: mesh data structures From several Computer Graphics / Mesh Processing 101 courses - including (earlier versions of) mine -
  • 36. Halfedges Design Principles 1. Individual combinatorial elements can be created/destroyed at any time in constant time 2. Basic operations (collapse, split, ) 3. Higher-level operations on top of them Part. 1 On Software Design Case study: mesh data structures Halfedges and edgeuses, harmful or useful ?
  • 37. + Benefit of abstraction: layered design Part. 1 On Software Design Case study: mesh data structures Halfedges Design Principles 1. Individual combinatorial elements can be created/destroyed at any time in constant time 2. Basic operations (collapse, split, ) 3. Higher-level operations on top of them Halfedges and edgeuses, harmful or useful ?
  • 38. + Benefit of abstraction: layered design - Separates things that should have been considered together Part. 1 On Software Design Case study: mesh data structures Halfedges and edgeuses, harmful or useful ? Halfedges Design Principles 1. Individual combinatorial elements can be created/destroyed at any time in constant time 2. Basic operations (collapse, split, ) 3. Higher-level operations on top of them
  • 39. + Benefit of abstraction: layered design - Separates things that should have been considered together Not the optimal level of granularity Part. 1 On Software Design Case study: mesh data structures Halfedges and edgeuses, harmful or useful ? Halfedges Design Principles 1. Individual combinatorial elements can be created/destroyed at any time in constant time 2. Basic operations (collapse, split, ) 3. Higher-level operations on top of them
  • 40. Part. 1 On Software Design Case study: mesh data structures Indexed Mesh data structure (no data structure)
  • 41. Part. 1 On Software Design Case study: mesh data structures Indexed Mesh data structure (no data structure)
  • 42. Part. 1 On Software Design Case study: mesh data structures Indexed Mesh data structure (no data structure)
  • 43. Part. 1 On Software Design Case study: mesh data structures Indexed Mesh data structure (no data structure)
  • 44. Part. 1 On Software Design Case study: mesh data structures Indexed Mesh data structure (no data structure)
  • 45. Part. 1 On Software Design Case study: mesh data structures Indexed Mesh data structure (no data structure)
  • 46. Objection ! (?) Deletion of one individual element is O(n) instead of constant In fact: deleting 1 element = wrong granularity level ! Part. 1 On Software Design Case study: mesh data structures Indexed Mesh data structure (no data structure)
  • 47. Deleting a bunch of elements Part. 1 On Software Design Case study: mesh data structures Indexed Mesh data structure (no data structure)
  • 48. Deleting a bunch of elements Part. 1 On Software Design Case study: mesh data structures Indexed Mesh data structure (no data structure)
  • 49. Deleting a bunch of elements Part. 1 On Software Design Case study: mesh data structures Indexed Mesh data structure (no data structure)
  • 50. Deleting a bunch of elements – operates also in O(n) – right granularity Part. 1 On Software Design Case study: mesh data structures Indexed Mesh data structure (no data structure)
  • 51. Deleting a bunch of elements – operates also in O(n) – right granularity Part. 1 On Software Design Case study: mesh data structures Needs array permutation (not in the STL unfortunately, but easy to implement, see GEOGRAM::permutation). Indexed Mesh data structure (no data structure)
  • 52. Indexed Mesh data structure (no data structure) Summary: •An array of vertices coordinates •An array of triangle vertices indices Part. 1 On Software Design Case study: mesh data structures
  • 53. •An array of vertices coordinates •An array of triangle vertices indices •An array of triangle adjacencies (optional) •An array of facet first indices (optional) Part. 1 On Software Design Case study: mesh data structures Indexed Mesh data structure (no data structure) Summary:
  • 54. Benefits of such a non-datastructure, non-object, non-oriented, (non-)programming 1. Simpler code Part. 1 On Software Design Case study: mesh data structures
  • 55. Benefits of such a non-datastructure, non-object, non-oriented, (non-)programming 1. Simpler code 2. Less memory; Part. 1 On Software Design Case study: mesh data structures
  • 56. Benefits of such a non-datastructure, non-object, non-oriented, (non-)programming 1. Simpler code 2. Less memory; 3. Parallelization #pragma omp parallel for Part. 1 On Software Design Case study: mesh data structures
  • 57. Benefits of such a non-datastructure, non-object, non-oriented, (non-)programming 1. Simpler code 2. Less memory; 3. Parallelization #pragma omp parallel for 4. Easy copy: memcpy() Part. 1 On Software Design Case study: mesh data structures
  • 58. Benefits of such a non-datastructure, non-object, non-oriented, (non-)programming 1. Simpler code 2. Less memory; 3. Parallelization #pragma omp parallel for 4. Easy copy: memcpy() 5. Easy I/O: fread()/fwrite() Part. 1 On Software Design Case study: mesh data structures
  • 59. Benefits of such a non-datastructure, non-object, non-oriented, (non-)programming 1. Simpler code 2. Less memory; 3. Parallelization #pragma omp parallel for 4. Easy copy: memcpy() 5. Easy I/O: fread()/fwrite() 6. Properties/attributes are simply additional arrays Part. 1 On Software Design Case study: mesh data structures
  • 60. Benefits of such a non-datastructure, non-object, non-oriented, (non-)programming 1. Simpler code 2. Less memory; 3. Parallelization #pragma omp parallel for 4. Easy copy: memcpy() 5. Easy I/O: fread()/fwrite() 6. Properties/attributes are simply additional arrays 7. Directly understood by OpenGL: VertexBufferObject Part. 1 On Software Design Case study: mesh data structures
  • 61. A mesh = a bunch of arrays (std::vectors) Part. 1 On Software Design Case study: mesh data structures
  • 62. A mesh = a bunch of arrays (std::vectors) How do you iterate on a vector ? Part. 1 On Software Design Case study: mesh data structures
  • 63. Pre-2011: for(std::vector<Thing>::iterator it = V.begin(); it!=V.end(); ++it) { do something with *it } Part. 1 On Software Design Case study: mesh data structures How do you iterate on a vector ?
  • 64. Pre-2011: for(std::vector<Thing>::iterator it = V.begin(); it!=V.end(); ++it) { do something with *it } Part. 1 On Software Design Case study: mesh data structures How do you iterate on a vector ? It s a pain to type Clutters the source-code (less legible)
  • 65. Pre-2011: for(std::vector<Thing>::iterator it = V.begin(); it!=V.end(); ++it) { do something with *it } 2011: for(auto it = V.begin(); it!=V.end(); ++it) { do something with *it } Part. 1 On Software Design Case study: mesh data structures How do you iterate on a vector ?
  • 66. Pre-2011: for(std::vector<Thing>::iterator it = V.begin(); it!=V.end(); ++it) { do something with *it } 2011: for(auto it = V.begin(); it!=V.end(); ++it) { do something with *it } now: for(auto&& i : V) { do something with i } Part. 1 On Software Design Case study: mesh data structures How do you iterate on a vector ?
  • 67. A mesh = a bunch of arrays (std::vectors) How do you iterate on a vector ? Part. 1 On Software Design Case study: mesh data structures Warning: flying tomatoes alert ahead, (modern C++ lovers might throw tomatoes at me)!
  • 68. Pre-2011: for(std::vector<Thing>::iterator it = V.begin(); it!=V.end(); ++it) { do something with *it } 2011: for(auto it = V.begin(); it!=V.end(); ++it) { do something with *it } now: for(auto&& i : V) { do something with I } Part. 1 On Software Design Case study: mesh data structures How do you iterate on a vector ?
  • 69. How I iterate on a vector: for(uint i=0; i<V.size(); ++i) { do something with V[i]; } Part. 1 On Software Design Case study: mesh data structures How do you iterate on a vector ?
  • 70. How I iterate on a vector: for(uint i=0; i<V.size(); ++i) { do something with V[i]; } Part. 1 On Software Design Case study: mesh data structures + Easy to understand, even by C-only and Fortran programmers + Compatible with all compilers + #pragma omp parallel-for friendly* (and also better vectorization) - 15 additional keystrokes as compared to modern C++ range-for How do you iterate on a vector ? *But use ints instead of uints, omp does not like uints
  • 71. How I iterate on a vector: for(uint i=0; i<V.size(); ++i) { do something with V[i]; } Part. 1 On Software Design Case study: mesh data structures + Easy to understand, even by C-only programmers + Compatible with all compilers + #pragma omp parallel-for friendly - 15 additional keystrokes as compared to modern C++ range-for The following code has been approved for APPROPRIATE AUDIENCES PG-13
  • 72. How I iterate on a vector: for(uint i=0; i<V.size(); ++i) { do something with V[i]; } Part. 1 On Software Design Case study: mesh data structures + Easy to understand, even by C-only programmers + Compatible with all compilers + #pragma omp parallel-for friendly - 15 additional keystrokes as compared to modern C++ range-for #define FOR(i,N) for(uint i=0; i<(N); ++i) FOR(i,V.size()) { do something with V[i]; } + Easy to understand, legible + Trivial iterations easy to spot - Macros are evil [Nicolas Ray]
  • 73. Part. 1 On Software Design Case study: mesh data structures Objection: It is bad because it is not flexible, what if you want to adapt your algorithm to another container ?
  • 74. Part. 1 On Software Design Case study: mesh data structures Objection: It is bad because it is not flexible, what if you want to adapt your algorithm to another container ? Answer: I m not going to use something else than a vector, because it is the best choice for the mesh data structure. Why keeping a tuning knob on the dash board if it is always on the same position ? modern/generic != futuristic
  • 75. Part. 1 On Software Design Case study: mesh data structures Objection: It is bad because it is not flexible, what if you want to adapt your algorithm to another container ? Answer: I m not going to use something else than a vector, because it is the best choice for the mesh data structure. Why keeping a tuning knob on the dash board if it is always on the same position ? (think of the I-Phone) The Nokia N95, a modern/generic phone. The I-phone, a futuristic phone. modern/generic != futuristic
  • 76. Part. 1 On Software Design Case study: mesh data structures modern/generic != futuristic It is good because it has everything that you need The Nokia N95, a modern/generic phone. The I-phone, a futuristic phone.
  • 77. Part. 1 On Software Design Case study: mesh data structures modern/generic != futuristic It is good because it has everything that you need It is even better because it has nothing else than what you need The Nokia N95, a modern/generic phone. The I-phone, a futuristic phone.
  • 78. Part. 1 On Software Design Case study: mesh data structures modern/generic != futuristic It is good because it has everything that you need It is even better because it has nothing else than what you need Work is finished when you have nothing to add and nothing to remove ! The Nokia N95, a modern/generic phone. The I-phone, a futuristic phone.
  • 79. Part. 1 On Software Design Case study: mesh data structures Why keeping a tuning knob on the dash board if it is always on the same position ? (think of the I-Phone) A parameter that always has the same value is not a parameter and should be removed from the API. A template that is instanced only once should not be a template.
  • 80. Part. 1 On Software Design Case study: mesh data structures A parameter that always has the same value is not a parameter and should be removed from the API. A template that is instanced only once should not be a template. Objection: but we loose genericity if we do that ??? Why keeping a tuning knob on the dash board if it is always on the same position ? (think of the I-Phone)
  • 81. Part. 1 On Software Design Case study: mesh data structures A parameter that always has the same value is not a parameter and should be removed from the API. A template that is instanced only once should not be a template. Objection: but we loose genericity if we do that ??? Answer to objection: but we gain a lot, it declutters the code, makes it more legible, reduces compilation times, makes C++ compilation error messages more legible. Why keeping a tuning knob on the dash board if it is always on the same position ? (think of the I-Phone)
  • 82. Part. 1 On Software Design Case study: mesh data structures Rule of thumb: Make it a parameter not before you need it with at least two different values. Make it a template not before you need at least two different instanciations. *regarding compilation time, legibiity of error messages and run-time flex.
  • 83. Part. 1 On Software Design Case study: mesh data structures Rule of thumb: Make it a parameter not before you need it with at least two different values. Make it a template not before you need at least two different instanciations. About templates, consider less annoying* alternatives, such as (1) object oriented programming / virtual functions (2) or simply a parameter and if() statements *regarding compilation time, legibility of error messages and run-time flex.
  • 84. Graphics 2 Fast and Easy eye-candy with GLUP
  • 85. Part. 2 Graphics – endangered species The Windows start menu The I-Phone jack glBegin(GL_TRIANGLES) glVertex(… ) glEnd() OpenGL immediate mode glPush/Pop/MultMatrix() glLight() OpenGL fixed functionality pipeline
  • 86. Part. 2 Graphics – endangered species glBegin(GL_TRIANGLES) glVertex(… ) glEnd() OpenGL immediate mode glPush/Pop/MultMatrix() glLight() OpenGL fixed functionality pipeline Difficulties for an undergraduate who starts: (1) Assemble vertex buffer objects (2) Design vertex and fragment shaders (3) (+ the Professor, I see nothing syndrom, nothing new here) R.I.P. R.I.P.
  • 87. Part. 2 Graphics – GLUP Immediate mode + fixed functionality pipeline implemented in modern OpenGL (4.x) (nearly source-compatible) glupBegin(), glupEnd(), glupVertex(), glupPushMatrix()…
  • 88. Part. 2 Graphics – GLUP Immediate mode + fixed functionality pipeline implemented in modern OpenGL (4.x) (nearly source-compatible) glupBegin(), glupEnd(), glupVertex(), glupPushMatrix()… normals not needed (per-fragment shading)
  • 89. Part. 2 Graphics – GLUP Immediate mode + fixed functionality pipeline implemented in modern OpenGL (4.x) (nearly source-compatible) glupBegin(), glupEnd(), glupVertex(), glupPushMatrix()… normals not needed (per-fragment shading) new volumetric primitives: GLUP_TETRAHEDRA, GLUP_HEXAHEDRA, GLUP_PRISMS, GLUP_PYRAMIDS, GLUP_SPHERES
  • 90. Part. 2 Graphics – GLUP Immediate mode + fixed functionality pipeline implemented in modern OpenGL (4.x) (nearly source-compatible) glupBegin(), glupEnd(), glupVertex(), glupPushMatrix()… normals not needed (per-fragment shading) new volumetric primitives: GLUP_TETRAHEDRA, GLUP_HEXAHEDRA, GLUP_PRISMS, GLUP_PYRAMIDS, GLUP_SPHERES new clipping modes (on-GPU marching cells algorithm)
  • 91. Part. 2 Graphics – GLUP Immediate mode + fixed functionality pipeline implemented in modern OpenGL (4.x) (nearly source-compatible) glupBegin(), glupEnd(), glupVertex(), glupPushMatrix()… normals not needed (per-fragment shading) new volumetric primitives: GLUP_TETRAHEDRA, GLUP_HEXAHEDRA, GLUP_PRISMS, GLUP_PYRAMIDS, GLUP_SPHERES new clipping modes (on-GPU marching cells algorithm) glupEnable(GLUP_DRAW_MESH)
  • 92. Part. 2 Graphics – GLUP glupDrawArrays(), glupDrawElements(), VBOs VanillaGL (1.x) OpenGL ES, WebGL GLSL 1.5 (GL3.3) GLSL 4.4 (GL4.4) POINTS LINES TRGLS QUADS SPHERES T ETS PRISMS HEXES PYRAMIDS glupDrawArrays()/glupDrawElements()/VBOs and immediate mode Immediate mode only
  • 93. Part. 2 Graphics – GLUP
  • 94. Part. 2 Graphics – GLUP
  • 95. Part. 2 Graphics – GLUP glupDrawElements(GLUP_TETRAHEDRA) 1 single draw call with VBOs, everything occurs on GPU glupSetClippingMode(GLUP_CLIP_SLICE)
  • 96. Part. 2 Graphics – GLUP
  • 97. Part. 2 Graphics – GLUP glupDrawElements(GLUP_SPHERES) 1 single draw call with VBOs, everything occurs on GPU (GLUP + screen-space ambient occlusion in Graphite)
  • 98. Part. 2 Graphics – GLUP
  • 99. Part. 2 Graphics – GLUP glupDrawElements(GLUP_HEXAHEDRA) glupDrawElements(GLUP_TETRAHEDRA) 2 draw calls with VBOs, everything occurs on GPU (GLUP + screen-space ambient occlusion in Graphite) Hexahedral-dominant mesh [Ray, Sokolov, Unterreiner, L 2016]
  • 100. Part. 2 Graphics – GLUP glupDrawElements(GLUP_HEXAHEDRA) glupDrawElements(GLUP_TETRAHEDRA) 2 draw calls with VBOs, everything occurs on GPU (GLUP + screen-space ambient occlusion in Graphite) Cross-section computed with on-GPU marching cells with interpolated attrib.
  • 102. Part. 3. Numerics Numerical problems: neighborhoods F = sum of terms, attached to neighborhoods Discrete fairing [Kobbelt98, Mallet95] Parameterization [Desbrun02] Deformations [CohenOr], [Sorkine] Curv. Estimation [Cohen-Steiner 03] Texture mapping [L01] Discrete fairing [Desbrun], ... Parameterization [Haker00] [L02] [Eck]
  • 103. Part. 3. Numerics Numerical problems: mesh parameterization i j1 j2 j… Ui = ai,jUj j  Ni  i,j ai,j > 0 ai,i = -  ai,j The border is mapped to a convex polygon [Tutte], [Floater]
  • 104. Part. 3. Numerics Numerical problems: mesh fairing i j1 j2 j… F(p)=  pi - ai,jpj 2 j  Nii [Mallet], [Kobbelt], [Sorkine]
  • 105. Part. 3. Numerics Numerical problems: mesh fairing
  • 106. Part. 3. Numerics Numerical problems: mesh fairing F(x) = 2A x - b
  • 107. Part. 3. Numerics Numerical problems: mesh fairing F(xf) = xf xl [ Af Al] - b 2 F(x) = 2A x - b
  • 108. Part. 3. Numerics Numerical problems: least squares F(xf) = A.x - d = Al.xl + Af.xf - d 2 2
  • 109. Part. 3. Numerics Numerical problems: least squares F(xf) = A.x - d = Al.xl + Af.xf - d 2 2 F(xf) minimum Af t.Af.xf = Af t.d - Af tAl.xl M.x = b } }
  • 110. Part. 3. Numerics Numerical problems: least squares F(xf) = A.x - d = Al.xl + Af.xf - d 2 2 F(xf) minimum Af t.Af.xf = Af t.d - Af tAl.xl M.x = b } } The problem: (1) construct the linear system (assembly) (2) solve a linear system
  • 111. Part. 3. Numerics – the OpenNL library. Numerical problems: least squares The problem: (1) construct the linear system (assembly) (2) solve a linear system
  • 112. Part. 3. Numerics – the OpenNL library. Numerical problems: least squares The problem: (1) construct the linear system (assembly) (2) solve a linear system Similarity between a mesh and a sparse matrix:
  • 113. Part. 3. Numerics – the OpenNL library. Numerical problems: least squares The problem: (1) construct the linear system (assembly) (2) solve a linear system nlBegin(NL_ROW) nlAddCoefficient(I,j,val) nlRightHandSide(val) nlEnd(NL_ROW) Similarity between a mesh and a sparse matrix: OpenNL: API inspired by OpenGL immediate mode. (+ automatic construction of AtA for least-squares)
  • 114. Part. 3. Numerics – the OpenNL library. Numerical problems: least squares The problem: (1) construct the linear system (assembly) (2) solve a linear system NLSparseMatrix: dynamic data structure (can grow) OpenNL internals … … … … …
  • 115. Part. 3. Numerics – the OpenNL library. Numerical problems: least squares The problem: (1) construct the linear system (assembly) (2) solve a linear system NLSparseMatrix NLCRSMatrix OpenNL internals nlCompress()
  • 116. Part. 3. Numerics – the OpenNL library. Numerical problems: least squares The problem: (1) construct the linear system (assembly) (2) solve a linear system NLSparseMatrix NLCRSMatrix NLCusparseMatrix OpenNL internals GPU nlCompress() (optionnal)
  • 117. Part. 3. Numerics – the OpenNL library Numerical problems: least squares The problem: (1) construct the linear system (assembly) (2) solve a linear system nlSolve() Iterative solvers CG GMRes BiCGStab CPU/GPU Abstraction layer OpenMP multicore CUDA CuBLAS CuSparse
  • 118. Part. 3. Numerics – the OpenNL library Numerical problems: least squares The problem: (1) construct the linear system (assembly) (2) solve a linear system nlSolve() Iterative solvers Direct solvers CG GMRes BiCGStab SuperLU CHOLDMOD CPU/GPU Abstraction layer OpenMP multicore CUDA CuBLAS CuSparse
  • 119. Part. 3. Numerics – the OpenNL library Numerical problems: least squares The problem: (1) construct the linear system (assembly) (2) solve a linear system nlSolve() Iterative solvers Direct solvers CG GMRes BiCGStab SuperLU CHOLDMOD CPU/GPU Abstraction layer OpenMP multicore CUDA CuBLAS CuSparse Eigen solver ARPACK
  • 120. Part. 3. Numerics – the OpenNL library OpenNL as a pluggable software module Following futuristic programming principles: * OpenNL also available as a single .c,.h pair, portable to all architectures, easy to compile. * Object-Oriented abstract matrix interface in C (achieves run-time CPU/GPU flexibility) * Dynamically loads CUDA CuBLAS and CuSparse on demand (as well as CHOLMOD, SUPERLU,ARPACK) * Double precision (and no single precision).
  • 121. Part. 3. Numerics – the OpenNL library OpenNL at work Everything available in geogram GUI in graphite
  • 122. Part. 3. Numerics – the OpenNL library OpenNL at work LSCM, Spectral parameterization. (600 lines of code for both) ABF++ (800 lines of code) PGP, QuadCover, MIP. (700 lines of code) Manifold Harmonics, HKS, ADF. (400 lines of code) Everything available in geogram GUI in graphite
  • 123. Part. 3. Numerics – the OpenNL library OpenNL at work Everything available in geogram GUI in graphite Baby groot © Marvel (this version by Byambaa on Thingyverse)
  • 124. Part. 3. Numerics – the OpenNL library OpenNL at work Everything available in geogram GUI in graphite Automatic decimation and normal map generation. Baby groot © Marvel (this version by Byambaa on Thingyverse)
  • 125. Geometry 4 Predicates without the agonizing pain* *Section title is a tribute to Jonathan Shewchuk.
  • 127. 4. Geometry - Motivations [Martinez, Dumas, Lefebvre]
  • 128. 4. Geometry - Motivations
  • 131. Part. 4. Geometry Computing (restricted) Voronoi diagrams
  • 132. Part. 4. Geometry Computing (restricted) Voronoi diagrams
  • 133. Part. 4 Geometry Pointset X Simplicial complex S either triangulated surface or tetrahedralized solid The input
  • 134. Part. 4 Geometry Vor(X)|S (Intersection between Vor(X) and S) The output
  • 135. Part 4. Geometry – a difficult dataset Lots of degeneracies: Voronoi diagram with degree 4 vertices. Voronoi cell faces match exactly facets of the initial surface.
  • 136. Part. 4 Geometry Voronoi cells as iterative convex clipping Half-space clipping xi x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11
  • 137. Part. 4 Difficulties – predicates xi xj Elementary operation: cut a polygon (or polyhedron) with a bisector
  • 138. Part. 4 Difficulties – predicates xi xj Elementary operation: cut a polygon (or polyhedron) with a bisector Classify the vertices of the polygon
  • 139. Part. 4 Difficulties – predicates xi xj Elementary operation: cut a polygon (or polyhedron) with a bisector Classify the vertices of the polygon Sign( d(p,xj) – d(p,xi)) > 0
  • 140. Part. 4 Difficulties – predicates xi xj Elementary operation: cut a polygon (or polyhedron) with a bisector Classify the vertices of the polygon Sign( d(p,xj) – d(p,xi)) > 0 Sign( d(p,xj) – d(p,xi)) < 0
  • 141. Part. 4 Difficulties – predicates xi xj Elementary operation: cut a polygon (or polyhedron) with a bisector Classify the vertices of the polygon Compute the intersections Sign( d(p,xj) – d(p,xi)) > 0 Sign( d(p,xj) – d(p,xi)) < 0
  • 142. Part. 4 Difficulties – predicates xi xj Sign( d(p,xj) – d(p,xi)) > 0 Sign( d(p,xj) – d(p,xi)) < 0 Elementary operation: cut a polygon (or polyhedron) with a bisector Classify the vertices of the polygon Compute the intersections - discard
  • 143. Part. 4 Difficulties – predicates xi xj xk Now clipping with the bisector of (xi, xk)
  • 144. Part. 4 Difficulties – predicates xi xj xk Now clipping with the bisector of (xi, xk) We need to classify all the points, including these ones !
  • 145. Part. 4 Difficulties – predicates xi xj xk Now clipping with the bisector of (xi, xk) We need to classify all the points, including these ones ! (they are intersections between a segment and a bisector)
  • 146. Part. 4 Difficulties – predicates xi xj xk Now clipping with the bisector of (xi, xk) We need to classify all the points, including these ones ! (they are intersections between a segment and a bisector) This generates a new intersection (between a facet and two bisector)
  • 147. Part. 4 Difficulties – predicates Three configurations 1) Side(xi,xj,q) where q is a vertex of S
  • 148. Part. 4 Difficulties – predicates Three configurations 1) Side1(xi,xj,q)
  • 149. Part. 4 Difficulties – predicates Three configurations 1) Side1(xi,xj,q) 2) Side(xi,xj,q) where q = π(i,k) ∩ [p1,p2]
  • 150. Part. 4 Difficulties – predicates Three configurations 1) Side1(xi,xj,q) 2) Side2(xi,xj,xk,p1,p2)
  • 151. Part. 4 Difficulties – predicates Three configurations 1) Side1(xi,xj,q) 2) Side2(xi,xj,xk,p1,p2) 3) Side(xi,xj,q) where q = π(i,k) ∩ π(i,l) ∩ [p1,p2,p3]
  • 152. Part. 4 Difficulties – predicates Three configurations 1) Side1(xi,xj,q) 2) Side2(xi,xj,xk,p1,p2) 3) Side3(xi,xj,xk, xl,p1,p2,p3)
  • 153. Part. 4 Difficulties – predicates Three configurations 1) Side1(xi,xj,q) 2) Side2(xi,xj,xk,p1,p2) 3) Side3(xi,xj,xk, xl,p1,p2,p3) Implementations of exact predicates: - J. Shewchuk s code - CGAL (Pion, Meyer)
  • 154. Part. 4 Difficulties – predicates Three configurations 1) Side1(xi,xj,q) 2) Side2(xi,xj,xk,p1,p2) 3) Side3(xi,xj,xk, xl,p1,p2,p3) Implementations of exact predicates: - J. Shewchuk s code - CGAL (Pion, Meyer) They do not have Side1(), Side2(), Side3() ( exotic predicates )
  • 155. Part. 4 Difficulties – predicates Three configurations 1) Side1(xi,xj,q) 2) Side2(xi,xj,xk,p1,p2) 3) Side3(xi,xj,xk, xl,p1,p2,p3) How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign()
  • 156. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() Wish list: • Easy to use (no Guru needed for each new predicate) • Reasonably efficient • Easy to compile/integrate ( Futuristic programming ) (multi_precision.h, multi_precision.cpp and that s all)
  • 157. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() Idea #1: (dense) multi-precision (GMP) a0a1a2a3 x 20 x 21*32x 22*32x 23*32 … Each number is an array of (32 bits) integers: Implement +,-,* (reasonably easy) Sign: look at the leading non-zero component
  • 158. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() Idea #1: (dense) multi-precision (GMP) a limitation : c = a10 * 210*32 + b0
  • 159. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() Idea #1: (dense) multi-precision (GMP) a limitation : b000a10 x 20x 210*32 c = a10 * 210*32 + b0 …
  • 160. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() Idea #2: (sparse) multi-precision b0 | 0a10 | 10 c = a10 * 210*32 + b0 Store the exponents of the components
  • 161. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() Idea #2: (sparse) multi-precision b0 | 0a10 | 10 c = a10 * 210*32 + b0 Exp. Exp.
  • 162. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() Idea #2: (sparse) multi-precision b0 | 0a10 | 10 c = a10 * 210*32 + b0 Exp. Exp.mantissa mantissa
  • 163. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() Idea #2: (sparse) multi-precision b0 | 0a10 | 10 c = a10 * 210*32 + b0 Exp. Exp.mantissa mantissa These are floating point numbers !!!
  • 164. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() Idea #3: expansions (Shewchuk) x3 x2 x1 … Each number is represented by the sum of an array of components These are floating point numbers !!!
  • 165. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() Idea #3: expansions (Shewchuk) x3 x2 x1 … Each number is represented by the sum of an array of components They are sorted in decreasing exponents These are floating point numbers !!!
  • 166. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() Idea #3: expansions (Shewchuk) x3 x2 x1 … Each number is represented by the sum of an array of components They are sorted in decreasing exponents They are non-overlapping These are floating point numbers !!!
  • 167. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() Idea #3: expansions (Shewchuk) x3 x2 x1 … Each number is represented by the sum of an array of components They are sorted in decreasing exponents They are non-overlapping The sign is determined by the first component (highest exponent) These are floating point numbers !!!
  • 168. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() Idea #3: expansions (Shewchuk) x2 x1Two_sum(double a, double b)
  • 169. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() Idea #3: expansions (Shewchuk) x2 x1Two_sum(double a, double b) + Length: l+m Length l Length m
  • 170. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() Idea #3: expansions (Shewchuk) x2 x1Two_sum(double a, double b) + * Length: l+m Length: 2*l A double Length l
  • 171. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() Idea #3: expansions (Shewchuk) * … Length: 2*l*m Expansion * Expansion product implemented by a recursive function ( distillation ) Length l Length m
  • 172. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() Idea #3: expansions (Shewchuk) * … Expansion * Expansion product implemented by a recursive function ( distillation ) Performance ? 10 to 40 times slower than standard doubles Length: 2*l*mLength l Length m
  • 173. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() Idea #3: expansions (Shewchuk) * … Expansion * Expansion product implemented by a recursive function ( distillation ) Performance ? 10 to 40 times slower than standard doubles Use arithmetic filters Adaptive precision [Shewchuk] ? Too complicated to get right Length: 2*l*mLength l Length m
  • 174. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() Idea #3: expansions (Shewchuk) * … Expansion * Expansion product implemented by a recursive function ( distillation ) Performance ? 10 to 40 times slower than standard doubles Use arithmetic filters Adaptive precision [Shewchuk] ? Too complicated to get right Quasi-static filters [Meyer and Pion] – FPG generator (easy to use) Length: 2*l*mLength l Length m
  • 175. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() PCK (Predicate Construction Kit) multi_precision.h / multi_precision.cpp A low-level expansion class (allocates expansions on stack) A high-level C++ number type (+,-,*,Sign overloads) a compiler that generates the filter with FPG [Meyer and Pion] and the exact precision version with expansions
  • 176. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() PCK (Predicate Construction Kit) multi_precision.h / multi_precision.cpp A low-level expansion class (allocates expansions on stack) A high-level C++ number type (+,-,*,Sign overloads) a compiler that generates the filter with FPG [Meyer and Pion] and the exact precision version with expansions (why not templates / metaprogramming ? would be possible, but specialized language is much better here).
  • 177. Part. 4 Exact Arithmetics How to implement Side1(), Side2(), Side3() ? We need an exact number type with +,-,*,Sign() PCK (Predicate Construction Kit) multi_precision.h / multi_precision.cpp A low-level expansion class (allocates expansions on stack) A high-level C++ number type (+,-,*,Sign overloads) a compiler that generates the filter with FPG [Meyer and Pion] and the exact precision version with expansions So we are done ?
  • 178. Part. 4 Symbolic Perturbation How to implement Side1(), Side2(), Side3() ? xi xj Not yet !!
  • 179. Part. 4 Symbolic Perturbation How to implement Side1(), Side2(), Side3() ? xi xj Not yet !!
  • 180. Part. 4 Symbolic Perturbation
  • 181. Part. 4 Symbolic Perturbation
  • 182. Part. 4 Symbolic Perturbation
  • 183. Part. 4 Symbolic Perturbation
  • 184. Part. 4 Symbolic Perturbation
  • 185. Part. 4 Symbolic Perturbation
  • 186. Part. 4 Symbolic Perturbation
  • 187. Part. 4 Symbolic Perturbation
  • 188. Part. 4 Symbolic Perturbation
  • 189. Part. 4 Symbolic Perturbation
  • 190. Part. 4 Symbolic Perturbation
  • 191. Part. 4 Symbolic Perturbation
  • 192. Part. 4 Symbolic Perturbation
  • 193. Part. 4 Symbolic Perturbation
  • 194. Part. 4 Symbolic Perturbation
  • 195. Part. 4 Symbolic Perturbation
  • 197. [Voronoi] [Edelsbrunner et.al] [Devillers et.al] Part. 4 Symbolic Perturbation Each point pi is replaced by a trajectory pi(ε) xi(ε) = xi + ε3i yi(ε) = yi + ε3i+1 zi(ε) = zi + ε3i+2 For instance:
  • 198. [Voronoi] [Edelsbrunner et.al] [Devillers et.al] Part. 4 Symbolic Perturbation Each point pi is replaced by a trajectory pi(ε) Take the limit when ε tends to 0
  • 199. xi xj π(i,j) = {p | d2(p,xi) = d2(p,xj)} [Voronoi] [Edelsbrunner et.al] [Devillers et.al] Part. 4 Symbolic Perturbation In our case, perturb the weights of a power diagram.
  • 200. xi xj πw(i,j) = {p | d2(p,xi) - wi = d2(p,xj) - wj} [Voronoi] [Edelsbrunner et.al] [Devillers et.al] Part. 4 Symbolic Perturbation In our case, perturb the weights of a power diagram.
  • 201. xi xj πw(i,j) = {p | d2(p,xi) - wi = d2(p,xj) - wj} [Voronoi] [Edelsbrunner et.al] [Devillers et.al] The Voronoi diagram is replaced with a power diagram Part. 4 Symbolic Perturbation
  • 202. xi xj πw(i,j) = {p | d2(p,xi) - wi = d2(p,xj) - wj} [Voronoi] [Edelsbrunner et.al] [Devillers et.al] The Voronoi diagram is replaced with a power diagram Symbolic perturbation – Simulation of Simplicity: Define the weight as a function of ε: wi = εi Part. 4 Symbolic Perturbation
  • 203. xi xj πw(i,j) = {p | d2(p,xi) - wi = d2(p,xj) - wj} [Voronoi] [Edelsbrunner et.al] [Devillers et.al] The Voronoi diagram is replaced with a power diagram Symbolic perturbation – Simulation of Simplicity: Define the weight as a function of ε: wi = εi The combinatorics is determined by the limit ε →0 Part. 4 Symbolic Perturbation
  • 204. How to write side1(), side2(), side3(), side4() ? d2(q,pj)-wj – d2(q,pi) + wi where: q = πw(i,k1) ∩ …πw(i,kd) ∩ [p1,p2,p3…pd] Part. 4 Symbolic Perturbation
  • 205. How to write side1(), side2(), side3(), side4() ? d2(q,pj)-wj – d2(q,pi) + wi where: q = πw(i,k1) ∩ …πw(i,kd) ∩ [p1,p2,p3…pd] Solve for q in: q Є πw(i,k1) … q Є πw(i,kd) q Є [p1,p2,p3…pd] { Part. 4 Symbolic Perturbation
  • 206. How to write side1(), side2(), side3(), side4() ? d2(q,pj)-wj – d2(q,pi) + wi where: q = πw(i,k1) ∩ …πw(i,kd) ∩ [p1,p2,p3…pd] q = (1/d) Q Keep numerator and denom. separate (remember, we are not allowed to divide) Solve for q in: q Є πw(i,k1) … q Є πw(i,kd) q Є [p1,p2,p3…pd] { Part. 4 Symbolic Perturbation
  • 207. How to write side1(), side2(), side3(), side4() ? d2(q,pj)-wj – d2(q,pi) + wi where: q = πw(i,k1) ∩ …πw(i,kd) ∩ [p1,p2,p3…pd] q = (1/d) Q Keep numerator and denom. separate (remember, we are not allowed to divide) Inject q=(1/d) Q in side1() and mutliply by d to remove the division Solve for q in: q Є πw(i,k1) … q Є πw(i,kd) q Є [p1,p2,p3…pd] { Part. 4 Symbolic Perturbation
  • 208. How to write side1(), side2(), side3(), side4() ? d2(q,pj)-wj – d2(q,pi) + wi where: q = πw(i,k1) ∩ …πw(i,kd) ∩ [p1,p2,p3…pd] q = (1/d) Q Keep numerator and denom. separate (remember, we are not allowed to divide) Inject q=(1/d) Q in side1() and mutliply by d to remove the division Order the terms in wi = εi Solve for q in: q Є πw(i,k1) … q Є πw(i,kd) q Є [p1,p2,p3…pd] { Part. 4 Symbolic Perturbation
  • 209. How to write side1(), side2(), side3(), side4() ? d2(q,pj)-wj – d2(q,pi) + wi where: q = πw(i,k1) ∩ …πw(i,kd) ∩ [p1,p2,p3…pd] q = (1/d) Q Keep numerator and denom. separate (remember, we are not allowed to divide) Inject q=(1/d) Q in side1() and mutliply by d to remove the division Order the terms in wi = εi the constant one is non-perturbed predicate if zero, the first non-zero one determines the sign Solve for q in: q Є πw(i,k1) … q Є πw(i,kd) q Є [p1,p2,p3…pd] { Part. 4 Symbolic Perturbation
  • 210. Part. 4 Symbolic Perturbation – side1 #include "kernel.pckh" Sign predicate(side1)( point(p0), point(p1), point(q0) DIM ) { scalar r = sq_dist(p0,p1) ; r -= 2*dot_at(p1,q0,p0) ; generic_predicate_result(sign(r)) ; begin_sos2(p0,p1) sos(p0,POSITIVE) sos(p1,NEGATIVE) end_sos } Source PCK
  • 211. Part. 4 Symbolic Perturbation – side1 #include "kernel.pckh" Sign predicate(side1)( point(p0), point(p1), point(q0) DIM ) { scalar r = sq_dist(p0,p1) ; r -= 2*dot_at(p1,q0,p0) ; generic_predicate_result(sign(r)) ; begin_sos2(p0,p1) sos(p0,POSITIVE) sos(p1,NEGATIVE) end_sos } Source PCK (p1-p0).(q0-p0)
  • 212. Part. 4 Symbolic Perturbation – side2 #include "kernel.pckh“ Sign predicate(side2)( point(p0), point(p1), point(p2), point(q0), point(q1) DIM) { scalar l1 = 1*sq_dist(p1,p0) ; scalar l2 = 1*sq_dist(p2,p0) ; scalar a10 = 2*dot_at(p1,q0,p0); scalar a11 = 2*dot_at(p1,q1,p0); scalar a20 = 2*dot_at(p2,q0,p0); scalar a21 = 2*dot_at(p2,q1,p0); scalar Delta = a11 - a10 ; scalar DeltaLambda0 = a11 - l1 ; scalar DeltaLambda1 = l1 - a10 ; scalar r = Delta*l2 - a20*DeltaLambda0 - a21*DeltaLambda1 ; Sign Delta_sign = sign(Delta) ; Sign r_sign = sign(r) ; generic_predicate_result(Delta_sign*r_sign) ; begin_sos3(p0,p1,p2) sos(p0, Sign(Delta_sign*sign(Delta-a21+a20))) sos(p1, Sign(Delta_sign*sign(a21-a20))) sos(p2, NEGATIVE) end_sos } Source PCK
  • 213. Part. 4 Symbolic Perturbation – side2 #include "kernel.pckh“ Sign predicate(side2)( point(p0), point(p1), point(p2), point(q0), point(q1) DIM) { scalar l1 = 1*sq_dist(p1,p0) ; scalar l2 = 1*sq_dist(p2,p0) ; scalar a10 = 2*dot_at(p1,q0,p0); scalar a11 = 2*dot_at(p1,q1,p0); scalar a20 = 2*dot_at(p2,q0,p0); scalar a21 = 2*dot_at(p2,q1,p0); scalar Delta = a11 - a10 ; scalar DeltaLambda0 = a11 - l1 ; scalar DeltaLambda1 = l1 - a10 ; scalar r = Delta*l2 - a20*DeltaLambda0 - a21*DeltaLambda1 ; Sign Delta_sign = sign(Delta) ; Sign r_sign = sign(r) ; generic_predicate_result(Delta_sign*r_sign) ; begin_sos3(p0,p1,p2) sos(p0, Sign(Delta_sign*sign(Delta-a21+a20))) sos(p1, Sign(Delta_sign*sign(a21-a20))) sos(p2, NEGATIVE) end_sos } Source PCK Denominator
  • 214. Part. 4 Symbolic Perturbation – side2 #include "kernel.pckh“ Sign predicate(side2)( point(p0), point(p1), point(p2), point(q0), point(q1) DIM) { scalar l1 = 1*sq_dist(p1,p0) ; scalar l2 = 1*sq_dist(p2,p0) ; scalar a10 = 2*dot_at(p1,q0,p0); scalar a11 = 2*dot_at(p1,q1,p0); scalar a20 = 2*dot_at(p2,q0,p0); scalar a21 = 2*dot_at(p2,q1,p0); scalar Delta = a11 - a10 ; scalar DeltaLambda0 = a11 - l1 ; scalar DeltaLambda1 = l1 - a10 ; scalar r = Delta*l2 - a20*DeltaLambda0 - a21*DeltaLambda1 ; Sign Delta_sign = sign(Delta) ; Sign r_sign = sign(r) ; generic_predicate_result(Delta_sign*r_sign) ; begin_sos3(p0,p1,p2) sos(p0, Sign(Delta_sign*sign(Delta-a21+a20))) sos(p1, Sign(Delta_sign*sign(a21-a20))) sos(p2, NEGATIVE) end_sos } Source PCK Barycentric coords. of q
  • 215. Part. 4 Symbolic Perturbation – side2 #include "kernel.pckh“ Sign predicate(side2)( point(p0), point(p1), point(p2), point(q0), point(q1) DIM) { scalar l1 = 1*sq_dist(p1,p0) ; scalar l2 = 1*sq_dist(p2,p0) ; scalar a10 = 2*dot_at(p1,q0,p0); scalar a11 = 2*dot_at(p1,q1,p0); scalar a20 = 2*dot_at(p2,q0,p0); scalar a21 = 2*dot_at(p2,q1,p0); scalar Delta = a11 - a10 ; scalar DeltaLambda0 = a11 - l1 ; scalar DeltaLambda1 = l1 - a10 ; scalar r = Delta*l2 - a20*DeltaLambda0 - a21*DeltaLambda1 ; Sign Delta_sign = sign(Delta) ; Sign r_sign = sign(r) ; generic_predicate_result(Delta_sign*r_sign) ; begin_sos3(p0,p1,p2) sos(p0, Sign(Delta_sign*sign(Delta-a21+a20))) sos(p1, Sign(Delta_sign*sign(a21-a20))) sos(p2, NEGATIVE) end_sos } Source PCK Barycentric coords. of q Solely depend on dot products between input points
  • 216. Part. 4 Symbolic Perturbation – side2 #include "kernel.pckh“ Sign predicate(side2)( point(p0), point(p1), point(p2), point(q0), point(q1) DIM) { scalar l1 = 1*sq_dist(p1,p0) ; scalar l2 = 1*sq_dist(p2,p0) ; scalar a10 = 2*dot_at(p1,q0,p0); scalar a11 = 2*dot_at(p1,q1,p0); scalar a20 = 2*dot_at(p2,q0,p0); scalar a21 = 2*dot_at(p2,q1,p0); scalar Delta = a11 - a10 ; scalar DeltaLambda0 = a11 - l1 ; scalar DeltaLambda1 = l1 - a10 ; scalar r = Delta*l2 - a20*DeltaLambda0 - a21*DeltaLambda1 ; Sign Delta_sign = sign(Delta) ; Sign r_sign = sign(r) ; generic_predicate_result(Delta_sign*r_sign) ; begin_sos3(p0,p1,p2) sos(p0, Sign(Delta_sign*sign(Delta-a21+a20))) sos(p1, Sign(Delta_sign*sign(a21-a20))) sos(p2, NEGATIVE) end_sos } Source PCK Result when in generic position
  • 217. Part. 4 Symbolic Perturbation – side2 #include "kernel.pckh“ Sign predicate(side2)( point(p0), point(p1), point(p2), point(q0), point(q1) DIM) { scalar l1 = 1*sq_dist(p1,p0) ; scalar l2 = 1*sq_dist(p2,p0) ; scalar a10 = 2*dot_at(p1,q0,p0); scalar a11 = 2*dot_at(p1,q1,p0); scalar a20 = 2*dot_at(p2,q0,p0); scalar a21 = 2*dot_at(p2,q1,p0); scalar Delta = a11 - a10 ; scalar DeltaLambda0 = a11 - l1 ; scalar DeltaLambda1 = l1 - a10 ; scalar r = Delta*l2 - a20*DeltaLambda0 - a21*DeltaLambda1 ; Sign Delta_sign = sign(Delta) ; Sign r_sign = sign(r) ; generic_predicate_result(Delta_sign*r_sign) ; begin_sos3(p0,p1,p2) sos(p0, Sign(Delta_sign*sign(Delta-a21+a20))) sos(p1, Sign(Delta_sign*sign(a21-a20))) sos(p2, NEGATIVE) end_sos } Source PCK Symbolic perturbation
  • 218. Part. 4 Symbolic Perturbation – side2 Sign side2_exact_SOS( const double* p0, const double* p1, const double* p2, const double* q0, const double* q1, coord_index_t dim ) { const expansion& l1 = expansion_sq_dist(p1, p0, dim); const expansion& l2 = expansion_sq_dist(p2, p0, dim); const expansion& a10 = expansion_dot_at(p1, q0, p0, dim).scale_fast(2.0); const expansion& a11 = expansion_dot_at(p1, q1, p0, dim).scale_fast(2.0); const expansion& a20 = expansion_dot_at(p2, q0, p0, dim).scale_fast(2.0); const expansion& a21 = expansion_dot_at(p2, q1, p0, dim).scale_fast(2.0); const expansion& Delta = expansion_diff(a11, a10); Sign Delta_sign = Delta.sign(); vor_assert(Delta_sign != ZERO); const expansion& DeltaLambda0 = expansion_diff(a11, l1); const expansion& DeltaLambda1 = expansion_diff(l1, a10); const expansion& r0 = expansion_product(Delta, l2); const expansion& r1 = expansion_product(a20, DeltaLambda0).negate(); const expansion& r2 = expansion_product(a21, DeltaLambda1).negate(); const expansion& r = expansion_sum3(r0, r1, r2); Sign r_sign = r.sign(); ……….. Exact version with expansions
  • 219. Part. 4 Symbolic Perturbation – side2 if(r_sign == ZERO) { const double* p_sort[3]; p_sort[0] = p0; p_sort[1] = p1; p_sort[2] = p2; std::sort(p_sort, p_sort + 3); for(index_t i = 0; i < 3; ++i) { if(p_sort[i] == p0) { const expansion& z1 = expansion_diff(Delta, a21); const expansion& z = expansion_sum(z1, a20); Sign z_sign = z.sign(); len_side2_SOS = vor_max(len_side2_SOS, z.length()); if(z_sign != ZERO) { return Sign(Delta_sign * z_sign); } } if(p_sort[i] == p1) { const expansion& z = expansion_diff(a21, a20); Sign z_sign = z.sign(); len_side2_SOS = vor_max(len_side2_SOS, z.length()); if(z_sign != ZERO) { return Sign(Delta_sign * z_sign); } } if(p_sort[i] == p2) { return NEGATIVE; } } vor_assert_not_reached; } return Sign(Delta_sign * r_sign); } Exact version with expansions
  • 220. Part. 4 Symbolic Perturbation – side3 #include "kernel.pckh" Sign predicate(side3)( point(p0), point(p1), point(p2), point(p3), point(q0), point(q1), point(q2) DIM ) { scalar l1 = 1*sq_dist(p1,p0); scalar l2 = 1*sq_dist(p2,p0); scalar l3 = 1*sq_dist(p3,p0); scalar a10 = 2*dot_at(p1,q0,p0); scalar a11 = 2*dot_at(p1,q1,p0); scalar a12 = 2*dot_at(p1,q2,p0); scalar a20 = 2*dot_at(p2,q0,p0); scalar a21 = 2*dot_at(p2,q1,p0); scalar a22 = 2*dot_at(p2,q2,p0); scalar a30 = 2*dot_at(p3,q0,p0); scalar a31 = 2*dot_at(p3,q1,p0); scalar a32 = 2*dot_at(p3,q2,p0); scalar b00 = a11*a22-a12*a21; scalar b01 = a21-a22; scalar b02 = a12-a11; scalar b10 = a12*a20-a10*a22; scalar b11 = a22-a20; scalar b12 = a10-a12; scalar b20 = a10*a21-a11*a20; scalar b21 = a20-a21; scalar b22 = a11-a10; scalar Delta = b00+b10+b20; scalar DeltaLambda0 = b01*l1+b02*l2+b00 ; scalar DeltaLambda1 = b11*l1+b12*l2+b10 ; scalar DeltaLambda2 = b21*l1+b22*l2+b20 ; scalar r = Delta*l3 - ( a30 * DeltaLambda0 + a31 * DeltaLambda1 + a32 * DeltaLambda2 ) ; Sign Delta_sign = sign(Delta) ; Sign r_sign = sign(r) ; generic_predicate_result( Delta_sign*r_sign ) ; begin_sos4(p0,p1,p2,p3) sos(p0, Sign(Delta_sign*sign( Delta-((b01+b02)*a30+ (b11+b12)*a31+ (b21+b22)*a32) ))) sos(p1, Sign(Delta_sign* sign((a30*b01)+ (a31*b11)+ (a32*b21)))) sos(p2, Sign(Delta_sign*sign( (a30*b02)+ (a31*b12)+ (a32*b22)))) sos(p3, NEGATIVE) end_sos } Source PCK
  • 221. Part. 4 Symbolic Perturbation – side4 ………. scalar b00= det3x3(a11,a12,a13,a21,a22,a23,a31,a32,a33); scalar b01=-det_111_2x3(a21,a22,a23,a31,a32,a33); scalar b02= det_111_2x3(a11,a12,a13,a31,a32,a33); scalar b03=-det_111_2x3(a11,a12,a13,a21,a22,a23); scalar b10=-det3x3(a10,a12,a13,a20,a22,a23,a30,a32,a33); scalar b11= det_111_2x3(a20,a22,a23,a30,a32,a33); scalar b12=-det_111_2x3(a10,a12,a13,a30,a32,a33); scalar b13= det_111_2x3(a10,a12,a13,a20,a22,a23); scalar b20= det3x3(a10,a11,a13,a20,a21,a23,a30,a31,a33); scalar b21=-det_111_2x3(a20,a21,a23,a30,a31,a33); scalar b22= det_111_2x3(a10,a11,a13,a30,a31,a33); scalar b23=-det_111_2x3(a10,a11,a13,a20,a21,a23); scalar b30=-det3x3(a10,a11,a12,a20,a21,a22,a30,a31,a32); scalar b31= det_111_2x3(a20,a21,a22,a30,a31,a32); scalar b32=-det_111_2x3(a10,a11,a12,a30,a31,a32); scalar b33= det_111_2x3(a10,a11,a12,a20,a21,a22); scalar Delta=b00+b10+b20+b30; scalar DeltaLambda0 = b01*l1+b02*l2+b03*l3+b00; scalar DeltaLambda1 = b11*l1+b12*l2+b13*l3+b10; scalar DeltaLambda2 = b21*l1+b22*l2+b23*l3+b20; scalar DeltaLambda3 = b31*l1+b32*l2+b33*l3+b30; ………. scalar r = Delta*l4 - ( a40*DeltaLambda0+ a41*DeltaLambda1+ a42*DeltaLambda2+ a43*DeltaLambda3 ); Sign Delta_sign = sign(Delta); generic_predicate_result(Delta_sign*sign(r)) ; begin_sos5(p0,p1,p2,p3,p4) sos(p0, Sign( Delta_sign*sign(Delta - ( (b01+b02+b03)*a30 + (b11+b12+b13)*a31 + (b21+b22+b23)*a32 + (b31+b32+b33)*a33 ))) ) sos(p1, Sign( Delta_sign*sign(a30*b01+a31*b11+a32*b21+a33*b31))) sos(p2, Sign( Delta_sign*sign(a30*b02+a31*b12+a32*b22+a33*b32))) sos(p3, Sign( Delta_sign*sign(a30*b03+a31*b13+a32*b23+a33*b33))) sos(p4, NEGATIVE) end_sos } q is the intersection of three bisectors and a tetrahedron embedded in nD Note: There is a special case in 3d (no need for the tetrahedron) = insphere3d() The code of the general nD version (excerpt) : Source PCK
  • 222. Part 4. Geometry – Crash test 1/2
  • 223. Part 4. Geometry – Crash test 1/2
  • 224. Part 4. Geometry – Crash test 1/2
  • 225. Part 4. Geometry – Crash test 1/2
  • 226. Part 4. Geometry – Crash test 2/2
  • 227. Part 4. Geometry – Crash test 2/2
  • 232. Part 4. Geometry - RVD If we eliminate the zero components during computations, the length of the expansions remain reasonable (see observation in Shewchuk’s paper)
  • 233. Part 4. Clipped Voronoi diagram
  • 234. Part 4. Clipped Voronoi diagram Polyhedral elements for Finite Elements Analysis >vorpaline/vorpalite profile=poly fusee.meshb
  • 235. Part 4. Geometry – 3D Anisotropic VD
  • 236. Part 4. Geometry – 3D Anisotropic VD
  • 237. The PCK (Predicate Construction Kit) Features: • Expansion number type – low level API (allocation on stack, efficient) • High level API with operators (easy to use, less efficient) • Script to generate FPG filter and exact version with SOS • Standard predicates (orient2d, 3d, insphere3d, orient4d) • More exotic predicates for RVD (side1, side2, side3, side 4 in dim 3,4,6,7) • 3D Delaunay triangulation • 3D weighted Delaunay triangulation • Only 6 source files • multi_precision.(h,cpp) • predicates.(h,cpp) • delaunay3d.(h,cpp) • Fully documented • No dependency (compiles and runs everywhere*, I got a version on my phone :-) BSD license (do what you want with it, including business) *In the IEEE754 world
  • 238. What s next 5 Physics + Mathematics + Computing = ?
  • 239. ? T ρ1 ρ2 Minimize C(T) = ∫Ω || x – T(x) ||2 dx Subject to: T is measure-preserving ρ1(x) Optimal Transport
  • 240. A map T is a transport map between μ and ν if μ(T-1(B)) = ν(B) for any Borel subset B B (X;μ) (Y;ν) Optimal Transport
  • 241. A map T is a transport map between μ and ν if μ(T-1(B)) = ν(B) for any Borel subset B B T-1(B) (X;μ) (Y;ν) Optimal Transport
  • 245. Optimal Transport – semi-discrete ∫X ψc (x)dμ + ∫Y ψ(y)dν Sup ψ Є ψc (DMK) ∑j ∫Lagψ(yj) || x – yj ||2 - ψ(yj) dμ ∫X inf yj ЄY [ || x – yj ||2 - ψ(yj) ] dμ ∑j ψ(yj) vj
  • 246. Voronoi diagram: Vor(xi) = { x | d2(x,xi) < d2(x,xj) } Power Diagrams
  • 247. Power diagram: Pow(xi) = { x | d2(x,xi) – ψi < d2(x,xj) – ψj } Voronoi diagram: Vor(xi) = { x | d2(x,xi) < d2(x,xj) } Power Diagrams
  • 256. Subd surface fitted using Optimal Transport Scan2FEA
  • 257. Finite Element Analysis (vibration modes) Scan2FEA
  • 259. Think Big: Simulating the entire universe
  • 260. The millenium simulation project, Max Planck Institute fur Astrophysik pc/h : parsec (= 3.2 années lumières)Large-Scale structure
  • 261. Optimal Transport Early Universe Reconstruction The Data
  • 262. Optimal Transport Invert Newton Einstein Eqn to go back 14 milliards years in time The millenium simulation project, Max Planck Institute fur Astrophysik pc/h : parsec (= 3.2 light years)
  • 263. Optimal Transport The millenium simulation project, Max Planck Institute fur Astrophysik pc/h : parsec (= 3.2 années lumières) In 2002, 5 hours of computation with a supercomputer / 5000 points
  • 264. Optimal Transport The millenium simulation project, Max Planck Institute fur Astrophysik pc/h : parsec (= 3.2 années lumières) In 2002, 5 hours of computation with a supercomputer / 5000 points Can we do it with 1 000 000 points ?
  • 265. Optimal Transport The millenium simulation project, Max Planck Institute fur Astrophysik pc/h : parsec (= 3.2 années lumières) In 2002, 5 hours of computation with a supercomputer / 5000 points Can we do it with 1 000 000 points ? Yes, if we wait 4500 years
  • 266. Optimal Transport In 2002, 5 hours of computation with a supercomputer / 5000 points Can we do it with 1 000 000 points ? Yes, if we wait 4500 years
  • 267. Optimal Transport In 2002, 5 hours of computation with a supercomputer / 5000 points Can we do it with 1 000 000 points ? Yes, if we wait 4500 years We need a new algorithm.
  • 268. Towards Early Universe Reconstruction Numerical Experiment: Performances 2002: several hours of supercomputer time were needed for computing OT with a few thousand Dirac masses, with a combinatorial algorithm in O(n2log(n))
  • 269. Towards Early Universe Reconstruction Numerical Experiment: Performances 2002: several hours of supercomputer time were needed for computing OT with a few thousand Dirac masses, with a combinatorial algorithm in O(n2log(n)) 2015: 3D version of [Mérigot] (multilevel + BFGS) + several tricks [L 2015]
  • 270. Towards Early Universe Reconstruction Numerical Experiment: Performances 2002: several hours of supercomputer time were needed for computing OT with a few thousand Dirac masses, with a combinatorial algorithm in O(n2log(n)) 2015: 3D version of [Mérigot] (multilevel + BFGS) + several tricks [L 2015]
  • 271. Towards Early Universe Reconstruction Numerical Experiment: Performances 2002: several hours of supercomputer time were needed for computing OT with a few thousand Dirac masses, with a combinatorial algorithm in O(n2log(n)) 2015: 3D version of [Mérigot] (multilevel + BFGS) + several tricks [L 2015] 2016: Damped Newton [Mérigot, Thibert] + several tricks for 3D: 1 million Dirac masses in 240 seconds
  • 272. Towards Early Universe Reconstruction Numerical Experiment: Performances 2002: several hours of supercomputer time were needed for computing OT with a few thousand Dirac masses, with a combinatorial algorithm in O(n2log(n)) 2015: 3D version of [Mérigot] (multilevel + BFGS) + several tricks [L 2015] 2016: Damped Newton [Mérigot, Thibert] + several tricks for 3D: 1 million Dirac masses in 240 seconds 10 million Dirac masses in 90 minutes
  • 273. Towards Early Universe Reconstruction Numerical Experiment: Performances 2002: several hours of supercomputer time were needed for computing OT with a few thousand Dirac masses, with a combinatorial algorithm in O(n2log(n)) 2015: 3D version of [Mérigot] (multilevel + BFGS) + several tricks [L 2015] 2016: Damped Newton [Mérigot, Thibert] + several tricks for 3D: 1 million Dirac masses in 240 seconds 10 million Dirac masses in 90 minutes 2017: 10 million Dirac masses in 2 minutes (for specific configurations) Semi-discrete OT is now scalable ! (new tool in Num. Ana. Toolbox)
  • 275. Take-home message Programming is a great source of fun
  • 276. Take-home message Programming is a great source of fun Futuristic programming principles (make it fun for your users as well)
  • 277. Take-home message Programming is a great source of fun Futuristic programming principles Program speed Low memory consumption Lines of code Classes Templates
  • 278. Take-home message Programming is a great source of fun Futuristic programming principles Program speed Low memory consumption Lines of code Classes Templates Gains Costs
  • 279. Take-home message Programming is a great source of fun Futuristic programming principles Program speed Low memory consumption Lines of code Classes Templates Gains Costs Measure it ! (profiler, continuous integration)
  • 280. Take-home message: Usefulness is primary .h, .cpp .h, .cpp .h, .cpp .h, .cpp .h, .cpp .h, .cpp .h, .cpp Object-oriented design Generic design
  • 281. Take-home message: Usefulness is primary .h, .cpp .h, .cpp .h, .cpp .h, .cpp .h, .cpp .h, .cpp .h, .cpp Object-oriented design Generic design
  • 282. Take-home message: Usefulness is primary Futuristic design .cpp .h void the_functionality(Data& )
  • 283. Take-home message: Usefulness is primary Futuristic design .cpp .h void the_functionality(Data& ) * Make it easy to compile * Do not bother the user with internal details (even if you are proud of them)
  • 284. Take-home message: Usefulness is primary .cpp GLUP.h – C API glupBegin(), glupEnd(), glupVertex() GLUP state variablesVanillaGL OpenGL ES / WebGL GLSL 1.5 GLSL 4.4 matrix stacks buffers Shaders OpenNL.h – C API nlBegin(), nlEnd(), nlCoeff(), nlSolve() .c CG GMRes BiCGStab SuperLU CHOLDM OD CPU/GPU Abstraction layer OpenMP multicore CUDA CuBLAS CuSparse ARPACK NLSparseMatrix NLCRSMatrix nlCompress()
  • 285. Take-home message: Usefulness is primary .cpp GLUP.h – C API glupBegin(), glupEnd(), glupVertex() GLUP state variablesVanillaGL OpenGL ES / WebGL GLSL 1.5 GLSL 4.4 matrix stacks buffers Shaders OpenNL.h – C API nlBegin(), nlEnd(), nlCoeff(), nlSolve() .cpp CG GMRes BiCGStab SuperLU CHOLDM OD CPU/GPU Abstraction layer OpenMP multicore CUDA CuBLAS CuSparse ARPACK NLSparseMatrix NLCRSMatrix nlCompress() Algorithms and Data Structures Mostly arrays (std::vector) and for() loops Object oriented / virtual functions Run-time selection of algorithm Generic programming For dimension-independent code (RVD) If() statements Predicates
  • 286. Futuristic programming – the product GLUP.h – C API glupBegin(), glupEnd(), glupVertex() OpenNL.h – C API nlBegin(), nlEnd(), nlCoeff(), nlSolve() Geogram – C++ API Mesh class, Delaunay, Voronoi, Remesh, param., repair, reconstruct. Predicate Construction Kit Compiler for arbitrary precision Geometric predicates (C/C++ API) Graphite: Qt GUI + LUA scripting Download from gforge.inria.fr, see also links on my webpage
  • 287. Acknowledgements Eurographics Association European Research Council GOODSHAPE ERC-StG-205693 VORPALINE ERC-PoC-334829 ANR MORPHO (Vision), ANR BECASIM (Physics) ANR MAGA (P.I.: Q. Merigot), ANR ROOT (P.I.: N. Bonneel) Optimal Transport stuff. Inria EXPLORAGRAM Key contributors to Geogram/Graphite: N. Ray, W.-C. Li, B. Vallet, D. Sokolov, N. Bonneel, R. Zayer, A. Sheffer MOKA team (Monge-Ampere-Kantorovich)