0% found this document useful (0 votes)
3K views78 pages

Game Physics Cookbook 1st Edition Gabor Szauer Download PDF

The document promotes various ebooks available for download on ebookgate.com, including titles related to game physics and development. It highlights the 'Game Physics Cookbook' by Gabor Szauer, which offers over 100 recipes for implementing game physics and collision detection. Additionally, it provides information about the authors and the structure of the content within the books, emphasizing the importance of understanding physics engines in game development.

Uploaded by

beesekoria82
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3K views78 pages

Game Physics Cookbook 1st Edition Gabor Szauer Download PDF

The document promotes various ebooks available for download on ebookgate.com, including titles related to game physics and development. It highlights the 'Game Physics Cookbook' by Gabor Szauer, which offers over 100 recipes for implementing game physics and collision detection. Additionally, it provides information about the authors and the structure of the content within the books, emphasizing the importance of understanding physics engines in game development.

Uploaded by

beesekoria82
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 78

Get the full ebook with Bonus Features for a Better Reading Experience on ebookgate.

com

Game Physics Cookbook 1st Edition Gabor Szauer

https://ebookgate.com/product/game-physics-cookbook-1st-
edition-gabor-szauer/

OR CLICK HERE

DOWLOAD NOW

Download more ebook instantly today at https://ebookgate.com


Instant digital products (PDF, ePub, MOBI) available
Download now and explore formats that suit you...

Game Physics Second Edition David H. Eberly

https://ebookgate.com/product/game-physics-second-edition-david-h-
eberly/

ebookgate.com

Physics for Game Developers 1st Edition David M Bourg

https://ebookgate.com/product/physics-for-game-developers-1st-edition-
david-m-bourg/

ebookgate.com

iOS Swift Game Development Cookbook 2nd Edition Simple


Solutions for Game Development Problems Jonathon Manning

https://ebookgate.com/product/ios-swift-game-development-cookbook-2nd-
edition-simple-solutions-for-game-development-problems-jonathon-
manning/
ebookgate.com

Polycystic Ovary Syndrome 2nd edition Gabor T. Kovacs

https://ebookgate.com/product/polycystic-ovary-syndrome-2nd-edition-
gabor-t-kovacs/

ebookgate.com
Etymological Dictionary of Egyptian Volume 3 m Gabor
Takacs

https://ebookgate.com/product/etymological-dictionary-of-egyptian-
volume-3-m-gabor-takacs/

ebookgate.com

Clinical Manual of Couples and Family Therapy 1st Edition


Gabor I. Keitner

https://ebookgate.com/product/clinical-manual-of-couples-and-family-
therapy-1st-edition-gabor-i-keitner/

ebookgate.com

Ruthless Game Game Ghostwalker Christine Feehan

https://ebookgate.com/product/ruthless-game-game-ghostwalker-
christine-feehan/

ebookgate.com

Electrical Submersible PumpsManual Design Operations and


Maintenance Second Edition 2017 Gabor Takacs

https://ebookgate.com/product/electrical-submersible-pumpsmanual-
design-operations-and-maintenance-second-edition-2017-gabor-takacs/

ebookgate.com

How To Start A Conversation And Make Friends Revised And


Updated Gabor

https://ebookgate.com/product/how-to-start-a-conversation-and-make-
friends-revised-and-updated-gabor/

ebookgate.com
Game Physics
Cookbook

Discover over 100 easy-to-follow recipes to help you


implement efficient game physics and collision detection
in your games

Gabor Szauer

BIRMINGHAM - MUMBAI
Game Physics Cookbook

Copyright © 2017 Packt Publishing

All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or
transmitted in any form or by any means, without the prior written permission of the publisher,
except in the case of brief quotations embedded in critical articles or reviews.

Every effort has been made in the preparation of this book to ensure the accuracy of the
information presented. However, the information contained in this book is sold without
warranty, either express or implied. Neither the author nor Packt Publishing, and its dealers
and distributors will be held liable for any damages caused or alleged to be caused directly or
indirectly by this book.

Packt Publishing has endeavored to provide trademark information about all of the companies
and products mentioned in this book by the appropriate use of capitals. However, Packt
Publishing cannot guarantee the accuracy of this information.

First published: March 2017

Production reference: 1200317

Published by Packt Publishing Ltd.


Livery Place
35 Livery Street
Birmingham B3 2PB, UK.

ISBN 978-1-78712-366-3

www.packtpub.com
Credits

Author Project Coordinator


Gabor Szauer Devanshi Doshi

Reviewers Proofreader
Francesco Sapio Safis Editing

Commissioning Editor Indexer


Ashwin Nair Francy Puthiry

Acquisition Editor Graphics


Divya Poojari Abhinash Sahu

Content Development Editor Production Coordinator


Onkar Wani Aparna Bhagat

Technical Editor Cover Work


Rashil Shah Aparna Bhagat

Copy Editors
Safis Editing
Shaila Kusanale
About the Author
Gabor Szauer graduated from Full Sail University with a bachelor's degree in game
development. He has been making video games professionally for over 6 years. He has
worked on games for the Nintendo 3DS, Xbox 360, browser-based games, and mobile games.

In his free time Gabor makes video games, researches video game-related technologies, and
likes to design and construct furniture. Gabor currently resides in San Francisco, working in
the mobile game industry.
Acknowledgements
I would like to thank my mom and dad, Gabriella and János. Without your constant love and
support this book would not be possible.

I also want to thank my wife Lisa Jennifer Gordon who not only managed to put up with me
through the process of writing this book, but helped create many of the illustrations in the
book as well.

Finally, I want to thank my brother Martin, without his curiosity for programming the first draft
of this book would not have been written.
About the Reviewer
Francesco Sapio obtained his Computer Science and Control Engineering degree from
Sapienza University of Rome, Italy, with a couple of semesters in advance, scoring summa
cum laude. He is currently studying a Master of Science in Engineering in Artificial Intelligence
and Robotics at the same university.
He is a Unity3D and Unreal expert, a skilled game designer, and an experienced user of the
major graphics programs. He developed Gea2, formerly Game@School (Sapienza University
of Rome), an educational game for high school students to learn the concepts of physics, and
Sticker Book (series) (Dataware Games), a cross-platform series of games for kids. In addition,
he worked as a consultant for the (successfully funded by Kickstarter) game Prosperity – Italy
1434 (Entertainment Game Apps, Inc.), and for the open online collaborative ideation system
titled Innovoice (Sapienza University of Rome). Moreover, he has been involved in different
research projects such as Belief-Driven-Pathfinding (Sapienza University of Rome), a new
technique for pathfinding in videogames that was presented as a paper at the DiGRA-FDG
Conference 2016; and perfekt.ID (Royal Melbourne Institute of Technology), which included
developing a recommendation system for games.
He is an active writer on the topic of game development. Recently, he authored the book
Getting Started with Unity 5.x 2D Game Development (Packt Publishing) which takes your
hand and guides you through the amazing journey of game development, the successful
Unity UI Cookbook (Packt Publishing), which has been translated into other languages and
teaches readers how to develop exciting and practical user interfaces for games within Unity,
and a short e-guide What do you need to know about Unity (Packt Publishing). In addition,
he co-authored the book Unity 5.x 2D Game Development Blueprints (Packt Publishing).
Furthermore, he has also been a reviewer for the following books: Mastering Unity 5.x
(Packt Publishing), Unity 5.x by Example (Packt Publishing), and Unity Game Development
Scripting (Packt Publishing).
Francesco is also a musician and a composer, especially of soundtracks for short films and
video games. For several years, he worked as an actor and dancer, where he was a guest
of honor at the theatre Brancaccio in Rome. In addition, he is a very active person, having
volunteered as a children's entertainer at the Associazione Culturale Torraccia in Rome.
Finally, Francesco loves math, philosophy, logic, and puzzle solving, but most of all, creating
video games — thanks to his passion for game designing and programming.
You can find him at www.francescosapio.com.
Acknowledgements
I'm deeply thankful to my parents for their infinite patience, enthusiasm, and support
throughout my life. Moreover, I'm thankful to the rest of my family, in particular to my
grandparents, since they have always encouraged me to do better in my life with the
Latin expressions "Ad maiora" and "Per aspera ad astra".

Finally, a huge thanks to all the special people around me whom I love, in particular to my
girlfriend; I'm grateful for all of your help in everything. I do love you.
www.PacktPub.com

eBooks, discount offers, and more


Did you know that Packt offers eBook versions of every book published, with PDF and ePub
files available? You can upgrade to the eBook version at www.PacktPub.com and as a print
book customer, you are entitled to a discount on the eBook copy. Get in touch with us at
[email protected] for more details.

At www.PacktPub.com, you can also read a collection of free technical articles, sign up
for a range of free newsletters and receive exclusive discounts and offers on Packt books
and eBooks.

https://www.packtpub.com/mapt

Get the most in-demand software skills with Mapt. Mapt gives you full access to all Packt
books and video courses, as well as industry-leading tools to help you plan your personal
development and advance your career.

Why Subscribe?
ff Fully searchable across every book published by Packt
ff Copy and paste, print, and bookmark content
ff On demand and accessible via a web browser
Customer Feedback
Thank you for purchasing this Packt book. We take our commitment to improving our content
and products to meet your needs seriously—that's why your feedback is so valuable. Whatever
your feelings about your purchase, please consider leaving a review on this book's Amazon
page. Not only will this help us, more importantly it will also help others in the community
to make an informed decision about the resources that they invest in to learn.

You can also review for us on a regular basis by joining our reviewers' club. If you're interested
in joining, or would like to learn more about the benefits we offer, please contact us:
[email protected].
Table of Contents
Preface vii
Chapter 1: Vectors 1
Introduction 1
Vector definition 2
Component-wise operations 5
Dot product 11
Magnitude 13
Normalizing 16
Cross product 17
Angles 20
Projection 22
Reflection 26
Chapter 2: Matrices 31
Introduction 31
Matrix definition 32
Transpose 35
Multiplication 38
Identity matrix 41
Determinant of a 2x2 matrix 43
Matrix of minors 44
Cofactor 48
Determinant of a 3x3 matrix 49
Operations on a 4x4 matrix 51
Adjugate matrix 54
Matrix inverse 55

i
Table of Contents

Chapter 3: Matrix Transformations 59


Introduction 59
Matrix majors 60
Translation 62
Scaling 64
How rotations work 65
Rotation matrices 68
Axis angle rotation 76
Vector matrix multiplication 79
Transform matrix 82
View matrix 84
Projection matrix 86
Chapter 4: 2D Primitive Shapes 91
Introduction 91
2D points 92
2D lines 93
Circle 95
Rectangle 96
Oriented rectangle 98
Point containment 100
Line intersection 103
Chapter 5: 2D Collisions 107
Introduction 107
Circle to circle 108
Circle to rectangle 109
Circle to oriented rectangle 112
Rectangle to rectangle 114
Separating Axis Theorem 116
Rectangle to oriented rectangle 121
Oriented rectangle to oriented rectangle 125
Chapter 6: 2D Optimizations 129
Introduction 129
Containing circle 130
Containing rectangle 132
Simple and complex shapes 133
Quad tree 135
Broad phase collisions 144

ii
Table of Contents

Chapter 7: 3D Primitive Shapes 147


