0% found this document useful (0 votes)
24 views83 pages

Game Physics Cookbook Gabor Szauer Instant Download

The 'Game Physics Cookbook' by Gabor Szauer provides over 100 recipes for implementing efficient game physics and collision detection. It covers essential topics such as vectors, matrices, 2D and 3D shapes, and collision detection techniques, aimed at beginner to intermediate game developers. The book emphasizes practical applications and includes guidance on building a physics engine from scratch using C++.

Uploaded by

ogzqefkwib0043
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)
24 views83 pages

Game Physics Cookbook Gabor Szauer Instant Download

The 'Game Physics Cookbook' by Gabor Szauer provides over 100 recipes for implementing efficient game physics and collision detection. It covers essential topics such as vectors, matrices, 2D and 3D shapes, and collision detection techniques, aimed at beginner to intermediate game developers. The book emphasizes practical applications and includes guidance on building a physics engine from scratch using C++.

Uploaded by

ogzqefkwib0043
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/ 83

Game Physics Cookbook Gabor Szauer download

https://ebookbell.com/product/game-physics-cookbook-gabor-
szauer-6872300

Explore and download more ebooks at ebookbell.com


Here are some recommended products that we believe you will be
interested in. You can click the link to download.

Game Physics Cookbook Szauer Gabor

https://ebookbell.com/product/game-physics-cookbook-szauer-
gabor-153709354

Game Physics Cookbook Gabor Szauer

https://ebookbell.com/product/game-physics-cookbook-gabor-
szauer-31644648

Game Physics Cookbook Gabor Szauer Gabor Szauer

https://ebookbell.com/product/game-physics-cookbook-gabor-szauer-
gabor-szauer-7336540

Game Physics Second Edition 2nd Edition David H Eberly

https://ebookbell.com/product/game-physics-second-edition-2nd-edition-
david-h-eberly-2266232
Game Physics Interactive 3d Technology Series David H Eberly

https://ebookbell.com/product/game-physics-interactive-3d-technology-
series-david-h-eberly-2309988

Game Physics Engine Development How To Build A Robust Commercialgrade


Physics Engine For Your Game Second Edition 2nd Edition Ian Millington

https://ebookbell.com/product/game-physics-engine-development-how-to-
build-a-robust-commercialgrade-physics-engine-for-your-game-second-
edition-2nd-edition-ian-millington-2474548

Game Physics Engine Development Ian Millington

https://ebookbell.com/product/game-physics-engine-development-ian-
millington-33573490

Game Physics Pearls Van Den Bergen Gino

https://ebookbell.com/product/game-physics-pearls-van-den-bergen-
gino-4433848

Learning Game Physics With Bullet Physics And Opengl Practical 3d


Physics Simulation Experience With Modern Featurerich Graphics And
Physics Apis Chris Dickinson

https://ebookbell.com/product/learning-game-physics-with-bullet-
physics-and-opengl-practical-3d-physics-simulation-experience-with-
modern-featurerich-graphics-and-physics-apis-chris-dickinson-43258772
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

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
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
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
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
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
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
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.
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.
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.
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"
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 feedback@packtpub.com, 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.
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.
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
Vectors

2. Add the implementation of the reflection function to vectors.cpp:


vec2 Reflection(const vec2& vec,const vec2& normal) {
float d = Dot(vec, normal);
return sourceVector - normal * (d * 2.0f );
}

vec3 Reflection(const vec3& vec, const vec3& normal) {


float d = Dot(vec, normal);
return sourceVector - normal * (d * 2.0f);
}

How it works…

Given and , we're going to find , which is the reflection of around :

First, we project onto , this operation will yield a vector along that has the length
of :

28
Chapter 1

We want to find the reflected vector . The following figure shows in two places,
remember it doesn't matter where you draw a vector as long as its components are the same:

Looking at the preceding figure, we can tell that subtracting from will result
in :

This is how we get to the final formula, .

29
Matrices
2
In this chapter, we will cover the basic math needed to multiply and invert matrices:

ff Definition
ff Transpose
ff Multiplication
ff Identity matrix
ff Determinant of a 2x2 matrix
ff Matrix of minors
ff Matrix of cofactors
ff Determinant of a 3x3 matrix
ff Operations of a 4x4 matrix
ff Adjugate matrix
ff Matrix inverse

Introduction
Matrices in games are used extensively. In the context of physics, matrices are used to
represent different coordinate spaces. In games, we often combine coordinate spaces; this
is done through matrix multiplication. In game physics, it's useful to move one object into the
coordinate space of another object; this requires matrices to be inverted. In order to invert a
matrix, we have to find its minor, determinant, cofactor, and adjugate. This chapter focuses on
what is needed to multiply and invert matrices.

31
Matrices

Every formula in this chapter is followed by some practical examples. If you


find yourself needing additional examples, Purplemath is a great resource;
look under the Advanced Algebra Topic section: www.purplemath.com/
modules/

Matrix definition
A matrix is a grid of numbers, represented by a bold capital letter. The number of rows
in a matrix is represented by i; the number of columns is represented by j.

For example, in a 3 X 2 matrix, i would be 3 and j would be 2. This 3 X 2 matrix looks like this:

Matrices can be of any dimension; in video games, we tend to use 2 X 2, 3 X 3, and 4 X 4


