Efficient Simulation of Fluid Dynamics in a 3D Game Engine

Transcription

Efficient Simulation of Fluid Dynamics in a 3D Game Engine
Efficient Simulation of Fluid
Dynamics in a 3D Game Engine
ROBERT
BONGART
Master of Science Thesis
Stockholm, Sweden 2007
Efficient Simulation of Fluid
Dynamics in a 3D Game Engine
ROBERT
BONGART
Master’s Thesis in Computer Science (20 credits)
at the School of Engineering and Business Management
Royal Institute of Technology year 2007
Supervisor at CSC was Olle Bälter
Examiner was Lars Kjelldahl
TRITA-CSC-E 2007:018
ISRN-KTH/CSC/E--07/018--SE
ISSN-1653-5715
Royal Institute of Technology
School of Computer Science and Communication
KTH CSC
SE-100 44 Stockholm, Sweden
URL: www.csc.kth.se
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Efficient Simulation of Fluid Dynamics in a 3D Game Engine
Abstract
This thesis deals with the efficient simulation of Computational Fluid Dynamics (CFD) into a realtime 3D graphics engine by discussing the development of the C’Nedra virtual reality game engine
project carried out at Ecole Centrale Paris. The thesis tries to somewhat bridge the gap of
theoretical papers of CFD algorithms by implementing Jos Stam’s stable method for fluid effects in
3D with the C’Nedra plug-in framework and simulates fire and smoke. I find that my CFD
implementation in the C’Nedra game engine gives decent results in terms of realism however
mediocre results in terms of performance. Hence, I conclude that the engine is in many ways not
mature for the implementation of CFD.
Effektiv simulering av flödesdynamik i en 3D spelmotor
Sammanfattning
Examensarbetet behandlar effektiv simulering av datorbehandlad flödesdynamik i en 3D
grafikmotor genom att diskutera utvecklingen av spelmotorn C’Nedra på Ecole Centrale Paris.
Uppsatsen försker genombrygga klyftan mellan teoritiska uppsatser om datorbehandlad
flödesdynamik genom att implementera Jos Stam’s stabila algorithm för flödes dynamik i 3D med
hjälp av C’Nedra plug-in klasser och simulera eld och rök. Jag finner att min implementaion av
datorbehandlad flödes-dynamik i C’Nedra ger godkända resutlat i termer av realism, men dåliga
resutlat i termer av effektivitet. Jag drar därför slutsatsen att C’Nedra inte är en mogen plattform för
att implementera flödesdynamik.
Simulation efficace de mécaniques fluides dans un moteur de jeux 3D
Résumé
Cette thèse traite l'exécution et simulation efficace de la mécanique de fluides dans le moteur en
temps réel des graphiques 3D en discutant le développement du projet virtuel de moteur de jeu de
C'Nedra mis à exécution à Ecole Centrale Paris. Je constate que le moteur de jeu C'Nedra est de
beaucoup de manière pas suffisamment robuste pour l’utilisation de mécaniques de fluides. Je mis
en forme la méthode stable de Jos Stam pour les mécaniques de fluides en 3D avec le système de
plug-in en C’Nedra et simule la dissipation de gaz et feu. Je trouve que m’implémentation de
simulation de mécanique de fluides numerique en C’Nedra donne de résultats suffisantes en termes
de réalisme, mais mauvais en termes de efficacité. Alors, je fais la conclusion que C’Nedra n’est pas
un logiciel bien construit pour implémenter les mécaniques de fluides.
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Acknowledgement
I would like to dedicate this thesis to my beloved family: my late mother Urszula and my dear father
Krzysztof. They have supported me, not only during the writing of this thesis, but also through my
entire educational path in life. Without their inspirational and loving support, I would not have
accomplished any of it.
Secondly, I would like to thank my advisors Olle Bälter at The Royal Institute of Technology and
Patric Callet at Ecole Centrale Paris for their support and guidance. I would also like to thank
Sébastien Candel for his excellent course in Fluid Dynamics at Ecole Centrale Paris.
Third, I want to thank my fellow students Francois Foucart, Patrice Laidet and Fabrice Larcher who all
contributed to the project at ECP as well the VIA Centrale Réseaux association.
Finally, I would like to thank my girlfriend Karin in Stockholm who stood up with me the last
months during the writing of this thesis.
I want to dedicate this thesis to my mother who always wanted me to be successful and who
introduced me to computers in general. Below is a poem about life in memory of her:
Life is but a stopping place,
A pause in what's to be,
A resting place along the road,
to sweet eternity.
We all have different journeys,
Different paths along the way,
We all were meant to learn some things,
but never meant to stay...
Our destination is a place,
Far greater than we know.
For some the journey's quicker,
For some the journey's slow.
And when the journey finally ends,
We'll claim a great reward,
And find an everlasting peace.
Table of Contents
1 Introduction........................................................................................................................................... 1
1.1
General Introduction................................................................................................................................... 1
1.2
Background and Purpose............................................................................................................................ 2
1.3
Work Performed .......................................................................................................................................... 2
1.4
Problem statement....................................................................................................................................... 2
1.5
Outline........................................................................................................................................................... 3
1.6
Target Audience ........................................................................................................................................... 3
1.7
Delimitations ................................................................................................................................................ 3
2 Game Engines.......................................................................................................................................4
2.1
What is a Game Engine?............................................................................................................................. 4
2.2
Background of Game Engines................................................................................................................... 4
2.3
Game Engine Functionality and Design................................................................................................... 5
3 C’Nedra Game Engine..........................................................................................................................6
3.1
Background................................................................................................................................................... 6
3.2
History and Evolution................................................................................................................................. 6
3.3
Functionality and Design ............................................................................................................................ 6
3.4
Kernel ............................................................................................................................................................ 7
3.5
C’Nedra Plug-ins.......................................................................................................................................... 8
3.6
Graphics Engine (3D plug-in).................................................................................................................... 8
3.6.1 Scene Management ............................................................................................................................................ 9
3.6.2 Rendering pipeline ........................................................................................................................................... 10
3.6.3 Lighting.......................................................................................................................................................... 11
3.6.4 Texturing ....................................................................................................................................................... 12
3.6.5 Shadowing ...................................................................................................................................................... 14
3.6.6 Shaders........................................................................................................................................................... 14
3.7
Physics Engine (World plug-in) ............................................................................................................... 14
3.7.1 Mesh Loading................................................................................................................................................. 14
3.8
Terrain Engine (Terrain plug-in).............................................................................................................. 17
3.8.1 Height Field Approach ................................................................................................................................... 17
3.8.2 Importing Pre-Generated Terrain Meshes......................................................................................................... 17
3.8.3 Artificial Terrain Generation .......................................................................................................................... 17
3.9
Artificial Intelligence Engine (AI plug-in) .............................................................................................. 18
3.10
Multimedia Engine (Sound plug-in) ........................................................................................................ 20
3.11
Interface management (Interface plug-in) .............................................................................................. 20
3.12
Scripting (xml plug-in)............................................................................................................................... 20
3.13
User Driven Data....................................................................................................................................... 20
3.14
Editors ......................................................................................................................................................... 21
3.15
Special Effects (special-effects plug-in)................................................................................................... 21
3.16
Summary of Features implemented in C’Nedra during thesis work ................................................... 22
4 Theory of Fluid Substances ................................................................................................................ 23
4.1
Definition of Fluid Substances................................................................................................................. 23
4.2
Perception of Fluid Substances................................................................................................................ 23
4.3
Simulation Approaches for Fluids ........................................................................................................... 24
4.4
Choice of Method for Simulation............................................................................................................ 24
4.5
The Navier-Stokes Equations .................................................................................................................. 24
4.5.1 External Forces .............................................................................................................................................. 25
4.5.2 Advection ....................................................................................................................................................... 25
4.5.3 Diffusion ........................................................................................................................................................ 25
4.5.4 Pressure .......................................................................................................................................................... 26
4.5.5 Incompressibility.............................................................................................................................................. 26
5 Previous research ................................................................................................................................ 28
5.1
Particle systems and Noise ....................................................................................................................... 28
5.2
CFD approaches ........................................................................................................................................ 28
5.3
Large Scale Fluid Motion .......................................................................................................................... 30
5.4
Summary ..................................................................................................................................................... 30
6 Methodology ....................................................................................................................................... 31
6.1
Outline of Methodology ........................................................................................................................... 31
6.2
Solving the Navier-Stokes Equations...................................................................................................... 31
6.2.1 Helmholtz-Hodge Decomposition..................................................................................................................... 31
6.2.2 Advection ....................................................................................................................................................... 33
6.2.3 Viscous Diffusion ........................................................................................................................................... 33
6.2.4 Initial and Boundary Conditions ..................................................................................................................... 34
6.3
Implementation .......................................................................................................................................... 35
6.3.1 Discretization ................................................................................................................................................. 35
6.3.2 Solver Implementation ..................................................................................................................................... 37
6.3.3 Texture implementation................................................................................................................................... 37
6.4
Scenario testing........................................................................................................................................... 37
6.4.1 Equipment ..................................................................................................................................................... 37
7 Results ................................................................................................................................................. 38
7.1 Test Criteria....................................................................................................................................................... 38
7.2 Test Scenarios ................................................................................................................................................... 38
7.2.1 Test 1: Advection of the Velocity Field ............................................................................................................ 38
7.2.2 Test 2: Advection of the Density Field ............................................................................................................. 40
7.2.3 Test 3: Thermal Buoyancy............................................................................................................................... 41
7.2.6 Test 6: Boundaries .......................................................................................................................................... 47
7.2.7 Test 7: Exploding Object ................................................................................................................................ 49
7.2.8 Test 8: Time & Gridsize................................................................................................................................ 50
7.2.9 Test 9: Number of Iterations in the Pressure Solver.......................................................................................... 51
7.2.10 Test 10: Time and Stability .......................................................................................................................... 52
7.2.11 Test 11: Texture Precision ............................................................................................................................ 52
7.2.12 Test 12: Multiple Instances ........................................................................................................................... 53
7.3 Summary of Results ......................................................................................................................................... 57
8 Conclusions ......................................................................................................................................... 58
8.1 Possible improvements in C’Nedra ............................................................................................................... 58
8.2 Possible improvement of fluid dynamics in C’Nedra ................................................................................. 59
9 Critique................................................................................................................................................ 60
9.1 Problems Experienced..................................................................................................................................... 60
9.2 Field Developing Fast...................................................................................................................................... 60
10 Literature ........................................................................................................................................... 61
10.1 CFD literature................................................................................................................................................. 61
10.2 Textbooks ....................................................................................................................................................... 62
10.3 Internet sources.............................................................................................................................................. 62
Appendix 1: Notation............................................................................................................................. 64
Vectors and Vector Fields ........................................................................................................................................ 64
The Gradient Operator............................................................................................................................................. 64
Appendix 2: C’Nedra XML file.............................................................................................................. 66
Appendix 3: CFD Solver Code............................................................................................................... 67
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Table of Figures
Figure 1: The pictures are taken from the movie Shrek and display simulations of fluid.
Figure 2: A simplified model of the game engine building blocks.
Figure 3: A schema displaying the various parts in the C’Nedra virtual reality toolkit.
Figure 4: A simplified model of a real-time air-traffic control system.
Figure 5: Plug-in class structure.
Figure 6: Scene graph holding a sphere build up by triangles defined by vertices.
Figure 7: Uniform grids, BSP Trees and Octrees.
Figure 8: A simplified model of the rendering process.
Figure 9: Lighting equation.
Figure 10: The three fundamental components of lighting in 3D graphics engines: diffuse, ambient, and
specular.
Figure 11: The image displays texturing implemented in C’Nedra.
Figure 12: Per-vertex and per-pixel normals.
Figure 13: Pictures showing a model created with a 3D scanner at the ECP research facility.
Figure 14: Skeletal Animation.
Figure 15: Oriented bounded box decomposition in C’Nedra.
Figure 16: Collision with the tank that rolls over with the help of the laws of physics.
Figure 17: Height field terrain engine implementation.
Figure 18: Height field terrain engine implementation visualized in C’Nedra.
Figure 19: Pictures showing simulations created in C’Nedra virtual reality toolkit with a simple xml file.
Figure 20: Pictures showing the new editor implemented to help designers creating worlds by not writing
XML directly.
Figure 21: Special effects implemented into C’Nedra.
Figure 22: Summary of generic game engine features.
Figure 23: Summary of fluid effects.
Figure 24: Steps followed in implementing fluids in 3D graphics.
Figure 25: Newton’s second law of motion.
Figure 26: Navier-Stokes equations.
Figure 27: Helmholtz-Hodge Decomposition Theorem.
Figure 28: The simulation algorithm.
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Figure 29: Euler’s method.
Figure 30: Stam’s method.
Figure 31: Discretization of the simulation volume.
Figure 32: Hot smoke rising with all steps in the algorithm enabled.
Figure 33: Hot smoke rising with all steps in the algorithm enabled.
Figure 34: Hot smoke rising with all steps in the algorithm enabled.
Figure 35: Cold smoke falling and ring up the sides of the simulation box.
Figure 36: Smoke rising with Vorticity Confinement Disabled.
Figure 37: Smoke rising with Vorticity Confinement Enabled.
Figure 38: Red hot smoke rising.
Figure 39: Red smoke with object boundary.
Figure 40: Single burning object.
Figure 41: Exploding object.
Figure 42: Showing how frame rate changes with grid size.
Figure 43: Displays how frame rate changes with the number of iterations.
Figure 44: Showing how the frame rate changes with time steps.
Figure 45: Frame rate as a function of texture precision.
Figure 46: Simultaneously burning fires.
Figure 47: Simultaneously igniting and burning objects.
Figure 48: Simultaneous black hot smoke rising.
Figure 49: A summary of possible improvements in C’Nedra.
Figure 50: A summary of possible improvements to C’Nedra pertaining to fluid dynamics.
Figure 51: A summary of open source graphics engines.
Figure 52: A summary of commercial source graphics engines.
Figure 53: A summary of open source graphics engines.
Figure 54: A summary of 3D modelling software.
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
1 Introduction
Chapter 1 is the introductory chapter giving a general introduction to 3D graphics and the Computational
Fluid Dynamics field. This is followed by a presentation of the background, purpose and problem statement
of this thesis. A detailed outline is also presented as well as the target audience introduced.
As we have entered the 3rd millennia, it is clear that computer and communications technologies
have become a dominant force in people’s lives. Activities as wide-ranging as filmmaking,
publishing, banking and education continue to undergo revolutionary changes as these technologies
alter how we conduct our daily activities. 3D graphics in particular have during the last 10-15 years
become an increasingly essential part of the engineering and entertainment community, and as
computers have become more and more powerful, so has the exigency for realism increased.
Figure 1: The pictures are taken from the movie Shrek and display simulations of fluid
In order to tackle this demand for higher performance, we are to a greater extent turning to the
natural laws of physics. One of the most difficult areas pertaining to implementing physics into
computer graphics is called Computational Fluid Dynamics (CFD) and refers to the creation of realistic
fluids often in 3D environments. This field involves methods for solving mathematical equations
modelling real world behavior such as for example the Navier-Stokes Equations. This thesis aims at
shedding some light on the implementation of such modelling methods into real-time 3D graphics
engines. An example of this is the answer to the question by Jeffrey Katzenberg, the director at
DreamWorks SKG, of which scene was the most difficult to produce in Shrek stated in Enright et
al. (2003):
“It’s the pouring of milk into a glass…”
1.1 General Introduction
The implementation of theoretical algorithms in the CFD area is not always straight forward,
especially when it comes to the specific needs of game engines. In these graphics systems there is a
myriad of components interacting and one has to try various approaches, often ad-hoc and
experimental, in order to get a satisfactory result. Many papers give theoretical advice about these
various algorithms, however they do not give the reader any practical help about how it actually is
to implement these into real game engines. Therefore this thesis tries to somewhat bridge this gap
by implementing such an algorithms and testing its efficiency in terms of execution performance.
1
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
1.2 Background and Purpose
The purpose of the Master Thesis project was to develop a real time graphics engine supporting the
academic needs of Ecole Centrale Paris (ECP) and was later extended into implementing CFD into
this system. ECP aimed at using the application in order for students to simulate various physical
phenomena as part of their curricula. Most of the work for this Master Thesis was carried out at the
ECP research facility for Applied Mathematics on Systems (Laboratoire de Mathématiques Appliquées
aux Systèmes) (www.mas.ecp.fr/) in conjunction with the C’Nedra Open Source Virtual Reality
Framework (www.cnedra.org/) and the VIA Centrale Reseaux association at ECP
(www.via.ecp.fr/via/). Other stake holders that attended the presentation in Paris were the French
Ministry of Education. The purpose of the project was initially to create a game engine from
scratch and was later evolved into implementing CFD techniques into this specific graphics engine.
The reason for not using an existing and established system such as Ogre (ogre3d.org) or Torque
(www.garagegames.com) was that the school wanted to possess its own platform. This decision was
to a high degree based on the success that the school has had with VideoLan (www.videolan.org)
and VLC player which has allowed for the creation of the company Anevia (www.anevia.com).
1.3 Work Performed
ƒ
A comprehensive literature study was conducted throughout the whole project.
ƒ
The game engine kernel was further developed in order to allow xml scripting language to
define objects.
ƒ
The C’Nedra Plug-ins were further developed to properly support sound, network, interface,
physics and better 3D capabilities.
ƒ
A collision detection system was created and implemented partially based on the Tokamak
physics engine.
ƒ
3D models were created both by using 3D Max Studio 5.0 and Maya 6.0 and a 3D scanner in
the research facility and implemented into scenarios.
ƒ
A webpage for the 3D scanner was conceived (catia.etudes.ecp.fr/optocat/index.html).
ƒ
Website for the project was launched (www.cnedra.org).
ƒ
A report in French pertaining to the needs of ECP was composed and the project was
presented to the school as well as the French Ministry of Education.
ƒ
Fluid dynamics based on the Stam Navier-Stokes solver were implemented into fire and gas
simulations and tested.
ƒ
This report in English pertaining to the KTH requirements was composed and presented.
1.4 Problem statement
With the introduction and the background of the work carried out in mind, I formulate my main
research question representing the main theme of this thesis:
Can realistic fluid dynamics be run efficiently in the C’Nedra game engine?
2
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
1.5 Outline
ƒ
Chapter 1 introduces the rationale behind this thesis and discusses the implementation of
fluid dynamics into 3D game engines. The chapter lays out the problem statement of the
thesis and discusses the target audience as well as its delimitations.
ƒ
Chapter 2 discusses 3D game engines in more detail by going through the background of
game engines and their functionality.
ƒ
Chapter 3 goes through the C’Nedra game engine step by step. The chapter gives the
background to the specific game engine used, the history and evolution as well as a
thorough outline of its functionality.
ƒ
Chapter 4 lays down the theory of fluids. The chapter defines fluids and examines various
approaches to simulating them. The chapter explains the framework for the Navier-Stokes
Equations.
ƒ
Chapter 5 gives an outline of the previous research made in the Computational Fluid
Dynamics field.
ƒ
Chapter 6 is the methodology chapter and describes how CFD has been implemented into
C’Nedra.
ƒ
Chapter 7 presents the results of the thesis and discusses them briefly.
ƒ
Chapter 8 concludes the thesis and suggests points for improvement.
ƒ
Chapter 9 criticises the work done and suggests points for improvement.
1.6 Target Audience
The target audience is mainly researchers and industry entrepreneurs, developing products and
architectures based on 3D game engines. Students and other readers that are interested in gaining a
broad picture of game engines will also find it valuable reading this thesis. Stakeholders interested in
creating open source graphics engines will find interesting information here as well.
1.7 Delimitations
The area of game engines and CFD is a tremendously vast area, which could not possibly be
covered in a single master thesis; hence this thesis aims at specifically focusing on the
implementation of computational fluid dynamics into 3D game engines. Further, I also focus on
the implementation of fire and gas effects seeing as it would be out of the scope for this thesis to
cover all the various forms of fluid in depth such as oceans, clouds, smoke etc. The reader should
keep in mind that the progress in the area is very fast and some topics covered may already have
been outdated during the writing of this thesis.
3
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
2 Game Engines
Chapter 2 defines game engines and goes through what a game engine is. The chapter also deals with the
background and functionality of real-time graphics engines in order to give the reader a foundation for the
work performed in the thesis project. Readers with a thorough understanding of computer graphics and game
engines may pass to the next chapter.
2.1 What is a Game Engine?
A game engine is the core software component of a video game. It usually handles graphical
rendering and other necessary technology, but might also handle additional tasks such as artificial
intelligence and collision detection between game objects, among other things. The most common
element that a game engine provides is graphics rendering facilities. Another common attribute of
game engines is platform abstraction, so the game can run in various platforms with little, if any,
changes in the game source code. Game engines are often coupled with various stand alone
packages that ease development such as for example physics engines that add realistic motion and
explosions just to mention a few capabilities.
2.2 Background of Game Engines
The term "game engine" arose in the mid-1990s, especially in connection with 3D games such as
first-person shooters (FPS) with the popularity of Id Software's Doom and Quake games. These
software packages were created in such a way that would allow developers to licence the core
portion of the software and design their own graphics, characters, weapons and other so called
“game content” (Stang 2003).
Further on, games such as Quake III Arean and Epic Game’s 1998 Unreal were designed
specifically with this approach in mind, which enabled the licensing of such technology. This has
proved to be a very useful auxiliary revenue stream for some game developers seeing as a single
license for a high-end commercial game engine can range from US$10,000 to $3,750,000.
Moreover, reusable engines make developing game sequels much easier and faster, a valuable
advantage in the competitive computer game industry (Stang 2003).
The continued refinement of game engines has allowed a strong separation between rendering,
scripting, artwork, and level design. This has increased the emphasis on the artist’s rather than
programmer’s work. First-person shooter games remain the predominant users of third-party game
engines, but they are now also being used in other genres. For example, the role playing game
Morrowind and the Massively Multiplayer Online Role-Playing Game (MMORPG) Dark Age of
Camelot are based on the NetImmerse engine, the MMORPG Lineage II is based on the Unreal
engine. On game consoles game engines are used as well, for example the RenderWare engine is
used in Grand Theft Auto III and Burnout 2 & 3.
Modern game engines are some of the most complex applications written, frequently featuring
dozens of finely tuned systems interacting to ensure a finely controlled user experience.
4
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
2.3 Game Engine Functionality and Design
When discussing the game engine I try to cover the areas that are pertinent to the areas covered
during the project.
A game engine consists of many parts that interact with each other in order for a game to work.
What makes or breaks a game engine is how well the various parts interact with each other in a
functioning package.
A complex game engine with gaming capabilities is constructed with object oriented programming
and design patterns seeing as the complexity between everything from simple window handling to
keeping track of objects in the scenes grows exponentially during the development process. The
following figure is a simplified model for a generic game engine:
Figure 2: A simplified model of the game engine building blocks
Plug-ins
Terrain Engine
Data
Physics Engine
AI Engine
(World)
Graphics Engine
Special Effects
(Renderer)
Kernel
Multimedia
Engine
Sound files
Textures
(avi, mp3, wav)
(bmp, jpg, png...)
3D models
Multimedia
(3ds,obj...)
(avi, mpg...)
Scripting
The finished 3D application
The model displays hypothetical parts in a simplified game engine and the interaction between plugins, kernel,
scripting and data.
The purpose of the game engine is to simplify and accelerate the speed in which new productions
as well as sequels can be released. Of course, in theory all the parts could be intertwined on code
level; however this would make it extremely difficult to add new functions and create an evolving
programming vehicle. Hence these plug-ins are often implemented with the aid of design patterns
i.e. high level data structures that simplify programming.
In the following chapter, I go through the parts of the game engine one by one in order to give the
reader a global picture of game engine functionality and in particular the C’Nedra game engine
functionality. This is however only an overview seeing as one could write several books for every
single part and algorithm available. I therefore direct the reader to one good introductory text for
more in dept reading such as Angel (2001).
5
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
3 C’Nedra Game Engine
Chapter 3 gives the lay down of the C’Nedra game engine which was developed by students at Ecole
Centrale Paris and used in this master thesis project. The chapter explains the background and the
development behind the engine, the history and evolution of the engine and finally in broad terms how the
engine works.
3.1 Background
C’Nedra (pronounced [snedra]) is a fully functioning 3D real-time virtual reality graphics engine
with networking capabilities. Its cross-platform software programmed in C++ runs on both Linux
and Windows and is available with a GPL license developed by students at Ecole Centrale Paris.
The system allows the user to generate a virtual world containing objects, sounds and events thanks
to a script file defined in the XML language. The software is composed of a core and several plugins meaning that the various parts of the engine can be developed decoupled of each other. The
C’Nedra toolkit and additional information on the project is available on: www.cnedra.org
3.2 History and Evolution
C’Nedra was launched in 2000 by students within the master thesis project framework of the
second year at Ecole Centrale Paris. The aim of these students was at the time to create real time
3D and network application in line with that of Massively Multiplayer Online Role-Playing Games.
The first elements that were set up were basic interface management such as 3D, sound and
window management.
The continuation of the research project was assured by new teams taking up where the old left in
2001, 2002 and 2003 as well as creating an on campus club affiliated with VIA Centrale Réseaux
(the creator of Videolan and Vlc player). Thereafter in 2003, the project was directed towards a
more structured programming approach seeing as the development of a 3D graphics engine is
complex. Thus during 2003, the development principle of the project was restudied and the
objective of the project was more broadly defined than that initially envisaged – namely to design a
real time user defined virtual reality generator.
In order for efficient development of the engine, a kernel-plug-in structure was set up in 2003-2004.
The plug-ins are independent of each other with thread management making it possible creating
powerful applications with dissociated functionalities.
3.3 Functionality and Design
Explaining the entire structure and functionality of C’Nedra is out of the scope for this thesis. I will
here focus on the main functionality in order to give the reader an understanding of the work
carried out and how fluid mechanics were implemented into the system.
The development platform was mainly Windows XP with Microsoft Visual C++ and Debian
Linux.
6
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Figure 3: A schema displaying the various parts in the C’Nedra virtual reality toolkit
The image displays the main structure in the C’Nedra 3D game engine. The game engine has a kernel-plug-in
structure with a xml-file used for scripting capabilities.
3.4 Kernel
A kernel is the core of the game engine as well as the core of real-time software applications. In
C’Nedra it supplies real-time management of threads making interacting parts autonomous and
hence the illusion of a real-time system is achieved. It also takes care of tasks such as memory
management and it allows for a client-server structure. In a formal definition, real-time software
pertains to computer applications that have a time-critical nature or, more generally, applications in
which data acquisition and response must be performed under time-constrained conditions.
Consider, for example, a computer program that displays information about arrivals on a large
screen in an airport terminal; several lines of text display information about flight numbers, status,
and time of landing, and so on. Clearly, the software responds to timely events – an airplane lands,
delays are announced, and so on. The arrival of these bits of information is highly unpredictable,
and the application must process and respond to them accordingly. Moreover, this time-dependent
information must then be displayed on a screen to provide a visual presentation of the timedependent data.
Figure 4: A simplified model of a real-time air-traffic control system
Games are not very different from this architecture. Imagine that we eliminate the radar, generate
virtual air traffic using a software simulator, and tell the user he must make planes land safely. Add
a scoreboard to that and a game over screen and it begins to sound familiar. All games are indeed
interactive, real-time applications. The operator (henceforth called the player) can communicate
with the game world, which itself simulates real-time activity using software components. An
enemy chasing us, elevators going up and down, and returning fire are all examples of the kind of
virtual real-time found in games. But there is more to games than you might think. Games are also
time constrained; they must display information at a set pace (usually above 25 frames per second)
7
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
to allow interaction to become seamless. This certainly limits the scope of both the real-time
simulators and the presentation layer found in games – we cannot do more than what the hardware
allows in the given time slice.
3.5 C’Nedra Plug-ins
The C’Nedra game engine is constructed so that independent plug-ins can be developed and used
in various scenarios. In C’Nedra there are three layers of implementation and there is one global
and one non-global class for each layer.
ƒ
The kernel layer represents the classes for the kernel implementation of the plug-in which
defines how a plug-in should communicate with the rest of the application.
ƒ
The Interface layer contains classes used to make the features in a specific plug-in
available to other plug-ins. The messages sent between the plug-ins are based on these
classes.
ƒ
The Plug-in layer contains classes at the programmer’s disposal to implement the plug-ins
methods and classes. This layer defines the plug-in.
Figure 5: Plug-in class structure
The rest of this chapter will explain and elaborate upon some of the plug-ins implemented in
C’Nedra and conclude with the special effects plug-in being the integral part of this thesis.
3.6 Graphics Engine (3D plug-in)
In the following section, I describe the core of game engines i.e. the graphics engine. I use a top
down approach instead of bottom-up as often described in the literature.
In C’Nedra graphics scenes are built up by scene graphs of objects that are represented by vertices
r r r
defined by {x , y , z }∈ ℜ3 . Two vertices are grouped together to create a facet that grouped together
creates primitives often in the form of triangles. These primitives are then used to build various
geometric objects defined by matrices or quarternions. The objects are grouped into scene graphs
representing a higher level of abstraction defined as scene management.
The reason for using triangles is that they are minimal and are determined by 3 points or 3 edges.
We can define a triangle by ( x1 , y1 , z1 ), ( x 2 , y 2 , z 2 ), ( x3 , y 3 , z 3 ) or we can define it in terms of
three edges on the following equation and matrix form:
8
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Ax1 + By1 + Cz1 + D = 0
⎡ x1
Ax 2 + By 2 + Cz 2 + D = 0 Æ ⎢ x 2
⎢
Ax3 + By 3 + Cz3 + D = 0
⎢⎣ x3
y1
y2
y3
z1 ⎤ ⎡ A⎤
⎡1⎤
z 2 ⎥ ⎢ B ⎥ = − D ⎢1⎥
⎥⎢ ⎥
⎢⎥
z 3 ⎥⎦ ⎢⎣C ⎥⎦
⎢⎣1⎥⎦
3D Graphics Engines are often divided into several layers where the scene management layer deals
primarily with objects and the rendering layer deals with triangles and graphics state.
Figure 6: Scene graph holding a sphere build up by triangles defined by vertices
Scenegraph
Triangles with vertices
Object
3.6.1 Scene Management
The scene management system in C’Nedra is responsible for efficiently rendering complex scenes.
The system maintains a world full of objects and determines what gets drawn and in what order.
Scene graphs are conceptual tools used to represent virtual three-dimensional (3D) worlds in
computer graphics applications. A scene graph is a hierarchical structure containing nodes
connected by edges. The nodes of the scene graph manage the data describing a virtual scene and
the edges that connect the nodes describe the relationships that exist between them in a meaningful
way. The nodes are ideally arranged in a hierarchical manner that corresponds spatially and
semantically to the modelled object/world. There exist several ways of partitioning objects and the
shapes used is often referred to Oriented Bounded Box (OBB).
ƒ
Uniform grids mean dividing space uniformly instead of hierarchically and can be very
fast or very slow depending on distribution of size and variations in location.
ƒ
Binary Space Partitioning (BSP) tree starts with all of the space. If there are too many
objects we split into two subspaces and choose a plane to divide the space in two. This
plane can be placed anywhere and oriented in any direction. Heuristics are used to choose a
good plane. In order the access objects in the nodes recursion is used. BSP trees of various
environments can easily be created by third party software from for example Id such as
q3Radiant.
ƒ
Octrees starts by placing a cube around the entire scene. If the cube contains “too may”
primitives (say 10) we split into 8 equally nested cubes. We then recursively test and
possibly subdivide each of those cubes. We hence get a more regular structure than a
sphere tree, which provides a clear rule for subdivision and no overlap between cells.
9
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Figure 7: Uniform grids, BSP Trees and Octrees
The picture displays the 2D division in a uniform grid to the left, a BSP tree in the middle and an octree to the right.
In C’Nedra the Scene Management system is based on evenly divided bounded boxes that are held
in a recursive tree in the form of BSP.
3.6.2 Rendering pipeline
C’Nedra allows for both OpenGL and DirectX implementations of handling graphics. Although, the
two graphics packages impose different API’s their implementation is similar in broad terms.
C’Nedra is mainly based on OpenGL and in this thesis I will focus on the OpenGL API although
the fundamentals are equivalent. When rendering 3D graphics, the user application passes
geometric primitives to the graphics adapter as streams of vertices. E.g., a triangle is passed to the
graphics adapter as three vertices, defining the corners of the triangle. Normally, an object in a
scene is passed down for tessellation (subdivision into triangles) and passed as triangles in the form
of vertices to the render system.
Each vertex can have a range of attributes attached to it, such as a normal vector, a color, and other
properties, which affect the processing of the vertex and the primitive it defines. Upon receiving
the vertex streams, the graphics adapter applies the appropriate geometric transformations of the
vertex coordinates and normal vectors, to reflect the desired view of the 3D objects. A color is
computed for each vertex, taking account for the attributes of the vertices and the light in the
scene.
Transformations, which are represented by matrix multiplication, include modelling, viewing, and
projection operations. Such operations include rotation, translation, scaling, reflection, orthographic
projection, and perspective projection.
Generally, one uses a combination of several transformations to draw a scene. Since the scene is
rendered on a rectangular window, objects (or parts of objects) that lie outside the window must be
clipped. In three-dimensional computer graphics, clipping occurs by throwing out objects on one
side of a clipping plane. Culling is similar to clipping but means to determine which objects in the
scene are not visible. Backface culling is normally handled in lower rendering layer such as OpenGL
or DirectX presented in the next section. However, when we have large groups of objects we
would like to cull groups of objects quickly. Finally, a correspondence must be established between
the transformed coordinates and screen pixels. This is known as a viewport transformation.
The primitives are clipped, so only the viewable parts remain, and the primitives are rasterized,
producing streams of fragments, which are pixels with color values, texture coordinates, and depth
values. Different operations, such as texture mapping, blending, and depth-testing, can then be
10
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
performed for each fragment, before the fragments are finally drawn onto a frame buffer as pixels,
thereby creating the rendered image.
Figure 8: A simplified model of the rendering process
3.6.3 Lighting
Light is the most important idea behind visual representation of anything that a human being can
visually perceive. The idea of perception of light lies in the fact that what we can see is not based on
the objects that you are viewing but on the rays of light cast from a light source and reflected from
those objects. It is important to note that eyes do not directly see objects as there is no physical
correlation between your eyes and those objects. Light rays commonly originate from an energy
source such as the sun or a lamp in your room. It is important to note that theoretically a ray of
light travels in a straight line and by the time you visually perceive an object, it is the rays of light
reflected or scattered off that object that your eyes absorb. When considering lighting in a game
engine such as C’Nedra many various components have to be taken into account such as the
property of the surfaces i.e. their material properties, the location and direction of the light sources,
the properties of the lights shining on the object as well as the location of the viewer. The following
terms describe different types of light that are essential to 3D game engines such as C’Nedra:
Figure 9: Lighting equation
clit = cspecular + cdiffuse + cambient
It is important to understand what effect each of these types of light creates on the surface of
rendered 3D objects. These terms were created because certain effects that light produces on the
objects needed to be described in order to derive the complex mathematical calculations of light.
However, this does not mean that these exact types of light actually exist in nature, we just think of
them as an abstraction of the effects that light can produce when cast on different materials. It
would be very time consuming to calculate the real mechanics of light and the way it works in
nature so, this common set of light types was generally adopted by OpenGL: specular, diffuse and
ambient. These components can be implemented in a game engine with various techniques often
depending on the capabilities of the hardware as well as the light implementation algorithms at
hand.
11
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
ƒ
Diffuse component represents a directional light cast by a light source. Diffuse light can
be described as the light that has a position in space and comes from a single direction. A
flashlight can be though of as emitting diffuse light. When diffuse light touches the surface
of an object, it scatters and reflects evenly across that surface.
ƒ
Ambient component is the average volume of light that is created by emission of light
from all of the light sources surrounding the lit area. When sun rays pass through the
window of a room they hit the walls and are reflected and scattered into all different
directions which averagely brightens up the whole room. This visual quality is described by
ambient light. Ambient light alone cannot communicate the complete representation of an
object set in 3D space because all vertices are evenly lit by the same color and the object
appears to be 2-dimensional.
ƒ
Specular component is what gives a surface its shiny appearance i.e. the component of
light that a surface reflects to the environment. Specular reflection (or specular highlight) is
displayed bellow in addition to the ambient and diffuse layers of light. You can observe
how the object's 3D representation is greatly augmented by specular light properties. Just
like diffuse light, Specular light is a directional type of light. It comes from one particular
direction. The difference between the two is that specular light reflects off the surface in a
sharp and uniform way. The rendering of specular light relies on the angle between the
viewer and the light source. From the viewer’s standpoint specular light creates a
highlighted area on the surface of the viewed object known as specular highlight or
specular reflection. The intensity of the specular reflection is dependent on the material the
object is made of and the strength of the light source which contains the specular light
component.
Figure 10: The three fundamental components of lighting in 3D graphics engines: ambient, diffuse and specular
ambient
ƒ
diffuse
specular
Lightmapping is basically just a texture that contains luminance information rather than
an image. The elements of the lightmap are referred to as lumels as they represent elements
of luminosity. After the lightmap has been generated, the texture to be lit and the lightmap
are blended together when applied to the polygon to produce the final effect. The blending
can be pre-calculated before runtime to speed up the program, though the trend now is to
use hardware multi-texturing.
3.6.4 Texturing
Texturing is achieved by storing texture coordinates as vertex data for all vertices and then
wrapping an image file over the object. This is called planar mapping. The coordinates are
interpolated to each pixel during scan conversion. The color is looked up in the texture map file per
pixel. There are various ways of coming up with the coordinate assignments as well as generating
the texture which can be used in creating various effects. The methods implemented in C’Nedra are
as presented bellow:
12
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Figure 11: The image displays texturing implemented in C’Nedra
ƒ
Environment Mapping is a texture technique that fakes mirror-like reflections of an
environment. This is done by precomputing an image and storing it in an environment
map and reflecting distant environment. The technique is a relatively simple technique that
can be used to simulate the look of reflective surfaces such as water or metals. Instead of
computing the true reflection, which is a costly process, it uses a texture map and some
texture coordinate trickery to create a quite convincing reflective effect. Notice, however,
that environment mapping does not simulate true reflections. It is just a clever
mathematical trick that fools the eye almost completely.
ƒ
Sphere Mapping is a type of environment mapping in which the irradiance image is
equivalent to that which would be seen in a perfectly reflective hemisphere when viewed
using an orthographic projection. It is used to add a reflection to a metallic or reflective
object in your scene. Although it is not as accurate as real life or as a cube environment
map, it is a whole lot faster. Cube mapping uses a cube as coordinates for the texturing
process.
ƒ
Bump Mapping is a method for making a smooth surface bumpy by using a texture to
represent the variation in surface height. Then with Phong interpolation we have a normal
for each pixel and use the texture value to perturb the normal. Finally, we use the
perturbed normal for the per-pixel lighting.
ƒ
Procedural Texturing is a way of numerically computing the texture and is useful for
pseudo-random “noise” functions. Examples of such algorithms are the Perlin noise function,
which is a smoothly varying pattern which useful for swirly turbulent effects and the Worley
Cellular Noise is a pattern with edges that is useful for rocky scaly effects.
Per-pixel vs. per-vertex lighting
Depending on the rendering technique used the lighting equation can also be calculated per-pixel or
per-vertex. Per-pixel lighting looks better than per-vertex lighting and is usually hardware
accelerated. When displaying light a normal is used on the surface of the object. However, before
per-pixel lighting was introduced with newer graphics cards you had to tesstle an object to a very
fine mesh in order to receive the same results and this was highly computationally expensive.
Figure 12: Per-vertex and per-pixel normals
13
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
3.6.5 Shadowing
When another object is between the surface and a light source that light source should not
contribute to the surface’s illumination. Shadow Mapping is a way of implementing shadows by
rendering an image from the light’s point of view and aiming the camera to look at objects in the
scene. Then only the z-buffer depth values (holds depth of closes object to the camera) are
rendered (no colors are needed) and the results are stored in a shadowmap. Then when lighting a
point on a surface, for each light that has a shadowmap transform the point to the shadowmap’s
image space. We get the the X,Y and Z values. The Z value to the depth value at X, Y in the
shadowmap. If the shadowmap depth is less than Z then some other object is closer to the light
than this point. Hence, this light is blocked and should not be included in the illumination.
However, if the shadowmap is the same as Z, then this point is the one that’s closes to the light and
we should illuminate it with this light.
3.6.6 Shaders
The software or hardware render calls an arbitrary routine at every pixel which is known as shader.
It implements various type of lightning models and is often written in special-purpose languages
such as RenderMan Shading Languauge, Cg, and HLSL (Direct X). Normally, there are two types of
shaders namely Vertex and Pixel where the prior runs once for each vertex while the second runs
for each pixel as explained in the lighting section. Vertex shaders and fragment shaders are
constructed using API specific languages. In OpenGl, these languages are supplied in the GL_
ARB_vertex_program and GL_ARB_fragment_progam extensions, defining two different assembly
languages. High-level languages for creating vertex shaders and fragment shaders are also becoming
widely used. The most well known is Cg (C for graphics), which is a C-like language designed by
NVDIA. The Microsoft DirectX 9.0 API supports a similar high level language called High-Level
Shading Language (HLSL) and in OpenGl the extensions GL_ARB_shading_languauge_100 gives
support for the similar OpenGL Shading Languauge. As of today C’Nedra does not have support
for vertex shaders hence this is not utilized when implementing fluid dynamics into the system.
3.7 Physics Engine (World plug-in)
In order to make an object or the user move in a game engine various projections of matrices have
to be performed such as scaling, translation or rotation. The motion techniques are often coupled
with a physics engine with the aim of implementing the laws of physics such as for example gravity.
A physics engine allows for real world constraints to be simulated in the game engine. This could
be everything from motion and inertia to for example gravity. A very important issue in the
creation of game engines is collision detection. We implemented this in C’Nedra with the Tokamak
physics package (www.tokamakphysics.com).
3.7.1 Mesh Loading
In high quality games of today all characters and objects in a game are modelled and textured in
modelling software such as 3D Max Studio or Maya. These objects are then loaded by means of
mesh loading, which means parsing objects from files created in modelling software. Depending on
the file type various sorts of parsers have to been written to incorporate the data in the modelling
file to be transferred into the graphics engine API. The C’Nedra engine supports 3D objects
implemented in both 3D Max Studio (3ds) format with texturing; however does not support
animated objects with skeletal structures. During the project various models were implemented
with Maya and 3D Max Studio into C’Nedra.
14
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Figure 13: Pictures showing a model created with a 3D scanner at the ECP research facility
The images display a tank that we scanned by a 3D scanner, textured in 3D Max Studio and finally inserted into
C’Nedra graphics engine.
3.7.2 Skeletal Animation
This is a technique used to pose character models. A skeleton is embedded in, and attached to, a
character model. Once the skeleton is attached, the character model becomes the skin. Posing the
skeleton causes the skin to be deformed to match the position of the underlying bones. Skeletal
animation has a major advantage over jointed models in that a one piece mesh is used, so there are
no seams. The model be created and animated in a modelling program such as Maya or 3D Max
studio and then inserted and controlled from within the game engine.
Figure 14: Skeletal Animation
3.7.3 Collision
We based the collisions detection system in C’Nedra on an OBB (oriented bounded boxings), tree
approach. C’Nedra enables collision of two objects in translation meaning that spinning collision
effects can be implemented as explained in Eberly (2001).
15
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Figure 15: Oriented bounded box decomposition in C’Nedra
The collision system coupled with Tokamak takes advantage of forward and inverse kinematics but does not
use skeletal bodies. The next part discusses this functionality.
Figure 16: Collision with the tank that rolls over with the help of the laws of physics
3.7.4 Kinematics
This is a concept that involves explicitly setting the position and orientation of objects at specific
frame times. For skeletons this means directly setting the rotations at selected joints and possibly
the global translation applied to the root joint creating a pose. To avoid doing this for each frame
of an animation, a series of keyframe poses can be specified at different frames with intermediate
poses calculated by interpolating the joint parameters between the keyframe. The object can then
be animated by displaying each intermediate pose.
Inverse Kinematics allows for the position of any object within a skeleton only to be indirectly
controlled by specifying rotations at the joints between the root and the object itself. In contrast
forward kinematic techniques provide direct control over the placement of an end-effect or object
at the end of a kinematic chain of joints solving for the joint rotations which place the object at the
desired location. An animator can instead directly specify the position of an end-effector while the
system automatically computes the joint angles needed to place the part.
3.7.5 Dynamics
Forward Dynamics involves explicit application of time varying forces and torques to objects. Some
forces such as those due to gravity and collisions between objects may be handled automatically. An
equation relates angular acceleration to apply torques by the animation system and other forces are
applied directly by the animator to objects in the scene. The motion is approximated by taking a
16
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
series of discrete steps in time and at each step solving the equations of motion for the acceleration
an object undergoes in response to the applied force. Given the position and velocity of an object
from the previous time step, the acceleration can be twice integrated to determine a new velocity
and position respectively for the current time step.
Inverse Dynamics automatically determines the force and torque functions needed to accomplish a
stated goal. In the degenerate case the stated goal is a complete description of the motion and the
aim is to determine the forces and torques which reproduce the motion under forward dynamic
simulation. While this case is of interest in robotics, its application is of little use in an animation
system after all if the motion trajectories and timing are known beforehand the expense of the
physical simulation is unnecessary.
3.8 Terrain Engine (Terrain plug-in)
The terrain engine is the part of the system that interacts with the renderer in order to build
seamless creator defined terrain. This is most commonly done by creating large meshes with
varying height. The mesh is textured with various techniques such as for example splatting.
3.8.1 Height Field Approach
C’Nedra used the simplest form of terrain representation: a regular height field which is a grid in
the XZ-plane, with evenly spaced points with a height attributed to each point. This representation
saves a lot of space when storing the terrain because one will only need the heights, and a reference
point in the terrain, for instance the centre point in the XZ-plane. Since the grid is evenly spaced
one does not need to store both x and z values for each point. Starting from this premise, one can
easily conceive a height map as a greyscale image, where the intensity of each pixel corresponds to a
height. This method is simple and gives the game creator control over the area created; however it
is not very useful for certain games were random worlds are created.
Figure 17: Height field terrain engine implementation
3.8.2 Importing Pre-Generated Terrain Meshes
Another common technique is to generate meshes of terrain in special terrain generating software
or in modelling languages such as Maya or 3D Max Studio and importing these into the game
engine, which also is possible in C’Nedra by loading the terrain as an object defined in the XMLfile.
3.8.3 Artificial Terrain Generation
Other more sophisticated methods for implementing terrain consist of artificially generating terrain.
This means using some sort of algorithm that divides the space and creates either highs or lows.
17
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Examples of common such algorithms are the Fault Algorithm, the Circles Algorithm and Mid Point
Displacement. Even though artificial terrain generation was not implemented into C’Nedra, I give a
brief explanation of parts of its functionality:
ƒ
The Fault Algorithm starts with a planar height field, where all points have zero height.
Then it selects a random line which divides the terrain in two parts (in general these parts
will be different in size). The points to one side of the line will have their height displaced
upwards, whereas the points on the other side will have their heights displaced downwards.
So now we have a terrain with two distinct heights. If one keeps dividing the terrain like
this then one gets something that has valleys, mountains and so on.
ƒ
Circles Algorithm works similarly to the fault algorithm; however, instead of a line
dividing the space, the circle algorithm uses a circle with random centre. The radius is user
defined. Points inside the circle are displaced upwards, whereas the remaining points will
keep their height. This leaves us with valleys and mountains.
Figure 18: Height field terrain engine implementation visualized in C’Nedra
ƒ
Mipmapping is a level-of-detail method used in C’Nedra with reasonable compromise
between performance and quality which is used in most graphics hardware and software
renderers. Level of Detail (LOD) refers to the various techniques of reducing detail for
objects as they get further away. There are various techniques that are implemented
throughout the game engine’s various building blocks. By using this several mipmaps are
stored as scaled down-versions of the original image usually half the resolution. These are
then tiled as a function of distance to conserve memory.
3.9 Artificial Intelligence Engine (AI plug-in)
Artificial Intelligence, as used by commercial game developers is simplistic in comparison to the
techniques being used in mainstream academic research and industrial applications. Some of the
more important reasons for this lack of sophistication include a lack of CPU resources and
development time, as well as lack of control of the result achieved. This has led to the emergence of
a number of very well established, well understood and robust techniques that are in wide use by
game developers. These include Finite State Machines, and their close relation Fuzzy State Machines, the
A* path finding algorithm, and a number of techniques including flocking algorithms. These are often
referred to as deterministic approaches. More advanced types of techniques are statistical including for
example neural networks, genetic algorithms and case-based reasoning. In the beginning of the project we
intended to implement AI; however due to lack of time this was never pursued seriously.
18
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Nevertheless, I present some of the most common topics in the area according to Millington
(2001).
ƒ
Finite State Machines (FMS) are used to create deterministic behavior in game engines
such as for example triggering opponents to charge when the user enters a certain area or
performs an action. It is mostly only a design concept – that is, the game has no general
FSM interpreter, but the FSMs are realized by scripts and simple if-then statements.
ƒ
Fuzzy logic enables a computer to reason about linguistic terms and rules in a way similar
to humans thereby making it easy to extract domain specific knowledge from an expert and
to present it in a form a game playing agent can utilize. Monitoring and adapting to the
opponent's style of play. A number of rules which can be adapted, graded, modified and
measured which is an excellent way of computer learning. Fuzzy logic represents facts as a
matter of degree rather than true/false statements. Humans often assign facts to categories
with some flexibility about the boundary conditions. For example, in a football match, a
player might have to decide whether to try to outrun a defender or pass the ball to a teammate, e.g. decisions will be based on assessments of speed and agility like “the defender is
fast but can't turn very quickly” rather than “the defender can cover 20m in 2.8s from
standing, but requires 0.95s to turn 180 degrees”
ƒ
Path finding algorithms are used to find the best (shortest) solution of a problem where
the outcomes and paths to the solution are represented by for example a tree. Every
problem in AI is a “virtual” tree of all possible (successful or unsuccessful) solutions. And
there are various approaches of finding an efficient search strategy. The leaves in the trees
are the solutions. For example the computer decides the best path to move a vehicle
without crashing into a wall. The widely used A* algorithm is an improved version of
Dijkstra’s shortest-path algorithm.
ƒ
Classic Flocking means that virtual agents are steered to follow another object under
certain constraints. For example, it may be used when the computer has characters helping
the player or enemies searching for the player.
ƒ
Neural Networks can be fed with information that could be interpreted as vision or
auditory information. This information can then be used to select an output response or
teach the net. These responses can be learned in real-time and updated to optimize the
response. A neural net can be used by game creatures as a form of memory. The neural net
can learn through experience a set of responses, and then when a new experience occurs,
the net can respond with something that is the best guess at what should be done. The
output of a neural net can be used to control the actions of a game creature. The inputs
can be various variables in the game engine. The net can then control the behavior of the
creature.
ƒ
Genetic algorithms are good when searching very large problem spaces, and also for
evolutionary development. For example, using characters with a large structure of possible
traits (aggressiveness, probability of running away when low on health etc.) then a genetic
algorithm can be used to find the best combination of theses structures to beat the player.
For example, the player would go through a level, and at the end of that level, the program
would pick the monsters that had done the best against the player.
ƒ
Case-based reasoning broadly construed, is the process of solving new problems based
on the solutions of similar past problems. This is a way of the computer to learn from past
experiences. For example in a strategy game the computer could use a genetic algorithm
when optimally allocating resources and then use case-based reasoning to bias this behavior
towards previously human created behaviour by having stored prior human decisions.
19
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
3.10 Multimedia Engine (Sound plug-in)
No game engine worth the name can be without sound. This component may seem easy to
implement; however there are a lot of issues to achieving realistic sound effects with moving
objects such as for example Doppler effects. C’Nedra use a package called OpenAl, which
supplements a great open source API for sound development. OpenAl is basically an audio library
that contains functions for playing back sounds and music in a game environment. It allows a
programmer to load whatever sounds they like and control certain characteristics such as position,
velocity, direction and angles for cones that determine how the sound is travelling. All sounds are
positioned relative to the listener which represents the current place in the game universe where the
user is.
3.11 Interface management (Interface plug-in)
A game engine normally has various types of interfaces that the user can utilise in order to interact
with the system. This can be everything from simple mouse and keyboard input to more elaborate
menu systems orthogonally projected onto the screen. C’Nedra supports mouse and keyboard
interaction as well as the creation of orthogonal and projected interfaces.
3.12 Scripting (xml plug-in)
Many commercial game engines include simplified scripting languages that allow the game creator
to create applications without having extensive programming skills. The scripting language is often
an XML or C like language that interacts with the game engine API. Other languages commonly
used are LUA and JavaScript. The C’Nedra game engine supports scripting by using a XMLconfiguration file. In order to create a scenario you only have to modify the XML configuration file
and there is no need to rebuild the entire software package each time a new object is added or
changed in a scenario. Please refer to Appendix for an example of XML-scripting from the
C’Nedra 3D game engine. By defining a specific object the necessary collision coordinates are
automatically generated and placed in a .mtrdat file and the object can be used in the world.
Figure 19: Pictures showing simulations created in C’Nedra virtual reality toolkit with a simple xml file
3.13 User Driven Data
The structure of game engines is to allow for user driven data to easily be implemented into the
system from other applications such as for example Maya and 3D Max Studio. Models
implemented into the engine are first created, textured and animated in these modelling
environments and then inserted into the game engine by using the XML-script file.
20
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
3.14 Editors
Most commercial game engines include GUI-, World- and Scenario Editors intertwining the
scripting languages making it possible for “What You See Is What You Get” development and
almost no programming skills are needed to create interesting games. During my year of the project
there was no editor available for constructing world through the xml file. Today there is a very
simple editor available for creating worlds.
Figure 20: Pictures showing the new editor implemented to help designers creating worlds by not writing XML directly
3.15 Special Effects (special-effects plug-in)
Even though there were many algorithms implemented into C’Nedra which would have been
interesting to discuss more in depth in this thesis, I choose to focus on the implementation of CFD
in the form of special effects of fire and gas. Hence the special effect plug-in implemented in
C’Nedra is the base for the rest of this thesis. The plug-in developed allows for placing a fluid
substance in the form of gas or fire defined by a rectangular grid.
Figure 21: Special effects implemented into C’Nedra
21
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
The fluid can then be animated thanks to the Navier-Stokes equations. The animation can be
controlled by setting various parameters such as the ambient temperature or the boundaries of an
object submerged in smoke or fire. The rest of this paper will deal with the implementation of fluid
dynamics in the form of fire and smoke.
3.16 Summary of Features implemented in
C’Nedra during thesis work
In this last section, I summarize the work carried out in enhancing the C’Nedra game engine. The
integral part of this thesis deals with implementing special effects in the form of fire and gas;
however, many other enhancements to the C’Nedra toolkit were carried out in due course of the
project. These areas have mainly been dealt with in the previous chapters and are summarized in
the table bellow:
Figure 22: Summary of C’Nedra game engine features
Kernel
Graphics
Engine
Terrain
Engine
Physics
Engine
Special
Effects
Real-time thread
management
Scene
Management
Height
Field
Mesh
loading
Client-server
Rendering
Imported
Meshes
Camera
Movement
Lighting
Texturing
Collision
detection
Shadowing
LOD
AI Engine
Multimedia
Engine
Other
Gas
2D Sound
Interface
management
Fire
3D Sound
Scripting
User driven
data
Editors
Texturing
Cross
Platform
22
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
4 Theory of Fluid Substances
From having given the reader a general introduction to game engines and the particular software in question
I move on to introducing the theory behind this thesis. I start by defining what fluids are and what types of
simulation approaches are the most common. The chapter also defines the Navier-Stokes equations, which
often are used to model fluids substances in Computational Fluids Dynamics.
4.1 Definition of Fluid Substances
As the aim of this thesis is to simulate fluid substances such as liquids or gases, it is important that
we understand what fluid really is. In this chapter, I will try to define fluids by describing how we
perceive fluid, and introduce the mathematical model of fluid motion. Please refer to Appendix I
for an outline of the mathematical notation used in the thesis.
To describe all physical properties of fluids would be out of the scope of this thesis. I therefore
limit the introduction to the necessities of this report. For a more thorough description of fluid
dynamics, I refer the reader to physics textbooks, such as Candel (1995).
4.2 Perception of Fluid Substances
Fluid substance effects range from small scale effects, such as water poured into a glass and smoke
rising from a cigarette, to large scale effects, such as oceans. To give an idea of the wide range of
fluid effects, I give a list of examples:
Figure 23: Summary of fluid substance effects
ƒ
Large scale liquids: rivers, oceans, waterfalls, etc.
ƒ
Small scale liquids: coffee in a cup, water in a bath tub, etc.
ƒ
Explosions: from local explosions, such as from a grenade, to big explosions, creating blast
waves.
ƒ
Evolution of weather systems: cloud formations, hurricanes, etc.
ƒ
Global wind: wind blowing in treetops, wind that makes fallen leafs “dance” in corners of
buildings, etc.
ƒ
Local wind: a blowing fan, warm air rising from a heater, etc.
ƒ
Fire: from candles to burning buildings.
ƒ
Smoke: for instance rising from a candle.
ƒ
Mist: drifting fog.
ƒ
Clouds: moving clouds in the sky, flying into clouds in flight simulators.
23
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
4.3 Simulation Approaches for Fluids
Currently there are many different approaches to simulating fluids in real time graphics engines
ranging from particle systems and ad-hoc methods to more advanced approaches such as computational
fluid dynamics (CFD) often involving solving the Navier-Stokes equations with various algorithms.
The implemented approach all depends on the specific application. For example when simulating a
fountain or a waterfall then perhaps some sort of particle system would be the most efficient
implementation, while when displaying a flame with more realism we would like to use CFD
approaches. The implementation of a fluid would normally consist of the following steps:
Figure 24: Steps followed in implementing fluids in 3D graphics
1. Choice of method based on the needs of the simulation in question
2. Creation of a motion by particles systems, CFD approaches or ad-hoc methods
3. Rendering of the fluid using texturing and for example shading
4. Application or handling of constraints such as collision i.e. floating in the fluid or waves
4.4 Choice of Method for Simulation
Which method to use in practice depends largely on the problem at hand and on the computing
power available. Most engineering tasks require that the simulation provide accurate bounds on the
physical quantities involved to answer questions related to safety, performance, etc. The visual
appearance (shape) of the flow is of secondary importance in these applications. In computer
graphics, on the other hand, the shape and the behaviour of the fluid are of primary interest, while
physical accuracy is secondary or in some cases irrelevant. Fluid solvers, for computer graphics,
should ideally provide a user with a tool that enables us to achieve fluid-like effects in real-time.
4.5 The Navier-Stokes Equations
The Navier-Stokes differential equations are a set of partial differential equations (PDEs), which
describe the motion of viscous incompressible fluids. This means that all properties of the fluid are
described exclusively by its viscosity and density. Although air is not actually incompressible, most
gas effects observed in everyday life uphold this property. Thus, I will assume gas to be
incompressible in the context of this report.
The Navier-Stokes equations are based on the assumption that fluids can be described as a
collection of particles. The terms describe the forces acting on a particle, derived by observing the
behavior in a unit cube around the particle. This is done under the assumption that the fluid inside
this unit cube behave uniformly. The Navier-Stokes equations were derived from Newton’s second
law of motion, which states that:
Figure 25: Newton’s second law of motion
r
r
f = m⋅a
24
(4.1)
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
r
r
where m is mass, a is acceleration, and f is force. They describe the changes in a velocity field, i.e.
the acceleration of the fluid, as a sum of the forces acting on the fluid – including forces introduced
by the fluids own movement. In a compact vector notation the Navier-Stokes equations are
presented as:
Figure 26: Navier-Stokes equations
r
∂u 1 r r
r
r 1
= f − (u ⋅ ∇ )u + v∇ 2 u − ∇p,
∂t ρ
ρ
(4.2)
r
∇ ⋅ u = 0.
(4.3)
4.5.1 External Forces
The first term in the Navier-Stokes equations represents external forces and is given by the
following expression:
1 r 1 x y
f = (f , f , f
ρ
r
(
where the force field f = f x , f y , f z
)
T
ρ
)
z T
(4.4)
is the sum of all external forces working on the fluid, and
r
ρ is the density of the fluid, which describes the mass of a unit cube of fluid. Because u is a
vector quantity, there are four equations and four unknowns: u, v, w, p . The four terms on the
right-hand side of Equation (4.2) represent accelerations. I will examine each of them in turn.
4.5.2 Advection
The second term in the Navier-Stokes equations represents advection and represents the force of
the fluid motion working on itself. This can be thought of as the molecules in a fluid bouncing into each
other. If one molecule bumps into another molecule, the other molecule is affected and will start
moving. The contribution of advection is described by:
⎛ x
⎜u
⎜
⎜
r
r
− (u ⋅ ∇ )u = −⎜ u x
⎜
⎜ux
⎜
⎝
r
∂u x
∂x
∂u y
∂x
∂u z
∂x
(
∂u x
∂y
∂u y
uy
∂y
∂u z
uy
∂y
uy
where ∇ is the gradient operator, and u = u x , u y , u z
)
T
∂u x ⎞
⎟
∂z ⎟
∂u y ⎟
uz
⎟
∂z ⎟
∂u z ⎟
uz
∂z ⎟⎠
uz
(4.5)
is the velocity.
4.5.3 Diffusion
Diffusion occurs when part of the fluid passes by an obstacle, or another part of the fluid with a
different velocity. The fluid is slowed down and vortices appear. The contribution of diffusion is
described by the term:
25
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
⎛ ∂ 2u x
⎜ 2
⎜ ∂x
⎜ ∂ 2u y
r
v∇ 2 u = v ⎜ 2
⎜ ∂2x z
⎜∂ u
⎜ ∂x 2
⎝
∂ 2u x
∂y 2
∂ 2u y
+
∂y 2
∂ 2u z
+
∂y 2
+
∂ 2u x
∂z 2
∂ 2u y
+
∂z 2
∂ 2u z
+
∂z 2
+
⎞
⎟
⎟
⎟
⎟
⎟
⎟
⎟
⎠
(4.6)
where v is the kinematic viscosity of the fluid, which describes the “thickness” of the fluid. Hence,
diffusion is also referred to as the effect of viscosity. Some fluids are “thicker” than others. For
example, molasses and maple syrup flow slowly, but alcohol flows quickly. We say that thick fluids
have a high viscosity. Viscosity is a measure of how resistive a fluid is to flow. This resistance
results in diffusion of the momentum (and therefore velocity), so the third term is called the
diffusion term.
4.5.4 Pressure
Fluid moving in and out of the observed unit cube causes the pressure to change. Differences in
pressure between the unit cube and its surroundings affect the velocity as described given by
T
r
1 ⎛ ∂p ∂p ∂p ⎞
− ∇p = − ⎜⎜ , , ⎟⎟ ,
ρ
ρ ⎝ ∂x ∂y ∂z ⎠
1
(4.7)
r
where ρ is still the density of the fluid and p is the pressure. Because the molecules of a fluid can
move around each other, they tend to “squish” and “slosh”. When force is applied to a fluid, it
does not instantly propagate through the entire volume. Instead, the molecules close to the force
push on those farther away, and pressure builds up. Because pressure is force per unit area, any
r
r
pressure in the fluid naturally leads to acceleration. (Think of Newton’s second law, F = m ⋅ a )
The second term, called the pressure term, represents this acceleration.
4.5.5 Incompressibility
To ensure that the volume of the fluid is kept constant, the net flow of the unit cube should be
zero, indicating that the amounts of fluid entering and leaving the cube should be equal. This is
described by the incompressibility constraint:
r
∂u x ∂u y ∂u z
∇⋅u = 0 ⇔
+
+
= 0.
∂x
∂y
∂z
(4.8)
By adding all these terms, the equations (4.2) and (4.8) can thus be written component wise,
without the use of the gradient operator, as:
26
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
∂u x
∂u x
∂u x ⎞ ⎛ ∂ 2 u x ∂ 2 u x ∂ 2 u x ⎞ 1 ∂p
f x ⎛ x ∂u x
⎟ + v⎜
⎟−
=
− ⎜⎜ u
+ uy
+ uz
+
+
∂t
∂x
∂y
∂z ⎟⎠ ⎜⎝ ∂x 2
∂y 2
∂z 2 ⎟⎠ ρ ∂x
ρ ⎝
y
y
⎛ ∂ 2 u y ∂ 2 u y ∂ 2 u y ⎞ 1 ∂p
∂u y
f y ⎛ x ∂u y
y ∂u
z ∂u ⎞
⎟ + v⎜
⎟−
=
− ⎜u
+u
+u
+
+
∂t
∂x
∂y
∂z ⎟⎠ ⎜⎝ ∂x 2
∂y 2
∂z 2 ⎟⎠ ρ ∂y
ρ ⎜⎝
∂u z
∂u z
∂u z ⎞ ⎛ ∂ 2 u z ∂ 2 u z ∂ 2 u z ⎞ 1 ∂p
f z ⎛ x ∂u z
⎟ + v⎜
⎟−
=
− ⎜⎜ u
+ uy
+ uz
+
+
∂t
∂y
∂z ⎟⎠ ⎜⎝ ∂x 2
∂y 2
∂z 2 ⎟⎠ ρ ∂z
ρ ⎝ ∂x
(4.9)
∂u x ∂u y ∂u z
+
+
= 0.
∂x
∂y
∂z
The most important quantity to represent in a fluid simulation is the velocity of the fluid, because
velocity determines how the fluid moves itself and the things that are in it. In the context of this
report, I define the velocity vector field of a fluid on a Cartesian grid such that for every discrete
r
r r
r
r
r
position x = ( x, y , z ) , there is an associated velocity at time t , u ( x , t ) = (u ( x , t ), v ( x , t ), w( x , t ) )
The key to fluid simulation is to take steps in time, and at each time step, correctly determine the
current velocity field. This is done by solving the Navier-Stokes equations for incompressible flow.
Once velocity field is acquired, one can use it to move objects, smoke, cloud water concentrations,
and other quantities that can be displayed in applications.
27
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
5 Previous research
Chapter 5 introduces previous research on implementing computational fluid dynamics into 3D graphics
and gives some background for the fluid dynamics solver implemented and tested in this thesis.
5.1 Particle systems and Noise
Particle Systems were introduced in the early 1980s by Pixar (then part of the Lucasfilm special
effects group) for the movie Star Trek II: The Wrath of Kahn. Specifically, particle systems were
used to represent a chain-reaction explosion on the surface of a planet, so the planet changed from
a dead, barren look to a full living ecosystem (Eberly 2001). Particle systems are essentially a
mathematical formalism used to describe phenomena that are complex, dynamic and highly parallel
with small individual components. Examples of such behavior include smoke from a chimney, fire,
birds flying in a flock, snowflakes, and hundreds of other phenomena. Particle systems are context
insensitive, meaning they can be used to model very different situations. The particle system is a
tool, but does not imply a specific use-case in itself. By changing some of its inner components, it
can be suited to many problems.
Noise is a method of mimicking CFD and was first described by Perlin (1985), who modelled
ocean waves by stochastically perturbing surface normals (bump mapping) according to a
superposition of randomly distributed spherical wavefront sources. A random spatial frequency f is
assigned to each spherical wavefront source. The amplitude of the wavefronts are f=1 and the
phase of the sources is modulated by a function of pf.
5.2 CFD approaches
The Navier-Stokes differential equations are a set of partial differential equations (PDEs) that
describe the motion of viscous incompressible fluids. This means that all properties of the fluid are
described exclusively by its viscosity and density. The solution of these equations has long been
impossible. However, thanks to advances in numerical computation these equations have entered
computer graphics and are one of the hottest topics today and can be used to simulate everything
from water and gas to clouds and fire.
ƒ
Foster and Metaxas (1996) describe one of the first methods for simulating the full 3D
Navier-Stokes equations for computer graphics. The method is based on explicit methods
and only stable for small time steps. In fact, the time step must uphold the Courant-FriedrichLevy (CFL) condition:
⎛ ∂t
∂t z ∂t ⎞
1 > max⎜⎜ u x , u y
,u
⎟⎟, ∀u x , u y , u z
x
y
z
∂
∂
∂
⎝
⎠
(5.1)
where u x , u y , and u z are the velocity components in x, y and z directions.
ƒ
Foster and Metaxas (1997) give an extended version of the 1996 algorithm including the
forces of thermal buoyancy. This means that temperature is represented in the centre of
each grid cell, defining a discrete temperature field equivalently to pressure. The
temperature field is advected and diffused using the same method as with velocity. When
updating the velocity field, the temperatures are used for calculating external forces given
by:
28
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
r
r
Fbv = − βg y (T0 − Tk ),
(5.2)
r
where β is the coefficient of thermal expansion, g y is the gravity vector, T0 , is the initial
reference temperature, and Tk is the simulated temperature.
ƒ
Stam (1999) extends Foster and Metaxas (1996) with the aim of making the solver
unconditionally stable. Thus, the different contributions of the Navier-Stokes equations are
added in the following steps:
1. External forces are added simply by adding the force field to the velocity field.
2. The effect of advection is added by using a semi-Lagrangian method. With this
method, grid points are advected backwards (as opposed to forward in
Lagrangian methods) to find the new velocities values.
3. The effect of diffusion is added by solving the diffusion term using an implicit
method, yielding:
∂u~ r
u~ −
=u
∂t
(5.3)
r
∂u~
is given
where u is the current velocity, u~ is the yet unknown, updated velocity, and
∂t
by the diffusion term of the Navier-Stokes equations.
This yields a velocity field that is not mass-conserving. But instead of using a Sucessiver
Over Relaxation (SOR) method, a mathematical result called Helmholtz-Hodge
decomposition is used. This states that any vector field can be decomposed into a scalar
gradient field and a mass-conserving vector field, yielding:
r
r
u~ = u + ∇q, ∇ ⋅ u = 0
(5.4)
⇒ ∇ ⋅ u~ = ∇2 q.
The last equation is a Poisson equation for the unknown scalar field q . When spatially
discretezed this equation yields a sparse linear system, which can be solved in a number of
ways. When solved, the pressure field is used to calculate the mass-conserving velocity field
according to the last equation.
ƒ
Fedkiw et al (2001) give a method for simulating smoke based on Stam’s method. Under
the assumption that the effects of viscosity are negligible in gases, when simulated on a
coarse grid, the diffusion term of the Navier-Stokes equations are left out, leaving the
incompressible Euler equations:
r
r
r
r
∂u
= −(u ⋅ ∇ )u − ∇ρ + f ,
∂t
r
∇ ⋅ u = 0,
29
(5.5)
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
r
r
where u is the velocity, ρ is the pressure, and f is the external forces. In order to make
up for the coarse grid representations, vorticity confinement is used to add the small scale detail
that has been damped out by numerical dissipation back into the velocity field.
ƒ
Stam (2003) presents a simple and rapid implementation of the Stam (1999) fluid
dynamics solver for game engines with the Navier-Stokes equations. The algorithm
presented in Stam’s papers presents a 2D implementation and needs to be extended into
3D.
ƒ
Losasso et al. (2004) present a method for simulating water and smoke on an unrestricted
octree data structure exploiting mesh refinement techniques to capture the small scale
visual detail. The paper proposes a new technique for discretizing the Poisson equation on
this octree grid with fast solution methods such as preconditioned conjugate gradients.
ƒ
Harris et al. (2003) present a physically-based, visually-realistic cloud simulation suitable
for interactive applications such as flight simulators. Clouds in the system are modelled
using partial differential equations describing fluid motion, thermodynamic processes,
buoyant forces, and water phase transitions.
ƒ
Guendelman et al. (2005) present a novel method for solid/fluid coupling that can treat
infinitesimally thin solids modelled by a lower dimensional triangulated surface. Since
classical solid/fluid coupling algorithms rasterizing the solid body onto the fluid grid, an
entirely new approach is required to treat thin objects that do not contain an interior
region.
ƒ
Selle et al. (2005) introduce a new hybrid technique that makes synergistic use of
Lagrangian vortex particle methods and Eulerian grid based methods to overcome the
weaknesses of both. The approach uses vorticity confinement itself to couple these two
methods together and generates highly turbulent effects unachievable by standard grid
based methods, and show applications to smoke, water and explosion simulations.
5.3 Large Scale Fluid Motion
Oceans among other phenomena are often large scale phenomena that need a different approach
than the local both with regards to quality as well as performance. For example, simulating an entire
ocean in a flight simulator with Navier-Stokes is very computationally expensive and not very
practical. These algorithms are often based on various combinations of trigometric functions.
These approaches are however not the focus of this thesis as I am focusing on local fluid such as
fire and gas.
5.4 Summary
When rendering fluids, such as water and liquids in general, where the surface is, in fact, defining
the substance, particle system come short. Using particle systems for rendering liquid effects tends
to make the surface of the liquid seem diffuse, which ruins the visual effect. Thus, particle systems
are more appropriate for rendering low quality gases. More advanced methods, based on the
physics of fluids, achieve much more realistic effects, and can be used for the generation a wider
range of effects (Johanson 2004). Unfortunately, they do take a lot of processing power in real-time;
30
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
nevertheless I choose to implement Stam’s algorithm in 3D seeing as the approach, gives
astonishing results and is quite straight forward to implement.
31
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
6 Methodology
Chapter 6 discusses the methodology used in the project. Further, the methodology used in creating fluid
effects and testing scenarios for the specific game engine is discussed.
6.1 Outline of Methodology
1. Gaining understanding of C’Nedra through implementing new functionality
2. Solving the Navier-Stokes Equations
3. Implementing the algorithm in a C’Nedra plug-in
4. Scenario testing of the special effects plug-in
6.2 Solving the Navier-Stokes Equations
Analytical solutions of the Navier-Stokes equations can only be found for a few simple physical
problems. Nevertheless, it is possible to use numerical integration techniques to solve them
incrementally. The aim of this project is to display the evolution of the flow over time, so an
incremental numerical solution is sufficient. The algorithm I used to solve the Navier- Stokes
equations is based on the “stable fluids” technique described in Stam, (1999), Stam (2003) and
Fedkiw et al. (2001). In this section I describe the mathematics of each step in the algorithm.
The first step in the algorithm is to transform the Navier-Stokes equations into a form that one can
use in numerical solution.
Recall that the two-dimensional Navier-Stokes equations are three equations that we can solve for
the quantities u , v , and p (velocity, viscosity and pressure). The following section describes a
transformation that leads to a straightforward algorithm.
6.2.1 Helmholtz-Hodge Decomposition
r
From vector calculus we know that any vector v can be decomposed into a set of basis vector
r
components whose sum is defined by v . For example, we commonly represent vectors on a
r
Cartesian grid as a pair of distances along the grid axes v = ( x, y ) . This can be written as
r
v = xi + yj where i and j are unit basis vectors aligned to the axes of the grid. Hence we can
decompose a vector into a sum of vectors; and we can also decompose a vector field into a sum of
vector fields. If we allow D to represent the region in space on which a fluid is defined to have a
r
smooth boundary, ∂D , and a normal direction n one can use that any vector field can be
decomposed into the sum of two other vector fields: a divergence-free vector field and the gradient of a
scalar field.
32
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Figure 27: Helmholtz-Hodge Decomposition Theorem
r
A vector field w on D and be uniquely decomposed in the form:
r r
w = u + ∇p ,
(6.1)
r r
r
where u has zero divergence and is parallel to ∂D i.e. u ⋅ n = 0 on ∂D .
Step 1
In order to solve the Navier-Stokes equations we need to perform several calculations to update the
velocity field at each time step. We need to apply advection, diffusion and force. This gives us a
r
new velocity field, w , with nonzero divergence; however the continuity equation requires that each
time step ends with a divergence-free velocity. The Helmholtz-Hodge Decompostion Theorem
states that the divergence of the velocity can be corrected by subtracting the gradient of the
pressure field:
r r
u = w − ∇p
(6.2)
Step 2
If we apply the divergence operator to both sides of Equation (6.4.1), we obtain
r
r
r
∇ ⋅ w = ∇ ⋅ (u + ∇p ) = ∇ ⋅ u + ∇ 2 p
(6.3)
r
And we have that ∇ ⋅ u = 0 , which gives us
r
∇2 p = ∇ ⋅ w
(6.4)
This is a Poisson equation for pressure of the fluids. It means that when we arrive at our divergent
r
r
velocity, w , we can solve Equation (6.4) for p , and then use w and p to compute the divergence
r
free field, u , using Equations (6.3).
r
The next step is to find a way to compute w . Seeing as we know that the definition of the dot
r
r
product, we can find the projection of a vector r onto a unit vector s by computing the dot
r
r
product of r and s . The dot product is a projection operator for vectors that maps a vector
r
r
r onto its component in the direction of s . We define a projection operator, P , that projects a
r
vector field w onto its divergence free component, u . If we apply P to Equation (6.1)
r
r
Pw = Pu + P (∇p )
P
(6.5)
r
r r
Pw = Pu = u
(6.6)
P(∇p ) = 0
(6.7)
r
⎛ r
r 1
r r⎞
∂u
= P⎜⎜ − (u ⋅ ∇ )u − ∇p + v∇ 2 u + F ⎟⎟
∂t
ρ
⎝
⎠
r
r
r
r
r
∂u
= P − (u ⋅ ∇ )u + v∇ 2 u + F
∂t
(
)
33
(6.8)
(6.9)
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Figure 28: The simulation algorithm
S = P o D o Ao F
(6.10)
Add force Æ Advect Æ Diffuse Æ Project
V
6.2.2 Advection
Advection is a process by which a fluid’s velocity transports itself and other quantities in the fluid.
To compute the advection of a quantity, we must update the quantity at each grid point. Seeing as
we are computing how a quantity moves along the velocity field, it helps to imagine that each grid
r
cell is represented by a particle. If we move the position r of each particle forward along the
velocity field the distance it would travel in time δt :
Figure 29: Euler’s method
r
r
r
r (t + δt ) = r (t ) + u (t )δt
(6.11)
This is a simple method for forward integration of ordinary differential equations. However, there
are problems with this approach.
The first is that simulations that use explicit methods for advection are unstable for large time
r
steps, and can “blow up” if the magnitude of u (t )δt is greater than the size of a single grid cell.
The solution is to invert the problem and use an implicit method (Stam, 1999). Rather than
advecting quantities by computing where a particle moves over the current time step, trace the
trajectory of the particle from each grid cell back in time to its former position, and copy the
quantities at that position to the starting grid cell. To update a quantity q (this could be velocity,
density, temperature, or any quantity carried by the fluid), use the following equation:
Figure 30: Stam’s method
r
r r r
q ( x , t + δ t ) = q ( x − u ( x , t )δ t , t )
(6.12)
Not only is this method easily implemented on the Graphics Processing Unit (GPU), but as Stam
showed, it is stable for arbitrary time steps and velocities.
6.2.3 Viscous Diffusion
Viscous fluids have a certain amount of resistance to flow, which results in diffusion (or
dissipation) of velocity. A partial differential equation for viscous diffusion is:
r
r
∂u
= v∇ 2u
∂t
(6.13)
r r
r r
r r
u ( x , t + δ t ) = u ( x , t ) + v δ t∇ 2 u ( x , t )
(6.14)
(I − v δ t∇ )ur ( xr , t + δ t ) = ur ( xr , t )
(6.15)
2
34
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Here, I is the identity matrix. This formulation is stable for arbitrary time steps and viscosities.
Equation (6.15) is a Poisson equation for velocity. Remember that the use of the Helmholtz-Hodge
decomposition results in a Poisson equation for pressure. These equations can be solved using an
iterative relaxation technique.
Solution of Poisson Equations
We need to solve two Poisson equations:
ƒ
The Poisson-pressure equation
ƒ
Viscous diffusions equation
These are solved through an iterative approach that starts an approximate solution and improves it
r
r r
every iteration. The poison equation is a matrix equation on the form A x = b , where x is the
vector of unknown values. The iterative technique starts with an initial “guess” for the
r
r
solution x ( 0 ) , and each step k produces an improved solution x ( k ) . One of the simplest of these
approaches is called Jacobi iteration
Both Equation (6.4) and (6.15) can be discretized (See Appenix) and written on the form:
x i(−k1), j + x i(+k1), j + x i(,kj )−1 + x i(,kj )+1 + α bi , j
r
x i(,kj +1 ) =
,
β
(6.16)
where α and β are constants. This expression becomes different for the two different Poisson
equations.
r
In the Poisson-pressure equation x represents p δ t , and b represents ∇ ⋅ w , α = (δ x )2 , and
β = 4.
2
r
For the viscous diffusion equation, x and b represents u , α = (δ x ) , and β = 4 + α .
vδt
To solve the equations, I simply run a number of iterations in which I apply Equation (6.16).
6.2.4 Initial and Boundary Conditions
Any differential equation problem defined on a finite domain requires boundary conditions in order
to be well-posed. Also, to compute the evolution of the flow over time, we must know how it
started—in other words, its initial conditions. For my fluid simulation, I assume the fluid initially
has zero velocity and zero pressure.
Because my fluid is simulated on a rectangular grid, I assume that it is a fluid in a box and cannot
flow through the sides of the box.
For velocity, I use the no-slip condition, which specifies that velocity goes to zero at the
boundaries.
The correct solution of the Poisson-pressure equation requires pure Neumann boundary
conditions: ∂ pr = 0 . This means that at a boundary, the rate of change of pressure in the direction
∂n
normal to the boundary is zero.
35
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
6.3 Implementation
The implementation provides the simulation code for smoke and fire. The simulation code is based
on a simple one-phase-flow. The code is intended for smoke animated seeing as a fire animation
model is better approximated by a two-phase-flow (one for the fuel and one for the hot gaseous
products) rather than a one-phase flow. However, due to time constraints, I use a one-phase-flow
model.
The one-phase-flow simulation used the incompressible, invicid Navier-Stokes-equations including
a convection and pressure term and external forces for buoyancy and vorticity confinement to
update the flow.
The stable fluids method from Stam (2003), that provides a semi-lagrange approach for better
handling of numerical instabilities, is used to update the fluid state. The stability inherently comes
from particle tracing along the streamline backward in time while computing the convection flow.
This approach is stable, but pretty much damps out curls and turbulence. In order to ameliorate
this problem, a vorticity confinement term is added to the equation to get the turbulence back.
In order to animate smoke, density values are placed at the inflow region and are convected
through the flow. For displaying fire or a flame, temperature values are convected along steamlines
as is done in the smoke animation with the density values. But here, an additional temperature
falloff, that simulates the energy exchange with the cooler, surrounding air, is computed.
6.3.1 Discretization
To solve the Navier-Stokes equations using a computer, the equations have to be discretized, so
numerical methods can be applied. To apply the numerical methods efficiently, the values of the
fields representing velocity, pressure, temperature, etc. Should be easy obtainable in the points
needed by the numerical methods. This indicates that the discretization of the equations and the
discretization of the vector fields are tightly connected, and should thus be considred together, in
this chapter, some of the most commonly used discretization methods will be described.
ƒ
Uniform Cartesian Grinds are the most commonly used for computer graphics
applications. The grid used in this project is of this type. A Cartesian grid means that cells
are axis-aligned boxes. Together, all the boxes form a larger box; hence it can be thought
of as a volume. One should think of a uniform Cartesian grid as volume, placed in allpositive octant of a three-dimensional left-handed coordinate system, divided into smaller
cells. The lower left cell is placed with one corner in origo.
ƒ
Collocated Grids are a special type of uniform Cartesian grid. In a collocated grid, all
fields in the simulation are represented at the centre of cells. I.e., if
r
p = , C ( c i , j ,k ), c i , j ,k ∈ Φ
then
r r
r
u ( p ) = u ( C ( c i , j ,k ))
r
is represented explicitly in the discretization of the field u with the grid Φ . Values at other
positions must be interpolated from the nearest values. To shorten the notation, we will simply use
r
the u i , j ,k to specify
36
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
r
r
u i , j ,k = u ( C ( c i , j ,k )), c i , j ,k ∈ Φ .
Although this representation is attractive because of its simplicity it has some numerical
disadvantages. For instance, when using central differencing, on a collocated grid, the divergence
r
r
∇ ⋅ u of the velocity field u is computed discretely as:
∂ u ix, j ,k
∂ u iy, j ,k
∂ u iz, j ,k
r
∇ ⋅ u i , j ,k =
+
+
=
∂x
∂y
∂z
uix+1, j ,k − uix−1, j ,k + u1y, j +1,k − u1y, j −1,k + u1z,1,k +1 − u1z,1,k −1
2h
r
r
I.e., the divergence in point p = C ( c i , j ,k ) is computed without regards to the value u ( p ) of the
velocity field in that position. This is a general problem, since a stepwise linear function is not
differentiable in the end points of the linear intervals. In this case it actually corresponds to taking
the average of the divergences computed in the centre of the neighbouring intervals, since e.g.
x
x
x
x
x
x
x
1 ⎛ ∂ui +1 / 2, j ,k ∂ui −1 / 2, j ,k ⎞ 1 ⎛ ui +1, j ,k − ui , j ,k ui , j ,k − ui −1, j ,k ⎞ 1 (u x
⎜
⎟= ⎜
⎟ = 2 h i + 1 , j , k − u i −1 , j , k ) .
+
+
⎟
∂x ⎟⎠ 2 ⎜⎝
2 ⎜⎝ ∂x
h
h
⎠ .
This introduces numerical dissipation of the fluid motion, making the fluid appear thicker than it
should.
Figure 31: Discretization of simulation volume
ƒ
Staggered Grids is another type of uniform Cartesian grid. With this type of grid, the
pressure field is still represented at the centre of cells, but velocities are represented on the
faces between cells, and could thus be thought of as indicating flow between cells. Many
other types of fields are also used in the field of CFD for discretizing the simulation
volume. Many of the grids are outside the scope of this thesis. Nevertheless, this is an
interesting subject that the reader could do more research into, for example structured
grids and adaptive grids.
37
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
6.3.2 Solver Implementation
The simulation code is found in Appendix and can be summarized in update per frame as follows:
1. Update temporary velocity field (stable convection)
2. Compute pressure field (solving Poisson’s equation)
3. Project pressure gradients onto temperature velocity field
4. Compute vorticity confinement force
5. Advect temperature values (including falloff)
6. Compute buoyancy-force, dependent on temperature
7. Add integrated forces to the velocity field
6.3.3 Texture implementation
Since we are dealing with 3D simulation and thus 3D vector fields, an obvious choice for field
representation is to use 3D texture maps. In 3D texture maps, pixels are indexes using 3D
coordinates (R,S,T), so no abstraction between grid coordinates and texture coordinates is needed.
The colors can then be set for the various RGB components to fit the needs of the simulation.
6.4 Scenario testing
6.4.1 Equipment
The computer system Microsoft Windows XP was mainly used. The hardware was a lap top DELL
Inspiron with an Intel Pentium Centrino 1.5 GHz with 1 Gb Ram.
For the display system, a 17-inch wide WUXGA TFT screen on ATI Mobility Radeon 9600 PRO
TURBO 128 MB was applied. The screen ran at a 60 Hz refresh frequency, with a 1920x1200 pixels
resolution, and with 32-bit color. The monitor’s contrast and brightness settings were both set to
maximum.
38
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
7 Results
Chapter 7 presents the test criteria for implementing CFD, explains what was tested and goes through the
test scenarios giving the results achieved.
7.1 Test Criteria
ƒ
Solver efficiency: In order for a special effect to work in a 3D graphics engine the
algorithm have to run fast. Can the solver actually run in real-time, and what frame rates
are actually possible?
ƒ
Fire- and smoke like behaviour: The main purpose of the thesis is to simulate smoke in
a 3D game engine. Hence one criterion should be whether the simulation appears to be
realistic or not.
ƒ
Interaction with objects: In order for a special effects simulation to be useful in a 3D
graphics engine it has to be able to interact with other objects. Hence, does the simulated
fluid behave convincingly around inserted objects?
The overall performance of the solver depends of many basic operations such as the handling of
3D textures, and the handling and execution of the various steps in the solver as well as the overall
C’Nedra game engine. To test all operations explicitly would be an enormous task, and unnecessary.
It should be noted that all images displayed are given after a certain timeframe with one second
being the most frequent time slice.
7.2 Test Scenarios
7.2.1 Test 1: Advection of the Velocity Field
Advection is one of the most important features of fluid motion. Thus, it should be clear, that
when put in motion, e.g. by a vent force, the fluid advects accordingly.
To test the effect of the fluid advection it self, a scene is set up as shown in the images bellow.
Tests are run by only enabling velocity source, velocity advection and mass-conservation steps. To
get a clearer view of the advection, the velocity vector field is displayed. Only vectors with a
magnitude greater than some minimum are displayed to avoid a lot of small vectors disturbing the
picture. Vectors are colored with the color white.
When running the test scenario, velocities should advect from the centre of the simulation box
towards the facets of the simulation box and arrive simultaneously in all directions and be forced in
diagonal stream due to mass-conservation.
39
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
In the pictures bellow we see that the velocities do in fact advect towards the facets of the
simulation box and arrive simultaneously. When facets touch each other, the incompressibility
forces the fluid outwards in diagonal streams as expected.
The streams are not perfectly symmetric however, which may be due to some type of calculation
error.
Figure 32: Advection of the velocity field
t=0
t=1s
t=2s
t=3s
t=4s
t=5s
t=6s
t=7s
t=8s
40
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
7.2.2 Test 2: Advection of the Density Field
This test investigates the ability of another field to advect freely along the velocity field. For this test
the setup shown in the figures presented bellow. This test is run with the following steps enabled:
velocity source, velocity advection, density source, and density advection.
The result should be velocity vectors (white) moving through the density field (yellow) in the
simulation box. The velocity force is applied in one end of a rectangular box and the results shows
the velocity vectors propagating causing the density field to advect.
Figure 33: Advection of the density field
t=0
t=1s
t=2s
t=3s
t=4s
t=5s
t=6s
t=7s
t=8s
41
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
7.2.3 Test 3: Thermal Buoyancy
Differences in temperature should give rise to according forces: Heat should cause smoke to rise,
and cold should cause smoke to fall down.
Test 3a. Heat Source
Here the velocity source step is disabled in order to disable the vent force and enable the
temperature source and thermal buoyancy steps. Herby a hot temperature source is inserted that
should cause the density to rise.
Figure 34: Hot smoke rising with all steps in the algorithm enabled
t=0
t=1s
t=2s
t=3s
t=4s
t=5s
t=6
t=7s
t=8s
42
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
t=9
t=10s
t=11s
As can be inferred from the pictures the smoke does in fact rise in a realistic smoke like behavior.
Test 3b. Cold Source
In this test the smoke is turned upside down. Density and a cold source are inserted in the top of
the simulation box. The enabled steps are: velocity advection, density source, density advection
temperature source, and thermal buoyancy. When running this test, the density should stream
downward, hit the ground and stream outward and up the sides of the simulation box.
Figure 35: Cold smoke falling and ring up the sides of the simulation box
t=0
t=1s
t=2s
t=3s
t=4s
t=5s
43
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
t=6
t=9
t=7s
t=8s
t=10s
t=11s
As can be seen in the pictures the smoke does in fact fall down and stream upward the sides of the
simulation box implying smoke like behavior that follows the properties of buoyancy.
7.2.4 Test 4: Vorticity Confinement
These tests aim to investigate the effect of adding vorticity confinement to the simulation. As was
described in previous chapters vorticity confinement improves the numerical solution of the
Navier-Stokes equations by adding turbulence back.
Test 4a. Vorticity Confinement Disabled
This simulation is run without vorticity confinement showing smoke rising without turbulence
decreasing the realism of the simulation. The smoke more looks like a beam than realistic smoke.
Figure 36: Smoke rising with vorticity confinement disabled
t=0
t=1s
44
t=2s
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
t=3s
t=4s
t=5s
t=6
t=7s
t=8s
t=10s
t=11s
t=9
Test 4b. Vorticity Confinement Enabled
Now the same simulation as 4a is run but with vortcity confinement enabled, which should cause
the rising smoke to be more disturbed, and thus, more smoke-like than the smooth streams of
previous tests.
45
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Figure 37: Smoke rising with vorticity confinement enabled
t=0
t=1s
t=2s
t=3s
t=4s
t=5s
t=6
t=7s
t=8s
t=9
t=10s
t=11s
The pictures show that swirls are added to the smoke stream, and the stream is widened on its way
to the top of the box. Hence the simulation looks much more realistic with turbulence. One can
conclude that vorticity confinement does add the effect expected and creates realistic smoke like
behavior.
46
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
7.2.5 Test 5: Colored Density
By changing the RGB values of the smoke we can achieve smoke with various colors and alpha
components. Bellow I present red smoke:
Figure 38: Red hot smoke rising
t=0
t=1s
t=2s
t=3s
t=4s
t=5s
t=6
t=9
t=7s
t=10s
47
t=8s
t=11s
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Hence by showing that one can change the color of the smoke as well as the alpha component one
can achieve various results suitable for various simulated environments. This increases the flexibility
in creating realistic simulations.
7.2.6 Test 6: Boundaries
Seeing as the handling of internal boundaries in the solver is very straight forward, these tests
should be seen as a clarification of its capabilities.
I introduce a simple, solid object into the fluid. The setup is shown in the starting image of the
simulation. All the solver steps are enabled.
Test 6a. Object submerged in smoke
In this simulation a simple, solid object is introduced into the fluid. The setup is show in the
pictures bellow. The smoke should advect upwards until reaching the object. It should then curl
around the object, and form a wider, less dense stream above the object.
Figure 39: Red smoke with object boundary
t=0s
t=1s
t=2s
t=3s
t=4s
t=5s
t=6s
t=7s
t=8s
48
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
t=9
t=10s
t=11s
From the results of the test shown in the figure, we see that the simple method actually works very
well with a simple object. The smoke rises with the object, it is forced around the object, and
continues upwards with a curling behaviour.
Test 6b. Burning object
We now turn to setting an object on fire. The approach is analogue to simulating smoke; however
here a temperature gradient is added and advected in the form of texture. This feature creates a fire
like behavior with the same properties as the smoke with regards to objects. Hence the following
simulation is possible:
Figure 40: Single burning object
t=0
t=1s
t=2s
t=3
t=4s
t=5s
49
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
t=6s
t=9
t=7s
t=8s
t=10s
t=11s
The images show how the object slowly turns on fire by overheating and then bursting into fire.
Seeing as an object that is burning actually is turned into a gas the simulation becomes quite
realistic. In terms of efficiency it runs on the same level as the smoke simulation. One drawback of
the simulation is that the grid size implemented only allows for a certain size of the object. Hence
in order to create large scale fires one would need a large grid which is not feasible due to the need
of high performance in 3D game engines.
7.2.7 Test 7: Exploding Object
This simulation intends to display the capabilities of the fluid solver in creating other effect by
interacting with the fluid with the aim of displaying explosions. A burning object is thus expanded
and then eliminated creating the illusion of an explosion.
Figure 41: Exploding object
t=0
t=1s
50
t=2s
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
t=3s
t=4s
t=5s
t=6
t=7s
t=8s
t=9
t=10s
t=11s
This efficiency of the simulation is similar to that of the other simulations. By turning an object on
fire, expanding and then rapidly disabling it, a mushroom like cloud is created. This shows the
versatility of the algorithm making it useful for in more applications.
7.2.8 Test 8: Time & Gridsize
By having shown that the implementation can in fact produce quite realistic effect we turn to
performance. The first test to measure performance is to measure the frame rate on varying grid
sizes.
The obtainable frame rate is very dependent of the size of the grid – a larger grid yields a lower
frame rate. These tests are meant to clarify the relation between the size of a grid and the fame rate
of the simulation with that grid. The graph bellow summarized the results yielded:
51
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Figure 42: Showing how frame rate changes with grid size
70
60
Frames/second
50
40
30
20
10
0
4x4x4
8x8x8
16x16x16
32x32x32
64x64x64
60,121
50,349
11,976
1,449
0
Grid size
The simulation clearly shows that the solver is dependent on the size of the grid; the smaller the
grid volume the better frame rate for the simulation. For a simulation to be minimal useful the
quality of a 16x16x16 grid size is need with gives us only 12-14 frames per second. Increasing the
grid size gives catastrophic results. These results prove that the implementation is not efficient in
the plug-in setting of the C’Nedra game engine.
In the following tests I check for parameters that might improve the performances of the
implementation.
7.2.9 Test 9: Number of Iterations in the Pressure Solver
Figure 43: Displays how frame rate changes with the number of iterations
16
14
Frames/second
12
10
8
6
4
2
200
190
180
170
160
150
140
130
120
110
90
100
80
70
60
50
40
30
20
10
1
0
Number of Iterations
By increasing the number of iterations in the pressure solver we see that the frame rate falls. What
is interesting is that the quality of the fluid animation does not seem to be affected with the number
of iterations in the pressure solver.
52
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
7.2.10 Test 10: Time and Stability
In all previous tests the time step has been fixed to 0.01 corresponding to 13-14 frames per second.
In this section experiments are made with different time steps to explore the stability of the solver
when using the time steps as a variable. The results are presented in the graph bellow:
Figure 44: Showing how the frame rate changes with time steps
14
13,5
Frames/second
13
12,5
12
11,5
11
10,5
0,00001 0,0001 0,001
0,01
0,1
1
10
100
1000
10000 100000
dt
From the graph one can infer that there does not seem to be any clear correlation between frame
rates and time steps. The graphics quality of the simulation was negligibly affected. Hence we
conclude that decreasing the number of iterations does only marginally increase frame rate.
7.2.11 Test 11: Texture Precision
In this test we will run the same simulation as before but with different texture map precision to get
a feeling of how much influence the frame rate and graphics quality. From the results summarized
in the graph bellow we see that when increasing the bit quality of the textures the frame rate falls
heavily. Hence one can conclude that lowering the texture precision does only marginally improve
the frame rate.
Figure 45: Frame rate as a function of texture precision
16
14
Frames/second
12
10
8
6
4
2
0
8-bit
16-bit
32-bit
14,392
10,121
8,432
Texture precision
53
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
7.2.12 Test 12: Multiple Instances
These tests are designed to test the efficiency of running multiple instances of fires, burning objects
and smoke on the same time.
Test 12a. Simultaneously burning fires
We first simulate two burning fires. When running the simulation it becomes clear that on average
it runs with half the speed of only running one instance. The realism is quite good and the reader
can observe burning fires, burning objects as well as simulteanous smoke in the following images.
Figure 46: Simultaneously burning fires
t=0
t=2s
t=4s
t=6
t=8s
t=10s
t=12
t=14s
t=16s
54
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
t=18
t=20s
t=22s
t=2s
t=4s
Test 12b. Simultaneously burning objects
Figure 47: Simultaneously igniting and burning objects
t=0
t=6
t=8s
t=10s
t=12
t=14s
t=16s
55
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
t=18
t=20s
t=22s
t=0
t=2s
t=4s
t=6
t=8s
t=10s
Test 12c. Simultaneous black smoke
Figure 48: Simultaneous black hot smoke rising
56
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
t=12
t=14s
t=16s
t=18
t=20s
t=22s
Hence we conclude that due to the poor performance of the simulation it is difficult to run this
implementation of fluid dynamics in a computer game. A computer game would need the
possibility of many multiple fires and smoke in order to for example simulate a battle field. In terms
of realism the implementation has positive results but in terms of performance the implementation
has unfavorable results.
57
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
7.3 Summary of Results
The table bellow summarizes the main results found when conducting the simulations showing that
the C’Nedra game engine is not a good platform to implement the Stam fluid algorithm.
Figure 49: A summary of the results
Realism
ƒ
Advection works.
ƒ
Vorticity confinement works.
ƒ
Thermal buoyancy works.
ƒ
Temperature gradient works making it possible to simulate fire.
ƒ
Pigmentation and translucency is possible.
ƒ
Boundaries work (object submerged in smoke and objects burning).
Performance
ƒ
On a 16x16x16 grid the simulation has only 12 frames/second showing that only very
small grid sizes are possible.
ƒ
Decreasing the number of iterations in the pressure solver only marginally improves frame
rate.
ƒ
Frame rate only increases marginally with lower texture precision.
ƒ
Multiple instances run extremely slowly.
With regards to the quality of the simulation one can without performing any in depth tests infer
that the smoke and fire like behavior is satisfactory.
The reason for the mediocre performances may be that the algorithm is difficult to implement
correctly in general. Seeing as the algorithm has been used in real-time games this should not be the
case. Instead, I infer that the experimental structure of C’Nedra makes the interaction of the
algorithm in the form of a plug-in extremely slow.
Another reason for low performance may be due to having chosen to solve the algorithm on a
rectangular grid. Today, there are newer implementations that have tried to solve the algorithm on
other data structures such as octrees. This might give better performance. With regards to the
quality of the simulation one can without performing any in depth tests infer that the smoke and
fire behavior is satisfactory.
One way of testing which of the above causes have the largest impact on the simulation would be
to make a simple implementation of the algorithm in a lean-and-mean standalone graphics
application on various grids and measure the performance. Due to time constraints this was
deemed to be out of the scope for this thesis.
58
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
8 Conclusions
Chapter 8 discusses the results and draws conclusions from the work carried out on the game engine, the
CFD solver implemented and the scenarios tested.
I will start this chapter by returning to the first chapter and my posed problem statement:
Can realistic fluid dynamics be run efficiently in the C’Nedra game engine?
Well, after having acquired substantial knowledge of how to develop software with the C’Nedra
toolkit and its overall performance as well as run the various simulations, I conclude that it is not
advised to use C’Nedra as a platform for CFD development.
I conclude this on the overall difficulty in implementing plug-ins in the engine and the performance
yielded from the simulations. The game engine in its current form is highly unstable and lacks
pertinent documentation.
The temptation of creating a game engine from scratch is time consuming and hence it would be
more beneficial to use one of the more robust and established ones either open source or
commercial. Having tried some existing established game engines during due course of the project
in educational purpose such as Ogre and Torque as explained in the first chapter, I would
recommend any of these engines both in a commercial and educational objective, seeing as they
contain a tremendous amount of advanced functionalities already. It is therefore straightforward to
extend these as they come with documentation and well documented source code. Both engines are
highly robust and are being used in commercial applications.
8.1 Possible improvements in C’Nedra
Figure 50: A summary of possible improvements in C’Nedra
ƒ
Skeletal body support.
ƒ
Artificial Intelligence support.
ƒ
Improved terrain engine with artificially generated terrain.
ƒ
Additional special effects such as water effects, lens flares, etc.
ƒ
Improved performance and error handling.
ƒ
Vertex shader support
59
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
8.2 Possible improvement of fluid dynamics in
C’Nedra
In many aspects the C’Nedra engine is outdated as to regards to performance seeing as there or
more competitive open source engines out there such as Ogre or price worthy commercial ones
such as Torque it would be of interest to move to these platform for Ecole Centrale Paris and
continue development to continue development and testing of CFD.
For static effects we could animate the fluid effect in Maya and then import it into the game engine
making the costly real-time calculations of solving the Navier-Stokes eliminated to the cost of
running the animation. This takes away the ability for the user to interact with the fluid in real-time.
In this last section I summarize some of the possible improvements to the implemented special
effects plug-in.
Figure 51: A summary of possible improvements to C’Nedra pertaining to fluid dynamics
ƒ
Implementing and solving the fluid algorithm of Navier-Stokes on various other grids such
as for example octrees.
ƒ
Implementing other fluid effects with Navier-Stokes such as water effects.
ƒ
Trying other approaches of simulating fluid effects such as for example particle systems.
ƒ
Implementing a lean-and-mean version of the algorithm in a standalone graphics
application.
60
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
9 Critique
In this last chapter I criticise the work performed as well as the results achieved. I also talk about the fast
development in the field of Computational Fluid Dynamics and game engine design.
9.1 Problems Experienced
The project work was carried out in a timely fashion; however due to personal high set goals on
further developing the 3D game engine upon returning from France and pursuing studies at
Stockholm School of Economics delayed this written report. Finally, due to the passing of my
mother I had to take time in order to sort out personal issues. Hence, the finalization of this project
could have been carried out faster and more in line with the project planning.
9.2 Field Developing Fast
Seeing as the field computer graphics is very fast moving, the current standards have changed a lot,
even in the rather short duration of this project. Thus, elements of this report may already be
outdated at the time it is turned in. When reading, it should be kept in mind that this report only
reflects a snapshot of the available methods and features, at the time of writing. During my work
with this project, others have published material on the same subject, some too late for me to take
their work into account and appreciation. As a result of this, related or even duplicate work may
exist, which have not been considered in the analysis. It is my conviction, however, that this report
is still legitimate as an introductory text on the subject, and show legitimate results.
61
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
10 Literature
10.1 CFD literature
[1] Chen, J. and Lobo, N., “Toward Interactive-Rate Simulation of Fluids with Moving Obstacles Using
Navier-Stokes Equations”. Graphical Models and Image Processing, 57(2), 1995, pp. 107-116.
[2] Ebert, D. S. and Parent, R. E. “Rendering and Animation of Gaseous Phenomena by Combining Fast
Volume and Scanline A-buffer Techniques”. Computer Graphics (SIGGRAPH 90 Conference
Proceedings), 24(4):357366, August 1990.
[3] Fedkiw, R., Stam, J. and Wann Jensen, H., "Visual Simulation of Smoke", In SIGGRAPH 2001
Conference Proceedings, Annual Conference Series, August 2001, 1-8.
[4] Foster N. and Fedkiw, R., “Practical Animation of Liquids”, SIGGRAPH 2001 (in press).
[5] Foster, N. and Metaxas, D., “Modeling the Motion of Hot, Turbulent Gas”, Proceedings of
SIGGRAPH '97.
[6] Foster, N. and Metaxas, D., “Controlling Fluid Animation”, Proceedings CGI '97, pp. 178-188.
[7] Foster, N. and Metaxas, D., “Realistic Animation of Liquids”, Proceedings GI '96, pp. 204-212.
[8] Gardner, “Visual Simulation of Clouds”. Computer Graphics (SIGGRAPH 85 Conference
Proceedings), 19(3):297384, July 1985.
[9] Guendelman et al. “Coupling Water and Smoke to Thin Deformable and Rigid Shell”, ACM
SIGGRAPH 2005, ACM TOG 24, Pages 973-981.
[10] Johanson, C. “Real-time water rendering – Introducing the projected grid concept”, Lund University 2004.
[11] Kass, M. and Miller, G., “Rapid, Stable Fluid Dynamics for Computer Graphics”. ACM Computer
Graphics (SIGGRAPH '90), 24(4):4957, August 1990.
[12] Losasso et al., "Simulating Water and Smoke With an Octree Data Struture ", In SIGGRAPH 2004
Conference Proceedings, Annual Conference Series, August 2001, 1-8. ACM TOG 23, pages 457462.
[13] O'Brien, J. F. and Hodgins, J. K., “Dynamic Simulation of Splashing Fluids.” Proceedings of
62
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Computer Animation `95, Geneva Switzerland, April 19-21, pp. 198-205.
[14] Reeves, W. T., “Particle Systems. A Technique for Modelling a Class of Fuzzy Objects”. ACM
Computer Graphics (SIGGRAPH '83), 17(3):359376, July 1983.
[15] Stam, J., “Stable Fluids”, In SIGGRAPH 99 Conference Proceedings, Annual Conference
Series, August 1999, 121-128.
[16] Stam, J., “A General Animation Framework for Gaseous Phenomena”. ERCIM Research Report,
R047, January 1997.
[17] Stam, J. and Fiume, E., “Turbulent Wind Fields for Gaseous Phenomena”, In SIGGRAPH 93
Conference Proceedings, Annual Conference Series, August 1993, 369-376.
[18] Stam, J. and Fiume, E., "Depicting Fire and Other Gaseous Phenomena Using Diffusion Processes". In
Proceedings of SIGGRAPH ’95, pages 129136. Addison-Wesley Publishing Company, August
1995.
[19] Selle et al. “A Vortex Particel Method for Smoke, Water and Explosions”, ACM SIGGRAPH 2005,
ACM TOG 24, Pages 973-981.
[20] Stang, B. “Game Engines Features and possibilities”, IMM DTU 2003.
[21] Y. Dobashi, K. Kaneda, T. Okita, and T. Nishita. ”A Simple, Efficient Method for Realistic
Animation of Clouds”. In SIGGRAPH 2000 Conference Proceedings, Annual Conference Series,
pages 1928, July 2000.
10.2 Textbooks
[22] Angel E. 2001.Computer graphics, a top down approach. Prentice Hall. ISBN 123456789.
[23] Candel, S., 1995. Mécanique des fluides, DUNOD, ISBN 2-10-001136-7.
[24] Dalmau S. 2003. Core Techniques and Algorithms. New Riders Publishing. ISBN 0-1310-2009 9.
[25] Eberly, D. “3D Game Engine Design”. Academic Press, 2001. ISBN 1558605932.
[26] Millington, I. “Artificial Intelligence for Games”. Morgan Kaufman. ISBN 0129977820.
63
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
10.3 Internet sources
[27] Microsoft Direct X (www.microsoft.com/windows/directx/default.aspx)
[28] OpenAl (www.openal.org)
[29] OpenGl (www.opengl.org)
[30] Tokamak (www.tokamakphysics.com/)
64
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Appendix 1: Notation
Mathematics plays an important role in the simulation of fluid dynamics. In the following section, I
introduce the notation used in this report. Also, I introduce some mathematical concepts, which are
used extensively throughout the report.
Vectors and Vector Fields
r
I denote vectors with small caps with an arrow above, e.g. v . Similarly, vector fields will be written
r
in small caps with an arrow above, e.g. v (x ) . When nothing else is mentioned, vectors are assumed
r
three-dimensional, i.e. v ∈ ℜ3 , and vector fields are assumed to functions
r
v ( x ) : ℜ3 → ℜ3 . Vectors and vector fields will sometimes be written component wise. In this case
we will use the notations:
being
T
r
v = (v x , v y , v z ) , v x , v y , v z ∈ ℜ,
T
r
v ( x ) = (v x ( x ), v y ( x ), v y ( x ) ) , v x ( x ), v y ( x ), v y ( x ) ∈ ℜ
x ∈ ℜ3 .
The Gradient Operator
The equations of fluid motion are highly dependent on the gradient operator, ∇ (nabla), defined
by
T
⎛ ∂ ∂ ∂⎞
∇ = ⎜⎜ , , ⎟⎟ .
⎝ ∂x ∂ y ∂ z ⎠
For a scalar field s ( x ) I define the gradient of the scalar field:
T
⎛ ∂( x ) ∂( x ) ∂( x ) ⎞
,
,
∇s ( x ) = ⎜⎜
⎟ ,
∂y
∂z ⎟⎠
⎝ ∂x
x ∈ ℜ3 ,
r
For the vector field v ( x ) I define the divergence of the vector field:
r
∂v x ( x ) ∂v y ( x ) ∂v z ( x )
∇ ⋅ v ( x) =
+
+
,
∂x
∂y
∂z
x ∈ ℜ3 ,
And the curl of the vector field
⎛ ∂v x ( x )
⎜
⎜ ∂y
⎜ ∂v x ( x )
∇ × v( x ) = ⎜
⎜ ∂y z
⎜ ∂v ( x )
⎜ ∂x
⎝
−
−
−
r
For a vector field v ( x ) I use the notation:
65
∂v y ( x ) ⎞
⎟
∂z ⎟
∂v x ( x ) ⎟
⎟,
∂x ⎟
∂v x ( x ) ⎟
∂y ⎟⎠
x ∈ ℜ3 .
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
⎛ ∂ 2v x ( x)
⎜
2
⎜ ∂x
⎜ ∂ 2 v y ( x)
r
∇ ⋅ (∇v ( x ) ) = ⎜
2
⎜ 2∂xz
⎜ ∂ v ( x)
⎜ ∂x 2
⎝
r
∂ 2 v x ( x)
+
∂y 2
∂ 2 v y ( x)
+
+
∂y 2
∂ 2v z ( x)
+
+
∂y 2
+
∂ 2 v x ( x) ⎞
⎟
∂z 2 ⎟
∂ 2v y ( x) ⎟
⎟,
∂z 2 ⎟
∂ 2v z ( x) ⎟
∂z 2 ⎟⎠
x ∈ ℜ3 ,
r
And for vector fields v (x ) and w(x ) I use the notation:
⎛ x
∂w x ( x )
⎜ v ( x)
∂x
⎜
y
⎜
(vr ( x ) ⋅ ∇ )wr = ⎜ v x ( x ) ∂w ( x )
∂x
⎜
z
⎜ v x ( x ) ∂w ( x )
⎜
∂x
⎝
∂w x ( x ) ⎞
∂w x ( x )
⎟
+ v z ( x)
∂z 2 ⎟
∂y
∂w y ( x ) ⎟
∂w y ( x )
+ v z ( x)
+ v y ( x)
⎟,
∂z 2 ⎟
∂y
∂w z ( x ) ⎟
∂w z ( x )
+ v z ( x)
+ v y ( x)
∂z 2 ⎟⎠
∂y
+ v y ( x)
Which finally gives us the laplacian:
∇ ⋅ ∇ = ∇2 .
66
x ∈ ℜ3 ,
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Appendix 2: C’Nedra XML file
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes" ?>
- <Configuration>
- <I_MsgHandler>
<speed movement="6" rotation="5" jump="15" />
<movement_type name="fly" />
<mouse enabled="1" sensitivity="0.3" />
</I_MsgHandler>
<Timer name="GlobalTimer" />
- <I_3D>
<I_Window ref="CNedraWindow" />
<landscape texture="dat/terrain.png" texture_details="dat/terrain.png" step="64" detail_tex_paramX="0.01"
detail_tex_paramZ="0.01" />
<sky top="dat/sky.png" bottom="dat/sky.png" face1="dat/sky.png" face2="dat/sky.png" face3="dat/sky.png"
face4="dat/sky.png" distance="4000" />
<light id="0" positional="0" x="0" y="0.8" z="1" shininess="1" specular_r="0" specular_g="0" specular_b="0" specular_a="1"
diffuse_r="1" diffuse_g="1" diffuse_b="1" diffuse_a="1" ambient_r="0" ambient_g="0" ambient_b="0" ambient_a="1" />
<light id="1" positional="1" x="0" y="100" z="0" shininess="1" specular_r="0" specular_g="0" specular_b="0" specular_a="1"
diffuse_r="1" diffuse_g="1" diffuse_b="1" diffuse_a="1" ambient_r="1" ambient_g="0" ambient_b="0" ambient_a="1" />
- <object_description>
<eglise type="3ds" />
<player type="3ds" />
<balle type="3ds" />
<tank type="3ds" />
</object_description>
</I_3D>
- <descent load="true" type="singleplayer" frame_time="20">
<Timer ref="GlobalTimer" />
<I_Window ref="CNedraWindow" />
- <I_Fps>
<I_Window ref="CNedraWindow" />
<Timer ref="GlobalTimer" />
</I_Fps>
- <I_Sound NbBuffers="3" BufferSizeMilliSec="100000">
<Timer ref="GlobalTimer" />
</I_Sound>
- <Sounds>
<Cathedrale sound="dat/sounds/collision-cathedrale-1.wav" />
<Cathedrale sound="dat/sounds/collision-cathedrale-2.wav" />
<ShootBall sound="dat/sounds/rocket.wav" />
<OnQ sound="dat/sounds/touche-q-1.wav" />
<OnQ sound="dat/sounds/touche-q-2.wav" />
</Sounds>
</descent>
- <I_World viscosity="0.3" airviscosity="0.005" gravity="0.4" gravitation_constant="0" maxspeed="2000">
<landscape heightmap="dat/hmap.bmp" sizeX="2000" sizeZ="2000" />
<player x="0" y="100" z="400" theta="0" mass="100" HP="100" />
<balle mass="5" timer="50" damage="20" />
<object type="tank" x="0" y="500" z="0" mass="100" />
67
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
<object type="tank" x="1500" y="500" z="0" mass="100" />
<object type="eglise" x="0" y="20" z="-1500" theta="-90" static="1" />
</I_World>
</Configuration>
68
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
Appendix 3: CFD Solver Code
/* This codes extends Stam’s algorithm which is copyright and patented
by Alias. Hence this extension should only be used for academic
research and not for commercial applications. */
#include "CFD_Cnedra.h"
#include "CFD_Cnedra_utils.h"
#include "perlin.h"
#include <stdlib.h>
#include <math.h>
#include
#include
#include
#include
#include
<windows.h>
<GL/gl.h>
<GL/glu.h>
"glext.h"
<math.h>
#define I(i,j,k) ((i) + ((NX)+2)*(j) + ((NX)+2)*((NY)+2)*(k))
#define FOR_EACH_CELL for(i=1; i<=NX; ++i) { for(j=1; j<=NY; ++j) {
for(k=1; k<=NZ; ++k) {
#define END_FOR }}}
#define MAX_ITER 5
#define INFLOW_PAUSE 100
extern int CFD_showFieldId;
extern bool CFD_useObstacles;
extern float CFD_obstX, CFD_obstY, CFD_obstZ, CFD_obstR;
static float dt = 0.001;
static const float INFLOW_VEL =1.0f;
static float CFD_vortConf=3.0f, CFD_buoy=0.3f;
float CFD_airT=1.0f, CFD_smokeT=300.0f, CFD_coolConst=1000.0f; //1000
int i,j,k;
float x,y,z;
CFD_Cnedra::CFD_Cnedra() : NX(CELLS_IN_X), NY(CELLS_IN_Y),
NZ(CELLS_IN_Z), eR(2.5f), h(1.0f) {
p1x=(NX+2)/2; p0x=-p1x; p1y=(NY+2)/2; p0y=-p1y; p1z=(NZ+2)/2;
p0z=-p1z;
size=(NX+2)*(NY+2)*(NZ+2); fDens=1.0f; fVsc=0.0f;
fU0 = new float[size]; fV0 = new float[size]; fW0 = new float[size];
fU1 = new float[size]; fV1 = new float[size]; fW1 = new float[size];
fDiv = new float[size]; fP = new float[size];
CU = new float[size]; CV = new float[size]; CW = new float[size];
D0 = new float[size]; D1 = new float[size];
T0 = new float[size]; T1 = new float[size];
BU = new float[size]; M = new int[size];
N2D_B = new float[NX*NZ*3];
memset(fU0,0,size*sizeof(float)); memset(fV0,0,size*sizeof(float));
memset(fW0,0,size*sizeof(float));
memset(fU1,0,size*sizeof(float)); memset(fV1,0,size*sizeof(float));
memset(fW1,0,size*sizeof(float));
memset(fDiv,0,size*sizeof(float)); memset(fP,0,size*sizeof(float));
memset(CU,0,size*sizeof(float)); memset(CV,0,size*sizeof(float));
memset(CW,0,size*sizeof(float));
memset(D0,0,size*sizeof(float)); memset(D1,0,size*sizeof(float));
memset(T0,0,size*sizeof(float)); memset(T1,0,size*sizeof(float));
memset(BU,0,size*sizeof(float)); memset(M,0,size*sizeof(int));
69
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
if (CFD_useObstacles==true) {
FOR_EACH_CELL
x=(float)(i-p1x)-CFD_obstX; y=(float)(j-p1y)-CFD_obstY;
z=(float)(k-p1z)-CFD_obstZ;
if((x-1)*(x-1) + (y+(CELLS_IN_Y/4))*(y+(CELLS_IN_Y/4)) + z*z <
CFD_obstR*CFD_obstR) { M[I(i,j,k)]=1; }
END_FOR
}
}
CFD_Cnedra::~CFD_Cnedra() {
delete [] fU0; delete [] fV0; delete [] fW0;
delete [] fU1; delete [] fV1; delete [] fW1;
delete [] fDiv; delete [] fP; delete [] CU; delete [] CV; delete []
CW;
delete [] D0; delete [] D1; delete [] T0; delete [] T1; delete []
BU; delete [] M;
delete [] N2D_B;
}
void CFD_Cnedra::addForce(float* u0, float* v0, float* w0, float* su,
float* sv, float* sw) {
for(int i=0; i<size; ++i) { u0[i]+=dt*su[i]; v0[i]+=dt*sv[i];
w0[i]+=dt*sw[i]; }
}
void CFD_Cnedra::diffuse(float vsc, float* a0, float* a1) {
float _sum,_invA=1.0f/(dt*6.0f+1); setBnd(a1);
FOR_EACH_CELL
_sum=a1[I(i-1,j,k)]+a1[I(i+1,j,k)]+a1[I(i,j1,k)]+a1[I(i,j+1,k)]+a1[I(i,j,k-1)]+a1[I(i,j,k+1)];
a0[I(i,j,k)] = a1[I(i,j,k)] + dt*vsc * (_sum - a1[I(i,j,k)]*6);
END_FOR
setBnd(a0);
}
void CFD_Cnedra::advect(float* a0, float* a1, float* u, float* v,
float* w) {
int x0,x1, y0,y1, z0,z1;
FOR_EACH_CELL
x=i-(dt*u[I(i,j,k)]); y=j-(dt*v[I(i,j,k)]); z=k(dt*w[I(i,j,k)]); // 3
if(x<0.5f) {x=0.5f;} if(x>NX+0.5f) {x=NX+0.5f;}
x0=(int)x;
x1=x0+1; // 4
if(y<0.5f) {y=0.5f;} if(y>NY+0.5f) {y=NY+0.5f;}
y0=(int)y;
y1=y0+1; // 4
if(z<0.5f) {z=0.5f;} if(z>NZ+0.5f) {z=NZ+0.5f;}
z0=(int)z;
z1=z0+1; // 4
a0[I(i,j,k)]=trilerp(a1[I(x0,y0,z0)],a1[I(x1,y0,z0)],a1[I(x0,y1,z0)],a
1[I(x1,y1,z0)],
a1[I(x0,y0,z1)],a1[I(x1,y0,z1)],a1[I(x0,y1,z1)],a1[I(x1,y1,z1)],
x-x0, y-y0, z-z0);
END_FOR
}
void CFD_Cnedra::project(float* u0, float* u1, float* v0, float* v1,
float* w0, float* w1,
float* div, float* p, float matDens) {
FOR_EACH_CELL
70
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
div[I(i,j,k)] = ((u1[I(i+1,j,k)]-u1[I(i-1,j,k)])
+ (v1[I(i,j+1,k)]-v1[I(i,j-1,k)])
+ (w1[I(i,j,k+1)]-w1[I(i,j,k-1)])) * 0.5f;
p[I(i,j,k)]
= 0.0f;
END_FOR
setBnd(div); setBnd(p);
int _cf=6; float lhs;
for (int l=0; l<MAX_ITER; ++l) {
FOR_EACH_CELL
if(CFD_useObstacles) {
int _L=1-M[I(i-1,j,k)]; int _R=1-M[I(i+1,j,k)]; int _B=1M[I(i,j-1,k)]; int _T=1-M[I(i,j+1,k)];
int _N=1-M[I(i,j,k-1)]; int _F=1-M[I(i,j,k+1)];
_cf=(_L+_R)+(_B+_T)+(_N+_F);
lhs=_L*p[I(i-1,j,k)]+_R*p[I(i+1,j,k)]+_B*p[I(i,j1,k)]+_T*p[I(i,j+1,k)]+_N*p[I(i,j,k-1)]+_F*p[I(i,j,k+1)];
} else { lhs=p[I(i-1,j,k)]+p[I(i+1,j,k)]+p[I(i,j1,k)]+p[I(i,j+1,k)]+p[I(i,j,k-1)]+p[I(i,j,k+1)];}
if(_cf!=0) {p[I(i,j,k)]=(lhs-(div[I(i,j,k)]/dt))/_cf;}
END_FOR setBnd(p);
}
FOR_EACH_CELL
u0[I(i,j,k)] = u1[I(i,j,k)] dt*(((p[I(i+1,j,k)]-p[I(i-1,j,k)])*0.5f));
v0[I(i,j,k)] = v1[I(i,j,k)] dt*(((p[I(i,j+1,k)]-p[I(i,j-1,k)])*0.5f));
w0[I(i,j,k)] = w1[I(i,j,k)] - dt*(((p[I(i,j,k+1)]-p[I(i,j,k1)])*0.5f));
END_FOR
setBnd(u0); setBnd(v0); setBnd(w0);
}
void CFD_Cnedra::setBnd(float *f) {
for(i=1; i<=NX; ++i) for(j=1; j<=NY; ++j) {
f[I(i,j,0)]
= f[I(i,j,1)];
f[I(i,j,NZ+1)] = f[I(i,j,NZ)];
}
for(j=1; j<=NY; ++j) for(k=1; k<=NZ; ++k) {
f[I(0,j,k)]
= f[I(1,j,k)];
f[I(NX+1,j,k)] = f[I(NX,j,k)];
}
for(i=1; i<=NX; ++i) for(k=1; k<=NZ; ++k) {
f[I(i,0,k)]
= f[I(i,1,k)];
f[I(i,NY+1,k)] = f[I(i,NY,k)];
}
for (i=1; i<=NX; ++i) {
f[I(i,0,0)]
= (f[I(i,1,0)] + f[I(i,0,1)]) * 0.5f;
f[I(i,NY+1,0)]
= (f[I(i,NY,0)] + f[I(i,NY+1,1)]) * 0.5f;
f[I(i,0,NZ+1)]
= (f[I(i,0,NZ)] + f[I(i,1,NZ+1)]) * 0.5f;
f[I(i,NY+1,NZ+1)] = (f[I(i,NY,NZ+1)] + f[I(i,NY+1,NZ)]) * 0.5f;
}
for (j=1; j<=NY; ++j) {
f[I(0,j,0)]
= (f[I(1,j,0)] + f[I(0,j,1)]) * 0.5f;
f[I(NX+1,j,0)]
= (f[I(NX,j,0)] + f[I(NX+1,j,1)]) * 0.5f;
f[I(0,j,NZ+1)]
= (f[I(0,j,NZ)] + f[I(1,j,NZ+1)]) * 0.5f;
f[I(NX+1,j,NZ+1)] = (f[I(NX,j,NZ+1)] + f[I(NX+1,j,NZ)]) * 0.5f;
}
for (k=1; k<=NZ; ++k) {
f[I(0,0,k)]
= (f[I(0,1,k)] + f[I(1,0,k)]) * 0.5f;
f[I(0,NY+1,k)]
= (f[I(0,NY,k)] + f[I(1,NY+1,k)]) * 0.5f;
f[I(NX+1,0,k)]
= (f[I(NX,0,k)] + f[I(NX+1,1,k)]) * 0.5f;
71
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
f[I(NX+1,NY+1,k)] = (f[I(NX+1,NY,k)] + f[I(NX,NY+1,k)]) * 0.5f;
}
f[I(0,0,0)]
= (f[I(1,0,0)] + f[I(0,1,0)] + f[I(0,0,1)]) *
0.3333333f;
f[I(NX+1,0,0)]
= (f[I(NX,0,0)] + f[I(NX+1,1,0)] +
f[I(NX+1,0,1)]) * 0.3333333f;
f[I(0,NY+1,0)]
= (f[I(1,NY+1,0)] + f[I(0,NY,0)] +
f[I(0,NY+1,1)]) * 0.3333333f;
f[I(0,0,NZ+1)]
= (f[I(1,0,NZ+1)] + f[I(0,1,NZ+1)] +
f[I(0,0,NZ)]) * 0.3333333f;
f[I(NX+1,NY+1,0)]
= (f[I(NX,NY+1,0)] + f[I(NX+1,NY,0)] +
f[I(NX+1,NY+1,1)]) * 0.3333333f;
f[I(0,NY+1,NZ+1)]
= (f[I(0,NY,NZ+1)] + f[I(0,NY+1,NZ)] +
f[I(1,NY+1,NZ+1)]) * 0.3333333f;
f[I(NX+1,0,NZ+1)]
= (f[I(NX,0,NZ+1)] + f[I(NX+1,0,NZ)] +
f[I(NX+1,1,NZ+1)]) * 0.3333333f;
f[I(NX+1,NY+1,NZ+1)] =
(f[I(NX,NY+1,NZ+1)]+f[I(NX+1,NY,NZ+1)]+f[I(NX+1,NY+1,NZ)]) *
0.3333333f;
}
void CFD_Cnedra::setInflow(float* fu0, float* fv0, float* fw0) {
this->genN2DMap(N2D_B,NX,NZ, 0.05f);
for(i=1;i<=NX;++i) for(k=1;k<=NZ;++k) {
x=(float)(i-p1x); z=(float)(k-p1z);
if((x*x + z*z)<eR*eR) {
fu0[I(i,1,k)] = (N2D_B[k*NX*3+i*3]) * INFLOW_VEL * 0.5f;
fv0[I(i,1,k)] = ((N2D_B[k*NX*3+i*3+1]+1.0f)*5.0f + INFLOW_VEL);
fw0[I(i,1,k)] = (N2D_B[k*NX*3+i*3+2]) * INFLOW_VEL * 0.5f;
}
}
memset(M,0,size*sizeof(int));
if (CFD_useObstacles==true) {
FOR_EACH_CELL
x=(float)(i-p1x)-CFD_obstX; y=(float)(j-p1y)-CFD_obstY;
z=(float)(k-p1z)-CFD_obstZ;
if((x-1)*(x-1) + (y+(CELLS_IN_Y/4))*(y+(CELLS_IN_Y/4)) + z*z <
CFD_obstR*CFD_obstR) { M[I(i,j,k)]=1; }
END_FOR
}
}
vec3 CFD_Cnedra::getVorticity(int i, int j, int k) {
float DwDy,DvDz,DuDz,DwDx,DvDx,DuDy;
DwDy=DvDz=DuDz=DwDx=DvDx=DuDy=0.0f;
DwDy = (fW0[I(i,j+1,k)]-fW0[I(i,j-1,k)])*0.5f;
DvDz = (fV0[I(i,j,k+1)]-fV0[I(i,j,k-1)])*0.5f;
DuDz = (fU0[I(i,j,k+1)]-fU0[I(i,j,k-1)])*0.5f;
DwDx = (fW0[I(i+1,j,k)]-fW0[I(i-1,j,k)])*0.5f;
DvDx = (fV0[I(i+1,j,k)]-fV0[I(i-1,j,k)])*0.5f;
DuDy = (fU0[I(i,j+1,k)]-fU0[I(i,j-1,k)])*0.5f;
return vec3(DwDy-DvDz, DuDz-DwDx, DvDx-DuDy);
}
inline float nrm1(const vec3 &v)
fabs(v.z));}
inline float nrm2(const vec3 &v)
v.z*v.z);}
{return (fabs(v.x) + fabs(v.y) +
{return sqrt(v.x*v.x + v.y*v.y +
void CFD_Cnedra::updateCurls(float *cu, float *cv, float *cw) {
72
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
memset(cu,0,size*sizeof(float)); memset(cv,0,size*sizeof(float));
memset(cw,0,size*sizeof(float));
float DoDx=0.0f,DoDy=0.0f,DoDz=0.0f,len,invL; vec3 _v;
FOR_EACH_CELL
if(i>=2 && i<=NX-2) DoDx=(nrm2(getVorticity(i+1,j,k))nrm2(getVorticity(i-1,j,k)))*0.5f;
if(j>=2 && j<=NY-2) DoDy=(nrm2(getVorticity(i,j+1,k))nrm2(getVorticity(i,j-1,k)))*0.5f;
if(k>=2 && k<=NZ-2) DoDz=(nrm2(getVorticity(i,j,k+1))nrm2(getVorticity(i,j,k-1)))*0.5f;
len = sqrt(DoDx*DoDx + DoDy*DoDy + DoDz*DoDz);
if(len>=C_EPS) {invL=1.0f/len;DoDx*=invL;DoDy*=invL;DoDz*=invL;}
else {DoDx=DoDy=DoDz=0.0f;}
_v=getVorticity(i,j,k);
cu[I(i,j,k)] = (DoDy*_v.z - _v.y*DoDz) * CFD_vortConf;
cv[I(i,j,k)] = (DoDz*_v.x - _v.z*DoDx) * CFD_vortConf;
cw[I(i,j,k)] = (DoDx*_v.y - _v.x*DoDy) * CFD_vortConf;
END_FOR
}
void CFD_Cnedra::updateDensity() {
for(i=1;i<=NX;++i) for(k=1;k<=NZ;++k) {
x=(float)(i-p1x); z=(float)(k-p1z);
if((x*x + z*z)<eR*eR) {D0[I(i,1,k)]=1.0f;}
}
FOR_EACH_CELL
if(CFD_useObstacles) { x=(i-p1x)-CFD_obstX; y=(j-p1y)-CFD_obstY;
z=(k-p1z)-CFD_obstZ;
if((x-1)*(x1)+(y+(CELLS_IN_Y/4))*(y+(CELLS_IN_Y/4))+z*z<CFD_obstR*CFD_obstR)
{D0[I(i,j,k)]=1.0f;}
}
END_FOR setBnd(D0);
swp(D0,D1); advect(D0,D1,fU0,fV0,fW0);
}
void CFD_Cnedra::updateVelocity() {
this->addExtForces();
if(CFD_useObstacles) { FOR_EACH_CELL
x=(i-p1x)-CFD_obstX; y=(j-p1y)-CFD_obstY; z=(k-p1z)-CFD_obstZ;
if((x-1)*(x1)+(y+(CELLS_IN_Y/4))*(y+(CELLS_IN_Y/4))+z*z<CFD_obstR*CFD_obstR) {
float _x=x-1; float _y=y+(CELLS_IN_Y/4); float _z=z;
float _l=sqrt(_x*_x + _y*_y + _z*_z); if(fabs(_l)<=C_EPS)
{_l=C_EPS*sgn(_l);}
float _invL=5.0f/_l;
fU0[I(i,j,k)]=_x*_invL; fV0[I(i,j,k)]=_y*_invL;
fW0[I(i,j,k)]=_z*_invL;
}
END_FOR }
if(fVsc >= C_EPS) {
swp(fU0,fU1); swp(fV0,fV1); swp(fW0,fW1);
diffuse(fVsc,fU0,fU1); diffuse(fVsc,fV0,fV1);
diffuse(fVsc,fW0,fW1);
swp(fU0,fU1);swp(fV0,fV1);swp(fW0,fW1);
project(fU0,fU1,fV0,fV1,fW0,fW1,fDiv,fP,fDens);
setObstacleBnd();
}
swp(fU0,fU1); swp(fV0,fV1); swp(fW0,fW1);
advect(fU0,fU1,fU1,fV1,fW1); advect(fV0,fV1,fU1,fV1,fW1);
advect(fW0,fW1,fU1,fV1,fW1);
73
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
setObstacleBnd();
swp(fU0,fU1);swp(fV0,fV1);swp(fW0,fW1);
project(fU0,fU1,fV0,fV1,fW0,fW1,fDiv,fP,fDens);
setObstacleBnd();
}
void CFD_Cnedra::updateTemperature() {
static float offset=0.0f; offset+=0.0025f;
for(i=1;i<=NX;++i) for(k=1;k<=NZ;++k) {
x=(float)(i-p1x); z=(float)(k-p1z);
float xSqr = x*x; float zSqr = z*z; float radiusSqr = eR*eR;
if(xSqr + zSqr < radiusSqr) {
if(xSqr + zSqr < radiusSqr*0.6f) {
int _x=(i+1)*(1.0f/NX)*2.0f;
int _y=(k+1)*(1.0f/NZ)*2.0f;
float val = PerlinNoise2D(_x+offset,_y+offset,1.5f,1.0f,4);
T0[I(i,1,k)] = (fabs(val)+0.95f) * CFD_smokeT*0.45f;
}
else { T0[I(i,1,k)] = CFD_smokeT*0.45f; }
}
}
FOR_EACH_CELL
if(CFD_useObstacles) { x=(i-p1x)-CFD_obstX; y=(j-p1y)-CFD_obstY;
z=(k-p1z)-CFD_obstZ;
if((x-1)*(x1)+(y+(CELLS_IN_Y/4))*(y+(CELLS_IN_Y/4))+z*z<CFD_obstR*CFD_obstR)
{T0[I(i,j,k)]=CFD_smokeT;}
}
END_FOR setBnd(T0);
swp(T0,T1); advect(T0,T1,fU0,fV0,fW0);
FOR_EACH_CELL
if(T0[I(i,j,k)]>CFD_airT)
T0[I(i,j,k)]-=CFD_coolConst*0.2f*pow((T0[I(i,j,k)]CFD_airT)/(CFD_smokeT-CFD_airT),5);
if(T0[I(i,j,k)]<(CFD_smokeT-CFD_airT)*0.1f)
T0[I(i,j,k)]*=0.75f;
END_FOR setBnd(T0);
}
void CFD_Cnedra::addExtForces() {
this->updateCurls(CU, CV, CW); addForce(fU0,fV0,fW0,CU,CV,CW);
FOR_EACH_CELL
float _t=T0[I(i,j,k)];
BU[I(i,j,k)]=CFD_buoy*(T0[I(i,j,k)]);
fV0[I(i,j,k)]+=dt*BU[I(i,j,k)];
END_FOR
}
void CFD_Cnedra::update() {
this->setInflow(fU0,fV0,fW0);
float _maxFVel=0.0f;
FOR_EACH_CELL
float _FVel = fabs(fU0[I(i,j,k)]) + fabs(fV0[I(i,j,k)]) +
fabs(fW0[I(i,j,k)]);
if(_maxFVel<_FVel) _maxFVel=_FVel;
END_FOR
dt = 1.0f/(_maxFVel+(0.5f+0.5f+0.5f));
this->updateVelocity(); this->updateDensity(); this>updateTemperature();
}
void CFD_Cnedra::render(bool doVolRend) {
74
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
glPushAttrib(GL_ALL_ATTRIB_BITS);
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_3D);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
if (!doVolRend) { float *_fU,*_fV,*_fW;
switch(CFD_showFieldId) {
case CM_SHOW_VEL_FIELD: _fU=fU0;_fV=fV0;_fW=fW0; break;
case CM_SHOW_VORT_FIELD: _fU=CU;_fV=CV;_fW=CW; break;
}
float dx,dy,dz; glLineWidth(2); glBegin(GL_LINES);
FOR_EACH_CELL
x=(float)(i-p1x); y=(float)(j-p1y); z=(float)(k-p1z);
dx=_fU[I(i,j,k)]; dy=_fV[I(i,j,k)]; dz=_fW[I(i,j,k)];
float len=(float)sqrt(dx*dx + dy*dy + dz*dz); if(len>1.0f)
{dx/=len;dy/=len;dz/=len;}
glColor3f(0,0,0);glVertex3f(x,y,z);glColor3f(0.5f,0.0f,len/INFLOW_VEL)
;glVertex3f(x+dx,y+dy,z+dz);
END_FOR glEnd();
glPointSize(4); glColor3f(0,1,1);
glBegin(GL_POINTS); FOR_EACH_CELL if(M[I(i,j,k)]==1) glVertex3i(ip1x,j-p1y,k-p1z); END_FOR glEnd();
}
glPopAttrib();
}
void CFD_Cnedra::setObstacleBnd() {
if (CFD_useObstacles) {
FOR_EACH_CELL
if (M[I(i,j,k)] == 1) { int _emptyNeighbors=0;
if (M[I(i-1,j,k)] == 0) { ++_emptyNeighbors;
fU0[I(i,j,k)]=-fU0[I(i-1,j,k)]; fV0[I(i,j,k)]=-fV0[I(i1,j,k)]; fW0[I(i,j,k)]=-fW0[I(i-1,j,k)];
}
else if (M[I(i+1,j,k)] == 0) { ++_emptyNeighbors;
fU0[I(i,j,k)]=-fU0[I(i+1,j,k)]; fV0[I(i,j,k)]=fV0[I(i+1,j,k)]; fW0[I(i,j,k)]=-fW0[I(i+1,j,k)];
}
if (M[I(i,j-1,k)] == 0) { ++_emptyNeighbors;
fU0[I(i,j,k)]=-fU0[I(i,j-1,k)]; fV0[I(i,j,k)]=-fV0[I(i,j1,k)]; fW0[I(i,j,k)]=-fW0[I(i,j-1,k)];
}
else if (M[I(i,j+1,k)] == 0) { ++_emptyNeighbors;
fU0[I(i,j,k)]=-fU0[I(i,j+1,k)]; fV0[I(i,j,k)]=fV0[I(i,j+1,k)]; fW0[I(i,j,k)]=-fW0[I(i,j+1,k)];
}
if (M[I(i,j,k-1)] == 0) { ++_emptyNeighbors;
fU0[I(i,j,k)]=-fU0[I(i,j,k-1)]; fV0[I(i,j,k)]=-fV0[I(i,j,k1)]; fW0[I(i,j,k)]=-fW0[I(i,j,k-1)];
}
else if (M[I(i,j,k+1)] == 0) { ++_emptyNeighbors;
fU0[I(i,j,k)]=-fU0[I(i,j,k+1)]; fV0[I(i,j,k)]=fV0[I(i,j,k+1)]; fW0[I(i,j,k)]=-fW0[I(i,j,k+1)];
}
if (_emptyNeighbors == 0 || _emptyNeighbors > 1) {
fU0[I(i,j,k)]=0.0f; fV0[I(i,j,k)]=0.0f; fW0[I(i,j,k)]=0.0f;
}
}
END_FOR
}
}
75
Efficient Simulation of Fluid Dynamics in a 3D Game Engine – Robert Bongart
void CFD_Cnedra::genN2DMap(float* n2D, int nW, int nH, float offset) {
static float _o=0.0f; _o+=offset;
for(j=0;j<nH;++j) for(i=0;i<nW;++i) { x=i*(1.0f/nW)*2.0f;
y=j*(1.0f/nH)*2.0f;
n2D[j*3*nW+i*3] = PerlinNoise2D(x+_o,y,1.5f,1.0f,4);
n2D[j*3*nW+i*3+1] = PerlinNoise2D(x,y+_o,1.5f,1.0f,0.4);
n2D[j*3*nW+i*3+2] = PerlinNoise2D(x-_o,y,1.5f,1.0f,40);
}
}
76
TRITA-CSC-E 2007: 018
ISRN-KTH/CSC/E--07/018--SE
ISSN-1653-5715
www.kth.se