Game Math: More on Numeric Springing

This post is part of my Game Math Series.

Source files are on GitHub

Previously, I talked about numeric springing and provided some examples.

I have been saving up miscellaneous topics I would like to discuss about numeric springing, and now I have enough to write another post. Here are the topics:

  • Using The Semi-Implicit Euler Method
  • Numeric Springing vs. Tweening
  • Half-Life Parameterization

Continue reading

Posted in Gamedev, Math, Physics | Leave a comment

Game Math: Numeric Springing Examples

This post is part of my Game Math Series.

Source files are on GitHub

So, you have seen how to precisely control numeric springing in my previous post.

I showed this animation as an example.

spring

Manually fine-tuning the animation with animation curves can possibly give better results, if it’s a fixed animation, that is.

One big advantage of numeric springing over animation curves is that it can be dynamic and interactive. For instance, when the springing simulation has not completely come to a stop, and you poke the system (modify the target value or velocity) based on user input, the system can handle it gracefully with numeric springing and everything looks natural. On the other hand, it’s usually hard to interrupt an animation using animation curves and have it animate to a new target value without making it look visually jarring.

I will show you several examples of numeric springing in this post.

Before that, let’s quickly review the spring function presented in my previous post.

/*
  x     - value             (input/output)
  v     - velocity          (input/output)
  xt    - target value      (input)
  zeta  - damping ratio     (input)
  omega - angular frequency (input)
  h     - time step         (input)
*/
void Spring
(
  float &x, float &v, float xt, 
  float zeta, float omega, float h
)
{
  const float f = 1.0f + 2.0f * h * zeta * omega;
  const float oo = omega * omega;
  const float hoo = h * oo;
  const float hhoo = h * hoo;
  const float detInv = 1.0f / (f + hhoo);
  const float detX = f * x + h * v + hhoo * xt;
  const float detV = v + hoo * (xt - x);
  x = detX * detInv;
  v = detV * detInv;
}

Continue reading

Posted in Gamedev, Math, Physics | 7 Comments

Game Math: Precise Control over Numeric Springing

This post is part of my Game Math Series.

Source files are on GitHub

Check out this post if you want to see more visual examples of numeric springing.

Numeric springing is a very powerful tool for procedural animation. You specify the initial value, initial velocity, target value, and some spring-related parameters; the result is a smooth springing effect. You can apply this technique to all sorts of numeric properties, some common ones being position, rotation, and scale of an object.

spring

Continue reading

Posted in C/C++, Gamedev, Math | 9 Comments

GDC Social Tips

This post is part of My Career Series.

I wrote some tips on meeting people at GDC a while ago. It was the GDC that lead me to my current job at Naughty Dog (more on this here). Recently, I got some friends asking me for advice on breaking into the game industry, how to present yourself, and how to meet people at GDC. So I decided to write another post about it. This will be a collection of what I learned from the Career Service Center and the career workshops at DigiPen, plus my own experience.

These tips worked for me, but they might not suit everyone. Feel free to disregard any of them at your discretion.

Email, Twitter, Domain Name

Before doing anything else, you should have a professional-looking email address. Don’t use random internet names like AwesomeDude7345; that makes your address look unprofessional. Make sure the only thing present in the name part of the address is your name. The email address I share with people is MingLun.Chou[at]gmail.com.

Applying the same rule to your Twitter handle and domain name can help them appear more professional as well. My Twitter handle is TheAllenChou, and my domain name is AllenChou.net. Of course, you can always throw in some variation if that helps express more about yourself, such as JasonGameDev.net or AmysArt.net.

LinkedIn

Get a LinkedIn account, period. LinkedIn is a professional social network where you can build online professional connections. You can join groups and follow companies on LinkedIn. Your profile page is the place to show people your professional side; maintain it well. Many recruiters actively look for potential hires on LinkedIn by going through his/her 1st, 2st, and 3rd degree connections. It is important that you build connections with people in the industry on LinkedIn. I constantly receive messages on LinkedIn from recruiters in the game industry and software engineering industry.

You can customize your LinkedIn profile page’s URL. Choose one that follows the aforementioned rule for your email address. My LinkedIn profile page URL is linkedin.com/in/MingLunChou.

Continue reading

Posted in Gamedev | 2 Comments

Safe Scope-Based Instrumented Profiler

This post is part of my Game Programming Series.

Let’s say we have an interface for an instrumented profiling library that looks like this:

namespace Profiler
{
  void BeginBlock(const char *name);
  void EndBlock(void);
};

The argument you pass to BeginBlock is a custom block name for you to identify the block in the profiler output.

You call BeginBlock at the beginning of a block of code and call EndBlock when the program exits the block.

void GameLoop(void)
{
  Profile::BeginBlock("GameLoop");
    UpdateInput();
    UpdatePhysics();
    UpdateLogic();
    Render();
  Profile::EndBlock();
}

Let’s say you also inserted the proper calls to the profiling functions inside the functions you wish to profile, then the profiler might give you an output like this:

GameLoop - 16.0ms // 60fps, woo~
  |--UpdateInput - 1.0ms
  |--UpdatePhysics - 10.0ms
  |    |--InitRigidBodies - 0.1ms
  |    |--SolveConstraints - 0.6ms
  |    |--IntegrateRigidBodies - 0.3ms
  |--UpdateLogic - 5.0ms

This all depends on the fact that you properly call the EndBlock function before the program exits a block of code. What if, say, someone decides to throw in an early-out inside one of your functions and forgets to call EndBlock?

Continue reading

Posted in C/C++, Gamedev | 2 Comments

到目前為止的Naughty Dog生活

本文屬於My Career系列文

Here is the original English post.
本文之英文原文在此

Continue reading

Posted in Gamedev | Leave a comment

My Life at Naughty Dog So Far

This post is part of My Career Series.

本文之中文翻譯在此

Disclaimer: Opinions expressed in this post are my own and does not represent Naughty Dog in any way.

Edit: Thank you for all your concern. I already ran this post through the PR people at Naughty Dog before posting. Rest assured. My NDA is not violated.

I started working at Naughty Dog a few months ago, and I decided to share about my life so far at Naughty Dog and some interesting tidbits about the company. It is a brain dump, so I will just present it as a list, in no particular order of importance:

Scooters

People at Naughty Dog use scooters a lot as a means of travel within the office. From my standpoint, designers and animators visit the programmer section on scooters to communicate with us quite frequently.

When you see a scooter parked outside the restroom, you know someone is in there.

The Signing Counter

The kitchen counter at the office is used as a signing counter. People put things on the counter to be signed, such as game cases, posters, art books, etc. Usually, these things are products of Naughty Dog, which makes sense. However, people sometimes put things on the counter to give them away, usually followed by a company-wide email informing everyone.

If a giveaway stays on the counter for too long, someone eventually will mistakenly sign on it, and more people will follow. There was an old DVD player left on the counter for a week, and people just started signing on it until it was covered by signatures. Then one day it just disappeared. Perhaps someone took it home because of the signatures, not because he or she needed a DVD player.

Basically, if you leave stuff on the kitchen counter for too long, no matter what it is, people will start signing on it.

Continue reading

Posted in Gamedev | 1 Comment

Scope-Based Resource Management (RAII)

This post is part of my Game Programming Series.

It has been 4 months since I graduated from DigiPen and started working at Naughty Dog as a Game Programmer. Since then, I have been too lazy to write anything big and technical on my blog, mostly because I just want to relax and play games after work. From now on, instead of dealing with topics that are wide and deep like game physics and game math, I’ll probably just write about quick and tiny tips, most likely related to game development.

I’m going to begin with the programming idiom RAII (Resource Acquisition Is Initilization). I like how some people on StackExchange refer to RAII as a more friendly name, Scope-Based Resource Management, so I will stick with this name.

Scope-Based Resource Management is a very common and important resource management technique where the resource is tied to an object’s lifetime. This is done by allocating the resource in a helper object’s constructor and releasing the resource in the helper object’s destructor.

The usefulness and importance of this technique can be best illustrated by an example.

Continue reading

Posted in C/C++, Design Patterns, Gamedev | Leave a comment

Game Math: Interpolating Quaternions with Circular Blending

This post is part of my Game Math Series.

While processing data for skeletal animations, we are usually faced with a series of discrete samples of positions and orientations. The positional samples are typically stored as a series of 3D vectors, and the orientational samples are typically stored as a series of quaternions. The most straightforward way to interpolate between positional samples is using piece-wise lerp (linear interpolation), and the counterpart for orientational samples is using piece-wise slerp (spherical linear interpolation). For more information on slerp, please see my previous post on quaternion basics.

The samples are sometimes too far apart, and we can see the visual artifact of discontinuous change in the first-order derivative of interpolation, i.e. the interpolation is not smooth at sample points.

In this post, I will present to you a technique for interpolating orientational samples in a smooth fashion called circular blending. I leaned about this technique from the MAT 351 class at DigiPen, taught by professor Matthew Klassen.

Let’s say we are given a series of quaternions:

    \[ q_0, q_1, q_2, ..., q_n \]

Let q_i and q_{i + 1} denote the two quaternions we are trying to interpolate between, and let t denote the interpolation parameter (0 \le t \le 1). Also, let r_i(t) denote the interpolating curve between q_i and q_{i + 1}.

If we are just using the straightforward slerp approach, we get:

    \[ r_i(t) = Slerp(q_i, q_{i + 1}, t) \]

This is a C^0 curve, meaning the curve is only continuous up to the zeroth-order derivative, i.e. the curve itself. The first-order derivative is generally not continuous at sample points using this approach.

Circular blending gives us a nice C^1 curve, which means the curve is continuous up to the first-order derivative. It is difficult to visualize quaternions, so I will use a 2D analogy to explain how circular blending works and how to mathematically work it out.

Continue reading

Posted in Gamedev, Math | 2 Comments

Game Math: Quaternion Implementations

This post is part of my Game Math Series.

I have covered the basics of quaternions. In this post, I will show some examples of quaternion implementations.

The Interface

We want our quaternion class to handle basic arithmetics (addition, subtraction, and scalar multiplciation), as well as various operations (normalization, re-normalization, inversion, dot product, projection, quaternion product, vector rotation, and slerp).

class Quat
{
  public:
    
    // this component layout is just conforming to my math 
    // notation: [w, v] = [w, (x, y, z)]
    // the common layout is (x, y, z, w)
    float w, x, y, z;

    // constructors
    Quat(void);
    Quat(float w, float x, float y, float z);
    Quat(const Vec3 &axis, float angle);

    // arithmetics
    Quat &operator+=(const Quat &rhs);
    const Quat operator+(const Quat &rhs) const;
    Quat &operator-=(const Quat &rhs);
    const Quat operator-(const Quat &rhs) const;
    Quat &operator*= (float rhs);
    const Quat operator*(float rhs);

    // operations
    Quat &Normalize(void);
    const Quat Normalized(void) const;
    Quat &Renormalize(void);
    const Quat Renormalized(void) const;
    Quat &Invert(void);
    const Quat Inverted(void) const;
    float Dot(const Quat &rhs) const;
    Quat &Project(const Quat &onto);
    const Quat Projected(const Quat &onto) const;
    const Quat operator *(const Quat &rhs) const;
    const Vec3 &operator *(const Vec3 &rhs) const;
};

const Quat operator*(float lhs, const Quat &rhs);
const Quat Slerp(const Quat &q0, const Quat &q1, float t);

Note that all methods and functions work under the assumption that all quaternions are unit quaternions.

Now let’s look at the actual implementations.

Continue reading

Posted in Gamedev, Math | Leave a comment