Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
ROBERT
BONGART
ROBERT
BONGART
Masters 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 Blter 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
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 CNedra 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 Stams stable method for fluid effects in 3D with the CNedra plug-in framework and simulates fire and smoke. I find that my CFD implementation in the CNedra 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.
Sammanfattning
Examensarbetet behandlar effektiv simulering av datorbehandlad fldesdynamik i en 3D grafikmotor genom att diskutera utvecklingen av spelmotorn CNedra p Ecole Centrale Paris. Uppsatsen frsker genombrygga klyftan mellan teoritiska uppsatser om datorbehandlad fldesdynamik genom att implementera Jos Stams stabila algorithm fr fldes dynamik i 3D med hjlp av CNedra plug-in klasser och simulera eld och rk. Jag finner att min implementaion av datorbehandlad fldes-dynamik i CNedra ger godknda resutlat i termer av realism, men dliga resutlat i termer av effektivitet. Jag drar drfr slutsatsen att CNedra inte r en mogen plattform fr att implementera fldesdynamik.
Rsum
Cette thse traite l'excution et simulation efficace de la mcanique de fluides dans le moteur en temps rel des graphiques 3D en discutant le dveloppement du projet virtuel de moteur de jeu de C'Nedra mis excution Ecole Centrale Paris. Je constate que le moteur de jeu C'Nedra est de beaucoup de manire pas suffisamment robuste pour lutilisation de mcaniques de fluides. Je mis en forme la mthode stable de Jos Stam pour les mcaniques de fluides en 3D avec le systme de plug-in en CNedra et simule la dissipation de gaz et feu. Je trouve que mimplmentation de simulation de mcanique de fluides numerique en CNedra donne de rsultats suffisantes en termes de ralisme, mais mauvais en termes de efficacit. Alors, je fais la conclusion que CNedra nest pas un logiciel bien construit pour implmenter les mcaniques de fluides.
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 Blter at The Royal Institute of Technology and Patric Callet at Ecole Centrale Paris for their support and guidance. I would also like to thank Sbastien 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 Rseaux 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 CNedra 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 CNedra 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 CNedra 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 CNedra ............................................................................................................... 58 8.2 Possible improvement of fluid dynamics in CNedra ................................................................................. 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: CNedra XML file.............................................................................................................. 66 Appendix 3: CFD Solver Code............................................................................................................... 67
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 CNedra 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 CNedra. 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 CNedra. 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 CNedra. Figure 19: Pictures showing simulations created in CNedra 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 CNedra. 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: Newtons second law of motion. Figure 26: Navier-Stokes equations. Figure 27: Helmholtz-Hodge Decomposition Theorem. Figure 28: The simulation algorithm.
Figure 29: Eulers method. Figure 30: Stams 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 CNedra. Figure 50: A summary of possible improvements to CNedra 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.
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 peoples 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): Its the pouring of milk into a glass
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 CNedra 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.
approaches to simulating them. The chapter explains the framework for the Navier-Stokes Equations.
Chapter 4 lays down the theory of fluids. The chapter defines fluids and examines various
Chapter 5 gives an outline of the previous research made in the Computational Fluid
Dynamics field.
CNedra.
Chapter 6 is the methodology chapter and describes how CFD has been implemented into 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.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.
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.
Plug-ins
Terrain Engine (World) Physics Engine AI Engine
Data
Sound files (avi, mp3, wav) Textures (bmp, jpg, png...)
Special Effects
Multimedia Engine
3D models (3ds,obj...)
Kernel
Scripting
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 CNedra 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).
3.1 Background
CNedra (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 CNedra toolkit and additional information on the project is available on: www.cnedra.org
The image displays the main structure in the CNedra 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 CNedra 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)
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.
The rest of this chapter will explain and elaborate upon some of the plug-ins implemented in CNedra and conclude with the special effects plug-in being the integral part of this thesis.
x1 x 2 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
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 CNedra the Scene Management system is based on evenly divided bounded boxes that are held in a recursive tree in the form of BSP.
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 CNedra 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 CNedra:
Figure 9: Lighting equation
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
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 viewers 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 CNedra are as presented bellow:
12
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
3.6.5 Shadowing
When another object is between the surface and a light source that light source should not contribute to the surfaces illumination. Shadow Mapping is a way of implementing shadows by rendering an image from the lights 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 shadowmaps 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 thats 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 CNedra does not have support for vertex shaders hence this is not utilized when implementing fluid dynamics into the system.
14
The images display a tank that we scanned by a 3D scanner, textured in 3D Max Studio and finally inserted into CNedra graphics engine.
3.7.3 Collision
We based the collisions detection system in CNedra on an OBB (oriented bounded boxings), tree approach. CNedra enables collision of two objects in translation meaning that spinning collision effects can be implemented as explained in Eberly (2001).
15
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.
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 CNedra, 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 CNedra
Mipmapping is a level-of-detail method used in CNedra 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 engines 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.
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 Dijkstras 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
20
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
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.
22
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
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
r r f = ma
(4.1)
24
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
r u = 0.
(4.2) (4.3)
1 r 1 x y f = (f , f , f
z T
(4.4)
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
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
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
r 1 p p p p = , , , x y z
1
r
(4.7)
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 pressure in the fluid naturally leads to acceleration. (Think of Newtons 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
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 y y y 2 y 2 y 2 y u u u u u u u 1 p f + v 2 + = ux + uy + uz + 2 x t x y z y z 2 y z z z z z 2 z 2 z 2 z u u u u u u u 1 p f + v 2 + = ux + uy + uz + 2 x t y z y 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
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.
t t z t 1 > max u x , u y ,u , u x , u y , u z x y z
where u x , u y , and u z are the velocity components in x, y and z directions.
(5.1)
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
r r Fbv = g y (T0 Tk ), r
(5.2)
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:
~ r ~ u = u u t
t
(5.3)
~ r u ~ is given where u is the current velocity, u is the yet unknown, updated velocity, and
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
~ u = 2 q.
(5.4)
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 Stams 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,
(5.5)
29
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 Stams 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.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 Stams algorithm in 3D seeing as the approach, gives astonishing results and is quite straight forward to implement.
31
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.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
r r w = u + p ,
(6.1)
r r
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
Step 2 If we apply the divergence operator to both sides of Equation (6.4.1), we obtain
(6.2)
r r r w = (u + p ) = u + 2 p
And we have that u = 0 , which gives us
(6.3)
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). 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 )
r r r Pw = Pu = u
P(p ) = 0
P
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
Add force
V
S = P o D o Ao F
Advect
(6.10) Project
Diffuse
6.2.2 Advection
Advection is a process by which a fluids 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: Eulers 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: Stams 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.
r r r r r r u ( x , t + t ) = u ( x , t ) + v t 2 u ( x , t )
r r r r (I v t )u ( x , t + t ) = u ( x , t )
2
34
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:
k k x i(1), j + x i(+1), 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 + . vt
To solve the equations, I simply run a number of iterations in which I apply Equation (6.16).
35
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
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
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
38
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.
39
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
t=0
t=1s
t=2s
t=3s
t=4s
t=5s
t=6s
t=7s
t=8s
41
t=0
t=1s
t=2s
t=3s
t=4s
t=5s
t=6
t=7s
t=8s
42
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
t=6
t=7s
t=8s
t=9
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.
t=0
t=1s
t=2s
44
t=3s
t=4s
t=5s
t=6
t=7s
t=8s
t=9
t=10s
t=11s
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
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
t=0
t=1s
t=2s
t=3s
t=4s
t=5s
t=6
t=7s
t=8s
t=9
t=10s
t=11s
47
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.
t=0s
t=1s
t=2s
t=3s
t=4s
t=5s
t=6s
t=7s
t=8s
48
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
t=6s
t=7s
t=8s
t=9
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.
t=0
t=1s
t=2s
50
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.
51
70
60
50 Frames/second
40
30
20
10
4x4x4 60,121
8x8x8 50,349
32x32x32 1,449
64x64x64 0
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 CNedra game engine. In the following tests I check for parameters that might improve the performances of the implementation.
16 14 12 Frames/second 10 8 6 4 2 0 1 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200
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
14
13,5
13 Frames/second
12,5
12
11,5
11
10,5 0,00001 0,0001 0,001 0,01 0,1 1 dt 10 100 1000 10000 100000
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.
16 14 12 Frames/second 10 8 6 4 2 0
8-bit 14,392
32-bit 8,432
53
t=0
t=2s
t=4s
t=6
t=8s
t=10s
t=12
t=14s
t=16s
54
t=18
t=20s
t=22s
t=0
t=2s
t=4s
t=6
t=8s
t=10s
t=12
t=14s
t=16s
55
t=18
t=20s
t=22s
t=0
t=2s
t=4s
t=6
t=8s
t=10s
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
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 CNedra 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
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 CNedra game engine? Well, after having acquired substantial knowledge of how to develop software with the CNedra toolkit and its overall performance as well as run the various simulations, I conclude that it is not advised to use CNedra 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.
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
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
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.
61
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. Mcanique 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
64
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.
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 being 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:
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 .
= , , . x y z
For a scalar field s ( x ) I define the gradient of the scalar field:
( x ) ( x ) ( x ) s ( x ) = x , y , z ,
x 3 ,
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
And the curl of the vector field
x 3 ,
v x ( x ) y v x ( x ) v( x ) = z y v ( x ) x
For a vector field v ( x ) I use the notation:
v y ( x ) z v x ( x ) , x v x ( x ) y
x 3 .
65
2v x ( x) 2 x 2 v y ( x) r (v ( x ) ) = 2 2x z v ( x) x 2
r 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 ,
x w x ( x ) v ( x) x y x r r (v ( x ) )w = v ( x ) w ( x ) x z v x ( x ) w ( x ) x
Which finally gives us the laplacian:
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) = 2 .
x 3 ,
66
67
68
#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
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
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
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 +
72
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
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
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
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
www.kth.se