程序代写代做代考 algorithm c++ cache GPU data structure 01: Functions & Calculus

01: Functions & Calculus

03: Mesh Data Structures

Dr. Hamish Carr

COMP 5812M: Foundations of Modelling & Rendering
Data Structures
Based on identifying the requirements:
topological – mesh assumptions
algorithmic – what operations we will need
resource – how much memory / bandwidth
complexity – preprocessing / runtime cost
Throughout, we will assume IEEE floats (4B)

COMP 5812M: Foundations of Modelling & Rendering
Topological Requirements
Meshes are manifold (if possible)
If not, the boundary is clearly marked
Meshes are triangulations
Easily enforced – subdivide polygons
Sometimes generalise to quads
Almost never use larger mesh elements

COMP 5812M: Foundations of Modelling & Rendering
Algorithmic Requirements
Operations will include:
Rendering
GPU transfer
Iteration for mesh processing
Insertion / deletion / modification

COMP 5812M: Foundations of Modelling & Rendering
Operations
a. access to vertices, edges, faces
b. iteration over vertices, edges, faces (any order)
c. access to endpoints of edge
d. access to faces for each edge
e. oriented traversal of edges (walk around face)
f. oriented traversal of vertices (ditto) c,e
g. oriented traversal of edges (around vertex) d,e
h. oriented traversal of faces (ditto) d,g

COMP 5812M: Foundations of Modelling & Rendering
Example: Smooth Normals
We’ll use this as a running example
For each vertex
average the adjacent normals
to produce an approximate vertex normal
Strictly speaking, don’t need to iterate around
We just need to iterate over adjacent faces
Any order will do

COMP 5812M: Foundations of Modelling & Rendering
Resource Requirements
Memory footprint is the key issue
It also influences bandwidth
Memory transfer to GPU for rendering
Not all operations are on GPU
Ideal language these days is C++
Because it enforces the POD rule

COMP 5812M: Foundations of Modelling & Rendering
Runtime Polymorphism
OO languages have runtime polymorphism
decides which function to call at runtime
needs to store information on object class
typically done with trap table pointer
pointer to details of class in memory
object name, method base addresses, &c.

COMP 5812M: Foundations of Modelling & Rendering
Trap Table Penalty
This trap table pointer is on CPU
it’s totally useless on GPU
If you have a class representing a point
Point3 { float x, y, z; NULL *trapTablePtr;}
12B for your payload, 4B or 8B for the pointer
GPU bandwidth goes up by 33% or 67%
Unless you strip it out first (i.e. copy!)

COMP 5812M: Foundations of Modelling & Rendering
POD Loophole
If you have no runtime polymorphism
i.e. no virtual methods at all
you don’t need the trap table pointer
C++ guarantees not to create one
So you can copy your data straight to GPU
And arrays are even better!
One memory copy for the entire array

COMP 5812M: Foundations of Modelling & Rendering
Complexity Requirements
Algorithms should be O(n) if possible
Insertions / deletions should be O(1) cost
Iterations should also be O(1) cost
O(n lg n) should be reserved for preprocessing
O(lg n) is the maximum runtime lookup cost

COMP 5812M: Foundations of Modelling & Rendering
Mesh Data Structures
Face
Indexed Face
Winged-Edge
Half-Edge
Directed Edge

COMP 5812M: Foundations of Modelling & Rendering
Face Data Structure
Simplest approach:
Each face consists of 3 (xyz) points
Render uses glVertex() or equivalent
Most operations iterate over faces
Cannot (usually) enforce constraints
Attributes (normals, &c.) need to be repeated
Colloquially called triangle/polygon soup

COMP 5812M: Foundations of Modelling & Rendering
Face Operations
Reading / rendering is easy (but not fast)
Vertices stored 6x, prone to matching errors
Cannot iterate around vertices
Cannot (easily) swap faces across edge
Can iterate over vertices 6x, edges 2x
by iterating through faces
Can iterate over, around faces
No per vertex/edge storage

COMP 5812M: Foundations of Modelling & Rendering

Smooth Normals- Face
Hopelessly inefficient – O(v2)
Recomputes each normal six times

COMP 5812M: Foundations of Modelling & Rendering
(Old) Face Improvements
Display lists – save bandwidth, cache on GPU
Implicit vertex reuse
Line Strips & Loops
Triangle Fans & Strips
Quads, Quad Strips
Polygons

COMP 5812M: Foundations of Modelling & Rendering
Lines, Strips & Loops

GL_LINES:
v0v1
v1v2
v2v3
v3v4
v4v5
v5v0
2 v/e
GL_LINE_STRIP:
v0v1
(v1)v2
(v2)v3
(v3)v4
(v4)v5
~ 1 v/e
GL_LINE_LOOP:
v0v1
(v1)v2
(v2)v3
(v3)v4
(v4)v5
(v5)(v0)
~ 1 v/e

COMP 5812M: Foundations of Modelling & Rendering
Triangle Fans/Strips

GL_TRIANGLE_FAN:
v0v1v2
(v0)(v2)v3
(v0)(v3)v4
(v0)(v4)v5
~ 1.16 v/e
(degree 6 vertex)

GL_TRIANGLE_STRIP:
v0v1v2
(v2)(v1)v3
(v2)(v3)v4
(v4)(v3)v5
~ 1 v/e
(for long strips)
alternate CW/CCW
NP-hard to find them
easier on regular grids

COMP 5812M: Foundations of Modelling & Rendering
Face Costs
Memory / bandwidth cost:
3 x 3 x 4B per face = 36B
f ~ 2v, so 72B per vertex
Every glVertex() call has overhead
so no advantage for batched operations
Horrendously inefficient operations
But easy and lowest common denominator

COMP 5812M: Foundations of Modelling & Rendering
Indexed Face Data Structure
Store a single array of vertices / attributes
Store their indices (or pointers) for each face
Pointers are no longer cheaper
Most PUs have 1-op array lookup
Render uses vertex arrays / VBOs
But operations aren’t so easy

COMP 5812M: Foundations of Modelling & Rendering
Vertex Arrays
Replace individual glVertex() calls
Pass entire arrays to library
Push loop through vertices into library call

COMP 5812M: Foundations of Modelling & Rendering
Vertex Buffer Objects
Same idea, but data transferred to VRAM
I.e. we cache the data & save the bandwidth
Which means memory management:
allocation: glGenBuffers, glDeleteBuffers
binding: glBindBuffer
transfer: glBufferData
And more is moving onto GPU with Vulkan

COMP 5812M: Foundations of Modelling & Rendering
Indexed Face Operations
Reading / rendering is easy & fast
Cannot iterate around vertices
But can iterate over them
Cannot (easily) swap faces across edge
Can iterate over, around faces
No per edge storage
Overall weakness – edge operations

COMP 5812M: Foundations of Modelling & Rendering

Smooth Normals – Indexed Face
Much better – O(v) computation
But it cannot iterate around vertices yet

COMP 5812M: Foundations of Modelling & Rendering
Reading Polygon Soup

COMP 5812M: Foundations of Modelling & Rendering
Writing Indexed Faces

COMP 5812M: Foundations of Modelling & Rendering
Indexed Face Costs
Memory / bandwidth cost:
3 x 4B per vertex= 12B
f ~ 2v, so 6 x 4B indices per vertex
Total: 36B / vertex
Efficient rendering
Default in practice: OBJ files / VBOs
But limited in its operations

COMP 5812M: Foundations of Modelling & Rendering
Improvements Needed
Mesh processing requires more operations
In particular, iterating in cyclic order
This allows us to preserve topology
e.g. testing 2-manifold conditions
can’t (easily) do this with indexed face
We will need to track vertices, faces, edges
Each will need index + attribute storage

COMP 5812M: Foundations of Modelling & Rendering
Face-Based Structures
Each vertex stores:
position 12B
1 face index (first) 4B 16B/vert
Each face stores:
3 vertex indices 12B
3 neighbours (face indices) 12B 24B/face
(2 faces / vertex) 48B /vert
Total: 64B / vert

COMP 5812M: Foundations of Modelling & Rendering
Smooth Normals – Face-Based
Iteration around vertices now possible
But lots of if statements
Starts failing with non-triangular faces

COMP 5812M: Foundations of Modelling & Rendering
Edge-Based Structures
These start explicitly representing edges
And using them to store cyclic edge loops
Each edge points to the next/previous edge
At each end, and for each face
Paradigm is the winged edge (Baumgart, 1972)

COMP 5812M: Foundations of Modelling & Rendering
Winged Edge

end[0]
end[1]
face[0]
face[1]
next[0]
prev[0]
prev[1]
next[1]

COMP 5812M: Foundations of Modelling & Rendering
Winged Edge Structures
Each vertex stores:
position 12B
1 edge index (first) 4B 16B/vertex
Each edge stores:
2 vertex indices 8B
2 face indices 8B
2 edge indices (next) 8B
2 edge indices (prev) 8B 32B/edge
(3 edges / vertex) 96B/vertex
Each face stores:
1 edge index (first) 4B
(2 faces / vertex) 8B /vert
Total: 120B / vert

COMP 5812M: Foundations of Modelling & Rendering
Smooth Normals – Winged Edge
This is cleaner, and handles arbitrary meshes
Face can store vertex IDs as well (+24B/v)
Still need if statements to track things

COMP 5812M: Foundations of Modelling & Rendering
Half-Edge Structures
Break winged-edges into a pair of half-edges
Mantyla 1988, Kettner 1999
Each half edge has:
vertex, face, next, prev
ID of paired half-edge
But store them in pairs
Use XOR on bit 0 to flip between them
Same cost as winged-edge, simpler code

COMP 5812M: Foundations of Modelling & Rendering
Smooth Normals – Half Edge
This is nice, but still memory-inefficient
We need to reduce the per edge costs

COMP 5812M: Foundations of Modelling & Rendering
Directed Edge Structures
Campagna 1998
Stores the directed-edges per triangle
I.e. in groups of three
Assumes arithmetic cheap, memory not
Uses modular arithmetic (%3) instead of XOR
And uses it for implicit storage of topology

COMP 5812M: Foundations of Modelling & Rendering
Conversion
Each directed edge d is no. i on face f:
d = 3f + i f = h/3 i = h%3
d is directed face index
f is face index
i is 0, 1, or 2 in CCW order
next = 3f + (i + 1) % 3
prev = 3f + (i + 2) % 3

COMP 5812M: Foundations of Modelling & Rendering
Smooth Normals – Directed Edge
Right, let’s look at the cost

COMP 5812M: Foundations of Modelling & Rendering
Directed Edge Structures
Each vertex stores:
position 12B
1 edge index (first) 4B 16B/vertex
Each directed edge stores:
1 vertex index 4B
1 paired directed edge index 4B 8B/directed edge
(6 directed edges / vertex) 48B / vertex
Each face stores:
nothing
Total: 64B/ vertex

COMP 5812M: Foundations of Modelling & Rendering
Implementation
We will do this C-style, not OO
so we get that efficiency as well
the vertices are stored in a vertex array
and the faces have vertex indices in an array
since directed edges are stored per face
their vertex indices are also the face’s list

COMP 5812M: Foundations of Modelling & Rendering
Code (Finally)
After all that mess, it’s surprisingly simple
But it’s not perfect

COMP 5812M: Foundations of Modelling & Rendering
Directed Edge Comments
A boundary edge does not have a pair
So store a negative index
Similar structure for quads is easy to construct
but we can’t mix the two
Libraries exist (OpenMesh, CGAL, &c.)
But most people roll their own
Because their attributes vary

COMP 5812M: Foundations of Modelling & Rendering

Page 1/7/Users/scshca/Desktop/mesh_structures.cpp
Saved: 30/01/2018 11:33:34 Printed for: Hamish Carr

// FACE DATA STRUCTURE1
for (each face f)2
{ // loop through faces3
// start with a zero vector4
normal = zero5
for (each vertex v on face f)6
{ // loop through vertices on face7
// loop through all faces (including this one)8
for (each face f1)9
{ // loop through faces again10
for (each vertex v1 on face f1)11
{ // loop through vertices on faces12
// if it’s the same vertex (look out for roundoff errors!)13
if (v1 == v)14
{ // vertex match15
compute normal n_f1 for face f116
normal += n_f117
} // vertex match18
} // loop through vertices on faces19
} // loop through faces again20
// note: we don’t need to keep the degree or divide through21
// because we’re going to normalise anyway! 22
normalise(normal)23
} // loop through faces24

25
26
27
28
29
30
31
32
33
34

Page 1/7/Users/scshca/Desktop/mesh_structures.cppSaved: 30/01/2018 11:33:34 Printed for: Hamish Carr// FACE DATA STRUCTURE
1
for (each face f)
2
{ // loop through faces
3
// start with a zero vector
4
normal = zero
5
for (each vertex v on face f)
6
{ // loop through vertices on face
7
// loop through all faces (including this one)
8
for (each face f1)
9
{ // loop through faces again
10
for (each vertex v1 on face f1)
11
{ // loop through vertices on faces
12
// if it’s the same vertex (look out for roundoff errors!)
13
if (v1 == v)
14
{ // vertex match
15
compute normal n_f1 for face f1
16
normal += n_f1
17
} // vertex match
18
} // loop through vertices on faces
19
} // loop through faces again
20
// note: we don’t need to keep the degree or divide through
21
// because we’re going to normalise anyway!
22
normalise(normal)
23
} // loop through faces
24
25
26
27
28
29
30
31
32
33
34

COMP3811: Computer Graphics 2014-2015

GLint vertices[8][3] = { -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, !
1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1}; !
GLint normals[6][3] = { -1, 0, 0, 0, -1, 0, 0, 0, -1!
1, 0, 0, 0, 1, 0, 0, 0, 1}; !
unsigned int triangles[36] = { 0, 1, 3, 0, 3, 2, 0, 1, 4, 1, 4, 5, !
0, 2, 4, 2, 6, 4, 5, 4, 6, 5, 6, 7, !
2, 3, 7, 2, 7, 6, 1, 5, 7, 1, 7, 3};!
!
glEnableClientState(GL_VERTEX_ARRAY);!
glVertexPointer(3, GL_INT, 0, vertices);!
glEnableClientState(GL_NORMAL_ARRAY);!
glNormalPointer(3, GL_INT, 0, normals);!
!
// this runs it’s own loop internally!
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, indices);!
!
// turn it off when we’re done!
glDisableClientState(GL_VERTEX_ARRAY);!
glDisableClientState(GL_NORMAL_ARRAY);!

Cube With Normals

X

Y

Z

0

1

2

3

4

5

6

7

COMP3811: Computer Graphics 2014-2015

Vertex Buffer Objects
•Vertex Buffer Object:!
• essentially a Vertex Array cached in VRAM!
•which means all the usual tasks:!
• allocation: glGenBuffers, glDeleteBuffers!
• binding: glBindBuffer!
• transfer: glBufferData

COMP3811: Computer Graphics 2014-2015

Faster Yet . . .
•Use the GPU instead of the CPU!
•Do everything on the GPU!
•Using geometry, vertex, pixel shaders!
•Generalise to GPGPU programming!
• Shift the O/S to the GPU!
• Treat the CPU as an I/O device

COMP3811: Computer Graphics 2014-2015

Vertex Arrays vs. Vertex Buffer Objects

•Vertex Array: !
• assembled in RAM, transferred to VRAM!
• pay RAM cost to set up, then PCIe!
•Vertex Buffer Object:!
• assembled in VRAM!
• pay only PCIe cost to set up

COMP3811: Computer Graphics 2014-2015

Faster Yet . . .
•Use the GPU instead of the CPU!
•Do everything on the GPU!
•Using geometry, vertex, pixel shaders!
•Generalise to GPGPU programming!
• Shift the O/S to the GPU!
• Treat the CPU as an I/O device

COMP3811: Computer Graphics 2014-2015

Engineering Graphics Code
• Four major types of graphics use:!
• Small-scale!
•Games!
• Film!
•Visualisation / CAD / CAM!
• Each of which has different usages

COMP3811: Computer Graphics 2014-2015
GLint vertices[8][3] = { -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, !
1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1}; !
GLint normals[6][3] = { -1, 0, 0, 0, -1, 0, 0, 0, -1 !
1, 0, 0, 0, 1, 0, 0, 0, 1}; !
unsigned int triangles[36] = { 0, 1, 3, 0, 3, 2, 0, 1, 4, 1, 4, 5, !
0, 2, 4, 2, 6, 4, 5, 4, 6, 5, 6, 7, !
2, 3, 7, 2, 7, 6, 1, 5, 7, 1, 7, 3}; !
!
glEnableClientState(GL_VERTEX_ARRAY); !
glVertexPointer(3, GL_INT, 0, vertices); !
glEnableClientState(GL_NORMAL_ARRAY); !
glNormalPointer(3, GL_INT, 0, normals); !
!
// this runs it’s own loop internally !
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, indices); !
!
// turn it off when we’re done !
glDisableClientState(GL_VERTEX_ARRAY); !
glDisableClientState(GL_NORMAL_ARRAY); !
Cube With NormalsX
Y
Z
0
1
2
3
4
5
6
7
COMP3811: Computer Graphics 2014-2015
Vertex Buffer Objects•
Vertex Buffer Object:!

essentially a Vertex Array cached in VRAM!

which means all the usual tasks:!

allocation: glGenBuffers, glDeleteBuffers!

binding: glBindBuffer!

transfer: glBufferData
COMP3811: Computer Graphics 2014-2015
Faster Yet . . .

Use the GPU instead of the CPU!

Do everything on the GPU!

Using geometry, vertex, pixel shaders!

Generalise to GPGPU programming!

Shift the O/S to the GPU!

Treat the CPU as an I/O device
COMP3811: Computer Graphics 2014-2015
Vertex Arrays vs. Vertex Buffer Objects

Vertex Array: !

assembled in RAM, transferred to VRAM!

pay RAM cost to set up, then PCIe!

Vertex Buffer Object:!

assembled in VRAM!

pay only PCIe cost to set up
COMP3811: Computer Graphics 2014-2015
Faster Yet . . .

Use the GPU instead of the CPU!

Do everything on the GPU!

Using geometry, vertex, pixel shaders!

Generalise to GPGPU programming!

Shift the O/S to the GPU!

Treat the CPU as an I/O device
COMP3811: Computer Graphics 2014-2015
Engineering Graphics Code

Four major types of graphics use:!

Small-scale!

Games!

Film!

Visualisation / CAD / CAM!

Each of which has different usages

Page 2/7/Users/scshca/Desktop/mesh_structures.cpp
Saved: 30/01/2018 11:33:34 Printed for: Hamish Carr

// INDEXED FACE DATA STRUCTURE35
// initialise the normals to zeros for each vertex36
for (each vertex v)37
normal[v] = zero38

39
// now loop through the faces40
for (each face f)41
{ // loop through faces42
// start with a zero vector43
compute normal n_f for face f44
// loop through face’s vertices45
for (each vertex v on face f)46
{ // per vertex47
// add the face normal to the vertex normal48
normal[v] += n_f49
} // per vertex 50
} // loop through faces51

52
// now normalise them all53
for (each vertex v)54
normalise(normal[v])55

56
57
58
59
60
61
62
63
64
65
66
67
68

Page 2/7/Users/scshca/Desktop/mesh_structures.cppSaved: 30/01/2018 11:33:34 Printed for: Hamish Carr// INDEXED FACE DATA STRUCTURE
35
// initialise the normals to zeros for each vertex
36
for (each vertex v)
37
normal[v] = zero
38
39
// now loop through the faces
40
for (each face f)
41
{ // loop through faces
42
// start with a zero vector
43
compute normal n_f for face f
44
// loop through face’s vertices
45
for (each vertex v on face f)
46
{ // per vertex
47
// add the face normal to the vertex normal
48
normal[v] += n_f
49
} // per vertex
50
} // loop through faces
51
52
// now normalise them all
53
for (each vertex v)
54
normalise(normal[v])
55
56
57
58
59
60
61
62
63
64
65
66
67
68

Page 3/7/Users/scshca/Desktop/mesh_structures.cpp
Saved: 30/01/2018 11:33:34 Printed for: Hamish Carr

// FACE-BASED DATA STRUCTURE69
// loop through vertices70
for (each vertex v)71
{ // for each vertex72
// initialise normal to zero73
normal[v] = zero74
// start loop control variable at first face75
face = first[v]76
do { // do loop around neighbours77
compute normal n_f for face f78
normal[v] += n_f79
// now find which neighbour to use80
if (faceV[0] == v)81
face = neighbour[0]82
else if (faceV[1] == v) 83
face = neighbour[1]84
else if (faceV[2] == v)85
face = neighbour[2]86
} // do loop around neighbours87
while (face != first[v])88
89
// now normalise90
normalise(normal[v])91
} // for each vertex92

93
94
95
96
97
98
99

100
101

// WINGED-EDGE DATA STRUCTURE102

Page 3/7/Users/scshca/Desktop/mesh_structures.cppSaved: 30/01/2018 11:33:34 Printed for: Hamish Carr// FACE-BASED DATA STRUCTURE
69
// loop through vertices
70
for (each vertex v)
71
{ // for each vertex
72
// initialise normal to zero
73
normal[v] = zero
74
// start loop control variable at first face
75
face = first[v]
76
do { // do loop around neighbours
77
compute normal n_f for face f
78
normal[v] += n_f
79
// now find which neighbour to use
80
if (faceV[0] == v)
81
face = neighbour[0]
82
else if (faceV[1] == v)
83
face = neighbour[1]
84
else if (faceV[2] == v)
85
face = neighbour[2]
86
} // do loop around neighbours
87
while (face != first[v])
88

89
// now normalise
90
normalise(normal[v])
91
} // for each vertex
92
93
94
95
96
97
98
99
100
101
// WINGED-EDGE DATA STRUCTURE
102

Page 4/7/Users/scshca/Desktop/mesh_structures.cpp
Saved: 30/01/2018 11:37:02 Printed for: Hamish Carr

// WINGED-EDGE DATA STRUCTURE103
// loop through vertices104
for (each vertex v)105
{ // for each vertex106
// initialise normal to zero107
normal[v] = zero108
// start loop control variable at first edge109
edge = firstEdge[v]110
do { // do loop around neighbours111
// retrieve the corresponding face112
face = edge.face[0]113
// note: each vertex will need retrieval through edge114

// there are some further optimisations available here115
compute normal n_f for face f116
normal[v] += n_f117
// now step forward118
if (edge == firstEdge[end[0]])119

edge = edge.next[0]120
else121
edge = edge.next[1]122
} // do loop around neighbours123
while (edge != firstEdge[v])124
125
// now normalise126
normalise(normal[v])127
} // for each vertex128

129
130
131
132
133
134
135
136

Page 4/7/Users/scshca/Desktop/mesh_structures.cppSaved: 30/01/2018 11:37:02 Printed for: Hamish Carr// WINGED-EDGE DATA STRUCTURE
103
// loop through vertices
104
for (each vertex v)
105
{ // for each vertex
106
// initialise normal to zero
107
normal[v] = zero
108
// start loop control variable at first edge
109
edge = firstEdge[v]
110
do { // do loop around neighbours
111
// retrieve the corresponding face
112
face = edge.face[ 0]
113
// note: each vertex will need retrieval through edge
114
// there are some further optimisations available here
115
compute normal n_f for face f
116
normal[v] += n_f
117
// now step forward
118
if (edge == firstEdge[end[ 0]])
119
edge = edge.next[ 0]
120
else
121
edge = edge.next[ 1]
122
} // do loop around neighbours
123
while (edge != firstEdge[v])
124

125
// now normalise
126
normalise(normal[v])
127
} // for each vertex
128
129
130
131
132
133
134
135
136

Page 5/7/Users/scshca/Desktop/mesh_structures.cpp
Saved: 30/01/2018 11:37:02 Printed for: Hamish Carr

// HALF-EDGE DATA STRUCTURE137
// loop through vertices138
for (each vertex v)139
{ // for each vertex140
// initialise normal to zero141
normal[v] = zero142
// start loop control variable at first edge143
halfedge = firstHalfEdge[v]144
do { // do loop around neighbours145
// retrieve the corresponding face146
face = halfedge.face[0]147
// note: each vertex will need retrieval through edge148

// there are some further optimisations available here149
compute normal n_f for face f150
normal[v] += n_f151
// now step forward152
edge = edge.next153
} // do loop around neighbours154
while (edge != firstHalfEdge[v])155
156
// now normalise157
normalise(normal[v])158
} // for each vertex159

160
161
162
163
164
165
166
167
168
169
170

Page 5/7/Users/scshca/Desktop/mesh_structures.cppSaved: 30/01/2018 11:37:02 Printed for: Hamish Carr// HALF-EDGE DATA STRUCTURE
137
// loop through vertices
138
for (each vertex v)
139
{ // for each vertex
140
// initialise normal to zero
141
normal[v] = zero
142
// start loop control variable at first edge
143
halfedge = firstHalfEdge[v]
144
do { // do loop around neighbours
145
// retrieve the corresponding face
146
face = halfedge.face[0]
147
// note: each vertex will need retrieval through edge
148
// there are some further optimisations available here
149
compute normal n_f for face f
150
normal[v] += n_f
151
// now step forward
152
edge = edge.next
153
} // do loop around neighbours
154
while (edge != firstHalfEdge[v])
155

156
// now normalise
157
normalise(normal[v])
158
} // for each vertex
159
160
161
162
163
164
165
166
167
168
169
170

Page 6/7/Users/scshca/Desktop/mesh_structures.cpp
Saved: 30/01/2018 11:37:02 Printed for: Hamish Carr

// DIRECTED-EDGE DATA STRUCTURE171
// loop through vertices172
for (each vertex v)173
{ // for each vertex174
// initialise normal to zero175
normal[v] = zero176
// start loop control variable at first edge177
halfedge = firstHalfEdge[v]178
do { // do loop around neighbours179
// retrieve the corresponding face180
face = halfedge / 3181
whichEdge = halfedge % 3182
// note: each vertex will need retrieval through edge183

// there are some further optimisations available here184
compute normal n_f for face f185
normal[v] += n_f186
edge = 3 * face + (whichEdge + 1) % 3187
} // do loop around neighbours188
while (edge != firstHalfEdge[v])189
190
// now normalise191
normalise(normal[v])192
} // for each vertex193

194
195
196
197
198
199
200
201
202
203
204

Page 6/7/Users/scshca/Desktop/mesh_structures.cppSaved: 30/01/2018 11:37:02 Printed for: Hamish Carr// DIRECTED-EDGE DATA STRUCTURE
171
// loop through vertices
172
for (each vertex v)
173
{ // for each vertex
174
// initialise normal to zero
175
normal[v] = zero
176
// start loop control variable at first edge
177
halfedge = firstHalfEdge[v]
178
do { // do loop around neighbours
179
// retrieve the corresponding face
180
face = halfedge / 3
181
whichEdge = halfedge % 3
182
// note: each vertex will need retrieval through edge
183
// there are some further optimisations available here
184
compute normal n_f for face f
185
normal[v] += n_f
186
edge = 3 * face + (whichEdge + 1) % 3
187
} // do loop around neighbours
188
while (edge != firstHalfEdge[v])
189

190
// now normalise
191
normalise(normal[v])
192
} // for each vertex
193
194
195
196
197
198
199
200
201
202
203
204

Page 7/7/Users/scshca/Desktop/mesh_structures.cpp
Saved: 30/01/2018 11:52:07 Printed for: Hamish Carr

// data structure for directed-edge processing205
class Mesh206

{ // Mesh207
public:208
std::vector position; // xyz209
std::vector firstDirectedEdge; // per vertex210
std::vector faceVertices; // doubles as “directed edge to”211
std::vector otherHalf; // pairs the directed edges212

213
void Render()214

{ // Render()215
// use the arrays for vertex array calls216
// VBO’s are similar, but a bit messier217
glEnableClientState(GL_VERTEX_ARRAY);218
glVertexPointer(3, GL_INT, 0, position);219
glDrawElements(GL_TRIANGLES, faceVertices.size(), GL_UNSIGNED_INT, faceVertices);220
glDisableClientState(GL_VERTEX_ARRAY);221
} // Render()222

223
224
225

}; // Mesh226
227
228
229
230
231
232

Page 7/7/Users/scshca/Desktop/mesh_structures.cppSaved: 30/01/2018 11:52:07 Printed for: Hamish Carr// data structure for directed-edge processing
205
class Mesh
206
{ // Mesh
207
public:
208
std::vector position; // xyz
209
std::vector firstDirectedEdge; // per vertex
210
std::vector faceVertices; // doubles as “directed edge to”
211
std::vector otherHalf; // pairs the directed edges
212
213
void Render()
214
{ // Render()
215
// use the arrays for vertex array calls
216
// VBO’s are similar, but a bit messier
217
glEnableClientState(GL_VERTEX_ARRAY);
218
glVertexPointer( 3, GL_INT, 0, position);
219
glDrawElements(GL_TRIANGLES, faceVertices.size(), GL_UNSIGNED_INT, faceVertices);
220
glDisableClientState(GL_VERTEX_ARRAY);
221
} // Render()
222
223
224
225
}; // Mesh
226
227
228
229
230
231
232