matrices. If a matrix has the same number of rows and columns, it is called a square matrix.
In this book, we're going to be working mostly with square matrices.

Individual elements of the matrix are indexed with subscripts. For example, refers to the
element in row 1, column 2 of the matrix M.

Getting ready
We are going to implement a 2 X 2, 3 X 3, and 4 X 4 matrix. Internally, each matrix will be
represented as a linear array of memory. Much like vectors, we will use an anonymous
union to support a variety of access patterns. Pay attention to how the indexing operator
is overridden, matrix indices in code start at 0, not 1. This can get confusing; when talking
about matrices in a non-code context, we start subscripting them with 1, not 0.

How to do it…
Follow these steps to add matrix support to our existing math library:

1. Create a new C++ header file, call this file matrices.h. Add basic header guards
to the file, include vectors.h:
#ifndef _H_MATH_MATRICES_
#define _H_MATH_MATRICES_

32
Chapter 2
#include "vectors.h"

// Structure definitions

#endif

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


a 2 X 2 matrix:
typedef struct mat2 {
union {
struct {
float _11, _12,
_21, _22;
};
float asArray[4];
};

inline float* operator[](int i) {


return &(asArray[i * 2]);
}
} mat2;

3. After the definition of mat2, add the definition for a 3 X 3 matrix:


typedef struct mat3 {
union {
struct {
float _11, _12, _13,
_21, _22, _23,
_31, _32, _33;
};
float asArray[9];
};

inline float* operator[](int i) {


return &(asArray[i * 3]);
}
} mat3;

4. Finally, after the definition of mat3, add the definition for a 4 X 4 matrix:
typedef struct mat4 {
union {
struct {
float _11, _12, _13, _14,

33
Matrices
_21, _22, _23, _24,
_31, _32, _33, _34,
_41, _42, _43, _44;
};
float asArray[16];
};

inline float* operator[](int i) {


return &(asArray[i * 4]);
}
} mat4;

How it works…
In the above code, we implemented 2 X 2, 3 X 3, and 4 X 4 matrices. We used an anonymous
union and overloaded the indexing operator to support a variety of access patterns. The usage
of anonymous unions is similar to how we constructed the vec2 and vec3 structures.

The underlying data for each matrix is a linear array; rows are laid out sequentially in
this array:

This means the matrix is laid out in memory one row at a time, as follows:
float M[9] = { A, B, C, D, E, F, G, H, I };

Each matrix structure supports the following access patterns:


mat4 m4 = {1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 5.0f,
0.0f, 0.0f, 0.0f, 1.0f };

std::cout<< "element at index 11: " <<m4[2][3] << "\n";


std::cout<< "element at index 11: " << m4._34 << "\n";
std::cout<< "element at index 11: " <<m4.asArray[11] << "\n";

The first pattern demonstrated uses the overloaded indexing operator. This operator returns a
float pointer to the first element of the specified row. A pointer in C++ can be accessed as an
array; this allows us to use double brackets. This overload starts indexing a matrix at 0.

34
Chapter 2

Next, the anonymous union allows us to access elements using the _ij notation. Using this
notation, i is the row, j is the column. These indices start at 1, not 0! This means element
[2][3] is the same as element _34. This indexing scheme closely resembles the way we talk
about math in text.

Finally, we can access the array using the .isArray member of the anonymous union. This
allows us to index the matrix as the underlying linear array structure. Indexing for this array
starts at 0. You can convert a 2D array index i,j, to a 1D array index using the formula:
columns * i + j. Where i represents the row you are trying to access, j represents the
column, and columns is the number of columns in the 2D representation of the array.

Transpose
The transpose of matrix M, written as is a matrix in which every element i, j equals the
element j, i of the original matrix. The transpose of a matrix can be acquired by reflecting the
matrix over its main diagonal, writing the rows of M as the columns of , or by writing the
columns of M as the rows of . We can express the transpose for each component of a
matrix with the following equation:

The transpose operation replaces the rows of a matrix with its columns:

Getting ready
We're going to create a non-nested loop that serves as a generic Transpose function. This
function will be able to transpose matrices of any dimension. We're then going to create
Transpose functions specific to 2 X 2, 3 X 3, and 4 X 4 matrices. These more specific
functions are going to call the generic Transpose with the appropriate arguments.

35
Matrices

How to do it…
Follow these steps to implement a generic transpose function and transpose functions
for two, three and four dimensional square matrices:

1. Add the declarations for all of the Transpose function to matrices.h:


void Transpose(const float *srcMat, float *dstMat,
int srcRows, int srcCols);
mat2 Transpose(const mat2& matrix);
mat3 Transpose(const mat3& matrix);
mat4 Transpose(const mat4& matrix);

2. Create a new file, matrices.cpp. In this file, include the cmath, cfloat, and
matrices.h headers. Also, include a copy of the CMP macro we used in vectors.
cpp:
#include "matrices.h"
#include <cmath>
#include <cfloat>

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

3. Implement the generic transpose function in matrices.cpp:


void Transpose(const float *srcMat, float *dstMat,
int srcRows, int srcCols) {
for (int i = 0; i < srcRows * srcCols; i++) {
int row = i / srcRows;
int ccl = i % srcRows;
dstMat[i] = srcMat[srcCols * col + row];
}
}

4. Using the generic Transpose function, implement Transpose for 2 X 2, 3 X 3, and


4 X 4 matrices in matrices.cpp:
mat2 Transpose(const mat2& matrix) {
mat2 result;
Transpose(matrix.asArray, result.asArray, 2, 2);
return result;
}

mat3 Transpose(const mat3& matrix) {


mat3 result;
Transpose(matrix.asArray, result.asArray, 3, 3);

36
Chapter 2
return result;
}

mat4 Transpose(const mat4& matrix) {


mat4 result;
Transpose(matrix.asArray, result.asArray, 4, 4);
return result;
}

How it works…
Let's explore how the generic version of Transpose works by examining how a single element
is transposed. Assume we have the following 4 X 4 matrix:

We're going to find the transpose of the element in row 3, column 4; it has the value L. If
we access the matrix as an array, the linear index of L is 11. Let's explore how the generic
Transpose loop works when i == 11.

First, the values of row and col are calculated. To calculate the row of the element: row =
i / srcRows, substitute 11 for i, this becomes row = 11 / 4. C++ integer division
truncates the result towards 0, therefore row = 2. Remember the array is indexed starting at
0 not 1, meaning the row at index 2 is actually the third row. The column is calculated using
the modulo operator col = i % srcRows, substituting the variables becomes col = 11
% 4. The result of this operation is 3. Again, the column at index 3 is actually the 4th column,
and this is the expected behavior.

We index the source array using [srcCols * col + row], substituting the variables, this
becomes [4 * 3 + 2]. The result is index 14. The element in the original matrix at index
14 is element O, the transpose of L.

To index the original element, L, we would change the index calculation to [srcCols * row
+ col]. To access the transpose of the element, all we had to do was switch the row and
col variables.

37
Matrices

Multiplication
Like a vector, there are many ways to multiply a matrix. In this chapter we will cover multiplying
matrices by a scalar or by another matrix. Scalar multiplication is component wise. Given a
matrix M and a scalar s, scalar multiplication is defined as follows:

We can also multiply a matrix by another matrix. Two matrices, A and B, can be multiplied
together only if the number of columns in A matches the number of rows in B. That is, two
matrices can only be multiplied together if their inner dimensions match.

When multiplying two matrices together, the dimension of the resulting matrix will match the
outer dimensions of the matrices being multiplied. If A is an matrix and B is an
matrix, the product of AB will be an matrix. We can find each element of the matrix AB
with the following formula:

This operation concatenates the transformations represented by the two matrices into one
matrix. Matrix multiplication is not cumulative. . However, matrix multiplication is
associative, meaning .

Getting ready
Just as with the Transpose operation, we're going to write a generic matrix multiplication
function that works on arrays representing matrices of any size. Then, we're going to call
this generic matrix multiply function from operator overrides for mat2, mat3, and mat4.

How to do it…
Follow these steps to implement scalar multiplication for two, three and four dimensional
square matrices:

1. We're going to start with scalar multiplication. First, add the declaration for scalar
multiplication to matrices.h.:
mat2 operator*(const mat2& matrix, float scalar);
mat3 operator*(const mat3& matrix, float scalar);
mat4 operator*(const mat4& matrix, float scalar);

38
Exploring the Variety of Random
Documents with Different Content
“Do you know anybody on board?”

“I know Jack Crumpet. He sailed in the old Resolute [216]


with me. I went to see him—that’s how I know the Mary
Delaway sailed.”

“You were on board?” asked Dick.

“No, I wasn’t—I saw Jack on the dock. He said as how


the cap’n had given orders for nobuddy to come aboard
—why, I don’t know.”

“Well, I know,” muttered Dick. “It was to keep their


villainous doings secret. Who did you see on the
schooner?”

“I saw several men and two ladies. One lady looked kind
of excited.”

“It must have been Mrs. Stanhope!” murmured Dick.


“Come!” he cried. “Let us get some kind of a boat and
follow that schooner.”

The Rover boys were accustomed to quick action, and


they had supplied themselves with plenty of ready cash
to use in case of emergency. Consequently, it was an
easy matter for them to pick up a steam tug at one of
the docks. The captain said he would willingly follow up
the Mary Delaway and try to overtake her if he was paid
for it.

“Will you go along?” asked Dick, of the old tar. “I want


you to aid in picking up that schooner. You know her by
sight. I will pay you good wages.”

“I’ve signed articles for a trip to Africy, starting next [217]


week Thursday,” answered Larry Dixon, for such was
the sailor’s name.

“We’ll get you back long before that time,” answered


Dick. “And pay you a nice salary in the bargain.”

“Then I’m your man, messmate,” responded Larry


Dixon.

While the steam tug was getting ready to leave, Dick


called up Spud on the telephone and acquainted their
college chum with what had occurred.

“When will you be back?” asked Spud.

“I don’t know,” replied Dick. “Better not wait for us. This
may prove a long chase.”

“Well, I hope you rescue the lady, get back the fortune,
and land those rascals in jail,” said Spud.

The steam tug carried a crew of six, all good, strong,


hearty fellows. In a few brief words Dick and his
brothers explained to the captain how matters stood,
and Captain Wells promised to aid them all he could in
thwarting the plans of the evildoers. He was armed, and
said he could lend the Rovers some pistols if they
wanted them.

“I reckon the Mary Delaway will take the regular route [218]
to Portland—that is, so far as the wind will allow,” said
the owner of the tug. “We’ll follow that route just as fast
as our steam will permit. But let me give you a tip.
Perhaps it will be better for you to merely follow ’em to
Portland, and have them locked up when they reach
that place. If you tackle ’em on the high seas they may
show fight and get the best of you.”
“I’ll think that over,” answered Dick, slowly. “But
meanwhile crowd on all steam and get after them.
Never mind using up your coal—we’ll pay for it.”

The docks were soon left behind, and the black smoke
pouring from the funnel told how the fireman was doing
his best to make steam. But it was now late, and it
would soon become a problem, as to whether it would
be advisable to run so fast during the night. They might
pass the schooner without knowing it.

“I’ll leave the matter to you, Captain Wells,” said Dick,


after talking the matter over with his brothers. “I’ll pay
you your regular price for chartering the tug, and one
hundred dollars additional if we succeed in rescuing
Mrs. Stanhope.”

“I’ll do my level best for you, Mr. Rover,” responded the


captain. “I’ll talk to my crew.” And he did, promising
each man an extra five dollars if they succeeded in
doing what the Rovers desired. As a consequence every
man, including Larry Dixon, was constantly on the
lookout for the Mary Delaway.

Inside of an hour Boston Harbor had been left well [219]


behind, and then the bow of the steam tug was turned
up the coast in the direction of Portland, about a
hundred miles distance. The day was now over and the
lights on the tug were lit.

“Don’t see anything of the Mary Delaway yet,” remarked


Larry Dixon. “I’m afraid we’ll have to shut up shop till
mornin’.”

“Could the schooner reach Portland by that time?” asked


Sam.
“She’d be there early in the morning,” answered the old
sailor.

“Then we had better run for Portland, too,” said Tom.


“We might hang around outside the harbor on the
watch.”

It was a clear night, with no moon, but with countless


stars bespangling the heavens. The boys and some of
the others remained on the watch, although they could
see but little.

“It would be great if we had a searchlight,” said Sam.

“Just the thing!” cried Tom. “But we haven’t any, so


what’s the use of talking about it?”

“Might as well try to get some sleep,” said Captain [220]


Wells, about nine o’clock. “I can call you if anything
turns up.”

“We’ll stay up a couple of hours yet,” answered Dick,


although the excitement of the day had worn him out.

But not a sight of the schooner was seen, and one after
another the Rover boys laid down to get a few hours’
sleep. Captain Wells allowed them to rest until six
o’clock. By that time they were standing around near
the entrance to Portland harbor.

“See anything yet?” asked Dick, as he sprang up from


the berth upon which he had been resting.

“Not yet,” answered the captain of the tug.

“You don’t think they got here ahead of us?”


“No, for we have been here for several hours.”

The boys got up and washed, and then had breakfast.


In the meantime the steam tug cruised around, and
those on board watched eagerly for a sign of the Mary
Delaway.

Thus two hours passed. As the time went by the three


Rovers grew more anxious than ever.

“What do you make of this, Dick?” asked Tom.

“I don’t know what to make of it, Tom.”

“It looks to me as if they had given us the slip,” said


Sam.

“If they didn’t come here, where did they go to?” [221]

“I don’t know. What did that scrap of paper say?”

“That spoke of Slay’s Island. But none of the men on


this tug ever heard of such a place.”

“That is not to be wondered at, Dick,” went on Sam. “I


understand there are scores of islands in Casco Bay. It
isn’t likely these men from Boston would know the
names of all of ’em.”

They remained around the entrance to Portland harbor


until noon and then Dick ordered the captain to run in
and land them.

“You might go up and down the docks a bit,” he said.


“They might have slipped us after all.” They entered the
harbor, passing the old lighthouse, and soon were within
easy reach of the docks. They looked on all sides for the
Mary Delaway, but in vain.

“We have missed her!” groaned Dick.

“What are you going to do next?” questioned Tom.

“See if I can’t find out in some way where the schooner


went to—and also find out where Slay’s Island is
located.”

“We might get a map of Casco Bay. That would have the
names of the islands on it,” suggested Sam. “I know
there are a great many of ’em, some of ’em quite small
and others very large.”

At last they started to go ashore. They ran up to a dock [222]


where the tug was in the habit of landing when at
Portland, and the boys walked to the gangplank that
was put out for them.

“Look! look!” cried Tom, suddenly, and pointed to a


motor boat lying alongside the steam tug.

“Well, I never!” gasped Sam.

The motor boat was a craft of fair size, and very gaudily
painted, in red, blue and yellow. It was piled high with
suit-cases, bundles and fishing outfits. At the wheel was
a tall young man, smoking a cigarette—a stranger to the
Rovers. In the bow, also smoking, were two other
young men, Jerry Koswell and Bart Larkspur.

[223]
CHAPTER XXIII
ABOARD THE MARY DELAWAY

“Hold on there, you!” bawled Jerry Koswell.

“Why, it’s the Rovers!” ejaculated Bart Larkspur. “How


did they get here?”

“They are following us, that’s what!” stormed Koswell.


“And I won’t have it!”

“What do you want?” asked Dick, as he walked to the


end of the tug nearest to the motor boat.

“I want to know what right you’ve got to follow us?”


returned Jerry Koswell, sourly.

“Who said we were following you?”

“Oh, I know you are. Didn’t you follow us to Boston,


too? I want to know what it means?”

“Maybe it means that we are going to have you


arrested,” put in Tom, with a side wink at his brothers.

“Arrested!” gasped Larkspur, and turned pale. “You


shan’t do it!”
“I want you to stop following us,” went on Koswell.

“Go ahead—don’t talk to them any more!” whispered [224]


Larkspur, uneasily. “Let us get away as soon as we can.”

“I am not afraid,” answered Koswell, boastfully.

“But they may have us locked up!”

“What’s the row about?” asked the young man who was
at the wheel.

“Oh, it was a row we had at college, Alf. Those fellows


were in the wrong, but they made the Head believe
otherwise, and we had to—er—resign,” answered Jerry
Koswell. “Well, go ahead, if you want to,” he added.

“Where are you going?” asked Tom, as the motor boat


commenced to move from the dock.

“We are bound for——” began the stranger.

“Don’t tell them, Alf!” begged Larkspur. “Go ahead—let’s


get out.”

“If you don’t tell us where you are going——” began


Sam, when Dick stopped him.

“Let them go—we haven’t time to bother with them


now,” said the eldest Rover boy. “We have other fish to
fry.”

“As you say, Dick. But we ought to scare the wits out of
them if nothing else.”

“We’ll do it—some day,” put in Tom.


As the motor boat swept past they saw that the craft
was named the Magnet. Soon some other boats coming
in hid it from view.

On going ashore, the Rover boys made diligent inquiries [225]


concerning the Mary Delaway and at last learned that
the schooner was expected by a certain transportation
company some time that afternoon, to take on a cargo
of lumber for Newark, New Jersey.

“I don’t know what we can do excepting to wait,” said


Dick.

“Let us go down the harbor to meet the schooner,” said


Tom. “Then Sobber and Crabtree and the others won’t
have any chance to land in secret.”

“Do you think they’ll try to land here, Dick?”

“Honestly Tom, I don’t. It is more than likely the captain


of the schooner will land that crowd on some island
before he comes into Portland.”

“Slay’s Island?”

“Yes—if there really is such a place.”

The steam tug left the dock and ran down to the
neighborhood of Portland Light. Here they cruised
around for nearly two hours, when old Larry Dixon gave
a shout:

“I see her! I see her! There’s the Mary Delaway!”

“Where?” asked the three Rovers, excitedly.


“There!” And the old sailor pointed with his hand. “I
know her by the two patches on her mainsail and the
slit in her jib.”

The steam tug was headed in the direction of the [226]


incoming schooner, and before long the two craft were
within hailing distance of each other.

“Aboard the schooner!” cried Dick.

“Aboard the tug!” was the answering hail.

“I want to talk to the captain.”

“I’m the captain. What do you want?”

“I want you to lay-to and let me come on board.”

“What for?”

“Business.”

“I’m in a hurry,” snapped the captain of the Mary


Delaway, and the Rovers saw that he was a hard
looking individual.

“You can suit yourself, Captain. But if you don’t let me


come on board I’ll have you placed under arrest as soon
as you reach your dock,” said Dick, in the sternest voice
he could command.

“Arrest!” roared the master of the schooner. “Don’t you


talk like that to me, you young whipper-snapper.”

“I will talk like that to you—and I’ll do just what I said.”

“Have me arrested! You must be joking.”


“I am not.”

“What for?”

“You know well enough.”

“Honestly I don’t. You have made some mistake.” [227]

“Are you going to stop and let me come on board, or


not?” went on Dick, as calmly as he could. “If you don’t,
it’s arrest and nothing less. You can take your choice.”

“I don’t know what you are talking about,” growled the


captain. “But I suppose I’ll have to let you come aboard,
to avoid worse trouble.”

The schooner was brought around, and not without


difficulty Dick leaped aboard, followed by Tom and Sam.
The captain of the schooner when he saw that they
were only young men, glared savagely at them.

“Now then, explain yourselves!” he snapped, shortly.

“I want to know what you have done with Mrs.


Stanhope?” said Dick, thinking it best to come directly
to the point.

“Mrs. Stanhope? Who is she?”

“The lady who was abducted by Tad Sobber and Josiah


Crabtree and taken on your schooner at Boston.”

“Never heard of any of the people you are talking about,


young man. You have got hold of the wrong boat.”

“No, there is no mistake. You left Boston yesterday [228]


afternoon, and you had on board Mrs. Stanhope and her
abductors. I guess you are old enough to know what
the punishment is for abduction,” went on Dick,
pointedly.

“Abduction? I ain’t abducted nobody, I tell you. You’ve


got hold of the wrong boat. You can search us if you
want to.”

“Oh, I don’t suppose the lady is on board now. I want to


know what you did with her.”

“Don’t know her—never saw her.”

“You took her on board, and you were seen doing it,”
put in Tom.

“Seen!” cried the captain, and gave a start.

“Yes,” put in Sam. “Oh, we’ve got you dead to rights,


and the best thing you can do is to tell us at once where
she is.”

“Say,” said the master of the schooner, slowly and


thoughtfully. “You tell me the particulars of this matter
and maybe I can put you on the track of something. I
never heard of any lady being abducted.” He saw that
he was cornered and that if arrested matters might go
very hard with him.

In a few words Dick and his brothers told about how the
Stanhope fortune had been stolen and how the lady
herself had been abducted and taken to Boston. Then
they said they had positive proof that the lady had been
taken aboard the Mary Delaway.

“Where is the proof?” asked the captain, and now his [229]
voice was not as steady as it had been.
“Well, for one thing, there is a sailor on the tug who
saw the lady on your vessel,” said Dick. “In the second
place I’ve got a letter, written by one of those rascals,
and naming your boat——”

“What! Did any of those lunkheads write it down in a


letter?” roared the captain. “If they did——” he stopped,
in great confusion.

“Ah, so you admit the crime, do you?” said Dick, quickly.

“No, I don’t admit no crime!” growled the captain of the


schooner. “I promised to do a little job for two
gentleman, that’s all—and I did it—and got paid for it.”

“What was the job to be?”

“If I tell you, you won’t try to drag me into it, will you?”
was the anxious question.

“If you don’t tell us, you’ll surely go to jail.”

“I didn’t know there was anything wrong, honest I


didn’t—leastwise at the start, although I had some
suspicions later. That feller Sobber and the old gent,
Crabtree, along with a Mrs. Sobber, said they had an
aunt who was a bit insane, and they wanted to take her
to an island up here in Casco Bay, for rest and medical
treatment. They hired me to do the job, and paid me
well for it.”

“And you took them to the island?”

“I did.” [230]

“What island?” asked all of the Rover boys.


“A place called Chesoque.”

“Chesoque?”

“Yes. The old lobster catchers used to call it Shay’s


Island, after old Cap’n Shay, of the lobster fleet.”

[231]
CHAPTER XXIV
OUT ON CASCO BAY

The Rover boys listened with close attention to the


statement made by the captain of the schooner and
they felt that the fellow was now telling the truth.

“You say you suspected that all wasn’t square?” said


Dick, after a pause. “What made you do that?”

“Why—er—the way the lady acted. She seemed to be


more scared than crazy. But they kept her down in the
cabin, so I didn’t see much of her.”

“When did you land the crowd on the island?”

“About nine o’clock this morning.”

“Were you going back there later?”

“No, they said it wouldn’t be necessary.”

Dick walked to the rail of the schooner and beckoned to


the captain of the steam tug.

“This captain says he landed the crowd on Chesoque


Island,” he called out. “Do you know where that is?”
“I know where she is,” put in Larry Dixon, as Captain [232]
Wells hesitated in thought. “The lobster catchers used
to have a hangout there.”

“Where is it?” asked Captain Wells, and the old tar


described its location as well as he could.

“Reckon I could pick it up, from what the man says,”


said the captain of the tug, to Dick.

“All right then,” answered the eldest Rover. He turned


again to the captain of the schooner. “Now listen to me.
I know you and I know your boat. If you have told me
the exact truth, well and good. If you haven’t—well,
you’ll have to take the consequences, that’s all.”

“I didn’t abduct nobody. I only did a job and got paid for
it,” muttered the captain.

“Where are you bound?”

“Portland.”

“And after that?”

“Going to—er—take a load of lumber down to Newark,


New Jersey.”

“Very well—then we’ll know where to locate you. Come


on!” added Dick to his brothers.

“You can rely on me,” said the captain, and spoke quite
respectfully. “I’ll tell all I know, and so will my men.”

“Hello, Jack!” cried Larry Dixon to a sailor on the


schooner, and the fellow addressed waved his hand.
“I’ll talk to that man a minute,” said Dick, to the captain. [233]
The latter wished to demur, but Dick gave him no
chance. The fellow was told to go aboard the tug, and
there Larry Dixon asked him to tell his story. The sailor
had little, however, to add to what his captain had said,
excepting that the landing at Chesoque Island had been
made in something of a hurry.

“Here’s a dollar for you,” said Dick, on parting.


“Whenever the schooner makes a landing anywhere,
you send me word where she is,” and he gave the tar
his home address and also the address of a hotel in
Portland.

“Don’t try to get me into trouble and I’ll tell you


everything I know!” shouted the captain of the
schooner, as the steam tug went on its way.

“I’ll remember you!” answered Dick, somewhat grimly.


He did not know whether he could trust the captain or
not.

Leaving the entrance to Portland Harbor, the tug


steamed up into the waters of Casco Bay, that beautiful
spot with its scores of verdant and rocky islands. As it
was the height of the summer season they passed many
pleasure boats, big and little. Once they passed an
island where a big picnic was in progress and they
heard the music from a band quite distinctly. They also
passed Peak’s Island where there was a big, round-
topped structure, which the captain of the tug said was
a famous summer theater.

“A fellow could certainly have a dandy time here, [234]


cruising around among the islands,” was Tom’s
comment.
From Larry Dixon the boys learned that Chesoque Island
was away from most of the others, lying far out in the
Bay. It was a rocky place, and there was a story that
once a band of smugglers had used it for a rendezvous.
It was also said to be inhabited by numerous snakes.

“Excuse me, but I don’t want to run up against any


snakes,” said Sam, shuddering.

“Neither do I,” added Tom.

“No snakes shall stop me from trying to locate Mrs.


Stanhope,” said Dick. “More than likely the story about
snakes has little foundation to it.”

“Like the story about the snakes back of Putnam Hall,”


said Tom. “Old Farmer Landell said there were
thousands of ’em, and he and his son killed exactly five,
and only little ones at that.”

Presently a distant shore loomed up and after an


examination Larry Dixon declared it was the island for
which they were seeking.

“Are you sure?” questioned Dick. “This is very


important, and we don’t want to make any mistake.”

“I know the spot,” answered the old tar. “See that old [235]
building? The lobster catchers used to use that. And see
that rock? There is where the old John Spurr struck, in a
storm one winter.”

“Well, I don’t want to strike anything,” said Captain


Wells, and ordered the engineer to reduce speed. Then,
with great caution, they approached what had once
been a good dock, but one which was now practically in
ruins.
“Hello, there’s a motor boat!” cried Sam, as they came
closer. Then all looked and saw that a gaudily-painted
motor boat was tied up on one side of the old dock.

“Say, that looks like the motor boat Koswell, Larkspur


and that stranger had!” ejaculated Dick.

“It is the same!” shouted Tom. “There is the name,


Magnet. Now what do you think of that!”

“What do I think?” said Dick. “I think they must be


here.”

“With Sobber and the others?”

“I don’t know about that. I didn’t think they knew


Sobber.”

As the steam tug drew up on the other side of the


dilapidated dock, those on board saw three persons
rush from the old building nearby. They were Koswell,
Larkspur and the fellow who had been running the
motor boat.

“Say, I won’t have this!” roared Koswell. “You get out of


here, and be quick about it!”

“Can’t we stop ’em from landing?” asked Larkspur. He [236]


was plainly scared.

“You can’t land here!” called out the young man who
had run the Magnet. “This is private property. I forbid
you coming in.”

“Private property?” called out Captain Wells.


“That is what I said.” And now the young man turned to
his companions and a whispered, but animated
conversation ensued.

“Who are you?” asked Dick.

“I am Alfred Darkingham. This island belongs to my


uncle, John Darkingham. He gave us permission to
come camping here, and said we needn’t let anybody
else come ashore. I forbid your making a landing.”

“That’s the way to talk, Alf!” cried Koswell, in a low, but


earnest voice. “Make ’em stay away.”

“Yes! Yes! don’t let ’em come ashore!” added Larkspur.

“Mr. Darkingham, I’d like to talk to you,” said Dick, as


the steam tug bumped against the dock.

“Don’t you listen to him, Alf!” cried Koswell. “He only


came to make trouble.”

“Make him go right away,” added Larkspur.

“I want you to leave,” ordered Alfred Darkingham.


Evidently he was a close crony to the boys who had run
away from Brill.

“I want to ask you a few questions,” pursued Dick, [237]


firmly. “And I’ll not go away until you answer them—and
maybe not then.”

“This is private property, and—”

“You said that before. What I want to know is, Do you


know the other persons on this island?”

“There are no other persons.”


“I believe otherwise. A lady has been abducted, and I
have every reason to believe she was taken to this
island.”

“Nobody here. I was here yesterday, and all of last


week, and I know.”

“I think they brought the lady here this morning, about


nine o’clock. I’d like to search the island for her.”

“It’s a trick!” cried Larkspur. “It’s a trick to get ashore


and play us foul! Don’t you let ’em land!”

“There is nobody on this island but ourselves,” said


Alfred Darkingham. “You can take my word for that.”

“Will you let me make a search?”

“I will not. I want you to go away, and at once. This is


private property, and if you try to land I’ll have the law
on you!” And as he spoke the young man looked not
only at the Rovers but also at the captain of the steam
tug.

[238]
CHAPTER XXV
ON CHESOQUE ISLAND

For a moment there was silence. Dick looked at Alfred


Darkingham and then at Captain Wells.

“What do you think of this?” he asked of the captain of


the tug.

The captain shrugged his shoulders.

“You do as you think best, Mr. Rover,” he said slowly.


“He can certainly have us arrested if we land without
permission. And the authorities have been pretty strict
lately—so many folks landing where they hadn’t any
business to.”

“But if Mrs. Stanhope is here?”

“He says there is nobody but his crowd on the island.”

“They may be in hiding,” suggested Tom.

“If they are, they’ll take good care to keep out of your
way—if such a thing is possible.”

“Let us leave!” put in Sam, in a low voice. “I’ve got a


plan that may bring results.”
“What?” demanded Dick. [239]

“I’ll tell you as soon as we are out of hearing,” returned


the youngest Rover.

The steam tug was backed away from the dock. Koswell
and Larkspur grinned in triumph.

“Don’t you think of coming back!” shouted Koswell.

“If you do, remember we are armed,” added Larkspur.

“We’ll remember what you have done—don’t forget


that,” answered Dick, with some bitterness. It worried
him greatly to have the search for Mrs. Stanhope
delayed.

“Now, what is your plan?” asked Tom of Sam, as soon


as they were a goodly distance from the island.

“I propose we sail away and pretend to be going back


to Portland. Then we can turn and come up on the
other side of the island.”

“They’ll watch for us,” said Dick.

“We might land at night.”

“Yes, we could do that. But if we wait, we may be losing


valuable time.”

“I’ll run for the next island and sail around that,” said
Captain Wells. “That may throw them off the scent.”

It took the best part of half an hour to gain the next [240]
island and round a convenient point. Here the tug was
stopped, that they might decide on their next move.
“Oh, come on, let’s do something!” cried Tom. “Let us
sail for the other side of that island and chance it! If
they come after us, we can easily steam away again.”

So it was decided, and rounding the island they were at,


they set a new course, so that they might reach
Chesoque Island at a point directly opposite to where
the dock was located. In the middle of the island were
several rocky hills, so that the view from one side to the
other was completely shut off.

“I’ll have to be careful here,” said Captain Wells, “I can’t


afford to strike on the rocks. Those chaps would let us
drown before they would come to our assistance.”

The steam tug came in slowly. It could not reach the


island proper, but stopped at the first of a series of
rocks.

“Let me have one of those pistols,” said Dick, to the


captain, and the weapon was handed over. Then Tom
and Sam also armed themselves.

“You had better stand off,” went on Dick to Captain


Wells. “If we want you we’ll fire three shots, or wave a
handkerchief.”

“Say, don’t you want me along?” asked Larry Dixon. “I’d [241]
like a scrap, if it comes to that.”

“Come along if you want to,” answered Dick. He saw


that though the sailor was old he was strong, and not
afraid to take his own part.

The boys and the tar lost no time in jumping from one
rock to another until the main portion of the island was
gained. Then they ran for the shelter of some bushes.
In the meantime the steam tug moved away to such a
distance that those aboard could be seen with difficulty.

“Now, if the others didn’t see us land, we are all right,”


cried Tom.

“We don’t want to make any noise,” cautioned Dick.


“Remember, they may be on the watch for us—Koswell
and his cronies, and the Sobber crowd too.”

“Do you think Koswell and Larkspur would give aid to


those other rascals?” asked Sam.

“I think they’d do almost anything to make trouble for


us, Sam. You can see how bitter they acted at the
dock.”

With caution the party of four began a tour of the


island. They moved from the shelter of the bushes to a
thicket of pines, and then climbed along a ridge of
rough rocks.

“I’ll crawl to the top,” said Dick. “Then I’ll have a pretty
good chance to look around.”

At the top of the ridge, however, he found the view [242]


somewhat disappointing. There were other ridges, and
several thickets of pines and hemlocks, and at one point
what looked to be a cliff with some caves beneath.

“It will take some time to explore this island,” said he,
as he came down. “I don’t wonder that the smugglers
used to use it. It’s got a number of dandy hiding
places.”

“How in the world did the Sobber crowd learn of it?”


asked Sam.
“I think I can answer that,” said Tom “Josiah Crabtree
once taught in a Portland school and he used to put in
his summers on an island in this bay. More than likely, in
cruising around, he heard of this island, and when he
plotted to abduct Mrs. Stanhope he made up his mind it
would be just the spot to bring her to.”

“All providing she is here,” added Sam. “We haven’t


proved that yet.”

They moved on, and passed another ridge of rocks.


Then they came to a well-defined trail, running from
one end of the island to the other.

“Let us follow this,” said Dick. “If there are any buildings
near the centre of the island they’ll likely be on this
road.”

“Here is a spring!” exclaimed Sam, a minute later. “Say, [243]


that water looks good. I am going to have a drink.”

All stopped to quench their thirst, for the day had been
warm in spite of the breeze that was blowing.

“Look!” cried Dick, as he pointed at the wet ground.


“Somebody has been here before us.”

“That’s so!” returned Tom. “Now, if we were only


Indians, we would know whose footprints those were
and would follow ’em.”

Dick and Sam got down to examine the footprints. The


majority of them were of good size, but a few were
small, the heel marks especially so.

“I believe those marks were made by a woman’s shoes!”


murmured Dick. “And if so——”
“They were made by Mrs. Stanhope!” finished Sam.
“Dick, I think we’ve struck the right trail!”

“This proves that what that young fellow of the motor


boat said was not true,” said Dick. “Other folks are on
this island.”

“Let us follow up the footmarks!” cried Larry Dixon.


“Come on, messmates, to the rescue!” And he waved a
stick he had picked up.

To follow up the footmarks was not easy, for they led


from the dirt to the path and then to some smooth
rocks. But they managed to get the general direction,
which was something.

“I wonder if it would do any good to set up a yell,” said [244]


Tom. “Maybe Mrs. Stanhope would hear it, and answer
it.”

“If she got the chance.” said Sam. “If she didn’t, all the
yelling would do would be to let our enemies know we
were here.”

“No, we had better go ahead as quietly as we can,” said


Dick. “If possible, we want to take them unawares.”

Much to their surprise, at the other side of the smooth


rocks was another path, running between a thick
growth of pines. Here the going was somewhat
uncertain, and they had to proceed slowly, for fear of
stepping into a crevice and twisting an ankle.

“If they brought Mrs. Stanhope this way, it must have


been very hard on her,” murmured Tom.
Welcome to our website – the perfect destination for book lovers and
knowledge seekers. We believe that every book holds a new world,
offering opportunities for learning, discovery, and personal growth.
That’s why we are dedicated to bringing you a diverse collection of
books, ranging from classic literature and specialized publications to
self-development guides and children's books.

More than just a book-buying platform, we strive to be a bridge


connecting you with timeless cultural and intellectual values. With an
elegant, user-friendly interface and a smart search system, you can
quickly find the books that best suit your interests. Additionally,
our special promotions and home delivery services help you save time
and fully enjoy the joy of reading.

Join us on a journey of knowledge exploration, passion nurturing, and


personal growth every day!

ebookbell.com

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy