User Guide Vol1
User Manual:
Open the PDF directly: View PDF .
Page Count: 312
Download | |
Open PDF In Browser | View PDF |
User Guide Volume I Copyright © 2003 – Criterion Software Ltd. User Guide Contact Us Criterion Software Ltd. For general information about RenderWare Graphics e-mail info@csl.com. Developer Relations For information regarding Support please email devrels@csl.com. Sales For sales information contact: rw-sales@csl.com Acknowledgements Contributors RenderWare Graphics Development and Documentation Teams The information in this document is subject to change without notice and does not represent a commitment on the part of Criterion Software Ltd. The software described in this document is furnished under a license agreement or a nondisclosure agreement. The software may be used or copied only in accordance with the terms of the agreement. It is against the law to copy the software on any medium except as specifically allowed in the license or non-disclosure agreement. No part of this manual may be reproduced or transmitted in any form or by any means for any purpose without the express written permission of Criterion Software Ltd. Copyright © 1993 - 2003 Criterion Software Ltd. All rights reserved. Canon and RenderWare are registered trademarks of Canon Inc. Nintendo is a registered trademark and NINTENDO GAMECUBE a trademark of Nintendo Co., Ltd. Microsoft is a registered trademark and Xbox is a trademark of Microsoft Corporation. PlayStation is a registered trademark of Sony Computer Entertainment Inc. All other trademark mentioned herein are the property of their respective companies. I-2 11 February 2004 Foreword About the User Guide This is the RenderWare User Guide for release 3.7. The documentation has been updated for 3.7 and is organized into three volumes of general, platform independent material. Volume III includes Maestro documentation and a Recommended Reading appendix . Xbox, GameCube and PlayStation 2 have a separate platform specific addendum, containing material which is only useful for that platform and which has been updated for 3.7. Volume I contains the core library and the world library, giving basic immediate mode and retained mode functionality. • Introduction From the core library: • Fundamental Types • Initialization & Resource Management • Plugin Creation and Usage • The Camera, covering the basics of rendering • Rasters, Images and Textures • Immediate Mode • Serialization • Debugging & Error Handling From the world library: • World and Static Models • Dynamic Models • Lights In Volume II elements of the animation systems, special effects and world management functionality are discussed • • • • • • • • • • • • • • Skinning Fundamental Types for Animation The Animation Toolkit Hierarchical Animation Morph Delta Morphing Material Effects Lightmaps PTank Standard Particles (RpPrtStd) B-splines and Bézier Patches Collision Detection Potentially Visible Sets (PVS) Geometry Conditioning Foreword Volume III covers the utility libraries, which offer a variety of useful functionality and an in-depth coverage of PowerPipe, the key to customizing RenderWare for ultimate performance and unique functionality for your application. • • • • • 2D Graphics Toolkits Maestro The User Data Plugin, on exporting user data PowerPipe Overview Pipeline Nodes Platform specific documentation is included for PlayStation 2, Xbox and GameCube. PlayStation 2: • PS2All Overview • Pipeline Delivery System (PDS) Xbox: • Multi-texturing in MatFX • Multi-texturing on Xbox • Xbox State Cache • Xbox Pixel Shaders • Xbox Vertex Format Compression GameCube: • Multi-texturing in MatFX • Multi-texturing on GameCube We realize that this User Guide does not cover every single feature in RenderWare Graphics, but we hope you will find it useful. Please let us know what you think and feel free to offer any suggestions. Regards, The RenderWare Graphics Team I-4 11 February 2004 Table of Contents Chapter 1 - Introduction ....................................................................................... 13 1.1 1.2 1.3 1.4 Welcome to RenderWare Graphics .................................................................14 1.1.1 What you Should Know ...................................................................... 14 1.1.2 What is RenderWare Graphics? ........................................................... 15 1.1.3 Design philosophy ............................................................................. 16 The RenderWare Graphics SDK ......................................................................18 1.2.1 Libraries and Header Files .................................................................. 18 1.2.2 Examples ......................................................................................... 19 1.2.3 Documentation ................................................................................. 20 1.2.4 Artists Tools ..................................................................................... 21 1.2.5 Open Export Framework .................................................................... 21 RenderWare Graphics Architecture .................................................................22 1.3.1 The Core Library, Plugins and Toolkits ................................................. 22 1.3.2 PowerPipe ........................................................................................ 25 1.3.3 Namespaces ..................................................................................... 25 1.3.4 Just Graphics.................................................................................... 26 1.3.5 Objects ............................................................................................ 26 1.3.6 File I/O ............................................................................................ 27 Using RenderWare Graphics ..........................................................................28 1.4.1 Creating a scene ............................................................................... 28 1.4.2 Creating prototypes........................................................................... 29 Part A - Core Library ............................................................................................. 31 Chapter 2 - Fundamental Types............................................................................. 33 2.1 Introduction ................................................................................................34 2.2 RenderWare Graphics & Objects ....................................................................35 2.2.1 RenderWare Graphics Objects............................................................. 35 2.2.2 Object Instantiation........................................................................... 35 2.2.3 Object Destruction & Reference Counters ............................................. 36 2.3 The Boolean Type ........................................................................................38 2.4 Characters ..................................................................................................39 2.5 Integer Types..............................................................................................40 2.6 Real Types ..................................................................................................42 2.7 Vectors.......................................................................................................43 2.8 2.7.1 Two Dimensional Vectors ................................................................... 43 2.7.2 Three Dimensional Vectors ................................................................. 44 Coordinate Systems .....................................................................................45 2.8.1 Right-handed Coordinates .................................................................. 45 2.8.2 Object Space .................................................................................... 47 2.8.3 World Space ..................................................................................... 48 2.8.4 Camera Space .................................................................................. 48 2.8.5 Device Space.................................................................................... 48 User Guide 2.9 Matrices ..................................................................................................... 50 2.9.1 Matrix Mathematics in RenderWare Graphics ........................................ 50 2.10 Frames....................................................................................................... 52 2.10.1 Hierarchical Models & RenderWare Graphics ....................................... 53 2.10.2 Traversing Frame Hierarchies ........................................................... 54 2.10.3 Matrix Combination Flags in RenderWare Graphics .............................. 55 2.11 Bounding Boxes........................................................................................... 57 2.12 Lines.......................................................................................................... 58 2.13 Rectangles .................................................................................................. 59 2.14 Spheres...................................................................................................... 60 2.15 Colors ........................................................................................................ 61 Chapter 3 - Initialization & Resource Management ............................................... 63 3.1 Introduction ................................................................................................ 64 3.2 Basic Housekeeping ..................................................................................... 65 3.3 3.4 3.2.1 Initialization ..................................................................................... 65 3.2.2 Shutting down RenderWare Graphics................................................... 70 3.2.3 Changing Video Modes after Initialization ............................................. 71 Memory Management................................................................................... 72 3.3.1 The OS-level Memory Interface........................................................... 72 3.3.2 FreeLists .......................................................................................... 73 3.3.3 Memory Hints ................................................................................... 75 3.3.4 Resource Arenas ............................................................................... 76 3.3.5 Locking and Unlocking data ................................................................ 77 Summary ................................................................................................... 79 3.4.1 Starting The Engine........................................................................... 79 3.4.2 Shutting Down The Engine ................................................................. 79 3.4.3 Memory Handling .............................................................................. 80 3.4.4 Plugins ............................................................................................ 80 Chapter 4 - Plugin Creation & Usage ..................................................................... 81 4.1 4.2 Introduction ................................................................................................ 82 4.1.1 Toolkits ........................................................................................... 82 4.1.2 Plugins and Streaming ....................................................................... 82 Using Plugins .............................................................................................. 83 4.2.1 4.3 4.4 I-6 Attaching Plugins .............................................................................. 83 Creating Your Own Plugins............................................................................ 85 4.3.1 Introduction ..................................................................................... 85 4.3.2 Anatomy of a Plugin .......................................................................... 85 4.3.3 The "Plugin" Example ........................................................................ 85 4.3.4 Using the Physics Plugin .................................................................... 88 Plugin Design .............................................................................................. 91 4.4.1 Introduction ..................................................................................... 91 4.4.2 Extension vs. Derivation .................................................................... 91 4.4.3 Deriving new objects ......................................................................... 91 4.4.4 Plugins & C++ .................................................................................. 92 11 February 2004 Table of Contents Chapter 5 - The Camera ........................................................................................ 95 5.1 Introduction ................................................................................................96 5.1.1 5.2 The Camera Example ......................................................................... 96 The RenderWare Graphics Camera object .......................................................97 5.2.1 Camera Properties............................................................................. 97 5.2.2 The View Frustum ............................................................................. 98 5.2.3 The View Window .............................................................................. 99 5.2.4 The View Offset .............................................................................. 102 5.2.5 Fog ............................................................................................... 102 5.3 The Camera View Matrix ............................................................................. 105 5.4 Rasters & Cameras .................................................................................... 106 5.4.1 5.5 Creating a Camera ..................................................................................... 107 5.5.1 5.6 Z Buffer Accuracy............................................................................ 106 Orienting and Positioning a Camera in Scene Space............................. 107 Rendering to a Camera............................................................................... 109 5.6.1 Destroying a Camera ....................................................................... 110 5.7 Sub-Rasters .............................................................................................. 111 5.8 Other Features .......................................................................................... 112 5.9 5.8.1 Clearing the Buffers......................................................................... 112 5.8.2 Cloning a Camera............................................................................ 112 World Plugin Extensions.............................................................................. 113 5.9.1 About the Extensions....................................................................... 113 5.9.2 Automatic & Manual Culling .............................................................. 113 5.9.3 Clump Cameras .............................................................................. 113 5.9.4 Iterators ........................................................................................ 113 Chapter 6 - Rasters, Images and Textures .......................................................... 115 6.1 Introduction .............................................................................................. 116 6.2 Bitmaps & Textures.................................................................................... 117 6.3 6.2.1 Bitmaps ......................................................................................... 117 6.2.2 Images .......................................................................................... 117 6.2.3 Rasters .......................................................................................... 117 6.2.4 Textures ........................................................................................ 118 The Image Object ...................................................................................... 119 6.3.1 Image Dimensions .......................................................................... 119 6.3.2 Stride ............................................................................................ 119 6.3.3 Palettes ......................................................................................... 119 6.3.4 Gamma Correction .......................................................................... 119 6.3.5 Creating Images ............................................................................. 120 6.3.6 Example: Reading a BMP file ............................................................ 121 6.3.7 Reading the Image .......................................................................... 122 6.3.8 Image Processing............................................................................ 123 6.3.9 Raster Conversion ........................................................................... 125 6.3.10 6.4 Destroying Images ........................................................................ 125 The Raster Object ...................................................................................... 126 6.4.1 Basic Properties .............................................................................. 126 RenderWare Graphics 3.7 I-7 User Guide 6.5 6.4.2 The Raster as a Display Device ......................................................... 129 6.4.3 Rendering Rasters........................................................................... 130 6.4.4 Accessing Rasters ........................................................................... 131 6.4.5 Reading Rasters from disk................................................................ 131 Textures & Rasters .................................................................................... 132 6.5.1 Introducing Textures ....................................................................... 132 6.5.2 Loading Textures ............................................................................ 136 6.5.3 Texture Dictionaries ........................................................................ 138 6.5.4 Using Texture Dictionaries................................................................ 139 6.5.5 Platform independent texture dictionaries .......................................... 140 6.5.6 Using PI texture dictionaries............................................................. 140 6.5.7 Non-fixed hardware issues with texture dictionaries ............................ 141 6.5.8 Textures & Binary Streams............................................................... 141 Chapter 7 - Immediate Mode ...............................................................................143 7.1 Introduction .............................................................................................. 144 7.1.1 7.2 7.3 7.4 Properties & Render States .............................................................. 144 2D Immediate Mode................................................................................... 145 7.2.1 Basic Concepts ............................................................................... 145 7.2.2 Initializing an RwIm2DVertex object .................................................. 147 7.2.3 Primitives....................................................................................... 149 7.2.4 Triangle Winding Order .................................................................... 150 7.2.5 Primitives vs. Indexed Primitives....................................................... 151 7.2.6 Example 1: Rendering A Line............................................................ 152 3D Immediate Mode................................................................................... 154 7.3.1 Preparation for Rendering ................................................................ 154 7.3.2 Rendering ...................................................................................... 156 7.3.3 Closing the pipeline ......................................................................... 158 7.3.4 3D Immediate Mode & PowerPipe...................................................... 158 7.3.5 Platform Specific Information ........................................................... 159 7.3.6 Camera-space and Z-buffer depth equations ...................................... 160 7.3.7 Rt2D ............................................................................................. 161 Render States ........................................................................................... 162 7.4.1 Key Features .................................................................................. 162 7.4.2 API................................................................................................ 162 7.4.3 Blending ........................................................................................ 165 7.4.4 Sorting Alpha Primitives................................................................... 166 Chapter 8 - Serialization ......................................................................................167 I-8 8.1 Introduction .............................................................................................. 168 8.2 File I/O API ............................................................................................... 169 8.3 RenderWare Binary Streams ....................................................................... 171 8.3.1 Binary Stream Structure .................................................................. 171 8.3.2 Serializing Objects .......................................................................... 173 8.3.3 Explicit Streaming Functions............................................................. 178 8.3.4 RWS files ....................................................................................... 182 8.3.5 Stream Types ................................................................................. 186 11 February 2004 Table of Contents 8.4 Summary.................................................................................................. 187 8.4.1 File I/O API .................................................................................... 187 8.4.2 RenderWare Binary Streams............................................................. 187 Chapter 9 - File Systems ..................................................................................... 191 9.1 Introduction .............................................................................................. 192 9.2 File System Management ............................................................................ 193 9.3 The File Systems ....................................................................................... 194 9.4 9.3.1 The Generic File System................................................................... 194 9.3.2 OS-Specific File Systems.................................................................. 195 Using the RenderWare File System............................................................... 196 9.4.1 Basic Usage.................................................................................... 196 9.4.2 Synchronous vs. Asynchronous Access............................................... 198 9.4.3 File System Specific Remarks ........................................................... 199 9.4.4 Creating your Own File System ......................................................... 200 Chapter 10 - The Dictionary Toolkit..................................................................... 203 10.1 Introduction .............................................................................................. 204 10.1.1 This Document .............................................................................. 204 10.1.2 Other Resources............................................................................ 205 10.2 Basic Dictionary Schema Usage ................................................................... 206 10.2.1 Getting the Current Dictionary for a Schema..................................... 206 10.2.2 Setting the Current Dictionary for a Schema ..................................... 206 10.3 Creating and Streaming Dictionaries ............................................................ 207 10.3.1 Dictionary Creation ........................................................................ 207 10.3.2 Reading a Dictionary from a Stream ................................................ 207 10.3.3 Writing a Dictionary to a Stream ..................................................... 207 10.4 Dictionary Entries ...................................................................................... 209 10.4.1 Adding Entries to a Dictionary ......................................................... 209 10.4.2 Removing an Entry from a Dictionary............................................... 209 10.4.3 Locating an Entry by Name............................................................. 210 10.5 Advanced Dictionary Schema Usage ............................................................. 211 10.5.1 Schema Structure ......................................................................... 211 10.5.2 Initializing a Schema ..................................................................... 212 10.6 Summary.................................................................................................. 214 Chapter 11 - Debugging and Error Handling........................................................ 215 11.1 RenderWare Graphics Errors ....................................................................... 216 11.2 RenderWare Graphics Builds ....................................................................... 217 11.3 The Debug Object ...................................................................................... 218 11.3.1 The Default Debug Stream Handler.................................................. 218 11.3.2 Sending a Message to the Debug Stream ......................................... 219 11.4 Tracing RenderWare Graphics Activity .......................................................... 220 11.5 Replacing The Stream Handler.......................................................................... 222 11.5.1 Example....................................................................................... 222 Part B - World Library ......................................................................................... 225 RenderWare Graphics 3.7 I-9 User Guide Chapter 12 - World and Static Models ..................................................................227 12.1 Introduction .............................................................................................. 228 12.2 Scenes & Static Models............................................................................... 229 12.2.1 Scenes......................................................................................... 229 12.2.2 RpWorld Object............................................................................. 229 12.2.3 RpWorldSector Object.................................................................... 230 12.3 Iterator Functions ...................................................................................... 231 12.3.1 RpWorld Iterators.......................................................................... 231 12.3.2 RpWorldSector Iterators................................................................. 232 12.3.3 Collision Detection......................................................................... 232 12.4 Modeling Tools .......................................................................................... 233 12.4.1 Viewers........................................................................................ 233 12.5 Creating Worlds......................................................................................... 234 12.5.1 Creating Worlds from Foreign Data .................................................. 234 12.5.2 What is Pre-lighting? ..................................................................... 240 12.6 Rendering................................................................................................. 242 12.6.1 How to Render Worlds ................................................................... 242 12.6.2 Instancing .................................................................................... 242 12.6.3 Pre-instancing Static Geometry ....................................................... 243 12.7 Serialization .............................................................................................. 245 12.7.1 Writing......................................................................................... 246 12.7.2 Reading ....................................................................................... 247 12.8 Destruction ............................................................................................... 248 Chapter 13 - Dynamic Models...............................................................................249 13.1 Introduction .............................................................................................. 250 13.2 The World Plugin ....................................................................................... 251 13.2.1 The Geometry Object..................................................................... 251 13.2.2 The Atomic Object ......................................................................... 251 13.2.3 The Clump Object.......................................................................... 252 13.2.4 Clump Destruction......................................................................... 254 13.3 Creation of Dynamic Models ........................................................................ 255 13.3.1 Model Creation Overview................................................................ 255 13.4 Modeling Tools .......................................................................................... 256 13.4.1 Exporters ..................................................................................... 256 13.4.2 Viewers........................................................................................ 256 13.4.3 Procedural Model Creation .............................................................. 257 13.4.4 Vertices & Triangles....................................................................... 257 13.4.5 Textures & Materials ...................................................................... 259 13.4.6 Surface Properties & Geometry ....................................................... 261 13.4.7 Morph Targets .............................................................................. 262 13.4.8 Pentagons & Hexagons .................................................................. 263 13.4.9 Bounding Spheres & Transformations .............................................. 264 13.4.10 Atomics and Clumps ...................................................................... 266 13.5 Objects in more detail ................................................................................ 267 I-10 13.5.1 Reference Counting ....................................................................... 267 13.5.2 Texture coordinates....................................................................... 267 11 February 2004 Table of Contents 13.5.3 Prelighting.................................................................................... 268 13.5.4 Surface properties ......................................................................... 268 13.5.5 Meshes ........................................................................................ 268 13.6 Atomics, Clumps & Transformations ............................................................. 270 13.6.1 Worlds ......................................................................................... 270 13.6.2 Cloning ........................................................................................ 270 13.6.3 Iterator functions .......................................................................... 271 13.6.4 Sorting Geometry objects by Material .............................................. 273 13.6.5 Animation..................................................................................... 274 13.6.6 Skinned Models ............................................................................. 275 13.7 Optimization ............................................................................................. 276 13.8 Rendering ................................................................................................. 277 13.8.1 How to Render Dynamic Objects ..................................................... 277 13.8.2 Instancing .................................................................................... 278 13.8.3 Pre-instancing Dynamic Geometry ................................................... 279 13.8.4 Converting Model Data to RenderWare Graphics................................ 281 Chapter 14 - Lights ............................................................................................. 285 14.1 Introduction .............................................................................................. 286 14.1.1 Other Documentation..................................................................... 286 14.2 Dynamic Lights.......................................................................................... 287 14.2.1 Dynamic Lights Representation ....................................................... 288 14.2.2 Creating a dynamic light ................................................................ 289 14.2.3 Clump Lights & Streaming .............................................................. 292 14.2.4 Platform-Specific Lighting Models .................................................... 292 14.3 Static Lights using RpLight .......................................................................... 294 14.3.1 Creating Static Lights..................................................................... 294 14.3.2 Static Lighting Techniques .............................................................. 295 14.4 Related Examples ...................................................................................... 297 14.5 Summary.................................................................................................. 300 14.5.1 Dynamic Lights ............................................................................. 300 14.5.2 Static Lights ................................................................................. 301 Index .................................................................................................................. 303 RenderWare Graphics 3.7 I-11 Chapter 1 Introduction Chapter 1 - Introduction 1.1 Welcome to RenderWare Graphics Welcome to the RenderWare Graphics User Guide! RenderWare Graphics is a powerful 3D graphics library. This User Guide is aimed at helping newcomers to RenderWare Graphics become familiar with the product. This is in addition to the on-line help, and support that is offered with the purchase of any RenderWare Platform component. RenderWare Graphics is the result of many years of development, which began in 1991. The power and flexibility of the product has been increased with every release. RenderWare Graphics is a multi-platform Application Programming Interface (API), which is constantly being improved and updated to keep it at the cutting edge of 3D graphics. To support the community of developers in the field, we offer our Fully Managed Support System. Accessible via a personalized web interface, this allows our technical support personnel to be contacted, the status of outstanding queries to be tracked, and our knowledge base to be searched and viewed, plus lots of other useful information. To find out more and register for the service, point your browser at https://support.renderware.com/. If you are new to RenderWare Graphics, it is strongly suggested that you read this User Guide as you go along to acquaint yourself with its operation. Similarly, if you've already been using RenderWare Graphics for a while, stick around! The User Guide is written by the people who created the library, so you might gain new insights, tricks and tips. Additionally it has been revised and expanded to cover all our latest new technology. RenderWare Graphics is a module of Criterion Software's RenderWare Platform, the tailored set of open and extensible middleware tools which allows you to focus on content and gameplay. For further information on the other Components (including RenderWare Audio, RenderWare AI and RenderWare Physics) please visit www.renderware.com or contact your account manager. 1.1.1 What you Should Know This User Guide makes some assumptions about your level of proficiency with real-time 3D graphics programming: • I-14 This Guide is not aimed at complete newcomers to the field of computer graphics. If you are new to all this, check out the Recommended Reading appendix for links to online articles and books you can use as a starting point. 11 February 2004 Welcome to RenderWare Graphics • Secondly, this User Guide will not go into detail about the mathematics upon which most 3D graphics programming is founded. The whole point of graphics libraries such as RenderWare Graphics is to do the math for you. That said, some college-level math is required to understand some concepts. If your knowledge of the principles and practices of matrix and vector manipulation is limited, the Recommended Reading appendix contains pointers to relevant texts that can help you with this area. 1.1.2 • This User Guide assumes you are an experienced programmer with a thorough knowledge of the C (or C++) programming language. You should also be comfortable with the concepts behind object-oriented programming. • The User Guide is platform-neutral so it will not cover any specific development environment. Platform-specific variations and optimization notes will be provided in an appendix. What is RenderWare Graphics? • A graphics library RenderWare Graphics is a 2D and 3D graphics API. It is used by programmers to create real-time 3D graphics applications, such as computer games and simulations. • Multi-platform RenderWare Graphics has multi-platform, portable API that allows high level functionality to be achieved on all platforms, with platform specific optimizations to get the best from the hardware pipelines. RenderWare Graphics is available for Sony PlayStation 2, Microsoft Xbox, NINTENDO GAMECUBE, Microsoft Windows (Direct3D 8), Microsoft Windows (OpenGL) and Apple MacOS (OpenGL). • Customizable RenderWare Graphics has a component-based approach to its architecture based around a small-footprint, thin-layer core library, supplemented by a number of Plugins and Toolkits. Plugins are the key to RenderWare Graphics' power; they can extend existing objects and add new objects of their own that can also be further extended. Even the Retained Mode API is a Plugin, which gives RenderWare Graphics the unique feature of being the only 3D graphics library that can support any number of Retained Mode APIs. RenderWare Graphics 3.7 I-15 Chapter 1 - Introduction Further, this Plugin mechanism is fully exposed. You can write your own Plugins, extending and adding objects, for your own requirements we even encourage you to do so, as we do not claim to have thought of everything! • Compatible with many third-party tools and middleware RenderWare Graphics is a module of Criterion Software's RenderWare Platform, the tailored set of middleware tools offering a tightly integrated game development framework, which includes graphics, audio and physics modules, with other Components planned for availability in the future. 1.1.3 Design philosophy The design brief for RenderWare Graphics was to create a 3D graphics library that would never be obtrusive. We have tried hard to make sure the library is the most powerful multi-platform 3D library available. Platform Independent Development RenderWare Graphics has been designed from the ground up to let you get the most out of all its supported platforms – with no compromises. APIs are provided which expose low-level features and optimization opportunities to the developer, so the best performance can be obtained from your projects. The price for this is a little extra work during the porting process: each platform has different hardware, and different advantages and disadvantages. RenderWare Graphics gives you the freedom to choose how far you go down the optimization route: • Need to create a product quickly for more than one platform? No problem: use the common API features – the facilities provided as standard across all platforms – and treat it as an ordinary crossplatform library. • Alternatively, writing custom PowerPipe nodes and plugins enables RenderWare Graphics to be fine-tuned to specialized performance requirements. The purchase of a source code license gives the developer ultimate control over RenderWare Graphics. RenderWare Graphics gives you the freedom to take either route, or indeed any path between these two extremes. Such flexibility does come at a price: where platform-specific features of RenderWare Graphics are chosen, the code for each target platform will need to be changed when porting. C vs. C++ One of the most common questions asked about RenderWare Graphics is the choice of programming language: C. I-16 11 February 2004 Welcome to RenderWare Graphics There are two reasons for choosing to write RenderWare Graphics in the C programming language. The first is that there is no standard for C++ libraries; RenderWare Graphics would have to be shipped as a separate set of libraries for each supported compiler, as well as each platform. Clearly, this would complicate product support. Secondly, while C++ has many, many great features, most new platforms – particularly consoles – don't get a stable, mature C++ compiler until long after they get a good C compiler. In order for a new platform to be worked on as soon as possible, the fastest way to achieve this is to use a mixture of highly optimized C and assembly language. That said, it is quite possible to mix C and C++. The Plugin mechanism lets you add space for 'this' pointers to RenderWare Graphics objects with minimal fuss, and all RenderWare Graphics' header files have the requisite "extern 'C'" directives to allow the two languages to mix seamlessly. Several of our licensees have also produced their own C++ wrapper classes to encapsulate RenderWare Graphics in order to develop in a 'pure' C++ environment. RenderWare Graphics 3.7 I-17 Chapter 1 - Introduction 1.2 The RenderWare Graphics SDK 1.2.1 Libraries and Header Files RenderWare Graphics is supplied as a number of libraries on the Software Development Kit (SDK). Applications will need to link against these libraries and #include the associated header files. All RenderWare Graphics libraries are static. Each platform is provided with its own headers and libraries. In addition, the SDK contains null libraries, which are used by exporters and other tools. These are provided with all platforms. The null libraries contain all the PC functionality, but do not perform any rendering. A NULL target DLL is also provided that the art tools exporters make use of. This DLL contains almost all of the static NULL libraries. Note that the static NULL libraries, contained in a RenderWare Graphics (version 3.5 and above) installation, if linked into an application, require the multithreaded DLL runtimes. Null Libraries ✎ On Xbox, GameCube and PlayStation 2 null and nullplatform libraries are also built. For example, PlayStation 2 RenderWare Graphics SDK is supplied with null and nullsky libraries. These PC libraries are required for certain tools that process platform specific data. They can be used for the generation of texture dictionaries. It should be noted that nullplatform libraries can not create pre-instanced and geometry data. Debug, Metrics and Release Libraries For each platform, separate debug, metrics and release builds of the RenderWare Graphics libraries are also provided. Debug, release and metrics libraries live in separate folders inside the rwsdk/lib folder. RWDEBUG and RWMETRICS preprocessor symbols must be used to indicate which build is being used. It is crucial that you do not mix symbols and libraries between these builds. To illustrate, some API calls are implemented in release builds as macros. In debug builds these calls are really implemented as functions. This can mean that if you define the RWDEBUG preprocessor symbol, but link with the release build of the library you will get numerous "undefined symbol" link errors. Compilers supported Please see the appropriate platform specific top-level readme files supplied with the RenderWare Graphics SDK for information on the compilers supported by RenderWare Graphics. I-18 11 February 2004 The RenderWare Graphics SDK SN Systems, Visual Studio IDE integration and Project Files The RenderWare Graphics SDK provides full support for the SN Systems Visual Studio Integration features. Project Build Target settings are included for all platforms supported via Visual Studio. Developers should ensure the correct Project Build Target is selected. 1.2.2 Examples The SDK contains nearly 50 source code examples. Examples are small and designed to illustrate a particular technique or feature of the RenderWare Graphics API. They are intended as a means of education: we encourage you to look through the source code and play with them. Tools & Viewers Also included are tools and viewers for you to use during development. Of particular note is the RenderWare Visualizer viewer, which allows you to easily view RenderWare Graphics artwork on any target hardware. Two other viewers are also available for viewing artwork: 'wrldview', and 'clmpview'. 'wrldview' displays static models created for the Retained Mode API, and 'clmpview' displays dynamic models. RenderWare Graphics uses a single file format, using chunk-IDs, which is capable of storing any one or more RenderWare Graphics objects. The RenderWare Graphics Binary Stream format can be viewed using the 'strview' applet supplied with the SDK. A Microsoft Visual Studio 6 AppWizard is also supplied with RenderWare Graphics that can be used to generate an MFC framework-based clump or world viewer. This AppWizard can be incorporated into Microsoft Visual C++ and used in the same manner as the standard Microsoft AppWizards. Please see the accompanying documentation describing how to build a RenderWare Graphics viewer. Building the Examples The examples that are shipped on the SDK should not need compiling to run them. If you modify them, you will want to re-build the executables. The Project files provided with the tools and examples are not necessarily set for your particular platform so make sure you select the correct build configuration prior to compilation. The two screen shots below show the Integrated Development Environments (IDEs) and the build targets that they offer. In Visual Studio, you will need to select the correct Project Configuration; in CodeWarrior, you must select the correct Target. Further, there are separate release, debug, and metrics builds. Unless you have good reason not to, it is suggested that you select: RenderWare Graphics 3.7 I-19 Chapter 1 - Introduction • Win32 D3D8 or D3D9 Release project in Visual Studio for the PC • Xbox Release in Visual Studio for Xbox • PS2 Release in CodeWarrior for the PlayStation 2 • GCN Release in CodeWarrior for GameCube Visual Studio 1.2.3 CodeWarrior Documentation Documentation is provided in both online and PDF formats. The PDF format is intended for printing only and is not hyperlinked. The PDF files have been setup for double sided printing. The following documentation is provided in the SDK: • This User Guide • API Reference • Tutorials (PC only) • White Papers • Exporter Guides for artists and programmers • Tools and Viewers documentation • Examples document listing all examples with brief explanation • readme_xxx.pdf All the examples and tools have a related readme.txt file. It is highly recommended that you read these for information about any last-minute changes or features. There is also the top-level SDK readme_xx.pdf file, where xxx is the platform name, which lists last-minute changes, fixes and known issues and can be found in the root of the SDK. I-20 11 February 2004 The RenderWare Graphics SDK 1.2.4 Artists Tools The RenderWare Graphics installer can be used to install the artists' tools. These tools are exporter plugins for exporting 3D model data from packages such as 3ds max and Maya. When installed, artists will find: • The modeling package's RenderWare Graphics exporter plugin(s) • Sample artwork demonstrating optimal modeling techniques • Documentation covering how to create and export models successfully for RenderWare Graphics. ✎ 1.2.5 It is strongly recommended that programmers also read the documentation supplied with the artists tools. The installer adds links to these docs from the start menu. Open Export Framework The RenderWare Graphics programmer installer can be used to install the Open Export SDK that gives you a powerful way of extending the exporters. Consisting of a series of modular libraries and custom code hooks, you could soon be introducing new common classes to the modelers, changing behaviors or creating new object handlers under our plugin architecture. To get you started, we have provided the Getting Started section in the Open Export API Reference document. In addition, we have included six examples of what you can do with the SDK: • ExportObject - An example of a custom object exporter optimizes the exported textures, by making sure that all texture sizes are beneath a certain threshold. • MaxSimple - An example of how to write your own custom builder and export application. To demonstrate this we used a simplified 3dsmax exporter. • PostProcess – An example demonstrates how to post process the entire list of exported RenderWare Graphics assets, and how to customize the stream process for streaming them out. • ScaleAnim - This example adds support for animated scale to the RwExp layer. • TravAction - Demonstrates the use of traverse actions together with traverse lists that filters out all nodes containing a certain name. • VertexFilter - An example of a vertex filter which pre-lights a scene by applying per vertex operations. RenderWare Graphics 3.7 I-21 Chapter 1 - Introduction 1.3 RenderWare Graphics Architecture The diagram below shows how the RenderWare Graphics library fits into a typical application. Application RW Plugin Toolkit Plugin RW Plugin RW Toolkit RW Toolkit RpWorld RwCore Hardware Abstracting the underlying hardware is the RenderWare Graphics Core Library. Above this is the world plugin. This is the largest and most widely used of the optional RenderWare Graphics modules. Various plugins provided with the SDK are shown adding functionality. Also shown are toolkits, both supplied with the SDK, and non-RenderWare Graphics Toolkits supplied by third parties. A third party plugin is also shown. Above these components is the application which uses the services (functions) exposed by the various components. The gray boxes above that labeled RwCore are optional. Unlike monolithic 3D graphics libraries, most of the higher-level features can be omitted. Although it's not explicitly stated in the diagram, RpWorld, which provides the Retained Mode API, is itself just a Plugin. 1.3.1 The Core Library, Plugins and Toolkits The RenderWare Graphics components can be broken down: 1. Core Library 2. Plugins 3. Toolkits The first is the Core Library. The Core Library must always be linked into your application as it provides the glue that joins all the components together, as well as basic rendering functionality. I-22 11 February 2004 RenderWare Graphics Architecture Plugins These are the keys to RenderWare Graphics extensibility. Plugins can extend existing objects in both the Core Library and other Plugins – and add their own objects. This feature is what differentiates them from ordinary libraries. RenderWare Graphics' high-level APIs are all implemented as Plugins. Supplied Plugins The following Plugins are supplied as standard with all releases of the SDK: PLUGIN DESCRIPTION RpADC RpAnisot RpCollision RpDMorph RpHAnim RpLODAtomic Address Control flag generation Anisotropy extension for extending textures Collision-detection extensions Delta morphing and delta animation extensions Hierarchical animation plugin Level Of Detail extensions for RpWorld's "RpAtomic" object Render geometry using detailed static lighting information from lightmap textures. Multi-pass special effects, such as environmental mapping, bump mapping, 2-pass Texture mipmap "K" and "L" value extensions Morph-target animation extensions Bézier patch rendering engine Particle animation plugin Creation, management and rendering of user customizable particles Fast visibility culling extension for RpWorld, using Potentially Visible Sets Platform-neutral random number generator Skinned model rendering extensions with multiple bone weights per vertex Spline manipulation extensions Provides functionality for storing user defined data with geometry Attaches UV animations to materials RpLtMap RpMatFX RpMipmapKL RpMorph RpPatch RpPrtStd RpPTank RpPVS RpRandom RpSkin RpSpline RpUserData RpUVAnim RpWorld RenderWare Graphics 3.7 Provides RenderWare Graphics' Retained Mode API – specifically, the scene graph portion of it I-23 Chapter 1 - Introduction Toolkits A Toolkit is an ordinary library that just happens to make use of RenderWare Graphics features. A Toolkit usually provides conversion functions or other utilities. Supplied Toolkits The following Toolkits are supplied as standard with all releases of the SDK: TOOLKIT DESCRIPTION Rt2d Advanced 2D Graphics API utilizing underlying 3D graphics hardware Animation of 2D objects Create, stream and play keyframe animation. Mapping points between the barycentric space and Cartesian space Bézier patch generation utility library Microsoft® Windows® Bitmap image format handling A bitmapped character library Keyframe system supporting compressed matrix animation Generic containers of named objects File system manager and custom file systems Geometry Conditioning Polygon and line intersection testing functions Generation of lightmap textures - used with RpLtMap Texture mipmap "K" value calculation functions Object-picking functions Platform independent texture dictionary streaming Portable Network Graphics image format handling Quaternion manipulation functions Sun® Raster image format handling Ray-casting functions used for picking Skin & Geometry splitter for large bone count models Spherical Linear Interpolation functions Utility functions to allow PVS generation using spline paths Tag Image File Format image format handling Tiled rendering functions (used mainly for very highresolution renderings) Table Of Contents for a stream Vertex Cache Aware Tri-stripper Winged edge/half-edge Utility functions to be used in conjunction with RpWorld Rt2dAnim RtAnim RtBary RtBezPat RtBMP RtCharset RtCmpKey RtDict RtFSyst RtGCond RtIntersection RtLtMap RtMipK RtPick RtPITexd RtPNG RtQuat RtRAS RtRay RtSkinSplit RtSlerp RtSplinePVS RtTIFF RtTile RtTOC RtVCAT RtWing RtWorld I-24 11 February 2004 RenderWare Graphics Architecture RtWorldImport 1.3.2 Utilities for creating RpWorld objects from foreign data formats PowerPipe PowerPipe provides a means of overloading the rendering subsystem either wholly or piecemeal. You can replace or even create entirely new rendering pipeline nodes and clusters. 1.3.3 Namespaces All the RenderWare Graphics functions and objects carry two-letter prefixes to prevent naming clashes with your own code. This has been used to provide the best compromise between readability and name length. The prefixes depend on whether the object in question is part of the Core Library, part of a Plug-in, or part of a Toolkit. They are: PREFIX DESCRIPTION 'Rw' Indicates a function situated in the RenderWare Graphics Core Library ("rwcore.h" / "rwcore.lib"). These functions are always available as long as the core RenderWare Graphics library is linked to your application. Examples: RwEngineStart() RwCameraCreate() 'Rp' Indicates a function situated in a Plugin library (e.g. RpMorph.) In most cases, the name of the Plugin follows the prefix, but this guideline is sometimes ignored to keep function names sensible. The appropriate Plugin must be attached if you intend to use these functions and linked to the appropriate header and library files. Examples: RpMorphPluginAttach() 'Rt' RpPVSAtomicVisible() Indicates a Toolkit. Syntax is similar to that of Plugins, described above. Many Toolkits rely on one or more Plugins being attached, but Toolkits themselves do not need to be attached. Examples: RtSlerpCreate() 'Rx' Used by the PowerPipe API. Examples: RxHeapFree() 'Rs' RenderWare Graphics 3.7 RtTileRender() RxPipelineExecute() Source code to a simple (and very basic) platform abstraction layer used for all examples is provided. Major functions in this layer use an 'Rs' prefix. I-25 Chapter 1 - Introduction Exceptions 1.3.4 These include constants, such as #defines and enum values. These generally use the same prefixes as above, but entirely in lower case, followed by an all-caps name, such as: rwRASTERTYPECAMERA. Just Graphics This may seem obvious, but it is important to remember that RenderWare Graphics only provides multi-platform 3D graphics features. While some utilities are provided, such as an abstraction layer known as the 'Skeleton', this code is not officially supported. Most developers will create their own abstraction layers and write suitable plugins for RenderWare Graphics to provide a consistent programming interface across their supported platforms. 1.3.5 Objects As RenderWare Graphics is written in C and assembler, it makes objectoriented design that little bit harder to implement. C++ classes might need to be written to wrap the RenderWare Graphics API. One important issue to consider is the definition of an object in RenderWare Graphics. In C++, objects are an explicit part of the language's design. RenderWare Graphics 'objects' are either intrinsic, such as int and char, or an ordinary C struct. These usually have a noun for a name – e.g. World, Clump, and Vector. The methods or member functions associated with these objects are ordinary C functions that live outside these structures, but with names that begin with the same name as the 'object'. For instance, a hypothetical object called RwThing might have methods with names like RwThingGetProperty(). RenderWare Graphics objects have been designed to operate in much the same way as C++ objects. The main difference is that there are no member selection operators to separate object names from their associated methods. I-26 11 February 2004 RenderWare Graphics Architecture Objects & Properties Transparent vs. Opaque Objects RenderWare Graphics developers sometimes make a simple object transparent. For such objects, you will find complete documentation of the internals of the object in the API Reference, and often no property-access function information. This reduces unnecessary function calling overheads: you are free to directly change the individual object elements. This reveals the element of trust enshrined with RenderWare Graphics' design: where a data structure is not explicitly documented, it should be considered an opaque object. Usually, such objects will have no documentation for their individual members, so only their associated property access methods (using the traditional 'Get' and 'Set' convention) should be used. The table below shows some examples of opaque objects and access to their members: OBJECT PROPERTY 'METHOD' NAME RwCamera ViewWindow RpAtomic Geometry RwCameraGetViewWindow() RwCameraSetViewWindow() RpAtomicGetGeometry() RpAtomicSetGeometry() The object’s name always forms the root of the function name. This pattern is followed consistently throughout the RenderWare Graphics API. Obviously, the various header files document all members of a particular struct. In general, these members should not be modified in your code, but instead use the functions that are supplied in the library. ✎ 1.3.6 Of course, C doesn't automatically pass the object instance to the functions, so you still have to do this explicitly. Usually, the first parameter of a function will be a pointer to the object. File I/O File handling is an important facet of RenderWare Graphics and for this reason, we provide a file system that can be overloaded. The RwOsGetFileInterface() can be used to obtain a structure containing the pointers to the file operation functions. The file pointers in this structure can be replaced by pointers to your own, which makes it easier to divert file-handling to the DVD, host machine and possibly even over a TCP/IP link. File I/O is enhanced by the file system toolkit, which is composed of a file system manager, and a set of custom file systems for specific platforms. More information on this toolkit can be found the File System Chapter. RenderWare Graphics 3.7 I-27 Chapter 1 - Introduction 1.4 Using RenderWare Graphics 1.4.1 Creating a scene To render scenes in RenderWare Graphics applications, a number of steps need to be performed: 1. Create assets in a modeling package. This includes the background scenery and all the characters, props and other animated models that will populate that scenery. Textures may need creating in a paint package. 2. Export assets in the RenderWare Graphics format. The RenderWare Graphics Retained Mode API supports two kinds of model: static models that live in World objects, and dynamic models that live in Atomic objects. Backgrounds and other fixed scenery models are generally considered static; all other models are dynamic. To add dynamic scenery elements, you should use dynamic models and position them in the scene accordingly. These objects are part of the high-level RpWorld Plugin that encapsulates our Retained Mode API. More on this powerful Plugin can be found in the two chapters: Worlds & Static Models and Dynamic Models. 3. Load assets into the RenderWare Graphics application. RenderWare Graphics includes a multi-platform file serialization API – RwStream – that is used for this purpose. 4. Position them using frames. Frames, described in the Fundamental Types chapter, are an essential feature of the RenderWare Graphics architecture. They are attached to objects so they can be positioned in world space. Frames also manage model hierarchies. 5. Create lights. RenderWare Graphics supports a number of lighting models, as well as both static and dynamic lights, and the standard light model can be overridden. 6. Create a camera object and orient it. RenderWare Graphics uses the standard virtual camera metaphor in the Retained Mode API. This API, and Cameras in general, can be found in the following chapters: Cameras; Worlds & Static Models and Dynamic Models. 7. Take a picture. I-28 11 February 2004 Using RenderWare Graphics This process involves the actual rendering of the scene. 8. Update the scene. If you're producing real-time animation in 3D, you will need to update the models between renderings. 9. Repeat steps 7 and 8 until the user tells the application to quit. This is the rendering process in short. Aside from some of the terminology specific to RenderWare Graphics, this is much the same as in any other 3D graphics API. 1.4.2 Creating prototypes In order to be able to write our examples and other sample code just once, without the need to rewrite it for each target platform, the hardware abstraction layer called the 'Skeleton' has been developed. Almost all the sample code supplied with the SDK will use this code as its foundation. The Skeleton was developed for our sample code. It is not suitable for anything other than similarly simplistic test-beds and prototyping. It is absolutely, categorically not intended for use as the basis for a professional application. However, it does provide a convenient set of functions that can be used for rapid prototyping of games. The Skeleton code is completely unsupported. The source code to it is provided to show you that (a) it can be done, and (b) so that all our tools and examples can be presented in a consistent way. Put another way: the Skeleton is provided as-is and with no guarantee for any suitability or fitness for purpose. You use it entirely at your own risk. RenderWare Graphics 3.7 I-29 Part A Core Library Chapter 2 Fundamental Types Chapter 2 - Fundamental Types 2.1 Introduction This chapter covers many of the basic types that are exposed by RenderWare Graphics. Some types are simple and transparent, meaning you can access them and their elements directly. Others may be opaque and you should use the API provided to manipulate them. If your development is intended to run on multiple platforms then it is suggested that you use RenderWare Graphics' data types throughout your application. The Core Library implements a number of basic data types, such as RwChar, RwUInt16 and so on, which means that you can rely on RenderWare Graphics to ensure that on the different platforms the sizes of these types are correct. For example, you can rely on the RwChar to be the correct size on a particular platform to store characters as these are not guaranteed to be eight bits on all supported platforms. I-34 11 February 2004 RenderWare Graphics & Objects 2.2 RenderWare Graphics & Objects The first chapter explained that RenderWare Graphics is designed along object-oriented principles. As a result, the concept of objects plays an important part in understanding how the API works. Before covering the basic data types then, it is worth looking at the ramifications of this design in a little more detail. 2.2.1 RenderWare Graphics Objects C is not an object-oriented language, so one question frequently asked of the development team is why use C? This question was answered in the previous chapter, but it leaves open the question of how an object-oriented design is implemented. By design, the API looks rather like a C++ based one, without all the extra punctuation. By necessity, the API supports a plugin mechanism which is used to extend the "objects". This extension mechanism is managed programmatically rather than as an intrinsic feature of the programming language. For example, a look at the RpWorld plugin's API will reveal a number of base objects: RwTexture, RpClump, RpWorld and so on. Each of these objects is actually defined as a standard C struct datatype with their "methods" – functions – defined as ordinary functions separate from the data structure. 2.2.2 Object Instantiation This is usually a two-stage process. The first is to define a variable of the object's type. For example: RwTexture myTexture; It is rare for developers to create automatic instances; allocation on the heap is far more common. This example therefore defines myTexture as an object of type RwTexture. However, C does not support a constructor mechanism in the way C++ does, so myTexture has no valid data in it. To reduce bugs caused by referencing uninitialized objects, RenderWare Graphics' API usually provides some form of default object creation function. In the case of Texture objects, the function is RwTextureCreate(), which generates a new Texture from the given Raster object and returns a pointer to the Texture on success. RwTexture myTexture; RwTexture * pmyTexture = RwTextureCreate(); RenderWare Graphics 3.7 I-35 Chapter 2 - Fundamental Types Similar creator functions are provided for most RenderWare Graphics objects and it is advisable to use them where possible. 2.2.3 Object Destruction & Reference Counters As in C++, RenderWare Graphics objects must be destroyed when you are finished with them. This is particularly important if you are working on platforms with limited memory available. However, care is needed to ensure that you do not destroy objects that are still being referenced elsewhere in your code… Although the documentation for RenderWare Graphics talks about things like container objects, these just boil down to objects that contain lists of pointers to the objects they contain. The word pointer is emphasized here because it implies that an object can be referenced by more than one object. For example, a Texture can be "contained" by multiple Materials (part of the World Plugin and a useful container object for Textures), but this just means these Materials would each contain a pointer to the same Texture. So far, so obvious, but multiple references can be a problem when it comes to destroying objects. If a Texture is referenced by multiple objects, some method is needed to prevent it being destroyed before the other objects have finished with it. To avoid this, RenderWare Graphics uses a fairly standard reference counting system. For example, if a Texture is referenced by another object, the Texture's reference counter will be incremented using a call to the Texture's …AddRef() method. (RwTextureAddRef()) When the Texture is removed from that object, its counter is decremented. So if the Texture is referenced by, say, five other objects, its counter will be equal to five. When the Texture is no longer needed by an object, it should be destroyed by calling the object's …Destroy() method. (For Textures, the full function name is RwTextureDestroy().) This function will decrement the reference counter and, if it is zero, finally destroy the object referred to. It is important to note that the reference counting system is not fully automatic. For example, you will need to call …AddRef() and …Destroy() methods directly if you add a reference to a RenderWare Graphics object to a structure of your own. Destruction & Destruction Order The order in which objects are destroyed is an important consideration. RenderWare Graphics programming often involves the use of a number of container objects. A common bug can be brought about by deleting such containers before deleting the contained objects. I-36 11 February 2004 RenderWare Graphics & Objects For example, take the Clump and Atomic objects. These are part of the scene graph API provided by the World Plugin (RpWorld). For now, it's important to know only that Clumps are container objects for Atomics. A common cause of bugs is to destroy a Clump, then destroy each of its contained objects by referencing through the Clump. Obviously, the Clump no longer exists at this point, but many programmers assume that the pointer is still valid as no code has been executed to overwrite the data yet. This is a bad assumption to make: some platforms, including Microsoft Windows, have background tasks running which can easily trigger the overwriting of such data. This is a common cause of intermittent bugs and crashes, so you should always destroy objects in the correct order. RenderWare Graphics 3.7 I-37 Chapter 2 - Fundamental Types 2.3 The Boolean Type RenderWare Graphics supports one Boolean type: I-38 TYPE DESCRIPTION RANGE SIZE RwBool A standard Boolean type with the usual two states FALSE, TRUE 32 bits 11 February 2004 Characters 2.4 Characters TYPE DESCRIPTION RwChar Character type, in either ANSI or Unicode format RANGE SIZE 8 bits (ANSI char) or 16 bits (Unicode) RwChar is intended solely for storing individual characters and character strings (usually 8-bit for ANSI libraries and 16-bit for Unicode libraries). ✎ You should never use RwChar * as pointers to memory as it is wrong to assume it will be equivalent to the C Language "char" type. Use RwInt8 * or RwUInt8 * instead. RenderWare Graphics 3.7 I-39 Chapter 2 - Fundamental Types 2.5 Integer Types RenderWare Graphics is intended to run on a number of platforms. To ensure consistent behavior, new types are defined to replace the base C Language ones. The RenderWare Graphics replacements are designed to behave as consistently as possible over all supported platforms. RenderWare Graphics defines a number of integer types for specific bit widths, which are shown in the table on the following page. These data types are designed to behave identically across all supported platforms. It therefore makes sense to use these instead of the standard C data types in your own applications. I-40 11 February 2004 Integer Types Integer types: TYPE DESCRIPTION RANGE RwInt8 RwUInt8 RwInt16 signed byte (8 bits) unsigned byte (8 bits) signed word (16 bits) RwUInt16 unsigned word (16 bits) RwInt32 signed long (32 bits) RwUInt32 unsigned long (32 bits) RwInt64 64 bit, signed integers should only ever be used on platforms with native and compiler support for 64 bit data types. On other platforms, this data type is defined using a struct so no mathematical operations are available. 64 bit, unsigned integers should only ever be used on platforms with native and compiler support for 64-bit data types. On other platforms, this data type is defined using a struct so no mathematical operations are available. 128 bit, signed integers should only ever be used on platforms with native and compiler support for 128 bit data types. On other platforms, this data type is defined using a struct so no mathematical operations are available. 128 bit, unsigned integers should only ever be used on platforms with native and compiler support for 128 bit data types. On other platforms, this data type is defined using a struct so no mathematical operations are available. -128 to +127 0 to 255 RwInt16MINVAL (-32768) to RwInt16MAXVAL (32767) RwUInt16MINVAL (0) to RwUInt16MAXVAL (65535) RwInt32MINVAL (-231) to RwInt32MAXVAL (231-1) RwUInt32MINVAL (0) to RwUInt32MAXVAL (232-1) -263 to 263-1. No range defining macros are defined. RwUInt64 RwInt128 RwUInt128 RenderWare Graphics 3.7 0 to 264-1. No range defining macros are defined. -2127 to 2127-1. No range defining macros are defined. 0 to 2128-1. No range defining macros are defined. I-41 Chapter 2 - Fundamental Types 2.6 Real Types RenderWare Graphics supports the following real number types: TYPE DESCRIPTION RANGE SIZE RwReal Usually equivalent to the C Language's single-precision "float" type. 16 bit integer, 16 bit fractional fixed point value. Rarely used, as true floatingpoint math is usually faster in current hardware. RwRealMINVAL to RwRealMAXVAL 32 bits RWFIX_MIN to RWFIX_MAX 32 bits RwFixed A common mistake is to forget to provide a trailing "f" on floating point constants. Some platforms have no double precision hardware support. If the "f" is omitted from an expression compiled for these platforms the expression will be assumed to be double precision and it will be emulated in software. This can dramatically reduce performance. It is recommended that you get into the habit of either using type prefixes: RwReal g = 9.8f; RwReal f = m * g; or make use of type-casting in expressions, which is more portable: RwReal g = 9.8; RwReal f = m * (RwReal)g I-42 11 February 2004 Vectors 2.7 Vectors RenderWare Graphics supports two and three dimensional vector types and arithmetic. These types should be considered opaque as they can sometimes map directly onto underlying hardware vector processing units. 2.7.1 Two Dimensional Vectors The 2D Vector type is RwV2d. It contains x and y coordinates. The following functions are provided to manipulate 2D Vectors: FUNCTION OPERATION RwV2dAssign() Assignment (Copy) from a source vector to a target vector Addition Subtraction Length Return a unit normal vector calculated from the original vector Find a Unit Normal line between two vectors Scale Calculate Dot Product Calculate a 2D vector perpendicular to the given 2D vector RwV2dAdd() RwV2dSub() RwV2dLength() RwV2dNormalize() RwV2dLineNormal() RwV2dScale() RwV2dDotProduct() RwV2dPerp() RenderWare Graphics 3.7 I-43 Chapter 2 - Fundamental Types 2.7.2 Three Dimensional Vectors The 3D Vector type is RwV3d. It contains x, y and z coordinates. The table below shows the functions available to work with these vectors: FUNCTION OPERATION RwV3dAssign() Assignment (Copy) from a source vector to a target vector Addition Subtraction Length Calculate unit normal vector from the original vector Scale Multiplies the second 3D vector by the given scalar then adds the resulting vector to the first vector Calculate Dot Product Calculate Cross Product Negation Transform an array of points or vertices by the specified matrix Transform an array of vectors or normals by the specified matrix RwV3dAdd() RwV3dSub() RwV3dLength() RwV3dNormalize() RwV3dScale() RwV3dIncrementScaled() RwV3dDotProduct() RwV3dCrossProduct() RwV3dNegate() RwV3dTransformPoints() RwV3dTransformVectors() I-44 11 February 2004 Coordinate Systems 2.8 Coordinate Systems 3D graphics programming requires understanding of a number of common coordinate systems, known as spaces. Some basic conventions need to be covered. 2.8.1 Right-handed Coordinates RenderWare Graphics uses an orthogonal right-handed coordinate system for its 3D spaces. Typical right-handed coordinate system The figure above displays the positive directions of x, y, and z axes with z pointing away from the screen. Rotate right-handed coordinate system about y axis RenderWare Graphics right-handed coordinate system The RenderWare Graphics coordinate system is rotated about the y axis and the figure on the right displays the positive directions of the x, y and z axes. The positive z axis points into the screen and the positive x axis points to the left. As all the axes are rotated together the coordinate system is always right-handed. RenderWare Graphics 3.7 I-45 Chapter 2 - Fundamental Types Axis Naming Conventions The three axes are defined in RenderWare Graphics by three vectors. By convention, the axis names used are: AXIS VECTOR REPRESENTATION X Y Z "Right" "Up" "At" The vector is sometimes prefixed with the work "look", as in "look-at". This is commonly used when referring to the camera object which "looks" along the z axis. The RenderWare Graphics' coordinate system is right-handed and the x axis is represented by the right vector. However, as the RenderWare Graphics coordinate system is rotated the x axis positive direction points to the left. For example, the RenderWare Graphics camera faces into the screen, therefore we're effectively standing behind it. The camera's right vector points left as the RenderWare Graphics coordinate system has been rotated about the y axis so that z is pointing into the screen. Therefore moving the camera, by incrementing its x axis, results in the camera moving further to the left, along the positive x axis. ✎ I-46 In 3D Graphics terminology, the z axis, represented by the "at" vector, is sometimes referred to as the "front" vector. 11 February 2004 Coordinate Systems 2.8.2 Object Space Dynamic models in RenderWare Graphics are defined in terms of Object Space. This means that the vertices that define the model are relative to an arbitrary origin. For example, the front face of a cube of unit size could be defined thus: (0,1,0) (1,1,0) (0,0,0) (1,0,0) The origin in this case is the lower-left corner of the front face. However, the origin could be anywhere – even the center of the cube. This could be achieved by subtracting (0.5, 0.5, 0.5) from each vertex. The location of the origin can be important, as it is easier to align models if their origins are on a shared edge or a corner rather than at some arbitrary point in the middle or outside the models. RenderWare Graphics 3.7 I-47 Chapter 2 - Fundamental Types 2.8.3 World Space Dynamic models, defined in Object Space, need to have a frame of reference so that they can be positioned relative to other models and scene graph objects. This frame of reference is World Space. Objects positioned relative to this system are said to reside in world space. This coordinate system is used, for example, to specify the position of cameras and lights. Geometry can be positioned in world space using transformations described later. A bounding box defines the World Space limits. This is either generated by a modeling package exporter when exporting World data, or explicitly by the developer when calling RpWorldCreate(). Frames The RenderWare Graphics object that allows us to position objects in World Space is called the Frame (RwFrame). Many RenderWare Graphics objects require a Frame to be attached before they can be positioned within a World. 2.8.4 Camera Space Cameras, like many RenderWare Graphics objects, require a Frame to define their position and orientation. However, there is another system called Camera Space which defines the Camera's viewing coordinate system. A normalized Camera Frustum defines Camera Space as follows: • for a parallel projection model the Camera Frustum space has side planes at x = 0, x = 1, y = 0 and y = 1 • for a Perspective Projection model, it has side planes at x = 0, x = z, y = 0 and y = z Camera Space is also a right-handed system with an origin at the Camera's position (given by the Frame's pos vector). The positive z axis of Camera Space is given by the view direction, which points in the direction of the Frame's at vector. The units of Camera Space z coordinates are the same as those for World Space. RenderWare Graphics also recognizes a two-dimensional coordinate system. 2.8.5 Device Space The device coordinate system defines a device space. Its units are those of the display (screen or window) to which the camera's image buffer is copied and as such, it has coordinates that only take discrete (or integer) values. I-48 11 February 2004 Coordinate Systems The origin of device space is located at the top-left of the display with the xvalues running from left to right and the y-values running from top to bottom, as shown in the diagram: (0,0) +X +Y Device space can also be considered to have a depth component that is used in the Z buffer. RenderWare Graphics 3.7 I-49 Chapter 2 - Fundamental Types 2.9 Matrices RenderWare Graphics defines a pseudo-4x4 homogeneous Matrix (RwMatrix) object to represent 3D transformations. The Frame object, see 2.10 below, makes heavy use of matrices. Matrices in RenderWare Graphics appear as shown below: R x R y Rz U x U y U z A A Az y x P P Pz y x 0 0 0 1 The row vector (Rx, Ry, Rz) contains the components of the look-right vector, (Ux, Uy, Uz) are those of the look-up vector, (Ax, Ay, Az) for the look-at vector and (Px, Py, Pz) are the components of the pos vector. The components of a matrix are available to the application programmer by using RwMatrixGetRight(), RwMatrixGetUp(), RwMatrixGetAt() and RwMatrixGetPos(). 2.9.1 Matrix Mathematics in RenderWare Graphics Matrices are treated as quadruples of row vectors. Each row vector is a triple of real values. The vectors are the right, up and at vectors, which orient a Cartesian coordinate system, and the pos vector that positions this coordinate system with respect to a parent coordinate system. In conventional 4×4 matrix form, there is an implied last column of (0,0,0,1)T. The equations for matrix multiplication can then be expanded as shown below. C = A×B RxA ⋅ RxB + RyA ⋅ UxB + RzA ⋅ AxB A B Ux ⋅ Rx + U yA ⋅U xB + UzA ⋅ AxB A B A B A B Ax ⋅ Rx + Ay ⋅ Ux + Az ⋅ Ax P A ⋅ RB + PA ⋅ U B + PA ⋅ AB + PB y x z x x x x RxA ⋅ RyB + RyA ⋅ U yB + RzA ⋅ AyB UxA ⋅ RyB + U yA ⋅U yB + UzA ⋅ AyB RxA ⋅ RzB + RyA ⋅ UzB + RzA ⋅ AzB UxA ⋅ RzB + U yA ⋅UzB + U zA ⋅ AzB AxA ⋅ RyB + AyA ⋅ U yB + AzA ⋅ AyB AxA ⋅ RzB + AyA ⋅ UzB + AzA ⋅ AzB PxA ⋅ RyB + PyA ⋅ U yB + PzA ⋅ AyB + PyB PxA ⋅ RzB + PyA ⋅ UzB + PzA ⋅ AzB + PzB RxA A Ux A Ax PA x RyA U yA AyA PyA RzA U zA AzA PzA 0 0 = 0 1 0 RxB RyB RzB 0 UxB U yB U zB × 0 AxB AyB AzB 1 PxB PyB PzB Matrix multiplication is not commutative so, the order of the arguments passed to RwMatrixMultiply() is significant. Transformation of a position is performed mathematically in the following manner: I-50 11 February 2004 0 0 0 1 Matrices v = u×M T u x ⋅ Rx + u y ⋅ U x + u z ⋅ Ax + Px u x ⋅ R y + u y ⋅ U y + u z ⋅ Ay + Py u ⋅ R + u ⋅ U + u ⋅ A + P = (u x y z z z z x z 1 uy uz Rx R y Rz U x U y U z 1)× A Ay Az x P P P y z x 0 0 0 1 This is the operation performed by RwV3dTransformPoints(). This function is used to transform position vectors. There is also an RwV3dTransformVectors() function, which transforms vectors (e.g. normals). In this case, the matrix is assumed to contain a zero position vector and so does not contribute to the output vectors. ✎ Put another way: a direction vector is never translated, but only rotated. Using RwV3dTransformPoints() with normals, or RwV3dTransformVectors() with vertices will give strange results. The order of matrix transformations has an effect on the visible orientation of Atomics, as discussed (see 2.10.3 below). RenderWare Graphics 3.7 I-51 Chapter 2 - Fundamental Types 2.10 Frames RwFrame objects contain two matrices. These are the Local Transformation Matrix (or LTM), and the Modeling Matrix. These two matrices can be retrieved using RwFrameGetLTM() and RwFrameGetMatrix(), respectively. When transformations are performed on a frame (see next paragraph), it is the Modeling Matrix that is affected. (The LTM describes the total transformation from Object Space to World Space.) Unless the Frame belongs to a hierarchy, the Modeling and Local Transformation Matrices are identical. Otherwise, the Modeling Matrix is relative to the Frame's parent. Frames can be transformed using RwFrameTranslate(), RwFrameRotate(), RwFrameScale() and RwFrameTransform(). Rotation and scaling is accrued in the top-left 3x3 sub-matrix, while translation is accumulated in the bottom row. Given a transformation matrix, individual points and vectors (both of type RwV3d) can be transformed using RwV3dTransformPoints() and RwV3dTransformVectors(). Hierarchical modeling is the process of building models that preserve the hierarchical structure of objects and allow the position and orientation of an object in the hierarchy to be specified relative to its parent. I-52 11 February 2004 Frames 2.10.1 Hierarchical Models & RenderWare Graphics Hierarchical modeling explicitly models articulation, or joints, connecting objects. In RenderWare Graphics, these joints are represented by frames (RwFrame). These only define the hierarchy itself. The model data itself is sectioned, with each section stored in an atomic (RpAtomic). An atomic can be linked to a frame, with collections of atomics and frames thus forming a hierarchical model. Consider, for example, the modeling of a robot arm consisting of an upperarm, lower-arm and a hand represented by three atomics. We wish to model the arm so that movement of the upper-arm is transferred to the lower-arm and hand whilst movement of the lower-arm only affects the hand. Assume each atomic has its own frame (see API function RpAtomicSetFrame()). Then the required articulation can be achieved by attaching the lower-arm's frame as a child of the upper-arm's frame and, similarly, attaching the hand's frame as a child of the lower-arm's frame. The API function RwFrameAddChild is used to accomplish this. Upper Arm Lower Arm Hand Frame1 Frame 2 Frame 3 Atomic1 Atomic2 Atomic3 The modeling matrix of each frame is now described relative to the Frame's parent Frame object and the corresponding LTM becomes the concatenation of all the modeling matrices up to the root Frame, in this case the Frame on the upper-arm's atomic. For each case we have: LTM1=MM1 LTM2=MM2⊗LTM1 LTM3=MM3⊗LTM2 (where LTM = local transformation matrix and MM = modeling matrix.) Only the root Frame's modeling and local transformation matrices are identical. The object hierarchy is shown schematically above. Frame1 is the parent of Frame2 (therefore, Frame2 is the child of Frame1), while Frame2 is the parent of Frame3. Note that the arrangement of the Atomics is determined entirely by the frame hierarchy. If these Atomics were all added to a single Clump object, the Clump would impose no organization. Because a Clump is designed as a container for Atomics, it can be assumed that the Clump must order its Atomics but, as you can see, this is not how it works. RenderWare Graphics 3.7 I-53 Chapter 2 - Fundamental Types To model the robot hand in more detail by adding some fingers: • give the hand three fingers represented by three more Atomics. • build the hand hierarchy by attaching all the fingers' Frames as children of the hand's Frame (see diagram above). All the fingers' Frames (frame4, frame5, frame6) are child frames of the hand's frame and siblings of each other. In terms of the LTMs we have, for example: LTM4=MM4⊗ LTM3 This means the LTM of frame4 is the concatenation of the modeling matrices of Frames Frame1, Frame2, Frame3 and Frame4 – this is the same for the other fingers. Movement of the hand is now automatically transferred to all the fingers. It is recommended, though it is by no means required, that the hierarchy is encapsulated within a Clump which has its own Frame – see RpClumpSetFrame() – acting as the root of the Frame hierarchy. For example, Frame1 would be attached to the Clump's frame (say, Frame0,) as a child of that Frame. Also, each of the Atomics must be added the Clump using RpClumpAddAtomic() for this organization to work correctly. Frames and the Local Transformation Matrix Frame objects contain a matrix called the Local Transformation Matrix, (usually abbreviated to "LTM"). This matrix is used when working with hierarchies of Frame objects. Local Transformation Matrices are constructed by traversing the hierarchy from top to bottom. At each level in the hierarchy, the modeling matrix is pre-multiplied into the local transformation matrix from the level above to form the LTM for the current level. Because the LTM is used to post multiply vectors this means that the transformation stored in the lowest frame in the hierarchy affects the vertex first of all: U = V ⋅ M n ⋅ M n −1 ⋅ Λ ⋅ M 1 ⋅ M 0 In this equation, the Local Transformation Matrix at the root of the hierarchy is M0 and that at the bottom of the hierarchy is Mn, where there are n+1 levels in the hierarchy. 2.10.2 Traversing Frame Hierarchies There are two methods for traversing an object hierarchy depending on whether it is Frames or the objects hanging from them. It is assumed that a hierarchy of Frames and Atomics assembled into a Clump where the Clump's Frame acts as the root of the hierarchy. I-54 11 February 2004 Frames All Frames in the hierarchy may be iterated over using the RwFrameForAllChildren() iterator. Starting at the root Frame, this function will apply a user-defined callback to all first generation child Frames. Repeating RwFrameForAllChildren() on each callback will then iterate over all second generation, i.e. grandchild, frames, and so on. Also, for each Frame encountered a call to RwFrameForAllObjects() applies a callback to each object attached to the Frame. ✎ RwFrameForAllChildren() will only take you down one level in a hierarchy. You must use your callback function to call RwFrameForAllChildren()again to go down the hierarchy another level, so your callback should be designed for recursion. If the Frame hierarchy is not important, a call to the RpClumpForAllAtomics() iterator will iterate over all the Atomics registered with a Clump. The supplied user-defined callback function will be applied to each Atomic in turn. 2.10.3 Matrix Combination Flags in RenderWare Graphics Matrix and frame transformation functions in RenderWare Graphics (for example, RwFrameTransform()and RwMatrixRotate()) take a parameter, combineOp. This parameter is used to control the order in which the transform is applied to the matrix or Frame. The available combine operators are: replace, pre-concatenate, and postconcatenate. • rwCOMBINEREPLACE assigns the new transformation to the matrix. The original contents of the matrix are entirely replaced by the new transform. RwMatrixTranslate(M, t, rwCOMBINEREPLACE) builds a new matrix containing only a translation, and stores this matrix in M. Any rotation component in the matrix M is overwritten with a 3x3 identity sub-matrix. This is true for all matrix-transforming functions where the rwCOMBINEREPLACE flag is used. • rwCOMBINEPRECONCAT causes the transform matrix to be preconcatenated onto the matrix. This has the effect of applying the transformation before the transformation already in the matrix. Put another way: this operator causes the transformation to be made in object space (or the coordinate space of the matrix). • rwCOMBINEPOSTCONCAT instructs RenderWare Graphics to postmultiply the transformation into the matrix. The new transformation will take effect after the transform already in the matrix. In other words, the transformation takes place in world space. RenderWare Graphics 3.7 I-55 Chapter 2 - Fundamental Types Example Consider a call made to RwFrameScale() with a Frame F, and a vector S encoding the scale. The effect of changing the combination operator will be looked at. Firstly, however, it should be pointed out that the function alters the modeling matrix in the frame. ✎ A RenderWare Graphics application should never modify the LTM matrix directly, since the library is responsible for computing this matrix from the Modeling Matrix and the LTMs of the Frame hierarchy. In this example the modeling matrix, denoted M, is stored in Frame F. Notionally, the RwFrameScale() function computes a scale transformation matrix, S. This will be a 4x4 zero matrix with a diagonal encoding the elements from the scale vector, and 1: sx 0 S= 0 0 0 sy 0 0 0 0 sz 0 0 0 0 1 The table below illustrates the result of varying the combine operator on the matrix M. I-56 OPERATOR RESULTING MATRIX (M) rwCOMBINEREPLACE rwCOMBINEPRECONCAT rwCOMBINEPOSTCONCAT S SM MS 11 February 2004 Bounding Boxes 2.11 Bounding Boxes The Bounding Box (RwBBox) object defines a bounding box using two points: sup (supremum) and inf (infimum). These two points define diametrically opposite corners of the box, such that for any axis, the value in the inf coordinate is never larger than the value in the sup coordinate. The illustration below shows how this works in practice: Sup Inf The resulting box therefore represents a 3D axis aligned cuboid volume. Bounding boxes provide the basis for simple tests to determine whether specific coordinates in the coordinate space are bounded by the volume. The box may also be expanded to include another point within its volume, using the RwBBoxAddPoint() function. Another test available is RwBBoxContainsPoint(), which can be used to check if a vertex is inside or outside a Bounding Box. RwBBoxAddPoint() can also be used together with the RwBBoxInitialize() function. This takes a single vertex and initializes both the inf and sup elements to this point. RwBBoxAddPoint() can be called repeatedly to expand the Bounding Box to contain any arbitrary number of points. This technique is useful if the number of points involved is unknown. If, on the other hand, you do have a fixed-length array of vertices, you can use the RwBBoxCalculate() function to perform a similar operation to the above. This function is usually the more efficient of the two systems. RenderWare Graphics 3.7 I-57 Chapter 2 - Fundamental Types 2.12 Lines RenderWare Graphics naturally supports a basic line type. This is called RwLine and it is defined by two RwV3d objects denoting the start and end vertices. The RwLine object is used typically as an intersection primitive. Do not confuse the RwLine object with an immediate mode line, which is a renderable object. I-58 11 February 2004 Rectangles 2.13 Rectangles Rectangles are defined by the RwRect type. This type takes a positioning vector to locate the rectangle, as well as two parameters defining its width and height. As with lines above, the RwRect object is not renderable. Rectangles are typically used to define sub-regions of the screen. RenderWare Graphics 3.7 I-59 Chapter 2 - Fundamental Types 2.14 Spheres RenderWare Graphics defines the RwSphere type. This contains both a center and a radius as elements to define the location and size of the sphere. Spheres are heavily used during Retained Mode rendering to determine which models are within the Camera Frustum. Using spheres for the initial tests makes for rapid culling. Once this coarse-level checking has been performed, the remaining models can then be tested and clipped more accurately. Note that this object is not renderable, and is used primarily for intersection testing. I-60 11 February 2004 Colors 2.15 Colors RenderWare Graphics defines two color representation types: RwRGBA, which is an integer-based primitive for describing colors, and RwRGBAReal, which defines colors using real numbers rather than integers. The RwRGBA form is the most used as it corresponds closely with most of our supported platforms. This structure contains four RwUInt8 elements, one for each of the Red, Green, Blue and Alpha components. Although the RwRGBA format is fixed, the bitmap facilities offered by RenderWare Graphics are not and may differ widely in color element format. It is therefore possible that conversion may be needed when extracting or modifying individual pixels in a bitmap and such processing should thus be kept to a minimum. See the chapter on Rasters, Images and Textures for information on these items and their colors. RwRGBAReal defines four RwReal elements for red, green, blue and alpha. It is intended to be used in cases where high orders of accuracy are needed while processing colors. Values range from 0.0f to 1.0f. RenderWare Graphics 3.7 I-61 Chapter 3 Initialization & Resource Management Chapter 3- Initialization & Resource Management 3.1 Introduction RenderWare Graphics Core Library contains the base feature-set of the API. All other features are optional, provided in the form of either Plugins or Toolkits. The Core Library's functionality is divided up into the following broad categories: • Memory management • OS-level file and memory management • Plugin management • Basic objects and intrinsic types, such as RwInt32, RwBBox, RwMatrix, RwImage, etc. • 2D and 3D immediate modes • PowerPipe extensible rendering pipeline • Platform-Specific APIs (where applicable) • Managing rendering time through the Lock and Unlock commands. This chapter focuses on the memory management, plugin management and file management features of the core library. I-64 11 February 2004 Basic Housekeeping 3.2 Basic Housekeeping At the heart of RenderWare Graphics is the RwEngine object. This engine performs a number of housekeeping functions, including: • Initialization and shut-down procedures • Selecting the display device and video mode • Querying the underlying hardware about its capabilities • Updating metrics information (when linked to the Metrics libraries) • Managing Plugins All RenderWare Graphics applications have to initialize the engine before calling any other RenderWare Graphics functions. We'll look at this process next. 3.2.1 Initialization Getting the RenderWare Graphics engine up and running is a three-step process: 1. Initialization of memory management and default file system interface 2. Setting the video mode 3. Plugins and starting RenderWare Graphics and there are three functions you need to call: 1. RwEngineInit() 2. RwEngineOpen() 3. RwEngineStart() These functions must be called in the above order and you cannot start rendering until after the RwEngineStart() call. Why the three steps? RenderWare Graphics has to make allowances for the many platforms it supports. Splitting the start-up process into three stages lets us open up such features as file and memory management, as well enabling the plugin architecture to operate properly. Let's look at these steps in terms of what they're for… RenderWare Graphics 3.7 I-65 Chapter 3- Initialization & Resource Management Step 1 - Initialization of Memory Management and Default File System Interface This first step concerns the API function RwEngineInit() and involves setting up the memory and file-handling subsystems. Why Does the Engine need to be Initialized First? RwEngineInit() must always be the first RenderWare Graphics function your application calls as all other functions assume the memory management facilities have been set up. For example, the plugin mechanism needs to access these memory functions, so they need to be set up before any Plugins are attached. Similarly, the display device your application will use may also need some memory allocated for it. So again, we have to make sure the memory subsystem is ready first. The Memory Functions By default, RenderWare Graphics uses the standard ANSI memory functions, as implemented by the target platform's compiler, so any replacement functions must have identical prototypes to their ANSI counterparts. In theory, the application can replace the default RenderWare Graphics handlers with its own at any time. In practice the application should change the memory handler only at this initialization stage, rather than later. Changing the memory and file handling subsystems within the main loop of your application is possible, but not recommended as it can make debugging much more difficult. Pointers to the functions are stored in the RwMemoryFunctions structure returned by RwOsGetMemoryInterface(). If necessary, the entries in this structure can be overwritten directly with your own function pointers, but this is not recommended as the change takes place immediately—if memory has already been allocated with the original functions, then it is likely that memory will be "lost" to your application. Your application should create a new RwMemoryFunctions structure with pointers to your own functions, then pass a pointer to the structure to RwEngineInit(). The File Functions The file system is implemented in a similar way to the memory system, with a structure containing pointers to default POSIX functions used by default. Again, any replacement functions will need to share the same prototypes as the functions they will be replacing. I-66 11 February 2004 Basic Housekeeping A file functions structure filled with the default functions can be retrieved using RwOsGetFileInterface(). To replace these default function pointers with your own, overwrite the entries in the structure. Your functions will then be used when accessing files. Step 2 - Setting the Video Mode At this stage, you will need to: • Open the RenderWare Graphics Engine • Determine which graphics subsystem the application should be using, as some platforms can support more than one • Determine the video display mode the application should use. Video hardware varies greatly from platform to platform, so this procedure requires some additional steps of its own. Opening the RenderWare Graphics Engine The RenderWare Graphics Engine can be opened using RwEngineOpen(). Choosing the Graphics Subsystem The RenderWare Graphics API represents a graphics device as a graphics subsystem. The application must first determine how many graphics subsystems are available. This requires a call to RwEngineGetNumSubSystems(). With this information, the application iterates through the available subsystems, checking each one for suitability. This is achieved by calling RwEngineGetSubSystemInfo() and interrogating the structure returned. The following code fragment illustrates this process by printing out the identifying names of all graphics subsystems on a particular platform: RwInt32 numSubSystems, i; RwSubSystemInfo ssInfo; numSubSystems = RwEngineGetNumSubSystems(); for(i=0; izScale and camera->zShift for Z and offZ respectively. This is the technique used by the non-hardware T&L version of RenderWare Graphics. I-146 11 February 2004 2D Immediate Mode Vertices While the result of working with 2D Immediate Mode is primitives rendered on a display, your code will actually work directly with vertices, so let's take a look at these now. The vertex is the main data type for RenderWare Graphics' Immediate Mode APIs. There are two such types, one each for 2D and 3D Modes. The 2D Immediate Mode form is RwIm2DVertex. As with its RwIm3DVertex counterpart, this data type's physical format is platform-dependent, so you shouldn't try to access it directly. Instead, the API provides a complete set of functions to prepare and manipulate the vertex. Note: These functions are implemented as C Macros in most cases to provide optimum performance. 7.2.2 Initializing an RwIm2DVertex object As mentioned earlier, this object is defined in a platform-specific way. This prevents us from documenting its structure. Initializing such objects is therefore performed entirely through the API. An RwIm2DVertex object contains the following properties: • Red, Green, Blue and Alpha components • Camera-space coordinates (X, Y and Z) • Reciprocal of Camera's Z coordinate • Screen-space coordinates (X, Y and Z) • U and V coordinates Setting & Retrieving Coordinates 2D Immediate Mode vertices are usually in screen space and this means the RwIm2DVertex objects are also known as "device vertices". Since this vertex object is not exposed as a structure, you need to use the API functions, RwIm2DVertexSetScreenX(), RwIm2DVertexSetScreenY() and RwIm2DVertexSetScreenZ(), to set these coordinates programmatically. These functions have counterparts that can be used to retrieve these same values: RwIm2DVertexGetScreenX(), RwIm2DVertexGetScreenY() and RwIm2DVertexGetScreenZ(). It is also possible to specify coordinates in terms of camera space – the functions are: RwIm2DVertexSetCameraX(), RwIm2DVertexSetCameraY(), RwIm2DVertexGetCameraX() and RwIm2DVertexGetCameraY(). RenderWare Graphics 3.7 I-147 Chapter 7 - Immediate Mode Reciprocal Camera Z, Texture Coordinates & Platform Dependence The underlying platform's hardware has a great impact on the vertex object. Often, the RwIm2DVertex (and its 3D Immediate Mode counterpart) are simply wrappers for a hardware-specific data type. This means that even the format of the colors can change. For instance, some platforms require colors to be specified in floating point form while others prefer integer values. This is why, if you look at the API Reference entries for the two Immediate Mode APIs, you'll find color setting functions that accept both formats. This gives you the option of either sticking to one color format – the functions will convert where necessary – or changing the format from platform to platform if you prefer that level of control. In order for some rendering techniques, including Gouraud shading and perspective-correct texture mapping, to work correctly, you may need to specify the reciprocal camera-space Z coordinate of a vector and/or the actual camera-space Z coordinate itself. This is an important facet of Immediate Mode programming: some functions simply don't exist on some platforms; on others, different functions may be required to achieve the same effects. In the case of the reciprocal of Camera Z, the function (if available) to obtain this is RwIm2DVertexGetRecipCameraZ(). (There is an equivalent RwIm2DVertexSetRecipCameraZ() function too if the former is available.) The reciprocal camera Z value is generally required to enforce perspectivecorrect texture mapping. Texture coordinates can therefore also be specified if your primitive(s) are to be so rendered. Currently, the vertex object will only support one texture – multi-texturing is planned – so setting the U and V coordinates is a matter of calling the appropriate RwIm2DVertexSetU() and RwIm2DVertexSetV() functions respectively. ✎ I-148 The API Reference is rebuilt specifically for each platform so it will only contain the relevant platform-specific entries. Other platforms have different builds of the API Reference with different platform-specific entries as appropriate. 11 February 2004 2D Immediate Mode 7.2.3 Primitives RenderWare Graphics supports two major types of primitive: Lines and Triangles. These are in turn split into subtypes. Lines are split into line lists and poly-lines. Line Lists These are lists of vertex pairs defining the start and endpoints of lines. This data format is ideal for rendering groups of unconnected lines. Poly-lines This is a list consisting of one start point, followed by any number of endpoints. The Immediate Mode rendering engine will start at the first point, draw a line to the first endpoint and draw another from the end of that line to the next endpoint in the list. This primitive is ideal for sequences of connected lines. Except for the first line, the poly-line primitive type does not require two vertices to be processed per line. This means it needs the least data to work and is therefore the most efficient of the line primitives. If possible, use this primitive type when working with lines. ✎ Rendering individual lines can be done using RwIm2DRenderLine(). This function allows you to draw individual lines between arbitrary vertices. (See the API Reference for more details.) It should be noted, however, that drawing individual lines in this way is not recommended as it can be slow. RenderWare Graphics also supports a number of triangle primitives: Triangle Lists ("Tri-List") These are similar to the Line Lists mentioned earlier. They consist of triplets of vertices defining individual triangles. This implies that triangles in a trilist are entirely independent of each other. Triangle Strips ("Tri-Strip") These define strips of adjacent triangles, each sharing an edge with another. This form requires fewer vertices than the Triangle Lists type as, after the first triangle is defined, only one additional vertex is needed to define each subsequent triangle. This has significant performance benefits on most platforms. RenderWare Graphics 3.7 I-149 Chapter 7 - Immediate Mode The diagram to the right demonstrates the advantage of tri-strips. Once the first three vertices (shown as rings in the diagram) have defined the first triangle, only one additional vertex is required to add each new triangle to the strip. In the diagram, the second step shows a fourth vertex defining the second triangle (shown in red) and in the third step, we have just five vertices defining three triangles. Obviously, this format is more efficient as you add more triangles. Triangle Fans ("Tri-fan") These are similar in concept to triangle strips, relying on contiguous triangles to reduce the number of vertices that need to moved around and processed. As you can see from the example to the right, a triangle fan requires that all triangles share a vertex and are contiguous. This form has much the same advantages as triangle strips. Both the strip and fan forms are popular with transform and lighting processing hardware, so RenderWare Graphics is biased somewhat in their favor on most supported platforms. ✎ 7.2.4 The triangle fan and triangle strip primitives are not built on the fly by RenderWare Graphics' rendering engine. The RenderWare Graphics modeler exporter plugins allow you to export geometry optimized for triangle strips and/or fans. Triangle Winding Order Throughout RenderWare Graphics, the ordering of the vertices defining a triangle – the winding order – also define its visibility. RenderWare Graphics' use of a right-handed coordinate system means triangles with vertices defined in clockwise order (relative to the camera) have a normal pointing away from the camera and are therefore not visible, so they will not be drawn. In summary: visible Triangles must have vertices defined in anti-clockwise order, relative to the camera, as the normal to the Triangle is pointing towards the camera. I-150 11 February 2004 2D Immediate Mode 7.2.5 Primitives vs. Indexed Primitives 2D Immediate Mode can work directly with arrays of primitives, which are in any case just arrays of vertices. It can also work with arrays of indices to such arrays of vertices. This second technique is particularly important as it opens up more efficient use of system memory. In particular, it lets you re-use vertices rather than having define duplicates. The SDK includes a number of Examples, including the im2d Example. This illustrates 2D Immediate Mode by rendering a number of different primitives, including indexed and non-indexed forms. RenderWare Graphics 3.7 I-151 Chapter 7 - Immediate Mode 7.2.6 Example 1: Rendering A Line. This code fragment renders a single, simple, opaque red line: RwIm2DVertex vertex[2]; // Set up the vertices... RwIm2DVertexSetScreenX(&vertex[0], 20.0f ); RwIm2DVertexSetScreenY(&vertex[0], 20.0f ); RwIm2DVertexSetScreenZ(&vertex[0], 3276.0f ); RwIm2DVertexSetRecipCameraZ(&vertex[0], (1.0f/6.0f) ); RwIm2DVertexSetScreenX(&vertex[1], 620.0f ); RwIm2DVertexSetScreenY(&vertex[1], 460.0f ); RwIm2DVertexSetScreenZ(&vertex[1], 3276.0f ); RwIm2DVertexSetRecipCameraZ(&vertex[1], 1.0f/6.0f ); // Opaque red... RwIm2DVertexSetIntRGBA(&vertex[0], 255, 0, 0, 255); // ...and the same for the second vertex. RwIm2DVertexSetIntRGBA(&vertex[1], 255, 0, 0, 255); // Texturing off... RwRenderStateSet(rwRENDERSTATETEXTURERASTER, NULL); // Flat shading on... RwRenderStateSet(rwRENDERSTATESHADEMODE, (void *)rwSHADEMODEFLAT); // Alpha-transparency off... RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE); //Render line... RwIm2DRenderLine(vertex, 2, 0, 1); ✎ Release Builds There appear to be a lot of function calls involved in this code, but the overhead is not as bad as it first appears. The RenderWare Graphics libraries are supplied in three builds: Release, Metrics and Debug. Release builds redefine many trivial functions as macros. The upshot is that almost all property setting and access functions, such as those above, are inlined. I-152 11 February 2004 2D Immediate Mode Example 2: Rendering A Triangle. This code fragment renders a simple, yellow, flat shaded triangle: RwIm2DVertex vertex[3]; //Set up the vertices... RwIm2DVertexSetScreenX(&vertex[0], 20.0f ); RwIm2DVertexSetScreenY(&vertex[0], 20.0f ); RwIm2DVertexSetScreenZ(&vertex[0], 3276.0f ); RwIm2DVertexSetRecipCameraZ(&vertex[0], (1.0f/6.0f) ); RwIm2DVertexSetScreenX(&vertex[1], 20.0f ); RwIm2DVertexSetScreenY(&vertex[1], 40.0f ); RwIm2DVertexSetScreenZ(&vertex[1], 3276.0f ); RwIm2DVertexSetRecipCameraZ(&vertex[1], (1.0f/6.0f) ); RwIm2DVertexSetScreenX(&vertex[2], 40.0f ); RwIm2DVertexSetScreenY(&vertex[2], 40.0f ); RwIm2DVertexSetScreenZ(&vertex[2], 3276.0f ); RwIm2DVertexSetRecipCameraZ(&vertex[2], (1.0f/6.0f) ); // Opaque yellow... RwIm2DVertexSetIntRGBA(&vertex[0], 255, 255, 0, 255); // Opaque yellow... RwIm2DVertexSetIntRGBA(&vertex[1], 255, 255, 0, 255); // ...and, once again, opaque yellow... RwIm2DVertexSetIntRGBA(&vertex[2], 255, 255, 0, 255); // Texturing off... RwRenderStateSet(rwRENDERSTATETEXTURERASTER, NULL); // Flat shading mode... RwRenderStateSet(rwRENDERSTATESHADEMODE, (void *)rwSHADEMODEFLAT); // Alpha-transparency off... RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE); // Render triangle... RwIm2DRenderTriangle(vertex, 3, 0, 1, 2); As you can see from the examples above, there is an overhead involved in setting up the RenderState data. Because of this, it makes sense to group all your primitives by RenderState to speed up the rendering process. RenderWare Graphics 3.7 I-153 Chapter 7 - Immediate Mode 7.3 3D Immediate Mode 3D Immediate Mode provides low-level 3D rendering facilities. It is designed around the same concepts as its 2D counterpart, including the concepts of vertex lists, index lists and primitives. In addition, it makes heavy use of RenderWare Graphics' Render State API to control the rendering process. 7.3.1 Preparation for Rendering Vertices & Indices 3D Immediate Mode has its own vertex object: RwIm3DVertex. This holds coordinates defined using either world space (also known as 'scene space'), or in object space. This distinction is covered in more detail later. As with the 2D Immediate Mode's own vertex object, RwIm3DVertex is also an opaque, platform-dependent type. Access is entirely through the API. In fact, there isn't all that much to say about the 3D vertex object: aside from the extra dimension, it's relatively straightforward and the API is similar to that for 2D Immediate Mode's own RwIm2DVertex object. Where the 3D Immediate Mode API does differ slightly from the 2D one is that setting coordinates is done through a single function call: RwIm3DVertexSetPos(). This takes the X, Y and Z coordinates as well as a pointer to the RwIm3DVertex where they are to be stored. A retrieval function, RwIm3DVertexGetPos(), is also provided. As with the 2D Immediate Mode, 3D Immediate Mode expects vertices to be stored in arrays. These arrays can be referenced either directly or using an index array. The latter has the expected advantage of requiring fewer vertices, but can cause problems if your model geometry is to be adjusted in real-time. ✎ Unlike its 2D counterpart, the 3D Immediate Mode API provides clipping. Transforming Space To determine how a particular vertex maps to the display device, the 3D Immediate Mode API provides a function that takes an array of 3D vertices and transforms them to camera space (which is much the same thing as device space). The function that performs this feat is the RwIm3DTransform() function. This takes four parameters, the third of which is an optional parameter specifying an additional transformation matrix to be applied. This transformation matrix should be set when working with vertex arrays, which use object space. The matrix will be used to map the object to world space and then to camera/device space. I-154 11 February 2004 3D Immediate Mode The RwIm3DTransform() function normally produces two new arrays, one of camera space vertices and – for those vertices that lie within the camera frustum – an array of device space (device-dependent) vertices. Access to these intermediate data representations should be performed very carefully. They are platform-dependent, some hardware accelerators may store these new arrays in strange formats – or even not at all. Additional Vertex Properties As well as the usual three coordinates, each 3D Immediate Mode vertex can store RGBA values. These are set using the RwIm3DVertexSetRGBA() function. (The function accepts 8-bit unsigned integers, so floating point RGBA formats will need to be converted first.) The remaining two properties are U and V coordinates for texturing. The functions for setting these are RwIm3DVertexSetU() and RwIm3DVertexSetV() respectively. Both functions take an RwReal value for the texture coordinates. ☛ The 'impick' Example This example lets you pick and drag vertices in wireframe 3D Immediate Mode models. The commented code therefore illustrates a wide variety of Immediate Mode programming techniques. Lighting Lights are not supported in 3D Immediate Mode. You can simulate them by manipulating the vertex colors in accordance with a custom lighting model. RenderWare Graphics 3.7 I-155 Chapter 7 - Immediate Mode 7.3.2 Rendering Rendering in 3D Immediate Mode requires following this sequence: 1. Transform the primitives into camera space 2. Perform any rendering with the primitives 3. Terminate pipeline execution The primitives supported by 3D Immediate Mode are simply extensions of those found in the 2D mode: line lists, polylines, triangle lists, triangle strips and triangle fans. Again, the same trade-offs apply. The screenshots below illustrate some of the primitives in action. All are from the im3d Example. This first shot is the polyline form in action. (The code used to display this is contained within the polyline.c source file.) The next shot shows the triangle list primitive. (The code that exercises this primitive can be found in trilist.c.) I-156 11 February 2004 3D Immediate Mode We recommend you take a look through and modify the code that makes up this Example as it illustrates the salient features of this particular API. Render States 3D Immediate Mode rendering makes heavy use of render state settings. More on these in 7.4 Render States. As with the 2D Immediate Mode API, the most efficient way to handle render states is to group primitives with the same state and render them in batches, switching render states between each batch. Rendering primitives Two rendering functions are available for this: RwIm3DRenderPrimitive(), which renders non-indexed primitive types, and its counterpart RwIm3DRenderIndexedPrimitive(), which renders indexed ones. For instance, the following line… RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, myIndices, 8); …would be used to render an indexed triangle list. The relevant array indices are stored in the myIndices array, and there are 8 such indices to render. ✎ Remember that the RwIm3DTransform() function has already taken this array and transformed it into camera-space vertices. The PowerPipe Transform node caches these internally. It is these converted vertices that are referenced during any rendering. If your target platform allows it, it may be possible to access these converted vertex arrays using RenderWare Graphics' platform-specific API. The exact functionality available will likely vary from platform to platform. RenderWare Graphics 3.7 I-157 Chapter 7 - Immediate Mode 7.3.3 Closing the pipeline Once rendering of your array of primitives is complete, you must call RwIm3DEnd() to close and flush the rendering pipeline. 7.3.4 3D Immediate Mode & PowerPipe 3D Immediate Mode rendering makes use of RenderWare Graphics' PowerPipe rendering technology. When you transform an array of vertices with RwIm3DTransform(), you are actually firing up PowerPipe and calling its default pipeline. ✎ Many of our platforms are provided only with generic transform and render nodes. These nodes do not support all of the primitives. For instance, the generic transform node will expand triangle fans into ordinary triangle lists. The transform node also does not support unindexed primitives and will create indices for them, so you should use indexed rendering wherever possible. However, all PowerPipe nodes can be overridden by your own, so two functions are provided to give you direct access to the Transform and Rendering nodes. They are, respectively, RwIm3DGetTransformPipeline() and RwIm3DGetRenderPipeline(). Should you wish to revert to the generic nodes, you can obtain pointers to the generic transform and render nodes using RwIm3DGetGenericTransformPipeline() and RwIm3DgetGenericRenderPipeline(). On platforms that support Transform & Lighting in hardware, overloading the generic node will cause a software pipeline to be used. This will have a negative impact on performance so you may need to write your own hardware T&L node. Once the pipeline is fired up, it transforms and renders the supplied vertices. It's important to understand that the only way to transform some more vertices at this stage is to close down the pipeline using RwIm3DEnd() and restart it with RwIm3DTransform(). This is not the obstacle it appears, as you will usually render batches of primitives sorted by Render State anyway. It is not possible to nest Transform/End sequences. As you can see, efficient management of this process is the key to getting maximum performance out of RenderWare Graphics' 3D Immediate Mode. Uses for 3D Immediate Mode RenderWare Graphics provides a very rich Retained Mode API, which would lead many to suspect 3D Immediate Mode of being of relatively little use. Nothing could be further from the truth! 3D Immediate Mode is ideally suited to the rendering of program-generated data. For example, particle system explosions and other scenery effects are often added to a scene using this API. Other techniques include producing pseudo-3D imagery, such as that seen in some real-time strategy games. (Although produced long before RenderWare Graphics was released, Cavedog's "Total Annihilation" series is a good example of pseudo-3D.) I-158 11 February 2004 3D Immediate Mode An important use is for rendering of scientific data or mathematical models that don't map easily to traditional modeling paradigms. One of our developers has taken advantage of this aspect of 3D Immediate Mode to create a groovy multicolor lava lamp simulator using a marching cube algorithm. 7.3.5 Platform Specific Information Some platforms do their vertex transforms in hardware and cannot provide access to the transformed vertices. You should refer to the platform-specific documentation to see what functionality is available in this regard. Similarly, texture coordinates may have restrictions imposed by their underlying hardware. Again, you should refer to the platform-specific documentation to see if this applies to your target platform. RenderWare Graphics 3.7 I-159 Chapter 7 - Immediate Mode 7.3.6 Camera-space and Z-buffer depth equations The mapping functions that convert from camera space to screen depth space are provided here for information: Perspective Camera: Z − Z min R ( z − Rmin ) max Z ( z ) = Z min + max z Rmax − Rmin Parallel Camera: Z − Z min ( z − Rmin ) Z ( z ) = Z min + max Rmax − Rmin Where: • Z(z) is the Z-buffer value corresponding to a camera space z-coordinate z. • Zmax, Zmin are the maximum and minimum Z-buffer values, respectively. They correspond to the Z-buffer values given by Z(Rmax) and Z(Rmin). Their values may be queried using the API functions RwIm2DGetFarScreenZ() and RwIm2DGetNearScreenZ(). • Rmin, Rmax are the distances to the far and near clip planes, respectively. Their values may be queried using the API functions RwCameraGetFarClipPlane() and RwCameraGetNearClipPlane(). I-160 11 February 2004 3D Immediate Mode 7.3.7 Rt2D This Toolkit provides a 2D graphics API. Its power is such that it could justifiably be considered a kind of Retained Mode API for 2D graphics. Unlike 2D Immediate Mode, which deals solely with the most basic rendering chores, the 2D Toolkit also supports features such as resolutionindependence, scaleable fonts, paths, textured polygons, anti-aliasing, alpha blending effects, free rotation and scaling, clipping, rendering to any arbitrary Camera object, and more. Its power is derived from RenderWare Graphics' 3D graphics capabilities. This means it can make full use of any 3D graphics acceleration hardware to produce great 2D imagery. So why use 2D Immediate Mode? 2D Immediate Mode is a thin API. This makes it much better suited to fast, simple 2D operations of the type often required to create a user interface. Icons, debugging messages, quick bitmap font routines, side-panels, simple sprites and so forth are generally easier to produce using the 2D Immediate Mode API. RenderWare Graphics 3.7 I-161 Chapter 7 - Immediate Mode 7.4 Render States Briefly, the Render State object is a basic state machine. It is an opaque object, with two API functions provided to access its properties: RwRenderStateSet() and RwRenderStateGet(). 7.4.1 Key Features • Render States are a shared hardware resource. There is only one Render State structure and it is shared throughout RenderWare Graphics. Therefore, 2D Immediate Mode shares this with both the 2D and 3D Retained Mode APIs – Rt2D and RpWorld, respectively. • There is no multi-platform default setting for the Render State structure. This is because some platforms may not support all the Render State settings, or support them in different ways. Instead, the default setting for the Render State varies from platform to platform. • The application is responsible for ensuring any required state(s) are set correctly. Some high-level portions of the RenderWare Graphics API, such as RpWorld, may change the Render State settings if they need to. You should not assume that a particular Render State has been left untouched by, say, a call to RpWorldRender(). • Some Render State settings are unsupported on certain platforms. RenderWare Graphics does not provide any software emulation as such, so if a platform does not support a particular Render State feature, setting it will have no effect. 7.4.2 API The Render State API (RwRenderState) differs from most other APIs in that there is only one Set/Get pair of functions. They are RwRenderStateSet() and RwRenderStateGet() respectively. Both functions take two parameters: an enumerated type and a void pointer. The enum or 'render state specifier' determines which render state the function is to set or get. The void pointer holds the data. So the void pointer is used as an arbitrary 32-bit value whose contents depend on the value of the render state specifier. The programmer is responsible for checking the type of this parameter as the compiler will not check the type of void pointers. (Types cast to void in these function calls include RwRaster *, RwBool, and other enumerated types.) I-162 11 February 2004 Render States Currently, the following render states are supported: • rwRENDERSTATETEXTURERASTER Use this render state to set the Raster object to texture with. For example: RwRaster * myRaster; RwRasterCreate( myRaster ); RwRenderStateSet( rwRENDERSTATETEXTURERASTER, (void *)myRaster); • rwRENDERSTATETEXTUREADDRESS Use this render state to tell RenderWare Graphics how to handle the texture coordinate space. The options are: rwTEXTUREADDRESSWRAP, rwTEXTUREADDRESSCLAMP, rwTEXTUREADDRESSMIRROR or rwTEXTUREADDRESSBORDER. The values to pass as the void pointer are those described in the API Reference under RwTextureGetAddressing(). This render state will set both U and V handling to the same operation. The following two enumerated values can be used to set the U and V spaces individually so you can have different behavior for each: - rwRENDERSTATETEXTUREADDRESSU, - rwRENDERSTATETEXTUREADDRESSV, Example 1: Set both U and V coordinate spaces to Clamp mode: RwRenderStateSet( rwRENDERSTATETEXTUREADDRESS, (void *) rwTEXTUREADDRESSCLAMP); Example 2: Set V coordinate space to Wrap mode: RwRenderStateSet( rwRENDERSTATETEXTUREADDRESSV, (void *) rwTEXTUREADDRESSWRAP); • rwRENDERSTATETEXTUREPERSPECTIVE Pass TRUE or FALSE in the void pointer. TRUE enables perspective correction. • rwRENDERSTATEZTESTENABLE Pass TRUE or FALSE in the void pointer. TRUE enables Z-buffer tests. • rwRENDERSTATESHADEMODE Can be set to either rwSHADEMODEFLAT or rwSHADEMODEGOURAUD. • rwRENDERSTATEZWRITEENABLE Pass TRUE or FALSE in the void pointer. TRUE enables Z-buffer writes. RenderWare Graphics 3.7 I-163 Chapter 7 - Immediate Mode • rwRENDERSTATETEXTUREFILTER Texture filtering method. The values you can pass are as follows: - rwFILTERNEAREST, - rwFILTERLINEAR, - rwFILTERMIPNEAREST, - rwFILTERMIPLINEAR, - rwFILTERLINEARMIPNEAREST, - rwFILTERLINEARMIPLINEAR See the Rasters, Images and Textures chapter for more detailed information on these. • rwRENDERSTATESRCBLEND Used to set the source blending factor. • rwRENDERSTATEDESTBLEND Used to set the destination blending factor. • rwRENDERSTATEVERTEXALPHAENABLE Pass TRUE or FALSE in the void pointer. TRUE enables vertex alpha transparency. • rwRENDERSTATEBORDERCOLOR Border color for texturing with borders. The argument should be RGBA components packed into an RwRGBA value and cast to a void pointer. • rwRENDERSTATEFOGENABLE Pass TRUE or FALSE in the void pointer. TRUE enables fogging effects. (All polygons rendered from this point on until this is set to FALSE will be affected.) • rwRENDERSTATEFOGCOLOR Color used for fogging. The argument should be RGBA components packed into an RwRGB value cast to a void pointer. • rwRENDERSTATEFOGTYPE Select the type of fogging to use. Valid arguments are: - rwFOGTYPELINEAR, - rwFOGTYPEEXPONENTIAL, - rwFOGTYPEEXPONENTIAL2 The precise algorithms used vary from platform to platform, but are broadly similar. Read the documentation supplied with your target platform for more details on how fogging is implemented. I-164 11 February 2004 Render States On current platforms, linear fog will be faster than exponential forms. ✎ Not all platforms support all three fogging formats. • rwRENDERSTATEFOGDENSITY Defines the density of exp and exp2 fogging. The density should be an RwReal value cast to a void pointer. See the platform-specific documentation for the range(s) allowed. • rwRENDERSTATEALPHATESTFUNCTION Defines the alpha test function to accept or reject a pixel depending on it’s alpha value. Valid arguments are: - rwALPHATESTFUNCTIONNEVER, - rwALPHATESTFUNCTIONLESS, - rwALPHATESTFUNCTIONEQUAL, - rwALPHATESTFUNCTIONLESSEQUAL, - rwALPHATESTFUNCTIONGREATER, - rwALPHATESTFUNCTIONNOTEQUAL, - rwALPHATESTFUNCTIONGREATEREQUAL, - rwALPHATESTFUNCTIONALWAYS • rwRENDERSTATEALPHATESTFUNCTIONREF Defines the alpha test reference value associated with the alpha test function. Valid argument range is between 0 and 255, inclusive. ✎ 7.4.3 In all cases, the RwRenderStateGet() and RwRenderStateSet() functions will return FALSE if a particular render state is unsupported. Blending The Render State structure includes two blending settings, rwRENDERSTATESRCBLEND and rwRENDERSTATEDESTBLEND. These functions are used to control the blending of the rendered imagery with the data already extant in the target Raster. The components of the final pixel color value in the frame buffer are obtained according to the formula: (i ) (i ) (i ) (i ) (i ) C Out = B Src C Src + B Dest C Dest (for i = R, G, B, A) B Src : source blend factor C Src : source color B Dest : destination blend factor C Dest : destination color (frame buffer) RenderWare Graphics 3.7 I-165 Chapter 7 - Immediate Mode Several options are available for the source and destination blend factors, but there are some platform specific restrictions.The following are available for all platforms: rwBLENDZERO rwBLENDONE rwBLENDSRCALPHA rwBLENDINVSRCALPHA rwBLENDDESTALPHA rwBLENDINVDESTALPHA (0, 0, 0, 0) (1, 1, 1, 1) (As, As, As, As) (1-As, 1-As, 1-As, 1-As) (Ad, Ad, Ad, Ad) (1-Ad, 1-Ad, 1-Ad, 1-Ad) As and Ad are the source and destination alpha values respectively. On PlayStation 2, certain combinations of these factors for source and destination cannot be used together due to the underlying blend equation. See the API reference for more details. Note also that the DESTALPHA modes are only valid when the frame buffer actually contains an alpha channel. The following color blend factors are supported in any combination in RenderWare Graphics for Xbox, D3D8 and D3D9 but have more limited availability on other platforms:rwBLENDSRCCOLOR rwBLENDINVSRCCOLOR rwBLENDDESTCOLOR rwBLENDINVDESTCOLOR (Rs, Gs, Bs, As) (1-Rs, 1-Gs, 1-Bs, 1-As) (Rd, Gd, Bd, Ad) (1-Rd, 1-Gd, 1-Bd, 1-Ad) PlayStation 2 does not support them at all. OpenGL and GameCube only support DESTCOLOR factors for SRCBLEND and SRCCOLOR factors for DESTBLEND. One further mode is supported for Xbox and D3D8: • rwBLENDSRCALPHASAT 7.4.4 (f, f, f, 1), where f = min(As, 1- Ad) Sorting Alpha Primitives Current versions of RenderWare Graphics do not support sorting of alpha primitives for you. It is therefore necessary to perform such processing explicitly in your application. This issue is explored in one of our FAQ. I-166 11 February 2004 Chapter 8 Serialization Chapter 8- Serialization 8.1 Introduction RenderWare Graphics supports both a low-level file I/O API and a highlevel streaming API which is used for serialization of objects. This chapter covers the low-level file I/O API, which is similar in design to most ANSI-based operating system APIs. However, the main focus is on the streaming API. I-168 11 February 2004 File I/O API 8.2 File I/O API The low-level file I/O API deals with file-level access to storage devices. It exposes a file I/O interface based on the standard ANSI interface included with most C compilers. The interface is exposed through the RwFileFunctions structure, a pointer to which can be obtained through a call to RwOsGetFileInterface(). This structure contains pointers to the file I/O functions and a default set is installed by default by RenderWare Graphics upon initialization. The default functions implement the functionality either by using the platform's C compiler's default implementation (if available), or by passing the file I/O requests to a platform's underlying operating system. The following table lists the RwFileFunctions element names, its associated ANSI file I/O function, and its purpose. Due to the popularity of the ANSI file I/O interface, it is assumed developers are familiar with these functions and their usage. STRUCTURE ENTRY ANSI NAME PURPOSE rwfexist rwfopen rwfclose rwfread rwfwrite rwfgets() fexist() fopen () fclose () fread () fwrite () fgets () rwfputs() fputs () rwfeof() feof () rwfseek() fseek () rwfflush() fflush () rwftell() ftell () Returns TRUE if the file exists Opens a file for reading/writing Closes an opened file Reads data from a file Writes data to a file Reads a null-terminated string from a file Writes a null-terminated string to a file Returns TRUE if the end of the file has been passed Moves the file pointer to the specified point in the file Flushes any data written to a file from the internal cache Returns the current position of the file pointer in a file The application can replace the default functions by overwriting the entries in the RwFileFunctions structure with pointers to custom functions. The replacements must use the relevant function prototype. For this purpose, suitable prototype typedefs have been defined. These typedefs are highlighted in bold within the function prototypes given in the table below. RenderWare Graphics 3.7 I-169 Chapter 8- Serialization ANSI NAME PROTOTYPE fexist() fopen() RwBool (*rwFnFexist)(const RwChar *name); fclose() fread() fwrite() fgets() fputs() feof() fseek() fflush() ftell() I-170 void *(*rwFnFopen)(const RwChar *name, const RwChar *access); int (*rwFnFclose)(void *fptr); size_t (*rwFnFread)(void *addr, size_t size, size_t count, void *fptr); size_t (*rwFnFwrite)(const void *addr, size_t size, size_t count, void *fptr); RwChar *(*rwFnFgets)(RwChar *buffer, int maxLen, void *fptr); int (*rwFnFputs)(const RwChar *buffer, void *fptr); int (*rwFnFeof)(void *fptr); int (*rwFnFseek)(void *fptr, long offset, int origin); int (*rwFnFflush)(void *fptr); int (*rwFnFtell)(void *fptr); 11 February 2004 RenderWare Binary Streams 8.3 RenderWare Binary Streams RenderWare Graphics supports the concept of binary streams. A binary stream is a data format which allows data to be streamed to files or through a network connection. Only the former is supported explicitly. The binary stream mechanism is also used to support serialization of objects and this API relies on the low-level file I/O API described earlier, in section 1.2. 8.3.1 Binary Stream Structure The binary stream format is used when serializing all serializable objects. For example, static worlds (RpWorld) can be serialized to a binary stream and so can dynamic models (RpClump). Binary streams are normally written to, or read from, files. Such files can contain one or more serializable objects, so a system of chunk IDs—also known as object type IDs—is used to identify the specific entities within the stream. For example, the RenderWare Graphics SDK comes with a number of demonstrations and examples. Most of these load model geometry and other related data from individual files with an extension of either ".dff" for dynamic models, or ".bsp" for static models. Both of these file extensions are used purely to remind the programmer what is in each file. Both file types are fundamentally the same: both are binary streams and accessed using the same binary stream API. Note that from RenderWare Graphics 3.5, some file types are now considered "legacy": .dff and .bsp are among these. The default file type for new RenderWare Graphics binary streams is .rws. These .rws files encapsulate the data that the legacy file types would have contained and group related binary data together into a single container. The binary streaming methods remain unchanged however. See 8.3.4 RWS files for more information on .rws files. ✎ The meaning of "legacy" file types is that in the future, the RenderWare Graphics exporters may not export to these file types. However, the binary format of these files continues to be supported, and this version of RenderWare Graphics will read them. There is no need to re-export existing DFF/BSP/etc. artwork as RWS files. Although the examples provided with the SDK use individual files for each dynamic model or world, an application could keep all its data in a single binary stream if needed. This is one such use for an .rws file. The Header When an object is serialized, the data is preceded by a chunk header, represented by the RwChunkHeaderInfo structure: RenderWare Graphics 3.7 I-171 Chapter 8- Serialization • length – length of the chunk data in bytes • type – chunk ID, which can either be one of the following or a custom application-created ID: − rwID_ATOMIC - an atomic (type RpAtomic). − rwID_CAMERA - a camera (type RwCamera). − rwID_CLUMP - a clump (type RpClump). − rwID_GEOMETRY - a geometry (type RpGeometry). − rwID_IMAGE - an image (type RwImage). − rwID_LIGHT - a light (type RpLight). − rwID_MATERIAL - a material (type RpMaterial). − rwID_MATRIX - a matrix (type RwMatrix). − rwID_TEXDICTIONARY - a texture dictionary (type RwTexDictionary). − rwID_TEXTURE - a texture (type RwTexture). − rwID_WORLD - a world (type RpWorld). − rwID_CHUNKGROUPSTART – start of a chunk group (type RwChunkGroup) − rwID_CHUNKGROUPEND – end of a chunk group (type RwChunkGroup) • version – version of the chunk data Chunk Types The key to the streaming mechanism is in the type element. This element denotes the type of object stored in the chunk referred to by the chunk header. When a plugin is attached, it registers its supported object type IDs with the streaming API. The type ID should be created using the MAKECHUNKID macro. This macro is also used to create plugin IDs, but plugins rarely implement more than one serializable object, so the plugin ID can also be used as the object type ID. ✎ I-172 If a custom plugin does implement more than one object, you should ensure that the additional object IDs are unique. If you need more than 256 unique IDs, you should contact Criterion Software Ltd. to obtain additional Vendor IDs, each of which can be used to create a further 256 unique IDs. 11 February 2004 RenderWare Binary Streams Complex Chunks Chunks can contain other chunks, so a complete stream can be parsed as a tree-like hierarchy. Such chunks are known as complex chunks. The strview applet, which can be located in [SDK-ROOT]/tool/strview, illustrates this aspect of RenderWare Graphics' binary streams by displaying the structure of any valid stream as a hierarchical view. An example of the stream viewer in action can be seen in the screenshot on the next page. Complex chunks are handled transparently by callbacks which are registered with the streaming API. In the screenshot below, the structure of a typical RpClump container object is clearly visible, with its list of RwFrame objects, RpGeometry objects and RpAtomic objects. The stream viewer applet 8.3.2 Serializing Objects Although there is a trend towards originating 3D graphics data algorithmically, most 3D graphics data is streamed into memory from a storage device. Given RenderWare Graphics' target market, this is usually either a CD, DVD or hard disk. The streaming of extended or derived object data requires the creation of additional functions. We saw these in the Plugin example (see the Plugins: Creation & Usage chapter), but didn't see them in action. RenderWare Graphics 3.7 I-173 Chapter 8- Serialization Look for TestPluginStream() in the ClumpPhysics example's main.c file. This function, which is predicated on a build-time #define called TESTSTREAM, was included in this source code so you can see how the RenderWare Graphics Binary Stream facility is used. You may want to activate it, by defining the TESTSTREAM constant, and step through the code in your debugger to watch what it does. Registering the Stream Functions If you look at the source code, you'll notice that none of the three stream functions created for the new plugin appear to be called directly. This is because these functions are called directly by the clump object's own stream functions. Objects that support extension via the plugin mechanism and support for binary streams have two registration functions. Respectively, these are: • Rp[PLUGIN-NAME]RegisterPlugin() • Rp[PLUGIN-NAME]RegisterPluginStream() In the ClumpPhysics plugin example, both functions are called in the RpClumpPhysicsPluginAttach() function. The second of the two registration functions, RpClumpRegisterPluginStream(), is the one that tells the clump object about our own stream functions. The RpClumpRegisterPluginStream() function accepts three function pointers. Respectively, these are for reading, writing and returning the size of the additional data our functions will place into the stream. ✎ It is important to note that RpClumpRegisterPluginStream()is part of the RpClump plugin, not the ClumpPhysics plugin. All plugins that need to support extension of their binary streams must implement their own registration function to allow this. For example, the ClumpPhysics plugin would need to implement an RpClumpPhysicsRegisterPluginStream() function. Determining the Size of a Chunk A stream chunk is not assumed to be fixed in size. One reason for this is that plugins may extend existing chunk types rather than utilizing their own. Another issue is that some platforms work better if data is padded to a certain minimum block size. (This is often the case on consoles which make heavy use of caches and other hardware tricks.) Every chunk type needs to have its own chunk size function. This function will call the chunk size functions for any extensions within that chunk so, if another plugin extends the same chunk, it too must implement a chunk size function. This gives RenderWare Graphics a means by which it can determine the full size of a chunk: adding up the results of all the chunk size functions implemented for a chunk type gives the total size of the complex chunk. I-174 11 February 2004 RenderWare Binary Streams Reading and Writing Writing platform independent data to a stream is not as straightforward as it sounds. RenderWare Graphics' multi-platform nature means we have to take into account such things as packing sizes, default datatype sizes and even the endian-ness of the data. Otherwise, data written out on one platform may not be readable on another. Endian-ness Depending on the processor used at the heart of your target platform, data can be stored in one of two formats: big-endian or little-endian. This defines the byte-order of datatypes larger than a single byte when these are stored in RAM. The table below uses hexadecimal notation to show the difference between the two forms when storing the hexadecimal 4-byte number "0x12345678": BIG-ENDIAN LITTLE-ENDIAN 0x12 0x34 0x56 0x78 0x78 0x56 0x34 0x12 As you can see, all the endian-ness means is which order bytes are stored. Little-endian format places the least significant byte ("LSB") first, while bigendian format places the most significant byte ("MSB") first. This means you cannot simply throw your data structures at the stream as there's no guarantee that the raw bytes will be read back correctly on another platform. The solution is to standardize on some basic datatypes and make sure the endian-ness of the streamed data is consistent across all platforms. In RenderWare Graphics, we've chosen little-endian format as our standard. This was picked mainly because we use PCs to develop on and these use little-endian format. This standard is used for all streams, regardless of platform, so streams written on a big-endian platform will be converted to little-endian form. On platforms that use little-endian format, no endian-ness conversion takes place. The table below shows which of our key platforms uses which storage format: PLATFORM CPU STORAGE FORMAT Sony PlayStation 2 Microsoft Xbox PC (Direct3D / OpenGL) MacOS (OpenGL) MIPS-based core Intel Pentium III Various x86compatible CPUs Little-endian Little-endian Little-endian Motorola / IBM PowerPC Motorola / IBM PowerPC Big-endian NINTENDO GAMECUBE RenderWare Graphics 3.7 Big-endian I-175 Chapter 8- Serialization Endian-ness Conversion The endian-ness of individual platforms makes it impossible to create data streams that are cross-platform compatible without some conversion work. The RwMem part of the core library API provides such conversion functions. Some of the streaming functions—see the next section—perform these conversions internally. However, you must use the conversion functions described here if your application uses only the basic RwStreamRead()/RwStreamWrite() functions. An important point to note is that none of the RwMem conversion functions will change the physical size of the data being converted, so a "Float32" occupies the same number of bytes as an RwReal value. This makes calculating the size of the data to be read or written easier. The functions are: • RwMemFloat32ToReal() Used when reading from the stream: this function reverses the conversion process performed by RwMemRealToFloat32() and gives you back your original array of RwReal values. The RwMemNative32() function should be called first. • RwMemLittleEndian32() RwMemLittleEndian16() Used when writing to the stream: this function converts the integer data you've pointed it at and converts the data to little-endian format if necessary. (On platforms that natively use little-endian format, this function has no effect.) • RwMemNative32() RwMemNative16() Used when reading from the stream: this function converts the littleendian data read in from the stream into the native endian-ness of the platform. (As with its counterpart, this function has no effect if the platform uses little-endian format.) • RwMemRealToFloat32() Used when writing to the stream: this function converts an array of RwReals to a standard 32-bit floating point format for streaming. The appropriate RwMemLittleEndian32() function should be called after this. Reading & Writing to a Stream Once the data has been converted, the RwStream API is used to write the individual data elements to the stream. When reading data, the process is reversed. I-176 11 February 2004 RenderWare Binary Streams Endian-ness Conversion Endian-ness conversion must be performed explicitly if using the RwStreamRead()/RwStreamWrite() functions. However, when using the streaming functions that know about their type—such as RwStreamReadInt32() or RwStreamWriteReal()—you do not need to perform explicit endian-ness conversion: these functions perform the conversion internally. It is usual for developers to avoid using RwStreamRead()/RwStreamWrite() wherever possible. The following two tables list the read and write functions respectively. Stream Reading Functions These functions read data from a binary stream. Those functions with an explicit datatype as part of their name will perform any endian-ness conversions internally, if necessary. READ FUNCTION PURPOSE RwStreamRead() Reads the specified number of bytes from the specified stream into the given data buffer. RwStreamReadChunkHeaderInfo() RwStreamReadInt16() RwStreamReadInt32() RwStreamReadReal() RwStreamSkip() RenderWare Graphics 3.7 This function requires explicit endian-ness conversion. Reads the Chunk Header information and stores it into the RwChunkHeaderInfo structure provided. (Intended mainly for diagnostics.) Reads an array of 16-bit RwInt16 values from the stream into the specified buffer. Reads an array of 32-bit RwInt32 values from the stream into the specified buffer. Used to read an array of RwReal data values from the stream into the specified buffer. Used to skip the specified number of bytes in the given stream. I-177 Chapter 8- Serialization Stream Writing Functions These functions write data to a binary stream. Those functions with an explicit datatype as part of their name will perform any endian-ness conversions internally, if necessary. WRITE FUNCTION PURPOSE RwStreamWrite() Writes the specified number of bytes to the specified stream from the given data buffer. This function requires explicit endianness conversion. Used to write a chunk header to the specified stream. This function would typically be used by an application wishing to write application specific data to a file. Writes an array of 16-bit RwInt16 values to the stream from the specified buffer. Writes an array of 32-bit RwInt32 values to the stream from the specified buffer. Used to write an array of RwReal values to the stream from the specified buffer. RwStreamWriteChunkHeader() RwStreamWriteInt16() RwStreamWriteInt32() RwStreamWriteReal() 8.3.3 Explicit Streaming Functions In many cases, RenderWare Graphics' supplied plugins implement and expose streaming functions to serialize their objects explicitly. The RpClumpStreamRead() function is an example of such a function. When developing custom plugins and objects, it is worth considering exposing similar, high-level functions. This makes it easier for developers using the plugin to stream the plugin's data without having to explicitly parse its individual components—a task which becomes a chore if the plugin is a complex one. Another, very important, advantage of implementing high-level functions in this way is so that the function can perform any required pre- or postprocessing transparently. This avoids the need for developers to remember to perform such processes explicitly. In most cases, you will have already implemented the necessary low-level functionality needed to implement high-level functions, so adding them to your plugin's API is usually trivial. I-178 11 February 2004 RenderWare Binary Streams Using Explicit Streaming Functions In the previous section, 8.3.2 Serializing Objects, we looked at serialization from within a plugin. This is important to know, but what if your application needs to read or write an object to a stream directly? Although it is not entirely necessary for it to do so, it is good practice for your plugin to implement high-level stream-read and stream-write functions. The application to which the plugin is attached should be responsible for managing the streams. This is best illustrated with an example. Reading a Clump Object The clump (RpClump) object, part of the World plugin (RpWorld), is a complex object, containing additional objects such as frames (RwFrame) and atomics (RpAtomic). All this complexity is handled by callback functions set up by the plugin itself when it is attached to your application. This makes reading a clump object very simple. First, we need to declare our stream and clump objects: RwStream *stream; RpClump *newClump; Next, we open our binary stream: stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, "myclump.rws"); (Remember, the .rws filename extension is purely a reminder that this is a RenderWare Graphics binary stream.) Now we can check that the stream was opened and locate our clump object within the stream: if( stream ) { if( RwStreamFindChunk( stream, rwID_CLUMP, NULL, NULL) ) The RwStreamFindChunk() function call above locates the first occurrence of a chunk with a chunk ID of rwID_CLUMP. An .rws file may contain more than one clump, so it may be necessary to identify each clump unless the developer is aware of the exact contents of the file. One method by which the identification may take place is by using a table of contents (TOC). See 8.3.4 RWS files for information about TOCs in .rws files. RenderWare Graphics 3.7 I-179 Chapter 8- Serialization With the correct chunk located, the application can now read the clump data. { newClump = RpClumpStreamRead(stream); } Finally, we should close the stream as we no longer need to read anything else from it. RwStreamClose(stream, NULL); } Writing a Clump Object This process is rare within a game, but applications written as part of a tool-chain, such as an exporter for a modeling package, will need to perform this operation frequently. Writing an object is very similar to reading one. Again, we'll use a clump object for our example, which will assume that myClump contains a valid clump object for writing. First, we need to declare our stream object: RwStream *stream; Next, we need to open a stream for writing. This uses the same function as for reading, but with a different flag. (These flags are covered in section 8.3.5, Stream Types.) stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMWRITE, "myclump.rws"); At this point we should check that the stream was opened: if( stream ) { Now the data can be written to the stream: RpClumpStreamWrite( myClump, stream ); } Finally, the stream should be closed: RwStreamClose(stream, NULL); Designing an Explicit Streaming API It is not a requirement that a plugin exposes a high-level streaming API as there are a number of different ways in which a plugin can be implemented. Two examples of plugins that may not need such an API are: I-180 11 February 2004 RenderWare Binary Streams • Plugins that extend existing objects – if a plugin extends an existing object, there is usually no need for a high-level API. This is because streaming the original object will automatically cause RenderWare Graphics' streaming API to call the appropriate callbacks for the extended data. • Plugins that implement objects that do not need to be streamed – for instance, a plugin designed for run-time diagnostics may not need to serialize its objects at all. If there is nothing to be gained by allowing your plugin to stream its objects, don't implement a streaming API for it. However, if you decide your plugin does need to support explicit serialization of its objects, you will need to use the RwStreamRead() and RwStreamWrite() functions—as outlined in 8.3.2 Serializing Objects. Chunk Headers Any object that supports streaming must explicitly write a header chunk by calling RwStreamWriteChunkHeader() with both the chunk ID (discussed in 8.3.1 Binary Stream Structure) and the size of the object's data. It is important to note that reading the object data from a stream does not require the reading of the chunk header as the call to RwStreamFindChunk()—made by the calling application—performs this process. RenderWare Graphics 3.7 I-181 Chapter 8- Serialization 8.3.4 RWS files RWS files, identified by the .rws extension, extend the concept of RenderWare Graphics' binary streams to group related streams together into a single stream. An .rws file is designed to contain any number of clumps, worlds, texture dictionaries, etc. For example, it would be common to find a world and its textures together in an .rws file. There are no specific streaming functions for .rws files. The developer should just use the standard RenderWare Graphics read/write streaming functions described in this chapter on a single stream. The default export option in the RenderWare Graphics exporters for 3dsmax and Maya are to save .rws files. The Visualizer viewer also is capable of reading .rws files. Given broad uses of grouping related streams together, a single .rws file may contain many objects. .rws files may contain marker blocks called ‘chunk groups’ which bracket groups of chunks between ‘start’ and ‘end’ chunks. The ‘start’ chunks also contain asset names as specified from within the exporters. These marker blocks may be used from within your own toolchain to locate assets by name. .rws files also usually contain another type of object at their head called an RtTOC, or Table of Contents (TOC), to keep track of what the .rws file contains. Chunk Group A chunk group, RwChunkGroup, is a marker added to a stream to group and identify other data chunks. Its purpose is to add a name to a single or a group of chunks not available with RwChunkHeaderInfo. These can be used by the toolchain applications to identify groups of chunks that correspond to assets named within the exporters. A RwChunkGroup is created by the function RwChunkGroupCreate() and destroyed by RwChunkGroupDestroy(). A RwChunkGroup contains a fixed length string. This string is set by the user using RwChunkGroupSetName() and is used to label other data chunks in the stream. A group of data chunks is labeled by wrapping it between a group header and group trailer chunk. The group header chunk consists of a standard RwChunkHeaderInfo, with ID rwID_CHUNKGROUPSTART, and a data block with the RwChunkGroup data. The group trailer chunk just consists of the chunk header, rwID_CHUNKGROUPEND. No extra data blocks are currently written out for the group trailer chunk. I-182 11 February 2004 RenderWare Binary Streams To write out label information for a group of data chunk, the group header chunk must first be written out. This is achieved by calling the function, RwChunkGroupBeginStreamWrite(). Data chunks belonging to this group are then written out as normal using the appropriate streaming functions. Finally the group trailer chunk is written immediately after the last data chunk using RwChunkGroupEndStreamWrite(). The following is an example snippet of code to write out a group of data chunks with a chunk group label. /* First write out the header. */ if (RwChunkGroupBeginStreamWrite(stream, group)) == group) { /* Write out any data chunks here. */ /* Write out the trailer. */ if (RwChunkGroupEndStreamWrite(stream, group) == group) { /* Success. */ } else { /* Write trailer chunk error. */ } } else { /*Write header chunk error. */ } Reading a header chunk is similar to reading a standard data chunk. Once a header chunk is found, by the chunk header ID, rwID_CHUNKGROUPSTART, the function, RwChunkGroupBeginStreamRead() is used to read in a RwChunkGroup. A matching trailer chunk, rwID_CHUNKGROUPEND, will be read to mark the end of group. Example code to read a RwChunkGroup and its group of data chunks: /* First read in the chunk header. */ if (RwStreamReadChunkHeaderInfo(stream, &chunkInfo) == stream) { /* Check the type. */ if (chunkInfo.type == rwID_CHUNKGROUPSTART) { /* Read in the group header. */ group = RwChunkGroupBeginStreamRead(stream); if (group) { /* Read in any data chunks. */ RenderWare Graphics 3.7 I-183 Chapter 8- Serialization /* Read in the group trailer. */ if (RwStreamReadChunkHeaderInfo( stream, &chunkInfo) == stream) { /* Check the type. */ if (chunkInfo.type == rwID_CHUNKGROUPEND) { /* Success. */ } else { /* Possible error. * Unless it is nested. */ } } else { /* Read chunk header error. */ } } else { /* Read chunk group data error.*/ } } } else { /* Read chunk header error. */ } Groups can be nested inside each other to represent a hierarchical arrangement of data in the binary stream if required. Table of Contents Creation Given an existing stream containing many chunks, a TOC may be created using RtTOCCreate() that parses this stream constructing an entry per chunk. This TOC may then be prefixed to the original stream using RtTOCStreamWrite(). The entries in the TOC contain the ID of the chunk and a byte offset from the beginning of the stream to the entry's chunk header. This convention is used so that if a TOC entry's offset is used to skip through a stream, the usual RenderWare Graphics stream reading conventions can then be used to read the required chunk, as if the stream had been read sequentially. I-184 11 February 2004 RenderWare Binary Streams ✎ The TOC entries also contain a GUID that uniquely identifies the chunk. A GUID is automatically created by the RenderWare Graphics exporters for each new asset created in a supported modeling package. One such use of the GUID is to identify a unique chunk in an RWS file that contains many chunks of the same ID. Using a Table of Contents There are several uses and usage approaches for the TOC in an .rws file. The first is to quickly scan what an .rws file contains. 1. Open the .rws file for reading using RwStreamOpen() and the rwSTREAMREAD flag. 2. Find the TOC using RwStreamFindChunk() with the rwID_TOC ID. 3. Read the RtTOC using RtTOCStreamRead(). 4. Close the stream using RwStreamClose(). RtTOCGetNumEntries() can be used to query how many entries there are in the TOC. RtTOCGetEntry() can be used to obtain an entry in the TOC, identified by its zero-based index. The use of this entry is then application specific. For example, an ordered list of the chunk types can be obtained by simply looping through all TOC entries enumerating their ID. The second use for a TOC is to read entries from the stream. The application should be aware of whether the entries are to be read sequentially or non-sequentially. For a sequential read, the TOC need only be used to predetermine the chunk ID of the next entry. A single RWS load function would only be needed to cater for all chunk types, rather than individual load functions per chunk type. For a non-sequential read, the TOC can be used to skip regions of the stream to gain access to a specific chunk without having to perform a search using RwStreamFindChunk(). The usefulness of this becomes apparent when an .rws file contains multiple instances of the same chunk ID, e.g. two (rwID_WORLD) worlds, as you can preprocess the TOC entry without having to perform expensive stream operations. The byte offset of the TOC entry's chunk header is relative to the beginning of the stream. Hence, before that offset can be used in RwStreamSkip(), the stream position must be reset to the beginning. To do this, the stream must be closed and then re-opened. After a skip has been performed, the chunk should be read in the same manner as if it had been read sequentially from the stream. This is because the offset is to the chunk's header, as mentioned earlier. Whatever the TOC may be used for, it should be destroyed with RtTOCDestroy once finished with. RenderWare Graphics 3.7 I-185 Chapter 8- Serialization 8.3.5 Stream Types RenderWare binary streams are not limited to file-based streams. The RwStreamOpen() function therefore has two flag parameters. The first defines the type of stream to use and the possible flags are listed in the table below: FLAG PURPOSE rwSTREAMFILE The stream is to a disk file that has been set up by the user. The access mode should match that used when the file was opened. The type-specific argument should be set to the file's pointer (usually of type FILE *). rwSTREAMFILENAME The stream is to a disk file that has not been set up by the user. The type-specific argument should be set to the desired filename. The stream is to a chunk of memory. If access type is rwSTREAMAPPEND then the chunk of memory must have been created using RwMalloc as RenderWare may subsequently try to use RwRealloc to gain more memory. The type specific argument should be a pointer to the memory chunk (RwMemory *) giving the position and size of the chunk to use. rwSTREAMMEMORY The second flag parameter determines how the stream is opened: FLAG PURPOSE rwSTREAMREAD rwSTREAMWRITE Opens a stream for reading only. Opens a stream for writing only. If the stream is of type rwSTREAMFILE or rwSTREAMFILENAME the file size will be reduced to zero when the stream is opened. Opens a stream to which data will be appended. rwSTREAMAPPEND I-186 11 February 2004 Summary 8.4 Summary RenderWare Graphics supports both a low-level file I/O API and a highlevel streaming API. 8.4.1 File I/O API Low-level access to files on disk is accessed through the RwFileFunctions structure. This structure, which can be overwritten with custom functions, exposes an ANSI-compliant set of file I/O functions: 8.4.2 RenderWare Binary Streams Binary streams can contain simple objects, or complex ones. Complex objects can contain other objects—including other complex objects—so a stream's structure can be viewed as a tree. The Stream Viewer application, strview.exe, can be used to examine binary streams. It can be found in the [SDK-ROOT]/tool/strview/ folder. Stream Types RenderWare binary streams are usually file-based, but memory-based streams are also supported. Chunk IDs All objects are stored in chunks, which are the building-blocks of RenderWare binary stream. A chunk for a particular object is identified by its chunk ID. Chunk IDs are generated using the MAKECHUNKID() macro, which takes your vendor ID (used to log-in to the developer support website) and an object ID—between 0 and 255—which identifies the object itself. This is the same mechanism used for plugin IDs, so care should be taken not to confuse the two. Serializing Objects Object serialization is the responsibility of the plugin within which the object resides. Serializable objects must implement the three callback functions necessary for RwRegisterPluginStream(). These functions are: • a chunk read function; • a chunk write function; RenderWare Graphics 3.7 I-187 Chapter 8- Serialization • a function that returns the size of the chunk. The developer can choose to implement an object as either: • a container object, (e.g. RpClump and RpWorld) • an extension to another object, (e.g. RpMatFX) • a stand-alone object (e.g. RpLight). Container objects should expose a high-level serialization API, as should stand-alone objects. Objects that extend an existing object rarely need to expose a high-level serialization API, unless the object can also be used as a stand-alone object. In all cases, callback functions for serialization are necessary if the object is to support serialization at all. Registering the Stream Functions Plugin objects that support both the RenderWare Graphics binary stream API and extension via the plugin mechanism must call two plugin registration functions. The first function will be either one of two choices: • RwRegisterPlugin(), which registers the plugin with the core directly and is used only if the plugin does not extend other objects itself, or • ...RegisterPlugin(), which belongs to the API of the object which the plugin is to extend. The second function, ...RegisterPluginStream(), belongs to the API of the plugin that contains the object to be extended. It registers the serialization callback functions with that base object, so that it knows how to load the extended data. Endian-ness Data in a stream uses a little-endian storage format, so conversion functions—supplied by the RwMem API—must be used to ensure all the streamed data is in the right format. RWS files The concept of the RenderWare Graphics binary stream can be extended to RWS files that may contain all art assets packaged together. Assets saved out from the exporters into .rws files are bracketed within ‘start’ and ‘end’ marker blocks which may be accessed via the RwChunkGroup functions. I-188 11 February 2004 Summary To keep track of the contents of an RWS file, a Table of Contents is attached to the beginning of the file. RenderWare Graphics 3.7 I-189 Chapter 9 File Systems Chapter 9- File Systems 9.1 Introduction The RenderWare file system toolkit is composed of a file system manager, and a set of custom file systems for specific platforms. The file system manager is a high level interface, responsible for managing all file operations on a given platform. Each custom file system has a unique userdefined name from which it can be accessed via the file system manager. The file system manager handles file system registration, and provides a generic approach to all file operations. For example, it is the responsibility of the manager to find an appropriate file system on which to open a specific file, amongst the list of registered file systems. As opposed to any previous implementation, this toolkit enables asynchronous access to a file. The toolkit deals with all file-level access to storage devices. Other RenderWare modules, such as Streaming (used for the serialization of objects), are naturally affected by this new toolkit. Note that, when the file system manager is initialized it installs a generic interface to the standard RenderWare interface. All streaming functions remain unchanged as they simply rely on this standard file interface. This document details the components of the RenderWare file system toolkit, and shows you how custom file systems are used. I-192 11 February 2004 File System Management 9.2 File System Management The RenderWare file system manager provides a generic interface through which all RenderWare I/O operations are processed. This constitutes the first layer of the file system API. It supports multiple file systems, each representing a particular device type available on a specific platform, e.g. Playstation 2 host. In other words, the toolkit is designed to provide a common file transfer interface for all hardware devices. The second layer consists of custom file systems, which need to be registered (see figure below) with the file system manager. This step is necessary as file operations, e.g. file open, will automatically attempt to find an appropriate file system in the file system manager list of registered file systems. This step is performed by looking for the device name (see Changing the File System Device Name) attached to the front of the file name or by getting the default file system, should one be specified. Custom File System 2 Registers with RenderWare File System Manager Custom File System 1 File System Registration RenderWare Graphics 3.7 I-193 Chapter 9- File Systems 9.3 The File Systems The RenderWare file system toolkit provides a common interface to all OS specific file systems. It allows the definition of custom device names, thereby providing a powerful way to switch between different registered file systems. 9.3.1 The Generic File System The figure below illustrates the process that takes place during a file open operation. It shows that, from a user’s point of view, opening a file consists of getting the standard RenderWare file interface, and calling the rwfopen function. The whole opening process is undertaken via the file system manager. When the file system manager is initialized, it installs a set of generic functions that are used by all RenderWare file calls. Depending on the device name passed during the file system initialization, the appropriate file system is retrieved and the file open operation attempted. Custom File System (FS) Get RW File Interface by calling On Initialise Open a file by calling If generic FS not installed, install it with RwOSGetFileInterface Returns pointer to Implement Functionality ... Register FS with Open Read Write rwfopen RwFSInstallToRW File System Manager Points to RW Generic FS rwfsFOpen Registered once by calling calls Generic FS RwFSManagerFOpen Get FS from filename from Returns registered custom FS If slot available in FS call Use Case Diagram - File Open I-194 11 February 2004 The File Systems 9.3.2 OS-Specific File Systems File System Naming Once registered, each file system can be accessed by name using the file system manager function, RtFSManagerGetFileSystemFromName. You must specify the file system name on initialization. This provides an easy way to access any registered file systems in a user-defined way. This allows quick access to any registered file system, and provides the ability to manipulate the file system itself, although you do so at your own risk. Naming File System Devices A useful aspect of this file system is the ability to specify user-defined device names. This constitutes an easy way to switch between file systems. Registering a file system with a custom device name provides the ability to have files with path names that guarantee a specific file will be opened in a certain way. Consider the case where a file system is registered with the tdn: device name. Any files with a file name using this device name, e.g. tdn:./model/world.dff will automatically be opened on this file system. Note that file system device names are case sensitive. RenderWare Graphics 3.7 I-195 Chapter 9- File Systems 9.4 Using the RenderWare File System 9.4.1 Basic Usage Initializing and Registering File Systems The sample code below illustrates the different steps needed to initialize and register a file system. Before any custom file system can be registered, the file system manager needs to be initialized using RtFSManagerOpen. Following this call, the appropriate file system initialization function needs to be called. All custom file system initialization functions return a pointer to the file system itself or NULL if the initialization failed. Once the initialization has succeeded, the file system needs to be registered by calling RtFSManagerRegister, and passing the pointer returned by RtFSManagerInit. RtFileSystem *hfs; RwChar hBuffer[MAX_NB_FILES_PER_FS * READ_BUFFER_SIZE]; RwChar fsName[RTFS_MAX_NAME_LENGTH]; RwChar *hstDeviceName = "hst:"; /* Setup the file system manager */ RtFSManagerOpen(RWFSMAN_UNLIMITED_NUM_FS); rwstrcpy(fsName, "hst"); /* Init and register the host file system */ if ((hfs = RtSkyHSTFSystemInit(MAX_NB_FILES_PER_FS, hBuffer, READ_BUFFER_SIZE, hstDeviceName, fsName)) != NULL) { /* Now actually register the file system */ if (RtFSManagerRegister(hfs) == FALSE) { /* Registration Failed */ } else { /* Registration Succeeded: maybe set this file * system as the default one */ } } else { /* Initialization Failed */ return; } I-196 11 February 2004 Using the RenderWare File System Note that hBuffer is simply a memory block that will be used as a buffer by the file system. The size of this buffer must be equal to the maximum number of concurrently opened files, multiplied by the maximum read-size specified. This buffer will be internally segmented, and each part assigned to a per-file file buffer. Please refer to the API reference for the particular calls in the file system initialization function. ✎ Note that the file system name size must not exceed RTFS_MAX_NAME_LENGTH. Opening a File You can open a file directly via the standard RenderWare file interface. The file system manager initialization process installs a generic file system to the existing RenderWare file interface. As a result, a file can be opened as follows: RtFile *file; RwFileFunctions *fileFunctions = RwOsGetFileInterface(); file = fileFunctions->rwfopen(fileName, "r"); Reading from a file As for opening files, reading and writing can be done directly from the RenderWare file interface as follows: fileFunctions->rwfread(readb, READ_CHUNK_SIZE, 1, file); This way, none of your current synchronous RenderWare I/O calls need to be changed. The file system sits below the streaming interface and, as a result, RenderWare streams are read as they always have been, i.e. using the RwStream functions. Registering a Default File System The current API allows you to set a default file system amongst the set of file systems registered. The default file system is the one that will be used as a last resort when trying to open a file. This means that, if no file system is found that matches the device-name when opening a file, i.e. your path may be relative, the file system manager will automatically attempt to open the specified file on the default file system. Setting the default file system can be done by calling the RtFSManagerSetDefaultFileSystem function, and passing the appropriate file system pointer to it: RtFSManagerSetDefaultFileSystem (myFileSystemPtr); In the case where the default file system is not set, and no appropriate file system is found during a file open, the file open operation will fail at the file system manager level. This will cause the rwfopen call to return NULL, and set the file system manager error to RTFSM_ERROR_NOFS. RenderWare Graphics 3.7 I-197 Chapter 9- File Systems ✎ If your file path name does not include the device name, you will need to set a default file system in order to avoid any failure at the file system manager level. This is because the process of opening a file consists of looking for whether the file system’s device name matches the path name’s device name. If your file name does not include this device name, the default file system will automatically be used. Changing the File System Device Name The file system API allows you to change the device name used at any time. Remember that the initial device name is set during the file system initialization. Changing the file system name can be done in the following way: /* Get a registered file system */ RtFileSystem *fs = RtFSManagerGetFileSystemFromName("myfs") if (fs != NULL) { /* Set the new device name */ RtFileSystemSetDeviceName(fs, "test:"); } This example will set a new device name for a custom file system with the name “myfs”. This is particularly useful for Windows based file systems as it allows you to specify the drive on which to read from or write to. ✎ Note that the actual device name size can be of any size. Registering Multiple File Systems The file system toolkit allows you to register several file systems of the same type. For example, the toolkit allows you to initialize, and register, several Windows file systems. The usefulness of this functionality is particularly evident on Windows based file systems. For example, it provides you with the ability to have a file system per valid partition or device. This prevents you from potentially having to constantly change the device name in your code. Naturally, initializing and registering several file systems of the same type will require more memory, and may not constitute the optimal solution. 9.4.2 Synchronous vs. Asynchronous Access As opposed to synchronous file access, where a specific file operation being executed must complete before the function call returns, in asynchronous mode the operation returns immediately. An application can check whether an asynchronous operation is in progress by querying the RtFileSystemFileFunctionTable sync method provided. I-198 11 February 2004 Using the RenderWare File System Opening a File in Asynchronous Mode To access a particular file in asynchronous mode, set your access flags accordingly, and open the file via the file system manager. This can be done as follows: flags |= RWFILE_ACCESS_OPEN_ASYNC; file = RtFSManagerFOpen(fileName, flags); Note that it is usually common practice to use the file system in synchronous mode, and manage asynchronous operations in a separate thread. This guarantees an optimal control on the asynchronous operations you wish to perform. As a result, the RtFSManagerFOpen function should only be used when you want to directly open a file asynchronously, and use the internal asynchronous functionality. Defaulting a File System to Synchronous/Asynchronous On initialization file systems default to synchronous access mode. However, this default may be changed to a specific access mode. This can be done via the file system RtFileSystemDefaultToAsync function. A call to this function will automatically default all future operations to the specific mode chosen. For example, if TRUE is passed to this function all file operations following the next open will be done asynchronously. On the other hand, if FALSE is specified, these operations will be done synchronously. This function cannot be used for individual files; it is a per file system setting. The following code will default myFileSystemPtr to asynchronous: RtFileSystemDefaultToAsync(myFileSystemPtr, TRUE); 9.4.3 File System Specific Remarks Windows File System For the windows file system, the device name specified during initialization must be a valid device name, i.e. an existing drive or partition. This is to enable access to any valid drive on your hard disk(s). Playstation2 DVD File System This file system requires the loading of the rtfsiop irx module. This must be done before the file system initialization. Playstation 2 ATMon File System This file system requires a valid ATMon IP address to be passed during initialization. RenderWare Graphics 3.7 I-199 Chapter 9- File Systems GCN USB File System This file system uses an external tool called viewer_server (normally found in “your_dolphin_sdk”\X86\hiodemo). This tool needs to be started and properly configured, i.e. its FIO path needs to be set to your project directory in order for the file system to find a channel with a USB adapter. Note that this tool needs to be opened before your own application, and the server must be started once your application is running. 9.4.4 Creating your Own File System To create your own custom file system, you must implement a set of file system methods. Below are the required file system methods: File system methods to implement RtFileSystemGetFileFunc fsGetObject; RtFileSystemCloseFunc fsClose; RtFileSystemGetDeviceNameFunc fsGetDeviceName; Each file system contains a file function table. This structure, called RtFileSystemFileFunctionTable, contains all the file system specific file functions. So, a complete file function table must be implemented by any custom file system. The methods to implement are described below: File methods to implement I-200 RtFileOpenFunc open; RtFileCloseFunc close; RtFileReadFunc read; RtFileWriteFunc write; RtFileSetPositionFunc setPosition; RtFileSyncFunc sync; RtFileAbortFunc abort; RtFileEofFunc isEOF; RtFileGetStatusFunc getStatus; RtFileExistsFunc fExists; 11 February 2004 Using the RenderWare File System Additionally, every custom file system initialization function must call the _rtFSInit file system function. This function will actually perform some necessary internal initialization steps such as checking whether the file system can be initialized and setting the device name. It must be called in the following manner, after having allocated memory for the actual file system (here myfs): if (_rtFSInit((RtFileSystem *)myfs, maxNbOpenFiles, (RwChar *)fileSystemName, deviceName)) != RTFS_ERROR_NOERROR) { /* Internal Initialization Failed */ /* Free all Memory Allocated */ } Also note that all custom file system initialization functions must return a pointer to the newly created file system when initialization succeeds. If initialization fails, the function must return NULL. For more details, please refer to any of the custom OS-specific file systems, as well as the API reference. RenderWare Graphics 3.7 I-201 Chapter 10 The Dictionary Toolkit Chapter 10- The Dictionary Toolkit 10.1 Introduction The dictionary toolkit, RtDict, provides support for generic containers of objects that may be identified by name. RtDict works off two main objects: RtDictSchema and RtDict. The schema holds the layout of a dictionary of a user-specified object. It contains callbacks that are used to manage entries with dictionaries for that object type. In general, a schema is needed for dictionaries of each different object type. The schema can be used to create, or stream in, dictionaries of that schema type. It also maintains a ‘current’ dictionary for the contained object type. Each individual dictionary is managed within an RtDict structure. RtDict is used internally by RenderWare in systems such as the UV animation plugin, RpUVAnim, but is also available for your own usage. RtDictSchema schema1 RtDict of TypeA TypeA entry1 TypeA entry2 RtDict of TypeA TypeA entry1 RtDictSchema schema2 RtDict of TypeB RtDict of TypeA TypeA entry2 TypeA entry1 TypeB entry1 RtDict of TypeB TypeB entry2 TypeB entry2 10.1.1 This Document This document describes the usage of the generic dictionary toolkit, RtDict. For general operation of this toolkit in conjunction with other RenderWare modules that use it, read sections 10.2, 10.4 and 10.4. Section 10.5 describes how to set up schemas for your own custom dictionaries. II-204 11 February 2004 Introduction 10.1.2 Other Resources The API Reference: • RtDict toolkit • RpUVAnim plugin uses RtDict The uvanim example also uses dictionaries. RenderWare Graphics 3.7 II-205 Chapter 10- The Dictionary Toolkit 10.2 Basic Dictionary Schema Usage Before operations can be performed with a dictionary, an appropriate schema for that kind of dictionary must be obtained. RenderWare toolkits and plugins that use dictionaries provide functions that return schemas for those dictionaries. For example, the UV animation plugin, rpuvanim, has the function RpUVAnimGetDictSchema. As well as dictionary creation and stream reading (see section 10.3), a schema maintains a ‘current’ dictionary and a list of all dictionaries of that type. ✎ By default, the current dictionary for a schema is NULL. It is completely up to the creator of the schema to provide a current dictionary, and by no means necessary. 10.2.1 Getting the Current Dictionary for a Schema The current dictionary for a given schema may be obtained with RtDictSchemaGetCurrentDict: RtDict *dict = RtDictSchemaGetCurrentDict(&mySchema); if (!dict) { /*There is no current dictionary */ } 10.2.2 Setting the Current Dictionary for a Schema The current dictionary for a given schema may be set with RtDictSchemaSetCurrentDict: RtDictSchemaSetCurrentDict(&mySchema, dict); It’s okay to set NULL as the current dictionary. This indicates that there is no current dictionary for the schema. II-206 11 February 2004 Creating and Streaming Dictionaries 10.3 Creating and Streaming Dictionaries Any dictionary creation or reading from streams must be done via an appropriate RtDictSchema (see section 10.5). Dictionaries may be streamed out or destroyed directly. ✎ ✎ This convention, of creating or reading dictionaries based on a schema, means that the Dictionary streaming API differs from other RenderWare object streaming functions. The creation and streaming functions are RtDictSchemaCreateDict, RtDictSchemaStreamReadDict rather than RtDictCreate and RtDictStreamRead. Once created, the dictionary knows what its schema is. The dictionary destruction and stream-writing functions, RtDictDestroy and RtDictStreamWrite, don’t need to be told which schema to use. Dictionary schemas cannot be streamed. 10.3.1 Dictionary Creation Create a dictionary via an appropriate schema with the RtDictSchemaCreateDict function: RtDict *myDict = RtDictSchemaCreateDict(&mySchema); Multiple dictionaries may be created from the same schema: RtDict *myDict2 = RtDictSchemaCreateDict(&mySchema); When you have finished with the dictionary, for example on program shutdown, you must destroy it with the RtDictDestroy function: RtDictDestroy(myDict); 10.3.2 Reading a Dictionary from a Stream Dictionaries may be read from streams with the RtDictSchemaStreamReadDict function: RtDict *myDict = RtDictSchemaStreamReadDict(&mySchema, stream); The caller is responsible for the newly read dictionary, and must destroy it with RtDictDestroy when the dictionary is no longer needed. 10.3.3 Writing a Dictionary to a Stream Dictionaries may be written to streams with the RtDictStreamWrite function: if (!RtDictStreamWrite(dict, stream)) { return NULL; /* failure */ } RenderWare Graphics 3.7 II-207 Chapter 10- The Dictionary Toolkit A function is also provided to determine how many bytes will be written to the stream: RwUInt32 size = RtDictStreamGetSize(dict); II-208 11 February 2004 Dictionary Entries 10.4 Dictionary Entries Dictionaries store pointers to the objects they contain. These objects are referred to as ‘entries’. Entries may be added to or removed from the dictionary. The dictionary manages the lifetime and ownership of entries via AddRef and Destroy callbacks in the dictionary’s schema. The dictionary can also be used to look up entries based on their name. The dictionary uses a GetName callback to obtain each entry’s name. It is assumed that an entry’s name does not change while it is in a dictionary. 10.4.1 Adding Entries to a Dictionary To add an entry to a dictionary, use the RtDictAddEntry function: if (!RtDictAddEntry(dict, myEntry)) { return NULL; /* failure */ } Since the dictionary assumes ownership of the entry and increments the entry’s internal reference count with the dictionary schema’s AddRef callback, the entry can usually be destroyed at this point: EntryDestroy(myEntry); /* entry destruction function */ EntryDestroy is the entry-type-specific destruction function. ✎ In this case, it’s assumed that myEntry is a reference-counted entry. The dictionary has registered that it has a reference to the entry, and the caller of RtDictAddEntry already has a reference. If the caller is finished with the entry they can relinquish control with their EntryDestroy function. This won’t actually destroy the entry, because the dictionary still has a reference. 10.4.2 Removing an Entry from a Dictionary To remove an entry from a dictionary, use RtDictRemoveEntry: if (!RtDictRemoveEntry(dict, entry)) { /* entry was not found in dictionary */ } This also registers the fact that the dictionary no longer has a reference to the entry by calling the entry’s Destroy function. If you need to remove the entry from the dictionary, but retain ownership, you will need to AddRef the entry prior to calling RtDictRemoveEntry. RenderWare Graphics 3.7 II-209 Chapter 10- The Dictionary Toolkit ✎ A direct pointer comparison is used to identify the entry in the dictionary. 10.4.3 Locating an Entry by Name To find an entry by name, call RtDictFindNamedEntry: DictEntryType *entry = (DictEntryType *) RtDictFindNamedEntry(dict, “MyEntry”); if (!entry) { /* entry was not found */ } ✎ II-210 DictEntryType is your user-defined dictionary entry type 11 February 2004 Advanced Dictionary Schema Usage 10.5 Advanced Dictionary Schema Usage If you wish to create dictionaries of your own objects, you must initialize a schema that will describe and manage those dictionaries. In particular, you must setup the callbacks that are used to manage and stream the dictionary entries. 10.5.1 Schema Structure The schema structure is as follows: struct RtDictSchema { const RwChar *name; RwUInt32 dictChunkType; RwUInt32 entryChunkType; RwUInt32 compatibilityVersion; RwSList *dictionaries; RtDict *current; RtDictEntryAddRefCallBack *addRefCB; RtDictEntryDestroyCallBack *destroyCB; RtDictEntryGetNameCallBack *getNameCB; RtDictEntryStreamGetSizeCallBack *streamGetSizeCB; RtDictEntryStreamReadCallBack *streamReadCB; RtDictStreamReadCompatibilityCallBack *streamReadCompatibilityCB; RtDictEntryStreamWriteCallBack *streamWriteCB; }; The data members are described below. const RwChar *name Name of the schema. Handy for debugging. RwUInt32 dictChunkType; Chunk type of the dictionary in a stream; used for the initial chunk header by RtDictStreamWrite. RwUInt32 entryChunkType; Chunk type of the dictionary entries in a stream. Used for streaming the dictionary in. RwUInt32 compatibilityVersion; Used for inner version check when streaming in dictionaries. If the dictionary's version is less than this, the streamReadCompatibilityCB will be used for reading in the contents. RwSList *dictionaries; List of dictionaries that have been created using this schema. RtDict *current; RenderWare Graphics 3.7 II-211 Chapter 10- The Dictionary Toolkit Current dictionary of this schema type. RtDictEntryAddRefCallBack *addRefCB; Callback used to register that the dictionary has a reference to an entry. RtDictEntryDestroyCallBack *destroyCB; Callback used to register that the dictionary no longer has a reference to an entry RtDictEntryGetNameCallBack *getNameCB; Callback used to obtain the name of an entry RtDictEntryStreamGetSizeCallBack *streamGetSizeCB; Callback used to obtain the size of an entry RtDictEntryStreamReadCallBack *streamReadCB; Callback used to stream in an entry RtDictStreamReadCompatibilityCallBack *streamReadCompatibilityCB; Callback used to stream in an old version of the dictionary. This is mainly for RenderWare’s internal use; it may be set to NULL RtDictEntryStreamWriteCallBack *streamWriteCB; Callback used to stream out an entry 10.5.2 Initializing a Schema Define a schema structure by direct initialization: RtDictSchema mySchema = { = { "MyDictionarySchema", ID_MYDICTCHUNKID, ID_MYDICTENTRYCHUNKID, rwLIBRARYBASEVERSION, /* you could safely use 0 */ NULL, /* dictionaries */ NULL, /* current dictionary */ (RtDictEntryAddRefCallBack *)&MyEntryAddRef, (RtDictEntryDestroyCallBack *)&MyEntryDestroy, (RtDictEntryGetNameCallBack *)&MyEntryGetName, (RtDictEntryStreamGetSizeCallBack *)&MyEntryStreamGetSize, (RtDictEntryStreamReadCallBack *)&MyEntryStreamRead, NULL, /* streamReadCompatibilityCB */ (RtDictEntryStreamWriteCallBack *)MyEntryStreamWrite }; }; You must call RtDictSchemaInit before using the schema to create dictionaries. Among other things, this initializes the master list of dictionaries of this schema type: RtDictSchemaInit(&mySchema); II-212 11 February 2004 Advanced Dictionary Schema Usage On program shutdown, all schemas that you initialized must be destructed. RtDictSchemaDestruct(&mySchema); RenderWare Graphics 3.7 II-213 Chapter 10- The Dictionary Toolkit 10.6 Summary This chapter has dealt with running the RtDict generic dictionary system, including: II-214 • Basic usage of the RtDictSchema objects that manage RtDict dictionary objects. • Creation and streaming of RtDict objects. • Access of entries within dictionaries. • Finally, creation of custom RtDictSchema objects. 11 February 2004 Chapter 11 Debugging and Error Handling Chapter 11- Debugging and Error Handling 11.1 RenderWare Graphics Errors RenderWare Graphics functions return error codes using the RwError API. This is a simple, minimal impact, general-purpose error reporting mechanism that has minimal impact on application performance even if heavily used. The API has two functions, RwErrorSet() and RwErrorGet(), which are used to set or retrieve error codes respectively. By convention, most RenderWare Graphics functions will return: • a pointer to an object if successful; • NULL to represent failure. Should an API function fail, developers can check what the error code of the last function was using RwErrorGet(). Error codes take the form of an integer matching an enumerated value, such as E_RW_INVRASTERSIZE, ("Invalid Raster Size"). Error code enumerations can be found in the appropriate [SDKROOT]/rwsdk/include/ folder corresponding to the build target. The files have one of two extensions: • .def – for common error codes and those used by the core library; • .rpe – for error codes used by specific plugins and toolkits. I-216 11 February 2004 RenderWare Graphics Builds 11.2 RenderWare Graphics Builds RenderWare Graphics libraries are supplied in three different builds: Release, Metrics and Debug. Release Build, as its name implies, is for release builds of your applications. It has no debugging information or unnecessary hooks; it's a lean, mean rendering machine. Metrics Build is a modified version of the Release Build, exposing hooks in the rendering engine that can be queried with RwEngineGetMetrics(). The metrics structure accumulates values since the last call to either RwCameraShowRaster() or RwRasterShowRaster(), and is most useful when examined immediately before calls to these functions. The format of the data structure returned by this function will vary by platform – on Sony's PlayStation 2, for instance, it will cover aspects such as DMA and Vector Unit utilization. Finally, we come to the Debug Build. This set of libraries has been built with debug message logging enabled, so that a log file (with a file extension of .log) is created while running. This log file lists assert messages, errors, bad arguments and similar reports generated by the RenderWare Graphics API. The log file is generated through the RwDebug object, which we'll look at shortly. RenderWare Graphics 3.7 I-217 Chapter 11- Debugging and Error Handling 11.3 The Debug Object When using a Debug Build of RenderWare Graphics, the RwDebug object becomes active. In the other library builds, the object does nothing. This object maintains a simple debugging information reporting system, with output being handled by a Debug Stream Handler function. The default function simply diverts the messages to a file called "rwdebug.log", or, in the case of some console platforms, it sends the data across a network or other target/host link. This handler can be replaced by your own function with the RwDebugSetHandler() function. This function controls output for all RenderWare Graphics messages, including those emitted by assert and trace (covered in 11.4) messages. These messages are all disabled in release and metrics builds. An important, but often missed, point to understand is that a Debug Build of RenderWare Graphics is designed to behave exactly as if it were a Release Build. The only difference is the activation of the RwDebug API and the logging of any asserts and errors raised while running. This is an intentional design feature. Our view is that if an application is going to crash in Release Build, it should also crash in Debug Build. This may sound extreme, but it has the advantage of dramatically reducing unpleasant surprises when you're ready to build a release. In particular, it avoids the problem of bugs that cannot be repeated in a debug build. It is also important to note that overuse of the RwDebug functionality is very likely to affect performance, particularly if the output is being streamed to a file. For example, we do not advise placing long, descriptive messages in the stream for functions likely to be frequently called within the inner loop of a rendering cycle. 11.3.1 The Default Debug Stream Handler As we saw earlier, the default Debug Stream Handler outputs to a log file named "rwdebug.log". This file is either stored in the current working directory, or, on platforms where this isn't possible, is transmitted to the host (development) computer. If you have replaced the default debug stream handler with your own functionality, then passing NULL to RwDebugSetHandler() will re-instate it. I-218 11 February 2004 The Debug Object 11.3.2 Sending a Message to the Debug Stream The Debug Stream is not limited to RenderWare Graphics' own functions: you can send your own messages to the stream using RwDebugSendMessage(). These messages will be chronologically ordered with any other messages, including those resulting from asserts and the trace message mechanism. The function takes the following parameters: Type – Signifies whether this message is an Assert, an Error message, an informational Message, or a simple Trace ("where am I?") message. These are defined as rwDEBUGASSERT, rwDEBUGERROR, rwDEBUGMESSAGE and rwDEBUGTRACE respectively. Filename – The filename from where the message was sent. Usually, this is the source file containing the function sending the message and can be obtained using the ANSI C compiler directive __FILE__. Line – The line number where this particular call to RwDebugSendMessage() is taking place. Again, this is usually obtained using the ANSI C compiler directive __LINE__. Function Name – The name of the function from whence the message was sent. Message – The message itself. These are the arguments passed to RwDebugSendMessage(). Most of this information is combined before passing to the Debug Stream Handler itself. The stream handler only receives two parameters: the Type and a Message. The Message is a single string, usually containing the information outlined above. RenderWare Graphics 3.7 I-219 Chapter 11- Debugging and Error Handling 11.4 Tracing RenderWare Graphics Activity RenderWare Graphics' functions can be made to output simple Trace messages using the RwDebugSendMessage() mechanism. Trace messages are simple, informational "I Am Here" messages which can be used during debugging to track the flow of execution of your application. They are specified by passing rwDEBUGTRACE as the Type parameter to RwDebugSendMessage(). To enable these Trace messages, use: RwDebugSetTraceState(TRUE); Passing FALSE will disable them. All of RenderWare Graphics public API will output Trace messages when the Trace State is TRUE. (This can impact performance, so the default Trace State is FALSE.) Messages are output both on entry to and on exit from each function. The text below is an extract from an example Debug log with Trace enabled: ... D:/rel/rwsdk/world/baclump.c(1740): TRACE: RpClumpForAllAtomics: Enter d:/rel/rwsdk/plugin/morph/rpmorph.c(1151): TRACE: RpMorphAtomicAddTime: Enter d:/rel/rwsdk/plugin/morph/rpmorph.c(1203): TRACE: RpMorphAtomicAddTime: Exit D:/rel/rwsdk/world/baclump.c(1763): TRACE: RpClumpForAllAtomics: Exit D:/rel/rwsdk/src/bacamera.c(1580): TRACE: RwCameraClear: Enter D:/rel/rwsdk/src/bacamera.c(1592): TRACE: RwCameraClear: Exit D:/rel/rwsdk/src/bacamera.c(957): TRACE: RwCameraBeginUpdate: Enter D:/rel/rwsdk/src/bacamera.c(961): TRACE: RwCameraBeginUpdate: Exit D:/rel/rwsdk/world/baworobj.c(331): TRACE: WorldCameraBeginUpdate: Enter D:/rel/rwsdk/world/baworobj.c(342): TRACE: WorldCameraBeginUpdate: Exit D:/rel/rwsdk/src/bacamera.c(776): TRACE: CameraBeginUpdate: Enter D:/rel/rwsdk/src/bacamera.c(810): TRACE: CameraBeginUpdate: Exit D:/rel/rwsdk/world/baworld.c(1874): TRACE: RpWorldRender: Enter D:/rel/rwsdk/world/baworld.c(1885): TRACE: RpWorldRender: Exit D:/rel/rwsdk/src/bacamera.c(1118): TRACE: RwCameraGetRaster: Enter D:/rel/rwsdk/src/bacamera.c(1123): TRACE: RwCameraGetRaster: Exit D:/rel/rwsdk/src/baraster.c(347): TRACE: RwRasterGetWidth: Enter D:/rel/rwsdk/src/baraster.c(351): TRACE: RwRasterGetWidth: Exit D:/rel/rwsdk/src/bacamera.c(1118): TRACE: RwCameraGetRaster: Enter D:/rel/rwsdk/src/bacamera.c(1123): TRACE: RwCameraGetRaster: Exit D:/rel/rwsdk/src/baraster.c(371): TRACE: RwRasterGetHeight: Enter I-220 11 February 2004 Tracing RenderWare Graphics Activity D:/rel/rwsdk/src/baraster.c(375): TRACE: RwRasterGetHeight: Exit d:/rel/rwsdk/tool/charse/rtcharse.c(943): TRACE: RtCharsetGetDesc: Enter d:/rel/rwsdk/tool/charse/rtcharse.c(953): TRACE: RtCharsetGetDesc: Exit ... RenderWare Graphics 3.7 I-221 Chapter 11- Debugging and Error Handling 11.5 Replacing The Stream Handler We saw earlier that the Debug Stream Handler can be replaced by your own code. This is achieved through a standard callback mechanism. The callback function prototype is defined by a typedef named RwDebugHandler. Your callback function's prototype must match this. Secondly, either your main program or your handler will need to open or create any files it intends to use. Disabling the default handler will close the "rwdebug.log" file it uses automatically, so your new handler cannot make the assumption that it is still open for writing. To replace the default RenderWare Graphics handler with your own, you should call RwDebugSetHandler(), passing a pointer to your replacement callback function as the parameter. 11.5.1 Example The following code replaces the existing handler with a dummy handler that outputs the supplied text only if it is an rwDEBUGTRACE type. (This example assumes your program's global data is stored in a structure called GlobalData and that this structure has an entry named debugFile representing a FILE * type.) static void MyDebugHandler(RwDebugType type, const RwChar * debugText) { /* First check if output file is available... */ if ( !GlobalData.debugFile ) { /* * output file not initialized, better create it... */ GlobalData.debugFile) = RwFopen(RWSTRING("bug_out.txt"), RWSTRING("at")); } /* Output message if it's the right type... */ if ( (GlobalData.debugFile) && (rwDEBUGTRACE == type) ) { RwFwrite(debugText, (rwstrlen(debugText) * sizeof (RwChar)), 1, RWSRCGLOBAL(debugFile)); RwFwrite(cr, (rwstrlen(cr) * sizeof (RwChar)), 1, I-222 11 February 2004 Replacing The Stream Handler RWSRCGLOBAL(debugFile)); RwFflush(RWSRCGLOBAL(debugFile)); } return; } ✎ This example handler is for illustration purposes only and has little error checking of its own. Naturally you will want to remedy this in production code. Setting the above handler in your RenderWare Graphics application would be achieved by adding the following line to your code after the Engine has been initialized: RwDebugSetHandler(MyDebugHandler); We can reset the default debug handler by passing NULL to the above function, therefore there is no need to store the returned function pointer unless you are using multiple handlers. RenderWare Graphics 3.7 I-223 Part B World Library Chapter 12 World and Static Models Chapter 12 - World and Static Models 12.1 Introduction This chapter explains scenes and static models, which are represented by RpWorld and RpWorldSector. These objects are part of the World plugin (RpWorld) which provides RenderWare Graphics' Retained Mode API. This Plugin provides the following objects: RpAtomic; RpClump; RpGeometry; RpInterpolator; RpLight; RpMaterial; RpMorphTarget; RpWorld and RpWorldSector. It also adds some extensions to the Core Library's RwCamera API. These objects can be further extended through the plugin mechanism. I-228 11 February 2004 Scenes & Static Models 12.2 Scenes & Static Models 12.2.1 Scenes A typical scene will consist of: • Static models – the ‘scenery’ • Dynamic models – objects that can be moved or animated • Dynamic lights • Cameras – one or more depending on the number of views required This chapter is primarily concerned with static models. Separate chapters are devoted to dynamic models (Atomics), Lights and Cameras. 12.2.2 RpWorld Object The RpWorld object is a container for scenes. It links the dynamic and static components and provides a cohesive world space in which they can exist. A World is bounded by a single box, which is internally subdivided into static sectors (RpWorldSector objects). Each of these defines a cuboid volume within the scene, and encloses a section of the static scenery. The sectors are created by dividing up the static scenery using a binary space partition (BSP) tree and this sectorization process is usually performed at the exporter stage using the functions supplied by the RtWorldImport Toolkit. This structure is used to speed up the rendering process. Dynamic objects such as Atomics, Lights and Cameras can be added to a World and this allows links to be maintained between the objects and any World Sectors to which they are relevant. When dynamic objects are moved around, the World plugin will decide which World Sector(s) they should be linked to, based on their location. This makes the rendering process more efficient since: • Only World Sectors that are visible from the Camera need be rendered. • Dynamic objects that lie entirely within non-visible sectors can be eliminated. • Only the dynamic lights affecting visible sectors need be considered in lighting calculations. RenderWare Graphics 3.7 I-229 Chapter 12 - World and Static Models 12.2.3 RpWorldSector Object A World Sector is the static counterpart to the Geometry object, which is used for dynamic models. A World Sector performs two tasks: 1. Contains all Vertices, Triangles, Materials and other data that define the scenery within the World Sector's space. 2. Maintains links with Atomics, Cameras and Lights that have been positioned within the World Sector. The data for the static scenery is usually divided up across multiple World Sectors to increase the rendering engine's efficiency. This division is in the form of a binary space partitioning ('BSP') tree. Binary Space Partitioning The World is sectorized by recursively slicing the geometry along axisaligned planes to produce a BSP tree. The resulting box regions are sectors. Geometry cannot always be cleanly divided and sectors often overlap slightly. RenderWare Graphics uses a modified form of BSP, known as a K Dimensional Tree (KD-tree). The difference between the two forms is that KD-trees are always axis-aligned. Normals & Bounding Boxes Normals and bounding boxes are encountered when creating import and conversion tools for World and World Sector objects. • Normals These are required for lighting calculations. During the world creation process, the normals are stored as RwV3d for full floating-point precision, but in the final World Sectors they are compressed to triples of type RwInt8. • Bounding Box World Sectors have bounding boxes (RwBBox). Since models can rarely be cut into neat, straight lines, the bounding boxes of neighboring World Sectors often overlap. I-230 11 February 2004 Iterator Functions 12.3 Iterator Functions A number of simple iterator functions are provided to access the contents of both RpWorld and RpWorldSector objects: 12.3.1 RpWorld Iterators There are four RpWorld iterators: 1. RpWorldForAllClumps() This function takes a callback (type RpClumpCallBack()), which is called for each Clump within the specified RpWorld object. This function will only locate Clumps that have been added to the World using RpWorldAddClump(). 2. RpWorldForAllLights() This function takes a callback (type RpLightCallBack()), which is called for each Light within the specified RpWorld object. This function will only locate Lights that have been added to the World using RpWorldAddLight(). 3. RpWorldForAllMaterials() This function takes a callback (type RpMaterialCallBack()), which is called for each Material object within the specified RpWorld object. This function iterates only through Materials contained within World Sectors. Materials define how a model's surface should be rendered and are covered in more detail in the Dynamic Models chapter. 4. RpWorldForAllWorldSectors() This function takes a callback (type RpWorldSectorCallBack()), which is called for each World Sector within the specified RpWorld object. ☛ This function is one of the most often-used iterators and it is often used together with RpWorldSectorForAllAtomics(). RenderWare Graphics 3.7 I-231 Chapter 12 - World and Static Models 12.3.2 RpWorldSector Iterators There are three RpWorldSector iterators: 1. RpWorldSectorForAllAtomics() This function takes a callback (type RpAtomicCallBack()), which is called for each Atomic within the specified RpWorldSector object. This function will only locate Atomics that have been added to the World either explicitly, using RpWorldAddAtomic(), or implicitly using RpWorldAddClump(). It is often used in conjunction with RpWorldForAllWorldSectors() to access all Atomics with in a World. 2. RpWorldSectorForAllLights() This function takes a callback (type RpLightCallBack()), which is called for each Light within the specified RpWorldSector object. This function will only locate Lights that have been added to the World using RpWorldAddLight(). 3. RpWorldSectorForAllMeshes() This function takes a callback (type RpMeshCallBack()), which is called for each Mesh within the specified RpWorldSector object. This function will only locate Meshes that are part of the static model data. 12.3.3 Collision Detection Originally, the RpWorld API contained some basic collision detection functionality. This has now been moved into a separate RenderWare Graphics Plugin: RpCollision. I-232 11 February 2004 Modeling Tools 12.4 Modeling Tools The RenderWare Graphics modeling package exporters supplied with the SDK can be used to export static models. Artists should read the associated documentation installed with these exporters for details on how they work. Developers are also advised to read these documents, as exporters for particular modelers may not necessarily support all features. Exported files can be read by applications. 12.4.1 Viewers The static models exported by artists can be tested using the RenderWare Visualizer viewer supplied with the RenderWare Graphics SDK. Using the RenderWare Visualizer is covered in the RenderWare Visualizer Viewers document. The screenshot below shows this viewer displaying a static model of a building's interior. This viewer can display most serialized RenderWare Graphics objects including those supported directly by the World Plugin. RenderWare Graphics 3.7 I-233 Chapter 12 - World and Static Models 12.5 Creating Worlds 12.5.1 Creating Worlds from Foreign Data This process is essentially the same as that performed by the RenderWare Graphics modeling package exporters, the main difference is that such modeling packages usually supply their own API to assist in the process. The exporters take the model data, in the format the modeling package exposes it, and converts it into RenderWare Graphics Worlds, Clumps, Atomics, Morph Targets, Skinning data, etc. The source code for these exporters is provided to give some insight into how to write your own converter tools. Creating Worlds The SDK contains the World Import Toolkit (RtWorldImport). This Toolkit provides API functions for creating an RtWorldImport object. A RtWorldImport object is a fully exposed, un-optimized, uncompressed format of a world. It is suitable for easy creation of a new World and its static model data. The model data is exposed in the form of RenderWare Graphics Vertices, Triangles, Materials, Normals etc. The RtWorldImport object can then be converted by the World Import Toolkit into an optimized, compressed RpWorld structure, and written to disk. The toolkit provides controls for how this process is performed. In addition, an optional callback is available to provide progress information as the compression and optimization processing may take some time. This process is illustrated by the world SDK-Example supplied with the SDK. This creates a "buckyball" static model given the raw data and uses the model to create a valid RpWorld object. First, locate the world project files and open the world.c source file in your preferred editor. The first part of the file contains model data, stored in a bunch of ordinary arrays. The first function in the source code is CreateWorldImport(). The steps involved are explained below: 1. Create an RtWorldImport object by calling RtWorldImportCreate(). This is the very first thing the CreateWorldImport() function does. Once it's defined all the variables it needs, we see the following code: worldImport = RtWorldImportCreate(); if( worldImport == NULL ) { return NULL; I-234 11 February 2004 Creating Worlds } 2. Interrogate the modeling tool to find the number of triangles and vertices in the model to be exported then call RtWorldImportAddNumTriangles() and RtWorldImportAddNumVertices() to create memory for your data. The world Example is working with its own arbitrary, hand-typed data rather than from a modeling package's internal data structures, but the procedure remains the same… /* * Allocate the memory to store the world's vertices and triangles... */ RtWorldImportAddNumVertices(worldImport, NOV); RtWorldImportAddNumTriangles(worldImport, NOT); NOV - defines the number of vertices; NOT – defines the number of triangles 3. Call RtWorldImportGetVertices() and RtWorldImportGetTriangles() to obtain pointers to the vertex and triangle arrays. 4. The world example has to first generate some Textures and some Materials to put them in, so the vertices and triangles get added later: vertices = RtWorldImportGetVertices(worldImport); triangles = RtWorldImportGetTriangles(worldImport); These lines appear immediately after the two loops that generate the texture U/V coordinates for each vertex. If you are working with a modeling package's own data, you may be able to take these coordinates straight out of an existing data structure. 5. Iterate over the vertex array, copying the required data from your modeler data into the RtWorldImport object's vertices. In the Example, this copying takes place in the middle of two long for… loops, which also define surface normals. The code looks like this fragment, taken from the first (pentagons) loop: /* * Initialize the vertices with a world-space vertex position, * a normal, texture coordinates and a material... */ vertices->OC = VertexList[PentagonList[i]]; vertices->normal = normal; vertices->texCoords = uvPentagon[0]; vertices->matIndex = pentagonMatIndex; vertices++; …etc. RenderWare Graphics 3.7 I-235 Chapter 12 - World and Static Models 6. Similarly, iterate through the triangles and store these in the triangle array. The same for… loops also have code like this for the triangles: /* * Initialize the triangles with indices into the vertex list * and a material... */ triangles->vertIndex[0] = j; triangles->vertIndex[1] = j + 2; triangles->vertIndex[2] = j + 1; triangles->matIndex = pentagonMatIndex; triangles++; …etc. This is only a small fragment of the triangle copying code; refer to the source code to see the full code. 7. Use the RtWorldImportAddMaterial() and RtWorldImportForAllMaterials() functions to manage adding Materials to the RtWorldImport object. The return value from RtWorldImportAddMaterial() is the Material index. Materials are linked to triangles, so Material indices need to be copied to the appropriate elements in the RtWorldImport triangles array. The world Example actually performs this before the vertex copying steps. The programmer creates a standard RpMaterial object and populates it with the Texture loaded earlier… hexagonMaterial = RpMaterialCreate(); RpMaterialSetTexture(hexagonMaterial, hexagonTexture); Now the Material is added to the World Import data structure… hexagonMatIndex = RtWorldImportAddMaterial(worldImport, hexagonMaterial); And the process is repeated for the pentagons. (Buckyballs are built out of hexagons and pentagons)… pentagonMaterial = RpMaterialCreate(); RpMaterialSetTexture(pentagonMaterial, pentagonTexture); pentagonMatIndex = RtWorldImportAddMaterial(worldImport, pentagonMaterial); The following two steps are optional and the world Example only performs Step 8 as the model takes very little time to convert. 8. You can now optionally establish a callback procedure to handle the messages sent by the converter to advise on progress. To do this, you can use the RtWorldImportSetProgressCallback() function to specify the function that your exporter provides. The API Reference lists the messages that are sent. I-236 11 February 2004 Creating Worlds 9. Modify the parameters used to control the export process, using RtWorldImportParametersInit(). This is done in the CreateWorld() function which is also in the same source file. The relevant code is reproduced below: static RtWorldImportParameters params; RtWorldImportParametersInit(¶ms); params.flags = rpWORLDTEXTURED | rpWORLDNORMALS | rpWORLDLIGHT; params.conditionGeometry = FALSE; params.calcNormals = FALSE; 10. Call RtWorldImportCreateWorld() to perform the conversion of the RtWorldImport object into an optimized, compressed RpWorld object. A single line of code performs this task in the Example: world = RtWorldImportCreateWorld(worldImport, ¶ms); This will build your world with the default scheme, one that tries to balance the world and reduce splits to geometry and materials. The default scheme works by examining a number of candidate partitions for each axis, the default is 20. To change this value, to 50 in the example below, the following code should be called before RtWorldImportCreateWorld(): RwInt32 maxClosestCheck = 50; /* required value */ RtWorldImportSetStandardBuildPartitionSelector( rwBUILDPARTITIONSELECTOR_DEFAULT, (void*)&maxClosestCheck); RtWorldImport provides the mechanisms necessary to create a world that is partitioned in a way that is specific to your own requirements and there are a diverse set of functions that let you partition the world as controllably as you want. Details of these are in the white paper "BSP trees". RenderWare Graphics 3.7 I-237 Chapter 12 - World and Static Models The params structure is defined as follows: PARAMETER PURPOSE WorldSectorMaxSize (RwReal) Defines the maximum size of World Sector. This is generally a trade-off between storage space and speed. Maximum number of polygons in a World Sector. Set to TRUE to check the world for validity during the build process MaxWorldSectorPolygons (RwInt32) TerminatorCheck (RwBool) CalcNormals (RwBool) Set to TRUE to recalculate all normals. MaxOverlapPercent (RwReal) Maximum amount by which World Sectors are allowed to overlap. Set to TRUE to perform welding and other optimizations. (See the geometry conditioning white paper.) Set to TRUE if you want to specify a minimum Bounding Box for the World. Minimum Bounding Box (See above). Set to TRUE to enable fixing of T-junctions created during World generation. Flags to be used for the World. These are: rpWORLDLIGHT rpWORLDNORMALS rpWORLDTRISTRIP rpWORLDTEXTURED rpWORLDMODULATEMATERIALCOLOR rpWORLDPRELIT ConditionGeometry (RwBool) UserSpecifiedBBox (RwBool) UserBBox (RwBool) FixTJunctions (RwBool) Flags (RwInt32) Finally, the RpWorld object can be serialized. Converting custom formats You can use a custom file format for your models, or have legacy objects for which the original modeling tool files have become lost or incompatible with newer tools. In such cases, it is more convenient to write a format converter and the world Example explained earlier in this chapter. ✎ I-238 RenderWare Graphics separates static and dynamic geometry into Worlds and Atomics/Clumps. It would therefore make little sense to convert a legacy car model into an RpWorld object, or a complex building into an RpAtomic. RenderWare Graphics can perform intelligent scene management with an RpWorld, and can efficiently animate dynamic RpAtomics. 11 February 2004 Creating Worlds Creating an Empty World It is sometimes useful to create a "blank" World object that contains no scenery data. Such usage is common in viewer utilities and many of the viewers supplied with the RenderWare Graphics SDK do use empty Worlds. These Worlds contain only an empty World Sector that fills the entire world space and can be easily created using the RpWorldCreate() function. This takes a bounding box (RwBBox) parameter, which defines the extents of the single World Sector. You will find this function used frequently in the many SDK Examples supplied on the CD. Creation Flags A World's model data can be handled in a number of different ways. For instance, you might want to avoid lighting it dynamically using Lights and just use pre-lit vertices. Or, you may want to tell the rendering pipeline that the data is organized as triangle strips so it can run faster on the target platform. ✎ It is not normal to change these flags once the World has been created or loaded. Doing so may have a detrimental effect on performance. These and other settings are made using the RpWorldSetFlags() function. This exposes the following flags: • rpWORLDTEXTURED The World has textures applied. Texture coordinates are specified on a per vertex basis. If reading World data from a stream, you will need to either setup the search path for the Textures using RwImageSetPath(), or load a Texture Dictionary containing the Textures first. • rpWORLDPRELIT The World has prelit colors. The modeling package exporters provide full support for prelights. See the Artists Guides supplied with the exporters for details. • rpWORLDNORMALS The World has vertex normals. Normals are a requirement if you intend to have dynamic Light objects that affect the scenery. The rpWORLDLIGHT flag should also be set in such cases. • rpWORLDLIGHT Dynamic Light objects will light the World. RenderWare Graphics 3.7 I-239 Chapter 12 - World and Static Models Setting this flag tells RenderWare Graphics to allow dynamic Lights to affect the static geometry. As this form of lighting requires additional processing, you should take care when using this. Dynamic Lights also need normals for the lighting calculations, so you should also set the rpWORLDNORMALS flag as well. Using dynamic Lights does not preclude the use of prelights, but you may need to set the rpWORLDMODULATEMATERIALCOLOR flag if you intend to mix the two forms to best effect. • rpWORLDTRISTRIP World's static geometry can be rendered as triangle strips. This is a hint to the rendering pipeline that the model data is optimized as triangle strips. Triangle strips are an option available on the RenderWare Graphics modeling package exporters. • rpWORLDMODULATEMATERIALCOLOR This flag tells the rendering pipeline to take (a) lighting, (b) prelights and (c) Material colors into account when rendering the model data. This usually gives the most accurate rendering results, but can be expensive in terms of processing power. 12.5.2 What is Pre-lighting? The distinction between static and dynamic models is not the only such division. RenderWare Graphics also supports both dynamic and static lights. Static lighting doesn't actually involve a separate object, as the data is stored directly in the vertex data as arrays of RwRGBA color values. During the rendering cycle, the pipeline will simply combine this vertex prelight data with the Material for that vertex and extrapolate across the surface of the triangles. Prelights are defined by the artist in their modeling package. The artist can position supported lighting types at the appropriate locations in their model. Artists must then tag all static lights using a "prelight" tag (the exact method for doing this varies from modeling package to modeling package). At the export stage, the artist selects the appropriate option in the RenderWare Graphics exporter's options dialog box and the exporter then sets up the vertex lighting arrays and writes them out with the rest of the model data. ✎ I-240 The nature of the pre-lighting processing means only some of the modeling package's full complement of lights can be used for this purpose. See the artist documentation for modeler-specific details. 11 February 2004 Creating Worlds Creating Prelights using the World Import Toolkit The World Import Toolkit exposes the RtWorldImportVertex object. This is defined as follows: typedef struct RtWorldImportVertexTAG { RwV3d OC; /* World space vertex position */ RwV3d normal; /* World space vertex normal */ RwRGBA preLitCol; /* Vertex Pre-light color */ RwTexCoords texCoords; /* Vertex texture coordinates */ RwInt32 clipFlags; /* Internal use only */ RwInt32 matIndex; /* Vertex material index */ } RtWorldImportVertex; As you can see, setting the prelight color is simply a case of modifying the preLitCol element. Static Lights Static model prelights work a little differently compared to its dynamic model variant. RenderWare Graphics assumes static models are completely static – including any prelight data – so prelight colors cannot be manipulated directly. If you need lights that flicker, or any similar such effects, you will need to use either dynamic lights or Atomics placed over the static model. RenderWare Graphics 3.7 I-241 Chapter 12 - World and Static Models 12.6 Rendering 12.6.1 How to Render Worlds Rendering a World object will render its contents. This means that, usually, rendering a complete scene can be achieved with a single call to RpWorldRender(). The Rendering Process When you call RpWorldRender(), the BSP tree is searched and the visible World Sectors are rendered in turn. The following points should be taken into consideration: ✎ • When each World Sector is rendered, each Atomic and Light in that sector is rendered before the next visible World Sector is processed. • Rendering is performed either back-to-front, or front-to-back depending on which is faster on that particular platform. • Local dynamic Light objects may only affect some World Sectors. Use the bounding-box-to-sphere intersection collision detection functions to identify these. Rendering World Sectors World Sectors are rendered automatically by calls to RpWorldRender(). It is not possible to explicitly render a specific World Sector object. Render Callback It is possible to hook into the World Sector rendering process by providing a callback function to RpWorldSetSectorRenderCallBack(). This callback function, of type RpWorldSectorCallBackRender(), will then be triggered prior to rendering each sector. This allows you to include your own optimization techniques. The RpPVS visibility culling Plugin uses this hook. 12.6.2 Instancing A static geometry in RenderWare Graphics has two representations: a platform-independent (PI) representation (also known as platform neutral) and a platform-specific (PS) representation (also known as native data) optimized for the underlying hardware. The process of converting from platform neutral data to native data is called instancing. This process normally happens only during the first rendering of the world. I-242 11 February 2004 Rendering Native data is not actually stored within the geometry itself. Instead, it is allocated space in the Resource Arena. This is a cache that only stores native data. The caching metaphor is particularly apt since existing native data can be thrown out if there isn't enough space left to create new instances of other geometries that need to be rendered. This can result in a problem known as arena thrashing, whereby performance is crippled by the need to re-instance the geometry every frame. The Resource Arena's size is set during the start-up phase by calling the RwEngineInit() function. Exactly what size you should set is heavily dependent on your application, so you will need to experiment to get a good balance between speed and efficiency. The ideal is as small as possible without arena thrashing ever occurring during application execution. 12.6.3 Pre-instancing Static Geometry One optimization of the above instancing scheme can be performed if it is known that the platform independent (PI) representation will not be used at run-time, and that is to use solely pre-instanced platform specific (PS) representation, rather than creating it at run-time. This has the advantages that no CPU cycles are used to instance data on their first rendering, which gives a minor performance improvement, but also means that space is not required for storage of the platform neutral data. In the case of static geometry this is strongly recommended. The RpWorldInstance() function is used to generate a persistent copy of the native data, so at that time both representations of the world exist. The PI representation exists as before and the PS representation both exist outside the resource arena. When rendering occurs the platform specific representation is always used and the resource arena is now not used by the world during rendering. The platform specific data generated should be considered opaque and highly volatile as the format is subject to change between versions. Worlds with pre-instanced geometry are serialized slightly differently from those without. If the world is serialized, the function for writing the geometry to the stream RpWorldStreamWrite() does not export platform neutral data when persistent native data is present, and consequently when the world is loaded into memory with RpGeometryStreamRead()the PI data is lost. This is where the memory saving occurs. As the instancing process has already been performed and is not performed at run-time, the resource arena is never used, and the resource arena size may be reduced accordingly. The resource arena may be eliminated altogether if no instancing occurs, which would require any dynamic geometry to be pre-instanced too, see the Dynamic Models chapter of this guide. This means that features which use the PI data will no longer work, and functions to get PI data will return failure codes. For instance, static PVS creation should be undertaken before pre-instancing. Collision detection is not possible, though a lower resolution collision geometry, which is never rendered, could be used to test for collisions. RenderWare Graphics 3.7 I-243 Chapter 12 - World and Static Models The only exception to this is that the number of vertices and triangles in the geometry are preserved and can be read using RpGeometryGetNumVertices() and RpGeometryGetNumTriangles() respectively. These are stored mainly so that sensible metrics can be observed with PS data, and the actual PI triangle data itself is not present. Using RpWorldInstance() Firstly the availability of pre-instancing of worlds varies from platform to platform, and so please check the platform specific documentation for your platform to determine if this feature is supported for your platform. To pre-instance a world, it is required that the world plugin is attached. Also the correct rendering pipelines must be attached to the world and any materials it uses before the RpWorldInstance() function is called. These rendering pipelines may introduce PS data which is required to give the desired effect during rendering The RpWorldInstance() function must be called within the RwCameraBeginUpdate() and RwCameraEndUpdate() pair of calls within the rendering loop, as the render pipelines must be executed to ensure that all the relevant data is created. In practice the RpWorldInstance() function is similar to the RpWorldRender() function but that the PS data is not created in the resource arena but allocated from the heap, ensuring that the data is persistent. Clipping and culling are never performed so that all instanced data is generated even if not inside the camera’s view frustum. Save the world to disk using serialization functions as described below and use this as the asset for loading from the game disk. If loading of the PS data fails, it is sensible during development to automatically fallback to loading a platform independent version of the asset, and flag it for preinstancing in the render loop. Then save the new pre-instanced version over the top of the one that failed to load. This will cope with any changes to the binary format of pre-instanced data caused by updating your version of RenderWare Graphics. ✎ I-244 Pre-instancing should not be attempted when PVS is enabled. 11 February 2004 Serialization 12.7 Serialization The RpWorld object supports serialization through the standard RenderWare Graphics Binary Stream system. Filename Extensions ✎ The ".BSP" file extension is not obligatory. RenderWare Graphics has only one file format as such: the RenderWare Graphics Binary Stream. Different extensions are used as a memory aid. The functions provided by the RpWorld API for this purpose are: • RpWorldStreamGetSize() This returns the size, in bytes, of the binary stream representation of the given RpWorld object excluding dynamic objects. ✎ The size returned by this function is not the same as the size of an actual RpWorld object. • RpWorldStreamRead() Reads an RpWorld object, and all the RpWorldSector objects it contains, from the specified RenderWare Graphics binary stream. • RpWorldStreamWrite() Writes an RpWorld object, all the RpWorldSector objects it contains, to the specified RenderWare Graphics binary stream. • RpWorldSetStreamAlwaysCallBack() You provide a callback function, which will be called after any RpWorldStreamRead() operations. This function is designed to allow plugins that extend RpWorld to initialize structures based on data read from the stream. The callback is called after all World Sectors have been read. There is also an equivalent function for RpWorldSector objects, named RpWorldSectorSetStreamAlwaysCallBack(). This exists for similar reasons to the RpWorld function, but is called after each World Sector is read. ✎ It is important to remember that only the static model data is referenced when serializing RpWorld objects. Dynamic models must be written separately by explicit calls to the appropriate …StreamRead/Write() functions. RenderWare Graphics 3.7 I-245 Chapter 12 - World and Static Models 12.7.1 Writing The world SDK Example includes the code needed to serialize the World object it creates. This code is near the end of the world.c file. (The code fragments below show only the relevant code for clarity.) First, open a RenderWare Graphics binary stream… RwStream *stream; RwChar *path; path = RsPathnameCreate(RWSTRING ("./world.bsp")); stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMWRITE, path); …the stream needs to be writeable, hence the rwSTREAMWRITE flag… RsPathnameDestroy(path); if( stream ) { RpWorldStreamWrite(world, stream); …now the RpWorldStreamWrite() function to write the RpWorld's static model data to the stream. ✎ It is important to note that this function only writes static model data – the World Sectors – to the stream. No dynamic model data is written. At this point, all that is left is to close the stream thus: RwStreamClose(stream, NULL); } These steps should result in a file on disk with the name specified in the RwStreamOpen(). (In the code fragment above, the file would be named "world.bsp".) Dragging this file onto the "clmpview" viewer or the "RenderWare Visualizer" viewer should also display the buckyball. ✎ I-246 Note that the textures are not saved with the World data as they are treated separately. In most cases, they are already on the disk as either individually-serialized Textures (rare) or stored together in groups as a Texture Dictionary. 11 February 2004 Serialization 12.7.2 Reading The most common use of static models is as scenery. Normally, you will want to read such models from a RenderWare Graphics binary stream and render the resulting RpWorld object. The process is: 1. Ensure the path to any Texture images has been set using RwImageSetPath(). 2. Open a RenderWare Graphics binary stream using the standard RwStreamOpen() API. 3. Read the RpWorld object from the stream. 4. Close the stream. 5. Render the object. RenderWare Graphics 3.7 I-247 Chapter 12 - World and Static Models 12.8 Destruction C does not provide intrinsic support for object destructors, which means that any objects created in a program must be destroyed explicitly. Any objects associated with a World - the Atomics, Lights, Cameras and static scenery - will need to be destroyed and it is important that this is done in the correct order, as follows: 1. Remove and destroy any Clumps. These may contain collections of Atomics, Lights, and Cameras that are automatically removed from a World and destroyed during this process. 2. Remove and destroy any remaining Atomics, Lights, and Cameras that were added individually to the World. 3. Finally destroy the World itself. This automatically destroys the World Sectors and the static geometry they contain. I-248 11 February 2004 Chapter 13 Dynamic Models Chapter 13 - Dynamic Models 13.1 Introduction RenderWare Graphics' Retained Mode API distinguishes between two types of model: static and dynamic. For example, in a theater, static models are the "scenery" and dynamic models are the "actors". A racing game would therefore use a static model for the racing track and dynamic models for the cars. RenderWare Graphics assumes that a dynamic model is likely to be manipulated in real time by the application. For example, they may be moved around a world by animating the position and rotation of their frames, or their vertex colors or vertex normals could be changed to adjust the appearance of the object. Most real-time 3D graphics programming will make use of dynamic models. I-250 11 February 2004 The World Plugin 13.2 The World Plugin RenderWare Graphics' Retained Mode API is contained within the world plugin (RpWorld). This plugin defines many new object types. In this chapter, however, we are interested in the three primary dynamic model objects: the clump (RpClump), the atomic (RpAtomic) and the geometry (RpGeometry). Of these new objects, only the geometry object actually stores vertex and polygon information. The clump and atomic object are used to help manage the geometry. 13.2.1 The Geometry Object The geometry object contains the vertices, triangle indices, texture coordinates and all other necessary components needed to create a model. It represents a model, or, a part of one, and is the actual object that is rendered. The geometry, however, has no linkage for a frame (RwFrame) object, which is required for positioning within a scene. (Frames are covered in detail in the Fundamental Types chapter.) 13.2.2 The Atomic Object An atomic contains pointers to a geometry object and a frame object. It also contains a bounding sphere. This helps RenderWare Graphics determine quickly whether the atomic (strictly the geometry it points to) is visible. The atomic object provides the link between the geometry and a frame, which allows a geometry to be located within the scene. It is important to realize the difference between the atomic and the geometry. The atomic is a container for geometry. The geometry defines the data. RenderWare Graphics 3.7 I-251 Chapter 13 - Dynamic Models 13.2.3 The Clump Object Models tend to be quite complex and it is common for them to be broken down into smaller separate parts, particularly with hierarchical models. In RenderWare Graphics, a complete model is constructed from more than one geometry object. This means that multiple atomics need to be kept track of to manage complex models. A clump is a container for dynamic objects that are associated with a frame hierarchy. This usually just means atomics, but a clump might also contain cameras and lights. A clump is a convenient place to store, say, a football player's hierarchical model data together in one place. A clump can: 1. Add and remove atomics using RpClumpAddAtomic()and RpClumpRemoveAtomic(). 2. Render atomics in a clump using RpClumpRender(). 3. Get and Set frames in a clump using RpClumpGetFrame() and RpClumpSetFrame(). 4. Load and save clumps. We can attach a frame to a clump and link that frame to the top frame in the model's hierarchy. This way, transforming the clump's frame will transform the clump and the hierarchical model it contains. Be careful to avoid falling into the trap of thinking that the clump defines the relationship between atomics it holds. In fact, the hierarchical relationship is determined completely by the frame hierarchy. A Typical Clump Hierarchy of Atomics I-252 atomic frame clump atomic frame atomic frame frame atomic 11 February 2004 The World Plugin In the figure above, a relationship between clumps, atomics and frames is shown. A single clump contains four atomics. The clump and first atomic share their frame. This frame is itself a parent of a hierarchy of frames and the clump points at the root frame for convenience. The frames in the tree are used by the remaining three atomics. Any changes made to clump's frame since it's the root frame, in this example, will affect all atomics. Frames are parents of atomics, clumps and other objects, for example, camera and lights and more information on frames can be found in the Fundamental Types chapter. A Complicated Clump Hierarchy of Atomics Clump 1 clump Clump 2 frame atomic atomic clump atomic frame frame frame frame atomic atomic The figure above illustrates a more complicated clump hierarchy of atomics. The figure above shows a clump containing atomics, although the objects could just as easily be lights or cameras. Clumps and atomics can be attached to frames. A clump's frame can be the parent of an atomic's frame or a frame can be the parent of multiple atomics and multiple clumps. Why Use Clumps? It is not written in stone that atomics must be grouped in clumps. If you prefer to manage atomics yourself, you are perfectly free to do so; clumps were designed merely as a convenient container object. RenderWare Graphics 3.7 I-253 Chapter 13 - Dynamic Models That said, it can be useful to group atomics of a certain type together, even if they are not otherwise related. For instance, you may want to keep track of all atomics that use a particular Material so that you can get at them easily, or you may have atomics that have special attributes – e.g., they represent collectable items in a game. Again, clumps can be used for this. Attaching a frame to a clump is only required if you intend to render it using RpClumpRender(). You do not need to set up a frame otherwise. The main reason for using clumps is to make use of their iterator functions, which usually make managing hierarchies and arbitrary groups of atomics easier. ✎ ".DFF" Files Files with the extension DFF are considered to be legacy file types from RenderWare Graphics 3.5. These files were generally used to store clumps, but could actually contain anything that could be streamed through the RenderWare Graphics Binary Stream API. By definitions, a DFF would contain a single clump. RWS files are the default binary stream file type now. These files may contain many clumps. See the Serialization chapter for more details on RWS files. 13.2.4 Clump Destruction RpClumpDestroy() destroys all atomics (and other objects) in the clump, and all the frames in the hierarchy of the clump, but will not destroy the frames of the atomics in the clump if those frames are not in the clump hierarchy. I-254 11 February 2004 Creation of Dynamic Models 13.3 Creation of Dynamic Models 13.3.1 Model Creation Overview Clumps, atomics and dynamic model geometry must be created before they can be used in a RenderWare Graphics application. Although these objects can be created dynamically at run time, it is more common to create them offline. Typically, one of the supported modeling packages will be used for this process. The steps involved in exporting dynamic models from modeling package to a file that can be read by a RenderWare Graphics application are described in the documentation supplied with the appropriate exporter plugins. This documentation is supplied with the Art Tools and covers the model creation and export processes. The end result of the export process is, by default, an ".RWS" file of the kind we looked at briefly in the previous section. By convention, these files may contain any number of clump objects. The RenderWare Graphics streaming API can be used to find a clump in this RWS file. This clump will contain one or more atomics and frames. ☛ You can test whether the export process worked by clicking RenderWareÆView in 3ds max or Maya to launch the RenderWare Visualizer. RenderWare Graphics 3.7 I-255 Chapter 13 - Dynamic Models 13.4 Modeling Tools Most developers will be working with models built in a professional modeling package by an artist. To this end, RenderWare Graphics is supplied with a set of exporters for popular modeling packages, as well as some tools to view and test the output from these exporters. 13.4.1 Exporters RenderWare Graphics exporters are available for the following modeling packages: • Discreet 3ds max - support for versions 5 and 6. • Alias|Wavefront Maya - support for versions 4 and 5. Other modeling packages are not supported directly, but a number of RenderWare Graphics Toolkits have been provided to make it easier for you to develop your own exporters and tools. Artist and Programmer documentation are available for the RenderWare Graphics exporters at installation time. 13.4.2 Viewers The RenderWare Graphics SDK comes with three viewer applets. The viewers are RenderWare Visualizer, wrldview and clmpview. RenderWare Visualizer allows you to easily view RenderWare Graphics artwork on any target hardware. wrldview and clmpview deal with static and dynamic model data respectively, using the legacy file types .BSP and .DFF. ✎ The meaning of “legacy” file types is that in the future, RenderWare Graphics exporters may not export to these file types. However, the binary format of these files continues to be supported and this version of RenderWare Graphics will continue to read them. There is no need to re-export existing DFF/BSP/etc. artwork as RWS files. All viewers will accept files for viewing on the target platform. The Win32 builds for wrldview and clmpview are drag-and-drop enabled for legacy file types. You can drop a .BSP (for wrldview) or .DFF file (for clmpview) onto the window to view the file. These viewers are a useful means of testing your artists' exported models to ensure they look the way they're supposed to and contain valid data. I-256 11 February 2004 Modeling Tools 13.4.3 Procedural Model Creation Creating models during the execution of your game (procedural generation) is rare. Normally, you will only ever need to load models exported from a modeling package. However, it is always useful to understand why an object works as it does or needs to be used in a particular way. Also, it is important to realize that the exporters supplied with the RenderWare Graphics SDK are regular RenderWare Graphics applications that make calls into the API. To this end, this section will walk you through the "geometry" SDK example. This example shows you how to build a clump using the API function calls. For simplicity, we will ignore the rendering process of the example, and concentrate on the clump creation code. Overview The code in the example/geometry the geometry.c source file concerns itself with the construction of a simple buckyball object, as shown in the screen shot below. The "buckyball" is a "truncated icosahedron". The model is built from interconnected hexagons and pentagons. buckyball 13.4.4 Vertices & Triangles The first stage in model creation is to define the data. RenderWare Graphics 3.7 I-257 Chapter 13 - Dynamic Models All 3D geometry is defined in terms of vertices. These vertices are linked together to form polygons. The RenderWare Graphics geometry object supports only triangles, which is why the RenderWare Graphics' geometry objects are defined in terms of triangle (RpTriangle) objects. The first section of the geometry.c source file therefore consists of long lists of coordinates (vertices) and array indices, which define our buckyball object. The first list defines 60 vertices: static RwV3d BuckyBallVertexList[60] = { { 0.00f, 145.60f, 30.00f }, { 0.00f, 145.60f, -30.00f }, This list of vertices is indexed by subsequent arrays that use these vertices to define pentagons and hexagons in terms of triangles: static RwUInt16 BuckyBallPentagonList[5*NOP] = { 0, 2, 4, 6, 8, and: static RwUInt16 BuckyBallHexagonList[6*NOH] = { 0, 1, 20, 21, 3, 2, Note that at this point in the example we are not defining the polygons (triangles) that RenderWare Graphics will use, merely defining data that we shall later use. Object Space The vertices that make up the buckyball model are defined in object space. This means they are relative to the origin of the object itself and have no relationship with the world coordinate system. The result, in this case, is that the origin of the buckyball model is in the center of the model. I-258 11 February 2004 Modeling Tools 13.4.5 Textures & Materials Textures The geometry.c source file contains one long function: CreateBuckyBall(). This function processes the data and creates the objects. The first step is to load in the textures that will decorate the buckyball. First, the programmer sets the search path for the texture data. This is done using the Skeleton's RsPathnameCreate() function to create a valid, platform-dependent path. This path is then fed to the RwImageSetPath() function so that RenderWare Graphics knows where to search for the texture map files. RenderWare Graphics will use the path name(s) to determine where on the file system to look for images. (This is similar in concept to the PATH variable found in many CLI-based operating systems.) In RenderWare Graphics, multiple locations can be specified, by separating the paths by semi-colons. Next comes the actual creation of the texture objects with the RwTextureRead() function. The calls to RwTextureSetFilterMode() tells RenderWare Graphics that these textures are to use the "linear" filter mode. The filter mode that is set for each triangle is used by the rendering hardware to control how to texture map the surface. A linear filter mode helps "soften" the texture. In the code below, we load two textures from disk. These textures will be used to texture map the pentagon polygons, and the hexagon polygons respectively. /* * Create the bucky-ball textures... */ path = RsPathnameCreate(RWSTRING("./textures/")); RwImageSetPath(path); RsPathnameDestroy(path); pentagonTexture = RwTextureRead(RWSTRING("dai"), NULL); RwTextureSetFilterMode(pentagonTexture, rwFILTERLINEAR); hexagonTexture = RwTextureRead(RWSTRING("whiteash"), NULL); RwTextureSetFilterMode(hexagonTexture, rwFILTERLINEAR); Textures are no use on their own. They need to be linked to the model data in some way so that RenderWare Graphics knows when and how they should be rendered. RenderWare Graphics 3.7 I-259 Chapter 13 - Dynamic Models Materials Textures require two links with the model data. The first are the texture coordinates (U and V) defining where the texture is applied. Texture coordinates are stored on a per-vertex basis. For RenderWare Graphics' Retained Mode API, the remaining link is the material (RpMaterial) object and we can see that, indeed, the textures are being added to two such material objects just after they are loaded: /* * ...and materials... */ pentagonMaterial = RpMaterialCreate(); RpMaterialSetTexture(pentagonMaterial, pentagonTexture); hexagonMaterial = RpMaterialCreate(); RpMaterialSetTexture(hexagonMaterial, hexagonTexture); A buckyball is made up of pentagons and hexagons and the example's designer has decided to define two material objects, one each for the pentagons and hexagons. Pentagons will therefore all share one material (and its texture), while hexagons will share the other. With the textures now added to a material object, the texture coordinates need calculating for use later. These are calculated in the two subsequent for… loops. (This is documented in the function's source code.) Material Color To use material colors the rpGEOMETRYMODULATEMATERIALCOLOR flag needs to be set (see RpGeometryFlag). If a model is exported with material color 255, 255, 255, 255 the rpGEOMETRYMODULATEMATERIALCOLOR flag is not set and the material color will not be used. ✎ I-260 Using the RenderWare Graphics exporters (3ds max or Maya), if all the materials used are colored white, then the rpGEOMETRYMODULATEMATERIALCOLOR flag is set to OFF, otherwise the flag is set to ON. For worlds and patches, the flags rpWORLDMODULATEMATERIALCOLOR and rpPATCHMESHMODULATEMATERIALCOLOR are used respectively. They are applied in the same way as rpGEOMETRYMODULATEMATERIALCOLOR. 11 February 2004 Modeling Tools 13.4.6 Surface Properties & Geometry The instantiation of the actual geometry object is trivial, although it is worth noting the flags parameter. The full set of available flags is as follows: • rpGEOMETRYTRISTRIP This geometry's meshes can be rendered as strips of triangles. This is an optimization technique available on a number of platforms. ☛ Sony PlayStation2 Optimization Tip Tri-strips are practically mandatory on this platform due to the hardware's design. • rpGEOMETRYTEXTURED This geometry has textures applied. Including this flag means the renderer will expect texture objects to be used. • rpGEOMETRYPRELIT This geometry has pre-calculated lighting data. • rpGEOMETRYNORMALS This geometry has normals. If your model is never going to be lit by RenderWare Graphics' dynamic light (RpLight) objects, you can save on system resources by not storing normals. This is particularly useful for pre-lit models. • rpGEOMETRYLIGHT This geometry will be lit by dynamic light objects. • rpGEOMETRYMODULATEMATERIALCOLOR Modulate material color with vertex colors (pre-lit + lit), allowing prelight vertex colors and dynamic lighting to be blended with the underlying material color. Also defined in this part of the source code is the surface property (RwSurfaceProperty) data for the model. Surface properties define how surfaces reflect light. The three components, as you can see from the code, are ambient, specular and diffuse. Respectively, they determine how much ambient light is reflected by the object, how smooth and shiny the surface is, and how the light is spread over the surface. Surface properties are stored in material objects. Currently in RenderWare Graphics, the lighting does not compute a specular contribution. RenderWare Graphics 3.7 I-261 Chapter 13 - Dynamic Models 13.4.7 Morph Targets Geometry objects are essentially containers, similar to atomics. Their design is such that geometry will contain all the necessary data for a model, or portion of a model. One of the objects the geometry contains is the morph target (RpMorphTarget) object. RenderWare Graphics' Retained Mode Plugin, RpWorld, is intended to provide scene graph facilities with support for animation plugins. The morph target object plays a part in this by supporting morph-target (also known as "keyframe-interpolated") animation. While it is possible to perform morph-target animation directly with RpWorld, most will use the Morph plugin (RpMorph) to perform this kind of animation. For morph-target animation to work, all geometry objects have at least one morph target object. If there was no keyframe-interpolated animation sequence exported from the modeling package then the geometry object will contain exactly one morph target object. The morph target and geometry objects divide the model data between them. The triangle objects, which only reference vertices, are stored in the geometry object. The actual vertex positions and normals themselves are stored in the morph target(s). The prelight and UV texture coordinates for each vertex live in the geometry object. ☛ I-262 Why? Morph Targets exist because only the vertices need to be manipulated, not the model topology itself. 11 February 2004 Modeling Tools 13.4.8 Pentagons & Hexagons After retrieving the necessary pointers to the data structures, the geometry.c then proceeds to set up the data for the pentagons. The for… loop runs through each pentagon in the BuckyBallPentagonList array. The loop is divided into three parts: 1. Calculate the normal for the pentagon; 2. Initialize the vertex, normal and texture coordinates for each vertex in the polygon; 3. Assign the vertices to the triangles, which will define the pentagon, and assign the Material object to these triangles. These processes are performed in the next for… loop for the hexagons as well and the result of all this processing is an almost-complete geometry. Triangle Winding Order It is important that triangles are defined in a specific order. During rendering, RenderWare Graphics looks at the vertices of a Triangle and will only render those with coordinates arranged in a counter-clockwise sequence relative to the camera. If the sequence is clockwise, the triangle is assumed to be facing away from the virtual camera and is not rendered (culled). RenderWare Graphics 3.7 I-263 Chapter 13 - Dynamic Models 13.4.9 Bounding Spheres & Transformations In this example, we want to condition the geometry such that it has an origin at the center of the model, and has a known physical size. The next steps perform these tasks. The next section of code finishes off the construction of the geometry object. It is worth closer inspection… if( normalize ) (The calling function sets this to TRUE.) { /* * Center and scale to unit size... */ RwSphere boundingSphere; RwMatrix *matrix; RwV3d temp; RpMorphTargetCalcBoundingSphere(morphTarget, &boundingSphere); This function calculates a sphere that is just big enough to contain the entire buckyball model. The RenderWare Graphics core library and the world plugin both use bounding spheres heavily. In particular, the bounding sphere is used to determine whether the object is within the camera object's view frustum. Also, if you are making use of the static geometry functionality provided by RpWorld, the sphere is used to check which world sector(s) the model resides in. ✎ RwSphere is a simple exposed data-type. You can find its definition in the API Reference. Continuing with the bounding sphere calculations: matrix = RwMatrixCreate(); RwV3dScale(&temp, &boundingSphere.center, (RwReal)-1.0f); RwMatrixTranslate(matrix, &temp, rwCOMBINEREPLACE); temp.x = temp.y = temp.z = (RwReal)1.0f / boundingSphere.radius; RwMatrixScale(matrix, &temp, rwCOMBINEPOSTCONCAT); At this point, we have a matrix that contains two operations: 1. A translation that positions the object coordinate system origin at the center of the buckyball; 2. A scaling operation that will shrink our buckyball model to a unit size. I-264 11 February 2004 Modeling Tools This means that we now have a matrix that can be used to translate and rescale our buckyball model ready for viewing. ✎ This scaling is being done because the vertex list was calculated with paper and pen, rather than a 3D-modeling package. The next step is to apply the transformation matrix to our geometry object and then to destroy the matrix itself as we no longer need it. The call into RpGeometryTransform() will compute and set the bounding sphere for all morph targets on our behalf. /* * This will re-calculate and set the new bounding sphere * and also unlock the geometry... */ RpGeometryTransform(geometry, matrix); RwMatrixDestroy(matrix); } If you take a look at the code branch that is taken if normalize is not set, then you can see what code is necessary to compute and set bounding spheres: RwSphere boundingSphere; RpMorphTargetCalcBoundingSphere(morphTarget, &boundingSphere); RpMorphTargetSetBoundingSphere(morphTarget, &boundingSphere); Note that each separate morph target in a model requires a bounding sphere to be calculated and set. In this example, the code assumes (correctly) that there is only a single morph target. Locking, Unlocking Geometry objects are created in a locked state. Geometry objects have to be locked while they are having their actual content changed. (They can be translated and transformed using frames without locking them.) Unlocking the geometry will usually result in RenderWare Graphics creating new mesh (RpMesh) objects if the model data has been fundamentally changed. Mesh objects are covered in detail later in this chapter. RenderWare Graphics 3.7 I-265 Chapter 13 - Dynamic Models 13.4.10 Atomics and Clumps We've only created a geometry object so far. The next few lines of code put the geometry in a clump. /* * That's it...stick it in a single-atomic clump and return.. */ clump = RpClumpCreate(); frame = RwFrameCreate(); RpClumpSetFrame(clump, frame); At this point, we have an empty clump object with a frame. Clumps need frames so that they can be moved around. Now for the atomic… atomic = RpAtomicCreate(); frame = RwFrameCreate(); RpAtomicSetFrame(atomic, frame); This code has been used to create an empty atomic object with its own frame. RpAtomicSetGeometry(atomic, geometry, 0); This line links the geometry to the atomic. Atomics can only contain one geometry, so for a more complex model, multiple atomics would be needed, each with their own geometry. ✎ The third parameter to RpAtomicSetGeometry is a flag which should only be set to TRUE if you want to retain the bounding sphere from a previous geometry object stored in the atomic. This is an unusual situation, and possibly, one you will never encounter. RpClumpAddAtomic(clump, atomic); This links the atomic with the clump, so now we have our clump, atomic and geometry all nicely packaged. One final step remains: RwFrameAddChild(RpClumpGetFrame(clump), frame); This line links the clump's frame to that of the atomic. Without this, moving the clump around will have no effect whatsoever on the model itself; frames must be linked hierarchically like this for transformations to grow correctly. ✎ This point is an important one. Clumps do not actually manage hierarchies themselves; they're just dumb containers that make it easier to manage complex models. Our clump has been now completed and the only thing left to do is to return it to the calling function. return clump; I-266 11 February 2004 Objects in more detail 13.5 Objects in more detail In this section, we'll examine some of the objects we've encountered and look at them in more detail. 13.5.1 Reference Counting Many RenderWare Graphics objects use a reference counting system to avoid being destroyed prematurely. This involves objects maintaining a counter that is incremented whenever a reference is made to the object and the counter decremented when a reference is removed. RenderWare Graphics provides an …AddRef() function for each object which supports a reference counter. This function must be called when adding a reference to an object. To delete an object, use the equivalent …Destroy() function. This function will only destroy the object if the reference count is at zero, otherwise it just decrements the count. All objects defined by the World plugin must be destroyed explicitly after use. For example, you cannot simply destroy an RpWorld object on the assumption that it will automatically destroy all objects it contains as the results of this are undefined. Instead, you must iterate through all the contained objects, call the appropriate RpWorldRemove…() method on each, destroy it (if required) using the object's own …Destroy() method, and repeat for the remaining objects in the World. While this sounds overly complicated, it does allow objects to be reused more easily. In the end, the benefits outweigh the costs. 13.5.2 Texture coordinates By default, RenderWare Graphics' 3D Immediate Mode and Retained Mode supports only one (U,V) pair per vertex. A geometry does, however, have the ability to store up to 8 sets of UV pairs. If you need more than this, which is highly unlikely, the plugin mechanism can be used to extend the geometry structure. A textured geometry must be created by passing in the appropriate flags to RpGeometryCreate. For a single texture, use rpGEOMETRYTEXTURED. For more textures, use rpGEOMETRYTEXCOORDSETS(n) where n is the number of required texture coordinate sets. After the geometry is created, the storage for each set of texture coordinates specified can be access by calling the RpGeometryGetVertexTexCoords() API. This returns a pointer to an array of texture coordinate pairs, RwTexCoord. There is no equivalent “set” function. RenderWare Graphics 3.7 I-267 Chapter 13 - Dynamic Models Whenever the geometry is locked, you have write access to the contents of this array. (Note however that the geometry must be locked in a mode that supports access to texture coordinates, i.e. rpGEOMETRYLOCKTEXCOORDS, rpGEOMETRYLOCKTEXCOORDSn, rpGEOMETRYLOCKTEXCOORDSALL, or rpGEOMETRYLOCKALL). At all times, you have read access to this array. How you use texture coordinates (RwTexCoords) is heavily influenced by the target platform as well as the modeling package. For instance, ranges might be different from platform to platform because some consoles place limits according to their specific chipset designs. 13.5.3 Prelighting This is a form of static lighting and full details are given in the Worlds & Static Models chapter. In brief, prelighting involves pre-calculating the lighting values of vertices at design-time and storing the colors in the geometry. No further calculation is then required for the rendering. The major problem with this technique is that the lighting isn't "real" in any sense: if you position another model nearby, the prelit model will not cast any light or shadow upon it. As we saw in the example earlier, a simple flag setting can be used to determine if an atomic should be affected by dynamic lighting. This applies equally to prelit and unlit models. It should be noted that if the models are animated or transformed then prelighting data may no longer be valid. RenderWare Graphics will continue to use this data however. 13.5.4 Surface properties These are stored in material objects. Surface properties (RwSurfaceProperties) are used in dynamic lighting calculations and basically describe how lighting reflects from the surface of a model: whether it's shiny and just leaves a bright spot of color, or whether it's matte and spreads the light around a bit more. This mechanism is becoming superseded by PowerPipe API provided by RenderWare Graphics. This API gives more control over the rendering process. 13.5.5 Meshes The mesh (RpMesh) object is elusive. It hides inside the geometry object and is only barely exposed. I-268 11 February 2004 Objects in more detail This object is actually an internal, optimized representation of the model topology. It is the reason why geometry objects have to be locked and unlocked. When the model is unlocked by the application, RenderWare Graphics will take the model data and convert it into one or more mesh objects. Each mesh contains a group of triangles sharing the same material object. This minimizes render state changes required during rendering since RenderWare Graphics will render each mesh to completion before rendering the next. The mesh is stored as triangle lists, triangle fans or triangle strips. The API function RpMeshSetTristripMethod() lets you supply a callback function to perform the tri-stripping according to your own requirements. The choice between using tri-lists and tri-strips can be made using the RpGeometrySetFlags() function. If rpGEOMETRYTRISTRIP is set, triangle strips will be used, otherwise triangle lists will be used. At this time, you cannot construct meshes that use triangle fans to represent the object. Note that triangle strips may result in the creation of degenerate triangles, as shown in the diagram below. A C B ABC BCC CCX CXX XXY XYZ X Z Y In this example, there are two geometrically partitioned sections of the strip, the ends of which are shown: one on the left and one on the right. Since the triangle strip has to be continuous, four additional degenerate triangles are created, the vertices of which are listed in gray. Each new degenerate triangle introduces a duplicated vertex. RenderWare Graphics relies on graphics hardware being accurate enough to know that a zeroarea triangle cannot cover any pixel. This is certainly true on PlayStation2. RenderWare Graphics 3.7 I-269 Chapter 13 - Dynamic Models 13.6 Atomics, Clumps & Transformations Frames are important when dealing with atomics and clumps. They define the links that join hierarchical model elements together. They also give the atomics – and therefore, their contained geometry objects – a sense of place by giving them storage for position and orientation. The clump, atomic and frame objects have already been covered in some detail. This section will look at them in the context of Dynamic Models. 13.6.1 Worlds In order to render a clump or an atomic, we usually need to add the object to a world. Doing this gives RenderWare Graphics a frame of reference to work with and lets RenderWare Graphics work out whether the object is visible. For more information on the world object, read the World & Static Models chapter. ✎ One important point to note is that RenderWare Graphics relies on the bounding sphere defined for each atomic to determine (a) whether it is within the World, and (b) whether it should be rendered. A common mistake when creating atomics is to forget the calculation of the bounding sphere and this will often result in their not being rendered, no matter what you try and do with them! 13.6.2 Cloning Clumps and atomics cannot be copied directly, but they can be cloned. The functions for this are RpClumpClone() and RpAtomicClone(). What is Cloning? The cloning process will copy the interpolator, bounding sphere, render callback and a reference to (i.e. pointers to) the geometry object. The fact that pointers are copied means that a cloned object will share the exact same geometry object as the original. Changes made to the geometry affect all clones that reference it. ✎ Cloned atomics will have no attached frame: you'll need to create and add one yourself. Cloned clumps will copy the entire frame hierarchy. The RpClumpClone version naturally calls RpAtomicClone for all atomics contained in the original clump. I-270 11 February 2004 Atomics, Clumps & Transformations 13.6.3 Iterator functions General Iterators RenderWare Graphics supplies iterator functions for accessing atomics within clumps, materials within geometry objects, and so on. It is extremely common for these iterator functions to be used together. • RpClumpForAllAtomics() This iterator will call your supplied callback function on each atomic the clump contains. You can pass a (void *) data pointer to your callback through the iterator function to support user data. A simple use of this iterator function would be to visit every atomic that a clump contained, and increment a variable for each. This is a simple way to determine how many atomics the clump contains. It is common for a clump to contain just a single atomic. In this scenario, using the callback mechanism is the only way to get from the clump to the atomic. This can be inconvenient, although it is easy for an application to extend the clump object to contain a pointer to the (single) atomic. • RpAtomicForAllWorldSectors() We learned earlier that atomics, when added to worlds, are linked to world sectors so that RenderWare Graphics can work out which atomics can be ignored during the rendering process. This function will iterate through all the world sectors with which the atomic intersects, calling your supplied callback function. An example use of this iterator would be to examine which world sectors the atomic spans. Other iterator functions can get from a world sector to any lights that it contains, and so these functions can locate lights that affect the atomic. • RpWorldForAllClumps() This iterator will call your supplied callback function on each clump the world contains. You can pass a (void *) data pointer to your callback through the iterator function to support user data. If in your game you wanted to fade out every dynamic object, at the end of a level, say, you could use this function to visit every clump. Other callback functions could then be used to modify every material that each clump used. RenderWare Graphics 3.7 I-271 Chapter 13 - Dynamic Models • RpWorldSectorForAllAtomics() This iterator will call your supplied callback function on each atomic intersecting the specified world sector. You can pass a (void *) data pointer to your callback through the iterator function to support user data. • RpGeometryForAllMaterials() This iterator will call your supplied callback function on each material object within the specified geometry. You can pass a (void *) data pointer to your callback through the iterator function to support user data. This function is typically used by an application as it gets access to the texture that each material holds. • RpGeometryForAllMeshes() This iterator will call your supplied callback function on each mesh object within the specified geometry. You can pass a (void *) data pointer to your callback through the iterator function to support user data. • RwCameraForAllClumpsInFrustum() This iterator will call each clump's registered callback function on all clumps that can be seen by the specified camera object. You can pass a (void *) data pointer to your callback through the iterator function to support user data. The clump's callback function is specified by the RpClumpSetCallBack() function. You will need to set this to an appropriate callback of your own for all clumps that you need to intercept. Intersection test iterator The atomic object supports some collision-detection functionality in the form of the following iterator: • RpAtomicForAllIntersections() Requires a callback defined as type RpIntersectionCallBackAtomic(). This callback function is triggered for each intersection found between the atomic and the requested collision type, defined as an RpIntersectionType enumeration. RpIntersection defined The collision type mentioned above is an enumeration that identifies the type of collision primitive to test for. The types currently supported are: I-272 11 February 2004 Atomics, Clumps & Transformations • rpINTERSECTLINE: Line intersections. • rpINTERSECTPOINT: Point intersections. • rpINTERSECTSPHERE: Sphere intersections. • rpINTERSECTBOX: Box intersection. • rpINTERSECTATOMIC: Atomic intersections Atomic Rendering Callback It is possible to set a rendering callback for individual atomics. This callback, RpAtomicCallBackRender(), will be triggered when the atomic is about to be rendered, either by the RpWorldRender() function, or directly via RpAtomicRender(). This callback can be used, for example, to handle animations on a per-atomic basis. The callback is set using RpAtomicSetRenderCallBack(). Using atomic render callbacks can produce some very powerful techniques. Typically an application will want to store away the atomic render callback that is currently being used (with RpAtomicGetRenderCallBack()). This gives the application a way to continue with the atomic rendering. In RenderWare Graphics, this technique is called chaining function calls, or hooking functions. One example use might be if the application wanted to perform some high level culling. The application would store the current atomic render function and selectively call the stored function pointer if it wanted the atomic to be drawn. It might make the decision based on the distance of the atomic from the viewer or some other parameter. (In fact, this technique is exactly how the PVS plugin is implemented.) 13.6.4 Sorting Geometry objects by Material RpGeometrySortByMaterial() is used to create a modified clone of the specified geometry object. The modification involves sorting vertices by material and duplicating them along material boundaries where necessary. If the source geometry contains any RenderWare Graphics plugin extensions, the application must provide an RpGeometrySortByMaterialCallBack() callback function to update the extended data as appropriate. The callback will receive pointers to: • the original geometry; • the new geometry; • a mapping array that links every vertex in the new geometry with that of the corresponding vertex in the source geometry using vertex indices, and… RenderWare Graphics 3.7 I-273 Chapter 13 - Dynamic Models • the length of the mapping array, the number of vertices in the new geometry. On completion, each material's mesh references an independent set of vertices within the larger vertex array of the geometry. No vertices are shared between materials. The new geometry is returned in an unlocked state. 13.6.5 Animation RenderWare Graphics supports a number of animation techniques. The World plugin itself supports only a subset of these directly: other plugins need to be attached to use the others. In this section, we'll look at the forms of animation available directly to the World plugin. Frame-based We have already seen how frames affect the position and orientation of their associated atomic or clump. It is worth reiterating that hierarchies of frames can also be animated, either in whole or in part, by simply applying transformations and rotations to the individual frames. Using this technique, it is possible to animate hierarchical models procedurally by simply adjusting the appropriate frame objects. Vertex-based Vertex-based animation is usually best left to the morph target plugin (RpMorph). This plugin uses keyframes, defined in terms of morph target objects, with linear interpolation between these simple animations of an atomic. The API does expose some functionality that will let you access the vertex data directly. A number of animation techniques can be applied using this API, such as UV morphing, procedural vertex animations etc. However, there are some important notes that you need to read before you attempt such animation: • Geometry objects must be locked before you change any vertices. • Geometry objects must be unlocked after you've made your changes. • This lock-unlock cycle can be very slow. RenderWare Graphics may have to convert and/or re-instance the model data during the cycle and this can drastically impact performance. I-274 11 February 2004 Atomics, Clumps & Transformations • The only time the lock-unlock cycle is not needed is when changing material data. The only exception to this is for PC targets, when you want to change the material color and the modulate flag is set; this requires the geometry prelight to be locked. 13.6.6 Skinned Models "Skinning" is a form of model representation that applies weights to vertices and uses these weights to morph vertices. The technique is particularly applicable to organic character models such as humans, animals and others with flexible skin. This form of model representation is provided by the skin plugin (RpSkin). RenderWare Graphics 3.7 I-275 Chapter 13 - Dynamic Models 13.7 Optimization A RenderWare Graphics Toolkit, RtWorld, exists to provide a number of functions for world objects. Usually, the modeling package's RenderWare Graphics exporter plugin will use these when writing models out in RenderWare Graphics format. However, you can also use the functionality yourself in your own tools and utilities. The function of interest to us at this point is: • RtGeometryCalculateVertexNormals() This function is used to calculate a normal vector for each vertex defining the specified geometry. The geometry must have been created with the rpGEOMETRYNORMALS flag so that the data array holding the vertex normals is available. A vertex normal is calculated by averaging the face normals of all connecting polygons that share the vertex, weighted by the angle subtended by each polygon at the vertex. If the vertex is not shared, a normal equal to the face normal is used. The resulting vertex normals are set to unit length. Note that the geometry is unlocked after the vertex normals have been calculated. I-276 11 February 2004 Rendering 13.8 Rendering 13.8.1 How to Render Dynamic Objects There are two ways to render a dynamic object: directly or indirectly. In either case, the functions described need to be called between RwCameraBeginUpdate() and RwCameraEndUpdate() pair. Rendering Atomics and Clumps directly Assuming you have a camera to render into, you can render directly using either RpAtomicRender() or RpClumpRender(). You don't need to create a world object first, although rendering without one is rare. If you do have a world, some platforms will apply dynamic lighting to your model, regardless of whether you added it to the world object. See the platform-specific documentation supplied with the SDK for more details on this. ✎ RenderWare Graphics assumes you have handled visibility calculations when rendering directly, so it will attempt to render the model regardless of whether it is actually visible. Although rendering the model when it isn't visible will not cause any crashes, this can be a common cause of inefficient rendering and generally strange behavior. Render CallBack issues It is important to realize that rendering models with these functions will trigger any attached render callbacks regardless of visibility. If your callback functions are being called, but you cannot see the model on screen, this is probably the reason. RpWorldRender() This function is among the most powerful, most useful functions within the RenderWare Graphics API. A glance at the API Reference for RpWorld will reveal functions for adding clumps, atomics, lights and even cameras to a specified world object. When these functions are used, they add references to the specified object to any World Sectors within which they are located or intersect. ✎ Local & Global Lights There are two kinds of dynamic lights: local lights, which need to have a frame attached to them, and global lights, which do not. Local lights include spotlights and point lights. These need a frame object to define position and orientation. These lights are added to a world sector in the same way as an atomic, camera or clump. This allows the rendering engine to determine which world sector(s) are affected by the light. The number of world sector(s) affected by a Local light depends upon their radius of effect. Global lights include ambient and directional lights, which are assumed to affect the entire world. These should still be added to a world, but on some platforms, they will affect all worlds, regardless of whether they have been added to them or not. RenderWare Graphics 3.7 I-277 Chapter 13 - Dynamic Models The RpWorldRender() function can then be used to render an entire scene with a single function call. It first determines where the target camera is so it can then iterate through all visible world sector objects within the world and render them. As it renders each world sector, it checks it for any references to atomics, clumps and so forth and renders any it finds. This makes rendering a lot easier as you can just add clumps and atomics to a world and not have to worry about render order, frustum testing, culling, visibility etc: the RpWorldRender() function will do this for you. ✎ There is an exception to this: models with transparent materials often need a second rendering cycle for those materials on some platforms to ensure that models are rendered in the right order. Z sorting on the fly is not done by RenderWare Graphics. See the "alphasrt" example to see how this situation is handled. 13.8.2 Instancing A model in RenderWare Graphics has two representations: the platformindependent geometry/morph target data you get to play with and apply for collision detection, and an internal, platform-dependent "instanced" form optimized for the underlying hardware. This instantiation process usually happens once, on first rendering the model. RenderWare Graphics performs best when the vertices of your models stay put so it doesn't have to convert them to the platform-specific internal form again. Changing vertices is possible, but you have to lock the geometry first and inform RenderWare Graphics how – or if – the data is about to change using the lock flags. You are then free to change the vertices within the constraints you set yourself. Once you've done that, you must unlock the geometry. At this point, the platform-specific data is in a kind of limbo: only when – or, indeed, if – it is rendered will RenderWare Graphics' instantiation process kick in to convert your changed vertices into the platform-specific form needed to keep things running fast. Instanced data is not actually stored within the geometry itself. Instead, it is allocated space in the Resource Arena. This is a cache that only stores instanced data. Some platforms may store portions of instanced data in dedicated hardware video memory for efficiency. The caching metaphor is particularly apt since existing instanced data can be thrown out if there isn't enough space left to create new instances. This can result in a problem known as arena thrashing, whereby performance is crippled by the need to repeatedly re-instance the same geometry data during a rendering cycle because there isn't enough space to store a full scene's instanced data. The Resource Arena's size is set during the start-up phase by calling the RwEngineInit() function. Exactly what size you should set is heavily dependent on your application, so you will need to experiment to get a good balance between speed and efficiency. I-278 11 February 2004 Rendering Optimizing with a Metrics Build Determining the best Resource Arena size requires knowing how it is being used. The metrics build of the RenderWare Graphics libraries can help you decide on the best trade-off between speed and hardware resources by displaying resource usage on your target platform. The RwMetrics structure varies from platform to platform so you should see the platform-specific documentation for more details on what is supported on your target hardware. This screenshot shows the Win32, Direct3D metrics build in use in the "world" example. 13.8.3 Pre-instancing Dynamic Geometry One optimization of the above instancing scheme can be performed if it is known that the platform independent (PI) representation will not be used at run-time, and that is to use solely pre-instanced platform specific (PS) representation, rather than creating it at run-time. This has the advantages that no CPU cycles are used to instance data on their first rendering, which gives a minor performance improvement, but also means that space is not required for storage of the platform independent copy of the data. The RpAtomicInstance() function is used to generate a persistent copy of the platform specific data, so at that time, two representations of the atomic exist. The platform independent data and the platform specific data both exist outside the resource arena. When rendering occurs the platform specific representation is always used and the resource arena is now not used by the atomic during rendering. The platform specific data generated should be considered opaque and highly volatile as the format is subject to change between versions. RenderWare Graphics 3.7 I-279 Chapter 13 - Dynamic Models Atomics with pre-instanced geometry are serialized slightly differently from those without. If the atomic is serialized, the function for writing the geometry to the stream RpGeometryStreamWrite() is called internally from RpAtomicStreamWrite(). RpGeometryStreamWrite() does not export PI data when persistent PS data is present, and consequently when the atomic is loaded into memory with RpAtomicStreamRead() or RpGeometryStreamRead() only the PI data is lost. This is where the memory saving occurs. As the instancing process has already been performed offline, and is not performed at run-time, the resource arena is never used, and the resource arena size may be reduced accordingly. The resource arena may be eliminated altogether if no instancing occurs, which would require any static geometry to be pre-instanced too, see the Worlds and Static Models Chapter of this guide. This does mean that features which use the PI data will no longer work and functions to get PI data will return failure codes. For instance RpMorph and RpDMorph will not function, and static PVS creation should be undertaken before pre-instancing. Collision detection is not possible, though a lower resolution collision atomic which is never rendered could be used to test for collisions. The only exceptions to this is that the number of vertices in the geometry, and the number of triangles in the geometry, are preserved and can be read using RpGeometryGetNumVertices() and RpGeometryGetNumTriangles() respectively. These are stored mainly so that sensible metrics can be observed with PS data, and the actual PI triangle data itself is not present. Using RpAtomicInstance() Firstly the availability of pre-instancing of atomics varies from platform to platform, and so please check the platform specific documentation for your platform to determine if this feature is supported for your platform. To pre-instance an atomic, it is required that the world plugin is attached. Also the correct rendering pipelines are attached to the atomic and materials before the RpAtomicInstance() function is called. Those rendering pipelines may introduce PS data which is required to give the desired effect during rendering. The RpAtomicInstance() function must be called within the RwCameraBeginUpdate() and RwCameraEndUpdate() pair of calls within the rendering loop, as the render pipelines must be executed to ensure that all the relevant data is created. In practice the RpAtomicInstance() function is similar to the RpAtomicRender() function but that the PS data is not created in the resource arena but allocated from the heap, ensuring that the data is persistent. Clipping and culling are never performed so that all instanced data is generated even if not inside the camera’s view frustum. I-280 11 February 2004 Rendering Save the atomic and use this as the asset for loading from the game disk. If loading of the PS data fails, it is sensible during development to automatically fallback to loading a platform independent version of the asset, and flag it for pre-instancing in the render loop. Then save the new pre-instanced version over the top of the one that failed to load. This will cope with any changes to the binary format of pre-instanced data caused by updating your version of RenderWare Graphics. 13.8.4 Converting Model Data to RenderWare Graphics RenderWare Graphics' reliance on its own data format means you may have data that needs to be converted. This is not a particularly difficult task as a number of utility functions are provided to assist in the conversion process. Usually, you will want to feed in the data in one format and have valid clump or atomic data produced as a result. This is explained below. Conversion Overview The steps necessary to create an atomic or clump are roughly similar. No intermediate data type is necessary, and the exporter can create atomics directly. The steps involved are: 1. Create an atomic by calling RpAtomicCreate(). 2. Create a geometry object by calling RpGeometryCreate(). This function requires the number of vertices and triangles needed by the model, as well as a set of flags. The number of vertices and triangles can be obtained from the source data or, if developing an exporter for a modeling package, a suitable conversion API function. The flags should also be set up as required. For the purposes of simplicity, it is assumed that the geometry contains normals, texture coordinates and lighting values. 3. Obtain the default morph target object (which has an index of zero) from the geometry using RpGeometryGetMorphTarget(). This is where the vertices and normals are stored. 4. The UV coordinates are shared across all key-frames and can be found in the geometry object itself, so get a pointer to them using RpGeometryGetVertexTexCoords(). There is a one-to-one relationship between these and the vertex array in any related morph targets. 5. Obtain the vertex and normal arrays from the morph target using RpMorphTargetGetVertices(), and RpMorphTargetGetVertexNormals() respectively. RenderWare Graphics 3.7 I-281 Chapter 13 - Dynamic Models 6. Iterate over the vertices in your model, copying vertex, normal and texture co-ordinate data from the model into the geometry arrays. 7. Create all the material objects that your model requires, taking care to read any textures necessary from disk and setting material colors correctly. (255 indicates a full intensity color RGB component and also a fully opaque (non-alpha) material.) ✎ You may wish to build a Texture Dictionary object if the Null driver supports your target platform's bitmap formats. Alternatively, you may build a Platform Independent Texture Dictionary that can be used on any target platform. See the Rasters, Images and Textures chapter in this guide. 8. Iterate over the triangles in your model, setting the vertex indices and materials for all triangles in the geometry. You will need to use RpGeometryGetTriangles() to obtain the start address in memory where triangles are stored, and the various triangle object API functions to prepare and store them. 9. Calculate and set a bounding sphere for your morph target, using the API calls RpMorphTargetCalcBoundingSphere() and RpMorphTargetSetBoundingSphere(). (This step is often forgotten, but it is absolutely essential.) 10. Unlock the geometry. 11. Attach the geometry to the atomic with RpAtomicSetGeometry(). Take a look at the geometry example in examples folder to see the above construction process in action on hand-made model data. ✎ Null Libraries The Null Libraries supplied on the SDK are specifically designed for conversion work. For instance, we use them to build our modeling package exporters. These libraries are almost identical to the standard Release ones, with the exception that all actual rendering functionality is removed or diverted to a null driver. This is because conversion programs rarely need to render their output to the display while the conversion is taking place. In addition, it means that functionality or output formats that may not otherwise be supported on a particular platform can be included. Null libraries for each platform are also supplied with the SDK (for example, nullxbox). These are PC libraries used for building certain tools that process platform specific data. They can be used to build platform specific texture dictionaries. It should be noted that Null platform libraries can not create pre-instanced world and geometry data. I-282 11 February 2004 Chapter 14 Lights Chapter 14- Lights 14.1 Introduction RenderWare Graphics has two kinds of lighting models: dynamic and static. This chapter covers static lighting using RpLight. Static lighting can also be achieved using RpLtMap. The dynamic lighting model is the closest in behavior to real-world lighting, with lights being independent from the model geometry. Five light types are supported by the dynamic lighting model: • ambient • point • directional • spot • soft spot Static lighting—not to be confused with static geometry—is less flexible, but requires far fewer resources to use. This lighting model is tied to model geometry and is implemented in one of two ways, depending on whether the geometry itself is static or dynamic. 14.1.1 Other Documentation I-286 • See the API Reference Lighting section for more information about lights and lightmaps. ModulesÆLighting • Lightmaps user guide chapter 11 February 2004 Dynamic Lights 14.2 Dynamic Lights Dynamic lights represent the most flexible light model in RenderWare Graphics. They can: • be fully controlled and manipulated at run-time • be positioned at will and oriented in any direction • selectively illuminate both static and dynamic models • support a number of light types • make use of hardware transform and lighting features Dynamic lights have one important disadvantage: the processing power needed to implement them. On platforms with no hardware transform and lighting support, dynamic lights will eat up a substantial proportion of processing time, effectively limiting the number of dynamic lights your application can use. Another disadvantage is that hardware transform and lighting stages on different platforms generally make use of different algorithms. The result is that the same settings for a particular light can produce varied results across different platforms. RenderWare Graphics therefore supports both reference and platform-specific forms of dynamic lighting. The reference set supports all five light types. The platform-specific models usually support the same light types, but use the light types defined in the underlying hardware to perform the illumination calculations. This means the platform-specific lighting models are unlikely to give the same results across different platforms. The reference set light types are designed to produce very similar results across all supported platforms. On some platforms, they may be wholly or partially implemented using hardware lighting facilities. In other cases, the light types are implemented in software. Platform-specific dynamic lighting is provided mainly to enable access to all the light types available on the platform's hardware. ✎ There are no platform-specific APIs for static lighting. RenderWare Graphics 3.7 I-287 Chapter 14- Lights 14.2.1 Dynamic Lights Representation Objects RenderWare Graphics dynamic lighting models are controlled through two objects: RpLight and RpMaterial. The first object, RpLight, provides control over the light source itself. By linking this to an RwFrame, the light can be positioned within an RpWorld and, if necessary, oriented towards its target. In addition, the RpLight object exposes a number of functions, which allow the developer to modify the light's properties. Effective lighting requires consideration of both the light itself and the materials of the models it is illuminating. The RpMaterial object defines materials that are applied to models and therefore defines how models reflect light. This object is covered in detail in the Dynamic Models chapter, so this chapter will only touch upon the features that directly apply to dynamic lights. Dynamic Lighting Models A dynamic light is created using the RpLightCreate() function. This function takes a constant defining the light types to be used when processing the dynamic light. The table on the following page lists the constants and describes the reference light types. These are always available, regardless of the platform. Platform-specific lighting models Platform-specific light types are documented in the relevant section of the API Reference and usually map directly onto light types implemented in the platform's hardware. ✎ I-288 On the PlayStation 2 platform, all lighting models, including the reference models listed in the table below, are implemented using custom VU code. 11 February 2004 Dynamic Lights Reference Dynamic Light Types NAME LIGHTING TYPES rpLIGHTAMBIENT Ambient light type. This type provides lighting from all directions. The light source is omnipresent. Cannot be positioned or oriented. Directional light type. This model simulates a light source at infinite distance from the world. Cannot be positioned, but can be oriented. Point light type. This type simulates a point source of lighting. The light is emitted from this source in a sphere. Cannot be oriented, but can be positioned. Spot light type. This light type simulate spotlight sources, which emit a cone of light from a specific source in a particular direction, resulting in a spot of light on the target. Can be positioned and oriented. Soft spot light type. As rpLIGHTSPOT. rpLIGHTDIRECTIONAL rpLIGHTPOINT rpLIGHTSPOT rpLIGHTSOFTSPOT The "soft spot" type adds a soft edge so that the light falls off smoothly at the edge of the spot. Can be positioned and oriented. 14.2.2 Creating a dynamic light The following code fragment creates an RpLight object named myLight. It contains a dynamic light using the soft spot light (rpLIGHTSOFTSPOT) reference light type: RpLight *myLight; myLight = RpLightCreate( rpLIGHTSOFTSPOT ); At this point, myLight has been created, but has not yet been initialized. Initialization The initialization necessary for a particular light depends on the light types it is using. For instance, the ambient reference light type (rpLIGHTAMBIENT) needs only a color to be set. RenderWare Graphics 3.7 I-289 Chapter 14- Lights In most cases however, the first step will be to attach a frame object to the RpLight object, so it can be positioned and/or oriented within a world. Of all the reference light types, only the ambient light type can be used without a frame. Position & Orientation Assuming the myFrame frame object contains a valid, initialized RwFrame object, the following code fragment would attach it to the light: RpLightSetFrame( myLight, myFrame ); Attaching a frame to a light allows you to move and orient the light as required. The features of the RwFrame object also mean this light could easily be included in an RwFrame hierarchy along with model geometry. Color The next step is to set the color of the light. The RpLightSetColor() function performs this task. It takes an RwRGBAReal value defining the RGB and Alpha components. Assuming that lightColor has been initialized to the required color, our initialization continues: RpLightSetColor( myLight, &lightColor ); Sphere of illumination Aside from those using the ambient and directional light types, most lights affect models within a finite sphere of illumination. This sphere is defined by the light object's radius, an RwReal value. This can be set thus: RpLightSetRadius( myLight, 5.0f ); This radius defines the distance over which the lighting model acts, with the light falling off over distance according to the formula: intensity = max , 0 ) (radius – distance radius When the distance is zero, the light's intensity is at its highest. The intensity is zero when the distance traveled is equal to the radius. Cone Angle Spotlights also have a cone angle property, which defines the angle of the light cone. A wide angle results in a wide spot of light; a narrow angle gives a smaller spot of light. The cone angle is an RwReal value and may be set as follows: /* 0.785 is equivalent to PI / 4, about 45 degrees */ RpLightSetConeAngle( myLight, 0.785f ); I-290 11 February 2004 Dynamic Lights Adding the light to a world At this stage, the light is ready. All that remains is to add it to an RpWorld object. The fragment below assumes that the world object has been initialized: RpWorldAddLight( myWorld, myLight ); The application is now free to move and orient the light within the world as well as modify its other properties. Dynamic Lights & World Sectors When a dynamic light is added to a world, the RpWorldAddLight() function positions the light within a world sector object. The light's sphere of illumination is used to determine which world sectors the light affects. As such, a light may be referenced by more than one world sector. Light object flags Light objects also include a flags property. Currently, this can be used to inform the rendering engine which geometry types the light will affect: static and/or dynamic. Two flags are defined: rpLIGHTLIGHTATOMICS and rpLIGHTLIGHTWORLD. The former, if enabled, means the light will affect dynamic models. The latter, if enabled, means the light will affect static models. The flags should be logically ORed together if both are needed. The function to set or reset the flags is RpLightSetFlags(). An example of its use appears below. The example sets the light created earlier to illuminate both static and dynamic models: RpLightSetFlags( myLight, rpLIGHTLIGHTATOMICS | rpLIGHTLIGHTWORLD); Dynamic Lights, Geometry & Materials It is possible to modify the behavior of lighting at the RpGeometry level by manipulating the geometry flags. This lets applications enable or disable lighting for individual atomics. The flags are exposed by the RpGeometry object through the RpGeometrySetFlags() function. It is important to understand that these flags are specific to the geometry object, not an atomic. The geometry will always be illuminated according to these flag settings. There are two geometry flags relevant to lighting, as shown in the table below: RenderWare Graphics 3.7 I-291 Chapter 14- Lights FLAG DESCRIPTION rpGEOMETRYLIGHT If set, dynamic lights will illuminate the geometry. If cleared, dynamic lights will not illuminate the geometry. If set, the geometry will reflect illumination appropriately by combining both dynamic and static lighting to render the correct colors. If cleared, the geometry will not be lit at all. Instead, the geometry will be rendered using its material object's own color property alone. rpGEOMETRYMODULATEM ATERIALCOLOR Iterator functions The RpLight object exposes an iterator function, RpLightForAllWorldSectors(), which will call a user-supplied callback function for each world sector the light affects. 14.2.3 Clump Lights & Streaming An RpClump is a container for dynamic objects that are associated with a Frame hierarchy, and this includes dynamic Lights. Lights can be added to Clumps using the RpClumpAddLight() function. • They will be automatically streamed with the Clump and their position within the Frame hierarchy of the Clump preserved. • They will be automatically destroyed with the Clump when RpClumpDestroy() is called. • They will be added to and removed from Worlds with the Clump when the functions RpWorldAddClump() and RpWorldRemoveClump() are used. This mechanism is used whenever dynamic Lights are exported from one of the modeling packages. The artist is able to set up and position Lights within a world. Once exported within a Clump, the positions are stored in the Frame hierarchy. 14.2.4 Platform-Specific Lighting Models Many platforms support hardware acceleration for lighting. However this support is not identical across platforms. Such hardware often provides its own implementation of lighting and this means lights can produce different results on different platforms, even though they are initialized with the same values. I-292 11 February 2004 Dynamic Lights The reference light types provide a means of ensuring consistent lighting across supported platforms, but their performance will vary from platform to platform. RenderWare Graphics therefore exposes any platform-specific lighting models using the same API—only the lighting type constant changes. Platform-specific lighting types are available for Nintendo GameCube, Microsoft DirectX (both Windows and Xbox) and OpenGL. The Sony PlayStation 2 supports the reference lighting models in hardware. The RenderWare Graphics API for PlayStation 2 uses VU code to perform all rendering, so the reference lighting models are all accelerated. RenderWare Graphics 3.7 I-293 Chapter 14- Lights 14.3 Static Lights using RpLight Regardless of whether they are supported in hardware or software, dynamic lights require substantial processing. So, it is wise to avoid using too many dynamic lights. Static lights—also known as prelights—provide a form of lighting that avoids high processing overheads. They are a much simpler, faster, alternative to dynamic lights. The trade-off is that static lights are very limited in their abilities. Static lighting can be applied to: • Static models – i.e. worlds. The data is stored in RpWorldSector objects. • Dynamic models – i.e. atomics, clumps, etc. The data is stored in RpGeometry objects. The first usage is by far the most common as RenderWare Graphics modeling package exporter tools support static lighting features directly. Artists tag model geometry and apply lighting to it. When the model is exported, the RenderWare Graphics exporter encodes vertex lighting data right into the geometry. ✎ The exact tagging mechanism used varies from package to package. See the art tools documentation for full details. At run-time, all that is needed is to load and render the geometry. The static lighting is applied automatically when the relevant RpWorld object is rendered. For dynamic models, there is currently no support for exporting static lighting data directly from the modeling package. Exporters will allocate the necessary space for an array of RwRGBA values, but initialization of these values must be performed explicitly, either in a custom tool, in a modified build of the exporter, or at run-time. Static lighting is decreasing in importance as modern graphics hardware transform and light engines are reducing the need for processing dynamic lighting in the CPU. 14.3.1 Creating Static Lights Static models Static lighting is stored as fixed vertex lighting values. In static models—i.e. RpWorldSector data—these values are completely fixed and not exposed by the RenderWare Graphics API. This is a requirement of the static model rendering optimizations of RenderWare Graphics. I-294 11 February 2004 Static Lights using RpLight Developers building their own tools or creating static models from scratch will find that the RtWorld and RtWorldImport toolkits support creation of static lighting data as well as the model geometry itself. Dynamic models For dynamic models, static lighting is stored within RpGeometry objects. The data is represented by an array of RwRGBA values, which can be retrieved using RpGeometryGetPreLightColors(). The array only exists if the geometry has been created using the rpGEOMETRYPRELIT flag. Space for the prelight array must be explicitly allocated if you are creating geometry objects, as setting the flag will not perform this procedure automatically. The prelighting colors reside within the geometry's topology, at one color per vertex, and are therefore shared between all morph targets. 14.3.2 Static Lighting Techniques Static lights are very fast, using a negligible amount of processing power regardless of how many such lights are used. However, limitations in their design means that they are most often used in tandem with dynamic lights. Some common techniques are covered next, illustrating how the illusion of full lighting can be created without using too many dynamic lights. Interactive static lighting One of the most important limitations of static lighting models is that static lights do not actually cast any light. The process creates the illusion that light is striking the model. Static lighting affects only the vertices of the world sector or geometry objects in which the lighting information resides. As a result, a dynamic model passing through a statically-lit world will not be illuminated by static lighting. If you need to create the effect of static lights casting lights on other models, you will need to use a dynamic light as well. In most cases, the dynamic light can be a temporary creation, used only when the light would be visible to the camera and an object is near enough to it. Modifying static lights on static models There are occasions when static lights need to be disabled or modified in some way at run-time. This is trivial when working with statically-lit dynamic models, but the most common use for static lights is to light static models. The fixed nature of static lights in static models means modification is impossible so the effect must be achieved by using dynamic models for areas where the static lights need to be modifiable. RenderWare Graphics 3.7 I-295 Chapter 14- Lights Static lights in dynamic models Static lighting in geometry objects can be modified at run-time to simulate glowing or pulsating lights and other similar lighting effects. I-296 11 February 2004 Related Examples 14.4 Related Examples Static lights are not demonstrated by any one specific example. However, a model which has been exported from a modeling package with static lighting can be found in the texdict example. The model can be found in models/dungeon.bsp. RenderWare Visualizer can be used to view the model. RenderWare Visualizer showing a model with static lighting The SDK includes two examples covering dynamic lights: lights and lights2. RenderWare Graphics 3.7 I-297 Chapter 14- Lights The lights example illustrates the different light types available for dynamic lights. Use the menu options to choose different types and combinations. The lights example I-298 11 February 2004 Related Examples The lights2 example illustrates how lights interact with world sectors. When run, you will see a small landscape overlaid by wire-frame representations of the world sectors into which it has been divided. The lights2 example Move the dynamic light around the scene to see how RenderWare Graphics links the light to world sectors according to the radius of its sphere of illumination. ✎ The world sectors shown in the lights2 example were created deliberately to show this effect; in normal usage, such a simple landscape would not make use of more than one world sector. RenderWare Graphics 3.7 I-299 Chapter 14- Lights 14.5 Summary 14.5.1 Dynamic Lights Properties table The table below lists the main properties of the reference dynamic lighting models. Additional properties may be added for platform-specific dynamic lighting models. PROPERTY AMB. DIR. 9 9 Color Flags Frame POINT 9 9 9 Radius SPOT 9 9 9 9 ConeAngle 9 9 9 9 9 SOFTSPOT 9 9 9 9 9 Dynamic Lighting: Main Features • I-300 Five reference light types: • rpLIGHTAMBIENT – ambient • rpLIGHTDIRECTIONAL – directional • rpLIGHTPOINT – point-source • rpLIGHTSPOT – spot • rpLIGHTSOFTSPOT – soft-edged spot • Platform-specific light types are provided where necessary for access to hardware lighting. • Ambient lights do not require frames. • Directional, point lights, spot lights and soft spot lights always require frames. • All lights must be added to a world using RpWorldAddLight() if they are to affect the geometry within that world. • All lights can selectively illuminate both static and dynamic geometry. • The default light settings are intended to be "safe" on all supported platforms, but of little use in practice: you should explicitly set all of a dynamic light's properties on creation. 11 February 2004 Summary 14.5.2 Static Lights Static Lights: Main Features • Also known as prelights or prelighting. • A statically-lit model is known as a prelit model. • Cheaper in terms of processing power. • Prelit static models can be readily exported from modeling packages. • Prelit dynamic models must have their prelight data initialized by the developer either in a custom tool, or at run-time. • Prelights are not real lights. They are fixed vertex illumination levels and have no effect on nearby models. • Prelights in static models cannot be changed or modified in any way whatsoever. They are not exposed. • A pointer to the prelight data in dynamic models can be retrieved using RpGeometryGetPreLightColors(). RenderWare Graphics 3.7 I-301 Index Index Index Page numbers in bold face indicate the most important reference to the subject, where multiple references exist. The page numbers shown below refer to Volume I of the User Guide. 2 C 2D graphics toolkit ..........................................................161 C standard data types ........................................................ 40 C++ wrapper classes ......................................................... 17 plugins.......................................................................... 92 camera ....................................................................... 95, 229 anamorphic lens effect................................................ 101 cloning........................................................................ 112 creation of .................................................................. 107 destruction of.............................................................. 110 frame buffer................................................................ 106 orientation .................................................................. 107 orthographic views ....................................................... 99 positioning.................................................................. 107 projection .................................................. See projection raster........................................................................... 106 space........................................................................... 146 sub-rasters ................................................ See sub-rasters telephoto zoom ........................................................... 101 view matrix................................................................. 105 view offset.................................................................. 102 view window ................................................................ 99 viewpoint...................................................................... 98 camera space ....................................... 48, 98, 145, 154, 160 chaining function calls .................................................... 273 character data type............................................................. 39 clipping 2D immediate mode ................................................... 145 immediate mode ......................................................... 154 clipping planes .................................................................. 98 clmpview viewer ....................................................... 19, 256 clump .............................................................................. 252 adding to worlds......................................................... 270 atomic, adding an ....................................................... 266 cloning........................................................................ 270 culling from frustum........................................See culling destroying................................................................... 254 hierarchy of atomics ................................................... 252 iterating over ...................................... 114, 231, 271, 272 procedural generation................................................. 257 rendering directly ....................................................... 277 clumps using........................................................................... 253 CodeWarrior ................................................... See compilers collision detection ........................................................... 232 color .................................................................................. 61 3 3ds max .............................................................................21 A actors ................................................. See dynamic geometry animation.........................................................................274 keyframe animation ....................See keyframe animation morph target................................................................274 of the frame hierarchy.................................................274 of vertices ...................................................................274 ANSI character strings ......................................................39 aspect ratio.......................................................................100 at vector .............................................................................50 atomic ..............................................................................251 animation ....................................................................274 bounding sphere..........................................................270 cloning........................................................................270 culling from frustum....................................... See culling frame................................................................. See frame geometry......................................................See geometry intercepting rendering.................................................273 iterating over...............................................232, 271, 272 rendering directly........................................................277 B bilinear filtering...............................................................134 binary space partition (BSP)....................................229, 230 binary streams.............................................. See serialization bitmap........................................... 117. See raster. See raster blend modes.....................................................................165 blitting ................................................... See raster rendering bounding box.............................................................57, 230 bounds test....................................................................57 enlarging.......................................................................57 build debug ....................................................................18, 217 metrics ..........................................................18, 217, 279 release...................................................................18, 217 I-304 11 February 2004 Index alpha component .......................................................... 61 blending...................................................................... 165 palettes ....................................................................... 119 compilers CodeWarrior................................................................. 19 Microsoft Visual C....................................................... 19 context stack ................................................................... 109 converting model data..................................................... 281 co-ordinate systems........................................................... 45 axes .............................................................................. 46 camera space .........................................See camera space device space ...........................................See device space handedness ................................................................... 45 object space ............................................ See object space scene space..............................................See world space screen space............................................See device space world space .............................................See world space core library, the ................................................................. 22 culling ............................................................................. 113 custom file systems ................................................... 27, 192 D data types fixed point .................................................................... 42 floating point ................................................................ 42 integer .......................................................................... 40 RwBool ........................................................................ 38 RwChar .................................................................. 34, 39 RwFixed ....................................................................... 42 RwIm2DVertex .................................................. 145, 147 RwIm3DVertex .......................................................... 154 RwInt128...................................................................... 41 RwInt16........................................................................ 41 RwInt32........................................................................ 41 RwInt64........................................................................ 41 RwInt8.......................................................................... 41 RwReal......................................................................... 42 RwRGBA ................................................................... 240 RwUInt128................................................................... 41 RwUInt16............................................................... 34, 41 RwUInt32..................................................................... 41 RwUInt64..................................................................... 41 RwUInt8....................................................................... 41 debugging........................................................................ 218 build ........................................................................... 217 messages .................................................................... 219 trace messages ....................................................... 220 streaming............................................................ 218, 219 degenerate triangles......................................................... 269 device space .............................................................. 48, 145 dictionary ........................................................................ 204 schema........................................................................ 211 RenderWare Graphics 3.7 displaying models ............................................................. 19 documentation .................................................................. 20 artists'................................................................... 21, 233 double buffering ............................................................. 109 double precision arithmetic............................................... 42 dynamic geometry .................................................. 250, 267 bounding .................................................................... 264 example...................................................................... 257 platform independent representation.......................... 279 platform specific representation......................... 243, 279 prelighting.................................................................. 268 dynamic lights..........................................................See light dynamic models .................................See dynamic geometry E engine closing.................................................................... 70, 71 initializing ........................................................ 65, 66, 71 opening ............................................................ 65, 67, 71 shut down............................................................... 70, 79 starting ................................................................... 65, 79 stopping ................................................................. 70, 71 terminating................................................................... 70 error handling ................................................................. 216 examples building........................................................................ 19 camera.......................................................................... 96 geometry .................................................................... 257 im2d ........................................................................... 151 im3d ........................................................................... 156 images ........................................................................ 121 lights .................................................................. 297, 299 mipmap ...................................................................... 135 plugin........................................................................... 85 SDK ............................................................................. 19 texadrss .............................................................. 134, 136 world.................................................................. 234, 279 exporters ................................................................... 21, 256 Open Export framework .............................................. 21 writing........................................................................ 234 extensions object ........................................................................... 92 F file format Aldus Tag Image File Format (*.TIF)........................ 121 image handlers registration ............................................................ 121 writing................................................................... 121 Microsoft Windows bitmap (*.BMP)......................... 121 Portable Document Format (*.PDF) ............................ 20 Portable Network Graphics (*.PNG) ................. 121, 125 I-305 Index RenderWare Dive File Format (*.DFF)......................254 RenderWare Stream Format (*.RWS) ........................182 Sun Microsystems Raster Format (*.RAS).................121 Targa (*.TGA) ............................................................121 file I/O function ...............................................................169 fclose ..........................................................................169 feof .............................................................................169 fexist ...........................................................................169 fflush...........................................................................169 fgets ............................................................................169 fopen...........................................................................169 fputs............................................................................169 fread............................................................................169 fseek ...........................................................................169 ftell .............................................................................169 fwrite ..........................................................................169 serialization ................................................................187 file system .........................................................................27 access mode ................................................................199 generic ........................................................................194 initializing...................................................................196 manager ................................................................27, 192 naming ........................................................................195 OS-Specific ................................................................195 overloading...................................................................27 registering...................................................................197 system methods ..........................................................200 toolkit ...................................................................27, 192 files image search paths......................................................122 ISO 9660 convention ..................................................138 fog ...................................................................................102 density ........................................................................103 distance.......................................................................103 enabling ......................................................................103 exponential .................................................................103 fog table......................................................................104 linear...........................................................................103 setting color ................................................................103 frame dirty ............................................................................109 hierarchy.......................................................53, 252, 270 child frame ...............................................................53 parent frame .............................................................53 root frame ................................................................53 siblings.....................................................................54 traversal ...................................................................54 local transformation matrix (LTM).........................52, 54 modeling matrix............................................................52 synchronizing LTMs...................................................109 frame buffer.............................................................100, 129 clearing .......................................................................112 frames ................................................................................52 I-306 freelists.............................................................................. 73 front vector........................................................See at vector frustum ........................................................................ 48, 98 clipping.............................................. See clipping planes culling from.....................................................See culling test sphere................................................................... 113 Fully Managed Support Services (FMSS)......................... 14 website ......................................................................... 14 G gamma correction............................................................ 119 geometry ......................................................................... 251 bounding..................................................................... 264 dynamic lighting flag ................................................. 261 example ...................................................................... 257 flags............................................................................ 261 locking........................................................................ 265 material color modulation flag ................................... 261 mesh ................................................................... 265, 268 morph target .......................................... See morph target normals flag................................................................ 261 offline generation ....................................................... 255 prelighting flag ........................................................... 261 texture co-ordinates .................................................... 267 texturing flag .............................................................. 261 tri-strip flag................................................................. 261 tri-strip method........................................................... 269 unlocking.................................................................... 265 H hardware abstraction ................................................... 22, 29 hooking functions............................................................ 273 I image....................................................................... 117, 119 attaching bitmap to ..................................................... 123 conversion from raster ............................................................. 125 to raster.......................................................... 125, 127 copying....................................................................... 124 creating............................................................... 120, 123 destruction .................................................................. 125 example ...................................................................... 121 file format handlers registration............................................................. 121 writing ................................................................... 121 loading................................................................ 120, 122 mask ................................................................... 123, 125 multiply referencing bitmaps...................................... 124 quantization................................................................ 124 resampling.................................................................. 124 11 February 2004 Index resizing....................................................................... 124 saving ......................................................................... 122 search path.................................................................. 122 size ............................................................................. 124 stride................................................................... 119, 124 immediate mode.............................................................. 144 2D145 2D line lists ................................................................ 149 2D polylines ............................................................... 149 2D primitives.............................................................. 149 2D tri-fans .................................................................. 150 2D trilists.................................................................... 149 2D tri-strips ................................................................ 149 2D vertices ................................................................. 147 3D154 3D example ................................................................ 156 3D indexed primitives ........................................ 154, 157 3D line lists ................................................................ 156 3D pipeline................................................................. 158 3D polylines ............................................................... 156 3D primitives...................................................... 156, 157 3D tri-fans .................................................................. 156 3D tri-lists .................................................................. 156 3D tri-strips ................................................................ 156 3D vertex positioning................................................. 154 3D vertices ................................................................. 154 lighting .................................................................. 155 properties............................................................... 155 3D, applications for.................................................... 158 clipping .............................................................. 145, 154 destruction, 3D ........................................................... 158 im2d example ............................................................. 151 index lists ................................................................... 154 indexed primitives...................................................... 151 platform dependence issues........................................ 148 primitives ................................................................... 154 render states................................................................ 144 rendering a line example ............................................ 152 rendering a triangle example ...................................... 153 rendering cycle ........................................................... 156 rendering primitives ................................................... 157 rendering transformed points...................................... 156 transforming 3D primitives ........................................ 154 vertex lists .................................................................. 154 z-buffer....................................................................... 146 indexed primitives........................................................... 151 infinite loop...................................................... See recursion initialization ...................................................................... 65 attaching plugins .......................................................... 70 file management ........................................................... 66 plugins.......................................................................... 85 subsystem ..................................................................... 67 video mode................................................................... 67 RenderWare Graphics 3.7 changing.................................................................. 71 enumeration............................................................. 68 setting...................................................................... 68 instancing................................................................ 242, 278 intersection ..................................................................... 272 iterating over.............................................................. 272 iterators ................................................................... 113, 271 atomic ........................................................ 232, 271, 272 clump ................................................. 114, 231, 271, 272 frame............................................................................ 55 intersection................................................................. 272 light.................................................................... 231, 232 material .............................................................. 231, 272 mesh................................................................... 232, 272 world.......................................................................... 231 world sector ....................................... 113, 231, 232, 271 K K dimensional (KD) tree...............See binary space partition keyframe animation interpolator................................................................. 204 L language ANSI C ........................................................................ 16 C++ .............................................................................. 16 libraries dynamically linked....................................................... 18 null....................................................................... 18, 282 statically linked ............................................................ 18 library core, the ............................................ See core library, the light color........................................................................... 290 dynamic ............................................. 242, 286, 287, 300 ambient.......................................................... 286, 289 cone angle ............................................................. 290 creating.................................................................. 288 directional ..................................................... 286, 289 initializing ............................................................. 289 point .............................................................. 286, 289 processing time ..................................................... 287 soft spot......................................................... 286, 289 sphere of illumination ........................................... 290 spot................................................................ 286, 289 example...................................................................... 297 geometry dynamic lighting flag ................................. 261 geometry prelit flag.................................................... 261 iterating over...................................................... 231, 232 light types .................................................................. 289 models........................................................................ 286 platform-specific ........................................................ 292 I-307 Index static ...........................................................286, 294, 301 changing.................................................................295 creating ..................................................................294 world adding to ................................................................291 world dynamic lighting flag........................................239 world normals flag......................................................239 world prelit flag ..........................................................239 line.....................................................................................58 link errors ..........................................................................18 M material............................................................................260 geometry material modulation flag.............................261 iterating over.......................................................231, 272 world modulate material flag......................................240 matrix ................................................................................50 post-concatenate ...........................................................55 pre-concatenate.............................................................55 replace ..........................................................................55 transformation...............................................................50 combining ....................................................53, 54, 55 transforming points ..................................................51 transforming vectors ................................................51 Maya..................................................................................21 memory freelists .........................................................................73 management..................................................................72 OS-level ...................................................................72 plugins ..........................................................................83 resource arena.........................................................75, 76 memory management ........................................................80 mesh ........................................................................265, 268 iterating over.......................................................232, 272 tri-strip method ...........................................................269 metrics .............................................................................279 Microsoft Visual C ..........................................See compilers mipmaps ..........................................................................134 automatic generation...................................................127 example ......................................................................135 filtering .......................................................................134 generation ...................................................................137 loading........................................................................137 manual generation.......................................................127 mip levels ...................................................................134 number of levels .........................................................129 writing a mip level generator ......................................138 models creating .........................................................................21 exporting.......................................................................21 morph target ....................................................................262 I-308 N native data ....................................................................... 242 normals............................................................................ 230 geometry normals flag................................................ 261 vertex, calculating ...................................................... 276 vertex, smoothing....................................................... 276 O object space....................................................... 47, 154, 258 objects destroying..................................................................... 36 member functions......................................................... 26 methods ........................................................................ 26 opaque .......................................................................... 27 passing instances to functions ...................................... 27 property access methods............................................... 27 reference counters ........................................................ 36 RenderWare.................................................................. 26 RpAtomic ................................................................... 251 RpClump .................................................................... 252 RpGeometry ....................................................... 251, 291 RpIntersection ............................................................ 272 RpLight .............................................................. 288, 292 RpMaterial ................................................................. 288 RpMorphTarget.......................................................... 262 RpTriangle ................................................................. 258 RpWorld..................................................................... 229 RpWorldSector........................................................... 230 RwBBox..................................................................... 230 RwDebug ................................................................... 218 RwEngine..................................................................... 65 RwError...................................................................... 216 RwFrame .................................................................... 288 RwIm2d...................................................................... 144 RwIm3d...................................................................... 144 RwImage .................................................... 116, 117, 119 RwRaster ............................................................ 116, 117 RwResources................................................................ 77 RwSurfaceProperty .................................................... 261 RwTexDictionary....................................... 116, 117, 138 RwTexture.................................................. 116, 117, 132 RwVideoMode ............................................................. 68 transparent.................................................................... 27 optimization .................................................................... 276 P palettes ............................................................................ 119 parallax scrolling............................................................... 99 PI data ..................................................................... 242, 279 platform Apple Macintosh .......................................................... 15 11 February 2004 Index Direct3D 8.................................................................... 15 Microsoft Windows...................................................... 15 Microsoft Xbox ............................................................ 15 NINTENDO GAMECUBE.......................................... 15 OpenGL........................................................................ 15 Sony PlayStation 2 ....................................................... 15 platform independent texture dictionaries ..................................................... 140 plugins............................................................................... 23 attaching........................................................... 70, 83, 85 memory ................................................................... 83 creating......................................................................... 85 defining ........................................................................ 85 dependencies ................................................................ 84 example ........................................................................ 85 exposed ........................................................................ 85 initialization ................................................................. 85 registering .................................................................... 87 RpADC ........................................................................ 23 RpAnisot ...................................................................... 23 RpCollision .......................................................... 23, 232 RpDMorph ................................................................... 23 RpHAnim..................................................................... 23 RpLODAtomic............................................................. 23 RpLtMap ...................................................................... 23 RpMaterialEffects ........................................................ 23 RpMipmapKL .............................................................. 23 RpMorph ...................................................................... 23 RpPatch ........................................................................ 23 RpPrtStd....................................................................... 23 RpPTank ...................................................................... 23 RpPVS.......................................................................... 23 RpRandom ................................................................... 23 RpSkin.................................................................. 23, 275 RpSpline....................................................................... 23 RpUserData.................................................................. 23 RpUVAnim .................................................................. 23 RpWorld....................................................... 23, 228, 251 shut down ..................................................................... 85 supplied ........................................................................ 23 using............................................................................. 83 porting............................................................................... 16 pos vector.......................................................................... 50 PowerPipe ......................................................................... 25 pre-instancing.......................................................... 243, 279 atomics ....................................................................... 279 worlds......................................................................... 243 pre-lighting...................................................................... 240 static geometry ........................................................... 241 using RtWorldImport ................................................. 241 projection parallel............................................................ 48, 99, 160 perspective ............................................. 48, 99, 146, 160 RenderWare Graphics 3.7 shadows ....................................................................... 99 PS data............................................................................ 242 R raster ....................................................................... 117, 126 camera................................................... See camera raster clearing ...................................................................... 131 context stack ...................................................... 109, 129 conversion from image ............................................................ 125 from images .......................................................... 127 to image................................................................. 125 creating ...................................................................... 126 determining valid formats .......................................... 127 format......................................................................... 129 loading ....................................................................... 131 lock modes ................................................................. 131 locking ....................................................................... 131 locking palettized....................................................... 131 mipmaps..................................................................... 127 number of Mipmap levels .......................................... 129 platform dependence.................................................. 126 rendering.................................................................... 130 sub-rasters .................................................See sub-rasters unlocking ................................................................... 131 unlocking palettized................................................... 131 reciprocal camera Z ........................................................ 148 rectangle ........................................................................... 59 recursion ..................................................... See infinite loop registering custom file systems .................................................... 193 extensions .................................................................... 88 plugins ......................................................................... 87 render callback........................................................ 273, 277 render state.............................................................. 144, 162 exhaustive list ............................................................ 162 getting ........................................................................ 162 rwRENDERSTATEBORDERCOLOR ..................... 164 rwRENDERSTATEDESTBLEND.................... 164, 165 rwRENDERSTATEFOGCOLOR.............................. 164 rwRENDERSTATEFOGDENSITY .......................... 165 rwRENDERSTATEFOGENABLE ........................... 164 rwRENDERSTATEFOGTYPE ................................. 164 rwRENDERSTATESHADEMODE .......................... 163 rwRENDERSTATESRCBLEND ...................... 164, 165 rwRENDERSTATETEXTUREADDRESS............... 163 rwRENDERSTATETEXTUREADDRESSU ............ 163 rwRENDERSTATETEXTUREADDRESSV ............ 163 rwRENDERSTATETEXTUREFILTER ................... 164 rwRENDERSTATETEXTUREPERSPECTIVE ....... 163 rwRENDERSTATETEXTURERASTER.................. 163 rwRENDERSTATEVERTEXALPHAENABLE....... 164 I-309 Index rwRENDERSTATEZTESTENABLE ........................163 rwRENDERSTATEZWRITEENABLE .....................163 setting .........................................................................162 render states.....................................................................157 fog...............................................................................103 using ...........................................................................104 rendering a step by step guide.......................................................28 atomics directly ..........................................................277 begin an update...................................................109, 277 clumps directly ...........................................................277 double buffering .........................................................129 end an update......................................................109, 277 immediate mode .........................................................109 intercepting for atomics ..............................................273 rasters .............................................See rasters, rendering static geometry............................................................242 to multiple viewports ................................ See sub-rasters worlds .........................................................................277 RenderWare components.............................................................22–27 RenderWare AI..................................................................14 RenderWare Audio............................................................14 RenderWare Graphics .......................................................14 RenderWare Physics..........................................................14 RenderWare Platform........................................................14 resource arena................................75, 76, 80, 243, 278, 279 right vector ..................................................................46, 50 RtAnim............................................See keyframe animation RtTOC .................................................. See table of contents RtWorldImport, using......................................................234 RwBBox ............................................................................57 RwCamera .........................................................................97 RwEngineClose .....................................................70, 71, 79 RwEngineInit ..................................................65, 66, 71, 79 RwEngineOpen ...............................................65, 67, 71, 79 RwEngineStart.............................................................65, 79 RwEngineStop.......................................................70, 71, 79 RwEngineTerm ...........................................................70, 79 RwLine ..............................................................................58 RwRect ..............................................................................59 RwRGBA ..........................................................................61 rws (RenderWare stream file format) ..............................182 RwSphere ..........................................................................60 RwVideoMode ..................................................................68 S saving memory ........................................................243, 279 scaleable fonts .................................................................161 scene creation ....................................................................28 scene space .................................................. See world space scenes ............................ See static geometry or world sector I-310 screen dump .................................................................... 131 screen space ................................................See device space SDK examples............................................See examples, SDK serialization ..................................................................... 168 atomics ............................................................... 173, 179 binary streams ............................................................ 171 chunk ID................................................................ 171 BSP ............................................................................ 171 chunk headers..................................................... 171, 181 chunk IDs ................................................................... 187 chunk size................................................................... 174 chunk type .................................................................. 172 clumps ........................................................ 173, 179, 180 DFF ............................................................................ 171 endian-ness......................................................... 177, 188 big-endian.............................................................. 175 little-endian............................................................ 175 file functions............................................................... 169 file I/O function.......................................... 168, 169, 187 fclose ..................................................................... 169 feof ........................................................................ 169 fexist ...................................................................... 169 fflush ..................................................................... 169 fgets ....................................................................... 169 fopen...................................................................... 169 fputs....................................................................... 169 fread....................................................................... 169 fseek ...................................................................... 169 ftell ........................................................................ 169 fwrite ..................................................................... 169 file interface ............................................................... 169 frames................................................................. 173, 179 geometry..................................................................... 173 reading worlds............................................................ 247 rws...................................................................... 182, 188 streaming.................................................... 174, 180, 187 reading................................................... 175, 176, 177 registering.............................................................. 188 types .............................................................. 186, 187 writing ................................................... 175, 176, 178 strview viewer ............................................................ 173 writing worlds ............................................................ 246 shut down plugins.......................................................................... 85 RenderWare Graphics .................................................. 70 skeleton ............................................................................. 29 skinning........................................................................... 275 SN Systems Visual Studio Integration .............................. 19 sorting by material.................................................................. 273 customizing ........................................................... 273 sorting alpha primitives................................................... 166 11 February 2004 Index source code skeleton ........................................................................ 29 source code license............................................................ 16 sphere................................................................................ 60 split screen .....................................................See sub-rasters static geometry ................................................................ 228 platform independent representation .................. 242, 243 pre-lighting................................................................. 241 rendering .................................................................... 242 sectors .................................................... See world sector tools............................................................................ 233 viewing....................................................................... 233 static lighting........................................................... See light static models ...........................................See static geometry streaming..................................................... See serialization string data type.................................................................. 39 strview viewer........................................................... 19, 173 sub-rasters ............................................................... 111, 129 subsystem enumeration.................................................................. 67 initialization ................................................................. 67 surface properties .................................................... 261, 268 T table of contents .............................................................. 182 creating....................................................................... 184 streaming.................................................................... 184 texture ............................................................. 118, 132, 259 addressing example ............................................ 134, 136 addressing modes ............................................... 132, 135 addressing U axis independently ................................ 136 addressing V axis independently ................................ 136 bordering .................................................................... 136 clamping..................................................................... 136 filtering............................................................... 132, 134 geometry textured flag ............................................... 261 geometry, storage of co-ordinates in .......................... 267 immediate mode ......................................................... 148 loading................................................................ 136, 141 mipmap ...................................................................... 137 mirroring ............................................................ 134, 136 saving ......................................................................... 141 streaming.................................................................... 141 stretching.................................................................... 133 tiling ........................................................................... 133 world texturing flag.................................................... 239 wrapping .................................................................... 136 texture co-ordinates......................................................... 132 texture dictionary .................................................... 138, 139 adding textures to ....................................................... 140 current ........................................................................ 139 finding textures .......................................................... 140 RenderWare Graphics 3.7 platform independent ................................................. 140 streaming ................................................................... 139 TOC ......................................................See table of contents toolkits .............................................................................. 24 Rt2d ..................................................................... 24, 145 Rt2D .......................................................................... 161 Rt2dAnim .................................................................... 24 RtAnim ................................................................ 24, 204 RtBary.......................................................................... 24 RtBezPat ...................................................................... 24 RtBMP ................................................................. 24, 120 RtCharset ..................................................................... 24 RtCmpKey ................................................................... 24 RtDict........................................................................... 24 RtFSyst ........................................................................ 24 RtGCond...................................................................... 24 RtIntersection............................................................... 24 RtLtMap....................................................................... 24 RtMipK........................................................................ 24 RtPick .......................................................................... 24 RtPITexD................................................................... 140 RtPNG ................................................................. 24, 120 RtQuat.......................................................................... 24 RtRAS.................................................................. 24, 120 RtRay........................................................................... 24 RtSkinSplit................................................................... 24 RtSlerp ......................................................................... 24 RtSplinePVS ................................................................ 24 RtTIFF ................................................................. 24, 120 RtTile ........................................................................... 24 RtTOC ................................................................. 24, 182 RtVCAT....................................................................... 24 RtWing......................................................................... 24 RtWorld ............................................................... 24, 276 RtWorldImport ............................................ 25, 229, 234 supplied........................................................................ 24 tools artists'........................................................................... 21 skeleton, the ................................................................. 26 topology.................................................................. 262, 269 triangles .......................................................................... 258 winding order............................................................. 263 trilinear filtering.............................................................. 134 tri-strip method ....................................................................... 269 world tri-strip flag...................................................... 240 U Unicode character strings.................................................. 39 up vector ..................................................................... 46, 50 UV co-ordinates.............................................................. 132 immediate mode......................................................... 148 I-311 Index V vectors ...............................................................................43 2D operations................................................................43 3D operations................................................................44 at See at vector pos .............................................................See pos vector right ......................................................... See right vector three dimensional..........................................................44 two dimensional............................................................43 up See up vector vertical blank interrupt (VBI) ..........................................130 vertices ............................................................................258 video mode changing .......................................................................71 enumeration ..................................................................68 flags ..............................................................................68 initialization..................................................................67 setting ...........................................................................68 viewers clmpview ..............................................................19, 256 strview ..................................................................19, 173 visualizer ......................................................................19 Visualizer....................................................................256 wrldview.......................................................................19 wrldview.....................................................................256 Visual Studio Integration...................................................19 visualizer ...........................................................................19 visualizer viewer..............................................................256 vsync pulse ................................. See vertical blank interrupt W winding order ..................................................................263 world ...............................................................................229 adding I-312 atomics .................................................................. 229 cameras.................................................................. 229 lights...................................................................... 229 adding clumps ............................................................ 270 creating....................................................................... 234 creating empty............................................................ 239 destroying................................................................... 248 dynamic lighting......................................................... 239 example ...................................................................... 234 flags............................................................................ 239 importing data ............................................................ 234 loading........................................................................ 247 modulating material color .......................................... 240 normals....................................................................... 239 prelit ........................................................................... 239 properties.................................................................... 239 rendering ............................................................ 242, 277 saving ......................................................................... 246 serialization ................................................................ 245 texturing ..................................................................... 239 tri-stripping................................................................. 240 world sector..................................................................... 230 culling from frustum........................................See culling iterating over .............................................. 113, 231, 271 modeling..................................................................... 233 world space ............................................................... 48, 154 placing in using frames................................................. 48 wrldview viewer.............................................................. 256 wrldview viewer................................................................ 19 Z z sorting........................................................................... 166 z-buffer.................................................................... 106, 160 immediate mode ......................................................... 146 resolution...................................................................... 98 11 February 2004
Source Exif Data:
File Type : PDF File Type Extension : pdf MIME Type : application/pdf PDF Version : 1.3 Linearized : Yes Producer : Acrobat Distiller 4.05 for Windows Creator : Microsoft Word 9.0 Modify Date : 2004:02:11 08:34:59Z Author : Catherine Hislam Title : . Create Date : 2004:02:11 08:34:22 Page Count : 312 Page Mode : UseOutlinesEXIF Metadata provided by EXIF.tools