INF633 - Advanced 3D Graphics (2023 - 2024)

INF633 - Advanced 3D Graphics (2023-2024) - Lab Course

INF633 - Advanced 3D Graphics (2023 - 2024)


Github Repository Github Page Moodle


First Steps

Introduction

Welcome to the official page for the lab sessions of INF633 for the course 2023-2024!

The goal of this project is to create, starting from a flat empty terrain, one with interesting features, objects and dynamic, living creatures all interacting together. For this, multiple edition tools will be created and basic principles of animation and crowd simulation used to give life to the virtual world.

In this page, you will find the same introduction to install and setup Unity that you can find also in the README.md of the repository at https://github.com/Paul-Hubert/inf633-2023-2024, and also the description and content for each lab session.

Installing Unity

Link to download: https://unity.com/download

First Setup in Unity

Before even importing the lab project, let’s have a general overview of Unity. First, we first need to associate Unity with our chosen C# editor.

Unity Interface and Controls

Unity uses a modular window system. That means, that each part of the interface can be reorganized and placed as you like. By default, Unity will show a similar appearance to this one:

Image

3D Controls

In the Scene view:

Interface and Interaction

Some fast tips regarding the overall workflow in Unity:


Starting our project

Opening the project

Running the scene


SESSION 01 - Terrain edition

Getting started

In this session, you will be designing and implementing brushes, allowing you to dynamically edit the terrain. Your brushes will extend the base class TerrainBrush and control terrain modifications in a restricted area around the mouse, by implementing the method draw.

The base code for this session can be found in the following file, and shows how to set all cells in the current region to a defined height.

public class SimpleBrush : TerrainBrush {

    public float height = 5;

    public override void draw(int x, int z) {
        for (int zi = -radius; zi <= radius; zi++) {
            for (int xi = -radius; xi <= radius; xi++) {
                terrain.set(x + xi, z + zi, height);
            }
        }
    }

Code Snippet 1: "Scripts/01Terrain Brushes/SimpleBrush.cs"

Copy this file to use it as a base for your own brushes, by changing the name of the copied file and class name.

Brush ideas

Examples

       

       

Useful functions and variables

// Get or set the height of the terrain at (x, z)
  float terrain.get(int x, int z);
  void terrain.set(int x, int z, float height);
  // Get the terrain normal at (x, z)
  Vector3 terrain.getNormal(float x, float z);

  // Get the terrain size
  Vector3 terrain.gridSize();

  // Reset the whole terrain to height=0
  void terrain.reset();

  // Print to the Unity console (next to game tab)
  print("message");
  // Print to game viewport (top left)
  terrain.debug.text = "message";

Code Snippet 2: Useful functions

  // Access the underlying terrain
  CustomTerrain terrain;

  // Radius of the brush
  int radius;
  int terrain.brush_radius;

Code Snippet 3: Useful variables

SESSION 02 - Object Placement

Getting started

In this second session, you will design brushes that place objects on the terrain. Here it will be trees, but you can search for or provide other objects.

The base code for this session shows how to instantiate one object where the user clicked, and four at the corners of the drawing region. Note that these types of brushes extend the InstanceBrush class instead of the TerrainBrush one used in the previous session.

public class SimpleInstanceBrush : InstanceBrush {

    public override void draw(float x, float z) {
        spawnObject(x, z);
        spawnObject(x - radius, z - radius);
        spawnObject(x - radius, z + radius);
        spawnObject(x + radius, z - radius);
        spawnObject(x + radius, z + radius);
    }
}

Code Snippet 4: "Scripts/02\_Instance Brushes/SimpleInstanceBrush.cs"

Like in the previous session, you can use this file as a base for your own brushes by copying it and changing the file and class names.

You can set the object that will be instantiated by drag-and-dropping a model in the Object_prefab parameter of the terrain at run-time. A few models of trees are already in the project, in 04 - Terrain Assets > Environment > Trees and then the file with a tree icon in one of the three sub-folders.

To remove objects, you can use the default tools provided in the original terrain editor by Unity. For this, select the terrain and go to the terrain > Paint trees tab (in the inspector). You can then shift-click on the terrain to remove objects around your cursor. Note that this works outside of play mode in the Scene view (not in the Game view!), as opposed to the brushes you implement.

Brush ideas

Object ideas

Useful functions and variables

  // Spawns an object at coordinates (x, z)
  void spawnObject(float x, float z);

  // Returns the interpolated height of the terrain
  float terrain.getInterp(float x, float z);
  // Returns the steepness of the terrain
  float terrain.getSteepness(float x, float z);

  // Return the number of objects instantiated
  int terrain.getObjectCount();
  // Return the location of an object
  Vector3 terrain.getObjectLoc(int index);
  // ADVANCED - Return an instantiated object
  // See Unity manual of TreeInstance for more details
  TreeInstance terrain.getObject(int index);

Code Snippet 5: Useful functions