Introduction 147
Point 148
Line segment 149
Ray 151
Sphere 152
Axis Aligned Bounding Box 154
Oriented Bounding Box 156
Plane 158
Triangle 160
Chapter 8: 3D Point Tests 163
Introduction 163
Point and sphere 164
Point and AABB 166
Point and Oriented Bounding Box 168
Point and plane 171
Point and line 172
Point and ray 174
Chapter 9: 3D Shape Intersections 177
Introduction 177
Sphere-to-sphere 178
Sphere-to-AABB 179
Sphere-to-OBB 180
Sphere-to-plane 182
AABB-to-AABB 183
AABB-to-OBB 184
AABB-to-plane 190
OBB-to-OBB 192
OBB-to-plane 194
Plane-to-plane 197
Chapter 10: 3D Line Intersections 199
Introduction 199
Raycast Sphere 200
Raycast Axis Aligned Bounding Box 204
Raycast Oriented Bounding Box 209
Raycast plane 214
Linetest Sphere 216
Linetest Axis Aligned Bounding Box 217
Linetest Oriented Bounding Box 219
Linetest Plane 220
iii
Table of Contents

Chapter 11: Triangles and Meshes 223


Introduction 223
Point in triangle 224
Closest point triangle 226
Triangle to sphere 229
Triangle to Axis Aligned Bounding Box 230
Triangle to Oriented Bounding Box 233
Triangle to plane 235
Triangle to triangle 237
Robustness of the Separating Axis Theorem 240
Raycast Triangle 244
Linetest Triangle 249
Mesh object 250
Mesh optimization 251
Mesh operations 258
Chapter 12: Models and Scenes 263
Introduction 263
The Model object 264
Operations on models 267
The Scene object 272
Operations on the scene 275
The Octree object 279
Octree contents 281
Operations on the Octree 283
Octree scene integration 288
Chapter 13: Camera and Frustum 293
Introduction 293
Camera object 294
Camera controls 302
Frustum object 306
Frustum from matrix 310
Sphere in frustum 313
Bounding Box in frustum 315
Octree culling 319
Picking 321
Chapter 14: Constraint Solving 327
Introduction 327
Framework introduction 328
Raycast sphere 333

iv
Table of Contents
Raycast Bounding Box 336
Raycast plane and triangle 342
Physics system 346
Integrating particles 351
Solving constraints 356
Verlet Integration 360
Chapter 15: Manifolds and Impulses 363
Introduction 363
Manifold for spheres 364
Manifold for boxes 369
Rigidbody Modifications 380
Linear Velocity 381
Linear Impulse 386
Physics System Update 393
Angular Velocity 399
Angular Impulse 407
Chapter 16: Springs and Joints 413
Introduction 413
Particle Modifications 414
Springs 416
Cloth 421
Physics System Modification 431
Joints 434
Appendix: Advanced Topics 437
Introduction 437
Generic collisions 438
Stability improvements 441
Springs 443
Open source physics engines 444
Books 446
Online resources 447
Summary 448
Index 449

v
Preface
At some point in your game development career, you might need to build a physics engine,
modify the source code of an existing physics engine, or even just model some interaction
using an existing physics engine. Each of these tasks is a real challenge. Knowing how a
physics engine is implemented under the hood will make all of these scenarios a lot simpler.

Building a physics engine from scratch might seem like a large, complex and confusing
project, but it doesn't have to be. Behind every physics engine are the same three core
components: a solid math library, accurate intersection testing, and usually impulse-based
collision resolution. The collision resolution does not have to use an impulse-based solver;
other resolution strategies exist as well.

This book covers the three core components of a physics engine in great detail. By the end
of the book you will have implemented particle-based physics, rigid body physics, and even
soft body physics through cloth simulation. This cookbook aims to break the components
of a physics engine down into bite-sized, independent recipes.

What this book covers


Chapter 1, Vectors, covers vector math using 2D and 3D vectors. Vectors will be heavily used
throughout the book, so having a solid understanding of the math behind vectors is essential.

Chapter 2, Matrices, covers the basics of 2D, 3D, and 4D matrices. Operations such as matrix
multiplication and inversion are covered. This chapter is an introduction to the implementation
matrices in C++.

Chapter 3, Matrix Transformations, covers applying matrices to games. This chapter builds
upon the understanding of vectors and matrices built up in the previous chapters to explain
how matrices and vectors can be used to represent transformations in 3D space.

vii
Preface

Chapter 4, 2D Primitive Shapes, covers common 2D shapes games may need. This chapter
provides practical definitions and implementations of common 2D primitives.

Chapter 5, 2D Collisions, covers testing the 2D shapes defined in the last chapter for
intersection. This chapter covers the fundamental concepts of intersection testing in 2D,
which later chapters will expand into 3D.

Chapter 6, 2D Optimizations, covers speeding up the intersection tests written in the last
chapter. Once hundreds or even thousands of objects are colliding, brute force collision
detection will no longer work in real time. The topics covered in this chapter are vital for
keeping collision detection running in real time, even with a large number of objects.

Chapter 7, 3D Primitive Shapes, covers the common 3D shapes games may need.
This chapter provides the definition of the geometric primitives we will later build upon
to create a working 3D physics engine.

Chapter 8, 3D Point Tests, covers nearest point and containment tests in a 3D environment.
This chapter covers finding the closest point on the surface of a 3D primitive to a given point
and provides containment tests for the 3D primitives previously covered.

Chapter 9, 3D Shape Intersections, covers testing all of the 3D primitive shapes for
intersection. This chapter expands many of the 2D intersection tests covered previously in the
book into 3D space. The chapter also provides additional insight into optimizing intersection
tests in 3D space.

Chapter 10, 3D Line Intersections, covers testing the intersection of a line and any 3D
primitive, as well as raycasting against any 3D primitive. Ray casting is perhaps one of
the most versatile intersection tests. We will use ray casting in later chapters to avoid the
common problem of tunneling.

Chapter 11, Triangles and Meshes, covers a new primitive, the triangle, and how to use
triangles to represent a mesh. In a 3D game world, objects are often represented by complex
meshes rather than primitive 3D shapes. This chapter presents the most straightforward
way of representing these complex meshes in the context of a physics engine.

Chapter 12, Models and Scenes, covers adding a transformation to a mesh, as well as
using a hierarchy of meshes to represent a scene. Games often reuse the same mesh
transformed into a different space. This chapter defines a model, which is a mesh with
some transformation. The chapter also covers multiple models in a scene.

Chapter 13, Camera and Frustum, covers the frustum primitive and building a camera out
of matrices. The focus of this chapter is to build an easy to use camera which can be used
to view any 3D scene. Each camera will have a frustum primitive attached. The attached
frustum primitive can optimize render times by culling unseen objects.

viii
Preface

Chapter 14, Constraint Solving, covers a basic introduction to physics. This chapter introduces
particle physics and world space constraints for particles. In this chapter, the word constraint
refers to an immovable object in the physics simulation.

Chapter 15, Manifolds and Impulses, extends the particle physics engine built in the last chapter
by defining a rigid body object, which unlike a particle has some volume. Impulse-based collision
resolution is also covered in this chapter.

Chapter 16, Springs and Joints, creates springs and simple joint constraints for springs. Using
springs and particles, this chapter covers the basic concept of soft body physics. The chapter
focuses on implementing 3D cloth using springs and particles.

Appendix, Advanced Topics, covers issues this book did not have the scope to address.
Building a physics engine is a huge undertaking. While this book built a basic physics engine,
there are many topics that fell outside the scope of this book. This chapter provides guidance,
references, and resources to help the reader explore these advanced topics further.

What you need for this book


Working knowledge of the C++ language is required for this book, as the book is not a tutorial
about programming. Having a basic understanding of calculus and linear algebra will be
useful, but is not required. You will need a Windows PC (preferably with Windows 7 or higher)
with Microsoft Visual Studio 2015 installed on it.

Who this book is for


This book is for beginner to intermediate game developers. You don't need to have a formal
education in games—you can be a hobbyist or indie developer who started making games
with Unity 3D.

Sections
In this book, you will find several headings that appear frequently (Getting ready, How to do it…,
How it works…, There's more…, and See also).

To give clear instructions on how to complete a recipe, we use these sections as follows:

Getting ready
This section tells you what to expect in the recipe, and describes how to set up any software or
any preliminary settings required for the recipe.

ix
Preface

How to do it…
This section contains the steps required to follow the recipe.

How it works…
This section usually consists of a detailed explanation of what happened in the
previous section.

There's more…
This section consists of additional information about the recipe in order to make the reader
more knowledgeable about the recipe.

See also
This section provides helpful links to other useful information for the recipe.

Conventions
In this book, you will find a number of text styles that distinguish between different kinds of
information. Here are some examples of these styles and an explanation of their meaning.

Code words in text, database table names, folder names, filenames, file extensions,
pathnames, dummy URLs, user input, and Twitter handles are shown as follows: "We can
include other contexts through the use of the include directive."

A block of code is set as follows:


#ifndef _H_MATH_VECTORS_
#define _H_MATH_VECTORS_

// Structure definitions
// Method declarations

#endif

New terms and important words are shown in bold. Words that you see on the screen, for
example, in menus or dialog boxes, appear in the text like this: "Under the Application divider
you will find the code"

x
Preface

Creating a Win32 window with an active OpenGL Context is outside the


scope of this book. For a better understanding of how Win32 code works
with OpenGL read: https://www.khronos.org/opengl/wiki/
Creating_an_OpenGL_Context_(WGL)

Reader feedback
Feedback from our readers is always welcome. Let us know what you think about this
book—what you liked or disliked. Reader feedback is important for us as it helps us
develop titles that you will really get the most out of.

To send us general feedback, simply e-mail [email protected], and mention the


book's title in the subject of your message.

If there is a topic that you have expertise in and you are interested in either writing or
contributing to a book, see our author guide at www.packtpub.com/authors.

Customer support
Now that you are the proud owner of a Packt book, we have a number of things to help you to
get the most from your purchase.

Downloading the example code


You can download the example code files for this book from your account at http://
www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.
packtpub.com/support and register to have the files e-mailed directly to you.

You can download the code files by following these steps:

1. Log in or register to our website using your e-mail address and password.
2. Hover the mouse pointer on the SUPPORT tab at the top.
3. Click on Code Downloads & Errata.
4. Enter the name of the book in the Search box.
5. Select the book for which you're looking to download the code files.
6. Choose from the drop-down menu where you purchased this book from.
7. Click on Code Download.

You can also download the code files by clicking on the Code Files button on the book's
webpage at the Packt Publishing website. This page can be accessed by entering the book's
name in the Search box. Please note that you need to be logged in to your Packt account.

xi
Preface

Once the file is downloaded, please make sure that you unzip or extract the folder using the
latest version of:

ff WinRAR / 7-Zip for Windows


ff Zipeg / iZip / UnRarX for Mac
ff 7-Zip / PeaZip for Linux

The code bundle for the book is also hosted on GitHub at https://github.com/
PacktPublishing/Game-Physics-Cookbook. We also have other code bundles from our
rich catalog of books and videos available at https://github.com/PacktPublishing/.
Check them out!

Errata
Although we have taken every care to ensure the accuracy of our content, mistakes do happen.
If you find a mistake in one of our books—maybe a mistake in the text or the code—we would be
grateful if you could report this to us. By doing so, you can save other readers from frustration
and help us improve subsequent versions of this book. If you find any errata, please report them
by visiting http://www.packtpub.com/submit-errata, selecting your book, clicking on
the Errata Submission Form link, and entering the details of your errata. Once your errata are
verified, your submission will be accepted and the errata will be uploaded to our website or
added to any list of existing errata under the Errata section of that title.

To view the previously submitted errata, go to https://www.packtpub.com/books/


content/support and enter the name of the book in the search field. The required
information will appear under the Errata section.

Piracy
Piracy of copyrighted material on the Internet is an ongoing problem across all media. At
Packt, we take the protection of our copyright and licenses very seriously. If you come across
any illegal copies of our works in any form on the Internet, please provide us with the location
address or website name immediately so that we can pursue a remedy.

Please contact us at [email protected] with a link to the suspected pirated material.

We appreciate your help in protecting our authors and our ability to bring you valuable content.

Questions
If you have a problem with any aspect of this book, you can contact us at questions@
packtpub.com, and we will do our best to address the problem.

xii
Vectors
1
In this chapter, we will cover the following vector operations:

ff Addition
ff Subtraction
ff Multiplication
ff Scalar Multiplication
ff Cross Product
ff Dot Product
ff Magnitude
ff Distance
ff Normalization
ff Angle
ff Projection
ff Reflection

Introduction
Throughout this book we are going to explore the mathematical concepts required to detect
and react to intersections in a 3D environment. In order to achieve robust collision detection
and build realistic reactions, we will need a strong understanding of the math required. The
most important mathematical concepts in physics are Vectors and Matrices.

Physics and collisions rely heavily on Linear Algebra. The math involved may sound
complicated at first, but it can be broken down into simple steps. The recipes in this chapter
will explain the properties of vectors using math formulas. Each recipe will also contain a
visual guide. Every formula will also have an accompanying code sample.

1
Vectors

This chapter does not assume you have any advanced math knowledge. I try
to cover everything needed to understand the formulas presented. If you find
yourself falling behind, Khan Academy covers the basic concepts of linear
algebra at: www.khanacademy.org/math/linear-algebra.

Vector definition
A vector is an n-tuple of real numbers. A tuple is a finite ordered list of elements. An n-tuple is
an ordered list of elements which has n dimensions. In the context of games n is usually 2, 3,
or 4. An n-dimensional vector is represented as follows:

The subscript numbers are called the components of the vector. Components are
expressed as a number or as a letter corresponding to the axis that component represents.
Subscripts are indexed starting with 0. For example, is the same as . Axis x, y, z, and w
correspond to the numbers 0, 1, 2, and 3, respectively.

Vectors are written as a capital bold letter with or without an arrow above it. and V are both
valid symbols for vector V. Throughout this book we are going to be using the arrow notation.

A vector does not have a position; it has a magnitude and a direction. The components of
a vector measure signed displacement. In a two-dimensional vector for example, the first
component represents displacement on the X axis, while the second number represents
displacement on the Y axis.

Visually, a vector is drawn as a displacement arrow. The two dimensional vector


would be drawn as an arrow pointing to 3 units on the X axis and 2 units on the Y axis.

2
Chapter 1

A vector consists of a direction and a magnitude. The direction is where the vector points and
the magnitude is how far along that direction the vector is pointing. You can think of a vector
as a series of instructions. For example, take three steps right and two steps up. Because
a vector does not have a set position, where it is drawn does not matter as shown in the
following diagram:

The preceding figure shows several vectors, with vector (3,2) appearing multiple times. The
origin of a vector could be anywhere; the coordinate system of the preceding figure was
omitted to emphasize this.

Getting ready
Video games commonly use two, three, and four-dimensional vectors. In this recipe, we are
going to define C++ structures for two and three-dimensional vectors. These structures will
expose each component of the vector by the name of an axis, as well as a numeric index.

How to do it…
Follow these steps to start implementing a math library with vector support:

1. Create a new C++ header file; call this file vectors.h; add standard C-style header
guards to the file:
#ifndef _H_MATH_VECTORS_
#define _H_MATH_VECTORS_

// Structure definitions
// Method declarations

#endif

2. Replace the // Structure definitions comment with the definition of a


two-dimensional vector:
typedef struct vec2 {
union {
struct {

3
Vectors
float x;
float y;
};
float asArray[2];
};

float& operator[](int i) {
return asArray[i];
}
} vec2;

3. After the definition of vec2, add the definition for a three-dimensional vector:
typedef struct vec3 {
union {
struct {
float x;
float y;
float z;
};
float asArray[3];
};

float& operator[](int i) {
return asArray[i];
}
} vec3;

How it works…
We have created two new structures, vec2 and vec3. These structures represent two and
three-dimensional vectors, respectively. The structures are similar because with every new
dimension the vector just adds a new component.

Inside the vector structures we declare an anonymous union. This anonymous union allows
us to access the components of the vector by name or as an index into an array of floats.
Additionally, we overloaded the indexing operator for each structure. This will allow us to
index the vectors directly.

With the access patterns we implemented, the components of a vector can be accessed
in the following manner:
vec3 right = {1.0f, 0.0f, 0.0f};
std::cout<< "Component 0: " <<right.x<< "\n";
std::cout<< "Component 0: " <<right.asArray[0] << "\n";
std::cout<< "Component 0: " <<right[0] << "\n";

4
Chapter 1

There's more…
Games often use a four-dimensional vector, which adds a W component. However, this W
component is not always treated as an axis. The W component is often used simply to store
the result of a perspective divide, or to differentiate a vector from a point.

The W component
A vector can represent a point in space or a direction and a magnitude. A three-dimensional
vector has no context; there is no way to tell from the x, y, and z components if the vector is
supposed to be a point in space or a direction and a magnitude. In the context of games,
this is what the W component of a four-dimensional vector is used for.

If the W component is 0, the vector is a direction and a magnitude. If the W component is


anything else, usually 1, the vector is a point in space. This distinction seems arbitrary right
now; it has to do with matrix transformations, which will be covered in Chapter 3, Matrix
Transformations.

We did not implement a four-dimensional vector because we will not need it. Our matrix class
will implement explicit functions for multiplying points and vectors. We will revisit this topic in
Chapter 3, Matrix Transformations.

Component-wise operations
Given two vectors, there are several component-wise operations we can perform. These
operations will operate on each component of the vector and yield a new vector.

You can add two vectors component wise. Given two n-dimensional vectors and ,
addition is defined as follows:

You can also subtract two vectors component wise. Given two n-dimensional vectors and
, subtraction is defined as follows:

5
Vectors

Multiplying two vectors can also be done component wise. There are other ways to multiply
two vectors; the dot product or cross product. Both of these alternate methods will be covered
later in this chapter. Given two n-dimensional vectors and , multiplication is defined
as follows:

In addition to multiplying two vectors, you can also multiply a vector by a scalar. In this
context, a scalar is any real number. Given vector and scalar S, scalar multiplication
is defined as follows:

Finally, we can check for vector equality by comparing each component of the vectors being
tested. Two vectors are the same only if all of their components are equal.

Getting ready
We're going to implement all of the preceding component-wise operations by overloading the
appropriate C++ operators. All of the operators presented in this section can be overloaded in
C# as well. In languages that do not support operator overloading, you will have to make these
into regular functions.

How to do it…
Follow these steps to override common operators for the vector class. This will make working
with vectors feel more intuitive:

1. In vectors.h, add the following function declarations:


vec2 operator+(const vec2& l, const vec2& r);
vec3 operator+(const vec3& l, const vec3& r);
vec2 operator-(const vec2& l, const vec2& r);
vec3 operator-(const vec3& l, const vec3& r);
vec2 operator*(const vec2& l, const vec2& r);
vec3 operator*(const vec3& l, const vec3& r);
vec2 operator*(const vec2& l, float r);
vec3 operator*(const vec3& l, float r);
bool operator==(const vec2& l, const vec2& r);
bool operator==(const vec3& l, const vec3& r);
bool operator!=(const vec2& l, const vec2& r);
bool operator!=(const vec3& l, const vec3& r);

6
Chapter 1

2. Create a new C++ source file, vectors.cpp. Include the following headers in the
new file:
#include "vectors.h"
#include <cmath>
#include <cfloat>

3. Add a macro for comparing floating point numbers to vectors.cpp:


#define CMP(x, y) \
(fabsf((x)–(y)) <= FLT_EPSILON * \
fmaxf(1.0f, \
fmaxf(fabsf(x), fabsf(y))) \
)

4. Add the implementation of vector addition to the vectors.cpp file:


vec2 operator+(const vec2& l, const vec2& r) {
return { l.x + r.x, l.y + r.y };
}

vec3 operator+(const vec3& l, const vec3& r) {


return { l.x + r.x, l.y + r.y, l.z + r.z };
}

5. Add the implementation of vector subtraction to the vectors.cpp file:


vec2 operator-(const vec2& l, const vec2& r) {
return { l.x - r.x, l.y - r.y };
}

vec3 operator-(const vec3& l, const vec3& r) {


return { l.x - r.x, l.y - r.y, l.z - r.z };
}

6. Add the implementation for vector multiplication to the vectors.cpp file:


vec2 operator*(const vec2& l, const vec2& r) {
return { l.x * r.x, l.y * r.y };
}

vec3 operator*(const vec3& l, const vec3& r) {


return { l.x * r.x, l.y * r.y, l.z * r.z };
}

7. Add the implementation for scalar multiplication to the vectors.cpp file:


vec2 operator*(const vec2& l, float r) {
return { l.x * r, l.y * r };
}

7
Vectors
vec3 operator*(const vec3& l, float r) {
return { l.x * r, l.y * r, l.z * r };
}

8. Finally, add the implementation for vector equality to the vectors.cpp file. This is
where the compare macro we created in step 3 comes in:
bool operator==(const vec2& l, const vec2& r) {
return CMP(l.x, r.x) && CMP(l.y, r.y);
}

bool operator==(const vec3& l, const vec3& r) {


return CMP(l.x, r.x) && CMP(l.y, r.y) && CMP(l.z, r.z);
}

bool operator!=(const vec2& l, const vec2& r) {


return !(l == r);
}

bool operator!=(const vec3& l, const vec3& r) {


return !(l == r);
}

How it works…
What these components-wise operations are doing might not be obvious from the definitions
and code provided alone. Let's explore the component-wise operations of vectors visually.

Addition
Every vector describes a series of displacements. For example, the vector (2, 3) means move
two units in the positive X direction and three units in the positive Y direction. We add vectors
by following the series of displacements that each vector represents. To visualize this, given
vectors and , draw them so the head of touches the tail of The result of the
addition is a new vector spanning from the tail of to the head of :

8
Chapter 1

Subtraction
Subtraction works the same way as addition. We have to follow the negative displacement of
vector starting from vector . To visually subtract vectors and , draw and with
their tails touching. The result of the subtraction is a vector spanning from the head of to
the head of :

A more intuitive way to visualize subtraction might be to think of it as adding negative to


, like so; . If we represent the subtraction like this, visually we can follow the rules
of addition:

In the above image, the vector appears multiple times. This is to emphasize that the
position of a vector does not matter. Both of the vectors above represent the same
displacement!

9
Vectors

Multiplication (Vector and Scalar)


Multiplying a vector by a scalar will scale the vector. This is easy to see when we visualize the
result of a multiplication. The scalar multiplication of a vector will result in a uniform scale,
where all components of the vector are scaled by the same amount. Multiplying two vectors
on the other hand results in a non-uniform scale. This just means that each component
of the vector is scaled by the corresponding component of the other vector:

Comparison
Comparing vectors is a component-wise operation. If every component of each vector is the
same, the vectors are equal. However, due to floating point error we can't compare floats
directly. Instead, we must do an epsilon comparison. Epsilon tests commonly fall in one
of two categories: absolute tolerance and relative tolerance:
#define ABSOLUTE(x, y) (fabsf((x)–(y)) <= FLT_EPSILON)
#define RELATIVE(x, y) \
(fabsf((x) – (y)) <= FLT_EPSILON * Max(fabsf(x), fabsf(y)))

The absolute tolerance test fails when the numbers being compared are large. The relative
tolerance test fails when the numbers being compared are small. Because of this, we
implemented a tolerance test with the CMP macro that combines the two. The logic behind the
CMP macro is described by Christer Ericson at www.realtimecollisiondetection.net/
pubs/Tolerances.

There's more…
It's desirable to make vectors easy to construct in code. We can achieve this by adding default
constructors. Each vector should have two constructors: one that takes no arguments and
one that takes a float for each component of the vector. We do not need a copy constructor or
assignment operator as the vec2 and vec3 structures do not contain any dynamic memory
or complex data. The pair of constructors for the vec2 structure will look like this:
vec2() : x(0.0f), y(0.0f) { }
vec2(float _x, float _y) : x(_x), y(_y) { }

10
Chapter 1

The vec3 constructors will look similar, it adds an additional component. The constructors for
the vec3 structure will look like this:
vec3() : x(0.0f), y(0.0f), z(0.0f) { }
vec3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) { }

Dot product
The dot product, sometimes referred to as scalar product or inner product between two
vectors, returns a scalar value. It's written as a dot between two vectors, . The formula
for the dot product is defined as follows:

The sigma symbol means sum (add) everything up that follows. The number on top of
the sigma is the upper limit; the variable on the bottom is the lower limit. If n and i is 0,
the subscripts 0, 1, and 2 are processed. Without using the sigma symbol, the preceding
equation would look like this:

The resulting scalar represents the directional relation of the vectors. That is,
represents how much is pointing in the direction of . Using the dot product we
can tell if two vectors are pointing in the same direction or not following these rules:

ff If the dot product is positive, the vectors are pointing in the same direction
ff If the dot product is negative, the vectors point in opposing directions
ff If the dot product is 0, the vectors are perpendicular

How to do it…
Follow these steps to implement the dot product for two and three dimensional vectors:

1. Add the declaration for the dot product to vectors.h:


float Dot(const vec2& l, const vec2& r);
float Dot(const vec3& l, const vec3& r);

11
Vectors

2. Add the implementation for the dot product to vector.cpp:


float Dot(const vec2& l, const vec2& r) {
return l.x * r.x + l.y * r.y;
}

float Dot(const vec3& l, const vec3& r) {


return l.x * r.x + l.y * r.y + l.z * r.z;
}

How it works…
Given the formula and the code for the dot product, let's see an example of what we could use
it for. Assume we have a spaceship S. We know its forward vector, and a vector that points
to its right, :

We also have an enemy ship E, and a vector that points from our ship S to the enemy ship E,
vector :

How can we tell if the the ship S needs to turn left or right to face the enemy ship E?

We need to take the dot product of and . If the result of the dot product is positive,
the ship needs to turn right. If the result of the dot product is negative, the ship needs
to turn to the left. If the result of the dot product is 0, the ship does not need to turn.

12
Chapter 1

There's more…
Our definition of the dot product is fairly abstract. We know that the dot product gives us some
information as to the angle between the two vectors, and . We can use the dot product
to find the exact angle between these two vectors. The key to this is an alternate definition of
the dot product.

Geometric definition
Given the vectors and , the geometric definition of the dot product is the length of
multiplied by the length of multiplied by the cosine of the angle between them:

The || operator in the above equation means length and will be covered in the next section. We
will cover the geometric definition and other properties of the dot product later in this chapter.

Magnitude
The magnitude or length of a vector is written as the letter of the vector surrounded by two
bars, . The magnitude of a vector is the square root of the dot product of the vector with
itself:

In addition to implementing the magnitude function, we're also going to implement


a magnitude squared function. The formula is the same, but it avoids the expensive
square root operation:

In games we often compare the magnitude of a vector to known numbers; however, doing
a comparison between a number and the magnitude is expensive because of the square
root operation. A simple solution to this problem is to square the number, and then compare
against square magnitude. This means, instead of the following:
if (Magnitude(someVector) < 5.0f) {

13
Vectors

We could instead write the following:


if (MagnitudeSq(someVector) < 5.0f * 5.0f) {

We'd then get the same result, avoiding the expensive square root operation.

Getting ready
To find the magnitude of a vector, take the square root of the vector's dot product with
its-self. The square root operation is a relatively expensive one that should be avoided
whenever possible. For this reason, we are also going to implement a function to find the
square magnitude of a vector.

How to do it…
Follow these steps to implement a function for finding the length and squared length of two
and three dimensional vectors.

1. Add the declaration for magnitude and magnitude squared to vectors.h:


float Magnitude(const vec2& v);
float Magnitude(const vec3& v);

float MagnitudeSq(const vec2& v);


float MagnitudeSq(const vec3& v);

2. Add the implementation for these functions to vectors.cpp:


float Magnitude(const vec2& v) {
return sqrtf(Dot(v, v));
}

float Magnitude(const vec3& v) {


return sqrtf(Dot(v, v));
}

float MagnitudeSq(const vec2& v) {


return Dot(v, v);
}

float MagnitudeSq(const vec3& v) {


return Dot(v, v);
}

14
Chapter 1

How it works…
We can derive the equation for the magnitude of a vector from the geometric definition of the
dot product that we briefly looked at in the last section:

Because we are taking the dot product of the vector with itself, we know the test vectors
point in the same direction; they are co-directional. Because the vectors being tested are
co-directional, the angle between them is 0. The cosine of 0 is 1, meaning the part
of the equation can be eliminated, leaving us with the following:

If both the test vectors are the same (which in our case they are) the equation can be written
using only :

We can rewrite the preceding equation, taking the square root of both sides to find the length
of vector :

There's more…
The magnitude of a vector can be used to find the distance between two points. Assuming we
have points and , we can find a vector ( ) that connects them by subtracting
from , as shown in the following diagram:

15
Vectors

The distance between the two points is the length of . This could be expressed in code
as follows:
float Distance(const vec3& p1, const vec3& p2) {
vec3 t = p1 - p2;
return Magnitude(t);
}

Normalizing
A vector with a magnitude of 1 is a normal vector, sometimes called a unit vector. Whenever
a vector has a length of 1, we can say that it has unit length. A normal vector is written as the
letter of the vector with a caret symbol on top instead of an arrow, . We can normalize any
vector by dividing each of its components by the length of the vector:

We never implemented division operators for the vector class. We can rewrite the preceding
equation as reciprocal multiplication. This means we can obtain the normal of a vector if we
multiply that vector by the inverse of its length:

Getting ready
We are going to implement two functions, Normalize and Normalized. The first function
will change the input vector to have a length of 1. The second function will not change the
input vector; rather it will return a new vector with a length of 1.

How to do it…
Follow these steps to implement functions which will make a vector unit length or return a unit
length vector. These steps utilize reciprocal multiplication.

1. Declare the Normalize and Normalized functions in vectors.h:


void Normalize(vec2& v);
void Normalize(vec3& v);

vec2 Normalized(const vec2& v);


vec3 Normalized(const vec3& v);

16
Chapter 1

2. Add the implementation of these functions to vectors.cpp:


void Normalize(vec2& v) {
v = v * (1.0f / Magnitude(v));
}

void Normalize(vec3& v) {
v = v * (1.0f / Magnitude(v));
}

vec2 Normalized(const vec2& v) {


return v * (1.0f / Magnitude(v));
}

vec3 Normalized(const vec3& v) {


return v * (1.0f / Magnitude(v));
}

How it works…
Normalizing works by scaling the vector by the inverse of its length. This scale makes the
vector have unit length, which is a length of 1. Unit vectors are special as any number
multiplied by 1 stays the same number. This makes unit vectors ideal for representing a
direction. If a direction has unit length, scaling it by some velocity becomes trivial.

Cross product
The cross product is written as a X between two vectors, . It returns a new vector that
is perpendicular to both vectors and . That is, the result of the cross product points
90 degrees from both vectors.

The cross product is defined only for three-dimensional vectors. This is because any two
non-parallel vectors form a plane, and there will always exist a line perpendicular to that
plane. As such, we will only be implementing the cross product for the vec3 structure.

The equation of the cross product is as follows:

Getting ready
The formula behind the cross product seems large and complicated. We're going to implement
a pattern in code that hopefully will make remembering this formula easy.
17
Vectors

How to do it…
The cross product is only well defined for three dimensional vectors. Follow these steps to
implement the cross product in an intuitive way:

1. Add the declaration for the cross product to vectors.h:


vec3 Cross(const vec3& l, const vec3& r);

2. Start the implementation in vectors.cpp:


vec3 Cross(const vec3& l, const vec3& r) {
vec3 result;
// We will add more code here
return resut;
}

3. Start by listing out the x, y, and z components of the result in a column:


vec3 Cross(const vec3& l, const vec3& r) {
vec3 result;
result.x = /* Will finish in step 6 */
result.y = /* Will finish in step 6 */
result.z = /* Will finish in step 6 */
return resut;
}

4. Flesh out the first row by multiplying l.y and r.z. Notice how the first column
contains x, y, and z components in order and so does the first row:
vec3 Cross(const vec3& l, const vec3& r) {
vec3 result;
result.x = l.y * r.z /* Will finish in step 6 */
result.y = /* Will finish in step 6 */
result.z = /* Will finish in step 6 */
return resut;
}

5. Follow the x, y, z pattern for the rest of the rows. Start each row with the appropriate
letter following the letter of the first column:
vec3 Cross(const vec3& l, const vec3& r) {
vec3 result;
result.x = l.y * r.z /* Will finish in step 6 */
result.y = l.z * r.x /* Will finish in step 6 */
result.z = l.x * r.y /* Will finish in step 6 */
return resut;
}

18
Chapter 1

6. Finally, complete the function by subtracting the mirror components of the


multiplication from each row:
vec3 Cross(const vec3& l, const vec3& r) {
vec3 result;
result.x = l.y * r.z - l.z * r.y;
result.y = l.z * r.x - l.x * r.z;
result.z = l.x * r.y - l.y * r.x;
return resut; // Done
}

How it works…
We're going to explore the cross product using three normal vectors that we know to be
perpendicular. Let vector , , and represents the basis of , three-dimensional
space. This means we define the vectors as follows:

ff points right; it is of unit length on the x axis:


ff points up; it is of unit length on the y axis:

ff points forward; it is of unit length on the z axis:

Each of these vectors are orthogonal to each other, meaning they are 90 degrees apart. This
makes all of the following statements about the cross product true:

ff Right X Up = Forward,
ff Up X Forward = Right,
ff Forward X Right = Up,

The cross product is not cumulative, is not the same as . Let's see what happens
if we flip the operands of the preceding formulas:

ff Up X Right = Backward,
ff Forward X Up = Left,
ff Right X Forward = Down,

19
Vectors

Matrices will be covered in the next chapter, if this section is confusing, I suggest re-reading
it after the next chapter. One way to evaluate the cross product is to construct a 3x3 matrix.
The top row of the matrix consists of vector , , and . The next row comprises the
components of the vector on the left side of the cross product, and the final row comprises the
components of the vector on the right side of the cross product. We can then find the cross
product by evaluating the pseudo-determinant of the matrix:

We will discuss matrices and determinants in detail in Chapter 2, Matrices. For now, the
preceding determinant evaluates to the following:

The result of is a scalar, which is then multiplied by the vector. Because


the vector was a unit vector on the x axis, whatever the scalar is will be in the x axis of the
resulting vector. Similarly, whatever is multiplied by will only have a value on the y axis and
whatever is multiplied by will only have a value on the z axis. The preceding determinant
simplifies to the following:

Angles
We have had a brief introduction to the angle between vectors when we discussed the dot
product and the magnitude of a vector. In this recipe, we will discuss how to find the actual
angle between two vectors. The formula to find angle theta between two vectors is:

20
Chapter 1

Getting ready
We have already implemented both the dot product and magnitude functions for vectors;
this means we have everything needed to find the angle between two vectors already written.
In general, this is a very expensive function, as it performs two square roots and an inverse
cosine. Because it's such an expensive function, we try to avoid it whenever possible.

We can save a little bit of performance if, instead of multiplying the length of both vectors,
we multiply the squared length of the vectors and then do just one square root operation
on the result.

How to do it…
1. Add the declaration of the angle function to vectors.h:
float Angle(const vec2& l, const vec2& r);
float Angle(const vec3& l, const vec3& r);

2. Provide the implementation of the angle function in vectors.cpp:


float Angle(const vec2& l, const vec2& r) {
float m = sqrtf(MagnitudeSq(l) * MagnitudeSq(r));
return acos(Dot(l, r) / m);
}

float Angle(const vec3& l, const vec3& r) {


float m = sqrtf(MagnitudeSq(l) * MagnitudeSq(r));
return acos(Dot(l, r) / m);
}

How it works…
This formula relies on the geometric definition of the dot product:

This formula states that the dot product of two vectors is the cosine of the angle between
them multiplied by both of their lengths. We can rewrite this formula with the cosine being
isolated if we divide both sides by the product of the lengths of and :

21
Vectors

We can now use the inverse of cosine, the arc cosine (acos), to find the angle theta:

There's more…
The acos function we used to find the angle between vectors comes from the standard C
math library. This implementation of acos returns radians, not degrees. It's much more
intuitive to think of angles in terms of degrees than radians.

Radians and degrees


Add the following macros to the top of the vectors.h header file:
#define RAD2DEG(x) ((x) * 57.295754f)
#define DEG2RAD(x) ((x) * 0.0174533f)

Using these macros you can convert between radians and degrees. For example, if you wanted
to get the angle in degrees between vectors and , you could use the following code:
float degrees = RAD2DEG(Angle(A, B));

If you are interested in the math used to derive these numbers, I suggest watching the
following Khan Academy video:

https://www.khanacademy.org/math/algebra2/trig-functions/intro-to-
radians-alg2/v/introduction-to-radians

Projection
Sometimes it's useful to decompose a vector into parallel and perpendicular components with
respect to another vector. Projecting onto will give us the length of in the direction
of . This projection decomposes into its parallel component with respect to . Once we
know the parallel component of , we can use it to get the perpendicular component. The
formula for projecting onto is as follows:

22
Chapter 1

The perpendicular component of with respect to is defined as follows:

Getting ready
Implementing the projection is fairly straightforward as we already have both the dot product
and magnitude squared defined. In the following function, the vector being projected is
represented by the variable length, and the vector it is being projected onto is represented
by the variable direction. If we compare it to the preceding formula, length is , and
direction is .

How to do it…
Follow these steps to implement projection functions for two and three dimensional vectors.
A function to get the perpendicular component of the projection is also described:

1. Declare the projection and perpendicular functions in vectors.h:


vec2 Project(const vec2& length, const vec2& direction);
vec3 Project(const vec3& length, const vec3& direction);

vec2 Perpendicular(const vec2& len, const vec2& dir);


vec3 Perpendicular(const vec3& len, const vec3& dir);

2. Add the implementation of projection to vectors.cpp:


vec2 Project(const vec2& length, const vec2& direction) {
float dot = Dot(length, direction);
float magSq = MagnitudeSq(direction);
return direction * (dot / magSq);
}

vec3 Project(const vec3& length, const vec3& direction) {


float dot = Dot(length, direction);
float magSq = MagnitudeSq(direction);
return direction * (dot / magSq);
}

23
Vectors

3. Add the implementation of perpendicular to vectors.cpp:


vec2 Perpendicular(const vec2& len, const vec2& dir) {
return len - Project(len, dir);
}

vec3 Perpendicular(const vec3& len, const vec3& dir) {


return len - Project(len, dir);
}

How it works…
Let's explore how projection works. Say we want to project onto , to find . Having
a ' character next to a vector means prime; it's a transformed version of the vector; is
pronounced A-Prime:

From the preceding figure we see that can be found by subtracting some unknown vector
from . This unknown vector is the perpendicular component of with respect to , let's
call it :

24
Chapter 1

We can get the perpendicular component by subtracting the projection of onto from
. The projection at this point is still unknown, that's what we are trying to find:

Because points in the same direction as , we can express as scaling by some


unknown scalar s, . Knowing this, the problem becomes, how do we find s?:

The dot product of two perpendicular vectors is 0. Because of this, the dot product of and
is going to be 0:

Substitute the value of with the equation we use to find its value, :

25
Vectors

Finally, let's substitute with the equation we use to find its value, :

Now the only unknown in the formula is s, let's try to find it. The dot product exhibits the
distributive property, let's distribute :

Let's start to isolate s, first we add to both sides of the equation:

Now we can isolate s if we divide both sides of the equation by . Remember, the dot
product of a vector with itself yields the square magnitude of that vector:

Now we can solve by substituting s with the preceding formula. The final equation
becomes:

Reflection
One of the most important concepts in physics for games is collision response and how to
react to a collision occurring. More often than not this involves one of the colliding objects
bouncing off the other one. We can achieve the bounding through vector reflection. Reflection
is also heavily used in many areas of game development, such as graphics programming, to
find the color intensity of a fragment.

26
Chapter 1

Given vector and normal , we want to find a vector that is reflected around :

The reflected vector can be found with the following formula:

Keep in mind, in the preceding equation, is a unit length vector. This means that the
part of the equation actually projects onto . If was a non-normalized
vector, the preceding equation would be written as follows:

Getting ready
Implementing the preceding formula is going to look a little different, this is because we
only overloaded the vector scalar multiplication with the scalar being on the right side of the
equation. We're going to implement the function assuming is already normalized.

How to do it…
Follow these steps to implement a function which will reflect both two and three
dimensional vectors.

1. Add the declaration of the reflection function to vectors.h:


vec2 Reflection(const vec2& vec, const vec2& normal);
vec3 Reflection(const vec3& vec, const vec3& normal);

27
Another Random Scribd Document
with Unrelated Content
A TÖRVÉNYEK HALOTTJA.

Jő napról napra bánat a fejemre,


Nagy fájdalom szállott bánatos szívemre,
Ha a nap lenyugszik, az elmém bujdosik,
Hosszú tenger éjen soha el nem nyugszik.

Népdal.

Hosszú hónapok folynak le; hosszak búban és fájdalomban,


rövidek az örömben. Keressük fel az ingovány szigetét.
A nád-tenger sűrűbb és vadonabb körülötte, mint valaha.
A kis ház falai vakolatlanok, kapuja a földön fekszik, ablakai be
vannak töredezve, kéménye nem füstöl, mint hajdan.
Az ananászok helyén maszlag terem, a málnabokrok helyén vad
tövisek, s hol egy időben az ibolya virult, ott csalánok tenyésznek.
A bogáncs elvadulva lepi a dombokat, a csenkesz öleket nő, de
gyümölcsöt nem hoz, a fák nem virágoznak.
A virágcserepekben kórók sárgulnak.
A diófa áll, de árnya nincs, mert ki van száradva; lombjaira nem
repülnek jókedvű madarak, éjenkint nem fekszik alatta a házi eb.
Minden olyan szomorú.
Emberi kéz nyoma nem látszik itt, hanem emberi átoké.
Olykor a sziget legvadonabb oldalán, az összefészkelt burján
közül egy emberalak jelenik meg, egy emberi rém; fejét ifjan
megőszült haj fedi s vadul lóg le szemébe; arcza sáppadt és agg,
ajkai lepittyedtek, nyaka mellére görbült s bágyadt feje ingó lépései
mindegyikénél biczczenik. Kezei hátul vannak összefonva.
Átnézi fénytelen szemeivel a környező sivatagot, átnézi a
felhőkkel sivatag eget s visszanéz magába és nem talál sehol
nyugalmat, sehol egy reményt. Ég, föld és szív, mind oly kietlenek.
Nem sóhajt, nem könyez, nem imádkozik.
Mindezen vigaszok meg vannak tőle tagadva, hanem némán
emésztődve visszafordul s a sziget tulsó oldalán ismét előtünik.
Ott is keresi a névtelen enyhülést és – nem találja.
Reggeltől késő estig űzik őt ekként, egyik parttól a másikig, belül
hordott kisértetek és az éj nem fekteti álomra gondjait.
Egy mély gödörbe van vetve neki ágya, oda fekszik éjjelenként; s
ilyenkor támad csak benne egy gyarló remény, de az nem a holnapra
felvirradás reménye, nem is a halálé, melyen túl tán egy ijesztő
öröklét, hanem az örök megsemmisülésé: elenyészni, mint a lehellet,
mint a hang elenyésznek; ez az ő hite, vallása, bizodalma; s oh,
mikor a szívnyomó álmok rettentő panorámája végig van nézve,
eljön a reggel s felkölti őt hideg ágyából, mintha mondaná:
– Kelj föl érzeni!
Megverte őt az Isten keze, mert neki sem mult, sem jövő, sem a
jelen percz nem ad vigasztalást.
Oh, a liget nem hiába szárad ott el, hol az ő lábai járnak.
Minden hónap elején megjelen iszonyú ellensége.
Mint az el nem imádkozható sors, oly pontosan elkövetkezik az ő
látogatása minden első negyedével a holdnak.
Ilyenkor, mikor a félhold felszáll felhői közé s homályfényét
szétönti a vizeken, mikor a vad, emberhangtalan éjt titkos,
sóhajszerű kisértethangok ijesztik át, mikor a törvények halottja, kit
elástak önkezei embertől nem ismert nagyszerű sírjába, álomtalanul
forgolódik gödör-ágyában, átkozza magát és a felhőkkel elzárt
egeket s riadva szökik fel fekhelyéről, midőn nevét hallja említeni…
– Góliáth Péter!… hangzik a csendben remegő hangon.
Hajszálai borzadva állanak föl önneve hallásától.
– Góliáth Péter, élsz-e még? kérdi a kisértő hang.
És a törvények halottjának nincs elég bátorsága hallgatni,
érthetetlen hangokban sikoltja föl sírja mélyéből, hogy él!
Melyre a remegő hang szól:
– Adjon az ég hosszú életet tenéked!
Azután újra néma lesz minden egy holdévig. Góliáth pedig ájulva
dől gyötrő álmai rémölébe.
Reggelre kelve, a sziget partján egy hónapra való eleséget talál a
törvények halottja s nincs elég bátorsága azt a vizekbe szórni, hogy
a jövő holdujultáig meghaljon éhen, sőt inkább gazdálkodva bánik
vele, mert a halál rá nézve nem jótétemény.
Így folytanak le a hónapok.
Góliáth Pétert mindenki elfelejté…
Egy este a holdnak ismét negyede volt; az évszakos esőzések
szüntelen borúban tarták az eget s az unalmas, változástalan
időjárás kizárt minden szeretni valót a természet legszebb helyeiből;
az ég elveszté kékjét, mintha egy nagy kéz a fenekére ülepedett
salakot kavarta volna fel, hogy attól a csillagok ne látszassanak; a
mezők virágiról lepállott a hímes szirom; ősz lett.
A mocsár vizei rendkívül megnőttek. Estennen a víz lakói, az
ungok, mintha rögtön, egy jelszóra, egy birodalom szólalna meg,
elkezdik melódiátlan egyhangú éneköket s a megszünt eső után
fehér vízháti köd oszlik a vidékre, nehéz bűzű egészségtelen köd,
majdan ragyacseppekben visszahullandó. A szúnyogok milliárdjai
forranak, mint egy óriási méhkas zúgván be a levegőt s a szürke ég
színében vándor vadludak vonulnak keresztül, szomorú
búcsuhangokat kiáltva le a magasból.
A vizek hátán egy hosszú vájt csónak látszik úszni; benne egy
férfi ül, kétlapátú evezővel hajtja a csónakot; nehézkesen látszik az a
holdvilágsütötte ködben haladni s csak a motoláló evező mozdulatai
különböztetik meg a mocsár kóbor úszó szigeteitől, minek sűrű
füvében olykor páros hattyú ül elrejtett fészkén.
A holdnak szivárványa van; a sötét szürke égen ezüstzöld fény-ív
hajlik át, kétfelől a mocsárba érnek le végei; túl rajta homályos
alaktalan üresség; felette egy másik ív, halaványpiros és szélesen
elmosódott tárul öblösen az alig csillagos égen. Ez az éjjeli
szivárvány sokkal tündériebb a nappalinál, mintha csak álma volna
amannak.
A csónak lassúdan evez az ingoványban; néhol úgy tetszik,
mintha zöld mezőben úsznék, hol a képtelenül magas nádnak csak a
hegye látszik ki s sík zölddé teszi a mély víz színét.
Ott a nádberek közepén van az ingovány oáza; a megnőtt vizek
nagy részét lefoglalák, a megmaradt rész vad növényekkel van
ellepve.
Itt a csónakos kiköt, lámpáját leteszi s a sziget partjára kilép;
nem igen van a fű letiporva rajta, nem igen látszik, hogy ember
járna rajta.
– Góliáth Péter, szól méla, illetődött hangon a csónakos; hangja
áthat a sziget egyik felétől a másikig s szétoszlik a nádberekben; alig
hallhatólag kiáltja vissza a nyári lak falán megütődött visszhang
egyes szótagjait.
Nagy, fekete éjbogarak dongtak a jövevény fülei körül, mint örök
vándorútra kárhozott vad szellemek.
– Góliáth Péter, merre vagy? kiálta újra.
Egy hosszú, nyögő sóhaj, fájdalmas és nehéz, szólala meg erre a
sziget bokrosából, reszkető nyöszörgéstől követve, minő azé, kit a
hideg ráz, vagy minőt a kicsukott eb hallat, midőn tagjait az éji
zivatar hidegje veszi meg.
– Ma van november másodika, szóla a jövevény, mint egy nem
látható lényhez beszélve, ma van a halottak ünnepe. Emlékezzél
meg halottaidról, Góliáth Péter, és élj sokáig.
– Oh jaj! ordíta föl egy emberkívüli hang s hallatszék, mint tépi
nyavalyogva a bokrokat a szerencsétlen.
A nyögés közeledett; nehézkes csörtetéssel nyiltak meg a bokrok
s négykézláb mászott elő reszketve és nyögve egy rémalak; ember
lehetett valaha, de most semmi állathoz nem hasonlít; arcza sárral
van bekeverve, mégis kirínak belőle a szokatlan őrültség és a
meggyógyíthatlan lélekfene kórjelei; szemei nem néznek többé fel az
égre. Tagjai csupa csont és bőr, ruházatja rongyokban csüng le róla,
rongyokban csüng le arczába a hosszú, egészen fehér haj.
Oda mászik a jövevény lábaihoz s ott hanyatt vágva magát,
tagjait görcsösen összerántva, karjait feje körül fonva fuldokol
érthetlen szavakat; azután átöleli a jövevény lábát s halálfej-arczát
felemelve hozzá, sír:
– Miért kínzasz engem?
– Eredj! szól ez a sírót elrúgva magától. Sírj, jajgass! nevettél és
örültél, mikor én sírtam és szenvedtem. Kelj fel. Hoztam neked
meleg ruhát és eledelt; tél lesz, fázni fogsz, minden madár elhagyja
tanyádat, magad maradsz. Meglátogat-e még apád árnyéka?
Az ember, mint a derékon szúrt hernyó vonaglott s rebegé:
– Meg. Hajh, milyen véres! Miért nem csuktátok leszemeit, mikor
eltemettétek?
– Csuktad volna le magad, te ölted meg!
– Hahaha! hangzik convulsiv kaczagása a kínzottnak.
– Hát gyermeked elporlott-e már?
– Jaj nekem! jaj nekem! jaj nekem! A darázs rászállt szívemre és
megszúrt.
– Fáj?
– Gyere oda, majd megmutatom; szép kis zöld halom, szájamban
hordom rá a vizet, hogy zöld maradjon. Virágos volt az almafa;
legvirágosabb ágát rágtam le fogaimmal, hogy kereszt legyen sírja
mellett. Oh, ha tudnád, hogyan fáj nekem az a kereszt! nem az én
szívembe van leszúrva, nem, hanem a földbe, de mégis az én
szívemnek fáj. – – – Fölaggattam a keresztre apró ruhácskáit, a
pólyát, a gyöngyös fejkötőt, a himzett mellényt, ott függnek rajta;
naponkint eljön a vihar és kimossa a ruhákat; a piros szalagok
egészen megfehérültek, – elrongyolnak mind – – – oda van melléje
vetve ágyam.
– Puha fekhelyed van?
– Puha, mert az iszap belefolyik; egy gödör, abban fekszem.
– Aludni is szoktál?
– Nem tudom; ott fekszem éj- és naphosszant; lelkem nem
nyugszik soha, szüntelen képeket kell látnom és velök beszélnem.
– Minő képeket?
– Nem mondhatom meg; ők ismernek, de én nem ismerem őket.
Rettenetes képek. Egy ember szívéből a vér csepeg s nekem azt kell
számlálnom, hogy hányat cseppenik; elszámlálok ezerig, tízezerig,
örökször ezerig, remélve, hogy majd eláll, – és mégsem áll el; aztán
egy kigyó lakik bennem, azon a helyen, a hol a szívem volt, belém
lopta magát, mikor aludtam, azt kell tejjel táplálnom, hogy sokáig
éljen és sokáig marhassa lelkemet; majd fenevadat látok futni, fogai
közt kicsiny gyermeket visz, – a kis gyermek sír, én a farkas után
lövök, lövök sokat, az elejti a gyermeket, ki már nem sír, – oda
megyek, fel akarom venni s porrá omlik; a farkas a gyermek vérét
nyalja, – oh iszonyú, iszonyú élet!
– Nem szeretnél eljönni innét?
– Szeretnék, de nem lehet.
– Ki nem engedi?
– Meg vagyok rontva, kötve vagyok nehéz lánczczal, nem
téphetem el, pedig fáj; forgok körülötte, mint a hold.
– Emlékezel-e azon asszonyra, ki valaha ott abban a kis házban
lakott?
Az ember szemei kerekre felnyíltak, melle sebesen pihegett, arcza
mosolygott volna, ha egy halálfej tudna mosolyogni s töredezetten
szólt:.
– Én is laktam ott valaha abban a házban; igen, benne laktam,
de most nem szabad bele mennem, mert ott kisértetek laknak,
ködös éjféleken előjönnek egymás után. Hah! egy sem oly bús, mint
az a – nő – a ki – a ki – a ki… – szava elakadt.
– És az a nő nem emlékezik te rólad; mikor te boldog voltál, ő
tébolyodott volt, most te vagy az őrült, ő a boldog. Szoktál-e
imádkozni?
– Szoktam; minden reggel és este megátkozom anyámat és
születésem óráját és az életet és a halált és a világot s önnön
magamat.
– Nesze! hoztam neked imádságos könyvet, ebből imádkozzál;
csak három levél van benne, de sok gondolat, nesze!
A szerencsétlen átvette a kis könyvet, felnyitotta.
Az egyikre egy férfi volt festve, kinek kés volt verve szívébe: ez
apja.
A másikra egy nő, ki fehér nyugágyon alszik, nyakán piros
gyöngyfüzér: ez neje.
A harmadikra egy csecsemő, piros bölcsőben, szalagos pólyában
kék ernyő alatt: ez gyermeke.
Nagyot kiálta, mint kinek galvánütés érte szívét, magasra
felszökött a levegőbe, azután összehanyatlott, elszédült, tagjai
összezsugorultak s ott feküdt mozdulatlanul, néha egy-egy rángástól
elidomtalanulva.
A félhold nagy udvarából világíta le rá.
Sokáig nézte ott, karjait összefonva, ellensége, Bálnai Körmös
István, a nyomorultat.
Gyönyörködött benne!
Rátette az álomholt fejére kezét, azt a jéghideg és vaserejű
kezet. Fülébe hajolt és fülébe súgott:
– Megbüntetem az apák bűneit a gyermekekben, harmad és
negyed ízig. A te apád halálos ellene volt az én apámnak; a te apád
megfosztá az enyimet nejétől, megfoszta engemet anyámtól,
megfosztá anyámat boldogságától; a te apád engem árvaságra, a
nyomor kenyerére juttatott; a te apád el akarta rabolni kedvesemet,
a szelid angyalt, s hogy el ne rabolhassa, kénytelen voltam őt a
halálnak adni menyasszonyul; a te apád egy várost égetett fel egy
buja szeszélyért, s mikor már ennyi vétke után kezeim között volt,
mikor rettenetes boszút akartam rajta állni, te voltál az, a ki
kiütötted a vérszomjú kezéből a poharat, hogy az a keserű, a mi
benne volt, mind a te fejedre szálljon által. Egy reményem volt még
ekkor hátra, de kelle, hogy megteljen a keserű kehely, – te e
reményemet csúfosan letépted, meggyalázál, testvéremet,
egyetlenemet a világon, becstelenné tetted, őrültté, magamat
földönfutóvá, embergyűlölővé, Isten-káromlóvá. De meglakolsz
nemzetséged minden bűneiért. Azon kézzel, mely bűnhödött, saját
kezeiddel ver meg az Isten; nem egyszer halsz meg, mindennap
meg kell halnod; mindennap visszajönnöd az élet fájdalmaira; belől
hordanod a sebet, mely kínoz, de se meg nem gyógyul, se meg nem
öl. Átkozott vagy és átkozott maradsz halálod órájáig, melyet
halaszszon sokáig az erős, bosszúálló Isten! Amen.
Ezzel ismét csónakába ült a látogató, melyből több zsákot, tűzi
eszközt és egy bundát rakott ki a partra s csendesen tova evezett.
Gyakorta néma napokon és estéken az ingoványi bozótból
fájdalmas sírás hallik, körül széthangozva a hallgató vizeken.
A távolban csíkászók kisértetrívásnak tartják, s nem mernek
közelgni feléje, a különben is járatlan, töretlen lápvadonban.
SZEGÉNY BIRÓ DE KÁR VOLT.

Kilencz iczczés a gyomrom,


Tizedikkel megtoldom.

Népdal.

Még egy tragikai esetet kell elmondanom, mielőtt e regényt


befejezném, mely mint tens Tölcsér János esküdt úr kimenetelét
tárgyazó, nem lehet az őt közelebbről ismerők előtt érdektelen.
***
Vala pedig a napnak igen nagy távolsága a földtől; a kényeső a
zérusfokon alul szállt; az ég vizei kristályozott alakban szálltak alá a
földre; szóval melegség hiánya volt az egész természeten, mely
tüneményt a tudománytalan köznép rövideden nevezi télnek.
Az esküdt úr «jó reggelt», kivánt a táblabiró úrnak, a táblabiró úr
pedig «jó estét», kivánt az esküdt úrnak; – vala pedig
mindkettőjökre nézve tökéletesen «jó éjszaka», míg oda fenn, t. i. a
pincze fölött, a legdicsőségesebb fényes nappal uralkodott.
Tehát a mi «par nobile fratrum» uraink már meglehetősen el
voltak készülve, vagyis magyarul szólván «nyakban voltak», s ha
Galilei soha ki nem találta volna is, hogy a föld forog, ők bizonyosan
bemutatták volna, hogy a föld tántorog, elannyira terhökre esett
nyugalomra kivánkozó testökkel a súlyegyent fentartani.
S elvégre, – biz az szégyen, de mi tűrés, tagadás? biz ők
tisztelettel legyen mondva – elestek. – – No de e történetet eléggé
kimenti a physika, miután bemutatja, hogy ennek oka egyenesen a
föld vonzerejében rejlik, mely minden testeket erőnek erejével ránt
magához.
Ott a földön aztán összeölelkeztek; a táblabiró úr hóna alá
kanyarította az esküdt úr fejét s ilyetén párbeszédhez fogának; mely
párbeszédnek nem csekély hasonlatossága van a takart versekhez.
– Nini, milyen szép csillagos az ég.
– A bizon, az én pejlovam is fakó.
– Ejnye, István, merre van a kulacs?
– De bizony fehér, csak meg kell hámozni.
– Anyjuk – hej anyjuk! – hordom én a te mivoltodat, de rossz
helyre vetetted a fejem alját.
– Elég szép kukoricza, csak hogy nincs meggerebenyezve.
– Hej te, Mihály, fütyölj annak a kutyának, hogy jőjjön ide.
– Magam is megenném, ha volna, nem hogy még neked adjak
belőle.
E gyönyörű összevágó kérdések és feleletek még tán sokáig
tartottak volna, ha a kulacs szíja csakugyan a táblabiró úr kezébe
nem kerül, ki a kulacs száját bajtársa szájához tolva, ezt ekkép meg
akarta itatni.
– Nem iszom, szólt az esküdt úr, hiszen bornemisza vagyok, nem
iszom én a bort sohasem, csak mikor búbánatom van. (Esküdt úrnak
veszedelmesen sok búbánatjának kellett lenni.) Később föl sem
emelve a földről fejét, így szóla a táblabiró úrhoz: ugyan, maga
végzett ember, tudományos ember, mondja meg nekem azt az egyet,
megyünk-e mink most?
E kérdésre a táblabiró úr rettenetes kaczajt ütött, kaczagott,
röhögött; még tán most is kaczagna, ha a köhögés rá nem érkezett
volna.
– Balgatag ember! Hogy szaladnánk; – repülünk – repülünk!
– Hah! kiálta az esküdt úr fölmeresztve szemeit, én még soha
sem repültem életemben, egyszer kivéve, mikor a vármegye háza
ablakán kidobtak, a restóracziókor.
– No én tudom, hogy repülünk, nem érzem a földet a talpam
alatt (a mi nagyon természetes volt, minthogy orrával támaszkodott
rajta); túl vagyok a hetedik égen, az egész világ, – nap – hold – és
akós hordók mind körülöttem forognak.
– De már úgy igaz, hanem én még sem hiszem. Majd mindjárt
megmondja a Jancsi, hogy megyünk-e, vagy csak repülünk.
– Ejnye bizony magam is ösmertem ám olyan embert, a kit
Jancsinak híttak. Hej Jancsi!
– Jancsi!!
– Jancsi!!
Egyik jobban rikoltozott, mint a másik.
Jancsi pedig, ki azalatt odakünn kedvére didergett deres
macskáinál, nem tudta mire vélni e nevére történt hivatkozásokat,
lélekvesztve rohanta meg a pinczeajtót, azt majd levitte magával a
lépcsőkön, ott pedig a saraglyán keresztül bukva, orrán, száján
érkezett le a replikázó felek nyaka közé, mint egy szinházi genius.
– Hát Jancsi, repülünk-e? volt hozzá első szava a táblabiró úrnak.
– Jaj, tens uracskám, bizony repültünk ám, felele orrát tapogatva
Jancsi, majd eltörtem a fejemet.
– Hohó! ad vocem «fej» kiálta fel az esküdt úr, hol maradt az én
fejem? te Jancsi, nem találtad meg a fejemet?
– Nem biz én, nagyuracskám, felelt együgyűen Jancsi, hanem
beütöttem az orromat.
– Minek hordod magaddal? Látod, otthon kellett volna hagynod.
Hanem én, – én – nem tudom, hogy hol hagytam a fejemet, pedig
épen az orromat kellene kifúnom, de az is rajta van. – Eredj,
Jancsikám, gyönyörűséges Jancsikám, keresd fel a fejemet, valahol
ott lesz a hordók között; vagy ha ott nem lesz, hát bizonyosan
másutt lesz.
Jancsi elindult, látván, hogy hányadán vagyunk s kis idő mulva
elkiáltá magát:
– Megvan ám már, nagyuracskám!
– No hozd ide.
– Jaj, de nehéz ám.
– Mindegy – hozd ide – kell.
Jancsi egy gyönyörű nagy kerek répát hozott elő.
Esküdt úr megtapogatta, megnézegette, s végre műértő minákkal
fordult Jancsihoz:
– Ez nem az én fejem, Jancsi, más valakié lehet, de nem az
enyim, az enyim nem ilyen nehéz. Eredj csak keresd – mert tudod,
hogy a nélkül haza nem mehetek.
– Már miért nem! szólalt meg a táblabiró úr, itt van a kulacs,
többet ér ez az úr fejénél, mert ez tele van, az úr feje pedig mindig
üres.
– Az igaz, szólt az esküdt úr, igen engedékeny hangulatban lévén,
nem szoktam benne tartani semmit, csakhogy, mivel az apámról
maradt rám – aviticum.
– Nem ez az? kiálta fel furfangos együgyűséggel Jancsi egy lopó-
tököt mutatva fel.
– De bizony – alighanem, – nem ismerem ugyan, de minthogy
megtaláltad, hát még is annak kell lenni, no csak hozd el, tedd jó
helyre, majd kapsz jó borravalót.
– De csak még is aligha repülünk ám.
– De alig ám.
– De nem is szaladunk ám.
– De nem ám.
– Hanem pihenünk.
– Pihenünk ám.
– Végy a hátadra, Jancsi.
– Jól van, nagyuracskám.
És Jancsi felhordta a nagyuracskákat hátán a pinczéből, s a
szánba belefektette, a kas oldalait hűségesen megtömve szénával és
venyigével.
Hideg volt, hogy az embernek a lelke is didergett.
A hideg nagy ellensége a mámornak.
Tehát a két úr láthatára lassankint tisztulni kezde, elannyira, hogy
már saját lábait mindenki meg tudta a szomszédjáétól különböztetni
(mert a csizmák pogányul kezdtek fázni), s a kulacsot önmagától,
melyhez ugyan felötlően hasonlított, minthogy ő is, az is tele valának
– borral.
Jancsi tehát magára vette öreg szűrét, beült a szánkó elejébe,
egyet előre, másikat hátra vágott czifra ostorával; – a két griffmadár
szétrugott lábaival, s legelsőbb is azon kezdte pályafutását, hogy a
szánkót beledöntötte a hóba.
– Ejnye, nagyuracskáim, szólt Jancsi a szánból kifordultakat újra
összetakarítva, majd feldültünk.
– Mi nem, felele az esküdt úr, csak a szánkó; mely elmés felelet
azt tanusítja, hogy a kis bukhencz sokat kivett a tens úr ködös
fejéből, a mi nem oda való volt, elannyira, hogy Jancsi segedelmével
a helyreállított szánra fel tudott tápászkodni, míg táblabiró úr a
kulacsot szerelmesen szorítván kebléhez, testének egész pondus
specificumát érezteté az őt emelgető Jancsival.
Újra fennültek volna tehát, ha nem feküdtek volna s e közben
szinte beesteledett, – oly rövid audientiákat tart a nap farsang
idején! – no de iszen – se baj, gondolá Jancsi, van a kalendáriomban
holdvilág, aztán a lovak egy csepp bort sem ittak, tudják az útat, – s
újolag neki indulának a czukorszín hótengernek, s ha a gondolat,
mely a költő szánkója elé van fogva, gyorsabb nem volna a két
nyebojszai gebénél, – noha amaz szegény sem szénát, sem abrakot
nem kér, – biz elmaradnának tőlök, mint a kerékvágás.
Így azonban elébök kerülünk, őket hátra hagyjuk, s addig
megyünk, míg ugyanazon az úton egy furcsa emberre nem találunk.
– Oh! sz’ nem ember ez, hanem csak czigány, mondaná erre
nemzetes Bókváryné asszonyság, ránczbaszedett ajkaival, mert
emberünk igen is czigány volt, ugyanazon czigány, ki Bálnait
Góliáthnak nyomába vezette.
Bodor, kóczos haján fakó túri süveg fészkelt, szemeire és füleire
lehúzva; nyakravaló és mándli nem voltak nála divatban, de igen az
elmaradhatatlan vörös pruszli, s ennek hegyébe kerekített névtelen
alapszínű, kékkel, zölddel és feketével foltozott felleghajtó, melyet
hol egyik, hol másik vállára rángatott, azt a csipős szél különböző
oldalról történt megtámadásai ellen védelmezvén, mely műtételt
alkalmasint valamely magyar politikustól tanulhatta el; – hóna alatt
valami olyast visz, mint egy nagy pálannya, alkalmasint duda;
lábszárait hirtelen kapkodja elő, mint kinek az inát korbácsolják;
ráfoghatjuk, hogy fázik.
Beretvánál élesebb a szél, mely a mezőkön keresztül süvölt, s
kikeres minden ajtót, ablakot a legkaczagányabb déczbundán,
melyen át a didergést bemutathassa.
Ime azonban ostorpattogás hallik, s nagy sebesen előcsúszik egy
fakószán s garázda bordalokat harsogtató tekintetes uraimék, kik
dülöngnek egymáshoz, mintha szélvésztől hányatott hajón
utaznának.
Czigányunk szép szemérmesen félre áll, süvegét lehúzza s «-
csés jó napot» mond fennhangon az uraknak, magában egy «álljon
meg a szemetek»-et toldván hozzá.
– Hohohohoó! ordítá a táblabiró úr düledező szemekkel, mely
óvástételre a Szellő és Tündér elereszté fülét farkát és megállt;
megállt a szán is, miként megállt Gibeonnak, vagy nem tudom kinek
a völgyében a hold Josué szavára; csak a hideg szél és a táblabiró úr
fején a báránysüveg nem akartak megállni.
– Te czi-i-gá-gány! hebegé a táblabiró úr, gyere ide mindjárt; hát
mi az, a mit a malaczlopó alatt viszesz?
– Megkövetem egész alázatossággal tekintetes, nagyságos,
nemzetes nagy uram, biz ez, mi tagadás benne, semmi sem egyéb,
mint egy alázatos szegény kis duda.
– Duda? duda! hahaha! uhhaha! bruhaha! (táblabíró úr előtt
rettenetes nevetséges szónak találtatott e szó «duda»). – Nosza, ha
duda, hát fújd.
– Jaj, bizony befagyott a torkom, tekintetes uram, nem lehet.
– Hm, az meglehet, dünnyögé az esküdt úr, az enyém is
befagyhatott volna, ha nem gondoskodom magamról. Tekintetes
uram, nézze, ez a szegény czigány talán még ma délután nem is
ivott, pedig ki tudja, talán ez is ember. Jer, te szánandó vándor, jer,
én értem a te fájdalmaidat, én tudom, hogy mit tesz az: egész
délután nem inni, jer, ülj ide a jobbomra, – (az esküdt úr elkezde
lágyulni, mint esős idővel a kukoriczamálé) – jer szegény árva, én
apád leszek tenéked. (A dade legalább is két annyi idős volt, mint az
esküdt úr, ki őt mámoros érzékenyültségében, a táblabiró úron
keresztül, lelkesülten szorította magához, részvétében erősen végig
sodorva a dade orrát dolmánya zsinórjain.
– Jól van no, ülj fel hát! szólt közbe a táblabiró úr jégcsapos
bajuszán végig húzva öklét, s egyet rántva farkasbundáján, hanem
aztán dudálsz!
Az esküdt úr sentimentalico-philantropico-cosmopolitai
érzeményeiben összecsapta a két első lábát s nagy szörnyűködései
közt ígyen szellőztette ki sértett felebaráti szeretete érzeményeit:
– Mit? hogyan! Hát így kell-e szólani egy emberhez? egy
emberhez, ki csaknem a mi formánkra van teremtve; kinek noha
csak egy pár csizmája, de azért két lába van, mint nekünk; kinek
noha kalapja nincsen, de azért feje van, mint nekünk; kinek ugyan
nincs mit rágnia, de azért foga van neki harminczkettő, mint nekünk,
s ki ámbár borhoz csak gyéren juthat, de azért még talán lelke is van
neki, mint nekünk? s még ennek ily szavakat mondani: «ülj fel,
dudálj!» holott így kellett volna mondani: «szeretett felebarátom és
polgártársam, ha úgy tetszik, legyen szíves helyet foglalni mellettem
és méltóztassék dudálni.»
– Uhhohoháhá! röhöge a táblabiró úr, nosza czigány, tégy
választást, melyik phrasis tetszik jobban: méltóztassék felülni és
dudálni, vagy igyál moré, aztán ülj fel.
– Bizony csak szebb szó ez az utolsó, szólt a barna művész a
kulacsra vigyorintva, melyet a táblabiró úr nyujta elébe, s miután
abból egy buzdító verset gyomrába lehelt volna, nagy nehezen egy
szóra felszállította magát a fakószán kaselejébe.
– No! hogy könnyebben csúszszék a szán! szólt a táblabiró úr,
Jancsival is közölve az öblös kulacsot, mely ekként kézről-kézre
kezde járni, és valahányszor egyet fordult, mindannyiszor egy fokkal
nőtt az esküdt úr elérzékenyülése, egy nuance-szal pirosult a
táblabiró úr arczszíne, egy hanggal magasodott a duda nyekegése s
Jancsi ostorából egy hüvelyknyi elkopott a Szellő és Tündér túros
hátain.
Az esküdt úr desperate kezdte hangoztatni kedvencz nótáját:
«bús az idő, bús vagyok én magam is», míg a táblabiró úr, mint csak
torkán kifért, danolá: «Félre bánat, félre bú, eb a ki ma szomorú!»
mely gyönyörűen egybe hangzó duettet a duda, amaz érzelemteljes
kanászdal áriájával kisérte, mely kezdődik ekkép: «ha valaki vígan
él» stb. Legvégül pedig Jancsi kapott vérszemet s kezét hányva-
vetve kezdé üvölteni: «Hej, hej, mladi pan! csoszo kteri tulipán
jaszom ti dovala?!» (Ha valaki e nótát nem találná érteni, vigasztalja
magát azzal, hogy én magam sem értettem.)
Ezen gyönyörűséges összehangzó symphonák felett pedig
nagyszerű alaphangokban dudolt a januáriusi zephir s roppant
jégcsapokkal koszorúzá a jókedvű menet hőseinek bajuszait.
Azonban nem tarthat minden örökké, mint ezt egy komáromi
fazekas is megmondá, midőn reggel rakott kályhája estére összedűlt;
a kulacs lassanként kifogyott, a duda és a két úr jó és rossz kedve
szinte kifogytak, Jancsi ostora is resignálta a szolgálatot, a szél
tüdejéből is kifogyott a lehellet; hanem e helyett megteltek a mi
kalandoraink fejei borral és szemei álommal s nehány percz mulva
egy sem tudta a négy közül, fiu-e vagy leány? Csak a lovak vették
egy ízben észre, hogy a szánkó szokatlanul megkönnyebbült s
szokott útjokat ösztönszerűleg követve, nagy későre bevánszorogtak
Gyékény Mártonné nagyasszonyom lakása elébe, ki a korhelyeket jó
adag korholásra és túros lepényre várta, s az ajtón, a szemközt fuvó
havas förmeteg ellenére, gyakran aggodalmas arczczal tekintgetett ki
az érkezendők elébe.
– No, Jancsi! hát megjöttetek? kiálta az álmából ocsudó Jancsira.
– Nem tudom én, nagyasszonykám, szólt Jancsi, ki eszének
jelenleg annyi hasznát sem tudta venni, mint egy vasatlan
bicskanyélnek.
– Hát az uraidat hol hagytad, Jancsi?
– Nem tudom én, nagyasszonykám.
– Részeg vagy te, Jancsi?
– Bizony nem tudom én, nagyasszonykám, felelt Jancsi példás
resignatióval.
Gyékény Mártonné asszony mindjárt nem jót sejtve a dologban,
összekurjantá cselédeit, s hát mit láttak? a kas, melyben a szénába
bepakolva ültek kalandoraink, a szánkóról lebontakozva hiányzott, s
hiányzottak mindazok, a kik bele valának helyheztetve.
– Lóra! szánkóra gyorsan! hadará Mártonné, az Istenért, a
farkasok eszik meg őket, vagy ott fagynak meg! frissen! fel kell
lármázni a szomszédokat! kardot, puskát, dorongokat! az egész
falut! az egész világot! rajta! szaporán! lóhalálba!!!!!

E közben a mi kalandoraink odakinn mulattak a havon.


A mint egy zökkenő helyen a rúdtörött szán túlságosan félre
farolt, a lebontakozott kas hirtelen lefordulván, ekkép a három
tündéri álmokban ringatott utazó «in solidum» lemaradt a szánról,
azon helyzetkülönbséggel, hogy míg az esküdt úr és a czigány
egymás ölébe hullának, addig táblabiró úr, testének egész hosszával,
a kas alá esett, mely őt ekként egészen leborította, mint mikor
félfont marhahúst egy tányérral leborítanak, hogy el ne vigyék a
macskák.
Esküdt úr és Bunda czigány, kinek ez alkalommal nagyon jól
eshetett volna, ha nevébe takarózhatott volna, egymást s a közbe
szorult dudát szorosan átölelve tarták, míg a kas alól a táblabiró úr
fiókmennydörgésszerű horkolása tört elő.
Mind a hárman mélységesen aludtak.
Hát egyszer, a mint ott alusznak, a jámbor dudahős fülét egy
borzalmas hang üti meg, mely körülbelől így hangzott: aou!
megeszem a nyakad! s egyszersmind úgy érzé, mintha meztelen
nyakát a takácsvakaró bugájával, vagy csizmadia-ráspolylyal nyalták
volna végig. – – – Fölfeszíti szemeit, – – hej, de jobb lett volna
vakon születnie, mint látni, a mit látott! – egy nagy bozontos szürke
farkast, a mint fejével oda hajolva, szerelmesen pillogatott szemei
közé tüzes szemeivel, s nyelvével száját körülnyalogatta.
– Szent Gábriel szűz és Ágnes pátriarcha! kiálta a czigány s
hirtelen úgy kijózanodott, hogy védszentjei nevét sem tudta
kimondani.
– Te! – te bolond te! meg ne harapj! kis kutyám, nono pisz! pisz
kis kutya! s meg akarta czirógatni a kis kutyát kezével; a kis kutya
azonban e szívesség elfogadására valamennyi fehér fogait
rávicsorítá, mely pantomimikától a hangművésznek szája padlásához
ragadt ijedtében a kimondandó szép szó.
– Jaj bizony, talán azért haragszik, hogy kutyának neveztem?
farkaskám, édes drágalátos kis farkaskám, ne bánts te engem,
bizony rossz ízű húsom van nekem, kitörik benne valamennyi fogad!
Ugyan már minek ennél meg engem? Ugy-e, te se szeretnéd, ha én
téged megennélek? osztán ha engem megeszel, ki ád a szegény
purdéknak kenyeret? Edd meg ezt itt ni! szólt az alvó esküdtöt tolva
előre; ez kalácson hízott, aztán csak nem pokol a béled, hogy mind a
négyünket meg akarj zabálni?
A farkas vagy értette a bőjti prédikácziót, vagy sem, fölnyújtotta
nyakát, s egy hosszút üvöltött, mire a távolból több hasonló üvöltés
felelgetett, s kis idő mulva a a czigány egy sereg apróbb-nagyobb
farkastól látá magát környezve, mik mind iszonyú gratulátiók közt
kerülgették, egyik a többiek közül már köpönyegje gallérjába markolt
fogaival, s kezdte kifelé húzni a hóra.
– Jaaj! ordíta a czigány s kétségbeesésében, a mint jobbra-balra
kapkodott, ime dudájának sípja akada kezébe, Ismerte-e azon
veszedelmes erőt, mely abban rejtezett, vagy csak épen hattyúdalát
akarta vele elfurulyázni, elég az hozzá, hogy végső szorongattatásai
közepett bele sóhajtott, a mint Isten tudnia engedé, a kecskebőrbe,
megnyomva azt erősen könyökével, s elkezde az impertinenter
nyekegni, nyikorogni, bőgni és sikoltozni, oly fülhasogató trillákban
és fioriturákban, staccato és furioso, a milyeneket sem annakelőtte,
sem annakutána nem hallott többé a fülekkel ellátott életműszeres
világ.
A farkasok, mintha mindeniknek a fülébe külön-külön tüzes
taplókat raktak volna, el kezdtek iramodni, s szaladásuk közben oly
jajgatásnak és ordításnak mentek végére, mintha épen egy
németszinházi operából szabadultak volna ki. Orpheus óta nem
cselekedett ily csodát a vadállatokkal a művészet hatalma.
A czigány vevén észre a roppant színi hatást, még erősebben
kezdte fujni és nyaggatni bőrzsákját, melynek egyik trombitája épen
a mélyen alvó esküdt úr füle szomszédságában okádta a hangok
szörnyetegeit.
De bárha aludt volna az esküdt úr oly mélységesen, mint ama
kilencz ifju, kik Decius császár alatt aluvának el s Theodosius alatt
ébredtek fel elalvásuk után 122 esztendőkkel:5) mégis fel kelle
ébrednie, eme farkasgyötrő symphoniáktól. Megmozdult, borzalmas
torzképet rántott, azután befogta az orrát; hogy ez nem használt,
szemeit dörzsölte; ez sem használt, a száját rejtette el; míglen
végtére rájött, hogy a füle az, mely ezen iszonyú variátiók alatt
szenved s felpillantott.
Egy czigányt látott az oldala mellett. – Iszonyúság! – Hármat
kellett lehelnie, hogy összeszedhesse magát.
– Mith? Hogyanh? Hát hogy mersz, te gazember czigány, én
mellettem helyet foglalni? nem tudod, hogy én vagyok a tekintetes
esküdt úr?
Az esküdt úr félóra alatt minden philantropiáját kialudta.
A czigány csak folyvást dögönyözte dudáját.
Welcome to Our Bookstore - The Ultimate Destination for Book Lovers
Are you passionate about books and eager to explore new worlds of
knowledge? At our website, we offer a vast collection of books that
cater to every interest and age group. From classic literature to
specialized publications, self-help books, and children’s stories, we
have it all! Each book is a gateway to new adventures, helping you
expand your knowledge and nourish your soul
Experience Convenient and Enjoyable Book Shopping Our website is more
than just an online bookstore—it’s a bridge connecting readers to the
timeless values of culture and wisdom. With a sleek and user-friendly
interface and a smart search system, you can find your favorite books
quickly and easily. Enjoy special promotions, fast home delivery, and
a seamless shopping experience that saves you time and enhances your
love for reading.
Let us accompany you on the journey of exploring knowledge and
personal growth!

ebookgate.com

You might also like