Reader small image

You're reading from  Game Physics Cookbook

Product typeBook
Published inMar 2017
Reading LevelIntermediate
PublisherPackt
ISBN-139781787123663
Edition1st Edition
Languages
Tools
Concepts
Right arrow
Author (1)
Gabor Szauer
Gabor Szauer
author image
Gabor Szauer

Gabor Szauer has been making games since 2010. He graduated from Full Sail University in 2010 with a bachelor's degree in game development. Gabor maintains an active Twitter presence, and maintains a programming-oriented game development blog. Gabor's previously published books are Game Physics Programming Cookbook and Lua Quick Start Guide, both published by Packt.
Read more about Gabor Szauer

Right arrow

Chapter 14. Constraint Solving

We have finally made it to the part of the book where we can stop talking about theory and actually implement some physics. By the end of this chapter you will have several particles bouncing around the screen colliding with obstacles. In order to achieve this, we will cover the following topics in this chapter:

  • Introduction to the Windowing Framework

  • Modifying Raycast against sphere

  • Modifying Raycast against Bounding Boxes

  • Modifying Raycast against plane and triangle

  • Basic Physics System

  • Integrating Particles

  • Solving Constraints

  • Verlet Integration

Introduction


In this chapter, we are going to start implementing actual physics. All of the physics related code will be provided within the chapter. A framework for creating windows and visualizing our Physics System is provided with the downloadable materials for this book. Things such as window management and graphics are outside the scope of this book. We will, however, dedicate a section of this chapter to exploring the framework provided so you can build new physics simulations without having to rewrite the visualization layer.

After we cover the framework provided with this book, we will start implementing our first physics simulation. In this chapter, we focus on particles, the laws of motion, and integrating the equations of motion. Particles are a logical starting point for physics as they have mass, but not volume. This will allow us to focus on integration without having to worry about things like rotation.

Framework introduction


We have arrived at a place in the book where things are about to start moving. A large part of writing a physics engine is making sure that the physics simulation looks accurate. We need a simple, intuitive way to visualize our Physics System.

In order to visualize the movement of our physics code, we need to manage windowing and rendering. An application framework that handles windowing and rendering is provided with the downloadable code for this chapter. In this section, we will explore the framework that will be used to create windows and visualize our physics simulation.

Getting ready

In this section, we are going to explore the framework provided with this chapter. We will explore which files contain what code, how physics demos are hooked up to the framework, and what to do to add a new demo.

How to do it…

Follow these steps to explore the framework provided with the download code of this book:

  1. Navigate to the source directory of this chapter and open the included...

Raycast sphere


In order to solve collisions against constraints, we will need to determine some extra information about rays being cast into the world. In our current implementation, each raycast returns a floating point t-value. From this value we can infer if the ray hit anything and if it did at what point the intersection happened. We still need this t-value, but we also need to know the normal of the surface that the ray hit.

Getting ready

In this section, we will start modifying the Raycast function to return more data. To achieve this, we first declare a new RaycastResult data structure. We will also implement a helper method to reset the new RaycastResult data structure.

How to do it…

Follow these steps to update the RaycastSphere function in a way that it returns more useful data:

  1. Declare the RaycastResult structure and ResetRaycastResult function in Geometry3D.h:

    typedef struct RaycastResult {
        vec3 point;
        vec3 normal;
        float t;
        bool hit;
    } RaycastResult;
    void ResetRaycastResult...

Raycast Bounding Box


Any box in 3D space, OBB, or AABB has six sides. This means the normal of a Raycast against a box will be the normal of one of the six sides. When doing a Raycast against a Bounding Box, we find the point of impact the same way we did for a Raycast against a Sphere. The normal, however, will be the same as the normal of the side which the ray hit.

Getting ready

Several of our existing functions use Raycast against AABB or OBB internally. When we change the API, we must be careful to update every spot where these functions are used. We must update the Linetest functions and the MeshRay function. In this section we are going to rewrite the Raycast function for AABB and OBB.

How to do it…

Follow these steps to update the Raycast functions of boxes in a way that they provide additional useful data:

  1. Update the declarations of Raycast against both OBB and AABB in Geometry3D.h:

    bool Raycast(const AABB& aabb, const Ray& ray, 
       RaycastResult* outResult);
    bool Raycast(const...

Raycast plane and triangle


We have two planar primitives in our geometry toolbox, the Plane and the Triangle. The collision normal for both primitives is the same as the normal of the primitive itself. We must keep in mind that if a ray hits a plane or triangle from behind, that is not actually a hit. This is not a bug, it's how raycasting against these primitives should work. The "forward" direction of a triangle is determined by counter clockwise winding.

Getting ready

When we modify the Raycast API for a plane or a triangle we break all the functions that internally use the old declaration. We must take care to update these broken functions as well. We will need to update the Linetest against triangle function and the MeshRay function.

How to do it…

Follow these steps to update the Raycast function for both triangles and planes so that the functions return more useful data:

  1. Change the declaration of Raycast against both the Plane and Triangle in Geometry3D.h:

    bool Raycast(const Plane& plane...

Physics system


It is finally time to start implementing a basic Physics Engine. By the end of this chapter we will have particles flying around the screen in a physically realistic way. Before we start implementing our physics simulation, let's take a minute to discuss what we will be simulating, the rigidbody.

A rigidbody is an object that does not change its shape, the object is rigid. Think about dropping a ball filled with air on the ground. At the point of impact the ball would squash, and then it would stretch as it bounces back up. This ball is not rigid; it changes shape (but not volume), which allows it to bounce. Now imagine a ball of solid steel being dropped. It would not change in shape or volume, but it would not bounce either.

Our object can bounce around because we can model the math behind what it would be like if they bounced, but really they will be rigid. Our simulated objects will never change shape as a result of a physical reaction.

A scene can have hundreds of thousands...

Integrating particles


Particles are a great place to start any physics engine. This is because particles have mass, but not volume. The lack of volume means we don't have to concern ourselves with rotation. In this section, we will create particles and move them using Euler Integration.

Integration is a way to guess where an object will be in some amount of time. In order to guess the new position of an object, we need to know its position, velocity, and all of the forces acting on the object. We first need to integrate acceleration with respect to time; this will yield the velocity of the object. We next integrate velocity with respect to time; this will yield the updated position of the object. The preceding integrations come right from Newton's Laws of Motion:

  • An objects velocity will not change unless affected by an external force

  • The acceleration of an object is proportional to the magnitude of the force acting on the object, and inversely proportional to the mass of the object

  • Every action...

Solving constraints


In the last section, Integrating Particles, we made our particle class move using Euler Integration. The only force affecting particles was gravity. This means if you were to run the simulation, every particle would fall down without interacting with anything. In this section, we will introduce several unmovable constraints to the world. By the end of the section, particles will bounce around the screen as they hit constraints while falling under the force of gravity.

Our PhysicsSystem currently only supports OBB constraints; however, adding additional constraint types is a trivial task. We will use raycasting to find collision features between a constraint and a particle. Because we modified the raycast for all primitives to return the same data, implementing new constraint types will use very similar code.

Solving constraints is based on Newton's third law of motion:

Every action has an equal and opposite reaction

In this section, we will explore what to do when a particle...

Verlet Integration


Earlier in this chapter, we discussed how and why Euler Integration becomes less stable over time. We provided a better way to integrate position, Velocity Verlet Integration. While better than Euler Integration, the new method provided can become unstable too. In this section, we will discuss in detail implementing a more stable integration method: Verlet Integration.

Getting ready

In order to move particles using Verlet Integration, we need to re-implement both the Update and SolveConstraints methods of the Particle class. We need to re-implement these functions in a way that finds the velocity of a particle using the previous and current positions of the particle.

How to do it…

Follow these steps to replace the Euler Integration of the Particle class with Verlet Integration:

  1. Remove the velocity variable from the definition of the Particle class in Particle.h.

  2. Re-implement the Update method of the Particle class in Particle.cpp. This new implementation will perform Verlet...

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Game Physics Cookbook
Published in: Mar 2017Publisher: PacktISBN-13: 9781787123663
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Gabor Szauer

Gabor Szauer has been making games since 2010. He graduated from Full Sail University in 2010 with a bachelor's degree in game development. Gabor maintains an active Twitter presence, and maintains a programming-oriented game development blog. Gabor's previously published books are Game Physics Programming Cookbook and Lua Quick Start Guide, both published by Packt.
Read more about Gabor Szauer