  // Object to instantiate by default
  GameObject terrain.object_prefab;
  // Min and max size of the instantiated objects
  float terrain.min_scale;
  float terrain.max_scale;

Code Snippet 6: Useful variables

SESSION 03 - Character Animation

Getting started

In this session, you will learn about some important concepts such as Inverse Kinematics, and learn about how to use this technique in order to fully animate one character using procedural methods.

Many animation techniques exist: Virtual characters are often animated using direct kinematics - animation clips, described by keyframes for each bone of character, that are normally played in a state machine among other clips. However, other many methods exist. Inverse Kinematics are often used to animate limbs in the other way around: Given a particular condition, IK calcutates the position and rotation of the limbs to satisfy such requirement. It is used very often as a second-layer for direct kinematic animations, for example, to place the feet of the characters correctly to the irregular ground, or to move the arm when the character takes a mug from a table.

However, you can use IK to animate whole characters as well. Procedural animations define an equation or any other parametrized system which must be followed by the animation, instead of following individual keyframes in the kinematic clips. A ball that falls due to gravity, is just another procedural animation - in this case, the ball follows a physics equation. This techniques are normally denominated as physically-based animations.

In this session, we will learn to convert this…

…to this…

All the necessary files will be in the folder 03 - Character Animation. Let’s start!

Fast IK Demonstration

First, let’s go to 03 - Character Animation > 00 - IK Demonstration. In the scene, you will learn how to build a simple Fast IK algorithm. The script FabricIK.cs contains several code snippets that you will need to complete. All the information that you need to understand the code is already included as comments along the script.

This IK technique is called Fabric IK. A forward and backward pass are used to place an end-effector on a target, while a pole is used to define one of the multiple solutions that one target may contain.

       

Quadruped with full IK

Now, we can use this knowledge to animate our quadruped:

In the hierarchy, you will find the character in Controllable Characters > Quadruped - (Procedural). It contains the hierarchy of bones, with root at Hips and the family of objects to apply IK inside IK.

All the necessary files are in 03 - Character Animation > 01 - Quadruped with full IK.

At the beginning, moving the goal will make the character to follow it without any animation, floating around and going inside the terrain when it gets higher. Your task is to make this character fully responsive when moving the goal. Again, these scripts contain code snippets that you will need to complete. All the information that you need to understand the code is already included as comments along the scripts.

Once you have it, think about particular applications. Characters that follow autonomously a piece of food, or animals that run away from “anti-goals” such as predators. Could we even use some learning-based approach to teach them to follow certain assets? There are many options! We will see more in the next session.

Bonus: Controllable character with FK and IK

If you have time, you can try to set a character controllable by Forward Kinematics, and using IK just to adapt its feet on the ground. This character is already included in the hierarchy, Controllable Characters > Human - (Controller + IK). In the Game window, you can change the display to Display 2 to set a third-person view. You can control the humanoid using the keyboard arrows or WASD keys.

Inside 03 - Character Animation > 02 - Biped Controller with IK you will find the script PlayerControllerIKFeetPlacementTask.cs. All the information about this task can be found in the repo in a separated document, under the Docs folder.

SESSION 04 - Crowds and Evolution

Getting started

During this session, you will be given a basic setup containing simple creatures with eyes, a brain, and steering capabilities, as well as a primitive evolution method. With these, the creatures are able to gradually develop from generation to generation in order to learn how to efficiently reach their food. Your goal is to change parts of this base to extend it to your liking. Ideas of such extensions will be given below.

In order to activate the module of this session, select the terrain and activate the checkbox next to the Genetic Algo component. When you launch the project, you should see capsules (representing animals) appearing and moving on the terrain. Their color changes from white to black as their hunger increases, and they die after some time if they do not manage to reach food in time. After letting the simulation run for a few generations, you should see the animal counter drastically increase, when some animals become smart enough to efficiently get their food.

Animals

The animals created in this session are basic creatures, made of three main components:

Evolution

A genetic algorithm is used to teach the animals how to steer towards their food, after multiple generations. This works by allowing the animals that reach food to reproduce, thus spreading their genes (parameters of their brain), with minor random modifications to allow evolution. The animals with inefficient genes are unable to reach food before dying, thus encouraging only the spread and evolution of successful animals. This is implemented in the file 04 - Crowds and Evolution/GeneticAlgo.cs .

Resources

The animals simulated here are designed to be herbivores, that eat by passing over a source of food. Grass grows randomly over the terrain, creating a competition between the different animals to access the resources.

Meta Extensions

Medium Extensions

Complex Extensions

Useful functions

  // Update the genetic algo simulation
  void GeneticAlgo.step();
  void GeneticAlgo.updateResources();

  // Animal main update function
  void Animal.Update();
  // Animal receptors computations
  void Animal.updateVision();

  // Brain class of the animals
  class NeuralNet;
  // Mutate a brain to simulate evolution
  void NeuralNet.mutate(...);

Code Snippet 7: Useful functions

The senior students of this course did some great projects. You can find videos of some of them at this link. May they inspire you!

Besides, other intersting links that can be useful: