gats · pdf fileintroduction section 1 ©1991 – 2016 garth santor & trinh hān...

278
GATS Encyclopaedia Garth Santor & Trinh Hān © 1991 – 2016

Upload: lydung

Post on 06-Feb-2018

257 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

GATS Encyclopaedia

Garth Santor & Trinh Hān © 1991 – 2016

Page 2: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Introduction Section 1

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 2 of 278

Introduction

Contents

Introduction ................................................................................................................................................................................................. 2

AI .............................................................................................................................................................................................................. 12 Neural Networks ................................................................................................................................................................................... 12

Algorithms ................................................................................................................................................................................................ 13

Algorithm vs. Formula .......................................................................................................................................................................... 13 Algorithm vs. Heuristic ......................................................................................................................................................................... 14

Analysis of Algorithms ......................................................................................................................................................................... 14 Counting ................................................................................................................................................................................................ 16 Numerical .............................................................................................................................................................................................. 16 Printing .................................................................................................................................................................................................. 20 Searching............................................................................................................................................................................................... 21 Sorting ................................................................................................................................................................................................... 23

Applications .............................................................................................................................................................................................. 42 UML Tools............................................................................................................................................................................................ 42

Audio Programming.................................................................................................................................................................................. 43 Compact Disc ........................................................................................................................................................................................ 43

Audio Engines ....................................................................................................................................................................................... 43 Music..................................................................................................................................................................................................... 48

C++ Programming .................................................................................................................................................................................... 50 Assertions .............................................................................................................................................................................................. 50 Best Practices ........................................................................................................................................................................................ 51

Bit Manipulation ................................................................................................................................................................................... 68 Boost ..................................................................................................................................................................................................... 70

Classes................................................................................................................................................................................................... 77 Coding Devices and Idioms .................................................................................................................................................................. 79 Dangerous Coding Practices ................................................................................................................................................................. 90

Memory Management ........................................................................................................................................................................... 91 Preprocessor .......................................................................................................................................................................................... 95

STL ....................................................................................................................................................................................................... 97 Templates .............................................................................................................................................................................................. 97

Database .................................................................................................................................................................................................... 99 Data Normalization ............................................................................................................................................................................... 99

Data Structures ........................................................................................................................................................................................ 106

Page 3: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Introduction Section 1

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278

Set ....................................................................................................................................................................................................... 106 Design Patterns ....................................................................................................................................................................................... 111

Implementation Patterns ..................................................................................................................................................................... 112 Game Programming ................................................................................................................................................................................ 115

Game Architecture .............................................................................................................................................................................. 115

Input .................................................................................................................................................................................................... 123 Logic / AI ............................................................................................................................................................................................ 123

Networking ......................................................................................................................................................................................... 124 Graphics .................................................................................................................................................................................................. 130

Concepts .............................................................................................................................................................................................. 130

Direct3D 9.0 Programming ................................................................................................................................................................. 137 Direct3D 10.0 Programming ............................................................................................................................................................... 153

File Formats ........................................................................................................................................................................................ 155 Hardware ............................................................................................................................................................................................. 183 Terrain ................................................................................................................................................................................................. 186

History..................................................................................................................................................................................................... 192 Mathematics ............................................................................................................................................................................................ 195

General ................................................................................................................................................................................................ 195 Algebra ................................................................................................................................................................................................ 198 2D/3D Algebra .................................................................................................................................................................................... 200

Calculus............................................................................................................................................................................................... 208

Geometry............................................................................................................................................................................................. 209 Graphs ................................................................................................................................................................................................. 225

Logic & Boolean Algebra ................................................................................................................................................................... 233 Number Systems ................................................................................................................................................................................. 238 Statistics .............................................................................................................................................................................................. 238 Trigonometry ...................................................................................................................................................................................... 241

Operating Systems .................................................................................................................................................................................. 244

Windows Vista .................................................................................................................................................................................... 244 Physics .................................................................................................................................................................................................... 245

General ................................................................................................................................................................................................ 245

Game ................................................................................................................................................................................................... 251 Metric .................................................................................................................................................................................................. 252

Programming Concepts ........................................................................................................................................................................... 254 Concurrent Programming.................................................................................................................................................................... 254 Development Process .......................................................................................................................................................................... 256 Errors................................................................................................................................................................................................... 258 Exception Handling ............................................................................................................................................................................ 262

Page 4: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Introduction Section 1

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 4 of 278

Generic Programming ......................................................................................................................................................................... 265 Object-Oriented Programming............................................................................................................................................................ 267

Testing & Reliability........................................................................................................................................................................... 269 Appendices .............................................................................................................................................................................................. 276

Page 5: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Introduction Section 1

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 5 of 278

Detailed Contents Introduction ................................................................................................................................................................................................. 2 AI .............................................................................................................................................................................................................. 12

Neural Networks ................................................................................................................................................................................... 12

Back Propagation Learning............................................................................................................................................................... 12 Algorithms ................................................................................................................................................................................................ 13

Pseudo-code Style ............................................................................................................................................................................. 13 Algorithm vs. Formula .......................................................................................................................................................................... 13

Algorithm vs. Heuristic ......................................................................................................................................................................... 14 Analysis of Algorithms ......................................................................................................................................................................... 14

Asymptotic Analysis ......................................................................................................................................................................... 14

Big-Oh Notation (theta & omega) .................................................................................................................................................... 15 Ram Model of Computation ............................................................................................................................................................. 15

Counting ................................................................................................................................................................................................ 16 Digits ................................................................................................................................................................................................. 16

Numerical .............................................................................................................................................................................................. 16

Greatest Common Divisor ................................................................................................................................................................ 16 Highest Common Factor ................................................................................................................................................................... 16

Multiplication – Russian Peasant Algorithm .................................................................................................................................... 17 Sieve of Eratosthenes ........................................................................................................................................................................ 17

Printing .................................................................................................................................................................................................. 20

Natural Numbers ............................................................................................................................................................................... 20 Searching............................................................................................................................................................................................... 21

Binary ................................................................................................................................................................................................ 21

Linear ................................................................................................................................................................................................ 22 Remove from Sequence .................................................................................................................................................................... 22 Splay Trees........................................................................................................................................................................................ 23

Sorting ................................................................................................................................................................................................... 23

Introduction ....................................................................................................................................................................................... 23

Bogo Sort .......................................................................................................................................................................................... 25

Cocktail-shaker ................................................................................................................................................................................. 27

Comb Sort ......................................................................................................................................................................................... 29 Count Sort ......................................................................................................................................................................................... 30 Heap Sort .......................................................................................................................................................................................... 30 Insertion Sort ..................................................................................................................................................................................... 32 Merge Sort ........................................................................................................................................................................................ 33 Ordersort ........................................................................................................................................................................................... 36

Page 6: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Introduction Section 1

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 6 of 278

Permutation Sort ............................................................................................................................................................................... 37 Pigeonhole Sort ................................................................................................................................................................................. 37

Quick sort .......................................................................................................................................................................................... 37 Selection Sort .................................................................................................................................................................................... 39

Shell’s Sort ........................................................................................................................................................................................ 41

Applications .............................................................................................................................................................................................. 42 UML Tools............................................................................................................................................................................................ 42

Argo UML ........................................................................................................................................................................................ 42 Audio Programming.................................................................................................................................................................................. 43

Storage Requirements ....................................................................................................................................................................... 43

Compact Disc ........................................................................................................................................................................................ 43 Sampling Rate ................................................................................................................................................................................... 43

Audio Engines ....................................................................................................................................................................................... 43 FMOD 4+ .......................................................................................................................................................................................... 44 FMOD 3.74 ....................................................................................................................................................................................... 46

Music..................................................................................................................................................................................................... 48 Sound Frequencies ............................................................................................................................................................................ 48

C++ Programming .................................................................................................................................................................................... 50 Assertions .............................................................................................................................................................................................. 50

Run-time Assertions.......................................................................................................................................................................... 50

Compile-time Assertions .................................................................................................................................................................. 50

Best Practices ........................................................................................................................................................................................ 51 BOOST ............................................................................................................................................................................................. 51

Coding Style...................................................................................................................................................................................... 55 Compiler / Environment ................................................................................................................................................................... 56 Design ............................................................................................................................................................................................... 56 Functions and Operators ................................................................................................................................................................... 57

Class Design and Inheritance ............................................................................................................................................................ 58

Construction, Destruction and Copying ............................................................................................................................................ 61 Namespaces and Modules ................................................................................................................................................................. 62 Templates and Genericity ................................................................................................................................................................. 62

Error Handling and Exceptions ......................................................................................................................................................... 63 STL Containers ................................................................................................................................................................................. 65 STL Algorithms ................................................................................................................................................................................ 66 Type Safety ....................................................................................................................................................................................... 67 OpenMP ............................................................................................................................................................................................ 68 String Manipulation .......................................................................................................................................................................... 68

Bit Manipulation ................................................................................................................................................................................... 68

Page 7: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Introduction Section 1

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 7 of 278

Boost ..................................................................................................................................................................................................... 70 Classes................................................................................................................................................................................................... 77

Access Specifiers .............................................................................................................................................................................. 77 Slurping and Binding ........................................................................................................................................................................ 78

Coding Devices and Idioms .................................................................................................................................................................. 79

I/O Stream Pattern............................................................................................................................................................................. 79 Curiously Recurring Template Pattern (CRTP) ................................................................................................................................ 82

Delegates ........................................................................................................................................................................................... 82 Duff’s Device .................................................................................................................................................................................... 87 Functors............................................................................................................................................................................................. 88

Transactional Programming .............................................................................................................................................................. 89 Dangerous Coding Practices ................................................................................................................................................................. 90

operator T* ........................................................................................................................................................................................ 90 Raw Pointers ..................................................................................................................................................................................... 90

Memory Management ........................................................................................................................................................................... 91

Memory Layout ................................................................................................................................................................................ 91 Memory Leaks .................................................................................................................................................................................. 91

Microsoft’s CRTDBG Library .......................................................................................................................................................... 94 Preprocessor .......................................................................................................................................................................................... 95

Macros............................................................................................................................................................................................... 95

STL ....................................................................................................................................................................................................... 97

Which container do I use? ................................................................................................................................................................. 97 Templates .............................................................................................................................................................................................. 97

Template Programming Techniques ................................................................................................................................................. 97 Database .................................................................................................................................................................................................... 99

Data Normalization ............................................................................................................................................................................... 99 First Normal Form (1NF).................................................................................................................................................................. 99

Second Normal Form (2NF) ........................................................................................................................................................... 101

Third Normal Form (3NF) .............................................................................................................................................................. 103 Forth Normal Form (4NF) .............................................................................................................................................................. 104

Data Structures ........................................................................................................................................................................................ 106

Set ....................................................................................................................................................................................................... 106 Design Patterns ....................................................................................................................................................................................... 111

Bridge .............................................................................................................................................................................................. 111 Delegate .......................................................................................................................................................................................... 111

Implementation Patterns ..................................................................................................................................................................... 112 Double Check Locking Pattern (DCLP) ......................................................................................................................................... 112 Producer-Consumer ........................................................................................................................................................................ 112

Page 8: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Introduction Section 1

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 8 of 278

Game Programming ................................................................................................................................................................................ 115 Game Architecture .............................................................................................................................................................................. 115

Direct3D and the Win32 Message Pump ........................................................................................................................................ 115 Game Loops .................................................................................................................................................................................... 120

Input .................................................................................................................................................................................................... 123

Thumbing Styles ............................................................................................................................................................................. 123 Logic / AI ............................................................................................................................................................................................ 123

Feedback Loops .............................................................................................................................................................................. 123 Networking ......................................................................................................................................................................................... 124

DirectPlay ....................................................................................................................................................................................... 124

Networking Issues ........................................................................................................................................................................... 126 Threading Issues ............................................................................................................................................................................. 128

Graphics .................................................................................................................................................................................................. 130 Concepts .............................................................................................................................................................................................. 130

Blit................................................................................................................................................................................................... 130

Camera ............................................................................................................................................................................................ 130 Culling, Backface ............................................................................................................................................................................ 133

Mouse Look .................................................................................................................................................................................... 134 Picking ............................................................................................................................................................................................ 135 Sprite ............................................................................................................................................................................................... 135

Texel ............................................................................................................................................................................................... 135

Vertex Buffer .................................................................................................................................................................................. 136 Vertex Winding ............................................................................................................................................................................... 136

Direct3D 9.0 Programming ................................................................................................................................................................. 137 Blitting Surface to Back Buffer ...................................................................................................................................................... 137 CopyRect......................................................................................................................................................................................... 137 Direct3D9 Pipeline.......................................................................................................................................................................... 137

Flexible Vertex Format ................................................................................................................................................................... 139

Fog .................................................................................................................................................................................................. 140 Images ............................................................................................................................................................................................. 141 Lighting, Direct3D Types ............................................................................................................................................................... 141

Meshes ............................................................................................................................................................................................ 144 Primitives ........................................................................................................................................................................................ 147 Sprites – ID3DXSprite .................................................................................................................................................................... 151 Surfaces – Direct writes to the back-buffer DirectX 9.0 .............................................................................................................. 152 Tuning Tips (Optimization) ............................................................................................................................................................ 153

Direct3D 10.0 Programming ............................................................................................................................................................... 153 API Differences between Direct3D 9 and Direct3D 10 .................................................................................................................. 153

Page 9: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Introduction Section 1

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 9 of 278

File Formats ........................................................................................................................................................................................ 155 RAW ............................................................................................................................................................................................... 155

X-file Direct3D .......................................................................................................................................................................... 156 Sample Framework DX-SDK 9.0c.............................................................................................................................................. 163

Sample Framework DX-SDK < 9.0c ........................................................................................................................................... 168

TextHelper Object SDK 9.0c ....................................................................................................................................................... 179 Texture Mapping ............................................................................................................................................................................. 180

Two-dimensional Rendering ........................................................................................................................................................... 183 Hardware ............................................................................................................................................................................................. 183

Adapters .......................................................................................................................................................................................... 183

Terrain ................................................................................................................................................................................................. 186 Height Maps .................................................................................................................................................................................... 186

Lighting, Static ................................................................................................................................................................................ 188 Skyboxes (sky-domes) .................................................................................................................................................................... 189

History..................................................................................................................................................................................................... 192

DirectX ............................................................................................................................................................................................ 192 Mathematics ............................................................................................................................................................................................ 195

General ................................................................................................................................................................................................ 195 Factorial .......................................................................................................................................................................................... 195 Fibonacci Numbers ......................................................................................................................................................................... 195

Golden Ratio ................................................................................................................................................................................... 196

Logarithms ...................................................................................................................................................................................... 197 Numbers .......................................................................................................................................................................................... 197

Pi ..................................................................................................................................................................................................... 197 Algebra ................................................................................................................................................................................................ 198

Binomial Coefficient ....................................................................................................................................................................... 198 Permutation ..................................................................................................................................................................................... 199

Sum of Natural Numbers ................................................................................................................................................................ 199

2D/3D Algebra .................................................................................................................................................................................... 200 Coordinate Transforms ................................................................................................................................................................... 200 Quaternion....................................................................................................................................................................................... 202

Transformations .............................................................................................................................................................................. 205 Vector (geometric) .......................................................................................................................................................................... 207

Calculus............................................................................................................................................................................................... 208 Euler’s Constant – e ........................................................................................................................................................................ 208

Geometry............................................................................................................................................................................................. 209 Euler Angles.................................................................................................................................................................................... 209 Lines – 2D ....................................................................................................................................................................................... 209

Page 10: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Introduction Section 1

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 10 of 278

Polyhedra ........................................................................................................................................................................................ 211 Polyhedra – Regular ........................................................................................................................................................................ 211

Tait-Bryan Angles ........................................................................................................................................................................... 224 Graphs ................................................................................................................................................................................................. 225

Representations ............................................................................................................................................................................... 225

Path-finding..................................................................................................................................................................................... 229 Logic & Boolean Algebra ................................................................................................................................................................... 233

Mathematical Induction .................................................................................................................................................................. 233 Propositional Logic ......................................................................................................................................................................... 234

Number Systems ................................................................................................................................................................................. 238

Two’s Complement ......................................................................................................................................................................... 238 Statistics .............................................................................................................................................................................................. 238

Arithmetic Mean ............................................................................................................................................................................. 238 Frequency distribution .................................................................................................................................................................... 238 Histogram ........................................................................................................................................................................................ 239

Mode ............................................................................................................................................................................................... 239 Standard Deviation & Variance ...................................................................................................................................................... 239

Statistical Median............................................................................................................................................................................ 240 Trigonometry ...................................................................................................................................................................................... 241

Operating Systems .................................................................................................................................................................................. 244

Windows Vista .................................................................................................................................................................................... 244

Automatic Log In ............................................................................................................................................................................ 244 Physics .................................................................................................................................................................................................... 245

General ................................................................................................................................................................................................ 245 Bounce ............................................................................................................................................................................................ 245 Gravity ............................................................................................................................................................................................ 245 Material Properties .......................................................................................................................................................................... 246

Game ................................................................................................................................................................................................... 251

Collision Detection ......................................................................................................................................................................... 251 Metric .................................................................................................................................................................................................. 252

Prefixes ........................................................................................................................................................................................... 252

Programming Concepts ........................................................................................................................................................................... 254 Concurrent Programming.................................................................................................................................................................... 254

Best Practices .................................................................................................................................................................................. 254 Internal vs. External Locking .......................................................................................................................................................... 255 Zombie Process ............................................................................................................................................................................... 256

Development Process .......................................................................................................................................................................... 256 Code Changes – Big/Little .............................................................................................................................................................. 256

Page 11: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Introduction Section 1

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 11 of 278

GOF – Gang of Four ....................................................................................................................................................................... 256 Reuse ............................................................................................................................................................................................... 257

Errors................................................................................................................................................................................................... 258 Bug .................................................................................................................................................................................................. 262

Exception Handling ............................................................................................................................................................................ 262

Benefits of exception handling ....................................................................................................................................................... 262 Software Design Issues ................................................................................................................................................................... 263

Why do so many people dislike exceptions? .................................................................................................................................. 264 Generic Programming ......................................................................................................................................................................... 265

Generic Programming Techniques ................................................................................................................................................. 265

Traits Classes .................................................................................................................................................................................. 266 Object-Oriented Programming............................................................................................................................................................ 267

Class Invariants ............................................................................................................................................................................... 267 Contract Classes .............................................................................................................................................................................. 267 Functor Classes ............................................................................................................................................................................... 268

Terminator Class ............................................................................................................................................................................. 269 Zombie Object ................................................................................................................................................................................ 269

Testing & Reliability........................................................................................................................................................................... 269 Test Doubles ................................................................................................................................................................................... 271 Testing Styles .................................................................................................................................................................................. 272

Transactional Programming Style................................................................................................................................................... 272

Invariants......................................................................................................................................................................................... 274 Appendices .............................................................................................................................................................................................. 276

Acronyms ........................................................................................................................................................................................ 276 References ....................................................................................................................................................................................... 276 Index ............................................................................................................................................................................................... 277

Page 12: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

AI Section 2

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 12 of 278

AI

Neural Networks

Back Propagation Learning A LAYER is a vector of nodes

A NODE is a structure containing a vector of incoming link-weights (w), an incoming signal (in), an outgoing signal (out) and an error delta ( ).

function BACK-PROP-LEARNING( examples, network ) returns a neural network

inputs: examples, a set of examples, each with input vector (input) and output vector (output)

network, a vector of layers, activation function g

repeat

for each e in examples do

for each node in do

for i = 2 to size{layers} do

for each node in ilayers do

for each node in the output layer do

for i = L – 1 downto 1 do

for each node in ilayers do

for each in do

until some stopping criterion is satisfied

return NEURAL-NET-HYPOTHESIS( network )

1layers

i iin node w node input e out node g in node

1[ ]j j iin node w node out node layers

out node g in node

{ }offset nodenode g in node output e out node

1j j inode g in node w node node layers

node 1ilayers

node nodew node w node out node node

Page 13: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 13 of 278

Algorithms Algorithms are step-by-step problem solving procedures that produce their results in a finite number of steps. They produce the exact result, in a

predictable amount of time. The best case time can differ from the worst case time, but the worst case time is finite.

Example: Binary Search locates information in a sorted list in no more than n2log searches.

Algorithms are so valuable to the computing sciences because they can be studied in a language-independent and machine independent manner.

As a result of these attributes, algorithms have a durability and importance matched by few other topics in computing. The language-independent

nature of algorithms presents a unique problem for computer scientists – how do we compare the relative performance of algorithms without

implementing them? The two most important methods of comparison are (1) the HTURAM model of computation and (2) HTUasymptotic analysis of

worst-case complexity.

The RAM Model of Computation can identify algorithm performance on a specific input set. The asymptotic analysis or HTUbig-ohUTH notation is more

complex but can yield performance information over all input sets.

Pseudo-code Style The style used in this book for pseudo code is derived from the pseudo code conventions published in MIT’s Introduction to Algorithms [IA-90].

1. Indentation indicates block structure.

2. The looping constructs while, for and repeat/until and the conditional structures if, then, else have the same interpretation as in Pascal.

3. The symbol ← indicates assignment. Multiple assignment i ← j ← k assigns the value of k to both i and j.

4. Variables are local to the given procedure.

5. Array elements are accessed by specifying the array name followed by square brackets. Arrays are assumed to be zero-based, therefore the first

element of an array is located at offset 0, and the last element is located at offset length{A} – 1.

6. Attributes of objects are accessed by naming the attribute followed by the object name wrapped in brace brackets. (e.g. length{A} provides the

length of array A measured in elements.)

7. Parameters are passed to procedures by value unless specified otherwise.

Algorithm vs. Formula A formula is a statement of a rule, principle, or other factual relationship.

Often problems can be solved more directly with formula than they can with algorithms.

Page 14: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 14 of 278

Example

The sum of the natural numbers from 1 to n:

n

i

ixsum1

can be calculated using the following algorithm:

function SUM-NATURAL( n ) returns natural number

sum ← 0

for i ← 1 to n do

sum ← sum + i

return sum

This algorithm will require n addition operations, n assignment operations, and n increment operations. O(3n). The same value can be computed

with the following formula.

2

1

nnsum

This calculation only requires a single multiply, a single divide and a single add. O(3).

Algorithm vs. Heuristic ‘Heuriskein’ the Greek word meaning ‘to find’.

Heuristics are like algorithms but they do not have the algorithm’s guarantee of completing in finite time. They will bring us closer and closer to a

better solution with each iteration, but may never produce the exact answer.

Analysis of Algorithms

Asymptotic Analysis Asymptotic analysis is a method of analyzing the complexity of algorithms expressing their performance relative to an input size of the data. Our

assumption is that the specific input values do not matter, just the size of the input data set. With this assumption we define three functions:

Best-case complexity of the algorithm is the function defined by the minimum number of operations taken on an input set of size n.

Average-case complexity of the algorithm is the function defined by the average number of operations taken on an input set of size n.

Worst-case complexity of the algorithm is the function defined by the maximum number of operations taken on an input set of size n.

In practice, the formula that specifically describes the performance can be quite complex and may obscure the important governing terms of the

equation that it most indicative of the algorithm’s overall performance. To highlight these important terms we use HTUbig-ohUTH, theta, and omega

notations.

Page 15: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 15 of 278

Big-Oh Notation (theta & omega) Big-Oh notation is used to highlight the important terms in HTUasymptotic analysis of algorithms. The actual functions produced by an asymptotic

analysis of an algorithm can be quite complex yielding performance graphs with many subtle changes, peaks and troughs. These subtleties can

obscure the overall shape of the performance graph and hide key performance characteristic that allows us to compare the algorithm with another.

Big-Oh notation (Theta notation and Omega notation) provide a method of isolating that critical term that governs the overall time complexity of

the algorithm.

Big-Oh notation: ngOnf means ngc is an upper bound on nf . Thus there exists some constant c such that nf is always ngc

, for a sufficiently large enough n.

Omega notation: ngnf means ngc is a lower bound on nf . Thus there exists some constant c such that nf is always ngc ,

for a sufficiently large enough n.

Theta notation: ngnf means ngc 1 is an upper bound on nf and ngc 2

is a lower bound on nf . Thus there exists some constant

c such that nf is always ngc , for a sufficiently large enough n. Thus there exists constants 1c and

2c such that ngcnf 1 and

ngcnf 2. This is a tightly bound function.

Ram Model of Computation The RAM Model of Computation is a method of assessing the performance of an algorithm in a manner that is independent of language and

machine. This model assumes the existence of a hypothetical computer called the Random Access Machine or RAM. The performance properties

of this machine are:

Each simple operation (+, *, =, if, function call, etc.) takes exactly 1 clock cycle.

Each memory access takes exactly 1 clock cycle.

The total amount of memory is unlimited.

Loops and subroutines take a number of clock cycles equal to the sum of component parts.

The most significant complaint about this model is that the simple operations tend to take different amounts of time. Integer addition typically

takes less time than floating-point division. Conditional statements consume different amounts of time to execute the true path than the false path

on a pipelined processor. Branch-prediction further confuses the issue. Memory access times tend to degrade in large data sets due to the

decreasing frequency of cache hits and the swapping of virtual memory.

Despite its shortcomings, the RAM model of computation is reliable enough for scoring the one algorithm against another.

Page 16: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 16 of 278

Counting

Digits The number of digits in an integer can be counted by successive divisions by the base (usually 10). When the quotient reaches zero – stop

counting.

function NUMBER-OF-DIGITS( n, base ) returns integer

digitCount 0

repeat

n n div base

digitCount digitCount + 1

until n = 0

return digitCount

Numerical

Greatest Common Divisor See Highest Common Factor.

Highest Common Factor Perhaps the oldest non-trivial algorithm (circa 300 B.C.E.), Euclid’s algorithm calculates the value of the greatest common divisor of two integers.

It is most easily conceived as a recursive algorithm.

The underlying theory from which the algorithm is derived is that: babhcfbahcf mod,, .

Also known as Euclid’s Algorithm and Greatest Common Divisor.

function HCF( a, b ) returns natural number

if b = 0

then return a

else return HCF( b, a mod b )

Note:

a and b are natural numbers.

Passing the large of the numbers as the ‘a’ parameter minimizes the depth of the recursion.

Page 17: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 17 of 278

Multiplication – Russian Peasant Algorithm The “Russian Peasant Algorithm” was named by an English mathematician travelling through Russia in the 19th century. He was surprised by the

method of multiplication taught to peasants in schools. The algorithm itself is much older, perhaps the oldest known algorithm, dating back some

4,000 years to ancient Egypt.

The Algorithm

1. Write two numbers side by side.

2. Record below:

a. The first number, the quotient of the first number divided by two. Any remainder is discarded.

b. The second number, the product of the second number multiplied by two.

c. Repeat until the number in the first column is a one.

3. Cross out all of the rows in which the number in the first column is even.

4. Add all the numbers in the second column that are not crossed out. The sum is the product of the first two numbers.

function MULTIPLY( a, b ) returns integer

acc ← 0

loop

if a is odd

then acc ← acc + b

if a = 1

then return acc

2

aa

2b b

Endloop

Sieve of Eratosthenes The process used by Eratosthenes (276-196 BCE) to find prime numbers.

Algorithm

1. Write down contiguously and in order a list of all the natural numbers starting with 2 and ending with n.

2. Start with the first number in the list.

3. Cross out all of the multiples of that number.

4. Locate the next number in the list that is not crossed out.

5. Repeat steps 3 & 4 until there are only crossed out number remaining in the list.

Page 18: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 18 of 278

Example

Coding - Naïve C++

typedef unsigned natural_type;

typedef std::vector<natural_type> primes_type;

// load sieve

primes_type primes;

for( natural_type i = 2; i <= MAX; ++i )

primes.push_back( i );

// mark sieve

primes_type::size_type nextPrimePos = 0;

while( nextPrimePos < primes.size() ) {

natural_type nextPrimeValue = primes[nextPrimePos];

for( primes_type::size_type pos = nextPrimePos + nextPrimeValue;

pos < primes.size(); pos += nextPrimeValue )

primes[pos] = 0;

do {

++nextPrimePos;

} while( nextPrimePos < primes.size() && primes[nextPrimePos] == 0 );

}

// remove zeros

for( primes_type::size_type i = 0; i < primes.size(); )

if( primes[i] == 0 )

primes.erase( primes.begin() + i );

else

++i;

8 7 6 5 4 3 2 16 15 14 13 12 11 10 9 24 23 22 21 20 19 18 17

8 7 6 5 4 3 2 16 15 14 13 12 11 10 9 24 23 22 21 20 19 18 17

8 7 6 5 4 3 2 16 15 14 13 12 11 10 9 24 23 22 21 20 19 18 17

8 7 6 5 4 3 2 16 15 14 13 12 11 10 9 24 23 22 21 20 19 18 17

Page 19: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 19 of 278

Coding – Swap and Trim

Although it works, the runtime performance of this code is terrible owing to the cost of the erase method calls which are O(n). This produces an

overall algorithm time complexity of O(n2). We need to fix the remove zeros portion of the algorithm.

// remove zeros

primes_type::size_type iNonPrime = 2;

primes_type::size_type iPrime = 3;

while( iPrime < primes.size(); ) {

swap( primes[iNonPrime], primes[iPrime] );

++iNonPrime;

do {

++iPrime;

} while( iPrime < primes.size() && primes[iPrime] == 0 );

}

primes.resize( iNonPrime );

Coding – Tweaking the cleanup

Two improvements can be made: replacing the swap with a direct assignment (since each location is only visited once), and searching for the next

prime number in increments of two (since there are no prime numbers that are multiplies of 2).

// remove zeros

primes_type::size_type iNonPrime = 2;

primes_type::size_type iPrime = 3;

while( iPrime < primes.size(); ) {

primes[iNonPrime] = primes[iPrime];

++iNonPrime;

do {

iPrime += 2;

} while( iPrime < primes.size() && primes[iPrime] == 0 );

}

primes.resize( iNonPrime );

Coding – Tweaking the sieve

The sieve can be improved by starting each iteration of the sieve not at the first multiple of the prime to be removed but at the square of the prime

to be removed. This works because any multiples for the prime less than the square of the prime would have already been eliminated by a multiple

of one of the previous primes.

// mark sieve

primes_type::size_type nextPrimePos = 0;

while( nextPrimePos < primes.size() ) {

natural_type nextPrimeValue = primes[nextPrimePos];

for( primes_type::size_type pos = nextPrimeValue * nextPrimeValue - 2;

pos < primes.size(); pos += nextPrimeValue )

Page 20: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 20 of 278

primes[pos] = 0;

do {

++nextPrimePos;

} while( nextPrimePos < primes.size() && primes[nextPrimePos] == 0 );

}

Euler Sieve

Leonard Euler created a version of the Sieve of Eratosthenes that marks each non-prime only once. Euler’s method remove (for each prime

located) all of the products of the prime and the numbers remaining on the list.

Coding – Euler’s Sieve

// mark sieve

primes_type::size_type nextPrimePos = 0;

while( nextPrimePos < primes.size() ) {

natural_type nextPrimeValue = primes[nextPrimePos];

primes_type::size_type topValue = MAX / nextPrimeValue + 1;

while( topValue > nextPrimeValue ) {

while( primes[ --topValue – 2 ] == 0 );

primes[ topValue * nextPrimeValue – 2 ] = 0;

do {

++nextPrimePos;

} while( nextPrimePos < primes.size() && primes[nextPrimePos] == 0 );

}

Printing

Natural Numbers The topic of printing numbers includes the conversion of a number’s internal representations to sequences of digits of a specific base.

Implementation – Recursive

function TO-STRING( n, base ) returns string

digits ← “0123456789ABCDEF”

if n < base

then return digits[ n ]

else return TO-STRING( n div base, base ) + digits[ n mod base ]

Page 21: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 21 of 278

This algorithm lacks robustness in that a call to this function with a base of 1 would result in an infinite recursion. The standard solution would be

to use a driver function that asserts a base value greater than 1.

Searching

Binary

Binary search runs in O( logB2Bn ) time on sorted data sets. An unsuccessful search requires 1log N iterations of the loop or calls to the

function.

Implementation – Array, Recursive

This implementation returns the index of the target element if found, or the size of the vector if not.

function BINARY-SEARCH( A, key, low, high ) returns a natural number

if low ≤ high

then middle ← (low + high) div 2

if key = A[middle] then return middle

else if key < A[middle] then return BINARY-SEARCH( A, key, low, middle – 1 )

else return BINARY-SEARCH( A, key, middle + 1, high )

else return length{A}

Implementation – Array, Iterative

This implementation returns the index of the target element if found, or the size of the vector if not.

function BINARY-SEARCh( A, key, low, high ) returns a natural number

while low ≤ high do

middle ← (low + high) div 2

if key = A[middle] then return middle

else if key < A[middle] then high ← middle – 1

else low ← middle + 1

return length{A}

Implementation – Array, Iterative

A potential speed improvement can be found by reducing the amount of branching inside the loop. In this version we always search down to a

sub-list of size one, then test to see if the remaining element is the key.

Page 22: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 22 of 278

function BINARY-SEARCH( A, key, low, high ) returns a natural number

while low < high do

middle ← (low + high) div 2

if A[middle] < key

then low ← middle + 1

else high ← middle – 1

if low = high and A[ low ] = key

then return low

else return length{A}

Linear The simplest search algorithm is the linear search; which starts at one end of the data structure and through brute force, tests each element in turn

until the target has been found.

Implementation – Array

This implementation returns the index of the target element if found, or the size of the vector if not.

function LINEAR-SEARCH( A, key ) returns a natural number

for i ← 1 to length{A} – 1 do

if A[i] = key

then return i

return length{A}

Implementation – Pointer

This implementation returns the index of the target element if found, or the size of the vector if not.

function LINEAR-SEARCH( beg, end, key ) returns a pointer

current ← beg

while current ≠ end do

if value{current} = key

then return current

return end

Remove from Sequence Presented here are two algorithms that remove all instances of an item from the given sequence. The first algorithm performs better on contiguous

sequences, the second performs better on non-contiguous sequences such as linked lists.

Page 23: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 23 of 278

procedure REMOVE-FROM-SEQUENCE( S, item )

front ← first{S}

back ← first{S}

while front ≠ end{S} and value{front} ≠ item do

front ← next{front}

back ← next{back}

while front ≠ end{S} do

repeat front ← next{S}

until front = end{S} or value{front} ≠ item

while front ≠ end{S} and front ≠ item do

value{back} ← value{front}

back ← next{back}

front ← next{front}

ERASE( S, back, end )

procedure REMOVE-FROM-SEQUENCE( S, item )

p ← first{S}

while p ≠ end{S} do

if value{p} = item then

p ← ERASE( S, p )

else

p ← next{p}

Splay Trees

References

C/C++ Users Journal (September 2005)

Sorting

Introduction Sorting is an operation that places things into some natural order.

Sorts are said to be stable if the elements with the same key value appear in the output collection in the same order that they appear in the input

collection. Sort stability is important when sorting a collection several times, each time by a different key. (E.g. firstly by day, secondly by month,

lastly by year)

Name, best, average, worst, memory, stable, method, comparison, notes

Name Best Average Worst Memory Stable Method Comparison Notes

Bogosort ( )O n ( !)O n n unbounded (1)O No n/a Yes

Page 24: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 24 of 278

Bubble ( )O n — 2

( )O n (1)O Yes Exchanging Yes Short-circuit variant

Cocktail ( )O n — 2

( )O n (1)O Yes Exchanging Yes

Comb ( log )O n n ( log )O n n ( log )O n n (1)O No Exchanging Yes

Heapsort ( log )O n n ( log )O n n ( log )O n n (1)O No Selection Yes

Insertion ( )O n 2

( )O n 2

( )O n (1)O Yes Insertion Yes Can be performed on serialized input

Merge ( log )O n n ( log )O n n ( log )O n n ( )O n Yes Merging Yes Can be implemented for external sorting

Permutation ( )O n ( !)O n n ( !)O n n (1)O No Selection No

Pigeonhole ( 2 )k

O n ( 2 )k

O n ( 2 )k

O n (2 )k

O Yes Tabulation No Assumes = 2k

n

Quicksort ( log )O n n ( log )O n n 2( )O n (log )O n No Partitioning Yes

Selection 2( )O n

2( )O n

2( )O n (1)O No Selection Yes

Shell’s — — 1.5( )O n (1)O No Insertion Yes

Is-Sorted – random-access container ‘IS-SORTED’ determines if a collection is sorted. The first algorithm is implemented for a random-access collection.

function IS-SORTED( A ) returns a Boolean

for i ← 1 to length{A} – 1 do

if A[i] < A[i – 1] then

return false

return true

Is-Sorted – forward iterators function IS-SORTED( beg, end ) returns a Boolean

if beg = end

then return true previous ← beg

current ← successor{beg}

while current ≠ end do

if value{current} < value{previous}

then return false previous ← current

current ← successor {current}

return true

Page 25: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 25 of 278

Bogo Sort ‘BOGO-SORT’ randomly shuffles the elements of the collection until satisfies ‘IS-SORTED’.

procedure BOGO-SORT( A )

while not IS-SORTED( A )

RANDOMIZE( A )

Is this the worst sorting algorithm of all time? Perhaps its not even an algorithm but is more likely an heuristic, and a bad one.

References

http://en.wikipedia.org/wiki/Bogosort

Bubble Sort

‘Bubble-Sort’ is the worst sorting algorithm in common use. It is both move intensive and comparison intensive. However, its lack-lustre

performance has never severely deterred novices from using it.

… in fact, the Bubblesort has hardly anything to recommend it except its catchy name. (Wirth, 1976)

Algorithm

1. repeat for as many times as there are elements less one;

2. for each element pair;

3. compare KBiB with KBi+1B, interchanging RBiB with RBi+1B if the keys are out of order.

Where K represents keys and R represents records.

Implementation – random-access container (brute force) This first implementation is a brute-force translation of the algorithm for a random-access container.

procedure BUBBLE-SORT( A )

for pass ← 1 to length{A} – 1 do

for idxPair ← 1 to length{A} – 1 do

if A[idxPair] < A[idxPair – 1]

then exchange A[idxPair] ↔ A[idxPair – 1]

This can easily be improved upon by recognizing that each pass places a minimum of one element into its sorted place, (i.e. the sorted portion

grows from the end to the beginning). Any further testing of those elements is redundant.

Implementation – random-access container (standard) This second implementation removes those extra comparisons.

Page 26: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 26 of 278

procedure BUBBLE-SORT( A )

for pass ← 1 to length{A} – 1 do

for idxPair ← 1 to length{A} – pass do

if A[idxPair] < A[idxPair – 1]

then exchange A[idxPair] ↔ A[idxPair – 1]

The next refinement removes the calculation within the inner loop’s termination condition.

procedure BUBBLE-SORT( A )

for idxEndOfPass ← length{A} – 1 downto 1 do

for idxPair ← 1 to idxEndOfPass do

if A[idxPair] < A[idxPair – 1]

then exchange A[idxPair] ↔ A[idxPair – 1]

Implementation – bi-directional iterators Now we can write the equivalent implementation for bi-directional iterators.

procedure BUBBLE-SORT( beg, end )

firstPair ← successor{beg}

while firstPair end do

previous ← beg

current ← firstPair

while current end do

if value{current} < value{previous}

then exchange value{current} ↔ value{previous}

previous ← current

current ← successor{current}

end ← predecessor{end}

Bubble sort’s performance on sorted and partially sorted lists can be dramatically improved by tracking the occurrences of exchanges in each pass.

If no exchanges occur, the then the list is already sorted and the algorithm could immediately be terminated.

This algorithm performs particularly poorly on reversed lists, since every element pair is swapped on every pass. The tests simply add overhead.

Implementation – random-access container (short-circuit) procedure BUBBLE-SORT( A )

for idxEndOfPass ← length{A} – 1 downto 1 do

hasSwapped ← false

for idxPair ← 1 to idxEndOfPass do

if A[idxPair] < A[idxPair – 1]

then exchange A[idxPair] ↔ A[idxPair – 1]

hasSwapped ← true

if hasSwapped is false

then return

Page 27: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 27 of 278

Implementation – bi-directional iterators (short-circuit) The bi-directional iterator implementation:

procedure BUBBLE-SORT( beg, end )

firstPair ← successor{beg}

hasSwapped ← true

while firstPair end and hasSwapped do

hasSwapped ← false

previous ← beg

current ← firstPair

while current end do

if value{current} < value{previous}

then exchange value{current} ↔ value{previous}

hasSwapped ← true

previous ← current

current ← successor{current}

end ← predecessor{end}

References

http://en.wikipedia.org/wiki/Bubble_sort

Cocktail-shaker The cocktail-shaker sort is a variation of the bubble sort. The difference is that the bubble passes are performed in both directions as opposed to

bubble sort’s forward only passes.

Algorithm

1. while the unsorted range is greater than 1

2. for each element pair in the unsorted range;

3. compare KBiB with KBi+1B, interchanging RBiB with RBi+1B if the keys are out of order.

4. for each element pair in the unsorted range;

5. compare KBiB with KBi-1B, interchanging R BiB with RBi-1B if the keys are out of order.

6. reduce the unsorted range by 1 at each end

Where K represents keys and R represents records.

Implementation – random-access container (naïve) The first implementation is the direct translation of the algorithm.

Page 28: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 28 of 278

procedure COCKTAIL-SHAKER-SORT( A )

idxFirstUnsorted ← 0

idxLastUnsorted ← length{A} – 1

idxCurrent ← idxFirstUnsorted

while idxFirstUnsorted < idxLastUnsorted do

while idxCurrent < idxLastUnsorted do

if A[idxCurrent + 1] < A[idxCurrent]

then exchange A[idxCurrent + 1] ↔ A[idxCurrent]

idxCurrent ← idxCurrent + 1

idxLastUnsorted ← idxLastUnsorted – 1

while idxCurrent > idxFirstUnsorted do

if A[idxCurrent – 1] > A[idxCurrent]

then exchange A[idxCurrent – 1] ↔ A[idxCurrent]

idxCurrent ← idxCurrent – 1

idxFirstUnsorted ← idxFirstUnsorted + 1

In the case of an empty container, idxLastUnsorted is initialized to –1. However, if the index type is unsigned, numeric underflow occurs causing

to be initialized to std::numeric_limits<unsigned>::max() – a clearly invalid location. The algorithm must either be implemented using a signed

range type or be rewritten.

Implementation – random-access container (safe) procedure COCKTAIL-SHAKER-SORT( A )

idxFirstUnsorted ← 0

idxEnd ← length{A}

idxCurrent ← idxFirstUnsorted

while idxFirstUnsorted < idxEnd do

idxCurrent ← idxCurrent + 1

while idxCurrent < idxEnd do

if A[idxCurrent – 1] < A[idxCurrent]

then exchange A[idxCurrent – 1] ↔ A[idxCurrent]

idxCurrent ← idxCurrent + 1

idxEnd ← idxEnd – 1

idxCurrent ← idxCurrent – 1

while idxCurrent > idxFirstUnsorted do

if A[idxCurrent – 1] > A[idxCurrent]

then exchange A[idxCurrent – 1] ↔ A[idxCurrent]

idxCurrent ← idxCurrent – 1

idxFirstUnsorted ← idxFirstUnsorted + 1

Page 29: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 29 of 278

Implementation – bi-directional iterators procedure COCKTAIL-SHAKER-SORT( beg, end )

if beg = end then

return

previous ← beg

next ← successor{beg}

while next ≠ end do

while next ≠ end do

if value{previous} > value{next}

then exchange value{previous} ↔ value{next}

previous ← successor{previous}

next ← successor{next}

previous ← predecessor{previous}

next ← predecessor{next}

end ← predecessor{end}

if previous = beg

then return

repeat

previous ← predecessor{previous}

next ← predecessor{next}

if value{previous} > value{next}

then exchange value{previous} ↔ value{next}

until previous = beg

previous ← successor{previous}

next ← successor{next}

beg ← successor{beg}

References

http://en.wikipedia.org/wiki/Cocktail_sort

Comb Sort The comb sort is a variation of the HTUbubble sortUTH first published in Byte by Steven Lacy and Richard Box (Stephen Lacy and Richard Box, "A Fast,

Easy Sort", Byte, April 1991, p.315). Comb sort can also be thought of as a variation of Shell’s sort. It uses Shell’s idea of enhancing the

performance of the insert by inserting in steps or shells of a magnitude greater than 1. The comb sort uses bubble passes that compare non-

contiguous elements; thereby moving an element closer to its correct resting spot in fewer moves. Lacy and Box investigated the gap reduction

factor and found that shrink factor of 1.3 was ideal and that further performance gains occur in the gap values of 9 and 10 are exchanged for 11.

Page 30: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 30 of 278

Implementation – random-access container

procedure COMB-SORT( A )

gap ← length{A}

loop

if gap = 9 or gap = 10

then gap ← 11

else if gap < 1

then gap ← 1

swapped ← false

for i ← 0 to length{A} – gap – 1 do

j ← i + gap

if A[ i ] > A[ j ]

then exchange A[ i ] ↔ A[ j ]

swapped ← true

if gap = 1 and not swapped

then return

Note that the container can not be empty if the range type is unsigned.

References

http://en.wikipedia.org/wiki/Comb_sort

Count Sort See ‘Pigeonhole Sort’

Heap Sort ‘Heap sort’ is what you would call a ‘good performer’. Its sorts in ( log )O n n time – always!

The heap sort works by first arranging all of the elements of the container into a heap. A heap is binary tree in which the key values of the child

nodes are both less than the key value of the parent node.

A binary tree structure can be implemented in a 1-base array by employing the relationship of left-child-index is double the parent-index, right-

child-index is one greater than the left-child-index.

Once formed, the heap can be converted to a sorted list by swapping the element at the top of the heap with the last element in the heap; shrinking

the heap by one; then fixing the heap by recursively adjusting the top element until the heap has been restored.

1.3gap gap

Page 31: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 31 of 278

Implementation – random-access container (iterative) procedure HEAP-SORT( A )

heapSize ← length{A}

for parentNode ← heapSize div 2 downto 1 do

HEAPIFY( A, parentNode, heapSize )

for idx ← length{A} – 1 downto 1 do

exchange A[0] ↔ A[idx]

heapSize ← heapSize – 1

HEAPIFY( A, 1, heapSize )

procedure HEAPIFY( A, parentNode, heapSize )

loop

leftNode ← parentNode × 2

if leftNode > heapSize

then return if A[leftNode – 1] > A[parentNode – 1]

then largestNode ← leftNode

else largestNode ← parentNode

rightNode ← leftNode + 1

if rightNode ≤ heapSize and A[rightNode – 1] > A[largestNode – 1]

then largestNode ← rightNode

if largestNode ≠ parentNode

then exchange A[largestNode – 1] ↔ A[parentNode – 1]

parentNode ← largestNode

else return

Limited Heap Sort

In web search engines we often want only the k best results presented in a sorted list, where there may have been as many as n > k results. There is

no point in storing all n results, sorting them all then throwing away the n – k excess elements.

A limited heap sort, sorts the k highest elements of a set of n elements. We first feed k elements into the heap and build an ascending order heap

(the lowest value at the top of the heap). For the remaining elements we compare the new element to the top element of the heap replacing the top

element if the new element is larger – then heapify. Once all elements have been tested and inserted into the heap, we complete the heap sort

producing an ascending order list.

We can then reverse the list to produce a descending order list if necessary.

References

http://en.wikipedia.org/wiki/Heapsort

Page 32: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 32 of 278

Insertion Sort Insertion sort is an attempt to minimize the number of comparisons performed during a sort by shifting through sorted space when positioning an

element.

Algorithm 1. for each element EBiB in the array;

2. we assume that the preceding elements EB1B, …, EBi-1B have already been sorted;

3. we insert EBiB, into its proper place among the sorted records

where E represents keys

Implementation – random-access container Here is an implementation for a random-access container.

procedure INSERTION-SORT( A )

for idxFirstUnsorted ← 1 to length{A} – 1 do

idx ← idxFirstUnsorted

while idx > 0 and A[idx] < A[idx – 1] do

exchange A[idx] ↔ A[idx – 1]

idx ← idx – 1

Notes For empty arrays the first line of the algorithm results in an index being created that has a negative value (i.e. –1). If your implementing

language’s index type is an unsigned type this statement would produce numeric underflow.

Implementation – bi-directional iterators procedure INSERTION-SORT( beg, end )

if beg = end then

return

firstUnsorted ← beg

loop

firstUnsorted ← successor{firstUnsorted}

if firstUnsorted = end

then return

element ← firstUnsorted

previous ← predecessor{element}

while element ≠ beg and value{element} < value{previous} do

exchange value{element} ↔ value{previous}

element ← predecessor{element}

previous ← predecessor{previous}

This implementation does present a challenge when converted to code since many modern implementations of iterators have ‘safe’ debug versions

that test to see that the iterators stay within bounds. This algorithm violates that rule on the final line.

Page 33: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 33 of 278

Implementation – bi-directional iterators (safe) procedure INSERTION-SORT( beg, end )

if beg = end then

return

firstUnsorted ← beg

loop

firstUnsorted ← successor{firstUnsorted}

if firstUnsorted = end

then return

element ← firstUnsorted

previous ← element

while element ≠ beg do

previous ← predecessor{previous}

if value{element} ≥ value{previous}

then break exchange value{element} ↔ value{previous}

element ← predecessor{element}

This is adjustment produces some ugly code, but languages that permit assignment inside loop conditions can significantly clean up the

implementation:

Implementation – bi-directional iterators (elegant) procedure INSERTION-SORT( beg, end )

if beg = end then

return

firstUnsorted ← beg

loop

firstUnsorted ← successor{firstUnsorted}

if firstUnsorted = end

then return

previous ← element ← firstUnsorted

while element ≠ beg and value{element} < value{ previous ← predecessor{previous} } do

exchange value{element} ↔ value{previous}

element ← predecessor{element}

References

http://en.wikipedia.org/wiki/Insertion_sort

Merge Sort Merge sort is the original divide and conquer sort. It executes in O(n logB2B n) time whether sorting vectors, linked lists or files. The vector and file

implementations require additional storage of equal size to process the merge; the linked list version does not.

Page 34: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 34 of 278

Merge sort can be processed using recursion or iteration. The recursive version is not easily adapted to files while the iterative version adapts

easily to all data types and stores.

Algorithm

1. If the list size is 0 or 1, return.

2. Split the list into 2 equal parts.

3. Merge-Sort each half-list separately.

4. Merge the two sorted lists into a single list.

Implementation – Random-access Container Using Recursion

procedure MERGE-SORT( A, beg, end )

if end – beg > 1 then

split ← (beg + end) div 2

MERGE-SORT( A, beg, split )

MERGE-SORT( A, split, end )

MERGE( A, beg, split, end )

procedure MERGE( A, low, high, end)

create a output array D the same size of A

lowWalker ← low

highWalker ← high

destWalker ← low

while lowWalker < high and highWalker < end

if A[lowWalker] < A[highWalker]

then D[destWalker] ← A[lowWalker]

lowWalker ← lowWalker + 1

else D[destWalker] ← A[highWalker]

highWalker ← highWalker + 1

destWalker ← destWalker + 1

if lowWalker < high

then D[destWalker .. end – 1] ← A[lowWalker .. high – 1]

else D[destWalker .. end – 1] ← A[highWalker .. end – 1]

A ← D

Optimization – Pre-allocate the copy vector.

The biggest performance hit in the preceding implementation is the constant reallocations of the hold array – D. The simple solution is to have the

driver function create D and then pass it to the merge function.

Page 35: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 35 of 278

Implementation – Random-access Container Using Iteration

procedure MERGE-SORT( A )

sublistSize ← 1

while sublistSize < length{A} do

low ← 0

while low < length{A} do

high ← low + sublistSize

end ← high + sublistSize

if end > length{A}

then end ← length{A}

if high > length{A}

then high ← length{A}

if high ≠ length{A}

then MERGE( A, low, high, end )

low ← low + 2 sublistSize

sublistSize ← 2 sublistSize

Optimization – Random-access Container Using Iteration with Short-circuiting

Another optimization is the recognition that there is unnecessary copying during the merge when the lower half of the array empties first. The data

remaining in the top half of the array is already in the correct position, so copying those elements to the temporary store would be pointless.

hgfedcba §§§§lkji

Array A

Array D

highlow end

lowWalker highWalker

destWalker

ponm

hgfedcba §§§§lkji

Array A

Array D

highlow

end

lowWalker highWalker

destWalker

ponm

ponm

copy

lowWalker high destWalker end

Array A´

Page 36: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 36 of 278

procedure MERGE( A, low, high, end )

lowWalker ← low

highWalker ← high

destWalker ← low

while lowWalker < high and highWalker < end

if A[lowWalker] < A[highWalker]

then D[destWalker] ← A[lowWalker]

lowWalker ← lowWalker + 1

else D[destWalker] ← A[highWalker]

highWalker ← highWalker + 1

destWalker ← destWalker + 1

if lowWalker < high

then A[destWalker .. end – 1] ← A[lowWalker .. high – 1]

A[low .. destWalker – 1] ← D[low .. destWalker – 1]

Note that the block copy in line 12 must be a high to low copy since the ranges could overlap.

Implementation – Linked List with Iteration procedure MERGE-SORT( L )

sublistSize ← 1

while sublistSize < length{L} do

empty the holdList

while L is not empty do

split a list of no greater size than sublistSize from the front of L

split another list of no greater size than sublistSize from the front of L

Merge the two lists

splice the merged list onto the end of the holdList

exchange holdList ↔ L

sublistSize ← sublistSize 2

References

http://en.wikipedia.org/wiki/Merge_sort

Ordersort The ordersort algorithm sorts by determining the order in which elements should be arranged, then arranging them into that order. The

arrangement order is determined by locating the immediate predecessors and successors of each element.

References

C/C++ Users Journal (September 2005)

Page 37: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 37 of 278

Permutation Sort Permutation sort is a trial-and-error type sort. Try every possible arrangement of the elements – at least one of them is sorted.

Pigeonhole Sort Pigeonhole sort is a special case sort capable of sorting in linear time. Counting sort requires that the input array being sorted only contains

ordinal values in a known and finite range. For our discussion we will assume that values are in the range [0..k]. The idea is to count the number

of instances of each value in the input array. Then for each value detected in the input array, write back to the array the correct number of

instances detected. However, we write the input values back in their sorted order.

One pass of the input array is required to accumulate the frequency table of values, and one more pass is required to write the values back to the

array. This simple approach destroys the original elements and is therefore of little practical use. The sort can be modified to copy the original

values from one array to another.

Implementation – random-access container procedure PEGEONHOLE-SORT( A, k )

for i ← 0 to k do

C[ i ] ← 0

for i ← 0 to length{A} – 1 do

C[ A[ i ] ] ← C[ A[ i ] ] + 1

j ← 0

for i ← 0 to length{C} – 1 do

while C[ i ] > 0 do

C[ i ] ← C[ i ] – 1

A[ j ] ← i

j ← j + 1

References

http://en.wikipedia.org/wiki/Pigeonhole_sort

Quick sort ‘Quick-sort’, as named by its originator – Sir Anthony (C.A.R.) Hoare (Oxford University) is one of the smallest, fastest and most elegant

algorithms known.

The basic idea is to perform ‘swapping passes’ instead of search and swap. During each ‘swapping-pass’, low-value elements in the top half of the

list are swapped for high-value elements in the bottom half of the list. Eventually the swapping pass would come to a middle point such that all of

the values in the bottom half of the list will have a value lower than every value in the top half of the list. The reverse – that all of the values in the

top half of the list will have a value higher than every value in the bottom half of the list – is necessarily true. The two sub-lists could then be

individually ‘quick-sorted’.

Page 38: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 38 of 278

Algorithm

1. If the size of the list is 0 or 1, return.

2. Pick any element from the list. Call this value ‘pivot.’ ( Av )

3. Partition the list into two distinct groups, such that the lower list only contains elements that are less than or equal to the pivot value and the upper list only

contains elements that are greater than or equal to the pivot value.

vxvAxL | and vxvAxU |

4. Return the sequential join of Quicksort(L) and Quicksort(U)

Implementation – random-access container (low is pivot)

The pivot value will be partitioned into the top half of the range.

procedure QUICK-SORT( A, low, high )

if low < high

then pivot ← PARTITION( A, low, high )

QUICK-SORT( A, low, pivot )

QUICK-SORT( A, pivot + 1, high )

The following partition algorithm returns the high index of the lower partition.

function PARTITION( A, low, high ) returns integer

pivotValue ← A[ low ]

low ← low – 1

high ← high + 1

loop

repeat low ← low + 1

until A[low] ≥ pivotValue

repeat high ← high – 1

while A[high] ≤ pivotValue

if low < high

then exchange A[low] ↔ A[high]

else return high

Implementation – random-access container (random pivot)

Choosing the first element as a pivot is as good as any other for a randomly scrambled list. However, it is terrible for a sorted or reverse-sorted

list, causing each swapping pass to correctly place only one element – making the sort perform in O(nP

2P) time. A randomly chosen pivot often

achieves the needed variation to avoid degenerate partitioning.

function PARTITION( A, low, high ) returns integer

pivot ← random value in the range [ low, high ]

pivotValue ← A[pivot]

low ← low – 1

Page 39: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 39 of 278

Implementation – random-access container (middle pivot)

An alternative to the random pivot is the mid-point pivot.

function PARTITION( A, low, high ) returns integer

pivot ← (low + high) div 2

pivotValue ← A[pivot]

low ← low – 1

Implementation – random-access container (Hoare)

Hoare’s implementation is an optimization of the mid-point pivot that merges the partition function and the recursive function. Most significantly

it does not move the pivot value to the beginning of the sub-list.

procedure QUICK-SORT( A, low, high )

lo ← low

hi ← high

pivotValue ← A[ (low + high) div 2 ]

while lo ≤ hi do

while A[ lo ] < pivotValue do

lo ← lo + 1

while A[ hi ] > pivotValue do

hi ← hi – 1

if lo ≤ hi

then exchange A[ lo ] ↔ A[ hi ]

lo ← lo + 1

hi ← hi – 1

if low < hi

then QUICK-SORT( A, low, hi )

if lo < high

then QUICK-SORT( A, lo, high )

Reference

http://en.wikipedia.org/wiki/Quicksort

Selection Sort Selection sort is an attempt to minimize the number of swaps performed during a sort by employing a search through the unsorted space to locate

the exact element to be placed in the sorted portion of the list.

Algorithm

1. for each element EBiB in the array;

2. we assume that the preceding elements EB1B, …, EBi-1B have already been sorted;

3. we search EBiB, …, EBnB for the element with the lowest value { EBkB };

4. exchange elements EBiB and EBkB.

Page 40: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 40 of 278

Notes: E represents keys.

assume the array to be 1-based.

Implementation – random-access container (lowest)

First, I’ll present a direct translation of the algorithm.

procedure SELECTION-SORT( A )

for idxFirstUnsorted ← 0 to length{A} – 2 do

idxOfLowest ← idxFirstUnsorted

for idx ← idxFirstUnsorted + 1 to length{A} – 1 do

if A[idxOfLowest] > A[idx] then

idxOfLowest idx

if idxOfLowest idxFirstUnsorted then

exchange A[idxOfLowest] ↔ A[idxFirstUnsorted]

Notes: For empty arrays the first line of the algorithm results in an index being created that has a negative value (i.e. –1). If your

implementing language’s index type is an unsigned type this statement would produce number underflow.

Implementation – random-access container (highest)

Often a more efficient implementation can be achieved by searching for the highest value and sorting from the high indices and working down.

The following implements such an approach

procedure SELECTION-SORT(A)

for idxLastUnsorted ← length{A} – 1 downto 1 do

idxOfHighest ← idxLastUnsorted

for idx ← idxLastUnsorted – 1 downto 0 do

if A[idxOfHighest] < A[idx] then

idxOfHighest idx

if idxOfHighest idxLastUnsorted then

exchange A[idxOfHighest] ↔ A[idxLastUnsorted]

Notes: For empty arrays the first line of the algorithm results in an index being created that has a negative value (i.e. –1). If your

implementing language’s index type is an unsigned type this statement would produce number underflow.

Implementation – forward iterators

The final implementation mimics the previous but replaces array references with pointers or iterators.

Page 41: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Algorithms Section 3

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 41 of 278

procedure SELECTION-SORT( beg, end )

while beg end do

lowest ← beg

current ← beg

loop current ← successor{current}

if current = end then

break

if value{lowest} > value{current} then

lowest ← current

if lowest beg then

exchange value{lowest} ↔ value{beg}

beg ← successor{beg}

Reference

http://en.wikipedia.org/wiki/Selection_sort

Shell’s Sort Insertion sort has good performance on sorted list, but poor performance on reversed lists. This fact inspired D. L. Shell to create this variation on

insertion sort. Insertion sort’s major problem is that when an element is found to be a great distance from its proper spot, it is only moved there

one position at a time. This fault produces a costly O(n P

2P) behaviour.

Shell’s sort eliminates this problem by segmenting the data set and performing the insertion on intermittent portions of the array.

Implementation – random-access container

procedure SHELL’S-SORT( A )

stepSize ← length{A} div 2

while stepSize > 0 do

for idxLastInSegment ← stepSize to length{A} – 1 do

idxCurrent ← idxLastInSegment

while idxCurrent ≥ stepSize and A[idxCurrent] < A[idxCurrent – stepSize] do

exchange A[idxCurrent] ↔ A[[idxCurrent – stepSize]

idxCurrent ← idxCurrent – stepSize

stepSize ← stepSize div 2

Reference

http://en.wikipedia.org/wiki/Shell_sort

Page 42: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Applications Section 4

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 42 of 278

Applications

UML Tools

Argo UML Argo UML is an open-source multiplatform UML modeling tool.

URL http://argouml.tigris.org

Installation – Windows

Unzip the argoUML archive to your ‘Program Files’ folder.

With Java installed, run ‘argouml.jar’.

Drag a short-cut of this file to your desktop to create a launch icon.

Installation – Linux

Login as ‘root’.

Download ArgoUML-0.22.tar.gz to the /usr/local directory.

Extract the argoUML archive to that directory.

Open a console and type the command:

ln –s /usr/local/ArgoUML-0.22/argouml.sh /usr/local/bin/argo

This creates a link in the search path of all users that will load Argo UML from its installation directory.

Page 43: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Audio Programming Section 5

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 43 of 278

Audio Programming

Storage Requirements To store a 10 second recording we must know three pieces of information: the sample rate, the sample quality and the number of channels.

The sample rate is the number of samples taken per second, usually measured in Hz.

The sample quality is the number of bits per sample. 8, 12, 16 and 24 bits per sample are typical levels of sample quality. 8 bits per sample gives

256 levels of loudness, 16 bits gives 65536 levels and 24 bits give over 16 million levels of loudness. 8 bits is considered low-quality, 24 bits is

studio mixing board quality and is unnecessary for a typical game.

The number of channels is determined by the number of microphones used to record the sound. One channel for monaural sound (mono), two

channels for stereo, etc.

10 seconds of stereo sound, recorded at a sample rate of 44.1 KHz using a 16-bit sampler requires:

44100 × 2 channels × 2 bytes (16-bits) × 10 seconds = 1,764,000 bytes.

Compact Disc

Sampling Rate Compact Audio Discs (CDs) are sampled at a rate of 44.1 KHz or 44,100 samples per second. Why 44.1 KHz? Before the CD, digital audio was

stored on magnetic video tape. Video tape plays at 60 frames per second showing 245 scan lines. Each scan line has 3 samples (one for each

primary colour). 60 × 245 × 3 = 44100.

Audio Engines Audio Engines serve the same purpose as graphics engines, but in the audio realm. They abstract audio hardware and provide an interface to high-

level audio functions.

Several popular audio engines used in the gaming industry are:

BASS – www.un4seen.com/music/ (Comprehensive support for Windows and many programming languages. Free for freeware.)

FMOD – www.fmod.org (Very comprehensive library that supports virtually every platform – PS2, XBox, GameCube, Windows, etc. Free for

freeware)

MikMod – www.mikmod.org (Cross-platform tracked music library. Freeware)

ModPlug – www.modplug.com (Quick and easy tracked music, Free)

Page 44: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Audio Programming Section 5

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 44 of 278

Miles Sound System – www.ragametools.com (The ultimate system. Used in over 3000 commercial games. Expensive!)

FMOD 4+ A favourite Audio API is FMOD. A favourite since it is multi-platform and free if used in non-commercial software. It can be found at

www.fmod.org.

Installation

fmodex.dll Place the DLL in the same directory as your application or into the

\Windows\system32 directory.

fmod.h

fmod.hpp

fmod_code.h

fmod_dsp.h

fmod_error.h

fmod_output.h

Include a path to these files in your projects include settings

fmodex_vc.lib

fmodexp_vc.lib

Include a path to these files in your projects libraries settings

Coding

This section documents the minimum requirements to setup streaming audio on a Windows XP system.

Preprocessor

Prepare your source code with the following pre-processor directives:

#include <fmod.hpp>

#include <fmod_errors.h>

#pragma comment (lib, "fmodex_vc.lib")

Initialization

Using FMOD’s new object-oriented C++ framework, we first create a system object.

FMOD::System* system;

FMOD_RESULT result = FMOD::System_Create( &system );

if( result != FMOD_OK ) {

cerr << "FMOD Error! (" << result << ") " << FMOD_ErrorString(result) << endl;

return 1;

}

The version number can be acquired from this object. The top 16 bits contains the major version number, the next 8 bits the sub version and the

bottom 8 bits, the minor version number.

unsigned version;

Page 45: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Audio Programming Section 5

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 45 of 278

system->getVersion( &version );

cout << "Version = " << (version >> 16) << '.' << (version & 0xffff >> 8) << '.' << (version & 0xff) << endl;

We can now setup a system that support 256 virtual voices with the command:

system->init( 256, FMOD_INIT_NORMAL, 0 );

Any customizations like the number of software mixers, hardware channels or speaker mode (like 5.1 surround-sound) must be set prior to calling

init().

Loading

Unlike FMOD3, FMOD4 uses a single interface model for all sounds properties whether streamed or not. By default, sounds are fully loaded and

decompressed into memory when opened.

FMOD::Sound* sound;

system->createSound("music.mp3", FMOD_DEFAULT, 0, &sound );

This may cause delays with long files since the entire sound will be decompressed into 16-bit PCM format. If you desire real-time decompression

you can open the file as a stream.

FMOD::Sound* sound;

system->createSound("music.mp3", FMOD_CREATESTREAM, 0, &sound );

Or the short-form of the command.

FMOD::Sound* sound;

system->createStream("music.mp3", FMOD_DEFAULT, 0, &sound );

Playing the sound or stream.

Whether the sound property is fully loaded or a disk-based stream, the same command will play the sound.

FMOD::Channel* channel;

system->playSound( FMOD_CHANNEL_FREE, sound, false, &channel );

Playing will immediately commence on the first available channel. Changing the ‘false’ parameter to ‘true’ will start the sound in a paused state.

Maintainence

Many of the platforms have specific requirements that must be met on a per frame basis. Call FMOD::System::update() each frame to services

these needs. While there is no harm in calling update more than once per frame, it is unnecessary and a drain on the CPU.

system->update();

Cleanup

Release the stream.

sound->release()

Close and release the sound system before process termination.

system->close();

Page 46: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Audio Programming Section 5

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 46 of 278

system->release();

Close out the sound system before process termination.

FMOD 3.74 A favourite Audio API is FMOD. A favourite since it is multi-platform and free if used in non-commercial software. It can be found at

www.fmod.org.

Installation

fmod.dll

fmod64.dll

Place the appropriate DLL in the same directory as your application or into the

\Windows\system32 directory.

fmod.h

fmod_error.h

fmoddyn.h

wincompat.h

Include a path to these files in your projects include settings

fmod64vc.lib

fmodvc.lib

Include a path to these files in your projects libraries settings

Coding

This section documents the minimum requirements to setup streaming audio on a Windows XP system.

Preprocessor

Prepare your source code with the following pre-processor directives:

#include <fmod.h>

#include <fmod_errors.h>

#pragma comment (lib, "fmodvc.lib")

Initialization

Initialization starts with checking the FMOD version, followed by selecting the sound driver type. On Windows 9x and W2k systems (including

Windows/XP) the DirectSound driver is best. On Windows/NT systems, use the Windows multi-media driver.

if( FSOUND_GetVersion() < FMOD_VERSION ) {

wostringstream woss;

woss << L"You are using the wrong DLL version! You should be using FMOD " <<

setprecision(2) << fixed << FMOD_VERSION;

::MessageBox( NULL, woss.str().c_str(), L"FMOD Error", MB_ICONSTOP );

return 1;

}

Gets the version number and checks that it is at least equal to the version compiled against.

if( !FSOUND_SetOutput( FSOUND_OUTPUT_DSOUND ) ) {

Page 47: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Audio Programming Section 5

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 47 of 278

::MessageBox( NULL, L"DirectSound not available.", L"FMOD Error", MB_ICONSTOP );

return 1;

}

Sets the system to use DirectSound as the underlying hardware interface. DirectSound is the most efficient interface for a Win9x or W2K system.

if( !FSOUND_Init( 44100, 32, 0 ) )

{

FSOUND_Close();

return 1;

}

Configuration

The audio buffer size can be set to better control the memory usage and performance. The buffer size is described by the duration in milliseconds.

The actual buffer size is calculated by multiplying the time by the sample rate by the number of channels.

FSOUND_Stream_SetBufferSize(1000);

Opening a stream.

Declare a variable appropriate to the stream.

FSOUND_STREAM* audioStream;

Then open the stream.

audioStream_ = FSOUND_Stream_Open( "Ramble On.mp3", FSOUND_NORMAL, 0, 0 );

if( audioStream_ == NULL )

{

// failure, don’t need to close the stream, do need to close the sound system.

}

The file type can be any of the following PCM based or compressed file formats; wave format (.wav), MP2 and MP3 format, OggVorbis (.ogg) or

RAW (.raw).

The last two parameters represent an offset into the file. The 3rd parameter being the starting position in the file to seek to before playing. The 4th

parameter is the length of the file and is only necessary if the 3rd parameter is non-zero or the file in being read from a memory buffer (not the

example here).

If you wish the audio stream to automatically repeat, pass FSOUND_LOOP_NORMAL as the second parameter of FSOUND_Stream_Open().

Playing the stream. FSOUND_Stream_Play( 0, audioStream );

Plays the audio stream indicated by audioStream on channel 0. The first parameter – the channel number – must not exceed the maximum

number of channels specified by FSOUND_Init().

Stopping the stream.

The stream can be stopped by either close the stream or sound system or by stopping just that particular stream.

Page 48: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Audio Programming Section 5

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 48 of 278

FSOUND_Stream_Stop( audioStream );

Cleanup

Close and release the stream.

FSOUND_Stream_Close( audioStream );

This stops the stream if it is currently playing.

Close out the sound system before process termination.

FSOUND_Close();

Music

Sound Frequencies

C0 16.35 C#0/Db0 17.32 D0 18.35

D#0/Eb0 19.45 E0 20.60 F0 21.83

F#0/Gb0 23.12 G0 24.50 G#0/Ab0 25.96

A0 27.50 A#0/Bb0 29.14 B0 30.87

C1 32.70 C#1/Db1 34.65 D1 36.71

D#1/Eb1 38.89 E1 41.20 F1 43.65

F#1/Gb1 46.25 G1 49.00 G#1/Ab1 51.91

A1 55.00 A#1/Bb1 58.27 B1 61.74

C2 65.41 C#2/Db2 69.30 D2 73.42

D#2/Eb2 77.78 E2 82.41 F2 87.31

F#2/Gb2 92.50 G2 98.00 G#2/Ab2 103.83

A2 110.00 A#2/Bb2 116.54 B2 123.47

C3 130.81 C#3/Db3 138.59 D3 146.83

D#3/Eb3 155.56 E3 164.81 F3 174.61

F#3/Gb3 185.00 G3 196.00 G#3/Ab3 207.65

A3 220.00 A#3/Bb3 233.08 B3 246.94

C4 261.63 C#4/Db4 277.18 D4 293.66

D#4/Eb4 311.13 E4 329.63 F4 349.23

F#4/Gb4 369.99 G4 392.00 G#4/Ab4 415.30

A4 440.00 A#4/Bb4 466.16 B4 493.88

C5 523.25 C#5/Db5 554.37 D5 587.33

D#5/Eb5 622.25 E5 659.26 F5 698.46

F#5/Gb5 739.99 G5 783.99 G#5/Ab5 830.61

A5 880.00 A#5/Bb5 932.33 B5 987.77

Page 49: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Audio Programming Section 5

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 49 of 278

C6 1046.50 C#6/Db6 1108.73 D6 1174.66

D#6/Eb6 1244.51 E6 1318.51 F6 1396.91

F#6/Gb6 1479.98 G6 1567.98 G#6/Ab6 1661.22

A6 1760.00 A#6/Bb6 1864.66 B6 1975.53

C7 2093.00 C#7/Db7 2217.46 D7 2349.32

D#7/Eb7 2489.02 E7 2637.02 F7 2793.83

F#7/Gb7 2959.96 G7 3135.96 G#7/Ab7 3322.44

A7 3520.00 A#7/Bb7 3729.31 B7 3951.07

C8 4186.01 C#8/Db8 4434.92 D8 4698.64

D#8/Eb8 4978.03

Page 50: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 50 of 278

C++ Programming

Assertions An assertion is a statement that can be tested to be either true or false. Programmers use assertions to verify the correctness of code either during

run-time or compile time. Assertions are best used to test for logic errors.

Run-time Assertions A run-time assertion is a statement that tests for a specific condition that would indicate a logic-error has occurred during the execution of the

program. The important idea is that we are looking for conditions that should never occur during the execution of the program under any

circumstance. This is in contrast to a run-time error that while undesirable, may be unavoidable.

Assertions are often used to test or enforce function preconditions, postconditions and invariants.

Example:

/** @fn size_t strlen( const char* string )

@return Number of characters in string.

@param string [in] Address of a zero terminated string.

@note precondition: string is non-null. */

size_t strlen( const char* string ) {

assert( string != 0 ); // confirm precondition

const char* start = string;

while( *string )

++string;

return string - start;

}

Compile-time Assertions A compile-time assertion is a statement that test for a specific condition that would indicate that the code could not be compiled safely as the

platform cannot meet the expectations of the code.

Compile-time assertions are not implemented as a standard element of either the C or C++ languages. The boost library provides a decent

implementation. If boost is not an option, a compile-time (or static assertion) can easily be implemented with the following macro:

#define STATIC_ASSERT(e) 1/(e)

A false condition produces a constant divide-by-zero expression that will be trapped and reported by the compiler.

Example (boost):

#include <boost/static_assert.hpp>

Page 51: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 51 of 278

int main() {

BOOST_STATIC_ASSERT( sizeof(unsigned) == 4 );

unsigned u = 0xA000FFFF;

The preceding code is dependent on unsigned variables being 32 bits and not 16 bits. The static assert will issue a compiler error if type unsigned

is not 4 bytes.

Best Practices We will define a best practice as the best possible way of doing a thing. Best practices may encompass coding style and idiom, documentation,

coding guidelines and in the extreme development processes such as Unified Process or Extreme Programming.

BOOST Use boost!

Boost provides free peer-reviewed portable C++ source libraries.

We emphasize libraries that work well with the C++ Standard Library. Boost libraries are intended to be widely useful, and usable across a broad spectrum of applications. The Boost license encourages both commercial and non-commercial use.

We aim to establish "existing practice" and provide reference implementations so that Boost libraries are suitable for eventual standardization. Ten Boost libraries are already included in the C++ Standards Committee's Library Technical Report (TR1) as a step toward becoming part of a future C++ Standard. More Boost libraries are proposed for the upcoming TR2.

– www.boost.org (December, 2005)

Boost originated with the C++ Standards Committee Library Working Group and has since opened participation to the C++ community at large.

All code accepted into boost is reviewed by the C++ community including those from the Standards Committee.

As of 2005, ten boost libraries had been accepted into TR1. You should not hesitate to use these libraries wherever they may help. These libraries

are:

Library Boost TR1

Tuple <boost/tuple.hpp> <tuple>

Smart Pointers <boost/weak_ptr.hpp>

<boost/shared_ptr.hpp>

<memory>

Array <boost/array.hpp> <array>

Unordered Associative Containers N/A <unordered_map>

<unordered_set>

Function object wrappers <boost/function.hpp> <functional>

Template function mem_fn <boost/mem_fn.hpp> <functional>

Page 52: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 52 of 278

Reference wrapper <boost/ref.hpp> <functional>

Class template result_of <boost/result_of.hpp> <functional>

Function object binders <boost/bind.hpp> <functional>

Type Traits <boost/type_traits.hpp> <type_traits>

Random <boost/random.hpp> <random>

Regular expressions <boost/regex.hpp> <regex>

Utilities <boost/utility.hpp> <utility>

any

Use boost::any when: [K06]

You need to store values of heterogeneous types in containers.

Storage for unknown types is required.

Types are being passed through layers that need not know anything about the types.

Use boost::any_cast<T> when a casting failure is an error. This cast will throw the exception boost::bad_any_cast.

Use boost::any_cast<T *> when a casting failure is not an error. This cast will return a null pointer.

When storing pointers in boost::any store a smart pointer.

variant

Use boost::variant when: [K06]

You need to store values of heterogeneous types in containers.

Storage for known types is required.

Types are being passed through layers that need not know anything about the types.

Casts

boost::lexical_cast<T>

When to use lexical_cast [K06]:

For conversions from string types to numeric types.

For conversions from numeric types to string types.

For all lexical conversions that are supported by your user-defined types.

Page 53: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 53 of 278

boost::numeric_cast<T>

When to use numeric_cast [K06]:

When assigning/comparing unsigned and signed types.

When assigning/comparing integral types of different types.

When assigning a function return type to a numeric variable, to protect against future changes to the function.

boost::polymorphic_cast<T>

When to use polymorphic_cast and dynamic_cast [K06] :

When a polymorphic cast failure is expected, use dynamic_cast<T*>. It makes it clear the failure is not an error.

When a polymorphic cast must succeed, use polymorphic_cast<T*>. It makes it clear the conversion failure is an error.

When performing polymorphic casts to reference types, use dynamic_cast<T&>.

boost::polymorphic_downcast<T>

When to use polymorphic_downcast [K06]:

If you are downcasting and need the speed of static_cast in release builds, use polymorphic_downcast; at least you’ll get assertions

for errors during testing.

If it’s not possible to cover all possible casts in testing, do not use polymorphic_downcast.

Smart Pointers

boost::intrusive_ptr

Use intrusive_ptr when [K06]:

You need to treat this as a smart pointer.

There is existing code that uses or provides an intrusive reference count.

It is imperative that the size of the smart pointer equals the size of a raw pointer.

boost::scoped_ptr

Use scoped_ptr when [K06]:

A pointer is used in a scope where an exception may be thrown.

There are several control paths in a function.

The lifetime of a dynamically allocated object can be limited to a specific scope.

Page 54: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 54 of 278

Exception safety is important (always!)

boost::shared_ptr

Use shared_ptr when [K06]:

When there are multiple clients of an object, but no explicit owner.

When storing pointers in standard library containers.

When passing objects to and from libraries without (other) expressed ownership.

When managing resources that need special cleanup [with the help of custom deleters].

boost::weak_ptr

Use weak_ptr to [K06]:

Break cyclic dependencies

Use a shared resource without sharing ownership

Avoid dangling pointers

tuple

Use boost tuple whenever you would need to create a structure to combine data values, but do not need to create constructors or methods for the

structure.

Utility

BOOST_STATIC_ASSERT

Use BOOST_STATIC_ASSERT when [K06]:

A condition can be expressed at compile time.

Requirements on types are expressible at compile time.

You need to assert a relationship of two or more constant integral values.

boost::addressof

Use addressof when you must retrieve the actual address of an object, regardless of the semantics for operator&. [K06]

boost::checked_delete

Use checked_delete when you need to ensure that types are complete when calling delete. [K06]

Page 55: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 55 of 278

boost::enable_if

[K06]

Use boost::enable_if when:

You need to add or remove a function to the overload set depending on some condition.

You need to add or remove a class template specialization from the set of specializations depending on some condition.

boost::noncopyable

Use boost::noncopyable when [K06]:

Copying and copy assignment of types is not allowed.

Prohibition of copying and assignment should be as explicit as possible.

Coding Style

Prefer compile- and link-time errors to run-time errors.

[SA04] § 14

Use const proactively.

[SA04] § 15

Avoid macros.

[SA04] § 16

Avoid magic numbers.

[SA04] § 17

Declare variables as locally as possible.

[SA04] § 18

Always initialize variables.

[SA04] § 19

Avoid long functions. Avoid deep nesting.

[SA04] § 20

Page 56: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 56 of 278

Avoid initialization dependencies across compilation units.

[SA04] § 21

Minimize definitional dependencies. Avoid cyclic dependencies.

[SA04] § 22

Make header files self-sufficient.

[SA04] § 23

Always write internal #include guards. Never write external #include guards.

[SA04] § 24

Compiler / Environment

Compile cleanly at high warning levels.

[SA04] § 1

For Visual C++ use warning level 4.

Use an automated build system.

[SA04] § 2

Use either Visual Studio or make.

Use a version control system.

[SA04] § 3

Use one of:

Visual Source Safe

CVS

Perforce

Design

Give one entity one cohesive responsibility.

[SA04] § 5

Page 57: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 57 of 278

Correctness, simplicity, and clarity come first.

[SA04] § 6

Know when and how to code for scalability.

[SA04] § 7

Don’t optimize prematurely.

[SA04] § 8

Don’t pessimize prematurely.

[SA04] § 9

Minimize global and shared data.

[SA04] § 10

Hide information.

[SA04] § 11

Know when and how to code for concurrency.

[SA04] § 12

Ensure resources are owned by objects. Use explicit RAII and smart pointers.

[SA04] § 13

Functions and Operators

Take parameters appropriately by value, (smart) pointer, or reference.

[SA04] § 25

Preserve natural semantics for overloaded operators.

[SA04] § 26

Prefer canonical forms of arithmetic and assignment operators.

[SA04] § 27

Prefer the canonical form of ++ and --. Prefer calling the prefix forms.

[SA04] § 28

Page 58: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 58 of 278

Consider overloading to avoid implicit type conversions.

[SA04] § 29

Avoid overloading &&, ||, or , (comma).

[SA04] § 30

Don’t write code that depends on the order of evaluation of function arguments.

[SA04] § 31

Use boost::operators to implement operators where possible.

Boost::operators provides a complete set of comparison operators, arithmetic operators and operators for iterators. It will help you provide a

complete set of operators that behave consistently with established practices while minimizing the amount of code that you write.

Avoid using multiple inheritance when including multiple operator base-classes by employing their derived-from argument in the template

argument list.

Example:

class CMyClass :

boost::less_than_comparable< CMyClass, boost::equality_comparable<CMyClass> >

{

};

Class Design and Inheritance

Be clear what kind of class you’re writing.

[SA04] § 32

value class

base class

traits class

policy class

exception class

ancillary class

Prefer minimal classes to monolithic classes.

[SA04] § 33

Page 59: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 59 of 278

Prefer composition to inheritance.

[SA04] § 34

Avoid inheriting from classes that were not designed to be base classes.

[SA04] § 35

Avoid inheriting from concrete base classes.

To add behaviour, prefer to add non-member functions instead of member functions.

To add state, prefer composition instead of inheritance.

Prefer providing abstract interfaces.

[SA04] § 36

Prefer to follow the Dependency Inversion Principle (DIP) that states:

High-level modules should not depend upon low-level modules. Rather, both should depend upon abstractions.

Abstractions should not depend upon details. Rather, details should depend upon abstractions.

Public inheritance is substitutability. Inherit, not to reuse, but to be reused.

[SA04] § 37

Object reuse is about reusing existing functions on new objects. Not new objects reusing base object code.

Practice safe overriding.

[SA04] § 38

An override can ask for less and provide more, but it must never require more or promise less because that would break the contract that was

promised to calling code.

You should only define an override that can fail if the base function can fail.

When overriding, never change default arguments.

Beware of inadvertently hiding overloads in the base class.

Consider making virtual functions non-public, and public functions nonvirtual.

[SA04] § 39

Avoid providing implicit conversions.

[SA04] § 40

By default, write explicit on single-argument constructors.

Page 60: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 60 of 278

Use named functions that offer conversions instead of conversion operators.

Make data members private, except in behaviorless aggregates (C-style structs).

[SA04] § 41

Don’t give away your internals.

[SA04] § 42

Avoid returning handles to internal data managed by your class.

Pimpl judiciously.

[SA04] § 43

Declare a ‘forward declaration’ just before a smart pointer to the implementation.

Prefer writing nonmember nonfriend functions.

[SA04] § 44

Always provide new and delete together.

[SA04] § 45

If you provide any class-specific new, provide all of the standard forms (plain, in-place, and nothrow).

[SA04] § 46

Prefer the Barton-Nackman Trick to resolve cyclic dependencies in class inheritance chains.

http://en.wikipedia.org/wiki/Barton-Nackman

The Barton-Nackman Trick. [K-06]

Multiple Inheritance

1. Make all base classes of abstract classes virtual.

2. Try to give your abstract base classes default constructors.

3. If your class requires outside initialization, create a protected init() function that takes the appropriate parameters and does the initialization.

Note: Do only class specific initialization in the init() function; do not call any base class init() functions.

4. Create single-inheritance constructors that initialize all base classes and all local data members (i.e. those init() functions).

5. Create multiple-inheritance constructors that initialize only the data members of the class. The canonical form of such a constructor just calls

the init() function for the class itself.

[CUJ2006:Multiple Inheritance Considered Useful]

Page 61: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 61 of 278

Construction, Destruction and Copying

Define and initialize member variables in the same order.

[SA04] § 47

Prefer initialization to assignment in constructors.

[SA04] § 48

Avoid calling virtual functions in constructors and destructors.

[SA04] § 49

Make base class destructors public and virtual, or protected and nonvirtual.

[SA04] § 50

Base classes, not concrete classes!

Destructors, deallocation, and swap never fail.

[SA04] § 51

Copy and destroy consistently.

[SA04] § 52

Write copy constructor, copy assignment and destructor together.

Explicitly enable or disable copying.

[SA04] § 53

Avoid slicing. Consider Clone instead of copying in base classes.

[SA04] § 54

Disable copying and implement a Clone function.

Prefer the canonical form of assignment.

[SA04] § 55

Don’t return const T&, this prevents T objects from being put into standard containers.

Whenever it makes sense, provide a no-fail swap (and provide it correctly).

[SA04] § 56

Page 62: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 62 of 278

Namespaces and Modules

Keep a type and its nonmember function interface in the same namespace.

[SA04] § 57

Keep types and functions in separate namespaces unless they’re specifically intended to work together.

[SA04] § 58

Don’t write namespace usings in a header file or before an #include.

[SA04] § 59

Avoid allocating and deallocating memory in different modules.

[SA04] § 60

Don’t define entities with linkage in a header file.

[SA04] § 61

Don’t allow exceptions to propagate across module boundaries.

[SA04] § 62

Use sufficiently portable types in a module’s interface.

[SA04] § 63

Templates and Genericity

Blend static and dynamic polymorphism judiciously.

[SA04] § 64

Dynamic polymorphism is best at:

Uniform manipulation based on superset/subset relationships.

Static type checking.

Dynamic binding and separate compilation.

Binary interfacing.

Static polymorphism is best at:

Uniform manipulation based on syntactic and semantic interface.

Page 63: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 63 of 278

Static type checking.

Static binding (prevents separate compilation).

Efficiency.

Customize intentionally and explicitly.

[SA04] § 65

To avoid providing points of customization unintentionally:

Put any helper functions your template uses internally into their own nested namespace, and call them with explicit qualification to disable ADL

Avoid depending on dependent names: … In short, when referring to any member of a dependent base class, always explicitly qualify with the base

class name or with this->, which you can think of just as a magical way of forcing all compilers to do what you actually want.

Don’t specialize function templates.

[SA04] § 66

You can’t specialize function templates partially, only totally.

Function template specializations never participate in overloading.

Don’t write unintentionally nongeneric code.

[SA04] § 67

Use != instead of < to compare iterators.

Prefer iterator to indexed access.

Use empty() instead of size() == 0.

Use the highest class in the hierarchy that offers the functionality you need.

Write const-correct code.

Prefer partial template specialization to complete template specialization.

Prefer member specialization to complete template specialization.

Error Handling and Exceptions

Assert liberally to document internal assumptions and invariants.

[SA04] § 68

Page 64: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 64 of 278

Establish a rational error handling policy and follow it strictly.

[SA04] § 69

Ensure that your policy includes:

Identification: What conditions are errors.

Severity: How important or urgent each error is.

Detection: Which code is responsible for detecting the error.

Propagation: What mechanisms are used to report and propagate error notification within each module.

Handling: What code is responsible for doing something about the error.

Reporting: How the error will be logged or users notified.

Distinguish between errors and non-errors.

[SA04] § 70

An error is any failure that prevents a function from succeeding.

Violation of, or failure to achieve, a precondition.

Failure to achieve a postcondition.

Failure to reestablish an invariant.

Design and write error-safe code.

[SA04] § 71

Ensure that errors always leave your program in a valid state.

Prefer to guarantee that the final state is either the original state or the promised state.

Prefer to use exceptions to report errors.

[SA04] § 72

Exceptions can’t be silently ignored.

Exceptions propagate automatically.

Exception handling removes error handling and recovery from the main line of control flow.

Exception handling is better than the alternatives for reporting errors from constructors and operators.

Throw by value, catch by reference.

[SA04] § 73

Page 65: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 65 of 278

Report, handle, and translate errors appropriately.

[SA04] § 74

Report errors at the point they are detected and identified as errors.

Handle or translate errors at the nearest level that can do it correctly.

Avoid exception specifications.

[SA04] § 75

STL Containers

Use vector by default. Otherwise, choose an appropriate container.

[SA04] § 76

Write for correctness, simplicity, and clarity first.

Write for efficiency only when and where necessary.

Prefer to write transactional, strongly error-safe code where reasonably possible, and don’t use invalid objects.

Use vector and string instead of arrays.

[SA04] § 77

Use vector (and string::c_str) to exchange data with non-C++ APIs.

[SA04] § 78

Store only values and smart pointers in containers.

[SA04] § 79

Prefer push_back to other ways of expanding a sequence.

[SA04] § 80

Prefer range operations to single-element operations.

[SA04] § 81

Use the accepted idioms to really shrink capacity and really erase elements.

[SA04] § 82

Page 66: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 66 of 278

STL Algorithms

Use a checked STL implementation.

[SA04] § 83

Prefer algorithm calls to handwritten loops.

[SA04] § 84

Consider trying the Boost Lambda library, which automates the task of writing function objects.

Use the right STL search algorithm.

[SA04] § 85

For unsorted ranges: find/find_if and count/count_if.

For sorted ranges: binary_search, lower_bound, upper_bound, and equal_range.

Use the right STL sort algorithm.

[SA04] § 86

Make predicates pure functions.

[SA04] § 87

Don’t allow predicates to hold or access state that affects the result of their operator(), including both member and global state.

STL applies predicates in no particular order and copies them liberally.

Prefer function objects over functions as algorithm and comparer arguments.

[SA04] § 88

Comparers for associative containers must be function objects.

Function objects are adaptable and, counterintuitively, they typically produce faster code than functions.

Write function objects correctly.

[SA04] § 89

Design function objects to be values that are cheap to copy. Where possible, make them adaptable by inheriting from unary_function or

binary_function.

Page 67: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 67 of 278

Type Safety

Avoid type switching; prefer polymorphism.

[SA04] § 90

Rely on types, not on representations.

[SA04] § 91

Avoid using reinterpret_cast.

[SA04] § 92

Avoid using static_cast on pointers.

[SA04] § 93

Avoid casting away const.

[SA04] § 94

Don’t use C-style casts.

[SA04] § 95

Don’t memcpy or memcmp non-PODs.

[SA04] § 96

Don’t use unions to reinterpret representation.

[SA04] § 97

Don’t use varargs (ellipsis).

[SA04] § 98

Don’t use invalid objects. Don’t use unsafe functions.

[SA04] § 99

Don’t treat arrays polymorphically.

[SA04] § 100

Page 68: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 68 of 278

OpenMP

When to use OpenMP

[MSDN20-10]

Target platform is multicore or multiprocessor.

Application is cross-platform.

Parallelizable loops. Loops without loop-carried dependencies.

Last-minute optimizations needed.

String Manipulation

Use boost::regex to perform validation, searching and replacing.

[K-06]

Bit Manipulation

Largest unsigned number template <typename T> T maxUnsigned() { return ~T(0); }

Setting a bit

unsigned var = GetSomeValue();

unsigned int bitToSet = 3;

unsigned int mask = 1 << bitToSet;

var |= mask;

SetSomeValue( var );

Clearing a bit

unsigned var = GetSomeValue();

unsigned int bitToSet = 3;

unsigned int mask = ~(1 << bitToSet);

var &= mask;

SetSomeValue( var );

Page 69: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 69 of 278

Multiplying, Dividing and Remainders

In the past the operations multiply, divide and modulus were relatively expensive compared to the bit-manipulating operations bit-shift-left, bit-

shift-right and bitwise-and.

Multiply by a power of two.

The left-shift operation performs a binary point shift the same way that multiplying by 10 performs a decimal place shift.

int i = 21;

i *= 8;

is equivalent to:

i <<= 3;

Works with true binary and 2’s complement values.

Divide by a power of two.

The right-shift operation performs a binary point shift the same way that dividing by 10 performs a decimal place shift. However, the remainder

part is thrown out.

int i = 384;

i /= 16;

is equivalent to:

i >>= 4;

Works with true binary and 2’s complement values.

Modulus by a power of two.

The bit-wise-and operation can be employed to compute remainders, where the divisor is a power of two. Essentially, we are looking for the

left-over bits that would have been shifted out by a right-shift which is all the bits below the power-of-two bit.

int i = 384;

i %= 16;

is equivalent to:

i &= 0x0f;

Works with true binary and 2’s complement values.

Today, most compilers will look for, and exploit these techniques where is there is a performance improvement to be had.

Page 70: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 70 of 278

XOR swap

A pair of POD variables can be swapped in place without the need for an additional hold variable using a series of XORs.

#include <iostream>

using namespace std;

int main() {

int x = 42, y = 24;

cout << x << "," << y << endl;

x ^= y;

y ^= x;

x ^= y;

cout << x << "," << y << endl;

return 0;

}

Boost All things boost can be found at www.boost.org.

Auto Test (1.36.0)

The simplest example of boost’s auto unit test is:

#define BOOST_TEST_MODULE MyTests

#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_CASE( first_test_case )

{

BOOST_CHECK( 1 == 1 ); // pass

BOOST_CHECK( 2 == 1 ); // fail

}

Installation of boost 1.61.0 for Visual Studio 2015

1. From the Boost website (http://www.boost.org/users/download/), download boost_1_61_0.7z

2. Extract the contents of these two files into a temporary folder (e.g. c:\tmp). You should see the folder: boost_1_61_0

3. Open a command shell in the boost_1_61_0 folder.

Page 71: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 71 of 278

4. Enter the command, bootstrap

in the command shell.

5. Enter the command, b2 -–build-type=complete msvc install address-model=32

in the command shell.

5.1. Exception: Sometimes this setting doesn’t build the full set of libraries (usually it’s the static libraries that are missing). You can force

which of the two link models to use by adding the parameter ‘runtime-link=static’ or ‘runtime-link=shared’.

6. Wait a long time… Visual C++’s command line compiler and linker are invoked to compile all of the non-template code into linker-ready

libraries that can be directly included into your projects. This could take ½ hour or longer to complete depending on the speed of your processor

and disk system. A folder will be created in the root of your C: drive called Boost that will contain the INCLUDE and LIB directories.

7. Rename the folder from C:\Boost\lib to C:\Boost\x86.

8. [Optional 64-bit install]

8.1. Open a command shell in the boost_1_61_0 folder.

8.2. Enter the command, b2 -–build-type=complete msvc install address-model=64

in the command shell Configure Visual C++.

8.3. Rename the folder from C:\Boost\lib to C:\Boost\x64.

9. Create a folder called C:\Boost\lib. Move the folder(s) x86 (and x64) into the C:\Boost\lib folder.

10. Load Visual Studio 2015

11. Open any C++ project.

12. Open the property manager (select View → Property Manager)

13. Expand the property manager tree until you see the ‘Microsoft.Cpp.Win32.user’ item in the property manger’s tree view.

Page 72: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 72 of 278

14. Right-click the ‘Microsoft.Cpp.Win32.user’ file and select ‘Properties’.

15. Select, “VC++ Directories” from the “Property Page”.

Page 73: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 73 of 278

16. Edit the ‘Include Directories’ list to contain an entry for the boost include directory. Note that the convention is to write include directives with

the boost folder prefixed to the included header file.

#include <boost/shared_ptr.hpp>

Therefore add a path to the boost-1_61_0 directory. (e.g. c:\Boost\x86\include\boost-1_61_0).

17. Do the same for the “Library Directories”. This time, enter the exact directory containing the library files. (e.g. c:\Boost\x86\lib).

18. [Optional 64-bit library install]

18.1. Open an “x64” project and the repeat steps 14 through 19, substituting 64 for 32 where appropriate.

Page 74: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 74 of 278

Installation of boost 1.45.0 for Visual Studio 2008

19. From the Boost website (http://www.boost.org/users/download/), download

19.1. boost-jam-3.1.18-1-ntx86.zip

19.2. boost_1_45_0.7z

20. Extract the contents of these two files into a temporary folder (e.g. c:\tmp). You should see two folders:

20.1. boost_1_45_0

20.2. boost-jam-3.1.18-1-ntx86

21. Copy the file bjam.exe from the folder boost-jam-3.1.18-1.ntx86 to the folder boost_1_45_0

22. You may delete the folder boost-jam-3.1.18-1.ntx86 if you wish.

23. Open a command shell in the boost_1_45_0 folder.

24. Enter the command "C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat" (be certain to include the quotation marks) or

"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat" on 64-bit Windows. This will

make the C++ 9.0 command line compiler available to the command shell.

25. Enter the command, bjam --toolset=msvc-9.0 -–build-type=complete install

in the command shell.

26. Wait a long time… Visual C++’s command line compiler and linker are invoked to compile all of the non-template code into linker-ready

libraries that can be directly included into your projects. This could take ½ hour or longer to complete depending on the speed of your processor

and disk system. A folder will be created in the root of your C: drive called Boost that will contain the INCLUDE and LIB directories.

27. Rename the folder from C:\Boost to C:\x86.

28. [Optional 64-bit install]

28.1. Open a command shell in the boost_1_45 folder.

28.2. Enter the command"C:\Program Files\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" x64 (be certain to include the quotation marks)

"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" x64 on 64-bit Windows.

This will make the 64-bit compiler tools available to the command shell.

28.3. Enter the command, bjam --toolset=msvc-9.0 -–build-type=complete address-model=64 install

in the command shell Configure Visual C++.

Page 75: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 75 of 278

28.4. Rename the folder from C:\Boost to C:\x64.

29. Create a folder called C:\Boost. Move the folder(s) x86 (and x64) into the C:\Boost folder.

30. Load Visual Studio 2008

31. Open the options dialog (select Tools → Options…)

32. Select the “Projects” folder, then the “VC++ Directories” subfolder.

33. Select, “Includes files” from the “Show directories for:” combo box.

34. Insert a new entry into the directories list.

Page 76: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 76 of 278

35. Enter the location of the boost include files. Note that the convention is to write include directives with the boost folder prefixed to the included

header file.

#include <boost/shared_ptr.hpp>

Therefore add a path to the boost-1_45 directory. (e.g. c:\Boost\x86\include\boost-1_45).

36. Do the same for the “Library files” option of “Show directories for:”. This time, enter the exact directory containing the library files.

(e.g. c:\Boost\x86\lib)

37. [Optional 64-bit library install]

37.1. Select, “x64” option of “Platform” and repeat the previous steps for the include directory

c:\Boost\x64\include\boost-1_45 and the library directory c:\Boost\x64\lib.

Page 77: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 77 of 278

38. Click, , “OK”.

Classes

Access Specifiers (Garth Santor, December 2006)

Access specifiers are keywords that indicate the visibility of members of a class, structure or union. The specifiers are public, protected and

private. Specifiers are applied to class, structure or union members or to inherited classes or structures1. A fourth, special-case specifier –

friend – can be applied to classes, functions or operators.

The access specifiers grant visibility to class members using the following rules.

Class members are private by default, structure and union members are public by default.

Class inheritance is private by default.

Class member is private

Class member is protected

Class member is public

Member is visible from outside class No No Yes Member is visible from inside same class Yes Yes Yes

Member is visible from inside derived class No Yes Yes Member is visible from friend class or function Yes Yes Yes

Class

inheritance is private

Class inheritance is protected

Class inheritance is public

Public base-class members are visible from outside class No No Yes

Public base-class members are visible from inside class Yes Yes Yes

Public base-class members are visible from derived class No Yes Yes

Public base-class members are visible from friend class or function Yes Yes Yes

Protected base-class members are visible from outside class No No No

Protected base-class members are visible from inside class Yes Yes Yes

Protected base-class members are visible from derived class No Yes Yes

Protected base-class members are visible from friend class or function Yes Yes Yes

Private base-class members are visible from outside class No No No

Private base-class members are visible from inside class No No No

Private base-class members are visible from derived class No No No

1 unions cannot be used as base classes.

Page 78: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 78 of 278

Private base-class members are visible from friend class or function No No No

Example class A {

private: int a;

protected: int b;

public: int c;

};

void foo() {

A obj;

obj.a = 42; // error

obj.b = 42; // error

obj.c = 42; // ok

}

class B : public A {

public: void bar() {

a = 42; // error

b = 42; // ok

c = 42; // ok

};

Slurping and Binding Slurping and binding are terms used to describe how temporary objects are handled in operator assignment.

In the statement:

std::string V = a + b;

An object is created as a result of the addition operator. This temporary object is slurped into the variable V, and is then disposed of to complete

the statement. The important thing to note is that an object may be created and destroyed within this statement. Optimizing compilers will attempt

to eliminate this allocation/deallocation by assigning the result of the operator directly to the object that will hold the result.

In the statement:

std::string& R = a + b;

An object is created as a result of the addition operator. This temporary object is bound to the reference R, but is not disposed of at the end of the

statement. Instead the temporary object acquires the life-span of the binding reference R. Binding eliminates the extra allocation/deallocation that

occurs with slurping.

So why slurp? Binding is limited by the scope of the reference which is local. Slurping can be performed on variables that transcend local scope.

Page 79: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 79 of 278

Coding Devices and Idioms

I/O Stream Pattern

The feof() function and .eof() method is a source of confusion in programmers new to C and C++. Languages like BASIC and Pascal report

end-of-file as true once the last character of the input stream has been read. C’s feof() function and C++’s .eof() method don’t report true

until an attempt has been made to read past the end of the input stream. This allows C/C++ programs to append input to the stream after the last

character has been processed. This difference has lead novice C/C++ programmers to write the following code, thinking it to be correct.

#include <iostream>

using namespace std;

int main() {

while( !cin.eof() ) {

double x;

cin >> x;

cout << x << endl;

}

return 0;

}

This leads to the last number read being output twice.

The eof() test must follow the input operation.

#include <iostream>

using namespace std;

int main() {

for( ;; ) {

double x;

cin >> x;

if( cin.eof() )

break;

cout << x << endl;

}

return 0;

}

This implementation is risky. It has the potential of becoming an infinite loop if the input stream contains a value that is not convertible to a

double; a word, for example. An infinite loop could also result from the remote case that input stream becomes utterly and unrecoverably corrupt.

The first case is detected with a call to the istream::fail() method and the second case by a call to the istream::bad() method.

Example:

#include <iostream>

Page 80: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 80 of 278

using namespace std;

int main() {

for( ;; ) {

double x;

cin >> x;

if( cin.eof() || cin.fail() || cin.bad() )

break;

cout << x << endl;

}

return 0;

}

Of course this code is somewhat cumbersome. The three negative tests can be replaced with one positive test: istream::good().

#include <iostream>

using namespace std;

int main() {

for( ;; ) {

double x;

cin >> x;

if( !cin.good() )

break;

cout << x << endl;

}

return 0;

}

The C++ architects want us to constantly test if our input statements succeeded, so they provided a convenient casting operator that returns the

result of istream::good() whenever the istream object finds itself sitting in the position of an ‘if’ or loop conditional. Our code can be more

compactly written as:

#include <iostream>

using namespace std;

int main() {

for( ;; ) {

double x;

if( cin >> x )

cout << x << endl;

else

break;

}

return 0;

}

Page 81: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 81 of 278

The code is now in a pattern in which input successes continue reads, input failures terminate reads. We can refactor this code into a simple while

loop.

#include <iostream>

using namespace std;

int main() {

double x;

while( cin >> x )

cout << x << endl;

return 0;

}

To discover whether the loop terminated on end-of-file or a failure, check the stream status after loop termination.

#include <iostream>

using namespace std;

int main() {

double x;

while( cin >> x )

cout << x << endl;

if( !cin.eof() ) {

cout << "Failure reading input" << endl;

return 1;

}

return 0;

}

Page 82: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 82 of 278

Curiously Recurring Template Pattern (CRTP) It solves the problem of cyclic dependency by using templates. A base-class that needs to know about derived class accepts the base class

definition as a template argument.

class Derived : public Base<Derived> {

};

It is heavily used in boost’s operator library.

The Barton-Nackman Trick uses the CRTP.

References

http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern

Delegates Delegates are not intrinsic to standard C++, but a close facsimile can be manufactured using function pointers and member function pointers.

class A {

public:

A();

virtual ~A();

virtual void dfunc( int i );

static void sfunc( int i );

};

Function pointers are used to delegate for static member function.

void (*spDelegate)( int ); // declare

spDelegate = A::sfunc; // bind

(*spDelegate)( 42 ); // call

spDelegate( 42 ); // call

Member function pointers are used to delegate for normal member functions.

void (A::*pDelegate)(int); // declare

pDelegate = &A::dfunc; // bind

A a;

(a.*pDelegate)(42); // call

A* p = &a;

(p->*pDelegate)(42); // call from pointer

The function pointer looks good – it completely hides the name of the bound function and has a simple and elegant syntax. The member function

pointer also hides the name of the bound member function, but in the first form (.*) does not hide the object that the method is called upon. The

second form does manage to hide the host object, but has a complex syntax and requires two variables – an object pointer and a member function

pointer – for its implementation.

Page 83: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 83 of 278

Hiding the implementation details

Obviously, we need to encapsulate these variables in a class. The class interface should be able to handle default construction, binding and

invoking as separate commands.

+bind(in pObj, in pmf)

+bind(in psf)

+operator ()(in x : float) : int

delegate

Such a class should allow us to write the following code:

class A

{

public:

A();

virtual ~A();

virtual int vfunc( float x ) { return (int)x; }

static int sfunc( float x ) { return (int)x*2; }

};

int main()

{

A a;

delegate d( &a, A::vfunc );

delegate dd;

dd.bind( &a, A::vfunc );

assert( 42 == d( 42.0 ) );

assert( 42 == dd( 42.0 ) );

d.bind( A::sfunc );

assert( 84 == d( 42.0 ) );

return 0;

}

A naïve implementation could be:

class delegate

{

public:

typedef int (A::*PMF)(float x);

delegate() : p_( 0 ), pmf_( 0 ), psf_( 0 ) { }

delegate( A* p, PMF pmf ) : p_( p ), pmf_( pmf ) { }

void bind( A* p, PMF pmf )

{

p_ = p;

pmf_ = pmf;

}

Page 84: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 84 of 278

int operator () ( float x )

{

assert( p_ && pmf_ );

return (p_->*pmf_)(x);

}

private:

A* p_;

PMF pmf_;

};

This implementation has several problems, the first being that is doesn’t handle static member functions. This can be easily fixed:

class delegate

{

public:

typedef int (*PSF)(float x);

typedef int (A::*PMF)(float x);

delegate() : p_( 0 ), pmf_( 0 ), psf_( 0 ) { }

delegate( A* p, PMF pmf ) : p_( p ), pmf_( pmf ), psf_( 0 ) { }

delegate( PSF psf ) : p_( 0 ), pmf_( 0 ), psf_( psf ) { }

void bind( A* p, PMF pmf )

{

p_ = p;

pmf_ = pmf;

psf_ = 0;

}

void bind( PSF psf )

{

p_ = 0;

pmf_ = 0;

psf_ = psf;

}

int operator () ( float x )

{

assert( (p_ && pmf_) || psf_ );

if( p_ )

return (p_->*pmf_)(x);

return (*psf_)( x );

}

private:

A* p_;

PMF pmf_;

PSF psf_;

};

Clearly we can see that there are two distinct implementations of the delegate – one for member functions and one for static functions. The bridge

pattern can solve this problem.

Page 85: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 85 of 278

+bind(in pObj, in pmf)

+bind(in psf)

+operator()(in x : float) : int

delegate

+operator()(in x : float) : int

«interface»

delegate_impl

1

-impl

1

+ctor(in psf)

+operator()(in x : float) : int

-psf

delegate_static_impl

+ctor(in pObj, in pmf)

+operator()(in x : float) : int

-pObj

-pmf

delegate_dynamic_impl

+somefunc(in x : float) : int

SomeClass 1

-pObj

1

The delegate implementation classes can be nested inside the delegate class itself:

class delegate

{

struct delegate_impl {

virtual ~delegate_impl() { }

virtual int operator () ( float x ) = 0;

};

struct delegate_dynamic_impl : public delegate_impl {

typedef int (A::*PMF)(float x);

delegate_dynamic_impl( A* p, PMF pmf ) : p_( p ), pmf_( pmf ) { }

int operator () (float x) { return (p_->*pmf_)(x); }

A* p_;

PMF pmf_;

};

struct delegate_static_impl : public delegate_impl {

typedef int (*PSF)(float x);

delegate_static_impl( PSF psf ) : psf_( psf ) { }

int operator () (float x) { return (*psf_)(x); }

PSF psf_;

};

public:

delegate() : pdelegate_( 0 ) { }

delegate( A* p, delegate_dynamic_impl::PMF pmf ) :

pdelegate_( new delegate_dynamic_impl( p, pmf ) ) { }

delegate( delegate_static_impl::PSF psf ) :

pdelegate_( new delegate_static_impl( psf ) ) { }

void bind( A* p, delegate_dynamic_impl::PMF pmf ) {

pdelegate_.reset( new delegate_dynamic_impl( p, pmf ) );

}

void bind( delegate_static_impl::PSF psf ) {

pdelegate_.reset( new delegate_static_impl( psf ) );

Page 86: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 86 of 278

}

int operator () ( float x ) {

assert( pdelegate_.get() ) ;

return (*pdelegate_)(x);

}

private:

std::auto_ptr<delegate_impl> pdelegate_;

};

Now we need to parameterize this class so that it will work with more than just objects of class A.

+bind(in pObj, in pmf)

+bind(in psf)

+operator()(in x : float) : int

delegate

RET, PAR

*

-impl

1

+ctor(in psf)

+operator()(in x : PAR) : RET

-psf

delegate_static_impl

RET, PAR

+ctor(in pObj : CLASS*, in pmf)

+operator()(in x : PAR) : RET

-pObj : CLASS*

-pmf

delegate_dynamic_impl

RET, PAR, CLASS

+somefunc(in x : float) : int

SomeClas 1

-pObj

1

+operator()(in x : PAR) : RET

-nRef

delegate_imp

RET, PAR

SomeClass delegate impl

«bind»(int,float,SomeClass)

Another use feature is to implement reference counting for delegate_impl. This reduces the amount of dynamic memory allocations when

delegates are copied.

Additional operators that can be implemented in delegate:

operator =

operator ==

operator !=

operator !

operator bool

Page 87: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 87 of 278

Multicasting

Delegates are often implemented so as to support the invocation of multiple functions/methods. This delegate type we’ll call a multicast delegate.

The only new operation required by a multicast delegate is an add operation (often implemented with operator +=). Many functions need to

be reengineered to accommodate the multicast delegate implementation. Fortunately, the bridge pattern can accommodate the multicast delegate

as a specialization of delegate_impl.

+bind(in pObj, in pmf)

+bind(in psf)

+operator()(in x : float) : int

+add(in psf)

+add(in pObj, in pmf)

+add(in delegate)

delegate

RET, PAR

*

-impl

1

+ctor(in psf)

+operator()(in x : PAR) : RET

-psf

delegate_static_impl

RET, PAR

+ctor(in pObj : CLASS*, in pmf)

+operator()(in x : PAR) : RET

-pObj : CLASS*

-pmf

delegate_dynamic_impl

RET, PAR, CLASS

+somefunc(in x : float) : int

SomeClass 1

-pObj

1

+operator()(in x : PAR) : RET

+isMulticast() : bool

-nRef

delegate_imp

RET, PAR

SomeClass delegate impl

«bind»(int,float,SomeClass,,,)

+operator()(in x : PAR) : RET

multicast_delegate

RET, PAR

*

*

The greatest short-coming of this design is that templates don’t handle variable-length argument lists with any grace. Therefore, you’ll need to

implement a version for void functions, one for single-parameter functions, another for two-parameter functions, and so on.

Duff’s Device Duff’s device was invented by Lucasfilm developer Tom Duff who in 1983 need to solve a performance issue involving a loop. The bottleneck

occurred due to the overhead of the looping mechanism in the language.

The standard way of unrolling a loop takes original code like:

for( int i = 0; i < numOut; ++i )

*pDest++ = *pSource++;

Page 88: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 88 of 278

And replaces it with:

int numLoops = numOut / 8;

for( int i = 0; i < numLoops; ++i ) {

*pDest++ = *pSrc++;

*pDest++ = *pSrc++;

*pDest++ = *pSrc++;

*pDest++ = *pSrc++;

*pDest++ = *pSrc++;

*pDest++ = *pSrc++;

*pDest++ = *pSrc++;

*pDest++ = *pSrc++;

}

for( int i = 0; i < numOut % 8; ++i ) {

*pDest++ = *pSrc++;

}

The remaining writes are handled by the second loop.

Duff’s Device consolidates the two loops by the clever combining of a do-while loop and a switch statement. Giving:

int numLoops = (numOut + 8 – 1) / 8;

switch( numOut % 8 ) {

case 0: do { *pDest++ = *pSrc++;

case 7: *pDest++ = *pSrc++;

case 6: *pDest++ = *pSrc++;

case 5: *pDest++ = *pSrc++;

case 4: *pDest++ = *pSrc++;

case 3: *pDest++ = *pSrc++;

case 2: *pDest++ = *pSrc++;

case 1: *pDest++ = *pSrc++;

} while( --numLoops > 0 );

}

Note that Duff’s Device has one critical flaw?

It doesn’t numOut == 0. It gives 8 outputs instead. This is easily corrected by an enclosing if-statement. However, the zero-case is rare enough

that we don’t require it to be written with all implementations of the device.

Ralph Holly published an excellent C++-macro implementation of Duff’s Device in Dr. Dobbs Journal, August 2005 – Embedded Systems.

Functors Functors in C++ are implemented by overloading the function call operator – operator ().

Page 89: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 89 of 278

In this example a vector will be populated with the Fibonacci sequence. A functor is used as the generator argument to the STL algorithm

std::generate().

#include <algorithm>

#include <iostream>

#include <vector>

using namespace std;

/** @class template <typename NUMBER_T> class CFibonacciSequence

@brief Produces a sequence of numbers that follow a linear progression. */

template <typename NUMBER_T> class CFibonacciSequence {

private:

NUMBER_T m_value; //< The current value in the sequence

NUMBER_T m_previous; //< The previous value in the sequence

public:

/** @fn FibonacciSequence()

@brief constructor */

CFibonacciSequence() : m_value( 1 ), m_previous( 0 ) { }

/** @fn NUMBER_T operator() ()

@brief Function operator

@return the current value in the sequence

@note Calculates and stores the next value in the sequence. */

NUMBER_T operator() ()

{

NUMBER_T next = m_value + m_previous;

m_previous = m_value;

m_value = next;

return m_previous;

}

};

int main() {

vector<unsigned> sequence(16);

generate( sequence.begin(), sequence.end(), CFibonacciSequence<unsigned>() );

copy( sequence.begin(), sequence.end(), ostream_iterator<unsigned>( cout, " " ) );

return 0;

}

Transactional Programming See Programming Concepts: Transactional Programming Styles for an overview.

The issue of rolling back nested transactions has been explored by Calum Grant of Sophos Plc. He has implemented a transaction-based approach

to the standard template library containers that have the capability to rollback any number of nested operations on individual variables or

containers.

http://calumgrant.net/atomic/

Page 90: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 90 of 278

Dangerous Coding Practices Every programming language has its perils, pitfalls, hazards and dangerous practices. The C language has been described as the rope with which

you will eventually hang yourself – C++ as the rope that is long enough to hang yourself and still have enough left over to hang the rest of your

project team!

operator T* Casting operators that create an implicit cast a pointer are dangerous since they can be invoked by the delete command. The delete will delete

what the cast operator exposes not the object as expected.

class Foo {

char * pOwnedByFoo_;

public:

~Foo () { delete pOwnedByFoo_; }

operator const char * () { return pOwnedByFoo_; }

};

void func() {

Foo bar;

delete bar; // bar.pOwnedByFoo_ deleted through cast operator

} // bar.pOwnedByFoo_ deleted by destructor

Raw Pointers Using raw pointers to manage dynamic memory (see Memory Management: Memory Leaks)

Page 91: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 91 of 278

Memory Management

Memory Layout

Operating System

Heap

Data

Code

Interrupt Vector Table

Stack

0GiB

4GiB

2GiB

{local variables}

{dynamic variables (new/delete)}

{global & static variables}

{litterals}

Memory Leaks A memory leak is a block of dynamically allocated memory that can no longer be released by the owning process resulting in a loss of usable

memory blocks.

The most common source of memory leaks in C/C++ are:

Failing to deallocate memory blocks at end of scope.

Failing to deallocate memory blocks before over-writing the owning pointer.

Example void function( void ) {

A* p = new A;

int* q = new int [512];

Page 92: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 92 of 278

q = new int [256]; // q:512 leaks - overwrite

delete [] q;

} // p leaks – object of class A not deallocated

How big a problem? The most common problem caused by memory leaks is degraded performance due to insufficient memory. When the memory demand of the

application’s working set exceeds the amount of available RAM, the operating system must resort to continually swapping the working set in and

out of RAM (thrashing).

In practice, small memory leaks are common-place and often harmless. The virtual memory system of modern operating systems will reclaim the

‘leaked’ memory when the application (and related virtual machine) is terminated. Applications that run for short periods of time or leak memory

at very low rates can often pass without notice.

More serious leak scenarios include:

Where the O/S does not automatically release memory on application termination. This is more common on older operating systems like

the Amiga OS.

Where an application runs for longer periods, such as server applications and embedded programs (switches, consumer electronics).

Where memory allocations are frequent, such as real-time simulations and computer games.

Where the leak occurs inside the operating system, device drivers, or resident applications like virus scanners.

Where program termination doesn’t require memory deallocation, such as with shared memory.

Leave Avoidance The two most common methods for avoiding memory leaks both involve abandoning the use of raw pointers to manage dynamic memory.

One of the most common reasons to use dynamic memory is to allocate an array whose size will not be known until run-time.

void function() {

unsigned size;

cin >> size;

int* array = new [ size ];

delete [] array;

}

This code can easily be replaced by an STL vector.

void function() {

unsigned size;

cin >> size;

std::vector<int> array(size);

} // ~vector<int> automatically called.

Page 93: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 93 of 278

The vector solution has the added benefit of being exception safe. If the function terminates on an exception, the delete command from the first

function will not be executed. The vector destructor will execute!

The other approach is to use smart pointers such as those provided by the BOOST library. Replace:

void function( void ) {

A* p = new A;

delete p;

}

With:

void function( void ) {

boost::scoped_ptr<A> p( new A );

} // destructor deallocates object

Currently (2008), BOOST’s shared_ptr<> has been accepted into Technical Report 1 of the upcoming C++ Standard. It is found in

<memory> as std::tr1::shared_ptr<>.

Leak Detection While leak avoidance is a good strategy, it does not eliminate leaks. They may still occur and therefore we need a technology for detecting

memory leaks. There is no standard technology in C or C++ to do this, but there are many products available that can. The biggest problem

though, is that the solutions tend to be compiler or platform specific.

Multiplatform

Rational (IBM) Purify (Windows, Linux & Unix) – memory debugger and code library.

Parasoft Insure++ (Windows, Linux & Unix) – a competitor to Purify.

Memwatch (ANSI C) – a portable C-library (with source) for memory tracking and execution tracing.

M-Patrol by Graeme Roy (Windows, Linux, Unix, Amiga) – memory tracking library.

Linux

Valgrind – originally a GPL implementation of Purify. It has grown to a general debugging tool.

Electric Fence by Bruce Perens – memory tracking library.

Checker by Tristan Gingold – memory tracking library with a modified compiler back end.

Windows

CRTDBG – Microsoft’s memory tracking library that integrates and ships with Visual Studio.

Page 94: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 94 of 278

Microsoft’s CRTDBG Library Microsoft’s CRTDBG library provides memory leak tracking facilities that are easily accessible via Visual Studio.

Enabling Leak Checking Add the following code at the top of main()...

#include <crtdbg.h>

int main() {

#ifndef NDEBUG

int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );

// Turn On (OR) - Keep freed memory blocks in the

// heap's linked list and mark them as freed

tmpFlag |= _CRTDBG_DELAY_FREE_MEM_DF;

tmpFlag |= _CRTDBG_LEAK_CHECK_DF;

// Turn Off (AND) - prevent _CrtCheckMemory from

// being called at every allocation request

tmpFlag &= ~_CRTDBG_CHECK_ALWAYS_DF;

// Set the new state for the flag

_CrtSetDbgFlag( tmpFlag );

#endif

This will display a report of leaked memory blocks to the output window in Visual Studio.

Detected memory leaks!

Dumping objects ->

{121} normal block at 0x00194D40, 100 bytes long.

Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD

Object dump complete.

It will also delay the return of freed memory blocks to OS. This can be useful in stress testing and it also guarantees that all memory allocations

are new allocations (data block is initialized to 0xCD).

Enhancing identification The memory block that leaked can be difficult to detect from its hex dump. To help identify objects in the memory dump, we can place

descriptive text.

class Base {

#ifndef NDEBUG

char m_tag[100];

#endif

public:

Base() {

#ifndef NDEBUG

strcpy( m_tag, "Base class" );

#endif

Page 95: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 95 of 278

cout << "def ctor" << endl;

}

~Base() { cout << "dtor" << endl; }

void msg() { cout << "msg()" << endl; }

};

The text – “Base class” – will now appear in the debug window memory dump.

Detected memory leaks!

Dumping objects ->

{121} normal block at 0x00B54D40, 100 bytes long.

Data: <Base class > 42 61 73 65 20 63 6C 61 73 73 00 CD CD CD CD CD

Object dump complete.

Preprocessor

Macros Macros perform (more-or-less intelligent) source code substitution prior to compilation. Macro substitutions are performed by the preprocessor.

The macro preprocessor was inherited from C and is often used for a purpose that is appropriate for C, but not for C++.

Macros as constants #define NSIZE 42

Substitutes the literal ‘42’ for the word NSIZE as in the statement:

int a[NSIZE];

This is unnecessary in C++ as a constant declaration would work while providing type checking.

int NSIZE = 42;

Macros as functions #define max(a,b) ((a)>(b)?(a):(b))

Substitutes the literal expression for the mnemonic ‘max’ as in the statement:

int c = max(a,b);

The problem with this substitution is that it does not type-check the parameters. In C++, use a template instead.

template <typename T> T& max( T& a, T& b) { return a > b ? a : b; }

Sloppy function macros can lead to unusual and hard to detect failures.

#define F(a,b) a + b

int c = F(a,b) * 3; which expands to:

int c = a + b * 3;

Page 96: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 96 of 278

Clearly, unintended!

Useful macros… The ‘#’ operator converts token following to a string.

#define F(expr) cout << #expr << " = " << expr << endl;

F(a + b); expands to:

cout << "a + b" << " = " << a + b << endl;

The ‘##’ operator concatenates two tokens.

#ifdef UNICODE

#define T(str) L##str

#else

#define T(str) str

#endif

The ‘UNICODE’ version of the macro prepends an L to indicate the string literal is a UNICODE string.

T("Hello") expands to L"Hello" for a UNICODE build and to "Hello" for a standard build.

The preprocessor also defines useful macros such as __LINE__ that is replaced by the source code line number being compiled, __FILE__ that

is replaced by the name of the file being compiled and __FUNCTION__ that is replaced by the name of the function being compiled. Examine

your compiler documentation for other predefined macros.

Conditional compilation Arguably, the most useful macro in C/C++ is the assert() macro. A simple implementation of assert could be:

#ifdef NDEBUG

#define assert(cond)

#else

#define assert(cond) \

if(cond == false) {\

cerr << #cond " failed in " __FILE__ " at line " << __LINE__ << endl;\

exit(1);\

}

#endif

which is effectively stripped from release builds, but compiled into debug builds.

References

[STRO2000]

Page 97: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 97 of 278

STL

Which container do I use? The answer, of course, is that it depends on what I am using the container for. Each container has strength and weaknesses that we must consider.

vector list stack queue dequeue map multimap set Multiset

Find O(n) O(n) n/a n/a n/a O( log n ) O( log n ) O( log n ) O( log n )

Find - sorted O( log n ) O(n) n/a n/a n/a O( log n ) O( log n ) O( log n ) O( log n )

Insert O(n) O(1) n/a n/a n/a O( log n ) O( log n ) O( log n ) O( log n )

Delete O(n) O(1) n/a n/a n/a O( log n ) O( log n ) O( log n ) O( log n )

Sort O( logn n ) O( logn n ) n/a n/a n/a O(1)* O(1)* O(1)* O(1)*

push_front O(n) O(1) n/a n/a O(1) n/a n/a n/a n/a

pop_front O(n) O(1) n/a n/a O(1) n/a n/a n/a n/a

push_back O(1) O(1) n/a n/a O(1) n/a n/a n/a n/a

pop_back O(1) O(1) n/a n/a O(1) n/a n/a n/a n/a

push / enqueue n/a n/a O(1) O(1) n/a n/a n/a n/a n/a

pop / dequeue n/a n/a O(1) O(1) n/a n/a n/a n/a n/a

* always sorted

Templates

Template Programming Techniques The following techniques employ C++’s template mechanism to solve various programming problems.

Parameterizing method virtualization Whether a method is polymorphic can be determined by a template parameter. In C++ a method is made polymorphic by prefixing the method

declaration with the keyword ‘virtual’ and once polymorphic, always polymorphic. The ‘virtual’ keyword is not needed in derived classes.

Consider the classes:

class Base {

Page 98: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

C++ Programming Section 6

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 98 of 278

public:

void foo() {}

};

And the class:

class VBase {

public:

virtual void foo() {}

};

The choice of base class – Base or VBase – will determine whether method foo() is polymorphic within the class hierarchy. We can make this

choice compile-time selectable with the template class:

template <class BASETYPE>

class Derived : public BASETYPE {

public:

void foo();

};

We can then choose a non-polymorphic implementation with the declaration:

Derived<Base> nonPolymorphic;

Or a polymorphic implementation with the declaration:

Derived<VBase> polymorphic;

Page 99: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Database Section 7

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 99 of 278

Database

Data Normalization Data normalization is a data modelling technique that improves the quality of a database and is a theory that defines the properties of relations.

Normalization can reduce data duplication which intern improves storage efficiency and increases reliability.

Concept: Functional Dependency

Functional dependency is a relation between attributes of a class. Specifically, it indicates that the value of one attribute is directly determined by

another.

For example: in an inventory database the product name is functionally dependent on the product code. In other words, ‘if we know the product

code we can uniquely determine the product name.’

Functional dependency can be in one direction or both. When functional dependency runs in both directions (i.e. A B and B A) we call the

relationship a 1-to-1 relationship. When it runs in one direction (i.e. A B only) we call the relation a 1-to-many relationship. No functional

dependency indicates a many-to-many relationship.

Normal Forms

Normal forms specify the ‘rules’ for relationships between table attributes.

First (1NF), second (2NF) and third (3NF) normal forms were identified by E. F. Codd. Boyce-Codd (BCNF), fourth (4NF) and fifth (5NF) were

added in later research. Each form is wholly contained within its preceeding, simpler form. The containment relationship is 1NF 2NF 3NF

BCNF 4NF 5NF.

In 1981, a seventh normal form was discovered, domain/key normal form (DK/NF). This normal form eliminates modification anomalies, but is

difficult to convert relation into this form.

First Normal Form (1NF)

According to Codd...

A relation is in first normal form if and only if all columns are single valued (null attributes not allowed).

Or: Each record as the same number of fields.

Or: Each row has the same number of columns.

Page 100: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Database Section 7

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 100 of 278

According to Chris Date...

A relation is in first normal form if and only if it is isomorphic to some relation, or:2

1. There is no top-to-bottom ordering to the rows.

2. There is no left-to-right ordering to the columns.

3. There are no duplicate rows.

4. Every row-column intersection contains exactly one value from the applicable domain (and nothing else).

5. All columns are regular [i.e. rows have no hidden components such as row IDs, object IDs, or common timestamps].

Example of tables violating 1NF

User

User ID Name Email

100 Phil Alain [email protected]

101 Sue Coleman [email protected], [email protected]

102 Tom Thomson [email protected]

103 Danièle Rochon [email protected]

This table violates 1NF by storing multiple email addresses for Sue Coleman.

User

User ID Name Email

100 Phil Alain [email protected]

101 Sue Coleman [email protected]

[email protected]

102 Tom Thomson [email protected]

103 Danièle Rochon [email protected]

This table violates 1NF by storing an array (or table) of values for the email addresses of Sue Coleman.

User

User ID Name Email 1 Email 2 Email 3

100 Phil Alain [email protected]

101 Sue Coleman [email protected] [email protected]

102 Tom Thomson [email protected]

103 Danièle Rochon [email protected]

This table violates 1NF by having null fields.

2 Chris Date, “What First Normal Form Really Means”, pp 127-8 http://www.dbdebunk.com/page/page/629796.htm

Page 101: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Database Section 7

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 101 of 278

Problems

1. Searches are more complex – they must check for multiple matches in the field. A straight pattern match won’t be sufficient.

2. Records are variable sizes – making the database more difficult to optimize (how much space should be reserved for new records?)

3. Space is wasted – many fields with be left empty.

Solution = 1NF

User Name

User ID Name

100 Phil Alain

101 Sue Coleman

102 Tom Thomson

103 Danièle Rochon

User email

User ID Email

100 [email protected]

101 [email protected]

101 [email protected]

102 [email protected]

103 [email protected]

Second Normal Form (2NF)

Terminology – Candidate Key

A candidate key is set of record attributes that can uniquely and completely identify a database record. A given table may have one or more

candidate keys. Typically, one of the candidate keys is chosen as the primary key of the table.

User

First Name Surname Email

Phil Alain [email protected]

Sue Coleman [email protected]

Tom Thomson [email protected]

Sue Thomson [email protected]

Danièle Rochon [email protected]

In this table neither the first name nor the surname uniquely identifies a record. The candidate key of the first name + surname does uniquely

identify a record.

Page 102: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Database Section 7

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 102 of 278

Definition

A table is in second normal form if-and-only-if it is in first normal form and none of its non-prime attributes (fields) are functionally dependant on

just part of a candidate key.

Corollary: a table in first normal form without a candidate is automatically in second normal form.

Example

User

Name Account Types Email

Phil Alain Standard [email protected]

Sue Coleman Standard [email protected]

Sue Coleman Power User [email protected]

Sue Coleman Administrator [email protected]

Tom Thomson Standard [email protected]

Tom Thomson Power User [email protected]

Danièle Rochon Standard [email protected]

This table violates 2NF by since it has a candidate key (name + account type) and the email attribute is functionally dependant on the name but not

the account type.

Problems

1. Wasted space – data is repeated. The same email address is stored in more than one record.

2. Data integrity – if a user’s email is changed, multiple records need be updated.

Solution = 2NF

User Account Type

Name Account Types

Phil Alain Standard

Sue Coleman Standard

Sue Coleman Power User

Sue Coleman Administrator

Tom Thomson Standard

Tom Thomson Power User

Danièle Rochon Standard

User Email

Name Email

Phil Alain [email protected]

Page 103: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Database Section 7

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 103 of 278

Sue Coleman [email protected]

Tom Thomson [email protected]

Danièle Rochon [email protected]

Third Normal Form (3NF) A table is in third normal form if-and-only-if the relation is in second normal form and every non-prime attribute of the table is directly dependant

on every key of the table.

Example

PGA Tour Winners

Tournament Date Winner Winner Date of Birth

Memorial Tournament May 28, 2008 Kenny Perry August 10, 1960

Mercedes-Benz Championship Jan 11, 2009 Geoff Ogilvy June 11, 1977

Sony Open – Hawaii Jan 18, 2009 Zach Johnson Feb 24, 1976

Bob Hope Classic Jan 25, 2009 Pat Perez March 1, 1976

FBR Open Feb 1, 2009 Kenny Perry August 10, 1960

The Tournament + Date is the candidate key for the table.

This table violates 3NF by since the Winner Date of Birth is only transitively dependant on the candidate key. The Winner Date of Birth is

dependent on the Winner which is in turn dependent on the candidate key.

Problems

1. Wasted space – values in the Winner Date of Birth are repeated.

2. Data integrity – if a Winner Date of Birth value needs to be corrected, multiple records need be corrected.

Solution = 3NF

PGA Tour Winners

Tournament Date Winner

Memorial Tournament May 28, 2008 Kenny Perry

Mercedes-Benz Championship Jan 11, 2009 Geoff Ogilvy

Sony Open – Hawaii Jan 18, 2009 Zach Johnson

Bob Hope Classic Jan 25, 2009 Pat Perez

FBR Open Feb 1, 2009 Kenny Perry

Winners Date of Birth

Winner Winner Date of Birth

Kenny Perry August 10, 1960

Page 104: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Database Section 7

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 104 of 278

Geoff Ogilvy June 11, 1977

Zach Johnson Feb 24, 1976

Pat Perez March 1, 1976

Forth Normal Form (4NF)

A table is in fourth normal form if-and-only-if, for every one of its non-trivial multivalued dependencies XY, X is either a candidate key or a

superset thereof.

Example

Pizza Delivery Permutations

Restaurant Variety Delivery Area

Dominos Thick Crust North

Dominos Thick Crust Central

Dominos Thick Crust East

Dominos Stuffed Crust North

Dominos Stuffed Crust Central

Dominos Stuffed Crust East

Little Caesar’s Thin Crust East

Little Caesar’s Stuffed Crust East

Pizza Pizza Thick Crust North

Pizza Pizza Thick Crust Central

Pizza Pizza Thin Crust North

Pizza Pizza Thin Crust Central

All fields are part of a candidate key – therefore automatically 3NF.

Problems

1. Data redundancy – repeated values, multiple updates.

Solution = 4NF

Varieties by Restaurant

Restaurant Variety

Dominos Thick Crust

Dominos Stuffed Crust

Little Caesar’s Thin Crust

Little Caesar’s Stuffed Crust

Pizza Pizza Thick Crust

Pizza Pizza Thin Crust

Page 105: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Database Section 7

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 105 of 278

Delivery Area by Restaurant

Restaurant Delivery Area

Dominos North

Dominos Central

Dominos East

Little Caesar’s East

Pizza Pizza North

Pizza Pizza Central

Page 106: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Data Structures Section 8

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 106 of 278

Data Structures Data structures are organizational patterns for data storage that describe the relationship

between element locations, size and reference information.

Example: An array stores elements in contiguous memory where an index indicates the offset of a given element from the beginning of the block

of memory.

Set The collection of things called elements. This concept forms the basis and set theory.

Axioms

Extensionality

(equivalence)

If X and Y are sets for which every element of X is an element of Y, and

every element of Y is an element of X, then the sets X and Y are one and the

same.

X = Y

Existence A collection that is empty ( ) is still a set.

Schema of

Comprehension Let P x be a predicate. For any set S, the collection of all objects x which

belong to S and for which P x is true is a set.

Notation: |x S P x

Example:

Let 1,2,3,4,5,6,7,8S .

Let | 4T x S x

array A 8992442

Offset = 0 Offset = 3

Page 107: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Data Structures Section 8

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 107 of 278

Therefore 1,2,3,4T

Pair For any sets A and B, the collection which has as its only objects A and B is

a set.

Notation: ,A B

Union For any set S, the collection of all objects which are elements of S is a set,

called the union of S.

Notation: SU

Infinity The collection ¥ of all natural numbers is a set with the following

property: If S is a subset of ¥ which satisfies the requirements:

1. 0 S ;

2. n ¥ , if n S , then 1n S ;

Then S ¥ .

Power Set For any set S, the collection of all subsets of S is a set.

Notation: The power set of S, is denoted by SP

Examples

1,2 , 1 , 2 , 1,2

P

P

Definitions

Empty set: The empty set is the unique set with no elements. Denoted by

Intersection: For any sets A and B, the intersection of A and B is the set |x A x B

Notation: A B

Union: For any sets A and B, the union of A and B is the union of the set ,A B .

Notation: ,A B A B U

Subset: For any set S, a set A is said to be a subset of S, if every element of A is an

element of S.

Notation: A S or S A

Alternate reading: A is included in S.

Page 108: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Data Structures Section 8

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 108 of 278

Finite set If S is a set for which there exists a positive integer n such that the elements

of S can be matched up by a one-to-one correspondence with the elements

of the set 1,2,3, ,nJ n K , then S is said to be a finite set. S is said to have

n elements, or to have size n.

Notation: S n

The empty set is also said to be finite with a size of zero. 0

Ordered Pair For objects A and B, the set , ,A A B is called the ordered pair of A and

B. A is called the first coordinate of the ordered pair and B is called the

second coordinate of the ordered pair.

Notation: , , ,A B A A B

Note that if A B then ,A B A

Cartesian Product For any sets S and T, the Cartesian product of S and T, is the set

| , for some and some X S T X A B A S B T P P

Notation: S T is the Cartesian product of S and T.

Alias: direct product

Ordered Triple For objects a, b, c, the ordered triple, (a, b, c) is defined by

, , , ,a b c a b c

Alias: 3-tuple

Page 109: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Data Structures Section 8

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 109 of 278

Cartesian Product

as ordered

pair/triple

Let A be a set and n be a positive integer. The Cartesian product 1

n

iA

is

denoted by nA .

Note: 1

n n

iA A A A A A

K , in other words, n Cartesian products of

A with itself.

Examples

Let 0,1A

1

2

3

0,1

0,0 , 0,1 , 1,0 , 1,1

0,0,0 , 0,0,1 , 0,1,0 , 0,1,1 , 1,0,0 , 1,0,1 , 1,1, 0 , 1,1,1

A

A

A

Properties

Union of empty

set. For any set A, A A A

Union is

commutative.

For any sets A and B, A B B A

Subset and the

empty set. For any set A, A

Self containment For any set A, A A

Predicate

containment For any predicate P x and set S, |x S P x S .

Intersection

containment For any sets A and B, A B A

Union

containment For any sets A and B, A A B

Size of power set For any natural number n, if S is a set with S n , then 2nS P

Ordered Pairs are

contained in

Power Sets

For any sets S and T, ,A B S T P P for every A S and B T .

Page 110: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Data Structures Section 8

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 110 of 278

History

Set theory was founded by the German/Russian mathematician Georg Cantor (1845 – 1918). After graduating from the University of Berlin in

1867 he published a series of papers in which he formulated his ideas on sets and infinite numbers.

Page 111: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Design Patterns Section 9

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 111 of 278

Design Patterns

Bridge The bridge pattern is normally implemented using bounded dynamic polymorphism.

+operation()

Abstraction

+operation()

Implementor

1

-impl

1

+operation()

ConcreteImplementationA

+operation()

ConcreteImplementationB

However, C++ and other languages with generics may implement the bridge pattern using unbounded static polymorphism.

+operation()

Abstraction

IMPL

+operation()

ConcreteImplementationA

+operation()

ConcreteImplementation

+operation()

AbstractionA

«bind»(ConcreteImplementationA)

+operation()

AbstractionB

«bind»(ConcreteImplementationB)

Delegate A delegate is an object that represents a function or method, but hides the identity of the specific function or method.

Page 112: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Design Patterns Section 9

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 112 of 278

A delegate is much like a function pointer but with a much cleaner interface. A delegate allows the programmer to invoke the delegated function

without knowing the actual name of the function or the name of the object to which the member function pointer has been bound to. In many

implementations, the delegate can support multiple function pointers using a subscription system.

Delegates can simplify the implementation of the observer pattern or callback systems.

Implementation Patterns

Double Check Locking Pattern (DCLP) DCLP was originally called the “Double-check Locking Optimization Pattern”.

DCLP is broken in Java.

DCLP is difficult in C++.

DCLP is a solution to the synchronization defect in the standard singleton pattern.

Intent

DCLP is a creational design pattern that facilitates lazy initialization of the shared resource.

Visual Studio 2005

Microsoft claims that DCLP can be implemented using critical sections and a volatile static pointer. (MSDN Magazine: June 2007)

Producer-Consumer

Introduction

The classical Producer-Consumer pattern has significant flaw when implemented – it cannot easily shut itself down.

Classic Pattern – Mutex and Semaphores

Mutex g_mutex

Semaphore g_emptySpots = BUFFER_SIZE

Semaphore g_fullSpots = 0

procedure PRODUCER

loop

PRODUCEITEM( item )

WAIT( g_emptySpots )

LOCK( g_mutex )

ENQUEUE( item )

UNLOCK( mutex )

SIGNAL( g_fullSpots )

end-loop

Page 113: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Design Patterns Section 9

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 113 of 278

procedure CONSUMER

loop

WAIT( g_fullSpots )

LOCK( g_mutex )

DEQUEUE( item )

UNLOCK( g_mutex )

SIGNAL( g_emptySpots )

CONSUMEITEM( item )

end-loop

The problem with the classic pattern is that it assumes that the producer and consumer will run forever and that there is only one consumer.

Solution – Condition Variable, Mutex & Semaphore

Boolean g_done = false

Mutex g_mutex

Semaphore g_emptySpots = BUFFER_SIZE

Condition g_producerChange

Queue g_Q

procedure CONSUMER

loop

LOCK(g_mutex)

if g_done and g_emptySpots then

UNLOCK(g_mutex)

return

if size{ g_Q } = 0 then

CONDITIONWAIT(g_producerChange)

if size{ g_Q } > 0 then

DEQUEUE( g_Q , item )

UNLOCK(g_mutex)

if item then

SIGNAL(g_emptySpots)

CONSUMEITEM(item)

end-loop

procedure PRODUCER

loop n times

PRODUCEITEM(item)

WAIT(g_emptySpots)

LOCK(g_mutex)

ENQUEUE(g_Q , item)

UNLOCK(g_mutex)

CONDITIONSIGNAL(g_producerChange)

end-loop

g_done ← true

CONDITIONBROADCAST(g_producerChange)

Page 114: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Design Patterns Section 9

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 114 of 278

Page 115: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Game Programming Section 10

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 115 of 278

Game Programming

Game Architecture

Direct3D and the Win32 Message Pump (Garth Santor, March 2007)

Win32/C++ still underlies the majority of games, frameworks and engines in the game industry. Unfortunately, the architecture of the standard

Win32/C++ application is not ideal for real-time Direct3D3.

Standard Win32 Here is the standard “Hello, world!” application written in Win32/C++.

#define STRICT

#define WIN32_LEAN_AND_MEAN

#include <windows.h>

LRESULT CALLBACK WndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {

switch( uMsg ) {

case WM_CREATE:

return 0;

case WM_PAINT: {

PAINTSTRUCT ps;

HDC hdc = BeginPaint( hwnd, &ps );

RECT rect;

GetClientRect( hwnd, &rect );

static TCHAR* pszGreetings = "Hello, world!";

DrawText( hdc, pszGreetings, lstrlen( pszGreetings ), &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE );

EndPaint( hwnd, &ps );

return 0;

}

case WM_DESTROY:

PostQuitMessage( 0 );

return 0;

default:

return DefWindowProc( hwnd, uMsg, wParam, lParam );

}

}

3 For the sake of this article Direct3D will refer to Direct3D9.

Page 116: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Game Programming Section 10

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 116 of 278

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, LPSTR /* lpCmdLine */, int nCmdShow ) {

// Register the window class

WNDCLASSEX wc = { 0 };

static char strAppName[] = "Hello, world";

wc.cbSize = sizeof( wc );

wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;

wc.lpfnWndProc = WndProc;

wc.hInstance = hInstance;

wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );

wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );

wc.hIconSm = LoadIcon( NULL, IDI_APPLICATION );

wc.hCursor = LoadCursor( NULL, IDC_ARROW );

wc.lpszMenuName = NULL;

wc.lpszClassName = strAppName;

RegisterClassEx( &wc );

// Create the main application window.

HWND hwnd = CreateWindowEx( NULL, strAppName, strAppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,

512, 512, NULL, NULL, hInstance, NULL );

// Display the window

ShowWindow( hwnd, nCmdShow );

UpdateWindow( hwnd ); // force WM_PAINT

// run message pump

MSG msg;

while( GetMessage( &msg, NULL, 0, 0 ) ) {

TranslateMessage( &msg );

DispatchMessage( &msg );

}

// return exit code to Windows

return static_cast<int>( msg.wParam );

}

If you examine the task manager while this application is running you will notice that the processor load if virtually zero, except briefly when the

window was created, resized or closed.

Why? A standard window application spends most of its time in a suspended state.

The Win32 function GetMessage() is key to understanding this behaviour. GetMessage() is a blocking function that acquires Windows

messages from that application’s message queue. If there are no messages pending, the application is suspended and execution transfers to another

process. The application doesn’t resume until an external event causes a message to be issued to the application. The application’s process state is

then changed from suspended to ready. Once the message queue has been cleared, the application returns to a suspended process state.

GetMessage() only returns false (and terminates the loop) when the message acquired is WM_QUIT.

Page 117: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Game Programming Section 10

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 117 of 278

Why this is bad… Real-time graphics applications like games don’t like the behaviour of standard Win32 applications, because they don’t want the program to enter

a suspended process state the moment the message queue is cleared. We want our full time-slice for rendered frames at as high a rate as possible.

Just because the user stopped playing doesn’t mean that the game has stopped playing.

To get our full time-slice back, we need to stop using GetMessage().

PeekMessage Pump The message-pump code of the standard Win32 application:

MSG msg;

while( GetMessage( &msg, NULL, 0, 0 ) ) {

TranslateMessage( &msg );

DispatchMessage( &msg );

}

Is replaced with:

int cIdle = 0;

MSG msg;

for(;;) {

if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) {

if( msg.message == WM_QUIT )

break;

TranslateMessage( &msg );

DispatchMessage( &msg );

}

else {

HDC hdc = GetDC( hwnd );

RECT rect;

GetClientRect( hwnd, &rect );

std::wstringstream oss;

oss << L"Hello, " << ++cIdle;

DrawText( hdc, oss.str().c_str(), (int)oss.str().size(), &rect, DT_CENTER|DT_VCENTER|DT_SINGLELINE );

ReleaseDC( hwnd, hdc );

}

}

PeekMessage() is non-blocking and return false when the message queue is empty, not when WM_QUIT has been issued as is the case with

GetMessage(). This behaviour allows our application to update the frame on any idle cycles.

Examining the task manager performance tab will reveal 100% CPU usage on single-thread, non-hyper-thread processors. Hyper-thread and

multi-core processors will show 50% CPU usage as the other core will be used to execute GDI function calls that are processed synchronously

with the application executing on the original core.

Page 118: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Game Programming Section 10

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 118 of 278

Now with Direct3D I’ll add the minimal Direct3D9 plumbing to the previous example, replacing the GDI calls that render “Hello, world” with an

IDirect3DDevice9::Clear() that cycles the window colour through all the shades of pure blue.

#define STRICT

#include <windows.h>

#include <d3d9.h>

#pragma comment (lib,"d3d9.lib")

IDirect3DDevice9* g_pd3dDevice = NULL;

void Render() {

static unsigned char blue = 0;

--blue;

g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,blue), 1.0f, 0 );

g_pd3dDevice->Present( NULL, NULL, NULL, NULL );

}

LRESULT CALLBACK MsgProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {

switch( uMsg ) {

case WM_DESTROY:

PostQuitMessage( 0 );

return 0;

default:

return DefWindowProc( hwnd, uMsg, wParam, lParam );

}

}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow ) {

IDirect3D9* pd3d = Direct3DCreate9( D3D_SDK_VERSION );

if( !pd3d )

return 1;

// Register the window class.

WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,

GetModuleHandle(NULL), NULL, NULL, NULL, NULL,

L"D3D Tutorial", NULL };

RegisterClassEx( &wc );

// Create the application's window.

HWND hWnd = CreateWindow( L"D3D Tutorial", L"D3D: CreateDevice", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,

GetDesktopWindow(), NULL, wc.hInstance, NULL );

if( hWnd == NULL )

return 1;

// Create the full screen device

D3DPRESENT_PARAMETERS d3dpp = { 0 };

Page 119: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Game Programming Section 10

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 119 of 278

d3dpp.Windowed = TRUE;

d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;

d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;

HRESULT hres = pd3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,

&d3dpp, &g_pd3dDevice );

if( FAILED( hres ) )

return 1;

ShowWindow( hWnd, nCmdShow );

UpdateWindow( hWnd );

// Message Pump

MSG msg;

for(;;) {

if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) {

if( msg.message == WM_QUIT )

break;

TranslateMessage( &msg );

DispatchMessage( &msg );

}

else

Render();

}

g_pd3dDevice->Release();

pd3d->Release();

return (int)msg.wParam; // all ok

}

Once again the processor load drops to near zero. If we measure the time it takes to cycle through all the shades of blue, we will discover that our

frame rate is approximately 60 fps. By default, a windowed presentation mode will have vertical sync enabled, locking the frame rate to the

monitor’s refresh rate. Since the IDirect3DDevice9::Present() method is synchronous, the application is suspended until the GPU

completes the operation.

To achieve higher frame rates, we need to turn vertical sync off with a more precisely specified device mode.

Page 120: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Game Programming Section 10

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 120 of 278

Game Loops

Load Game

Unload Game

/ Quit

Service Windows

Get Input

AI/Logic

Physics/Model Update

Render and Sound

Real-time Game Loop:

Stand-alone

Page 121: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Game Programming Section 10

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 121 of 278

Load Game

Unload Game

/ Quit

Service Windows

Send User Input to Server

Update Game State

Render and Sound

Real-time Game Loop:

Client

Load Game

Unload Game

/ Quit

Service OS

Get Client States

AI/Logic

Physics/Model Update

Broadcast Game State Changes

Real-time Game Loop:

Server

Page 122: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Game Programming Section 10

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 122 of 278

Load Game

Unload Game

/ Quit

Service Windows

Send User Input to Server

Update Game State

Render and Sound

Real-time Game Loop:

Threaded Client

Load Game

Unload Game

/ Quit

Service OS

Get Client Actions

AI/Logic

Physics/Model Update

Broadcast Game State Changes

Real-time Game Loop:

Threaded Server

Get State Changes

Update Game State

/ Quit

Get Client Input

Queue Client Action

/ Quit

Page 123: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Game Programming Section 10

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 123 of 278

Input

Thumbing Styles Game controllers present an interesting problem for software developers because controls, more than most input devices, are susceptible to

different input styles. Controller button input styles tend to be a variation of either the precise thumbing style or the sloppy thumbing style.

In the precise thumbing style, the user places their thumb above the primary button resting the tip of the thumb on the button. The thumb is then

moved to the other buttons as needed, but typically returns to the primary button after each press.

In the sloppy thumbing style, the user places their thumb above and touching all the buttons. The thumb is then rocked or tilted onto the specific

button as required.

The GameCube controller was built with sloppy thumb players in mind and has a larger primary key.

The great concern for a developer in understanding thumbing styles is that players with the sloppy thumbing style is more likely to accidentally

press more than one button when only a single button press is desired. This could result in a character such as Mario performing a ‘ground pound’

instead of the player’s intended ‘jump’ operation. These ambiguous button situations are a major source of player frustration with a game.

The two most common solutions to sloppy thumb problems are to only accept commands in the appropriate context or to increase the window of

time that a command can be executed (e.g. if jumping off a cliff, allow the jump command to be issued up to 0.25 seconds after running off the

edge of the cliff.)

Logic / AI

Feedback Loops A feedback loop is a technique that can be applied to any system where a transformation occurs. System input represent the influence of the

environment on the system; system output the influence of the system on the environment. Feedback is a system output that is also used as a

system input. Feedback represents the system’s influence on itself.

Positive Feedback Loops

If the feedback data accelerates the system’s progress in the same direction as preceding output, then we have a positive feedback loop. The

feedback heard in microphone/amplifier systems is an example of positive feedback. Other examples are chain reactions, explosions (both the

chemical kind and the population kind), compound interest, and the spread of a disease.

Negative Feedback Loops

If the feedback data reverses the direction from the preceding output, then we have a negative feedback loop. The feedback felt in a shock

absorber system is an example of negative feedback. If a negative feedback system produces a series of values that are successively smaller in

magnitude from the preceding output, the system will approach a state of equilibrium. These feedback loops can be characterized as goal seeking.

Page 124: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Game Programming Section 10

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 124 of 278

It is the negative feedback systems that are most interesting in game and simulation programming!

Networking

DirectPlay

Introduction

DirectPlay is the DirectX system for building multiplayer games. Introduced as part of the DirectX 2.0 API in 1996, DirectPlay provides a device-

independent and network independent communication model. The mechanics of enumerating and connecting to game servers and transferring

data among them is abstracted within the API. The most significant omission from the API is synchronization. Synchronization is not a part of

the API since developers differ greatly on how to implement synchronization.

With DirectX 9.0, DirectPlay supports the following features:

Available for Windows 95, 98, ME, NT, 2000, XP, 2003 and Pocket PC.

Communicates over Transmission Control Protocol/Internet Protocol (TCP/IP), Internetworking Packages Exchange (IPX), modem and serial

links.

Peer-to-peer sessions.

Client/server sessions.

Player lobbies.

Player groups.

Voice.

Can calculate round-trip travel times for messages.

Thread pools.

Support for Network Address Translation.

Support for Internet Protocol v6.

What DirectX does not support:

Secure communications.

Architecture

DirectPlay is composed of the DirectPlay COM object, which provides the programming interface, and the DirectPlay Service Provider which

implements network specific communications.

Page 125: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Game Programming Section 10

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 125 of 278

DirectPlay Transport Protocol

DirectPlay implements its own network protocol, the DirectPlay Transport Protocol. As of DirectX 8.0, it is used for all DirectPlay messages.

This transport layer provides features that are specific to the needs of game developers.

Reliable and unreliable messages. Reliable messages that are resent until received whereas unreliable messages are not.

Sequential and non-sequential messages. Sequential messages are received in the same order they were sent.

Message fragmentation and assembly. On networks with packet size limits, messages are fragmented, sent, and then reassembled by the

receiving application.

Congestion control. DirectPlay throttles the outgoing messages to a rate that the target application can handle. This prevents flooding of the

target application.

Message priorities. Messages can be sent with low, medium or high priority, with high priority messages being sent first.

Message lifespan. Message can be sent with a timeout attribute after which the sender will quit sending the message.

DirectPlay uses UDP for communicating over IP networks, which it implements using Winsock.

DirectPlay Addresses

DirectPlay uniquely identifies each game with a DirectPlay Address. DirectPlay Addresses take the form of an URL string. The format is:

x-directplay:/[data string]

The DirectPlay address string is normally encapsulated in a DirectPlay Address object, so the specific details are not an issue programmers need to

deal with.

Ports

DirectPlay automatically assigns a port address between 2302 and 2400 for local use when hosting enumerating or connecting.

Sessions

Since multiple games can be played on the same network, DirectPlay needs a method of identifying one game from another. This is called

sessions. Each game on the network, either peer-to-peer (P2P) or client/server is represented by a session. The host or the first peer creates the

session, then the clients or other players of a P2P games join that session.

Players

maintains a list of current players in a session.

each player has a friendly name, a formal name and an ID.

Player names are not used internally.

Page 126: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Game Programming Section 10

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 126 of 278

Player Groups

Player groups are like teams.

Player groups appear like players in a session.

Messages can be sent to the members of a group.

Messages

Communication is performed using ‘messages’.

Message can be sent to everyone, the group or an individual player.

Networking Issues (Garth Santor, pre 2006)

Most networking issues in multiplayer games are not unique to game programming. They are however, significant!

Issues that developers need to consider are:

number of players

network architecture

protocol

what data needs to be transmitted

time sensitivity of the information

Furthermore, these issues are related.

Network Architecture – Peer-to-Peer vs. Client/Server (and number of players) Network architectures in gaming can be generalized into one of three general models.

1. Client/Server – Server is a player.

2. Client/Server – Dedicated server.

3. Peer-to-peer.

Page 127: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Game Programming Section 10

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 127 of 278

host client

client client

host

client

client

clientclient

peer

peer peer

peer

Client/Server

Server is player

Client/Server

Dedicated ServerPeer-to-peer

In client-server architectures a server process executes the game logic and manages communication between all the players. Client processes

render the graphics and play audio, and handle input from the player. A dedicated server architecture has the server process running on it own

machine, whereas the server is a player architecture has the host player’s machine running both the server process and one of the client processes.

Real-time-strategy games are often implemented with the server is a player architecture. The dedicated server architecture is common in multi-

player first person shooters and massively-multiplayer online role-playing games.

The peer-to-peer approach treats all players as equal and each peer process executes its part of the game logic. Peer-to-peer architectures are more

common on network card games.

Critique

Peer-to-peer networking is generally easier to program and produces the shortest transmission times, but is limited in the number of players in a

game. Adding more players drastically increases the number of connections to the point of being unmanageable.

# Players # Connections – P2P

# Connections C/S

1 0 1

2 1 2

3 3 3

4 6 4

5 10 5

n

12

1

1O

2

n

i

i

n nx n

On n

Clearly, P2P networks do not scale well.

Page 128: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Game Programming Section 10

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 128 of 278

Another benefit of peer-to-peer networking is for host migration. If the game host quits, the host can easily be migrated to another computer

without having to re-establish network connections to the new server.

Protocols – TCP vs. UDP (and time sensitivity) TCP is a streamed protocol that focuses on reliable communication between client and server. It performs three way handshaking to ensure that

everything sent actually arrives. This has the consequence that establishing a connection requires a minimum of three packets to be sent back and

forth. Lost packets cause the system to halt transmission of new packets until the missing packet has been resent and received. It is however; very

easy to use as the TCP stack performs a lot of the security and reliability task for the application programmer.

UDP is a connectionless datagram protocol that focuses on efficient communication between client and server. It sends packets without

handshaking. If the packet fails to arrive the sender won’t know of the failure and the receiver won’t know a packet was sent. Security and

reliability must be handled by the application programmer. UDP has the added benefit that it can be multicast.

Multicasting allows a server to broadcast a single packet to an entire network. This is particularly useful for streaming video to multiple clients or

sending player state data to all the players on a LAN. A UDP broadcast does not require knowledge of specific client IP addresses and is therefore

useful to query a LAN for the presence of players.

A further consideration is the time-sensitivity of the information being transmitted. In the case of a 1st-person shooter – the direction a character is

facing is important, only in the present. If that information did not get transmitted at that instant, we can forget about that information. No-one

will have any historical interest as the current state of the character is not dependent on that information. Contrast this to a chess game. We must

record every move that each player makes and in correct sequence. The network must continue to try to transmit the data or quit the game. TCP

offers no benefit when the data is time sensitive and time independent; it just slows your communications. UDP is better suited to this situation.

Threading Issues Multi-threading is a topic that is rarely discussed in game programming books, largely due to the fact that programming multiple threads in

Direct3D is somewhat difficult. Direct3D, in general, doesn’t like to execute in multiple threads!

Why? I would assume that Direct3D’s designers didn’t want to handle the situation where thread A causes a display mode change while thread B

is rendering to Direct3D. To handle this situation, Direct3D would have to share a mutex with the OS that would destroy the performance of the

system. Due to this problem, the Direct3D engineers decided to enforce the rule that the methods IDirect3DDevice9::Reset and

IDirect3D9::CreateDevice can only be called by the thread that handles windows messages. The added complication of avoiding overlap in

IDirect3DDevice9::BeginScene / IDirect3DDevice9::EndScene calls leads developers to place all of the Direct3D code in the same thread as the

window message handler.

Where can you safely multithread?

The most common places for multithreading in a game are:

scene loading

networking

AI

Page 129: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Game Programming Section 10

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 129 of 278

Scene Loading

Scene or level loading usually requires one or more files on disk to be read, especially where textures must be loaded. Loading a textures usually

requires reading some portion of the file into memory, decoding the data (decompress and/or translate to a different format), then transfer the

texture to video memory. Reading data from the disk is normally handled by the system’s DMA controller and therefore requires little or no CPU

activity.

Each texture can be read and decompressed/converted in a separate thread. When the thread is blocked due to an I/O wait, the next thread will

execute. Eventually, the first thread will complete its read and move on decompression. While decompression occurs (a CPU intensive

operation) other threads will be performing disk-to-memory data transfers. The total load time can often be reduced to a fraction of the time that

would be required to load the texture in a serial fashion.

Networking

To avoid having to write your network routines as a polling system, the network read function can be written using blocking read functions that

reside in a loop running in a separate thread. This thread reads the socket and updates a block of shared memory that contains the state of game

objects from the network.

AI

AI is often processed in a separate thread. This is typically done when the AI calculations are complex and cannot be performed within the time

allotted between frames.

Page 130: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 130 of 278

Graphics

Concepts

Blit A blit is a colloquialism for bit block transfer.

Camera

Introduction

The ‘camera’ represents the virtual viewer (the user) within a 3D scene. The camera encapsulates the position, direction, orientation and ocular

properties of the viewer. An object-oriented implementation of a camera can enhance understanding of the system and simplify the overall

implementation of the rendering engine.

Both DirectX and OpenGL have support for the 3D camera concept. However, DirectX’s D3DXMatrixLookAtLH/RH() functions and

OpenGL’s gluLookAt() function are somewhat limited and are best suited to a system that is aiming at a fixed position.

3D games such as simulators and first-person shooters work with the idea that the viewer will look ahead, but not at anything in particular. There

is some variation in the camera’s behaviour depending on whether we use the camera for an aerial object or a land-based object.

Solution

The solution consists of three parts:

The view matrix.

Orientation operations.

Motion operations.

View Matrix

Each object in a 3D world can be thought to have its own 3-axis coordinate system. With that in mind, we can imagine that the camera’s

coordinate system is congruent to the world’s coordinate system, but with a different origin (translation) and a different orientation (rotation). If

we can find a combination of translation and rotation that transforms our local coordinate system to the world coordinate system then we can find

another transform that can transform the world coordinate system to our local (viewer) coordinate system.

Let zyx pppp be the position vector of the viewer.

Let zyx kkkk be the look vector of the viewer.

Page 131: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 131 of 278

Let zyx uuuu be the up vector of the viewer.

Let zyx rrrr be the right vector of the viewer.

Find a transformation matrix V such that:

000pV The position is transformed to the origin.

100kV The look vector is transformed to the z-axis.

010uV The up vector is transformed to the y-axis.

001rV The right vector is transformed to the x-axis.

Translation Part

The translation that takes p to the origin is simply −p, since 0pp .

Written as a 4x4 matrix with homogenous coordinates:

1 0 0 0

0 1 0 0

0 0 1 0

1x y z

T

p p p

Rotation Part

Since rotation matrices don’t require homogenous coordinates and 3x3 matrices are easier to work with than are 4x4 matrices, we will seek a 3x3

matrix A that aligns the right, up and look vectors to the world’s x-axis, y-axis and z-axis.

100

222120

121110

020100

aaa

aaa

aaa

kkk zyxkA

010

222120

121110

020100

aaa

aaa

aaa

uuu zyxuA

001

222120

121110

020100

aaa

aaa

aaa

rrr zyxrA

Since each system has the same coefficient matrix A, we can solve all the system at once.

Page 132: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 132 of 278

00 01 02

10 11 12

20 21 22

1 0 0

0 1 0

0 0 1

x y z

x y z

x y z

a a a

a a a

a a a

r r r

BA u u u

k k k

A can be solved in many ways, but the simplest solution is to recognize that A is the inverse of B since 1BBIBA

In the case that a matrix is orthogonal (its row vectors are an orthonormal basis – they are at right angles), we know that its inverse is equal to its

transpose.

1 T

x x x

y y y

z z z

r u k

B B A r u k

r u k

We can now combine the translation matrix with the rotation matrix to produce the final view matrix

1 0 0 0 0 0

0 1 0 0 0 0

0 0 1 0 0 0

1 0 0 0 1 1

x x x x x x

y y y y y y

z z z z z z

x y z

r u k r u k

r u k r u kTA V

r u k r u k

p p p p r p u p k

Right-Handed Systems

The solution provided here assumes a left-handed coordinate system. On a right-handed coordinate system we must flip either the

right vector to point left, or the look vector to be looking at us. All of the preceding arguments still apply for right-handed system.

The calculation requires that we start with -k for the look vector. The result is the view matrix transform:

0 0

0 0

0 0

1 1

x x x x x x

y y y y y y

z z z z z z

r u k r u k

r u k r u k

r u k r u k

p r p u p k p r p u p k

Orientation Operations

Orientation operations adjust the pitch, roll and yaw of the camera.

A change in pitch is a rotation about the camera’s right-vector. A positive pitch angle produces a downward pitch. Calculate a rotation matrix

about the right vector, then transform the coordinates of the up and look vectors by that rotation matrix.

A change in roll is a rotation about the camera’s look-vector. A positive roll angle produces a roll to the left or a bank-left in an aircraft. Calculate

a rotation matrix about the look-vector, then transform the coordinates of the right and up vectors by that rotation matrix. For land-based cameras

the roll operation can be ignored.

A change in yaw is a rotation about the camera’s up-vector. A positive yaw angle produces a yaw or turn to the right. Calculate a rotation matrix

about the up-vector, then transform the coordinates of the right and look vectors by that rotation matrix. For land-based cameras, calculate the

Page 133: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 133 of 278

rotation matrix about the world’s y-axis. Since the y-axis and the up-vector are not necessarily the same, you must transform the up-vector by the

rotation matrix as well.

Motion Operations

Motion operations adjust the location of the camera. The three types of motion are walk (forward and back), strafe (left and right) and fly (up and

down).

The walk operation adds the look-vector to the position-vector. For a land-based walk, add only the x and z components of the look-vector.

The strafe operation adds the right-vector to the position-vector. For a land-based strafe, add only the x and z components of the right-vector.

The fly operation adds the up-vector to the position-vector. For a land-based fly, do nothing.

Creeping Error

A concern about this camera system is that the axis vectors – look, up, right – will eventually loose their orthogonality and their normality. If this

happens, distortion will occur in view transform and the precision of the movement will be compromised. An occasional correction will need to

be applied to the vectors.

Left-Hand Coordinate System Right-Hand Coordinate System

kk

k

u k r

uu

u

r u k

rr

r

kk =

k

u = r k

uu =

u

r = k u

rr =

r

Culling, Backface Backface culling is the process of removing polygons from the rendering pipeline whose backface is oriented towards the viewer.

Why?

There are two reasons for backface culling: speed and wireframe objects.

Speed

In the case of rendering solid 3D objects, the faces pointing towards the viewer obscure our view of the faces pointing away from the viewer. (e.g.

a cube always has a maximum of three faces visible to the viewer and a minimum of 3 faces not visible to the viewer.) By not rendering the non-

visible faces, a significant amount of processing can be avoided by rendering the visible faces only.

Page 134: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 134 of 278

Wireframe Objects

When an object is rendered as a wireframe model, the viewer can see through the object. It is often difficult to identify the correct orientation of

the object (i.e. an optical illusion.) Backface culling can remove the surfaces that would not be seen and as a result, the edges that are rendered in

wireframe.

How?

The backface of an object can be identified by generating a surface normal from three consecutive vertices on the surface (the vertices must not

be collinear.) The vertex winding will determine the direction of the surface normal generated (see Vertex Winding.)

Once a surface normal has be acquired we can determine whether the surface points toward the viewer by testing the inner product of the normal

vector and a vector drawn from the surface to the viewer.

Let n be the normal vector of the surface.

Let v be a vector originating on the surface and terminating at the viewer.

s n v

If 0s then the surface faces the viewer (i.e. frontface)

If 0s then the surface faces away from the viewer (i.e. backface)

If 0s then the viewer is on the surface (this condition is usually treated as a backface)

Which cull type is correct for Direct3D?

The cull type to use in Direct3D depends on a combination of the coordinate system and vertex winding.

Right handed coordinate system (+Z towards user)

Left handed coordinate system (+Z away from user)

Anti-clockwise winding D3DCULL_CW D3DCULL_CCW

Clockwise winding D3DCULL_CCW D3DCULL_CW

Mouse Look Mouse look is a relatively easy feature to implement if you already have a camera class.

I’ll assume that you already have a camera class with the following minimal interface.

+Pitch()

+Yaw()

+Run()

+Strafe()

Camera

Page 135: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 135 of 278

The run and strafe simply map the ‘W’ and ‘S’ keys to the Run method and ‘A’ and ‘D’ keys to the Strafe method.

The trickier part is the Pitch and Yaw that must be tied to the mouse’s movements. A DirectInput mouse will provide data indicating the distance

in screen coordinates that the mouse have moved since the last polling (either through a state object or by accumulating mouse events in buffered

input.) Map the screen coordinates to an angle indicating the amount of rotation or elevation. As a starting point use:

Axis Screen Units (SU) Angle () Formula

Horizontal (Yaw) ½ screen width (180) 2

1

2

su su

widthwidth

Vertical (Pitch) ½ screen height ½ (90) 1

1 2

2

su su

heightheight

Picking Picking is the process of mapping a physical screen location to logical location within the 3D world.

The process of picking starts with reading a value from the mouse or another pointing device that reports its location in screen coordinates. From

this location, we calculate a ray that runs from the eye of the viewer through that screen location. The ray is expressed in terms of the virtual or

logical 3D world. With this ray we iterate through the objects of the scene testing objects (or just triangles) until we find an object that it

intersects. Typically, we search these items in a nearest to farthest order.

Picking algorithm.

The picking ray is calculated in three steps:

calculate the point on the projection window (the near plane of the projection) represented by the physical point on the screen.

calculate the picking ray that shoots through the point on the projection window.

transform the picking ray and the objects into the same space.

test for intersection between the picking ray and the scene objects.

Sprite A sprite is a graphic image that can be moved about a larger graphical scene.

Sprites are most commonly used in 2D games and to implement the mouse pointer graphic in a GUI. Standard sprite operations include loading

and unloading a sprite, moving a sprite, blitting, and rotating the sprite image (like a cartoon animation).

Texel Texel is an abbreviation of texture element, a pixel-like element or colour value of a texture.

Page 136: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 136 of 278

Vertex Buffer A vertex buffer is an array of vertices typically located in video memory from which a graphics accelerator draws geometry with which is renders

primitives (points, lines and triangles).

In DirectX, vertex buffers are managed through the IDirect3DVertexBuffer9 interface.

Vertex Winding Vertex winding refers to the order in which vertices are listed when used to represent a surface (usually a triangle). Vertices are wound in either

clockwise or anti-clockwise order.

Counter-clockwise winding.

Clockwise winding.

Why?

By imposing a consistent vertex winding upon the vertices that define a surface in a 3D model, we can mathematically determine whether the front

side or the back side of a triangle presents itself to the viewer.

A surface normal (a vector perpendicular to the surface) can be generated with the following formula:

AB AC

B A C A

n

n

uuur uuur

The surface normal n, will point towards the viewer in a counter-clockwise wound triangle. In the clockwise wound triangle, surface normal n

will point away from the viewer.

The surface normal can then used to determine whether the front face or back face presents itself to the viewer. Back faces could be culled if

belonging to solid polyhedra.

Typically, right-handed coordinate systems prefer counter-clockwise winding and left-handed systems prefer clockwise winding.

AB

C

A

B

C

Page 137: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 137 of 278

Direct3D 9.0 Programming

Blitting Surface to Back Buffer

To blit images from a surface object to the back buffer, we must first ensure that the surface has been created in the D3DPOOL_SYSTEMMEM

memory pool.

IDirect3DSurface9* pBackBuffer = 0;

g_pd3dDevice->BeginScene();

g_pd3dDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );

g_pd3dDevice->UpdateSurface( g_pSurface, NULL, pBackBuffer, NULL );

pBackBuffer->Release();

g_pbd3dDevice->EndScene();

See also Images – Load as Surface

CopyRect

IDirect3DDevice8::CopyRects() (Direct3D 8.0) has been replaced by IDirect3DDevice9::UpdateSurface().

Direct3D9 Pipeline The specific and full details of the Direct3D rendering pipeline can confuse and impede a persons understanding of its operation. We will examine

the pipeline with the aid of several simplified models.

This model gives the steps in processing a fixed vertex format 3D geometry.

Page 138: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 138 of 278

World Space Transform

View Space Transform

Backface Culling

Lighting

Clipping

Projection Transform

Viewport Transform

Rasterization

Geometery recorded relative to a local coordinate system.

Pixels are recorded in framebuffer/z-buffer

The object is placed within the scene (world).

Matrix transform applied with D3DTS_WORLD.

The viewer (or camera) is placed within the scene.

Matrix transform applied with D3DTS_VIEW.

Vertex winding is used to determine frontface/backface.

Backfaces are culled (removed) from the render pipeline.

Lighting normals, colour values, etc. are generated.

Triangles are clipped to the projection frustum.

Either wholely are partially.

Matrix transform applied with D3DTS_PROJECTION.

Converts geometry from 3D to 2D (projects to near view plane).

Logical (now 2D) coordinates are converted to

physical device coordinates.

Triangles and lines are drawn into the frame buffer.

Page 139: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 139 of 278

The relationship between GPU activity and Video RAM resource use is modeled here:

Using Fixed-Function Processing Using Shaders

Vertex Buffer

Index Buffer

VB/IB

Transform &

Lighting

Rasterizer /

Interpolator

Texture Stage

Cascade

Z, Alpha, Stencil,

Fog

Texture

Depth / Stencil

Render Target

Command Input

Video RAM

Vertex Buffer

Index Buffer

VB/IB

Vertex Shader

Rasterizer /

Interpolator

Pixel Shader

Z, Alpha, Stencil,

Fog

Texture

Depth / Stencil

Render Target

Command Input

Video RAM

Texture (SM3)

Flexible Vertex Format Flexible Vertex Format (FVF) is a protocol for describing vertices to the Direct3D render pipeline. The challenge is to efficiently provide the

pipeline with multiple buffer formats. Sometimes we want to couple geometry with colour information, and at other times with texture and normal

information.

The FVF structure is composed off one or more of the following items and must be declared in the order presented.

Page 140: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 140 of 278

FVF Description Data Declarations D3DFVF_XYZ X, Y, Z coordinates of the vertex D3DXVECTOR3 v;

D3DFVF_XYZRHW X, Y, Z, RHW coordinates of the

vertex

D3DXVECTOR4 v;

D3DFVF_XYZW X, Y, Z, W coordinates of the

vertex

D3DXVECTOR4 v;

D3DFVF_NORMAL 3 element vector indicating the

surface normal at the vertex

FLOAT nx, ny, nz;

D3DXVECTOR3 n;

D3DFVF_PSIZE Vertex point size FLOAT psize;

D3DFVF_DIFFUSE Diffuse colour information DWORD color;

D3DCOLOR color;

D3DFVF_SPECULAR Specular colour information DWORD specular;

D3DCOLOR specular;

D3DFVF_TEXCOORDSIZE1(x)

D3DFVF_TEXCOORDSIZE2(x)

D3DFVF_TEXCOORDSIZE3(x)

D3DFVF_TEXCOORDSIZE4(x)

Texture coordinate information.

The size ordinal indicates the

dimension of the textures: 1D,

2D, 3D, 4D.

FLOAT tu;

D3DXVECTOR2 t;

D3DXVECTOR3 t;

D3DXVECTOR4 t;

Fog Fog is a visual effect that blends the colour of the objects in a scene with a chosen fog colour. The fog colour becomes proportionately greater as

the depth of the objects in the scene increases.

Fog is used for several different purposes other than actual fog. These include ambience, heat haze, dust, mist, or rain. One of the most common

uses of fog is to obscure distant objects as they come into the view volume. We don’t want users to see house that are sliced in half or street lamps

suspended from nothing (the post is just outside the view volume). Fog can blur these most distant objects enough that we will not have our

attention drawn to these anomalies. Fog may, in fact, completely obscure these problems.

Fog in Direct3D

Direct3D supports two types of fog, pixel fog and vertex fog. Vertex fog can employ range-based fog which uses a more complex calculation that

measures the distance from the viewpoint instead of the distance from the front of the view volume. This can eliminate some of the odder things

that occur when viewing depth-based fog.

Code Sample: linear range-based vertex fog float const start = 10.0f;

float const end = 30.0f;

pd3dDevice->SetRenderState( D3DRS_FOGENABLE, TRUE );

pd3dDevice->SetRenderState( D3DRS_FOGCOLOR, color );

pd3dDevice->SetRenderState( D3DRS_FOGTABLEMODE, D3DFOG_NONE );

pd3dDevice->SetRenderState( D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR );

pd3dDevice->SetRenderState( D3DRS_RANGEFOGENABLE, TRUE );

pd3dDevice->SetRenderState( D3DRS_FOGSTART, *reinterpret_cast<DWORD*>(&start) );

Page 141: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 141 of 278

pd3dDevice->SetRenderState( D3DRS_FOGEND, *reinterpret_cast<DWORD*>(&end) );

See Also

MSDN-DirectX SDK Help: DirectX Graphics → Programming Guide → Getting Started → Direct3D Rendering → Fog

Images

Load as Surface To load an image into a surface for the purpose of blitting:

IDirect3DSurface9* g_pSurface = 0;

D3DXIMAGE_INFO info;

D3DXGetImageFromFile( "image.jpg", &info );

g_pd3dDevice->CreateOffscreenPlainSurface( info.Width, info.Height, info.Format,

D3DPOOL_SYSTEMMEM, &g_pSurface, NULL );

D3DXLoadSurfaceFromFile( g_pSurface, NULL, NULL, "image.jpg", NULL, D3DX_DEFAULT, 0, NULL );

The critical detail in this code is the memory pool in which we will create and store the surface. We have chosen D3DPOOL_SYSTEMMEM since

we are blitting the surface to the back-buffer.

DX-SDK9.0c: Create in OnCreateDevice() and Release() in OnDestroyDevice().

DX-SDK9.0b: Create in InitDeviceObjects() and Release() in DeleteDeviceObjects().

See also Blitting – Surface to Back Buffer

Load as Texture To load an image into a texture object:

IDirect3DTexture9* g_pTexture = 0;

D3DXCreateTextureFromFile( g_pd3dDevice, "myImage.jpg", &g_pTexture );

DX-SDK 9.0c: Create in OnCreateDevice() and Release() in OnDestroyDevice().

DX-SDK 9.0b: Create in InitDeviceObjects() and Release() in DeleteDeviceObjects().

Lighting, Direct3D Types Direct3D supports four types of lights – ambient light, directional lights, point lights and spot lights.

Ambient Light

Ambient light is the environmental light that seems to come from no particular place or direction – its just there. Unlike the other three light types,

we do not need to set a D3DLIGHT9 to use ambient light. Ambient light is handled as part of a device’s render state.

pd3dDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_XRGB(32,32,32) );

Page 142: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 142 of 278

Directional Light

Directional lights are the simplest and least computationally expensive lights in Direct3D. They have

colour and direction, but no position – distance and attenuation have no effect on results.

Directional lights are used to simulate the lighting from a distance source such as the sun.

D3DLIGHT9 light;

// Initialize light properties

ZeroMemory( &light, sizeof(light) );

light.Type = D3DLIGHT_DIRECTIONAL;

light.Diffuse = D3DXCOLOR( … );

light.Specular = D3DXCOLOR( … );

light.Ambient = D3DXCOLOR( … );

light.Direction = D3DXVECTOR3( … ); // the direction the light will travel

// Enable the light

pd3dDevice->SetLight( 0, &light );

pd3dDevice->LightEnable( 0, true );

pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, true );

pd3dDevice->SetRenderState( D3DRS_LIGHTING, true );

Point Light

Point lights have a source, but no direction. Light emanates from a specified location within the scene’s world

coordinate system. Distance to the light source and attenuation are calculated. There is no single direction. Light is

provided equally in all directions from the source location.

D3DLIGHT9 light;

// Initialize light properties

ZeroMemory( &light, sizeof(light) );

light.Type = D3DLIGHT_POINT;

light.Diffuse = D3DXCOLOR( … );

light.Specular = D3DXCOLOR( … );

light.Ambient = D3DXCOLOR( … );

light.Position = D3DXVECTOR3( … ); // the location the light emanate from

light.Range = 100.0f; // don’t illuminate objects beyond 100 units

light.Attenuation1 = 1.0f; // simple attenuation

// Enable the light

pd3dDevice->SetLight( 0, &light );

pd3dDevice->LightEnable( 0, true );

pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, true );

pd3dDevice->SetRenderState( D3DRS_LIGHTING, true );

Page 143: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 143 of 278

Light Attenuation

Attenuation controls how a light’s intensity diminishes with distance. Attenuation is determined using the formula

2

0 1 2

1attenuation

att att d att d

where d is the distance from the light source to the vertex being lit.

The standard attenuation values (though not default) are0 1 20, 1, 0att att att . Under no circumstances

should all attenuation values be zero.

Spot Light

Spot lights are similar to point lights in that they have a position within the scene (expressed in world

coordinates). They differ, however, in that they do not emanate in all directions, but have instead a

specific direction.

D3DLIGHT9 light;

// Initialize light properties

ZeroMemory( &light, sizeof(light) );

light.Type = D3DLIGHT_SPOT;

light.Diffuse = D3DXCOLOR( … );

light.Specular = D3DXCOLOR( … );

light.Ambient = D3DXCOLOR( … );

light.Direction = D3DXVECTOR3( … ); // the direction the light will travel

light.Position = D3DXVECTOR3( … ); // the location the light emanate from

light.Range = 100.0f; // don’t illuminate objects beyond 100 units

light.Attenuation1 = 1.0f; // simple attenuation

light.Falloff = 1.0f; // rate that cone diminishes

light.Theta = D3DX_PI / 20.0f; // inner cone

light.Phi = D3DX_PI / 10.0f; // outer cone

// Enable the light

pd3dDevice->SetLight( 0, &light );

pd3dDevice->LightEnable( 0, true );

pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, true );

pd3dDevice->SetRenderState( D3DRS_LIGHTING, true );

Performance

Each light type has performance consequences for your application. In general the light types exhibit the following performance levels:

Lowest cost Ambient

Low cost Directional

High cost Spot light†

Highest cost Point light†

innercone

outercone

Page 144: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 144 of 278

†This depends on the amount of objects illuminated. Spot lights can have a higher cost than point lights if they illuminate large numbers of

objects.

General Light Tips

1. Minimize the number of light sources.

2. Prefer ambient light to more lights to increase overall light level in a scene.

3. Use the range parameter to limit a light to the parts of the scene that matters. This is particularly effective with spot lights.

4. Disable specular highlights. Specular highlight typically double the cost of a lighting effect.

5. Set D3DRS_LOCALVIEWER to false with orthographic projections. This will decrease the cost of the halfway vector calculations.

Meshes

Definition

A mesh is a collection of vertices defining some geometry; a set of indices defining the triangular faces and a set of attribute groups to differentiate

the material properties and textures of the faces.

D3DX supports four types of meshes, the standard mesh – ID3DXMesh, progressive meshes – ID3DXPMesh, simplification meshes –

ID3DXSPMesh and skinned meshes – ID3DXSkinMesh.

+CloneMesh()

+DrawSubset()

«interface»

ID3DXBaseMesh

«interface»

ID3DXPMesh

+CloneMesh()

«interface»

ID3DXSPMesh

«interface»

ID3DXMesh

Usage

Meshes are collections of vertices, face indices and attributes groups. We can decompose meshes into subsets on the base of attributes as in this

‘boat’ example.

Boat

Subset 0 - Hull Subset 1 - Mast Subset 2 - Sail

We can also decompose meshes into vertices, face indices and subset attribute groups.

Page 145: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 145 of 278

2...40

Attribute Buffer: specifies subset

...320210 232221

...3210 23

Vertex Buffer: specifies geometery

Index Buffer: specifies vertex

Triangle 0 Triangle 1 Triangle 11

Coding struct TVertex

{

D3DXVECTOR3 xyz;

D3DXVECTOR3 nor;

D3DXVECTOR2 tex;

static const DWORD FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;

TVertex() { }

TVertex( FLOAT x, FLOAT y, FLOAT z, FLOAT nx, FLOAT ny, FLOAT nz, FLOAT t, FLOAT u )

: xyz(x,y,z), nor(nx,ny,nz), tex(t,u) { }

};

ID3DXMesh* pMesh;

IDirect3DTexture9* apTextures[nSubsets];

D3DXCreateMeshFVF( nFaces, nVertices, D3DXMESH_MANAGED, TVertex::FVF, m_pd3dDevice, &pMesh );

TVertex* v = 0;

pMesh->LockVertexBuffer( 0, (void**)&v );

v[0] = …;

v[nVertices-1] = …;

pMesh->UnlockVertexBuffer();

// create index buffer for the mesh

WORD* ind = 0;

pMesh->LockIndexBuffer( 0, (void**)&ind );

ind[0] = …;

ind[nFaces * 3 – 1] = …;

pMesh->UnlockIndexBuffer();

// assign triangles to subsets

DWORD* attr = 0;

pMesh->LockAttributeBuffer( 0, &attr );

Page 146: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 146 of 278

attr[0] = …;

attr[nFaces - 1] = …;

pMesh->UnlockAttributeBuffer();

// rendering

m_pd3dDevice->BeginScene();

for( int i = 0; i != nSubsets; ++i )

{

m_pd3dDevice->SetTexture( 0, apTextures[ i ] );

pMesh->DrawSubset( i );

}

m_pd3dDevice->EndScene();

// cleanup

for( int i = 0; i != nSubsets; ++i )

apTextures[i]->Release();

pMesh->Release();

Optimization

The advantage of meshes is primary, their easy of use. However, this simplicity often results in inefficient ordering of vertices or primitives.

Recognizing this problem, the ID3DXMesh developers offer several mesh optimizations.

OptimizeInplace()

The simplest method for optimization is in-place optimization. Unlike ID3DXMesh::Optimize(), a new mesh is not created, but instead the

existing mesh is optimized in its current location. All that is required is an adjacency list and hints as to how the mesh should be optimized.

The adjacency list, which is normally generated from the initial mesh, contains information about face relationship. The list contains three entries

per face in the mesh. Each trio contains the face indices of triangles that share a common edge with that triangle.

The hints can be any of the following:

D3DXMESHOPT_COMPACT – This removes indices and vertices that are unreferenced by the mesh.

D3DXMESHOP_ATTRSORT – Sorts the faces by attribute. This will enhance the performance of DrawSubset commands.

D3DXMESHOPT_VERTEXCACHE – Increases the probability of a hit on the vertex cache.

D3DXMESHOPT_STRIPREORDER – Reorganizes the indices to maximize the length of triangle strips. This option cannot be used in

combination with D3DXMESHOPT_VERTEXCACHE.

D3DXMESHOPT_IGNOREVERTS – Optimize indices without optimizing vertices.

Page 147: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 147 of 278

Coding (continued from previous example) // optimize mesh and produce an attribute table

std::vector<DWORD> adjacencyBuffer( m_pMesh->GetNumFaces() * 3 );

m_pMesh->GenerateAdjacency( 0.0f, &adjacencyBuffer[0] );

m_pMesh->OptimizeInplace( D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT |

D3DXMESHOPT_VERTEXCACHE, &adjacencyBuffer[0], 0, 0, 0 );

Primitives Primitives are the simplest graphical object that the system can render. Complex scenes are rendered by combining primitives to form more

elaborate objects.

In DirectX, primitives are points, lines and triangles. Primitives are described by vertex data and are usually grouped into collections. These

collections then impose an order or context for interpreting the relationship between individual vertices. The most common collections are lists,

fans, strips and meshes4. Most graphics systems also permit the order of vertices in a list to be determined by a separate index list.

Points – D3DPT_POINTLIST

Each vertex produces 1 point on

the display

nPoints nVertices

.

.

...

.

.

.

Lines – D3DPT_LINELIST

Vertices are taken in pairs to produce

a series of straight lines

2

nVerticesnLines

Lines – D3DPT_LINESTRIP

Vertices are connected one to the

next until the last vertices is reached.

1nLines nVertices

4 Meshes are typically handled by higher-level objects and not the graphics core.

Page 148: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 148 of 278

Triangles –

D3DPT_TRIANGLELIST

Vertices are taken in triplets to

produce a series of triangles.

3

nVerticesnTriangles

Triangles –

D3DPT_TRIANGLESTRIP

The first triangle is formed from the

first three vertices. Successive

triangles are formed from the last

two vertices of the last triangle

rendered and a new vertex.

2nTriangles nVertices

A

B

C

D

E

F

G

H

Triangles –

D3DPT_TRIANGLEFAN

The first triangle is formed from the

first three vertices. Successive

triangles are formed from the last

vertex of the last triangle, a new

vertex and the first vertex.

2nTriangles nVertices

AB

C D E

F

Primitives can also be rendered with colour, lighting, textures, cell, vertex and pixel shaders.

Rendering Primitives Rendering primitives in Direct3D is a three-step process:

1. Defining a vertex structure.

Page 149: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 149 of 278

2. Identifying a source of vertex data.

3. Calling IDirect3DDevice::DrawPrimitive*()

However, step two can be quite elaborate if vertex data is indexed and/or stored in video memory.

Method 1: user memory pointer.

The simplest method for drawing a primitive is also the least efficient, but we can get straight to drawing.

In step one; we must create a vertex structure. Here we create a transformed5 vertex structure.

struct TVertex {

FLOAT x, y, z, rhw;

DWORD color;

static const DWORD FVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE;

};

D3DX objects can also be used to simplify the vertex declaration.

struct TVertex {

D3DXVECTOR4 ver;

D3DCOLOR color;

static const DWORD FVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE;

};

The static constant is not stored as part of the vertex, but is accessible through the structure name; i.e. TVertex::FVF.

We inform the Direct3D run-time of our choice of vertex format with the IDirect3DDevice9::SetFVF() method.

In step two; we identify a source for vertex data. We can simply load an array with the appropriate data.

TVertex vertices[] = {

D3DXVECTOR4( 150.0f, 50.0f, 0.5f, 1.0f ), D3DCOLOR_ARGB( 255,255,0,0 ),

D3DXVECTOR4( 50.0f, 250.0f, 0.5f, 1.0f ), D3DCOLOR_ARGB( 255,0,0,255 ),

D3DXVECTOR4( 250.0f, 250.0f, 0.5f, 1.0f ), D3DCOLOR_ARGB( 255,0,255,0 ),

};

These vertices define a triangle with red, green and blue corners.

The third and last step is render the primitive with the IDirect3DDevice9::DrawPrimitiveUP() method. We must identify the type of

primitive to draw (more than one type can be generated from the same list of vertices) and the number of primitives to draw. We must also pass

the vertex stride. The stride is the number of bytes from the beginning of one vertex in the array to the beginning of the next vertex in the array.

Sometimes we ignore some the information packed in the vertex structure and we want the graphics core to jump over it in the list.

To draw a triangle from what we have, we must issue the DrawPrimiteUP within a BeginScene/EndScene pair. The complete code of an

OnFrameRender() would be:

void CALLBACK OnFrameRender( IDirect3DDevice9* pdev, double /*time*/, float /*elapsedTime*/ )

{

5 Transformed vertices do not require (or use) projection, view or world matrix transforms to be visible, however, they also cannot be rendered with lighting as

they are incompatible is surface normals.

Page 150: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 150 of 278

pdev->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,

D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );

if( SUCCEEDED( pdev->BeginScene() ) )

{

TVertex vertices[] = {

D3DXVECTOR4( 150.0f, 50.0f, 0.5f, 1.0f ), D3DCOLOR_ARGB( 255,255,0,0 ),

D3DXVECTOR4( 50.0f, 250.0f, 0.5f, 1.0f ), D3DCOLOR_ARGB( 255,0,0,255 ),

D3DXVECTOR4( 250.0f, 250.0f, 0.5f, 1.0f ), D3DCOLOR_ARGB( 255,0,255,0 ),

};

int nVertices = sizeof( vertices ) / sizeof( vertices[0] );

pdev->SetFVF( TVertex::FVF );

pdev->DrawPrimitiveUP( D3DPT_TRIANGLELIST, nVertices/3, (void*)vertices,

sizeof(TVertex) );

pdev->EndScene();

}

}

To draw the vertices as a line strip use:

pdev->DrawPrimitiveUP( D3DPT_LINESTRIP, nVertices-1, (void*)vertices,

sizeof(TVertex) );

Method 2: vertex buffer.

For this example we will use a global vertex buffer interface pointer:

IDirect3DVertexBuffer9* g_pVB = NULL;

The vertex buffer is created in OnResetDevice().

TVertex vertices[] = {

{ 150.0f, 50.0f, 0.5f, 1.0f, 0xffff0000, }, // x, y, z, rhw, color

{ 250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, },

{ 50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, },

};

V_RETURN( pd3dDevice->CreateVertexBuffer( 3 * sizeof(TVertex), 0, TVertex::FVF,

D3DPOOL_DEFAULT, &g_pVB, NULL ) );

VOID* pVertices = NULL;

V_RETURN( g_pVB->Lock( 0, sizeof(vertices), &pVertices, 0 ) );

memcpy( pVertices, vertices, sizeof(vertices) );

g_pVB->Unlock();

The vertex buffer is destroyed in OnLostDevice().

SAFE_RELEASE( g_pVB );

And rendered in OnFrameRender().

Page 151: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 151 of 278

if( SUCCEEDED( pd3dDevice->BeginScene() ) )

{

// Render a triangle

pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(TVertex) );

pd3dDevice->SetFVF( TVertex::FVF );

pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );

V( pd3dDevice->EndScene() );

}

Sprites – ID3DXSprite The ID3DXSprite object works in concert with IDirect3DTexture9 objects to provide a rudimentary sprite engine for Direct3D.

Setup

The ID3DXSprite object is created on an IDirect3DDevice9 object. If the IDirect3DDevice9 object is lost we should call

ID3DXSprite::OnLostDevice() to cleanup the sprite object’s state in preparation for a device reset. After reset, we can call

ID3DXSprite::OnResetDevice() to ready the sprite object for rendering.

The location at which a sprite will be drawn is determined by a set of transform methods.

SetTransform( D3DXMATRIX* ) – an all-in-one world-space transform setup.

SetWorldViewLH( D3DXMATRIX* pWorld, D3DXMATRIX* pView ) – customizes the world and view transforms for a left-hand

system.

SetWorldViewRH( D3DXMATRIX* pWorld, D3DXMATRIX* pView ) – customizes the world and view transforms for a right-hand

system.

The last two transforms are only required if the sprite is rendering using D3DXSPRITE_BILLBOARD, D3DXSPRITE_SORT_DEPTH_xxxx.

The transforms are stored in the object’s state and can be initialized prior to rendering.

Rendering g_pSprite->Begin( 0 );

g_pSprite->Draw( g_pTexture, NULL, NULL, NULL, 0xFFFFFFFF );

g_pSprite->End();

Textures with an alpha channel can be rendered by changing the parameter of ID3DXSprite::Begin() to D3DXSPRITE_ALPHABLEND.

DX-SDK 9.0c: Call D3DXCreateSprite() in OnCreateDevice() and release in OnDestroyDevice(). Call

ID3DXSprite::OnLostDevice() in OnLostDevice() and ID3DXSprite::OnResetDevice() in OnResetDevice().

DX-SDK 9.0b: Call D3DXCreateSprite() in InitDeviceObjects() and release in DeleteDeviceObjects(). Call

ID3DXSprite::OnLostDevice() in InvalidateDeviceObjects() and ID3DXSprite::OnResetDevice() in

RestoreDeviceObjects().

Page 152: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 152 of 278

Surfaces – Direct writes to the back-buffer DirectX 9.0

By default, the back buffer in DirectX is not directly writable. To make the back-buffer writable we must create the device with the presentation

parameter D3DPRESENTFLAG_LOCKABLE_BACKBUFFER.

DX-SDK9.0c: To create a device with a lockable back-buffer, you’ll have to write a ModifyDeviceSettings callback function and register it in the

call to DXUTCreateDevice().

void CALLBACK ModifyDeviceSettings( DXUTDeviceSettings *pDeviceSettings,

const D3DCAPS9* pCaps )

{

pDeviceSettings->pp.Flags |= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;

}

The back buffer’s actual location in video RAM is not fixed, so writing to it will require locking the buffer and acquiring a pointer to the buffer

once locked. This cannot be done while a scene is being rendered as BeginScene() locks the back buffer itself.

The code for locking and accessing the back buffer is:

IDirect3DSurface9* pBackBuffer = 0;

if( SUCCEEDED( pd3dDevice->GetBackBuffer( 0/*swap-chain*/, 0 /* first back buffer */,

D3DBACKBUFFER_TYPE_MONO, &pBackBuffer ) ) )

{

D3DLOCKED_RECT lockedRect;

pBackBuffer->LockRect( &lockedRect, NULL /* entire surface */, 0 );

And the code to unlock and release the back buffer is:

pBackBuffer->UnlockRect();

pBackBuffer->Release();

}

Once locked the D3DLOCKED_RECT object will contain a pointer to the back-buffer: pBits and the number of bytes in a single row or line of

back-buffer: Pitch. The location of a specific pixel can be calculated using the following byte-offset formula:

byteoffset y pitch x bytesperpixel

This byte offset is then added to pBits – the address of the beginning of the back-buffer.

Since the resulting address is of type void*, we cannot dereference it. We must first convert to a pointer of the correct size for the current pixel

colour depth. (e.g. a 32-bit colour scheme would use type INT32, DWORD, or unsigned long. Any of the 32-bit integer types.)

int byteOffset = y * lockedRect.Pitch + x * sizeof(INT32);

void* address = lockedRect.Pitch + byteOffset;

INT32* p = reinterpret_cast<INT32*>( address );

Finally, the colour can be written to the pixel’s memory location.

*p = (INT32)color;

Page 153: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 153 of 278

Tuning Tips (Optimization)

Lighting

1. When multiple light models can achieve the same effect, prefer:

a. ambient lighting to all others.

b. directional lighting to spot or point lighting.

c. spot lighting to point lighting when there are few objects caught by the light source.

d. point lighting to spot lighting when there are many objects caught by the light source.

2. Use ambient lighting to control the overall brightness of a scene.

3. Minimize the number of light sources.

4. Use the range parameter to limit a point or spot light to the part of the scene that matters.

5. Disable specular highlights.

6. Set D3DRS_LOCALVIEWER to false with orthographic projections. This will decrease the cost of the halfway vector calculations.

Textures

1. Texture load time can be improved by scaling and formatting images with a photo-editing tool.

2. Some hardware requires power-of-2 dimensions (e.g. 256 × 256), so store textures in a power-of-2 dimension.

3. Use Microsoft’s DDS format to store images. DDS can store any DirectX 9.0 texture format including mipmaps. It is also the easiest format

for D3DX to read. Its mipmap storage capabilities allow you use mipmap generation algorithms that may be more advanced than D3DX’s

algorithm.

4. Resample textures to a smaller size, thereby reducing the number of texels processed when mapping to a surface.

Direct3D 10.0 Programming

API Differences between Direct3D 9 and Direct3D 10

Direct3D 9 Direct3D 10

IDirect3DDevice9 ID3D10Device – methods are prefixed to indicate subsystem.

IA = Input Assembler

VS = Vertex Shader

GS = Geometry Shader

Page 154: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 154 of 278

SO = Stream Out

RS = Rasterizer Stage

PS = Pixel Shader

OM = Output Merger

IDirect3D9 IDXGIFactory, IDXGIAdapter, IDXGIDevice

IDirect3DDevice9::Present IDXGISwapChain::Present

IDirect3DDevice9::TestCooperativeLevel IDXGISwapChain::Present with PRESENT_TEST

IDirect3DBaseTexture9

IDirect3DTexture9

IDirect3DCubeTexture9

IDirect3DVolumeTexture9

IDirect3DIndexBuffer9

IDirect3DVertexBuffer9

ID3D10Buffer

ID3D10Texture1D

ID3D10Texture2D

ID3D10Texture3D

IDirect3DVertexShader9 ID3D10VertexShader

IDirect3DPixelShader9 ID3D10PixelShader

N/A ID3D10GeometryShader

IDirect3DVertexDeclaration9 ID3D10InputLayout

IDirect3DDevice9::SetRenderState ID3D10BlendState

ID3D10DepthStencilState

ID3D10RasterizerState

IDirect3DDevice9::SetTextureStageState ID3D10SamplerState

IDirect3DDevice9::DrawIndexedPrimitive

IDirect3DDevice9::DrawPrimitive

ID3D10Device::Draw

ID3D10Device::DrawIndexed

ID3D10Device::DrawIndexedInstanced

ID3D10Device::DrawInstanced

ID3D10Device::IASetPrimitiveTopology

Triangle fans are no longer supported

Page 155: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 155 of 278

N/A ID3D10Device::DrawAuto

IDirect3DDevice9::BeginScene

IDirect3DDevice9::EndScene

IDirect3DDevice9::PrimitiveUP

IDirect3DDevice9::DrawIndexedPrimitiveUP

Removed

IDirect3DDevice9::ShowCursor

IDirect3DDevice9::SetCursorPosition

IDirect3DDevice9::SetCursorProperties

Removed: Win32 mouse cursors now work with Direct3D

IDirect3DDevice9::Reset No more LOST DEVICE cases

IDirect3DDevice9::DrawRectPatch

IDirect3DDevice9::DrawTriPatch

IDirect3DDevice9::LightEnable

IDirect3DDevice9::MultiplyTransform

IDirect3DDevice9::SetLight

IDirect3DDevice9::SetMaterial

IDirect3DDevice9::SetNPatchMode

IDirect3DDevice9::SetTransform

IDirect3DDevice9::SetFVF

Removed

IDirect3DDevice9::CheckDepthStencilMatch

IDirect3DDevice9::CheckDeviceFormat

IDirect3DDevice9::GetDeviceCaps

IDirect3DDevice9::ValidateDevice

Cap bits removed.

Only a few formats usage cases are optional. Check with

ID3D10Device::CheckFormatSupport

File Formats

RAW RAW files have the simplest format for storing graphics image data. RAW files contain pixel data only. The only variation in the format is the

number of bits or bytes used to store a single pixel. The most common pixel size is a single byte per pixel.

Page 156: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 156 of 278

RAW files are useful since there is no header to decode (or bypass), no compression and no encryption. Raw files are simple! Loading a RAW

file usually requires a single function call.

The down-side of RAW files is that the application must acquire information about the dimensions of the image from another source (or have the

information hard-coded).

Organization

RAW files usually represent two-dimensional images.

However, the data is stored as a one-dimensional vector. By convention, graphical image editors

such as Adobe Photoshop interpret the first element as the top-left pixel. The next element is the

second pixel in the first row. The last element is the bottom-right pixel.

A mapping from x, y coordinates to offsets and back can be produced if an image width can be

assumed.

xowpixelsPerRyoffset or,

colowpixelsPerRrowoffset

And the reverse…

owpixelsPerR

offsetyrow

owpixelsPerRoffsetxcol mod

X-file Direct3D

Introduction

X files were introduced in DirectX 2.0 with a binary format appearing in DirectX 3.0. DirectX 6.0 introduced interfaces that facilitated reading

from and writing to .x files.

X files enable a DirectX programmer to store:

meshes

textures

animations

user-defined objects

X files are template driven and support instancing (multiple references to an object) and hierarchies.

0,0:0 63,0:63

63,63:40950,63:4032A 4KB RAW file showing

x,y:offset.

Width and height are 64 pixels

Page 157: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 157 of 278

Format

X files use this format:

1. header

2. user templates

3. data objects

Header

For a text-based x file (the only format we will discuss), the header is composed of the ‘magic-number’, the version numbers, encoding tag and

float size indicator.

e.g. xof 0303txt 0032

magic number xof ‘x’ object file

major version number 03 latest version as of DirectX

9.0

minor version number 03 latest version as of DirectX

9.0

encoding tag txt Text encoding

float size indicator 0032 use IEEE 32-bit floats

Data Objects

A comprehensive list of data objects can be found in the DirectX SDK Help.

DirectX Graphics

Reference

X File Reference

X File Format Reference

X File Templates

Mesh

The most common x file template is the mesh.

A general format is:

Mesh meshname {

number-of-vertices;

x0; y0; z0;,

x1; y1; z1;,

xn-1; yn-1; zn-1;;

Page 158: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 158 of 278

number-of-faces;

3; a0, b0, c0;,

3; a1, b1, c1;,

3; an-1, bn-1, cn-1;;

MeshMaterialList {

number-of-materials;

number-of-faces;

materialf0, // material for face 0

materialf1, // material for face 1

materialfn-1; // material for the last face

Material {

red; green; blue; alpha; ; // face color

shininess;

red; green; blue; // specular

red; green; blue; // emissive

}

}

}

Example:

xof 0303txt 0032

Mesh Square {

4; // number of vertices

-1.0; -1.0; 0.0;, // vertex 0

-1.0; 1.0; 0.0;, // vertex 1

1.0; 1.0; 0.0;, // vertex 2

1.0; -1.0; 0.0;; // vertex 3

2; // number of triangles

3;0,1,2;, // triangle #1

3;0,2,3;; // triangle #2

MeshMaterialList {

1; // one material

2; // two faces

0, // face #0 use material #0

0;;

Material

{

0.0; 1.0; 0.0; 1.0;; // face color

0.0; // power

0.0; 0.0; 0.0;; // specular

0.0; 0.0; 0.0;; // emissive color

}

}

}

Page 159: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 159 of 278

Materials

Materials can be placed outside of a Mesh block then referenced by name.

Material materialname {

red; green; blue; alpha; ; // face color

shininess;

red; green; blue; // specular

red; green; blue; // emissive

}

Mesh meshname {

number-of-vertices;

x0; y0; z0;,

x1; y1; z1;,

xn-1; yn-1; zn-1;;

number-of-faces;

3; a0, b0, c0;,

3; a1, b1, c1;,

3; an-1, bn-1, cn-1;;

MeshMaterialList {

number-of-materials;

number-of-faces;

materialf0, // material for face 0

materialf1, // material for face 1

materialfn-1; // material for the last face

{materialname}

}

}

Normals

Normals can be recorded as part of the mesh data;

Mesh meshname {

number-of-vertices;

x0; y0; z0;,

x1; y1; z1;,

xn-1; yn-1; zn-1;;

number-of-faces;

3; a0, b0, c0;,

3; a1, b1, c1;,

3; an-1, bn-1, cn-1;;

MeshNormals {

Page 160: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 160 of 278

number-of-normals;

x0; y0; z0;,

x1; y1; z1;,

xn-1; yn-1; zn-1;;

}

}

Example xof 0303txt 0032

Material Red {

1.0;0.0;0.0;0.0;;

0.0;

1.0;0.0;0.0;;

0.0;0.0;0.0;;

}

Material Green {

0.0;1.0;0.0;0.0;;

0.0;

1.0;0.0;0.0;;

0.0;0.0;0.0;;

}

Material Blue {

0.0;0.0;1.0;0.0;;

0.0;

1.0;0.0;0.0;;

0.0;0.0;0.0;;

}

Mesh Cube {

24;

-1.0;-1.0;-1.0;,

-1.0;-1.0;1.0;,

-1.0;1.0;1.0;,

-1.0;1.0;-1.0;,

-1.0;1.0;-1.0;,

-1.0;1.0;1.0;,

1.0;1.0;1.0;,

1.0;1.0;-1.0;,

1.0;1.0;-1.0;,

1.0;1.0;1.0;,

1.0;-1.0;1.0;,

1.0;-1.0;-1.0;,

-1.0;-1.0;1.0;,

-1.0;-1.0;-1.0;,

1.0;-1.0;-1.0;,

1.0;-1.0;1.0;,

Page 161: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 161 of 278

-1.0;-1.0;1.0;,

1.0;-1.0;1.0;,

1.0;1.0;1.0;,

-1.0;1.0;1.0;,

-1.0;-1.0;-1.0;,

-1.0;1.0;-1.0;,

1.0;1.0;-1.0;,

1.0;-1.0;-1.0;;

12;

3;0,1,2;,

3;2,3,0;,

3;4,5,6;,

3;6,7,4;,

3;8,9,10;,

3;10,11,8;,

3;12,13,14;,

3;14,15,12;,

3;16,17,18;,

3;18,19,16;,

3;20,21,22;,

3;22,23,20;;

MeshNormals {

24;

-1.000000;0.000000;0.000000;,

-1.000000;0.000000;0.000000;,

-1.000000;0.000000;0.000000;,

-1.000000;0.000000;0.000000;,

0.000000;1.000000;0.000000;,

0.000000;1.000000;0.000000;,

0.000000;1.000000;0.000000;,

0.000000;1.000000;0.000000;,

1.000000;0.000000;0.000000;,

1.000000;0.000000;0.000000;,

1.000000;0.000000;0.000000;,

1.000000;0.000000;0.000000;,

0.000000;-1.000000;0.000000;,

0.000000;-1.000000;0.000000;,

0.000000;-1.000000;0.000000;,

0.000000;-1.000000;0.000000;,

0.000000;0.000000;1.000000;,

0.000000;0.000000;1.000000;,

0.000000;0.000000;1.000000;,

0.000000;0.000000;1.000000;,

0.000000;0.000000;-1.000000;,

0.000000;0.000000;-1.000000;,

0.000000;0.000000;-1.000000;,

0.000000;0.000000;-1.000000;;

12;

3;0,1,2;,

3;2,3,0;,

Page 162: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 162 of 278

3;4,5,6;,

3;6,7,4;,

3;8,9,10;,

3;10,11,8;,

3;12,13,14;,

3;14,15,12;,

3;16,17,18;,

3;18,19,16;,

3;20,21,22;,

3;22,23,20;;

}

MeshMaterialList {

3;

12;

0,

0,

1,

1,

0,

0,

1,

1,

2,

2,

2,

2;

{Red}

{Green}

{Blue}

}

VertexDuplicationIndices {

24;

8;

0,

1,

2,

3,

3,

2,

6,

7,

7,

6,

10,

11,

1,

0,

11,

10,

Page 163: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 163 of 278

1,

10,

6,

2,

0,

3,

7,

11;

}

}

Sample Framework DX-SDK 9.0c Install the EmptyProject sample from the DirectX Sample Browser.

The minimal functioning complete main is:

#include "dxstdafx.h"

#include "resource.h"

INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )

{

DXUTInit();

DXUTCreateWindow();

DXUTCreateDevice();

DXUTMainLoop();

return DXUTGetExitCode();

}

Page 164: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 164 of 278

Sequence of events

Changing the window caption DXUTCreateWindow( L"DX9cFramework" );

Note that the string is a Unicode string.

DXUTCreateWindow

DXUTCreateDevice

RegisterClassEx()

CreateWindow()

ShowWindow()

UpdateWindow()

creates IDirect3D9 object

enumerates devices

chooses optimal mode

creates IDirect3DDevice9 object

OnCreateDevice()

OnResetDevice()

DXUTMainLoop()Win32 message pump

Normal execution

OnLostDevice()

OnDestroyedDevice()

Window resize

OnLostDevice()

Resize

OnResetDevice()

OnLostDevice()

Mode Change

OnResetDevice()

OnDestroyedDevice()

OnCreatedDevice()

OnFrameMove()

OnFrameRender()

Mode change

Quit

Page 165: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 11

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 165 of 278

Default Framework Windows Message Handler

The default message handler installed by the framework handles the following messages:

WM_KEYDOWN

WM_SYSKEYDOWN

WM_KEYUP

WM_SYSKEYUP

WM_LBUTTONDOWN

WM_LBUTTONUP

WM_LBUTTONDBLCLK

WM_MBUTTONDOWN

WM_MBUTTONUP

WM_MBUTTONDBLCLK

WM_RBUTTONDOWN

WM_RBUTTONUP

WM_RBUTTONDBLCLK

WM_XBUTTONDOWN

WM_XBUTTONUP

WM_XBUTTONDBLCLK

WM_MOUSEWHEEL

WM_MOUSEMOVE

WM_PAINT

WM_SIZE

WM_GETMINMAXINFO

WM_ENTERSIZEMOVE

WM_EXITSIZEMOVE

WM_SETCURSOR

WM_ACTIVATEAPP

WM_ENTERMENULOOP

WM_EXITMENULOOP

WM_NCHITTEST

WM_POWERBROADCAST

WM_SYSCOMMAND

WM_SYSCHAR

WM_CLOSE

WM_DESTROY

Custom device setting on start-up

A full screen 800x600 display can be the starting resolution with the line:

DXUTCreateDevice( D3DADAPTER_DEFAULT, false, 800, 600 );

Showing the cursor full screen

Place the line:

DXUTSetCursorSettings( true, true );

Before the line:

DXUTInit();

Rendering

Rendering is accomplished by registering a render callback function. This function has the signature:

void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice,

double fTime, float fElapsedTime )

This function is called once per frame or during a WM_PAINT.

We register the function with the statement:

DXUTSetCallbackFrameRender( OnFrameRender );

The callback registration must occur before the main loop (message pump) is executed.

NOTE: This is the point at which the V( ) macro is first used. The V( ) macro requires that a local scope variable of the type HRESULT with the

identifier ‘hr’ be defined.

Text

Render text requires the creation and management of a font object. The framework does not provide a font object but readily supports the D3DX

object ID3DXFont.

Page 166: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 166 of 278

The font object requires an IDirect3DDevice9 object during creation and also need attention during device reset and device loss. Callback

functions must be registered for object creation and maintenance. Place the following the ‘WinMain’ function:

DXUTSetCallbackDeviceCreated( OnCreateDevice );

DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );

DXUTSetCallbackDeviceReset( OnResetDevice );

DXUTSetCallbackDeviceLost( OnLostDevice );

Declare a global font object:

ID3DXFont* g_pFont = NULL; // Font for drawing text

The create the following functions containing the font creation and maintenance code:

HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice,

const D3DSURFACE_DESC* pBackBufferSurfaceDesc )

{

HRESULT hr;

// Initialize the font

V_RETURN( D3DXCreateFont( pd3dDevice, 15, 0, FW_BOLD, 1, FALSE,

DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,

DEFAULT_PITCH | FF_DONTCARE, L"Arial", &g_pFont ) );

return S_OK;

}

HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice,

const D3DSURFACE_DESC* pBackBufferSurfaceDesc )

{

HRESULT hr;

if( g_pFont )

V_RETURN( g_pFont->OnResetDevice() );

return S_OK;

}

void CALLBACK OnLostDevice()

{

if( g_pFont )

g_pFont->OnLostDevice();

}

void CALLBACK OnDestroyDevice()

{

SAFE_RELEASE( g_pFont );

}

GUI Controls

GUI Controls can be added to your system using the CDXUTDialog framework.

Create a dialog object:

CDXUTDialog g_GUI;

Page 167: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 167 of 278

This object serves the same purpose as a Windows dialog box. It hosts a set of controls and manages their I/O playing host to their message

handler.

Next we’ll add a control to the dialog. We’ll add a button that toggles between full-screen and windowed mode. In the application initialization

function (performed before the window is created), issue the following command.

g_GUI.AddButton( IDC_TOGGLEFULLSCREEN, L"Toggle full screen", X, Y, W, H );

IDC_TOGGLEFULLSCREEN is an ordinal (I use an enum) identifying the control. The X and Y coordinates are relative to the dialog location

which defaults to the location (0, 0).

The control must now be rendered by issuing the command:

V( g_GUI.OnRender( fElapsedTime ) );

Place this command in your OnFrameRender method between calls to BeginScene and EndScene.

This dialog location by default anchors on the top-left corner of the display. We can change this by resetting the dialog anchor in the

OnResetDevice callback.

g_GUI.SetLocation( pBackBufferSurfaceDesc->Width-125, 0 );

You will notice at this point that the control is inactive. We must redirect mouse and keyboard events to the dialog to get a response. For this we

need a custom message handler for the application. The callback and registration look like this.

LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,

bool* pbNoFurtherProcessing )

{

// Give the dialogs a chance to handle the message first

*pbNoFurtherProcessing = g_GUI.MsgProc( hWnd, uMsg, wParam, lParam );

if( *pbNoFurtherProcessing )

return 0;

return 0;

}

DXUTSetCallbackMsgProc( MsgProc );

This callback is called prior to the frameworks own application window message handler. The if(*pbNoFurtherProcessing) statement

provided to stop the framework from processing message that has already been consumed by a previous handler.

Next, we must create and register an event handler for the GUI. The event handler signature is:

void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl );

For now we’ll just use the second parameter ‘int nControlID’ to identify the button that we had created in a handler that toggles from

windowed to full-screen mode on each click of the button.

void CALLBACK OnGUIEvent( UINT, int nControlID, CDXUTControl* )

{

switch( nControlID )

{

case IDC_TOGGLEFULLSCREEN: DXUTToggleFullScreen(); break;

}

Page 168: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 168 of 278

}

As always, the handler must be registered.

g_GUI.SetCallback( OnGUIEvent );

Which can be done at any time prior to the execution of the main loop.

Sound

The new framework also provides abstractions for sound, although it is largely a rehash of the previous framework.

After confirming that the files DXUTsound.h and DXUTsound.cpp are part of the project, add the line: ‘#pragma comment (lib,"dsound.lib")’

somewhere into your project.6

The framework requires a minimum of two objects to play a sound file. First, a CSoundManager object that represents the DirectSound system

as a whole and a CSound object that represents the specific sound or sound file.

CSoundManager sm;

The sound manager needs to be initialized and connected and configured for an application window.

sm.Initialize( hwnd, DSSCL_NORMAL );

The DSSCL_ constants are those defined for IDirectSound8::SetCooperativeLevel().

The sound object itself is created from the sound manager object.

CSound* ps;

sm.Create( &ps, L"File.wav" );

The sound object can now be played and stopped using sound object interface.

ps->Play();

ps->Play( 0, DSBPLAY_LOOPING );

if( ps->IsSoundPlaying() )

ps->Stop();

Cleanup is a relatively simple matter, just delete the sound objects. If you are going to reuse a sound object, stop it, reset it

(CSound::Reset()) then reuse it.

Sample Framework DX-SDK < 9.0c

Introduction

Microsoft has provided programmers with a decent application framework for developing real-time Direct3D based applications. However, the

framework requires the programmer to accept some ugly code dependencies. We will start by identifying what files are required by the DirectX

SDK Common Samples (from here on, the DXCS).

6 I put this line in the DXUTsound.cpp file.

Page 169: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 169 of 278

Building a Project

To build a project with DXCS we need to collect the appropriate files, make some modifications to those files and then write a main program.

File Manifest

The files listed in this manifest should be deposited into the project’s directory.

File Type Folder and File Names

Manifest \DXSDK\Samples\C++\Direct3D\Billboard\billboard.manifest

Resource \DXSDK\Samples\C++\Direct3D\Billboard\winmain.rc

\DXSDK\Samples\C++\Common\directx.ico

Header \DXSDK\Samples\C++\Common\Include\

d3dapp.h

d3denumeration.h

d3dres.h

d3dsettings.h

d3dutil.h

dxutil.h

resource.h

Source \DXSDK\Samples\C++\Common\Src\

d3dapp.cpp

d3denumeration.cpp

d3dsettings.cpp

d3dutil.cpp

dxutil.cpp

Fix Dependencies

Edit the files with the following instructions.

File Tasks billboard.manifest Copy any of the manifest files from a sample to your project folder (e.g.

\DXSDK\Samples\C++\Direct3D\Fur\Fur.manifest).

Rename the file to myprogram.manifest.

winmain.rc Rename the manifest reference to myprogram.manifest.

Fixed the icon reference (delete the relative path).

d3dapp.h Add the following includes: "d3denumeration.h", "d3dsettings.h"

d3denumeration.h Add the following includes: <d3d9.h>, "dxutil.h"

d3dapp.cpp Add ‘pragma comment (lib,"d3d9.lib")’

dxutil.cpp Add ‘pragma comment (lib,"winmm.lib")’

d3dutil.cpp Add ‘pragma comment (lib,"d3dx9.lib")’

Create a WinMain #define STRICT

#include <windows.h>

Page 170: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 170 of 278

#include <commctrl.h>

#pragma comment (lib,"comctl32.lib")

#include "d3dapp.h"

class CMyApp : public CD3DApplication

{

};

INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )

{

CMyApp d3dApp;

InitCommonControls();

if( FAILED( d3dApp.Create( hInst ) ) )

return 0;

return d3dApp.Run();

}

Understanding the Common Sample Architecture

The common sample architecture implements a standard, albeit simple game-loop architecture.

Initialization is implemented in the methods:

OneTimeSceneInit()

InitDeviceObjects()

RestoreDeviceObjects()

Game logic is implemented in the FrameMove() method.

Rendering is implemented in the Render() method.

Shutdown is implemented in the methods:

InvalidateDeviceObjects()

DeleteDeviceObjects()

FinalCleanup()

Initialization and Shutdown are separated into 3 methods each since some cleanup is required

when an application is minimized or resized. This approach allows the common sample architecture

to rebuild graphical objects on an as-needed basis. The key framework methods are called under the

following circumstances:

Startup

1. The application object’s constructor.

Initialization

Quit?

Game Logic

no

Render

Shutdownyes

start

end

Page 171: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 171 of 278

2. ConfirmDevice()

3. OneTimeSceneInit()

4. InitDeviceObjects()

5. RestoreDeviceObjects()

Normal Execution

1. FrameMove()

2. Render()

Window-resize

1. InvalidateDeviceObjects()

2. RestoreDeviceObjects()

Change of video mode

1. InvalidateDeviceObjects()

2. DeleteDeviceObjects()

3. InitDeviceObjects()

4. RestoreDeviceObjects()

Shutdown

1. InvalidateDeviceObjects()

2. DeleteDeviceObjects()

3. FinalCleanUp()

4. The application object’s destructor.

Other Components

The common sample architecture contains other useful DirectX components, both graphical and otherwise.

Fonts

The first step to using the font management classes is to bind the code to your project. Add d3dfont.cpp and d3dfont.h to your project.

The CD3DFont class constructor has two required parameters – firstly, the font type face and secondly, the character height measured in pixels.

Since these values are generally not known at compile time, create a pointer to your font class, as you may have to recreate it at run-time.7

You must now call the following CD3DFont methods in the corresponding CD3DApplication methods:

7 A smart pointer such as boost::scoped_ptr is recommended.

Page 172: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 172 of 278

InitDeviceObjects

RestoreDeviceObjects

DeleteDeviceObjects

InvalidateDeviceObjects

Drawing operations are performed between a BeginScene() / EndScene() sandwich.

Music

CMusicManager mm;

CMusicSegment* pms;

mm.Initialize( hwnd );

mm.CreateSegmentFromFile( &pms, "sound1.wav", TRUE, FALSE );

pms->SetRepeats( 0 );

pms->Play();

delete pms;

Note that CMusicManager and CMusicSegment require dxguid.lib to be linked.

Input with CInputDeviceManager

CInputDeviceManager abstracts the uses of Direct Input 8 action mapping.

#include "diutil.h"

Link: diutil.cpp, dxutil.h

Dependencies: dxutil.h, dxutil.cpp

Overview

When using action-maps, DirectInput notifies the application only when an object’s state changes. Therefore the application is required to record

the state of the input device (i.e. whether a button is up or down.)

Multiple devices can be used to control the game object. Each device is likely to record a user action differently. Therefore we abstract input to

another level – the user state.

Declarations – CMyApp

There are fours parts to declaring input:

1. data structures definitions

2. map definition

3. objects

Page 173: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 173 of 278

4. methods

struct InputDeviceState

{

FLOAT fAxisRotateLR;

BOOL bButtonRotateLeft;

BOOL bButtonRotateRight;

FLOAT fAxisRotateUD;

BOOL bButtonRotateUp;

BOOL bButtonRotateDown;

BOOL bButtonPlaySoundButtonDown;

};

struct UserInput

{

FLOAT fAxisRotateUD;

FLOAT fAxisRotateLR;

BOOL bPlaySoundButtonDown;

BOOL bDoConfigureInput;

BOOL bDoConfigureDisplay;

};

The map definition:

enum INPUT_SEMANTICS

{

// Gameplay semantics

// TODO: change as needed

INPUT_ROTATE_AXIS_LR=1, INPUT_ROTATE_AXIS_UD,

INPUT_ROTATE_LEFT, INPUT_ROTATE_RIGHT,

INPUT_ROTATE_UP, INPUT_ROTATE_DOWN,

INPUT_CONFIG_INPUT, INPUT_CONFIG_DISPLAY,

INPUT_PLAY_SOUND,

};

// Actions used by this app

DIACTION g_rgGameAction[] =

{

// TODO: change as needed. Be sure to delete user map files

// (C:\Program Files\Common Files\DirectX\DirectInput\User Maps\*.ini)

// after changing this, otherwise settings won't reset and will be read

// from the out of date ini files

// Device input (joystick, etc.) that is pre-defined by DInput, according

// to genre type. The genre for this app is space simulators.

{ INPUT_ROTATE_AXIS_LR, DIAXIS_3DCONTROL_LATERAL, 0, TEXT("Rotate left/right"), },

{ INPUT_ROTATE_AXIS_UD, DIAXIS_3DCONTROL_MOVE, 0, TEXT("Rotate up/down"), },

{ INPUT_PLAY_SOUND, DIBUTTON_3DCONTROL_SPECIAL, 0, TEXT("Play sound"), },

// Keyboard input mappings

{ INPUT_ROTATE_LEFT, DIKEYBOARD_LEFT, 0, TEXT("Rotate left"), },

{ INPUT_ROTATE_RIGHT, DIKEYBOARD_RIGHT, 0, TEXT("Rotate right"), },

{ INPUT_ROTATE_UP, DIKEYBOARD_UP, 0, TEXT("Rotate up"), },

{ INPUT_ROTATE_DOWN, DIKEYBOARD_DOWN, 0, TEXT("Rotate down"), },

{ INPUT_PLAY_SOUND, DIKEYBOARD_F5, 0, TEXT("Play sound"), },

{ INPUT_CONFIG_DISPLAY, DIKEYBOARD_F2, DIA_APPFIXED, TEXT("Configure Display"), },

Page 174: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 174 of 278

{ INPUT_CONFIG_INPUT, DIKEYBOARD_F3, DIA_APPFIXED, TEXT("Configure Input"), },

};

#define NUMBER_OF_GAMEACTIONS (sizeof(g_rgGameAction)/sizeof(DIACTION))

Add to the framework application class:

CInputDeviceManager* m_pInputDeviceManager; // DirectInput device manager

DIACTIONFORMAT m_diafGame; // Action format for game play

HRESULT InputAddDeviceCB( CInputDeviceManager::DeviceInfo* pDeviceInfo, const DIDEVICEINSTANCE* pdidi );

static HRESULT CALLBACK StaticInputAddDeviceCB( CInputDeviceManager::DeviceInfo* pDeviceInfo, const DIDEVICEINSTANCE* pdidi,

LPVOID pParam );

OneTimeSceneInit() HRESULT CMyD3DApplication::InitInput( HWND hWnd )

{

HRESULT hr;

// Setup action format for the actual gameplay

ZeroMemory( &m_diafGame, sizeof(DIACTIONFORMAT) );

m_diafGame.dwSize = sizeof(DIACTIONFORMAT);

m_diafGame.dwActionSize = sizeof(DIACTION);

m_diafGame.dwDataSize = NUMBER_OF_GAMEACTIONS * sizeof(DWORD);

m_diafGame.guidActionMap = g_guidApp;

// TODO: change the genre as needed

m_diafGame.dwGenre = DIVIRTUAL_CAD_3DCONTROL;

m_diafGame.dwNumActions = NUMBER_OF_GAMEACTIONS;

m_diafGame.rgoAction = g_rgGameAction;

m_diafGame.lAxisMin = -100;

m_diafGame.lAxisMax = 100;

m_diafGame.dwBufferSize = 16;

_tcscpy( m_diafGame.tszActionMap, _T("DX9Joystick Game") );

// Create a new input device manager

m_pInputDeviceManager = new CInputDeviceManager();

if( FAILED( hr = m_pInputDeviceManager->Create( hWnd, NULL, m_diafGame,

StaticInputAddDeviceCB, this ) ) )

return DXTRACE_ERR( "m_pInputDeviceManager->Create", hr );

return S_OK;

}

Note that the last parameter ‘this’ is a pointer to the call-back parameters.

StaticInputAddDeviceCB

This call-back function is a helper function that assists the device manager in adding devices. For each device enumerated by the

CInputDeviceManager::Create, this function is called. This implementation then calls the application’s InputAddDeviceCB method which creates

a device state object for the device and sets the dead zone.

HRESULT CALLBACK CMyD3DApplication::StaticInputAddDeviceCB(

CInputDeviceManager::DeviceInfo* pDeviceInfo,

Page 175: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 175 of 278

const DIDEVICEINSTANCE* pdidi,

LPVOID pParam )

{

CMyD3DApplication* pApp = (CMyD3DApplication*) pParam;

return pApp->InputAddDeviceCB( pDeviceInfo, pdidi );

}

InputAddDeviceCB

InputAddDeviceCB creates an InputDeviceState object for each input device and links that object to the device info object for that device. This

example also sets the dead-zone for the input device.

HRESULT CMyD3DApplication::InputAddDeviceCB(

CInputDeviceManager::DeviceInfo* pDeviceInfo,

const DIDEVICEINSTANCE* pdidi )

{

UNREFERENCED_PARAMETER( pdidi );

// Setup the deadzone

DIPROPDWORD dipdw;

dipdw.diph.dwSize = sizeof(DIPROPDWORD);

dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);

dipdw.diph.dwObj = 0;

dipdw.diph.dwHow = DIPH_DEVICE;

dipdw.dwData = 500;

pDeviceInfo->pdidDevice->SetProperty( DIPROP_DEADZONE, &dipdw.diph );

// Create a new InputDeviceState for each device so the

// app can record its state

InputDeviceState* pNewInputDeviceState = new InputDeviceState;

ZeroMemory( pNewInputDeviceState, sizeof(InputDeviceState) );

pDeviceInfo->pParam = (LPVOID) pNewInputDeviceState;

return S_OK;

}

FrameMove()

The FrameMove is most direct. Simply access the user input state object and modify the model to match.

UpdateInput( &m_UserInput );

// Update the world state according to user input

D3DXMATRIX matWorld;

D3DXMATRIX matRotY;

D3DXMATRIX matRotX;

if( m_UserInput.fAxisRotateLR )

m_fWorldRotY += m_fElapsedTime * m_UserInput.fAxisRotateLR;

if( m_UserInput.fAxisRotateUD )

m_fWorldRotX += m_fElapsedTime * m_UserInput.fAxisRotateUD;

D3DXMatrixRotationX( &matRotX, m_fWorldRotX );

D3DXMatrixRotationY( &matRotY, m_fWorldRotY );

Page 176: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 176 of 278

D3DXMatrixMultiply( &matWorld, &matRotX, &matRotY );

m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );

If the display device is being reconfigured, you should disable the direct input system until the reconfiguration has completed (otherwise direct

input will intercept commands that should go to the dialog reconfiguration dialog boxes.)

if( m_UserInput.bDoConfigureDisplay )

{

// One-shot per keypress

m_UserInput.bDoConfigureDisplay = FALSE;

Pause(true);

// Configure the display device

UserSelectNewDevice();

Pause(false);

}

The task is a little more complex when user input is being reconfigured. if( m_UserInput.bDoConfigureInput && m_bWindowed ) // full-screen configure disabled

{

// One-shot per keypress

m_UserInput.bDoConfigureInput = FALSE;

Pause( true );

// Get access to the list of semantically-mapped input devices

// to delete all InputDeviceState structs before calling ConfigureDevices()

CInputDeviceManager::DeviceInfo* pDeviceInfos;

DWORD dwNumDevices;

m_pInputDeviceManager->GetDevices( &pDeviceInfos, &dwNumDevices );

for( DWORD i=0; i<dwNumDevices; i++ )

{

InputDeviceState* pInputDeviceState =

(InputDeviceState*) pDeviceInfos[i].pParam;

SAFE_DELETE( pInputDeviceState );

pDeviceInfos[i].pParam = NULL;

}

// Configure the devices (with edit capability)

if( m_bWindowed )

m_pInputDeviceManager->ConfigureDevices(m_hWnd,NULL,NULL,DICD_EDIT,NULL);

else

m_pInputDeviceManager->ConfigureDevices( m_hWnd, m_pDIConfigSurface,

(VOID*)StaticConfigureInputDevicesCB, DICD_EDIT, (LPVOID) this );

Pause( false );

}

UpdateInput()

UpdateInput() examines each device’s InputDeviceState object using that information to update the UserInputState object.

void CMyD3DApplication::UpdateInput( UserInput* pUserInput )

Page 177: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 177 of 278

{

if( NULL == m_pInputDeviceManager )

return;

// Get access to the list of semantically-mapped input devices

CInputDeviceManager::DeviceInfo* pDeviceInfos;

DWORD dwNumDevices;

m_pInputDeviceManager->GetDevices( &pDeviceInfos, &dwNumDevices );

// Loop through all devices and check game input

for( DWORD i=0; i<dwNumDevices; i++ )

{

DIDEVICEOBJECTDATA rgdod[10];

DWORD dwItems = 10;

HRESULT hr;

LPDIRECTINPUTDEVICE8 pdidDevice = pDeviceInfos[i].pdidDevice;

InputDeviceState* pInputDeviceState = (InputDeviceState*) pDeviceInfos[i].pParam;

hr = pdidDevice->Acquire();

hr = pdidDevice->Poll();

hr = pdidDevice->GetDeviceData( sizeof(DIDEVICEOBJECTDATA),

rgdod, &dwItems, 0 );

if( FAILED(hr) )

continue;

// Get the sematics codes for the game menu

for( DWORD j=0; j<dwItems; j++ )

{

BOOL bButtonState = (rgdod[j].dwData==0x80) ? TRUE : FALSE;

FLOAT fButtonState = (rgdod[j].dwData==0x80) ? 1.0f : 0.0f;

FLOAT fAxisState = (FLOAT)((int)rgdod[j].dwData)/100.0f;

UNREFERENCED_PARAMETER( fButtonState );

switch( rgdod[j].uAppData )

{

// TODO: Handle semantics for the game

// Handle relative axis data

case INPUT_ROTATE_AXIS_LR:

pInputDeviceState->fAxisRotateLR = -fAxisState;

break;

case INPUT_ROTATE_AXIS_UD:

pInputDeviceState->fAxisRotateUD = -fAxisState;

break;

// Handle buttons separately so the button state data

// doesn't overwrite the axis state data, and handle

// each button separately so they don't overwrite each other

case INPUT_ROTATE_LEFT:

pInputDeviceState->bButtonRotateLeft = bButtonState; break;

case INPUT_ROTATE_RIGHT:

pInputDeviceState->bButtonRotateRight = bButtonState; break;

case INPUT_ROTATE_UP:

pInputDeviceState->bButtonRotateUp = bButtonState; break;

case INPUT_ROTATE_DOWN:

pInputDeviceState->bButtonRotateDown = bButtonState; break;

case INPUT_PLAY_SOUND:

pInputDeviceState->bButtonPlaySoundButtonDown = bButtonState; break;

Page 178: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 178 of 278

// Handle one-shot buttons

case INPUT_CONFIG_INPUT: if( bButtonState ) pUserInput->bDoConfigureInput = TRUE; break;

case INPUT_CONFIG_DISPLAY: if( bButtonState ) pUserInput->bDoConfigureDisplay = TRUE; break;

}

}

}

// TODO: change process code as needed

// Process user input and store result into pUserInput struct

pUserInput->fAxisRotateLR = 0.0f;

pUserInput->fAxisRotateUD = 0.0f;

pUserInput->bPlaySoundButtonDown = FALSE;

// Concatinate the data from all the DirectInput devices

for( i=0; i<dwNumDevices; i++ )

{

InputDeviceState* pInputDeviceState = (InputDeviceState*) pDeviceInfos[i].pParam;

// Use the axis data that is furthest from zero

if( fabs(pInputDeviceState->fAxisRotateLR) > fabs(pUserInput->fAxisRotateLR) )

pUserInput->fAxisRotateLR = pInputDeviceState->fAxisRotateLR;

if( fabs(pInputDeviceState->fAxisRotateUD) > fabs(pUserInput->fAxisRotateUD) )

pUserInput->fAxisRotateUD = pInputDeviceState->fAxisRotateUD;

// Process the button data

if( pInputDeviceState->bButtonRotateLeft )

pUserInput->fAxisRotateLR = 1.0f;

else if( pInputDeviceState->bButtonRotateRight )

pUserInput->fAxisRotateLR = -1.0f;

if( pInputDeviceState->bButtonRotateUp )

pUserInput->fAxisRotateUD = 1.0f;

else if( pInputDeviceState->bButtonRotateDown )

pUserInput->fAxisRotateUD = -1.0f;

if( pInputDeviceState->bButtonPlaySoundButtonDown )

pUserInput->bPlaySoundButtonDown = TRUE;

}

}

Pause()

Pause clears the state of each input device. Since the action map system uses DISCL_FOREGROUND as its cooperative mode, device state

changes will not be detected when the application is not in focus. Therefore, when a dialog box opens (and focus is lost) any state change to an

input device, like releasing a key or joystick will not be detected by the system. Clearing the state guarantees a safe state when the application

regains focus.

VOID CMyD3DApplication::Pause( bool bPause )

{

CInputDeviceManager::DeviceInfo* pDeviceInfos;

DWORD dwNumDevices;

m_pInputDeviceManager->GetDevices( &pDeviceInfos, &dwNumDevices );

Page 179: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 179 of 278

for( DWORD i=0; i<dwNumDevices; i++ )

{

InputDeviceState* pInputDeviceState = (InputDeviceState*) pDeviceInfos[i].pParam;

ZeroMemory( pInputDeviceState, sizeof(InputDeviceState) );

}

CD3DApplication::Pause( bPause );

}

CleanupDirectInput()

Called from FinalCleanup(). We must first delete each dynamically allocated InputDeviceState object.

VOID CMyD3DApplication::CleanupDirectInput()

{

if( NULL == m_pInputDeviceManager )

return;

// Get access to the list of semantically-mapped input devices

// to delete all InputDeviceState structs

CInputDeviceManager::DeviceInfo* pDeviceInfos;

DWORD dwNumDevices;

m_pInputDeviceManager->GetDevices( &pDeviceInfos, &dwNumDevices );

for( DWORD i=0; i<dwNumDevices; i++ )

{

InputDeviceState* pInputDeviceState = (InputDeviceState*) pDeviceInfos[i].pParam;

SAFE_DELETE( pInputDeviceState );

pDeviceInfos[i].pParam = NULL;

}

// Cleanup DirectX input objects

SAFE_DELETE( m_pInputDeviceManager );

}

TextHelper Object SDK 9.0c

CDXUTTextHelper is a component of the DirectX SDK 9.0c framework. It is provided to simplify the use of formatted text in an application.

Example

The following code writes two lines of text to the display.

if( SUCCEEDED( pd3dDevice->BeginScene() ) )

{

CDXUTTextHelper txtHelper( g_pFont, g_pTextSprite, 16 );

txtHelper.Begin();

txtHelper.SetInsertionPos( 5,5 );

txtHelper.DrawTextLine( L"Hello," );

txtHelper.DrawTextLine( L"world!" );

txtHelper.End();

V( pd3dDevice->EndScene() );

}

Page 180: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 180 of 278

Texture Mapping

Alpha Channel Alpha channel texture mapping is a form of pixel blending that uses information stored in a texture’s alpha channel to determine how much of the

texel is visible in the destination raster.

The standard interpretation of the α-channel is as indicator of transparency or opacity, where the minimum value indicates full transparency and

the maximum value indicates full opacity.

The calculation of the destination pixel is: 1dp sp dp

Direct3D

Data IDirect3DTexture9* texture = NULL;

After device creation D3DXCreateTextureFromFile( pd3dDevice, L"ImageWithAlpha.dds", &texture );

Before rendering the textured primitive pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );

pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );

pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );

pd3dDevice->SetTexture( 0, texture );

Before device destruction texture->Release();

Blending OutPixel SrcPixel SrcBlend DstPixel DstBlend

Colour Keyed Colour keyed texture mapping transfers all pixels to the destination triangle except pixels that match the colour key. This technique is identical to

television green screens.

To use this technique in Direct3D follow these steps:

Loading the texture…

Replace D3DXCreateTextureFromFile() with D3DXCreateTextureFromFileEx(). The extended function allows you to set a colour key value.

e.g.

Page 181: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 181 of 278

D3DXCreateTextureFromFileEx(

pd3dDevice, L"keyed_texture.bmp", D3DX_DEFAULT, D3DX_DEFAULT, 1, 0,

D3DFMT_A8R8G8B8, // This is a 32-bit alpha-enabled format

D3DPOOL_MANAGED, D3DX_DEFAULT,

D3DX_DEFAULT,

D3DCOLOR_ARGB(255,0,255,0), // This is the color key

NULL,

NULL, &pTexture ) );

This command loads the texture replace the pixels matching the color key value with transparent black.

Stage states

The texture stage states essentially program the pipeline to combine or copy the texels the way we want them. For transparency, we need to set the

following stage states for our texture.

pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );

This instructs the pipeline to use the texture as the source of the first colour argument. This setting is the default.

pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );

This instructs the pipeline to use the colour argument we just set as the colour argument in colour operations.

pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );

This instructs the pipeline to use that same colour argument in alpha operations.

pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );

Finally, we instruct the pipeline that the texture is also the source of the first alpha argument.

Render states

Now we set the rendering states of the pipeline to recognize the stage states we have set.

pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );

Enable alpha blending operations.

pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );

Set the source blend factor to the alpha argument, which in this case is the colour from the texture.

pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );

Set the destination blend factor to the inverse (1 sA ) of the source alpha value.

Render the texture normally… e.g.

pd3dDevice->SetTexture( 0, pTexture );

pd3dDevice->SetStreamSource( 0, pVB, 0, sizeof(TVertex) );

pd3dDevice->SetFVF( TVertex::FVF );

pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2 );

Page 182: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 182 of 278

Disabling transparency

To shut of the transparency blending, toggle the D3DRS_ALPHABLENDENABLE render state to false.

Transformations Direct3D texture coordinates can be transformed by the render pipeline. This process allows texture coordinates to be “changed” during program

execution without requiring the vertex data to be physically modified.

A common application of this technique is a sprite engine.

Implementation

Create the vertices in the standard way for a textured surface. Call the following two methods prior to rendering the surface:

pd3dDevice->SetTransform( D3DTS_TEXTURE0, &transformMatrix );

pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );

The first method registers the specific transform with the appropriate texture transform matrix – in this case, texture zero (D3DTS_TEXTURE0).

The second methods indicates that the only the first two coordinates generated by the texture transform should be passed through to the rasterizer.

This is the appropriate setting for a 2D texture mapping.

Transforms Types

The any transform can be applied to the texture coordinate transform engine, individually or in combination. However, some transforms are more

meaningful than others as the texture coordinate system is a two-dimension system. The transforms are registered by passing 4x4 matrices to the

system, but these matrices may be interpreted as 3x3 or 2x2 matrices depending on the dimensionality of the texture coordinates. 2D texture

coordinates, for example, interpret the transforms as 3x3 matrices.

Translation

Two dimensional translations of texture coordinates are somewhat difficult as we cannot use the built-in matrix operations provide by Microsoft.

We have to create them ourselves.

The standard 2D translation matrix is:

1 0 0

0 1 0

1x y

To package the 2D translation matrix into a 4x4 matrix we arrange the matrix in the following way:

1 0 0 0

0 1 0 0

1 0

0 0 0 1

x y

In code we would see:

Page 183: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 183 of 278

D3DXMATRIX matTrans;

D3DXMatrixIdentity( &matTrans );

matTrans._31 = 2.0f;

matTrans._32 = 3.0f;

This produces a translation of 2 in x and 3 in y.

Rotation

The most meaningful rotation of 2D texture coordinates is a rotation about the Z axis (or a rotation in the X-Y plane.) The standard 3D rotation

produces a result that is correct in 2D.

Scaling

The standard 3D scaling matrix is correct in 2D if the z-scale is 1.0.

Two-dimensional Rendering The default state of a DirectX device is to have the depth buffer enabled as well as back-face culling of triangles. It is assumed that clock-wise

triangles are front face and anti-clock-wise triangles are back-face.

Two-dimensional rendering typically ignores back-face culling, although the depth buffer can be useful to leave enabled.

To disable back-face culling issue the command:

pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );

To disable z-buffering issue the command:

pd3dDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );

Both of these commands need only be called prior to rendering.

DX-SDK 9.0c: These commands can be safely issued in the OnResetDevice() callback function.

DX-SDK 9.0b: These command can be safely issued in the OnRestoreDevice() method.

Hardware

Adapters

3dfx Voodoo 3500

AGP Texturing

16MB SGRAM

183MHz clock and memory

366 Megatexels/s peak fill rate

8 Million polygons/s

Page 184: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 184 of 278

Single-pass multi-texturing

128-bit 2D/3D processor

350MHz RAMDAC

D3D, Glide, OpenGL support

nVidia Riva TnT2

AGP Texturing

32MB SDRAM/SGRAM

9 million triangles/sec, 300 million pixels/s

2.9GiB/s bus

300MHz RAM DAC

128-bit Twin-Texel

Optimized Direct3D and OpenGL acceleration

SEGA Dreamcast

CPU Hitachi SH-4

200MHz clock

360MIPS

1400 MFLOPS (900MFLOPS with external memory)

64-bit data bus

100MHz bus

Capable of 5 million polygons/s

800MB/s bus

32-bit integer unit

128-bit floating point bus

GPU NEC PowerVRSG

100MHz clock

32-bit bus

9 billion operations/s

3.5 million polygons/s

120 million pixles/s fill rate

Perspective-correct texture mapping

Bilinear and trilinear filtering

Anisotropic filtering

Gourand shading

32-bit Z-buffer

Page 185: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 185 of 278

Colored light sourcing

16 levels of transparency

Full-scene edge anti-aliasing

Fog vertex

Per-pixel fogging

Bump mapping

24-bit color

Sound Yamaha ARM7 ASIC

45MHz clock

40 MIPS

64 sound channels

Full 3D sound support

Modem Upgradable 33.6KB/s

CD-ROM Yamaha design

1GB data storage

12 speed

1800KB data transfer rate

Memory 16MB main RAM

8MB video RAM

2MB sound RAM

Video acceleration for DirectShow, MPEG1&2, and Indeo

Sony Playstation 2

CPU 128-bit “emotion engine”

300MHz system clock

16KB Instruction cache

8KB + 16KB (ScrP) Data cache

32MB Direct Rambus main memory (RDRAM)

3.2GiB/s memory bus

Co-processor FPU: Multiplier, Accumulator, Divider

2 Vector Units: Multiply, 9 Accumulators, 3 Dividers

6.2 GFLOPS

66 million polygons/s 3D CG geometric transformation

Graphics “Graphics Syntehsizer”

MPEG2 decoder

Page 186: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 186 of 278

150MHz clock

48GiB/s DRAM bus

256-bit DRAM bus width

RGB: Alpha: Z-buffer (24:8:32) pixel configuration

75million polygons/s maximum rate

Sound “SPU2+CPU”

Number of voice ADPCM: 48ch on SPU2 plus definable, software-programmable voices

44.1KHz or 48KHz selectable sampling frequency

CPU

Core Playstation 1 CPU

33.8 MHz or 37.5 MHz selectable clock

32-bit sub bus

IEEE1394 and USB

PCMCIA

Disc CD-ROM and DVD-ROM

Terrain

Height Maps

Introduction

A height map is an indexed collection (array or vector) where each element contains the height of a particular vertex in the terrain grid. Some

height maps contain the height information of each grid as apposed to each vertex. Conceptually, the height map can be thought of as a matrix

where each element corresponds to a grid vertex.

Height maps are efficiently stored on disk as byte-maps. Using byte-maps permit 256 different elevations. The byte-maps can be created with a

bitmap editing tool such as Adobe Photoshop. Typically, darker regions are lower elevations and lighter regions higher elevations.

Page 187: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 187 of 278

Data Structures

The data structures in the height map and vertex list are both one-dimensional data structures

representing two-dimensional objects. Therefore we need a mapping of 2D row-column

coordinates to 1D offsets.

colerRownVerticesProwoffset

erRownVerticesP

offsetrow

erRownVerticesPoffsetcol mod

The vertex buffer fills from left to right and back to front where consecutive elements are

on the same row.

Indices fill for each cell from left to right and back to front where each cell generates the

index pattern ABCBDC – for CW culled triangles or ACBBCD for CWW culled

triangles.

Textures coordinates fill from left to right and back to front. It is assumed that one texture

covers the entire surface.

Height information fills from left to right and back to front where consecutive elements

are on the same row. Each elevation value [0..255] is scaled by a preset value.

Walking on the terrain

We can examine the height map to gain information about what the height of the character

should be for any particular location on the terrain.

Given a location (x,z)

xwidth

x 2

, zdepth

z 2

1. Adjust the location to make the back-left the (0,0) location.

2. Normalize the coordinates, such that cellspacing = 1.

gcellspacin

zz

gcellspacin

xx ,

3. Locate the cell in which the normalized coordinates (x,y) is located.

zrowxcol ,

4. Get the heights of the four cell vertices from the height map. ),( colrowheightmapAy

)1,( colrowheightmapBy

(-w/2,+d/2)

(-w/2,-d/2) (+w/2,-d/2)

(+w/2,+d/2)cell spacing+z

+x

w = Width

C D

A B

[0,0] [1,0]

[0,1]

v0 v1 v2 v3 v4 v5

v6 v7 v11

v12

v35

v18

v24

v30

0,0:0 0,63:63

63,0:4032 63,63:4095

Page 188: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 188 of 278

),1( colrowheightmapCy

)1,1( colrowheightmapDy

5. Calculate the deltas of the coordinate within the cell.

zzzxxx ,

6. Determine which triangle of the cell the coordinate (x, z) is located in.

If xz 1 then the point is located in upper triangle ABC, otherwise the point is located in lower triangle DCB.

7. Interpolate ∆x and ∆z.

btatatbalerp ),,(

If upper triangle: ),,0(),,0( zAClerpxABlerpAheight yyyyy

Simplified: zACxABAheight yyyyy

If lower triangle: )1,,0()1,,0( zDBlerpxDClerpDheight yyyyy

Simplified: zDBxDCDheight yyyyy 11

Lighting, Static Terrain lighting presents some performance opportunities that other objects do not. Terrain generally doesn’t move, nor does the global,

directional light source relative to the terrain. Of course this may not be true if the game continues for a long duration, but often scenarios or

missions are short enough for this to be true. As a result, we can pre-calculate the effects of lighting on the terrain surface (typically a texture)

then render the terrain without the lighting engine enabled.

Method

The general solution begins with calculating the angle between the light vector L̂8 and the surface normal N̂ . We will call this angle . We will

then calculate a shading scalar s, where 0 s 1. If the angle between the light vector and the normal vector is 0° the shading scalar is 1 – full

brightness. As the angle increases the shading scalar decreases to a value of 0 when the = 90°. Angles greater than 90° indicate a light-source

below the surface and therefore do not light the surface.

Given: abc 9 and L̂

abu

8 The lighting vector is a unit vector originating with the light source and pointing towards the surfaces to be lit. 9 ABC are clockwise ordered in a LH system, anti-clockwise ordered in a RH system.

Page 189: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 189 of 278

acv

vun

n

nN ˆ

NL ˆˆcos s , where 11 s

Since negative angles indicate that the surface is being lit from the backside, we clamp s to zero when s is in the range )0,1[ .

We can now multiply each of the colour values for this surface by s.

Skyboxes (sky-domes) A skybox is simply a box that surrounds the viewer and has a picture of the sky and surrounding environment textured on to each of the sides.

A full skybox, is a six-sided cube complete with sky and ground textures on top and bottom and sky/horizon textures for each of the four walls.

Most games don’t require the bottom to be rendered and may omit that surface.

Alternatives to skyboxes are sky-domes, semi-spherical domes that sit above the viewer and have the sky and perhaps clouds textured to the

surface. Sky-domes are typically compressed in the y-axis to provide a more realistic perspective as clouds pass by the viewer. Sky-domes

generally don’t have horizons as part of the texture mapped to the dome.

Implementation

The skybox is rendered prior to all other shapes with either no world transformation and the camera transform striped of location, or translated to

the camera location and the full camera translation applied.

Which is of the two approaches to take depends on whether fog effects are present in your scene. If fog is present the second approach of

rendering the skybox in world coordinates must be taken. Otherwise the system will not calculate the pixel depths correctly. If fog is not present,

the first approach of rendering the skybox in local coordinates can be taken. This approach is typically faster, but requires the camera or view to

be set without position information.

Removing the position from the view matrix. D3DXMATRIX view;

pd3dDevice->GetTransform( D3DTS_VIEW, &view );

view._41 = view._42 = view._43 = 0;

pd3dDevice->SetTransform( D3DTS_VIEW, &view );

The position information is stored in the last row of the matrix. Setting these values to zero effectively removes the position information from the

matrix.

Page 190: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 190 of 278

Turtle Graphics

Turtles or turtle graphics come from the LOGO language developed at MIT in the late 1960’s.

LOGO was used to interact with and command a turtle-like robot that had the capability to move

across the floor, turn in any direction and to raise and lower pen onto the floor. If the pen was

lowered when the turtle was instructed to move, a line would be drawn on the floor.

This a LOGO styled script for drawing a square:

pen down

step 10

turn 90

step 10

turn 90

step 10

turn 90

step 10

In graphics languages like OpenGL and Direct3D it is either impractical or inefficient to draw directly to the frame buffer using the turtle-graphics

paradigm. However, a pen-less turtle can be quit useful and quit efficient if used to generate vertices that will be stored in a vertex buffer.

Design

Turtles easily lend themselves to object-oriented programming. The LOGO commands become methods and the class attributes are easily derived

from the functionality of the class. That leaves us with one fundamental question about architecture: do we encapsulate the 2D vector representing

the turtle’s location or do we derive our turtle from a 2D vector class.

Encapsulated location Derived from location

Turtle

+location:D3DXVECTOR2

+direction:float

+speed:float

+step():

+turn(angle:float):

D3DXVECTOR2

Turtle

+direction:float

+speed:float

+step():

+turn(angle:float):

step 10

turn 90

turn 90turn

90

step 10

step

10 ste

p 10

Page 191: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Graphics Section 13

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 191 of 278

Computations

Turn(angle) direction direction angle

Step cos ,sinlocation location speed direction direction

Page 192: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

History Section 14

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 192 of 278

History

DirectX

Introduction

DirectX has gone through many version, some released – some not, and even a few name changes. Here, I hope to record what changed, when and

how we benefit from those changes.

~1994: WinG

WinG was an early attempt by Microsoft to bring game developers to the Windows platform.

Windows could blt a bitmap to a window with a bandwidth comparable to an equivalent DOS program running on the same hardware. The

primary problem was that the efficient blting routine BitBlt could only blt from an HBITMAP which was not stored in application memory.

Therefore the application could not directly touch the pixels of an HBITMAP, it would have to go through the GDI with routines like SetPixel and

LineTo. DIBs which are stored in application memory are as much as 20 times slower than BitBlt.

WinG provided a set of objects, most notably WinGBitmap that can be blted directly from application memory. The performance of WinG’s blt is

comparable to DOS’s best time.

December 1994?: WinToon

WinToon is Microsoft’s animation playback tool for Windows. It uses the Video for Windows architecture integrated into the Windows 95 OS. It

would support the WinG API.

1995: DirectX 1.0 (Microsoft Game SDK)

Originally called the Microsoft Game SDK, Microsoft now uses its better accepted name DirectX version 1.0. The critical offering in this SDK is

DirectDraw 1.0, a technology that permits direct access to a video adapter’s memory in a device independent manner.

One of the first games to use DirectX was Descent, from Parallax Software

1996: DirectX 2.0

APIs

DirectDraw API provides direct access to bitmaps. Bitmaps may be in on-screen or off-screen video memory. Hardware bit-block transfer and

buffer-flipping is supported.

DirectSound API provides hardware and software sound mixing and playback.

DirectPlay API provides connectivity via modem or network.

Direct3D API provides direct low-level access to 3D hardware. DirectDraw surfaces can be used as render targets or source texture maps.

Page 193: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

History Section 14

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 193 of 278

DirectInput API provides abstractions for keyboard, mouse and joystick in a framework that is extensible to future devices.

Direct3D

Based on Reality Lab technology acquired from Render-Morphics in 1995.

Hardware Support

Video hardware features:

Overlays

Page flipping

Sprite engines

Stretching with interpolation

Alpha blending

Z buffer-aware bit-block transfers

1996: DirectX 3.0

1997: DirectX 5.0

1998: DirectX 6.0

1999: DirectX 7.0

2000: DirectX 8.0

Following the release of this SDK, Microsoft releases the first Xbox.

2001: DirectX 8.1

2002: DirectX 9.0

2003: DirectX 9.0b

2004: DirectX 9.0c

One of the finest examples of a DirectX 9.0c is Half-Life 2, by Valve Software

Page 194: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

History Section 14

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 194 of 278

2005: Xbox 360

2006: DirectX 10

Microsoft lists the design goals for DirectX 10 as:

improving small-batch performance

reducing validation overhead

in-GPU multipass

the elimination of capability bits

unify shader cores

strictly define behaviour across chipsets

more expressive programming

geometry shader

texture compression formats for normals

resource views

Recognizing that Direct3D 9 is a mature API, Microsoft decided to completely re-architect the system. This also allows Direct3D 10 to use

Vista’s new WDDM (Windows Display Driver Model)

Features:

Common shader core – all shaders use the same instructions.

Guaranteed feature set. All cards support all features.

Programmable shader model – all rendering uses shaders using HLSL SM 4.0.

Resources are now two logical pieces – buffers and views.

GPU and Memory is virtualized – ‘LOST DEVICE’ condition no longer occurs. Multiple applications can use Direct3D.

State/resource validation restricted to specific times (such as creation)

FAQS

The first good DirectX 10 game is Crysis, by Crytek.

Microsoft sees the Direct3D9 as the replacement to GDI for core windows graphics and Direct3D 10 as the path for high-performance graphics.

Page 195: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 15

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 195 of 278

Mathematics

General

Factorial The continued product 12321 nnn is called the factorial. It is the number of permutations of n things. We denote factorial using a

suffixed exclamation symbol. The factorial of zero is a special case with its value being 1. This is due to there being one arrangement of

1!0

12321!

nnnn

If n is large, an approximation of n! can be obtained using Stirling’s Theorem.

ne

nn

n

2!

Implementation

function FACTORIAL( n ) returns natural number

if 0 n 1

then return 1

else return n FACTORIAL( n – 1 )

A simple and elegant algorithm! But a poor performer in terms of memory and sometimes execution speed. An iterative implementation should

be preferred.

function FACTORIAL( n ) returns natural number

fact 1

for i 2 to n do

fact fact i

return fact

Fibonacci Numbers A number from the Fibonacci sequence: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, …

The general term nF can be found with the formula:

112

21

FF

FFF nnn

Page 196: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 15

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 196 of 278

Jacque Philippe Marie Binet (1776 – 1856) in 1843 derived a formula capable of calculating any specific Fibonacci number. This is called Binet’s

Form.

52

5151

n

nn

nF

Implementation

function FIBONACCI ( n ) returns natural number

if 0 < n 2

then return 1

else return FIBONACCI( n – 1 ) + FIBONACCI( n – 2 )

While a recursive solution is simple, it is a poor performer on both memory and time. The recursive calls branch out to a tree of function calls!

An iterative approach is to be preferred.

function FIBONACCI( n ) returns natural number

if 0 < n 2

then return 1

first second 1

for i 3 to n – 1 do

fib first + second

first second

second fib

return first + second

While the iterative approach is an improvement over the recursive approach, large Fibonacci numbers still require considerable processing time.

Such Fibonacci numbers can be calculated in constant time using Binet’s form.

Fibonacci and Euclid

Fibonacci numbers have an interesting relationship with the Euclidean Algorithm (HCF). For each successive pair of Fibonacci numbers the

following holds true;

1, 1 ii FFHCF

11 mod iii FFF

These relationships where investigated by Thomas Fantet de Lagny (1660 – 1734).

Golden Ratio The golden ratio is also known as the divine proportion, golden mean and the golden section.

It is denoted , or sometimes (abbr. Gk. “tome” meaning “to cut”).

The golden ratio possesses the following properties.

Page 197: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 15

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 197 of 278

1

1

012

The golden ratio can be calculated by the following means:

512

1

10csc

2

1

5

2sec

2

1

5cos2

032

1

4!!2

!121

8

13

nn

n

nn

n

1 1

11

1n nn

n

FF Where

nF is a Fibonacci number.

11111

Logarithms A logarithm is a function that gives value of the exponent in the equation xa b . The typical notation for a logarithm is logax b .

Numbers

Natural Numbers

Natural numbers are non-negative integers; i.e. 0, 1, 2, 3, … 42, …,

Notation: ¥ denotes the set of all natural numbers.

Pi π – pi.

1arccos

0 21

41

11

4

9

4

7

4

5

4

3

4

1

4

i

i

i

Page 198: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 15

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 198 of 278

Implementation – iterative

function PI( x ) returns a real number

last ← 0

p ← 4

denominator ← 1

sign ← –4

while p last do

last ← p

denominator ← denominator + 2

p ← p + sign denominator

sign ← –sign

return p

Note ε is the difference between the value 1 and the least value greater than one.

The primary problem with this method is floating-point error and the length of time required to produce an accurate result. Personally, I prefer to

use a pre-calculated constant in actual code.

Implementation – recursive

function PI( n ) returns a real number

if n = 0

then return 4

else return −1𝑛

1+2𝑛+ 𝑃𝑖(𝑛 − 1)

Algebra

Binomial Coefficient The binomial coefficient is the number of ways of picking k unordered outcomes from n possibilities. In terms of sets, the binomial coefficient

gives the number of k-subsets possible out of n distinct items. We write the binomial coefficient with the either the notation

k

n or

kn C and are

read as “n choose k”.

The value of the binomial coefficient is given explicitly by the formula: !!

!

knk

n

k

nCkn

The binomial coefficient is also known as combination or a combinatorial number.

Pascal’s Triangle The binomial coefficients form the rows of Pascal’s triangle.

Page 199: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 16

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 199 of 278

0

0

0

1

1

1

0

2

1

2

2

2

0

3

1

3

2

3

3

3

1

1 1

1 2 1

1 3 3 1

Permutation A permutation is an ordered arrangement of the elements of a set.

Example: ACBD, CBDA and DCBA are all permutations of the set {A, B, C, D}

The number of possible permutations (possible arrangements) is represented by n

rP where n is the number of different things and r is the number

of things in the arrangement.

Examples

The set {A, B, C} has the following 3-element arrangements: ABC, ACB, BCA, BAC, CAB, and CBA. The number of arrangement if given by

the expression: 3

3 6P .

The set {A, B, C, D} has the following 2-element arrangements: AB, AC, AD, BA, BC, BD, CA, CB, CD, DA, DB, DC. The number of

arrangement if given by the expression 4

2 12P .

Computing

!

!

n

r

nP

n r

Uses

Permutations are used the study of theories of equations, group theory and statistics.

Sum of Natural Numbers The sum of all the numbers from 1 up to a given upper limit:

Page 200: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 200 of 278

12

1

1321

1

nn

i

nnS

n

i

n

2D/3D Algebra

Coordinate Transforms Coordinate transformations are used to convert an object’s local coordinate system to the graphics engine’s world coordinate system.

Both 2D and 3D transformations are created by combining a rotation transform that aligns the axes of the local coordinate system with the axes of

the world’s coordinate system and a translation transform that aligns the local origin with the world origin.

Solution – 2D

Let the vectors u, v represent the local axes within the world coordinate system. You can think of these as the right and up vectors. Let L be the

location of the local coordinates system’s origin expressed in world coordinates.

We construct a rotation matrix by locating a matrix with the following properties:

11 12

21 22

11 12

21 22

1 0

0 1

x y

x y

a a

a a

a a

a a

u u

v v

Since these systems have the same coefficient matrix A, we can solve them at once.

11 12

21 22

1 0

0 1

x y

x y

a a

a a

u u

v v

The answer is obvious; the coefficient matrix is the result! We can now rewrite the transform as a homogeneous matrix R.

Page 201: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 201 of 278

0

0

0 0 1

x y

x y

u u

R v v

Now we need a homogeneous translation matrix that maps the local origin to the world origin.

1 0 0

0 1 0

1x y

T

L L

The complete coordinate transformation is just the product of the two matrices.

0 1 0 0 0

0 0 1 0 0

0 0 1 1 1

x y x y

x y x y

x y x y

u u u u

R T v v v v

L L L L

Coordinates the local system can be multiplied by this matrix to produce coordinates in the world system.

Solution – 3D

Let the vectors r, u, k represent the local axes within the world coordinate system. You can think of these as the right, up and look vectors. Let L

be the location of the local coordinates system’s origin expressed in world coordinates.

We construct a rotation matrix by locating a matrix with the following properties:

11 12 13

21 22 23

31 32 33

11 12 13

21 22 23

31 32 33

11 12 13

21 22 23

31 32 33

1 0 0

0 1 0

0 0 1

x y z

x y z

x y z

a a a

a a a

a a a

a a a

a a a

a a a

a a a

a a a

a a a

r r r

u u u

k k k

Since these systems have the same coefficient matrix A, we can solve them at once.

11 12 13

21 22 23

31 32 33

1 0 0

0 1 0

0 0 1

x y z

x y z

x y z

a a a

a a a

a a a

r r r

u u u

k k k

The answer is obvious; the coefficient matrix is the result! We can now rewrite the transform as a homogeneous matrix R.

v

u

L

Y

XO

Page 202: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 202 of 278

0

0

0

0 0 0 1

x y z

x y z

x y z

r r r

u u uR

k k k

Now we need a homogeneous translation matrix that maps the local origin to the world origin.

1 0 0 0

0 1 0 0

0 0 1 0

1x y z

T

L L L

The complete coordinate transformation is just the product of the two matrices.

1 0 0 0 00

0 1 0 0 00

0 0 1 0 00

1 10 0 0 1

x y zx y z

x y zx y z

x y zx y z

x y z x y z

r r rr r r

u u uu u uR T

k k kk k k

L L L L L L

Coordinates the local system can be multiplied by this matrix to produce coordinates in the world system.

Quaternion (Garth Santor, January 2007)

Quaternions are non-commutative extensions of complex numbers. They take the form of a 4-dimensional normed division algebra over real

numbers (H). It is useful to think of quaternions as having a real part w, and an imaginary part v, which is a 3-component vector. q w v

where v x y z . The real part w, represents an angle of rotation, and the vector part v, represents the axis in 3-space around which the

rotation occurs.

1843 Sir William Rowan Hamilton describes quaternions.

Avoids the ‘gimble-lock’ problem

Quaternion from axis-angle pair

cos sin cos sin sin sin2 2 2 2 2 2

x y z

q n n n n

Where n is a unit vector.

Page 203: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 203 of 278

Direct3D

D3DXQUATERNION* D3DXQuaternionRotationAxis(

D3DXQUATERNION* pOut,

D3DXVECTOR3* pAxis,

FLOAT angle );

Direct3D normalizes the axis vector.

Quaternion negation

w w x y z

w w x y z

q v

v

Direct3D

D3DXQUATERNION D3DXQUATERNION::operator – () const;

Quaternion identity

1 1 0 0 0 q 0

Direct3D

D3DXQUATERNION* D3DXQuaternionIdentity( D3DXQUATERNION* pOut );

Quaternion magnitude

22 2 2 2 2

w w x y z

w w x y z

q v

v

Direct3D

FLOAT D3DXQuaternionLength( CONST D3DXQUATERNION* pQ );

Quaternion Conjugate The conjugate of a quaternion is obtained by negating the vector portion of the quaternion. It is denoted by *

q .

*** w w x y z

w w x y z

q v

v

Page 204: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 204 of 278

Direct3D

D3DXQUATERNION* D3DXQuaternionConjugate( D3DXQUATERNION* pOut, CONST D3DXQUATERNION* pQ );

Quaternion Inverse The quaternion inverse is defined by the conjugate divided by its magnitude. It is denoted by 1

q .

*1

qq

q

Direct3D

D3DXQUATERNION* D3DXQuaternionInverse( D3DXQUATERNION* pOut, CONST D3DXQUATERNION* pQ );

Quaternion from Euler angles (Tait-Bryan angles)

cos 2 cos 2 cos 2 sin 2 sin 2 sin 2

cos 2 sin 2 cos 2 sin 2 cos 2 sin 2

sin 2 cos 2 cos 2 cos 2 sin 2 sin 2

cos 2 cos 2 sin 2 sin 2 sin 2 cos 2

q , where is yaw, is pitch, and is roll.

Direct3D

D3DXQUATERNION* D3DXQuaternionRotationYawPitchRoll(

D3DXQUATERNION * pOut,

FLOAT Yaw,

FLOAT Pitch,

FLOAT Roll );

Euler angles (Tait-Bryan) from Quaternion

Let be yaw, be pitch, and be roll.

Page 205: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 205 of 278

2 2

2 2

2 2

arctan cos 01

2

arctan1

2

arcsin 2

arctan cos 01

2

0

xz wyif

x y

xz wyotherwise

y z

yz wx

xy wzif

x z

otherwise

Transformations In 3D graphics, transformations are operations that map vectors from one system to another. Transformations are commonly used to map vertices

from world coordinates to view coordinates, or view coordinates to screen coordinates.

Transformations can be represented by matrices. For a 3D system, the matrices are 4×4. The most common transformations are:

Identity

Scaling

Translation

Rotation

Projection

View

Common Transforms

Name Description Symbol Matrix d3dx function

Identity Neutral transform. Maps the value

to itself. I 1 0 0 0

0 1 0 0

0 0 1 0

0 0 0 1

D3DXMatrixIdentity()

Scale Stretch, compress, mirror. S 0 0 0

0 0 0

0 0 0

0 0 0 1

x

y

z

s

s

s

D3DXMatrixScaling()

Page 206: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 206 of 278

Translation Move. T 1 0 0 0

0 1 0 0

0 0 1 0

1x y zt t t

D3DXMatrixTranslation()

Z-Rotation Rotates about the origin in the XY

plane. Also called roll. Z

R , ZR cos sin 0 0

sin cos 0 0

0 0 1 0

0 0 0 1

D3DXMatrixRotationZ()

Y-Rotation Rotates about the origin in the XZ

plane. Also called yaw. Y

R , YR cos 0 sin 0

0 1 0 0

sin 0 cos 0

0 0 0 1

D3DXMatrixRotationY()

X-Rotation Rotates about the origin in the YZ

plane. Also called pitch. X

R , XR 1 0 0 0

0 cos sin 0

0 sin cos 0

0 0 0 1

D3DXMatrixRotationX()

Common Composite Transformations

Description Formula

Rotation (R) about an arbitrary point (T) -1M = T × R θ ×T

How is the rotation matrix formed?

Imagine a vector that will be rotated in the XY plane by the angle .

The absolute angle , of the initial vector ,x y can be found using trigonometry.

cos sinx r y r

The final vector ,x y can also be found using trigonometry.

cos

cos cos sin sin

cos sin

x r

x r r

x x y

sin

cos sin sin cos

sin cos

y r

y r r

y x y

The final formulas are then arranged into the columns of the matrix.

cos sin 0 0

sin cos 0 0

0 0 1 0

0 0 0 1

ZR

Page 207: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 207 of 278

Vector (geometric)

Cross Product

Cross product is produces a vector that is perpendicular to the two original vectors.

y z z y z x x z x y y x u× v u v -u v u v u v u v u v

x x y z z y

y y z x x z

z z x y y x

u v u v u v

u v u v u v

u v u v u v

The direction of the perpendicular is dependent upon the order in which the original vectors are multiplied.

Example:

,u = 1 0 0 v = 0 1 0

y z z y z x x z x y y xu× v = u v - u v u v - u v u v - u v

= 0×0 - 0×1 0×0 -1×0 1×1- 0×0

= 0 0 1

y z z y z x x z x y y xv ×u = v u - v u v u - v u v u - v u

= 1×0 - 0×0 0×1- 0×0 0×0 -1×1

= 0 0 -1

The cross product of vectors multiplied with a counter-clockwise order produce a vector pointing towards the viewer in a right-hand system or

away from the viewer in a left-handed system.

The cross product of vectors multiplied with a clockwise order produce a vector pointing away from the viewer in a right-hand system or toward

the viewer in a left-handed system.

Properties of cross products

Length sin a b a b

Inner Product

Inner product is the magnitude of the projection of one vector upon another. The inner product is the sum of the products of corresponding

elements of two vectors. Inner product is denoted by a small dot placed between two vectors. vu is the inner product of vectors u and v.

The value of an inner product of vectors u and v is ii vuvu where u v ¡ .

Alternatively, the inner product can be calculated using trigonometry.

u× v

u

v

Page 208: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 208 of 278

cosvuvu where is the angle between the direction vectors u and v, and | 0 ¡ .

Properties of inner products

Associative vuvuvu kkk

Commutative uvvu

Distributive wuvuwvu

Square 2vvv for

2v V

Magnitude

The magnitude of a vector is the scalar length of a vector.

The value of vector magnitude of vector v is i

i

2vv

Calculus

Euler’s Constant – e e – the base of the natural (hyperbolic or Naperian) logarithms.

0 !

1

!3

1

!2

1

!1

11

i ie

0

32

!!3!2!11

i

ix

i

xxxxe

function E( x ) returns real number

last 0

e denominator term 1

numerator x

while e – last > do

e e + numerator denominator

term term + 1

denominator denominator term

numerator numerator x

Note is the difference between the value 1 and the least value greater than one.

Page 209: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 209 of 278

Geometry

Euler Angles (Garth Santor, January 2007)

The spatial orientation of an object can be represented by a sequence of rotations about three mutually perpendicular axes. The angles of the three

rotations are collectively called Euler angles after Leonard Euler, who developed them.

Euler angles may be expressed using many conventions, the most common being the x-convention (z-x-z) and the y-convention (z-y-z).

Interpretation To interpret these conventions, imagine an object in left-hand coordinate system that contains look-vector pointing straight forward, a right-vector

pointing 90 to the right, and an up-vector orthogonal to the previous two and pointing up.

x-convention

To resolve the direction of the object using its Euler angle , , :

1. Rotate the object degrees about the world up-axis. (right- and look-axes are transformed).

2. Rotate the object degrees about the transformed right-axis. (up- and look-axes are transformed).

3. Rotate the object degrees about the transformed up-axis.

Disambiguation Yaw-pitch-roll rotations used by aerospace engineers are often called Euler angles. They are a special case of the Euler angle (y-x-z) more

appropriately called Tait-Bryan angles.

Lines – 2D

Terminology

Normal axis of a line in 2-space. A line l in 2-spae determines a unique line l’ through the origin and perpendicular to l. l’ is called the normal

axis of l.

Representation

Lines can be represented in a variety of ways.

End-point representation: A pair of vertices. (e.g. AB )

Page 210: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 210 of 278

Vector representation: yx ,v for 2D lines and zyx ,,v for 3D lines. Note that this representation assumes one end located at the

origin.

Parametric representation: tt vPP 0)( where 10 t for a line segment.

Linear equation representation: cbyax for 2D lines and dczbyax for 3D lines. Note that this representation has no ending points.

Slope-intercept representation: bmxy for 2D lines. Note that this representation has no ending points.

Converting Between Representations

End-point to parametric (both 2D and 3D):

AB v

Parametric (2D) to linear (2D):

xy

x

y

yxc

b

a

vPvP

v

v

0

0

Linear (2D) to slope-intercept:

b

cb

b

am

Lines – Intersection in 2 dimensions

Give two lines represented by the linear equations:

111 cybxa

222 cybxa

We can solve the system of equations for x and y producing the equations:

0 AP

Page 211: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 211 of 278

1221

1221

1221

2112

baba

cacay

baba

cbcbx

Note that a denominator of zero indicates that the lines are either parallel or coincident.

Finding the time of intersection of two 2D lines

Given two lines in end-point form: AB and CD

1. Create two parametric equations, one for line AB and one for line CD .

2. Create linear equations for each of the two lines.

3. Solve the system of linear equations for x and for y.

4. Find the t value of the parametric equation that produces yxt ,P .

5. t is the time of intersection.

Polyhedra Polyhedra are solids bound by faces (plane polygons); the intersection of three or more edges are called vertices. The number of faces, edges and

vertices in polyhedra obey Euler’s law: 2 evf .

Polyhedra – Regular Regular polyhedra are solids bounded by regular polygons with all vertices on a circumscribing sphere. They are also known as the Platonic

Solids.

Platonic convex solids are the regular polyhedra: tetrahedron, hexahedron (cube), octahedron, dodecahedron, and icosahedron.

Polyhedron Faces Edges Vertices Face Type

Tetrahedron 4 6 4 equilateral

triangle

Hexahedron 6 12 8 square

Octahedron 8 12 6 equilateral

triangle

Dodecahedron 12 30 20 pentagon

Icosahedron 20 30 12 equilateral

triangle

Page 212: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 212 of 278

Tetrahedron

Metrics

Let a be the length of an edge.

Let R be the radius of the circumscribing sphere.

Let r be the inradius – the radius of the inscribing sphere.

Number of faces 4

Number of vertices 4

Number of edges 6

Face type Equilateral triangle

bottom view

30

xd

r

R

side view

aa

aa

a

perspective view

12 33

cos6

a

x a

2

2 1 13

2 6d x a a

Area of base 21 1

32 4

A a R x a

Surface Area 23S a

Dihedral angle

1 1arctan 2 2 2arcsin 3 arccos 70.53

3 3

o

Page 213: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 213 of 278

Height 2 2 16

3h a x a

Radius from edge length 2 2 16

2 4

x hR a

h

Inradius 1 1 16

12 4 3r R h a h R

Angle between bottom plane and centre 1arctan arctan 2

4

r

x

Edge length from Radius 4

6

Ra

Origami

Algebraic

1 6

3 12r R a

1 43

3 3 2

Rx a

1

2d x

Vertex Table (LHR) 0 0, ,0R

0

1

23

Page 214: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 214 of 278

1 0, ,r x

2 , ,

2

ar d

3 , ,

2

ar d

Edge Table

0 V[0], V[1]

1 V[0], V[2]

2 V[0], V[3]

3 V[1], V[2]

4 V[1], V[3]

5 V[2], V[3]

Face Table (LHR – Clockwise visible) 0 (right) V[0], V[1], V[2]

1 (front) V[0], V[2], V[3]

2 (left) V[0], V[3], V[1]

3 (bottom) V[1], V[3], V[2]

Geometric

Construct a cube use opposing vertices on the top and bottom faces of the cube as the vertices of the tetrahedron.

Cube – Hexahedron

Metrics

Let a be the length of an edge.

Let R be the radius of the circumscribing sphere.

Page 215: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 215 of 278

Let r be the in-radius – the radius of the inscribing sphere.

Number of faces 6

Number of vertices 8

Number of edges 12

Face type Square

Surface area 26aS

Volume 3aV

In-radius a

2

1

Radius a3

2

1

Dihedral angle

2

1

Edge length from radius

3

2Ra

Edge length from in-radius ra 2

Origami

Which of the origami patterns can be rendered by triangle strips? Which can be rendered by triangle fans?

Page 216: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 216 of 278

Algebraic

32

1 Rar

Vertex Table (LHR) 0 ),,( rrr

1 rrr ,,

2 rrr ,,

3 rrr ,,

4 rrr ,,

5 rrr ,,

6 rrr ,,

7 rrr ,,

Edge Table 0 0,1

1 0,3

2 0,7

3 1,2

4 1,6

5 2,3

6 2,5

7 3,4

8 4,5

9 4,7

10 5,6

11 6,7

Face Table (LHR – clockwise visible)

0 (front) 0,1,2,3

1 (right) 3,2,5,4

2 (top) 1,6,5,2

3 (back) 4,5,6,7

4 (left) 7,6,1,0

5 (bottom) 7,0,3,4

0

1 2

3

4

56

7

Page 217: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 217 of 278

Octahedron

Metrics

Let a be the length of an edge.

Let R be the radius of the circumscribing sphere.

Let r be the inradius – the radius of the inscribing sphere.

Number of faces 8

Number of vertices 6

Number of edges 12

Radius from edge length 12

2R a

Edge length from radius 2a R

Inradius 16

6

13

3

r a

r R

Origami

Algebraic

Vertex Table (LHR)

0 – top )0,,0( R

1 – front ),0,0( R

Page 218: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 218 of 278

2 – right )0,0,( R

3 – back ),0,0( R

4 – left )0,0,( R

5 – bottom )0,,0( R

Edge Table 0 0,1

1 0,2

2 0,3

3 0,4

4 1,2

5 1,4

6 1,5

7 2,3

8 2,5

9 3,4

10 3,5

11 4,5

Face Table (LHR – clockwise visible) 0 – top, front, right 0,2,1 – top, right, front

1 – top, front, left 0,1,4 – top, front, left

2 – top, back, left 0,4,3 – top, left, back

3 – top, back, right 0,3,2 – top, back, right

4 – bottom, front, right 5,1,2 – bottom, front, right

5 – bottom, front, left 5,4,1 – bottom, left, front

6 – bottom, back, left 5,3,4 – bottom, back, left

7 – bottom, back, right 5,2,3 – bottom, right, back

Dodecahedron

Metrics

Let a be the length of an edge.

Let R be the radius of the circumscribing sphere.

Let r be the inradius – the radius of the inscribing sphere.

Number of faces 12

Number of vertices 20

Number of edges 30

Page 219: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 219 of 278

Radius from edge length 150 10 5

10R a

Edge length from radius 10

50 10 5

Ra

Inradius from edge length 125 10 5

10r a

Origami

Algebraic

The standard (simple) form of a dodecahedron assumes an edge length of 5 1a . This gives a dodecahedron of radius 3 . The vertices of this

dodecahedron are 10, , , 1,0, , 1, ,0 , and 1, 1, 1 , where is the golden ratio.

Vertex Table 0 ( 1, 1, 1)

1 ( 1, 1, 1)

2 ( 1, 1, 1)

3 ( 1, 1, 1)

4 ( 1, 1, 1)

5 ( 1, 1, 1)

6 ( 1, 1, 1)

7 ( 1, 1, 1)

8 10, ,

Page 220: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 220 of 278

9 10, ,

10 10, ,

11 10, ,

12 1,0,

13 1,0,

14 1,0,

15 1,0,

16 1, ,0

17 1, ,0

18 1, ,0

19 1, ,0

Face Table – LH 0 13, 15, 7, 11, 3

1 15, 13, 1, 9, 5

2 15, 5, 18, 19, 7

3 18, 5, 9, 8, 4

4 6, 10, 11, 7, 19

5 0, 12, 14, 4, 8

6 0, 16, 17, 2, 12

7 0, 8, 9, 1, 16

8 1, 13, 3, 17, 16

9 4, 14, 6, 19, 18

10 2, 10, 6, 14, 12

11 2, 17, 3, 11, 10

Face Table – RH 0 3, 11, 7, 15, 13

1 5, 9, 1, 13, 15

2 7, 19, 18, 5, 15

3 4, 8, 9, 5, 18

4 19, 7, 11, 10, 6

5 8, 4, 14, 12, 0

6 12, 2, 17, 16, 0

Page 221: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 221 of 278

7 16, 1, 9, 8, 0

8 16, 17, 3, 13, 1

9 18, 19, 6, 14, 4

10 12, 14, 6, 10, 2

11 10, 11, 3, 17, 2

Icosahedron

Metrics

Let a be the length of an edge.

Let R be the radius of the circumscribing sphere.

Let r be the inradius – the radius of the inscribing sphere.

Number of faces 20

Number of vertices 12

Number of edges 30

Radius from edge length

15 5

8R a

Algebraic

The standard (simple) form of an icosahedron assumes an edge length of 2a . This gives a icosahedron of radius 1

2 5 58

. The vertices of

this icosahedron are 0, , 1 , 1,0, , and , 1,0 , where is the golden ratio.

Vertex Table 0 (0, , 1)

1 (0, , 1)

2 (0, , 1)

3 (0, , 1)

4 ( 1,0, )

5 ( 1,0, )

6 ( 1,0, )

7 ( 1,0, )

8 ( , 1,0)

9 ( , 1,0)

10 ( , 1,0)

11 ( , 1,0)

Page 222: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 222 of 278

Face Table - LH 0 0,1,8

1 0,8,4

2 0,4,6

3 0,6,10

4 0,10,1

5 1,10,7

6 1,7,5

7 1,5,8

8 2,3,11

9 2,11,6

10 2,6,4

11 2,4,9

12 2,9,3

13 3,9,5

14 3,5,7

15 3,7,11

16 4,8,9

17 5,9,8

18 6,11,10

19 7,10,11

Page 223: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 223 of 278

Origami

Sphere

Spheres can be generated using a regular icosahedron, quadric functions and trigonometry.

Trigonometry solution

Fill a vertex/index buffer with a sphere measured by slices (longitude) and stacks (latitude).

Page 224: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 224 of 278

procedure SPHERE( V, X, slices, stacks, R )

input: slices is the number of vertical partitions of the sphere

stacks is the number of horizontal partitions of the sphere

r is the radius of the sphere

output: V is a vertex buffer where the vertices contain a 3D coordinate – pos, a normal – nor, and a 2D texture coordinate – tex

X is an index buffer

1 1length V slices stacks

for iStack ← 0 to stacks do

𝑙𝑎𝑡𝑖𝑡𝑢𝑑𝑒 ← 𝜋2∙𝑖𝑆𝑡𝑎𝑐𝑘−𝑠𝑡𝑎𝑐𝑘𝑠

2∙𝑠𝑡𝑎𝑐𝑘𝑠

for iSlice ← 0 to slices do

𝑙𝑜𝑛𝑔𝑖𝑡𝑢𝑑𝑒 ← 𝜋2∙𝑖𝑆𝑙𝑖𝑐𝑒−𝑠𝑙𝑖𝑐𝑒𝑠

𝑠𝑙𝑖𝑐𝑒𝑠

𝑖 ← 𝑙𝑎𝑡𝑖𝑡𝑢𝑑𝑒(𝑠𝑙𝑖𝑐𝑒𝑠 + 1) + 𝑙𝑜𝑛𝑔𝑖𝑡𝑢𝑑𝑒

cos cos ,sin ,cos sinnor V i

pos V i R nor V i

,1longitude latitude

tex V islices stacks

0j

for latitude ← 0 to stacks – 1 do

for longitude ← 0 to slices – 1 do

1offset latitude slices longitude

X j offset

1 1X j offset slices

2 1 1X j offset slices

3X j offset

4 1 1X j offset slices

5 1X j offset

6j j

Tait-Bryan Angles (Garth Santor, January 2007)

Tait-Bryan angles are special-case Euler angles used in aerospace engineering and computer graphics amongst other disciplines. As will Euler

angles, an object’s orientation is expressed as a sequence of angles representing angular displacement from axes. In the Tait-Bryan system, the

angles represent roll, pitch and yaw. In a left-hand coordinate system, a z-x-y Euler angle system.

Page 225: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 225 of 278

Graphs

Definitions

The pictorial representative of a relation between variables.

From Gk. graphē, writing.

A graph EVG , where V is a set of vertices and E is a set of edges. Each edge is a pair wv, , where Vwv , . Vertices are often

referred to as nodes, and edges as arcs.

Arcs or edges are assumed to navigable in both directions. Such graphs are called undirected graphs.

Graphs in which the edge pairs are ordered are called directed graphs or digraphs. An alternate name is unidirectional graph.

A vertex v is said to be adjacent to vertex w if and only if Ewv , .

Some graphs have edges with a third component called a weight. The weight usually represents the cost of traversing that edge. These graphs

are called weighted graphs or weighted digraphs if unidirectional.

A path is a sequence of vertices that are connected by edges.

A cycle is a path in a digraph that begins and ends at the same vertex and contains at least one edge.

A graph is dense if the number of edges is large. 2VE .

A graph is sparse if the number of edges is small. VE .

Representations Graphs can be represented graphically. Circles indicate vertices or nodes – arrows indicate edges or arcs. Bi-directional graphs have arrows at

either end of the arcs, whereas digraphs have arrows only at one end.

Page 226: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 17

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 226 of 278

Digraph

Adjacency Tables

Adjacency tables (also called adjacency matrices) are 2-dimensional arrays each axis enumerates all the nodes in the graph. Adjacency is

represented by storing a Boolean value – true – at the cross-reference of the two nodes. Weighted graphs would store the arc weight in the cross-

referenced element.

The weighted graph above would have the following adjacency tables (left is weighted, right is un-weighted):

A B C D E

A -1 5 45 -1 -1

B 5 -1 30 20 -1

C 45 30 -1 10 7

D -1 20 10 -1 8

E -1 -1 7 8 -1

A B C D E

A f t t f f

B t f t t f

C t t f t t

D f t t f t

E f f t t f

Empty spots would be initialized to a value of zero or negative one.

You may have noticed that the information in the graph is symmetrical (i.e. the entry (x,y) contains the same information as entry (y,x) ). Memory

can be minimized by allocating rows that are no-longer than the row index. Row one has one element, row two has two elements, row n has n

elements. Any lookup into the table sorts the pairs before referencing the table element. If your algorithm can avoid lookups where the row and

column index are equal (i.e. where x = y) then only rowIndex – 1 elements need to be stored for each row of the table.

In a digraph, one axis would represent the origin node and the other axis the destination node.

8

Weighted Graph

b

c

d

30

10

20

a

5

45

e

7

Page 227: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 19

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 227 of 278

This general form for an adjacency table is useful for representing graphs in which any node could be connected to any other node.

The storage efficiency improves when the graph is dense but suffers when the graph is sparse.

To locate the neighbours of a given node, you examine each element in that node’s row of the table. This is relatively efficient for dense graphs,

but inefficient for sparse graphs.

Adjacency tables are often used to model airline graphs, phone and computer networks, or jump-gates in space games.

Adjacency Lists

Adjacency tables can be represented using linked lists. Each node maintains a list of the nodes that are adjacent to it.

The preceding adjacency table represented as an adjacency list would be:

B

A

A

B

C

C

C

B

C

D

D

D E

E

Direction Tables

Many games, most notably dungeon stomps have very sparse adjacency tables. Typically, a room will only connect to physically adjacent rooms.

Thus an adjacency table with 100 rooms would require a 100 by 100 matrix – 10,000 elements. We typically find that dungeon rooms can only be

exited in one of four directions – east, west, north, south. Since each room could only have a maximum of 4 adjacent rooms the most dense the

table could be is 400 used entries of the 10,000 total elements, or 0.4%.

A much more compact data structure, but much more limiting would be to store the numbers of the rooms accessible from the current room in

each of the 4 compass directions.

Example, given the following dungeon:

Page 228: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 19

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 228 of 278

0 1

2 3 4

5 6

We could produce a 7 by 7 adjacency table:

0 1 2 3 4 5 6

0 0 1 1 0 0 0 0

1 1 0 0 1 0 0 0

2 1 0 0 1 0 0 0

3 0 1 1 0 1 1 0

4 0 0 0 1 0 0 0

5 0 0 0 1 0 0 1

6 0 0 0 0 0 1 0

Storage efficiency is 29%.

Using a direction table, we would store:

N E S W

0 -1 1 2 -1

1 -1 -1 3 0

2 0 3 -1 -1

3 1 4 5 2

4 -1 -1 -1 3

5 3 6 -1 -1

6 -1 -1 -1 5

Storage efficiency is 50%.

Of course we could always store the adjacency matrix as a bitmap since all of the information is a true/false.

The direction table can also be stored as a bitmap, by renumbering rooms to correspond to cells in a complete grid.

Page 229: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 20

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 229 of 278

0 1 2

3 4 5

6 7 8

N E S W

0 0 1 1 0

1 0 0 1 1

2 0 0 0 0

3 1 1 0 0

4 1 1 1 1

5 0 0 0 1

6 0 0 0 0

7 1 1 0 0

8 0 0 0 1

Path-finding Graph path-finding determines a sequence of edges and nodes that connect a source node in the graph with a destination node in the graph. Path-

finding algorithms come in many varieties trading performance for path quality. Dijkstra’s single-source, shortest-path algorithm guarantees an

optimal path, but at the expense of time. The A* algorithm is a fast algorithm that finds good paths most of the time, but not all of the time.

Random Search Random search is virtually useless. It cannot determine whether a path to the destination is possible. Nor does it eliminate cycles in the path it

generates.

procedure RANDOM-SEARCH( Graph, s, e ) returns Queue

Q ← { s }

while s ≠ e do

randomly choose child such that ][, GEchilds

s ← child

ENQUEUE( Q, s )

return Q

Depth-first Search

Depth first search is a very natural search technique commonly employed by people solving maze problems, that is the “take every right turn until

you get stuck or cross your own path, then back up and take the other turn” approach. Depth-first search does exactly that – constantly moving

away from the source.

Page 230: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 21

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 230 of 278

The graph requires two extra elements, a colour for marking the explored vertices and a link to the parent node.

1. colour all the vertices white and set the parent links to nil.

2. investigate vertex start

The investigate procedure Tcolours each vertex TGREY when first visited and then TBLACK when all of the adjacent vertices have been visited

(although marking the vertex TBLACK is optional). Each newly visited vertex has its Tparent link set to the source vertex.

procedure DEPTH-FIRST-SEARCH( G, s )

for each vertex ][GVu do

color[u] ← white

parent[u] ← nil

DFS-INVESTIGATE( s )

procedure DFS-INVESTIGATE( u )

colour[u] ← grey

for each vertex ][uadjv do

if colour[v] = white

then parent[v] ← u

DFS-INVESTIGATE( v )

colour[u] ← black

Extracting the Path

The path from any vertex to the source vertex is stored in the graph. You can extract the path by following the parent links back from the

destination vertex to the source vertex.

procedure EXTRACT-PATH( G, s, t, P )

if s = t then

P ← s

else if parent[t] = NIL then

P ← Φ

else

P ← EXTRACT-PATH( G, s, parent[t], P ) + t

Breadth-first Search

This breadth-first search algorithm presented here requires that the graph store three additional attributes: a colour, a distance and a link to another

vertex.

1. We start by colouring all of the vertices WHITE to indicate that they have not been processed. The distance from the source is unknown is

represented by an impossible value (such as –1) or ∞. The parent links are set to NIL.

2. Set the source vertex colour to GREY, indicating that the node has been visited but not that vertices adjacent to it have not been explored.

Set its distance to zero. Indicating that it is zero hops from the source.

3. Add the source vertex to a queue of GREY vertices (i.e. vertices we are visiting, but not finished with).

Page 231: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 21

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 231 of 278

4. While the queue contains grey vertices, do

a. get and remove the vertex from the front of the queue

b. add each adjacent WHITE vertex to the queue after set its distance to one hop more than the current vertex and setting its parent to

the current vertex

c. colour the current vertex BLACK

procedure BREADTH-FIRST-SEARCH( G, s ) inputs: G, a graph

s, the path source vertex

outputs: G, modified graph (colours, distance and parents updated)

for each Tvertex u V G s

Tdo color[u] ← WHITE

distance[u] ← ∞

parent[u] ← NIL

color[s] ← GREY

distance[s] ← 0

parent[s] ← NIL

Q ← { s }

while Q do

u ← head[Q]

for each [ ]v Adj u do

if colour[v] = WHITE

then colour[v] ← GREY

distance[v] ← distance[u] + 1

parent[v] ← u

ENQUEUE( Q, v )

DEQUEUE( Q )

colour[u] ← BLACK

As with the depth-first search the path can be extracted using the EXTRACT-PATH procedure.

Dijkstra’s Algorithm

Created by Dr. Edsger Wybe Dijkstra (1930-2002), this single-source, shortest-path algorithm is amazingly efficient.

procedure SHORTEST-PATH( G, s, d )

INITIALIZE-SINGLE-SOURCE( G, s )

Q ← V[G]

while Q ≠ Φ do

u ← EXTRACT-MIN( Q )

for each vertex ][uadjv do

RELAX( u, v, w )

Page 232: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 21

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 232 of 278

procedure RELAX( u, v, weight )

if cost[v] > cost[u] + weight(u,v)

then cost[v] ← cost[u] + weight(u,v)

parent[v] ← u

procedure INITIALIZE-SINGLE-SOURCE( G, s )

for each vertex ][GVv do

cost[v] ← ∞

parent[v] ← nil

cost[s] ← 0

A* Algorithm

One of the greatest problems with DFS, BFS and Dijkstra’s algorithm is that they all search the entire graph for a solution. This can be prohibitive

in a real-time application with a large graph. The A* star algorithm is a variation of DFS that borrows some features from Dijkstra’s algorithm. In

essence, it’s a depth-first search that guesses at the best direction to search. It quits as soon as a solution is found.

The heuristic used to guess at the best direction can be tuned to exhibit seemingly complex behaviour such as preferring the same altitude to higher

altitudes when navigating through mountainous terrain.

The graph vertex requires three cost attributes g, h, f that indicate:

1. the current cost to get to the current vertex (g),

2. the best guess cost to get to goal vertex (h),

3. the best guess at the final total cost (f = g + h)

and a link to the parent vertex in the search path.

Page 233: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 21

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 233 of 278

procedure A-STAR-SEARCH( G, s, e )

g[s] ← 0

h[s] ← HEURISTIC( s, e )

f[s] ← g[s] + h[s]

ENQUEUE( OpenList, s )

while OpenList ≠ Φ do

find b OpenList such that [ ] [ ],f b f x x OpenList

if b = e return ∆path has been found

for each [ ]c adj b do

g ← g[b] + DISTANCE( b, c )

h ← HEURISTIC( c, e )

f ← g + h

if c OpenList and f > f[c] then continue

if c ClosedList and f > f[c] then continue

OpenList OpenList c

ClosedList ClosedList c

parent[c] ← b

h[c] ← h

g[c] ← g

f[c] ← f

OpenList OpenList c

ClosedList ClosedList b

Logic & Boolean Algebra There are three major systems of logic:

Syllogistic logic – 19 correct argument forms identified by Aristotle.

Propositional logic – building block approach of English mathematician George Boole.

Predicate logic – combination of syllogistic and propositional logic created by Gottlob Frege.

Mathematical Induction Mathematical induction is method for proving that a proposition (such as a formula) is true for all possible values.

Theorem (First Principle of Mathematical Induction)

Let ( )P n be a predicate and 0n be an integer for which the following conditions are satisfied.

1. Every integer greater than or equal to 0n belongs to the domain of ( )P n ;

Page 234: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 21

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 234 of 278

2. 0P n is true;

3. for every integer 0n n , ( )P n implies ( 1)P n .

Then ( )P n is true for each integer 0n n .

Example: sum of a series of integers

0

1

2

n

i

n ni

Let 1

2

n nP n

where n¥

0

0

0 0 10 0

2 i

P i

, which satisfies point 2 of the theorem.

To satisfy point 3 of the theorem we assume that P n is true and show that 1P n necessarily follows.

2

2 2

2 2

( 1) 1 ( )

1 1 1 11

2 2

1 2 2 1

2 2 2

3 2 2 2

2 2 2

3 2 3 2

2 2

P n n P n

n n n nn

n n n n n

n n n n n

n n n n

Theorem (Second Principle of Mathematical Induction)

Let ( )P n be a predicate and 0n be an integer for which the following conditions are satisfied.

1. Every integer greater than or equal to 0n belongs to the domain of ( )P n ;

2. 0P n is true;

3. for every integer 0n n , 0.. ,k n n P k implies ( 1)P n .

Then ( )P n is true for each integer 0n n .

Propositional Logic Proposition logic connectives

Name Meaning Notation

Page 235: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 21

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 235 of 278

negation not

conjunction and

disjunction or

implication if … then …

equivalence (biconditional) if and only if

Negation

A negation p is true if and only if p is false.

p p

True false

False true

English interpretations:

not p

p does not hold

it is not the case that p

p is false

Conjunction

A conjunction qp is true if and only if both p and q are true.

p q qp

true true true

true false false

false true false

false false false

English interpretations:

p and q

p but q

Page 236: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 21

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 236 of 278

not only p but q

p while q

p despite q

p yet q

p although q

Disjunction

A disjunction qp is true if and only if p is true or q is true. That is, either p or q is true or both are true.

p q qp

true true true

true false true

false true true

false false false

English interpretations:

p or q

p or q or both

p and/or q

p unless q

Implication

An implication qp is false if and only if p is true and q is false.

p q qp

true true true

true false false

false true true

false false true

English interpretations:

Page 237: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 21

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 237 of 278

if p then q

q if p

p only if q

q when p

p is sufficient for q

q is necessary for p

p implies q

p materially implies q

Equivalence

An equivalence, qp is true if and only if both p and q have the same truth value.

p q qp

true true true

true false false

false true false

false false true

English interpretations:

p if and only if q

q iff p

p is necessary and sufficient for q

p exactly if q

p is materially equivalent to q

Page 238: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 21

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 238 of 278

Number Systems

Two’s Complement

Fast Conversion – for humans Two’s complements numbers can be quickly converted to its negative by:

1. Copying all the zeros from the LSB until the first one is reached.

2. Copy that one.

3. Flip the remaining bits.

Example:

0001 1100 → 1110 0100

0001 1100 → 1110 0011 + 1 → 1110 0100

Sign Extension When increasing the number of bits in a two’s complement representation extend the sign bit (MSB) into the extra bits.

Statistics

Arithmetic Mean Mean is the statistic that most people call ‘average’ and is a measure of central tendency.

1

1 N

i

i

x xN

The symbol μ is often used to represent the mean.

Frequency distribution A frequency distribution tabulates raw data by dividing the range of the data values in even intervals and then counting the number of samples that

fall into each interval. The frequencies are typically expressed as absolute counts or as a relative count (percentage of overall data set).

Example:

{1,2,3,3,4,5,5,5,6,7,7,8}S

Page 239: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 21

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 239 of 278

Class interval Absolute frequency Relative frequency

1.0 – 2.9 2 0.167

3.0 – 4.9 3 0.250

5.0 – 6.9 4 0.333

7.0 – 8.9 3 0.250

Histogram A graphical representation of a frequency distribution where the frequency is plotted against the interval classes. Typically a bar chart is used.

Mode The mode of a set is the most commonly occurring value in that set.

For example:

mode

{1,2,3,3,4,5,5,5,6,7,7,8}

5

S

S

When two values appear as the most commonly occurring value, the set is called bi-modal and when there are more than two most-commonly

occurring values the set is called multi-modal.

mode

{1,2,3,3,4,5,5,5,6,7,7,7,8}

{5,7}

S

S

Standard Deviation & Variance Variance is the mean of the squares of the deviations from the data set’s mean.

N

X

2

2

is the formula for the population variance.

Standard deviation is the square root of the variance.

N

X

2

2

is the formula for the population standard deviation.

Notes:

X is data set.

N is size of data set.

μ is the mean of X

Page 240: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 21

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 240 of 278

Implementation

function VARIANCE( X ) returns a real number

← MEAN( X )

accumulator ← 0

for each x X do

2

accumulator accumulator x

return accumulator length X

Statistical Median A measure of central tendency and an ordering statistic that gives the ‘middle’ value of a sample. It is the value for which ½ of the samples have a

lower value and ½ of the samples have a greater value.

2 1

2 2 1

1mod 22

0mod 22

i

i i

XX

xX X

X

%

Page 241: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 21

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 241 of 278

Trigonometry (from Greek: trigonon = three angles, metro = measure)

Trigonometry is the branch of mathematics dedicated to angles, triangles and the

functions that describe their relationships. Many consider trigonometry the

computational component of geometry and therefore a subtopic of geometry.

Trigonometric Functions

The trigonometric functions represent ratios of right- angle triangles.

sinopposite

hypotenuse

1csc

sin

hypotenuse

opposite

cosadjacent

hypotenuse

1sec

cos

hypotenuse

adjacent

sintan

cos

opposite

adjacent

coscot

sin

adjacent

opposite

Inverse functions

Many students often confuse the trigonometric inverse functions with arithmetic inverse functions. This is an unfortunate problem with the

notation.

The arithmetic inverse of the sine function is: 1 1

sin cscsin

hypo

tenu

se op

posite

P(x,y)

+x

+y

θ

Page 242: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 21

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 242 of 278

The trigonometric inverse produces the angle from the ratio (as opposed to the trig. functions that produce the ratio from the angle). The

unfortunate notation uses an exponent squeezed in between the function name and the angle variable.

e.g. 1sinopposite

hypotenuse This is distinctly different from

1

sinopposite

hypotenuse

It is for this reason that I suggest using the older notation:

arcsin arccos arctanopposite adjacent opposite

hypotenuse hypotenuse adjacent

This notation has two additional advantages:

1. It constantly reminds us that the inverse trigonometric functions produce an angular measure of arc.

2. It matches the notation used by most computer math libraries. e.g. atan() is the arc tangent function in the C-Standard library.

Just to make things confusing…

The same is not true of positive exponents. Mathematicians do write the squares of trigonometric functions as:

22sin sin sin sin

Useful formulae

Given, ,P x y is a point on a circle of radius r.

r hypotenuse The radius of the circle is the same as the magnitude (or length) of the

hypotenuse.

cosx r The x-component can be calculated as a function of angle and radius.

siny r The y-component can be calculated as a function of angle and radius.

arctany

x

The angle from the origin to point P.

2 2sin cos 1 From the Pythagorean theorem. Usually written as

2 2tan 1 sec This follows from the Pythagorean theorem above.

2 21 cot csc This follows from the Pythagorean theorem above.

2 2

2 2

sin sin sin sin

cos cos

An often useful identity.

Page 243: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Mathematics Section 21

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 243 of 278

2 2

2 2

cos cos cos sin

cos sin

An often useful identity.

cos cos cos sin sin

sin cos sin sin cos

Page 244: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Operating Systems Section 22

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 244 of 278

Operating Systems

Windows Vista

Automatic Log In 1. Launch a more advanced user accounts management application by typing ‘control userpasswords2’ in the start menu’s search box.

2. Uncheck ‘Users must enter a user name and password to use this computer’.

3. Click OK.

4. Open Power Options window in Control Panel.

5. Click: ‘Change plan settings’.

6. Click ‘Change advanced power settings’.

7. Under addition settings, set ‘Require a password on wakeup’ to ‘no’.

8. Open ‘Personalization’ window in Control Panel.

9. Click ‘Screen Saver’.

10. Uncheck ‘On resume, display logon screen’.

Page 245: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Physics Section 23

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 245 of 278

Physics

General

Bounce (Garth Santor, January 2007)

Some energy retention rates of common balls bouncing on a steel plate.

Ping-pong ball 15%

Baseball 32%

Golf ball 36%

Soccer ball 40%

Tennis ball 49%

Basket ball 56%

Super ball 81%

Steel ball 98%

Gravity Acceleration due to gravity 9.8 / /g m s s

Distance an object falls 21

2d g t

Time to fall a given distance 2dt

g

Instantaneous velocity after time t iv g t

Instantaneous velocity after distance d 2iv gd

Average velocity over time t 1

2av g t

Page 246: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Physics Section 23

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 246 of 278

Average velocity over distance d 2

2a

gdv

Material Properties

Description

Material properties describe the light response properties of a material. Light response is separated into 5 categories; ambient colour, diffuse

colour, specular colour, emissive colour and shininess. All colour properties are expresses as four-component clamped colours. The colour

components are red, green, blue and transparency, with values range of 0.0 to 1.0. The value 0.0 represents black for the colour components and

fully transparent for the transparency component.

Light Source Materials

name ambient diffuse specular emission shininess

white 0, 0, 0, 0 0, 0, 0, 0 0, 0, 0, 0 1, 1, 1, 1 0.0

Page 247: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Physics Section 23

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 247 of 278

Metals

Page 248: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Physics Section 23

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 248 of 278

name ambient diffuse specular emission shininess

brass 0.329412,

0.223529,

0.027451,

1.0

0.780392,

0.568627,

0.113725,

1.0

0.992157,

0.941176,

0.807843,

1.0

0,

0,

0,

0

27.8974

bronze 0.2125,

0.1275,

0.054,

1.0

0.714,

0.4284,

0.18144,

1.0

0.393548,

0.271906,

0.166721,

1.0

0,

0,

0,

0

25.6

bronze (polished)

0.25,

0.148,

0.06475,

1.0

0.4,

0.2368,

0.1036,

1.0

0.774597,

0.458561,

0.200621,

1.0

0,

0,

0,

0

76.8

chrome 0.25,

0.25,

0.25,

1.0

0.4,

0.4,

0.4,

1.0

0.774597,

0.774597,

0.774597,

1.0

0,

0,

0,

0

76.8

copper 0.19125,

0.0735,

0.0225,

1.0

0.7038,

0.27048,

0.0828,

1.0

0.256777,

0.137622,

0.086014,

1.0

0,

0,

0,

0

12.8

copper (polished)

0.2295,

0.08825,

0.0275,

1.0

0.5508,

0.2118,

0.066,

1.0

0.580594,

0.223257,

0.0695701,

1.0

0,

0,

0,

0

51.2

gold 0.24725,

0.1995,

0.0745,

1.0

0.75164,

0.60648,

0.22648, 1.0

0.628281,

0.555802,

0.366065,

1.0

0,

0,

0,

0

51.2

gold (polished)

0.24725,

0.2245,

0.0645,

1.0

0.34615,

0.3143,

0.0903,

1.0

0.797357,

0.723991,

0.208006,

1.0

0,

0,

0,

0

83.2

pewter 0.105882,

0.058824,

0.113725,

1.0

0.427451,

0.470588,

0.541176,

1.0

0.333333,

0.333333,

0.521569,

1.0

0,

0,

0,

0

9.84615

silver 0.19225,

0.19225,

0.19225, 1.0

0.50754,

0.50754,

0.50754, 1.0

0.508273,

0.508273,

0.508273,

1.0

0,

0,

0,

0

51.2

Page 249: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Physics Section 23

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 249 of 278

silver (polished)

0.23125,

0.23125,

0.23125, 1.0

0.2775,

0.2775,

0.2775,

1.0

0.773911,

0.773911,

0.773911,

1.0

0,

0,

0,

0

89.6

Miscellaneous Substances

name ambient diffuse specular emission shininess

rubber (black)

0.02,

0.02,

0.02,

1.0

0.01,

0.01,

0.01,

1.0

0.4,

0.4,

0.4,

1.0

0,

0,

0,

0

10.0

rubber (cyan)

0.0,

0.05,

0.05,

1.0

0.4,

0.5,

0.5,

1.0

0.04,

0.7,

0.7,

1.0

0,

0,

0,

0

10.0

rubber (green)

0.0,

0.05,

0.0,

1.0

0.4,

0.5,

0.4,

1.0

0.04,

0.7,

0.04,

1.0

0,

0,

0,

0

10.0

rubber (red) 0.05,

0.0,

0.0,

1.0

0.5,

0.4,

0.4,

1.0

0.7,

0.04,

0.04,

1.0

0,

0,

0,

0

10.0

rubber (white)

0.05,

0.05,

0.05,

1.0

0.5,

0.5,

0.5,

1.0

0.7,

0.7,

0.7,

1.0

0,

0,

0,

0

10.0

rubber (yellow)

0.05,

0.05,

0.0,

1.0

0.5,

0.5,

0.4,

1.0

0.7,

0.7,

0.04,

1.0

0,

0,

0,

0

10.0

shiny (white) 1,1,1,1 1,1,1,1 1,1,1,1 0,0,0,0 100.0

Page 250: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Physics Section 23

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 250 of 278

Plastics

name ambient diffuse specular emission shininess

black 0.0,

0.0,

0.0,

1.0

0.01,

0.01,

0.01,

1.0

0.5,

0.5,

0.5,

1.0

0,

0,

0,

0

32.0

cyan 0.0,

0.1,

0.06,

1.0

0.0,

0.50980392,

0.50980392,

1.0

0.50196078,

0.50196078,

0.50196078,

1.0

0,

0,

0,

0

32.0

green 0.0,

0.0,

0.0,

1.0

0.1,

0.35,

0.1,

1.0

0.45,

0.55,

0.45,

1.0

0,

0,

0,

0

32.0

red 0.3,

0,

0,

1

0.6,

0,

0,

1

0.8,

0.6,

0.6,

1

0,

0,

0,

0

32.0

white 0,

0,

0,

1

0.55,

0.55,

0.55,

1

0.70,

0.70,

0.70,

1

0,

0,

0,

0

32.0

yellow 0,

0,

0,

1

0.5,

0.5,

0,

1

0.60,

0.60,

0.5,

1

0,

0,

0,

0

32.0

Page 251: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Physics Section 23

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 251 of 278

Stones

name ambient diffuse specular emission shininess

emerald 0.0215,

0.1745,

0.0215,

1.0

0.07568,

0.61424,

0.07568,

1.0

0.633,

0.727811,

0.633,

1.0

0,

0,

0,

0

76.8

jade 0.135,

0.2225,

0.1575,

1.0

0.54,

0.89,

0.63,

1.0

0.316228,

0.316228,

0.316228,

1.0

0,

0,

0,

0

12.8

obsidian 0.05375,

0.05,

0.06625,

0.82

0.18275,

0.17,

0.22525,

0.82

0.332741,

0.328634,

0.346435,

0.82

0,

0,

0,

0

38.4

pearl 0.25,

0.20725,

0.20725,

0.922

1.0,

0.829,

0.829,

0.922

0.296648,

0.296648,

0.296648,

0.922

0,

0,

0,

0

11.264

ruby 0.1745,

0.01175,

0.01175,

0.55

0.61424,

0.04136,

0.04136,

0.55

0.727811,

0.626959,

0.626959,

0.55

0,

0,

0,

0

76.8

turquoise 0.1,

0.18725,

0.1745,

0.8

0.396,

0.74151,

0.69102,

0.8

0.297254,

0.30829,

0.306678,

0.8

0,

0,

0,

0

12.8

Game

Collision Detection Collision detection is an expensive stage in a game’s logic/physics system. The number of possible collisions grows significantly as more objects

are introduced into the model. Examine the following table.

# of objects # of possible collisions/interactions

1 0

2 1

3 3

4 6

Page 252: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Physics Section 23

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 252 of 278

5 10

n

1

0

11

2

n

i n n

Clearly, collisions/interactions are 2O n .

Any technique that can reduce the number of interactions could potentially save huge amounts of processing.

Bounding circle/sphere collision detection

One of the simplest forms of collision detection is bounding circle (2D) or bounding sphere (3D). The idea is

to measure the distance between the centre points of the two objects being tested for collision. If the distance

between the two objects is less than the sum of radii of the smallest circle/sphere that fully encloses the

object, then a collision has occurred.

2 2 2

x y z

r r

D A B

d D D D

d A B

The presence of a square root in the distance formula is a short-coming since square root calculations are

rarely cheap.

However, the actual distance is not required, just the whether or not a collision occurred. Therefore, the square of the distance can be compared to

the square of the sum of the radii.

2 2 2 2

22

x y z

r r

D A B

d D D D

d A B

The new calculation can be computed using only adds and multiplies and is potentially much faster.

Metric

Prefixes

micro-

Combining form: one millionth of a specified unit. E.g. microsecond is a millionth of a second. [ < Gk. micros small]

milli-

Combining form: one thousandth of a specified unit. E.g. millisecond is a thousandth of a second. [ < L. mille thousand]

r

r

d

A

B

Page 253: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Physics Section 23

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 253 of 278

nano-

Combining form: one billionth of a specified unit. E.g. nanosecond is a billionth of a second. [ < Gk. nanos dwarf]

pico-

Combining form: one trillionth of a specified unit. E.g. picosecond is a trillionth (1E-12) of a second. [ < Sp. small quantity, peak]

Page 254: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 254 of 278

Programming Concepts

Concurrent Programming

Best Practices

Avoid Calling Unknown Code While Inside a Critical Section See Dr. Dobb’s Journal: Issue 403 – December 2007.

To summarize Herb Sutter:

Avoid calling library functions that cannot promise the absence of locks.

Avoid calling plug-ins.

Avoid calling other callbacks, function pointers, function delegates, etc.

Avoid calling virtual methods.

Avoid calling generic methods, or methods on a generic type.

Use Lock Hierarchies to Avoid Deadlock See Dr. Dobb’s Journal: Issue 404 – January 2008.

To quote Herb Sutter:

Write a wrapper around each of your favourite language- or platform-specific mutex types, and let the wrapper’s constructor(s) take a

level number parameter that is in a myLevel member. Use these wrappers everywhere.

Give the wrapper class a thread-local static variable called currentLevel, initialized to a value higher than any valid lock level.

In the wrapper’s lock method, assert that currentLevel is greater than myLevel, the level of the mutex that you’re about to try to acquire.

Remember, if the previous value of currentLevel is using another member variable, then set currentLevel = myLevel; and acquire the lock.

In the wrapper’s unlock method, restore the previous value of currentLevel.

As needed, also wrap other necessary methods you need to be able to use, such as try_lock. Any of these methods that might try to acquire

the lock should do the same things lock does.

Finally, write a “lock-multiple” method lock( m1, m2, … ) that takes a variable number of lockable objects, asserts that they are all at the

same level, and locks them in their address order (or their GUID order, or some other globally consistent order).

Page 255: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 255 of 278

Internal vs. External Locking When a function or method is a critical section (such as the enqueue and deque operations of a shared queue), we must decide whether to have the

method establish the lock or the caller establish the lock.

Internal Locking

Pros

Easy to use – the lock is applied to the critical section by the function/method automatically.

Less code – lock is implemented once in the function/method and not at each call location.

Reliability – the correct lock is always applied – no mix ups.

Cons

Efficiency – repeated calls to the function cause multiple locking/unlocking cycles.

Lack of transparency – lock is not obvious to the caller.

Risk of deadlock – in a multiple lock scenario, the lack of transparency makes it difficult for the caller to notice the possibility of

deadlock.

External Locking

Pros

Transparency – the lock is visible to the coder.

Deadlocks – easier to prevent deadlocks in a multiple-lock scenario.

Efficiency – can lock once and perform repeated calls.

Cons

More code – every call must have its own locking code.

Reliability – could forget lock, or use the wrong lock.

Efficiency – could apply lock for a longer duration then necessary (although this is relatively easy to avoid.)

Conclusions If you don’t know, use external locking. It provides good performance and safety.

If you can guarantee that the object will never be used in a multiple lock scenario, use internal locking.

Page 256: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 256 of 278

Zombie Process A zombie process is a process that has finished processing but has not yet been deallocated by the parent process.

Zombie processes occur as a natural part of a process’ life cycle. Processes typically end when they call the exit() or abort() routines or their

main() function returns. At this time the kernel releases any resources allocated to the process, but it maintains the exit status and process ID in

the process table. This dead but not buried state is called the zombie state. This state is identifiable using Unix’s ps command and is indicated by

a ‘Z’ in the status column. (Linux requires ‘ps j’ to get the status listing.)

A process remains in the zombie state until its parent process checks for the completion of the process by checking its exit status.

But what if the parent doesn’t check the child’s exit status (via wait() )? The zombie process cannot be killed with kill -9. Zombie aren’t

processes, therefore they can’t response to the kill signal. The way to kill a zombie is to kill its parent. In computers, parricide = infanticide. If

the parent terminates with zombie connected to it, the zombie children die too.

A zombie process is more properly, but less popularly called a defunct process.

Development Process

Code Changes – Big/Little A big-change is a change to a function or object that breaks existing user code.

A little-change is a change to a function or object that does not break existing user code. The two principles of a little-change are:

Require no more. The change to the function or object should not impose new requirements on caller. For example an image file loader function

that originally only read Windows Bitmap files, but now reads JPEG and PNG files qualifies as a little change. If doing so requires the caller to

add a ‘file-type’ parameter, the change would be a big change as the call would need to be rewritten.

Promise no less. The change to the function or object should not remove a capability from or restrict the range of values it can operate on. For

example if during the preceding example the maximum image file size loadable decreased from 100MB to 99MB, the change would be a big-

change.

GOF – Gang of Four Gang-Of-Four, the four authors of Design Patterns: Elements of Reusable Object-Oriented Software [DP-95]. They are:

Erich Gamma

Richard Helm

Ralph Johnson

John Vlissides

They use the acronym GOF since listing all their names individually is tiresome.

Page 257: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 257 of 278

Reuse

Black-box Black-box reuse refers to the construction of new objects from existing objects by employing object composition. It is called black-box because

the internal details of the new object are not visible to the users of the object. The objects appear as “black boxes”.

Black-box First Part

Second Part

1

-fp

1

-sp

Object composition has the following benefits (as compared to inheritance):

Composition can occur at run-time (dynamic binding).

Encapsulation is respected – internal objects can be changed at any time without changing the host class’ interface.

Lower coupling – fewer implementation dependencies.

Classes tend to be smaller and better focused.

Composition vs. Inheritance Background: Putting Reuse Mechanisms to Work – Inheritance versus Composition [DP-95: pages 18-20]

In this section of the HTUGOFUTH’s book, they discuss the relative merits of both inheritance as a mechanism of object reuse as well as composition as a

mechanism of object reuse. They also provide two principles of reusable object-oriented design:

1. Program to an interface, not an implementation.

2. Favour object composition over class inheritance.

I would caution the designer to first examine their beliefs about object-oriented design, by choosing the statement that best reflects their beliefs:

Object-oriented design is a methodology whose purpose is to facilitate code reuse.

or…

Object-oriented design is a methodology whose purpose is to help a programmer model the problem domain more directly.

It is unfortunate that object-oriented design is so good at producing reusable code, since many (perhaps most) believe that is its purpose. Code

reuse is just a benevolent side-effect of good object-oriented design.

Page 258: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 258 of 278

When choosing between composition and inheritance, the first question that should be asked is, “What better models the real object in the problem

domain – composition or inheritance?” If the real objects in the problem domain have a has-a relationship, then object composition should be

preferred. (e.g. a car has a motor. a car object should contain a motor object.) If the real objects in the problem domain have an is-a

relationship, then inheritance should be preferred. (e.g. an apple is a fruit. an apple object should inherit from a fruit object.)

If the design truly represents the real world objects as they are in the problem domain, then reuse becomes natural and almost automatic. (e.g. if

your fruit abstraction truly and accurately models all that is common to all fruit, then every fruit type object can safely be derived from it.

Bananas, pineapples, oranges and tomatoes.)

The real debate between composition and inheritance usually arises when the objects in the problem domain can be viewed as having either a has-

a or an is-a relationship. Or possibly both! (e.g. XIconWindow vs. a GDIIconWindow. Both classes are Windows and specifically IconWindows

– the is-a relationship. Yet both also have an implementation – X or GDI. Which to choose? Try the Bridge Pattern [DP-95: page 151] which

helps you represent both relationships.

White-box White-box reuse refers to the construction of new objects from existing object by employing subclassing. It is called white-box because the

internal details of the new object are often visible to the users of the object.

White-box

Subclass

Object subclassing has the following benefits (as compared to object composition):

Subclassing occurs at compile time (static binding). More opportunities for compiler optimization.

Easier to modify the implementation.

Maintains object type. The new object can be used by any function that understands the base type.

Errors Error handling is a difficult task for which the programmer needs all the help that can be provided. – Bjarne Stroustrup [STRO1995]

There are two ways to write error-free programs; only the third one works. – Alan Perlis

It’s hard enough to find an error in your code when you’re looking for it; it’s even harder when you’ve assumed your code is error-free. –

Steve McConnell

Page 259: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 259 of 278

What is an error? The Merriam-Webster dictionary defines an error as “5: a deficiency or imperfection in structure or function” – a good general

definition but too vague to be a useful definition for programming.

The most useful definition of a program error that we have found was expressed by Herb Sutter in his column from the C/C++ User’s Journal.

(‘Sutter’s Mill: When and How to Use Exceptions’, CUJ August 2004)

Sutter starts by declaring that “a function is a unit of work and failures should be viewed as errors.” In other words “an error is any failure that

prevents a function from succeeding.”

In design-by-contract programming, we document the preconditions, postconditions and invariants which specify the conditions under which

successful execution should occur. Therefore we have three types of errors:

Precondition errors: any condition that prevents a function from satisfying its precondition is an error.

Postcondition errors: any condition that prevents a function from satisfying any postcondition is an error. Failing to produce a valid return value

is a postcondition error.

Invariant errors: any condition that prevents the function from re-establishing an invariant that the function (or method) is responsible for

maintaining is an error.

Definition

A program error is any failure that prevents a function from succeeding. Function success is defined by the program satisfying all of the

preconditions, postconditions and invariants specified for that function.

Types of Errors

Syntax Errors

Syntax errors are errors in source code that prevent the code from being compiled or interpreted. Syntax errors are not considered to be critical

errors as they manifest during development. I would suggest that compiling on the compiler’s highest warning level is recommended as it will

identify questionable code (which doesn’t always do what we intend.)

Logic Errors

Logic errors are errors that should never occur. An example of a logic error is passing a negative number to a square-root function. The logic of

the program should prevent this circumstance from ever occurring. Logic errors are typically caught by assertions.

Run-time Errors

Run-time errors are errors that occur during the execution of a program whose timing is unpredictable or caused by factors external to the

program. An example of a run-time error is running out of memory, failing to open a file (because it doesn’t exist) or bad input.

Design Principles

When coding, programmers should endeavour to code in such a way as to implement as many of the following principles:

1. Not-my-problem principle. Satisfying preconditions are not the responsibility of the called function. These are program logic errors and

should not occur during run-time. Treat these errors as bugs that are to be eliminated during development. Hence, not my problem!

Page 260: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 260 of 278

2. Sanity principle. Always maintain invariants! If an error occurs, the invariant state should continue to be satisfied. The object’s or system’s

sanity is maintained.

3. Atomic principle. Treat functions as atomic operations. The function should either fully complete (i.e. satisfy all conditions/contracts) or fully

fail (i.e. satisfy no postcondition, but maintain the invariants). This principle necessarily requires a rollback approach to design. If the function

fails half way, rollback to the state that existed at the beginning of the function.

4. No-fail/No-throw principle. The ideal function will never fail. This is impossible to enforce for most functions, but some functions require a

no-fail/throw guarantee. Destructors and deallocation functions must never fail. Standard swap functions don’t require this but can easily be

implemented as a no-fail/no-throw function.

The not-my-problem principle can always be implemented. Preconditions are by definition testable and therefore can be implemented as an

assertion.

The sanity principle is the most basic run-time principles to maintain and is required for the succeeding principles to be enforced.

The atomic principle is usually easy to implement on small functions, but can be difficult to implement on larger functions. In some situations we

may be compelled to dismiss this principle for reasons of performance or memory use.

Error handling technologies

Once an error has been detected we have several options as to how we may respond to the error. They are:

1. Terminate (with or without report).

2. Return an error code.

3. Return a legal value and leave the program in an error state.

4. Call a function specifically designed to handle the error.

5. Throw an exception.

Terminate

This doesn’t really handle the error; so much as it informs you why the program is terminating. This is a suitable response for the not-my-problem

principle. Or errors so severe that recovering would be impractical.

This can be thought of as a ‘run-time’ assertion.

Return an Error Code

Returning an error code from a function (as either the return value or an output parameter) is a traditional approach to error handling that can be

found in many libraries such as the C-Runtime Library.

The positive:

Easy to code a thread-safe implementation.

The negative:

Single level of granularity. Each and every function must be tested individually.

Page 261: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 261 of 278

Error detection code can impose substantial overhead. Some estimates suggest that error handling code can triple the size of the code since

every function must be tested individually.

Errors don’t automatically propagate down the call stack. If the error needs to be detected at a higher level then the error code must be explicitly

returned to each caller until the appropriate level has been reached.

This approach is deprecated by most modern languages.

Return a Legal Value and Leave the Program in an Error State

This approach uses a global error state variable to hold the error code from the last failing function. This traditional approach to error handling is

also found in many libraries including the C-Runtime Library.

The negative:

Easy to ignore errors.

Errors don’t automatically propagate down the call stack.

Making the library thread-safe requires that the global error variable be instantiated for each thread that accesses the library.

The positive:

Error detection granularity is user defined. The programmer can test after each call or after each block of code.

Call a Function Specifically Designed to Handle the Error

While this is one of the most powerful approaches to error handling it is one of the least used. An example of the this approach is the

Tset_new_handlerT from the C++ Standard Library which allows the programmer to provide a function to be called whenever the TnewT operator

cannot allocated the requested block of memory.

The negative:

Very difficult to implement. The programmer must devise a reasonable response that can be invoked without knowledge of the caller context.

Propagating the error down the call stack is not handled by this approach. One of the other techniques must be applied.

The error handling context is largely divorced from the calling context.

The positive:

Lowest runtime overhead. If the handler is capable of resolving the problem the calling code need take no special action to deal with the error.

Once a handler is hooked, all errors are responded to by the system. Errors cannot be ignored!

Throw an Exception

Most modern languages offer structured exception handling as an error handling mechanism. Many languages prefer this approach: Java, .NET

and Standard C++.

The negative:

Not well understood by the programming community.

Page 262: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 262 of 278

The positive:

Minimal overhead to the normal execution path.

Automatically propagates down the call stack.

Thread safe

Cannot be ignored.

Error detection granularity is determined by the programmer.

Bug A defect or fault in a machine, design, plan or most commonly software.

Most people believe that the term originates with the discovery by Grace Murray Hopper of a moth that had short-circuited the Harvard computer

in the middle of the 20P

thP century, but the term is actually quite a bit older. The Oxford English Dictionary documents a letter written in 1889 by

Pall Mall Gaz. He writes:

“Mr. Edison, I was informed, had been up the two previous nights discovering ‘a bug’ in his phonograph – an expression for solving a difficulty,

and implying that some imaginary insect has secreted itself inside and is causing all the trouble.”

Exception Handling Prefer to use exceptions to report errors. – Herb Sutter & Andrei Alexandrescu [CCS-05]

An exception is an event that occurs during the execution of program, and requires the execution of code outside the normal flow of control

[MSDN2004]. Exception handling is the technologies provided by programming languages and operation systems to create, detect and respond to

these events.

Exception events can be generated by either hardware or by software. Hardware exceptions are typically generated by the CPU and are triggered

by attempts to divide by zero, or access invalid memory. Software exceptions are generated by application code or the operating system. End-of-

file and container range errors are typical software exceptions.

Examples of exception handling systems include:

C++ exceptions.

Windows structured exception handling.

Java exceptions.

.NET exceptions.

Benefits of exception handling There are many benefits to using exception handling as your primary means of responding to run-time errors.

Page 263: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 263 of 278

Exceptions cannot be ignored.

Uncaught exceptions are usually reported by the host operating system and cause the termination of the program. Some languages will not

compile the source code until all the exceptions that could occur in a given scope have a catch written for them.

No values are lost to error codes.

In the return an error code approach to reporting an error the program would have to choose a value that will be treated as an error, even if the

code chosen is a value from the output domain. Exceptions remove the need to make such a choice as exceptions provide a completely separate

mechanism for returning from a failed routine.

Exceptions reduce code bloat.

Error handlers (try / catch blocks) can be applied to blocks of code safely. The first offending function will terminate the block of code, transfer

control to the appropriate catch block.

The usual error handling case is to rollback processing to the beginning of a function if a error occurs. Traditional error handling techniques

require that each function be tested and error handling invoked by either a jump or a call to a common error handling function (which removes the

error handling code from the context of the error!) A single try / catch can wrap the entire function. See HTUtransactional programming styleUTH.

Exceptions are extensible without breaking old code.

Classes can be thrown instead of primitive data types. Exception classes can provide a name that clearly identifies the error condition (e.g.

std::bad_alloc), and can be localized within the scope of the classes issuing the exception or a namespace.

Exception classes for new error conditions can be derived from existing exception classes. Catch blocks parameterized by the base exception type

are capable of catching exception classes derived from the existing base class. Specialized catch blocks can then be added at a later time.

Software Design Issues Structured exception handling is often applied to situations for which it has not been designed nor is well suited.

Exceptions are a good choice for error handling in the following general situations:

Code containing an error condition that must not be ignored.

Code that follows the transactional programming style.

Situations where exceptions should not be used include:

Asynchronous events such as network signals, hardware interrupt handling, etc.

Alternative to standard flow-control statements. Loops can be terminated by throwing an exception inside the loop and catching it outside of

the loop. This is inefficient programming since the overhead of handling an exception is costly compared to the well-understood and well-

optimized control statements such as for, loop, while and switch.

Code where the performance of the error handling code is critical.

Page 264: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 264 of 278

Exception Safety

We can minimize the confusion that inexperienced programmers may suffer from when using exceptions by declaring one of three guarantees for

any function in a system that uses exception handling. [BOOST]

1. The basic guarantee: Class invariants are preserved and no resources are leaked if an exception is thrown.

2. The strong guarantee: The function has either completed successfully, or thrown an exception and the program is in the same state as when

the function was called. This is the same guarantee as the HTUtransactional program styleUTH.

3. The no-throw guarantee: The operation will not throw anything.

Why do so many people dislike exceptions? Many people consider exception harmful and lump them with gotos on the heap of bad programming practices. Some of the detractors’ arguments

are:

1. Exception handling implements a goto-like jump from one part of the code to another, but does so invisibly. It is difficult (or impossible)

to see which exceptions might be thrown without examining every function in the call chain. Even then the operating system may issue the

exception.

2. Exception handling creates invisible exit points in your functions. Any call that could throw an exception becomes a possible exit point to

your function. You would have to wrap every function call with a try / catch to regain control over your function’s exit point.

3. “Templates and exceptions were not designed to work together.” In fact it is impossible to write an exception safe generic container.

4. Exception handling code generates too much overhead and slows down my code.

Analysis

1. Every control statement implements an invisible goto-like jump from one part of the code to another. That was the whole point of structured

programming.

2. I believe that the concern expressed here is the cleanup of temporary or local variables and resources. A thrown exception has the potential to

terminate the execution of your function at any point during its execution. Objects with destructors will clean themselves up safely, our problem

is with the objects and variables that don’t. The use of auto_ptr-like class that automatically deallocate any owned resource can be employed

to solve this problem for data types that don’t have destructors.

3. This myth seems to have started after the publication of Tom Cargill’s article: “Exception Handling: A False Sense of Security,” C++ Report,

Nov-Dec 1994 where he points out many issues that arise when creating a container that throws exceptions. Cargill finishes the article by saying

that, “I am not confident that I can produce an exception-correct version.” Many took this article as proof that it could not be done – a classic

fallacy of logic! If fact, it can, as STL has demonstrated. We must understand that there is no specific template – exception issue. All templates

resolve to a concrete class when compiled, and it is that class that interacts with the exception system.

4. Good C++ compilers generate code that will not waste a single clock cycle if the exception is not thrown. These compilers also generate throw-

catch code that executes at a speed comparable to calling a function. [Stroustrup-94] Therefore, programs with exception handling are at least

as fast as code that ignores errors.

Page 265: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 265 of 278

Generic Programming

Generic Programming Techniques (Garth Santor, December 2006)

“Generic programming is about generalizing software components so that they can be easily reused in a wide variety of situations.” [BOOST]

Generic programming seeks to remove all non-essential details from code leaving only the essential elements of the algorithm, data type or

architecture.

Concept – Model A [generic] concept is a set of requirements consisting of valid expressions, associated types, invariants, and complexity guarantees. A type that

satisfies the set of requirements is said to model the concept. [BOOST] A refinement is a concept that extends the requirements of another

concept.

1. Valid expressions are language specific expressions that must compile successfully for the objects involved to be considered models of

the concept.

Example: an object modeling a forward iterator must successfully compile ++iter.

2. Associated types are types related to the modeling type in that they participate in one or more of the valid expressions.

Example: std::vector<T> has the associated types, std::vector<T>::iterator, std::vector<T>::value_type, etc.

3. Invariants are run-time characteristics of the objects that must always be true, that is, the functions involving the objects must preserve

these characteristics.

Example: std::vector<T>::iterator::operator*(), the dereferencing operator requires that the vector begin iterated not

reallocate. The iterator provided by std::vector<T>::begin() may not be valid after a call to

std::vector<T>::push_back(), std::vector<T>::insert() or std::vector<T>::operator=().

4. Complexity guarantees are maximum limits on how long the execution of one the valid expressions will take, or how much of various

resources it computation will use.

Example: std::vector<T>::insert() works in linear time.

Traits The traits class concept was created by Nathan C. Myers to solve the problem of an ever growing number of template parameters in C++’s

generics. Many of these extra parameters – both types and operations – could be naturally inferred by the generic’s base parameter’s type. Myers

technique collects these naturally inferable types and operations into a class templated on that base parameter type. This class he calls a traits

class.

Page 266: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 266 of 278

Policies Policy classes are similar to traits classes in that they provide an alternative method of extending the behaviour of generic software components.

The difference with traits classes is that they are generally orthogonal to the primary parameters of the generic.

Example: the choice of a pool allocator as opposed to a standard allocator for a std::vector<T> is a choice completely independent of the

vector being a container of integers or a container of strings.

Traits Classes (Garth Santor, December 2006)

Traits classes are generic classes that provide information or behaviours that can be naturally inferred from a class’ base parameter type.

The concept was created by Nathan C. Myers to solve the problem of an ever growing number of template parameters in C++’s generics. Having

noted that many of these types and values could be naturally inferred from another parameter, Myers collected these types and values into a

companion class of traits, or traits class.

Example The naïve template:

template <typename T> T sum( T const* beg, T const* end ) {

T s = T(0);

while( beg != end ) {

s += *beg;

++beg;

}

return s;

}

Works well if the parameterized type is an int, float or double. However, it performs poorly if T is a char or string. ‘unsigned

char’ will soon overflow as its range is 0 to 255. For type string, the += operator will be interpreted as catenation-assignment, but what does

T(0) mean to a string?

These problems can be solved by introducing a traits class that clarify the zero value and the data type of the sum.

template <typename T> class sum_traits {

public:

typedef T sum_type;

static T zero_value() { return T(0); }

};

template <typename T> typename sum_traits<T>::sum_type sum( T const* beg, T const* end ) {

typename sum_traits<T>::sum_type s = sum_traits<T>::zero_value();

while( beg != end ) {

s += *beg;

Page 267: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 267 of 278

++beg;

}

return s;

}

The special cases of chars and strings can be handled by specializing the sum_traits class.

template <> class sum_traits<unsigned char> {

public:

typedef unsigned int sum_type;

static sum_type zero_value() { return 0; }

};

template <> class sum_traits<std::string> {

public:

typedef std::string sum_type;

static sum_type zero_value() { return std::string(""); }

};

The assignment addition operator could also be made customizable by placing a sum method into the traits class.

References: [VJ03] (Chapter 15).

Promotion Traits [In progress]

Object-Oriented Programming

Class Invariants

A class invariant is a test or condition that must always evaluate to true for all values of that class in a visible state. (i.e. Tstring::size() ≥

0T is a class invariant for Tstd::stringT.) Class invariants may be compound conditions.

Contract Classes Contract classes are classes that are used to test or enforce a contract without burdening the actual runtime class with all the overhead of the

debug-build assertions and code.

Example: vector::insert()

void vector::insert( iterator where, size_type count, const Type& value ) {

#ifdef CHECK_CONTRACTS

int newSize = size() + count;

#endif

_Insert_n( where, count, value );

assert( size() == newSize );

Page 268: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 268 of 278

}

It is obvious that as the complexity of tests increase the amount of test code within the method could skyrocket! And it is hard enough to read and

debug code without confusing the work code with the test code.

Contract classes are a technique that will allow you to separate the test code from the work code, placing the test code into a separate class.

Example: std::vector<T>

template <typename T>

class vector_contract : public T {

public:

vector_contract( typename T::size_type n ) : T(n) {

assert( size() == n );

}

void resize( typename T::size_type n ) {

T old( *this );

T::resize( n );

bool same = true;

T::size_type nElements = std::min( old.size(), size() );

for( int i = 0; i != nElements; ++i )

same &= old[i] == (*this)[i];

assert( same );

}

};

void main() {

vector_contract< vector<int> > v(10);

for( int i = 0; i != v.size(); ++i )

v[i] = i;

v.resize( 20 );

}

Functor Classes A functor is an object that can be invoked in the manner of a function.

Functors can be are used to implement safer function callback mechanisms. The features and advantages provided by functors are:

1. Functors behave like functions.

2. Functors are proper objects.

a. Functors can carry state.

b. Functors can have unique instances.

c. Functors can be managed using standard object-oriented approaches (they are objects).

3. Consistent with object-oriented coding and design practices.

Page 269: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 269 of 278

4. Functors integrate well with generic programming (C++ templates).

5. Functors tend to have a far less cryptic syntax then function pointers or pointer to member functions.

6. Functors easily implement the strategy pattern.

Terminator Class A terminator class is a class that has no subclasses (classes derived from them). Most objects are instances of terminator classes.

Zombie Object A zombie object is an object that has died (it is irreversibly incapable of executing) but still exists in memory and is still referenced.

When an object zombies programmers have traditionally set a flag to indicate the zombied state. This would require the caller to check the

object’s status before or after each call. A preferable alternative is to have the zombie throw an exception indicating its demise and allowing the

calling function to kill or avoid the zombie.

Testing & Reliability “An effective way to test code is to exercise it at its natural boundaries”

– Brian Kernighan.

Testing methodologies can be examined from several perspectives:

The scope of a test.

The intrusiveness of a test.

The focus of a test.

The scope of a test refers to amount of the system or code that is being tested. Unit testing, integration testing, and system testing all refer to test

of differing scope.

The intrusiveness of a test refers to whether or not the test examines the internals of the unit being tested or whether the module is considered to be

impenetrable. Black-box testing or white-box testing indicates the intrusiveness of a test.

The focus of a test refers to aspect of the module being tested. Functional testing, load testing, performance testing, stress testing, security testing

and usability testing each examine a different characteristic of the software.

These terms are often mixed to indicate the overall test. For example, we may a black-box functional unit test or a system performance test.

The one oddball is regression testing which may refer to any of the previous tests. Regression testing is the reapplication of a test after a

refactoring of the code. The purpose of the test is to ensure that no new errors have been introduced into as a result of refactoring the code.

Regression testing is usually performed on functional tests.

Page 270: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 270 of 278

Unit Testing

Unit testing validates the post-condition of every function or object method in a module of source code (only non-trivial functions or methods need

be tested.)

The benefit of a unit test is to gain assurances that an individual part of a system is working properly. This knowledge would allow a programmer

to focus their efforts on integration or system testing.

The presence of a unit test assists in refactoring as a programmer can quickly determine whether the new, refactored code also satisfies the post-

conditions of the module.

Ideally, unit tests will be automated and used during regression testing.

Integration Testing

Integration testing tests groups of related modules to validate higher-order functionality. It is also called string testing since modules are “strung”

together to perform these tests.

Integration testing is typically performed after unit testing and before system testing.

System Testing

System testing tests the complete system.

System tests validate Use-Case scenarios in a Unified Process project.

Load Testing

Load testing focuses on a system’s or module’s ability to operate under expected usage. Typically we seek to validate correct behaviour is

maintained as memory allocation increases or the number of users of the system increases.

Load testing is often associated with performance testing.

Load testing is differentiated from stress testing in that load testing tests the system under expected usage whereas stress testing tests the system

under extreme usage.

Performance Testing

Performance testing attempts to measure the time or space utilization of a module, system or sub-system.

Performance testing is often performed in conjunction with load testing.

Stress Testing

Stress testing determines the stability of a module or system under extreme conditions (beyond normal).

Stress testing often includes testing the system under low-memory conditions, a high number of users or a high number of open files or handles.

Usability Testing

Usability testing does not test for correctness, but for ease of use.

Page 271: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 271 of 278

Ease of use can be measured via the metrics:

Time on Task – how long does it take a user to complete the given task?

Accuracy – how often does the user succeed in completing the given task?

Recall – how often does the user forget how to complete the given task?

Emotional Response – how positive does the user feel after completing the give task? (Assured? Confident? Stressed? Angry?)

Test Doubles Test doubles are function or object implementations used in the development or testing of code. Test doubles are typically used during unit testing

although they can also be useful during the early stages of integration testing. They allow for the testing of the unit or system to begin without a

complete implementation.

Test doubles range from trivial implementations that minimally satisfy the call (the function returned) to complex functions that implement a large

amount of the functionality.

The types of test doubles can be categorized by the following five definitions:

1. Dummy

2. Stub

3. Spy

4. Fake

5. Mock

Dummy

Dummies have no implementation – neither method bodies nor state data. They are interfaces. During testing they are used when as procedural

parameters.

Stub

Stubs are minimal implementations or interfaces or base classes. Methods and functions return hard-coded values.

Spy

Spies are stubs that log which members were invoked.

Fake

A fake is a partial implementation. Typically it handles interactions between members of the types it is inheriting.

Page 272: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 272 of 278

Mock

A mock is a dynamically create implementation, usually created from a mock library. Mocks are configurable to provide the correct data types

and values. They can be used in place of dummies, stubs, spies and fakes, although fakes are more difficult to simulate.

Testing Styles

Code Inspection

Reading the code…

Some studies have shown that have two people read the code triples the rate of finding errors as compared to one person reading the code.

Desk Check

The ‘desk check’ is an almost defunct approach to software testing in which the tester reads through the source code imagining the program state

and mentally tracing the program’s control flow. This approach was more popular in the 1960’s and 1970’s before full-screen editors and

interactive source-level debuggers.

Dry Run

An intense form of desk check in which the tester records the state of each variable as she proceeds through the code. This is only practical for

small routines or code segments. This approach was more recently been super ceded by visual debugger walkthroughs.

Walkthrough (w/visual debugger)

Using a visual debugging tool, stepping through a program line-by-line.

White-Box/Black Box Testing

White-box testing permits the examination of the source code, black-box testing does not.

Transactional Programming Style Transactional programming style emphasizes the principle that a function should either do everything or nothing. Transactional programming

supports the HTUatomic principle of programming.

Example – non-atomic.

TvoidT double_size( TintT*& p, TintT size ) {

TdeleteT [] p;

p = TnewT TintT [size * 2];

}

What happens if TnewT throws a memory allocation exception? p is left pointing to a block of memory we no-longer own.

TvoidT atomic_double_size( TintT*& p, TintT size ) {

TintT* pResized = TnewT TintT[ size * 2 ];

TdeleteT [] p;

p = pResized;

Page 273: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 273 of 278

}

Now, if new throws the original array is left untouched.

Sometimes more work is required to enforce the atomic principle.

Example:

Object* g_pGood = 0;

void foo() {

TdeleteT g_pGood;

g_pGood = new Object;

g_pGood->init(); T// could throwT

}

This is the atomic version:

Object* g_pGood = 0;

void atomic_foo() {

Object* p = new Object;

try {

p->init(); T// could throwT

TdeleteT g_pGood;

g_pGood = p;

}

catch( exception& e ) {

delete p;

}

}

The global object Tg_pGoodT will only be initialized if the entire allocation and initialization process succeeds. If an exception is thrown at any point

during the function, the program state is effectively rolled-back to the program state when function ‘TfT’ was called.

The use of smart pointers can simplify coding in a transactional style.

boost::scoped_ptr<Object> g_pGood;

void simple_atomic_foo() {

boost::scoped_ptr<Object> p( new Object );

p->init();

g_pGood.reset( p );

}

The Rules

To make a function atomic:

1. Create all of the new resources before you destroy the old resources being replaced.

Page 274: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 274 of 278

2. Use smart_ptr or objects with destructors to automatically clean up when an exception is thrown.

3. See HTUexception handling.

Issues

The preceding rules don’t handle the problem of rolling-back a set of functions.

void host() {

foo();

bar();

}

What if foo() completes successfully but bar() doesn’t? How do you rollback foo()?

Several methods have been devised to deal with this problem, but all incur overhead. The most common are modeled on database transactions,

such as those found in Transact-SQL.

Invariants

Loop Invariant

A loop invariant is a condition that does not vary during the execution of a loop.

Example:

TforT( TintT i = 0; i != n; ++i )

a[i] = i;

In this trivial example, the invariant is ‘i < n’. We can explicitly test for this using an assertion.

TforT( TintT i = 0; i != n; ++i ) {

a[i] = i;

assert( i < n );

}

Class Invariant

A class invariant is a condition that does not vary during the life of an object. Class invariants should test positively at:

at the end of object construction

at the start of object destruction

at the start and end of any method

Example:

A referencing-counting smart pointer may have a class invariant with the following condition:

p = nil or (p ≠ nil and count{p} > 0)

Example:

Page 275: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

Programming Concepts Section 24

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 275 of 278

bool invariant( char* file, char* func, int line ) {

//… test and report

}

#ifndef NDEBUG

#define TEST_INVARTIANT() invariant( __FILE__, __FUNCTION__, __LINE )

#else

#define TEST_INVARTIANT()

#endif

Role in testing

The role of invariants in testing is sanity checking (i.e. enforcing the HTUSanity Principle).

Page 276: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

References Section 25

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 276 of 278

Appendices

Acronyms AABB Math/Graphics Axis-Aligned Bounding Box

OBB Math/Graphics Oriented Bounding Box

POD C++ Jargon Plain-Old-Data. Non-pointer primitives or structures / classes made up of non-pointer

primitives. Essentially – a variable that can be safely copied with a binary copy.

References [AIS77] Christopher Alexander, Sara Ishikawa, Murray Silverstein, Max Jacobson, Ingrid Fiksdahl-King, and Shlomo Angel.

A Pattern Language: Towns/Buildings/Construction. Oxford University Press, 1977.

[BOOST] BOOST Documentation www.boost.org

[CUJ] C/C++ User’s Journal

[DP95] Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides. Design Patterns: Elements of Reusable Object-

Oriented Software. Addison-Wesley, 1995

[IA90] Corman, Thomas H., Leiserson, Charles E., & Rivest, Ronald L. (1990) Introduction to algorithms (1st ed.) The MIT

Press [0-262-03141-8]

[K06] Karlsson, Björn (2006) Beyond the C++ standard library: an introduction to Boost. Reading MA: Addison Wesley

[0-321-13354-4]

[MSDN2004] Microsoft Developer’s Network Library 2004.

[SA04] Sutter, Herb & Alexandrescu, Andrei (2004) C++ Coding Standards

[STRO1995] Stroustrup, Bjarne (1995) The design and evolution of C++. Reading, MA: Addison Wesley.

[STRO2000] Stroustrup, Bjarne (2000) The C++ programming language. Reading, MA: Addison Wesley.

[VJ03] David Vandevoorde & Nicolai M. Josuttis (2003) C++ Templates: The Complete Guide Addison Wesley

[0-201-73484-2]

Page 277: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

References Section 26

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 277 of 278

Index

A* algorithm, 225

algorithm, 13, 14, 15, 16, 17, 21, 22, 24, 25, 26, 27, 28, 32, 36,

37, 38, 40, 65, 66, 87, 88, 134, 152, 192, 222, 225, 226, 227,

228, 258, 269

asymptotic analysis, 13, 15

atomic principle, 253, 265

audio, 43, 44, 45, 46, 47, 126

backface culling. See culling: backface

BeginScene(), 136, 145, 149, 151, 170, 177

big-oh, 13, 14

Binet, Jacque Philippe Marie, 193

binomial coefficient, 195

bit block transfer, 129, 136

blit, 129

breadth-first search, 226

bridge pattern, 83, 86, 110

camera, 129, 131, 132, 133, 187

Camera, 129

collision detection, 245

combination. See binomial coefficient

combinatorial number. See binomial coefficient

culling, 132, 133, 181

backface, 132

D3DPOOL_SYSTEMMEM, 136, 140

D3DPRESENTFLAG_LOCKABLE_BACKBUFFER, 150,

151

DCLP, 111

de Lagny, Thomas Fantet, 193

depth-first search, 227, 228

design pattern, 111

bridge pattern, 110

bridge pattern, 83, 86

bridge pattern, 110

bridge pattern, 110

observer pattern, 111

Dialog Box, 165

Direct3D

memory pool, 136, 140

dodecahedron, 208, 216

DXUTCreateDevice(), 151, 162

Euclid’s Algorithm. See Highest Common Factor

factorial, 192

Factorial, 192

Fibonacci numbers, 87, 192, 193, 194

file formats

raw, 47, 53, 91

x-file, 155

fog, 139, 187

function

permutation, 196

functions

binomial coefficient, 195

factorial, 192

Fibonacci numbers, 87, 192, 193, 194

inner product, 133, 204

gang of four, 249, 250

golden ratio, 193, 194, 216, 218

Greatest Common Divisor.. See Highest Common Factor

GUI Controls, 165

height maps, 184, 185

hexahedron, 208

Hoare, Anthony, 37, 39

icosahedron, 208, 218, 219

IDirect3DSurface9, 136, 140, 151

inner product, 133, 204

invariants, 252, 253, 257, 260, 267, 268

Invariants, 50, 63, 64, 252, 253, 257, 258, 260, 267, 268

lighting, 141, 143, 147, 148, 151, 152, 186

Page 278: GATS  · PDF fileIntroduction Section 1 ©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 3 of 278 Set

References Section 27

©1991 – 2016 Garth Santor & Trinh Hān GATS Encyclopaedia 278 of 278

ambient, 151, 152

directional, 140, 152, 186

point, 140, 142, 152

spot, 140, 143, 152

matrix, 129

Matrix, 129, 202

memory pool, 136, 140

Direct3D, 136, 140

numbers

natural, 14, 16, 17, 106, 194

observer pattern, 111

octahedron, 208

path finding

A*, 225

breadth-first, 226

depth-first, 227, 228

pattern

DCLP, 111

Permutation, 24, 37, 196

permutations, 192, 196

polyhedron, 135, 207, 208

RAM model of computation, 13, 15

sanity principle, 253, 268

searching

A*, 225

breadth-first, 226

depth-first, 227, 228

skybox, 187

sphere, 207, 208, 211, 213, 215, 218, 220, 245

sprite, 134, 150, 180

sprites, 134, 150, 180

surface, 133, 135, 136, 139, 140, 148, 151, 152, 180, 185, 186,

187

surface normal, 133, 135, 139, 148, 186

surfaces, 133, 186, 189

templates, 52, 55, 58, 62, 63, 70, 73, 81, 86, 88, 94, 96, 97,

155, 156, 257, 258, 259, 260, 261

tetrahedron, 208, 211

Texture, 150

transactional programming, 256, 265

transforms, 122, 129, 130, 131, 132, 134, 148, 150, 180, 183,

187, 197, 198, 199, 201, 202

turtle graphics, 187, 188

vector

surface normal, 133, 135, 139, 148, 186

vector, geometric

inner product, 133, 204

vertex, 133, 135, 136, 138, 139, 141, 143, 145, 146, 147, 148,

149, 156, 157, 158, 180, 182, 184, 185, 188, 201, 206, 207,

208, 211, 213, 215, 216, 218, 220, 221, 225, 226, 227, 228

winding, 133, 135

view, 129, 131, 132, 139, 148, 150, 187, 201

View, 129