Version 1.5.9 — 28-Apr-2009
- Bone nodes in a model are now identified by a hash value derived from the bone's name instead of an index number based on the bone's position within the model. What this means is that any skinned mesh can be copied from one skeleton and pasted onto another skeleton as long as the bones that it needs exist in the new skeleton. There is no longer any requirement that the two skeletons have the same number of bones or that they occur in the same order within the skeletal hierarchy.
- Normal maps can now be compressed using ordinary S3TC when the alpha channel is unused (which disqualifies parallax maps). Compressed normal maps only contain information in the green and alpha channels of the texture after they've been imported. These provide an 8-bit x component and a 6-bit y component for each normal vector, and the z component is reconstituted in a slightly more expensive fragment program.
- A new
ShockwaveEffectclass has been added to the engine, and it produces an expanding distortion ring in the scene. This effect is implemented in the Extras plugin module, and theShellEffectclass has also been moved to the Extras plugin. - The Expand process has been added to the Shader Editor. It multiplies the input by 2.0 and then subtracts 1.0. This is useful for expanding values from the [0,1] range to the [−1,1] range. (Note that the Normal Map process already implicitly expands the values read from its texture, so it's not necessary to use an Expand process after a normal map is read.)
- A new Set External Variable method has been added to the Basic tab in the Script Editor. This method can set the value of an object-scope variable in another script to the value of any local variable belonging to the script that is running.
- The
kControllerLocalflag can now be specified by a controller to indicate that it operates autonomously and does not need to receive messages from remote machines. This flag would ordinarily be set in the controller'sPreprocess()function before calling the base class'sPreprocess()function, and it prevents the controller from being added to the world's controller array or being assigned a controller index. - With this release, PowerPC-based Mac support has been discontinued.
Version 1.5.8 — 4-Apr-2009
- The Models page in the World Editor now contains a tool for placing generic unregistered models. After a generic model has been placed in the scene, the model resource is specified under the Model tab in the Node Info window. When multiple instances of the same generic model exist in the scene, they share the same object data. However, if a registered model is placed in the scene, and the same model resource is specified for a generic model as well, then they do not share the same object data. That is, copies of registered models all share each other's data, and copies of generic models all share each other's data, but there's no sharing between registered and generic models. Therefore, you should be consistent in what method you use to place a particular model in the scene. If a model is registered with the engine (and thus appears in the list of registered models), it is always better to use the registered model than to use a generic model.
- The Terrain page now contains a smoothing brush. When this brush is used to draw on terrain, it applies a simple 3D blur filter to the underlying voxel field.
- The World Editor now adds a new command to the global Tools menu called "Reopen Played World", with the shortcut Ctrl-Shift-P. This menu item unloads the currently playing world and reopens the World Editor with the last world that was played by typing Ctrl-P.
- The range of speeds possible for the free camera in the World Editor has been increased on both the slow and fast ends.
- The skinning code has been modified in this release to allow normals and tangents to be skinned instead of calculated separately. New performance optimizations have also been implemented for skinned models. To use these new capabilities, an existing model must be either be re-imported or have the Recalculate Normals command applied to its geometries in the World Editor.
- Fluid and cloth simulation now run as multi-threaded tasks through the Job Manager.
- A new "Shader Time" process has been added to the Shader Editor. It outputs the engine's internal shader timer, which has a period of 120 seconds. The time output in the shader is normalized to the range [0,1).
- A perspective exclusion mask can now be specified for portals. This allows you to disable portals from specific camera perspectives, such as when rendering to the refraction buffer.
Version 1.5.5 — 21-Mar-2009
- The skin controller now performs skinning updates as a Job Manager task. The allows multiple models to be skinned in parallel on multi-core CPUs.
- Depth lights no longer have a constant shadow map boundary. Instead, the boundary is calculated dynamically based on the bounding
volumes in the scene being illuminated. The default method for calculating the boundary is conservative, so an optimally-sized box
usually won't be calculated automatically. However, you can draw a shadow space volume (in the Spaces page) and connect the light's
SHADconnector to it in order to force the light to assume a particular bounding box for the volume it illuminates. The whole point of this is that a depth light's position is no longer relevant for shadow mapping. Only the direction in which the light faces matters. Several visual improvements have been made in the World Editor:
- All types of nodes are now rendered in the perspective viewport (zones and groups being the only ones that weren't before).
- The volumes for triggers, emitters, spaces, physics shapes, and effects now display text on their surfaces describing the type of object for easier identification.
- Lights, sources, and cameras now display a volume similar to the other volumetric nodes, but only when selected.
- Infinite lights are now rendered with a big arrow showing the direction of illumination.
- Portals now show arrows indicating the direction in which they flow.
- Markers, models, lights, sources, cameras, and particle systems are now displayed as crosshairs with an icon attached off-center. Previously, the cubic icon would block out the background making alignment difficult.
- Groups are now rendered as loose bounding boxes.
- The gizmo in the World Editor now displays three new handles, colored red, green, and blue, when the rotation tool is selected. These handles can be used to rotate a node about its local axes, where red, green, and blue correspond to x, y, and z.
- Selection locking has been added to the World Editor. While the selection is locked, a tiny lock icon appears next to the cursor to indicate that the selection can't be changed.
- A new standard script method called "Get String Length" has been added to retrieve the length of a string. Ordinarily, a script variable would be fed into the method's "Input string" setting. The method outputs an integer.
- The post-processing pipeline can now accept a full color matrix to be applied to the final scene, enabling a wider range of special effects. The color matrix is set using the World::SetFinalColorTransform() function.
Version 1.5.2 — 13-Feb-2009
- This release contains a few workarounds for driver bugs on ATI hardware and on the Mac.
- Antialiasing is now enabled on ATI hardware because it works correctly in their latest drivers.
- The method by which normal vectors for terrain geometries are calculated has been changed again. Existing terrains can be updated by selecting all of the geometries in a block and choosing Rebuild Primitive from the Geometry menu in the World Editor.
- A new setting has been added to the Graphics Options dialog called "Use high-detail terrain textures". If this box is unchecked, then terrain palettes having entries of size 1024×1024 or larger are reduced in resolution to one-half size. This box is unchecked by default on the Mac due to some driver issues with 4096×4096 textures.
- The S3TC compression algorithm has been improved a little bit in this release. Some textures will now compress with higher quality.
- The Collada Importer tool now imports camera nodes. Only perspective cameras are supported.
- Texture array functionality is disabled on ATI hardware in this release, and this will continue to be the case until ATI supplies correctly working drivers. This only affects terrain texture palettes that were imported in version 1.5.1.
Version 1.5.1 — 8-Feb-2009
- The method by which normal vectors for terrain geometries are calculated has been changed. Existing terrains can be updated by selecting all of the geometries in a block and choosing Rebuild Primitive from the Geometry menu in the World Editor. The shading on the terrain will change slightly when this is done because the normals are smoother in regions containing clusters of vertices.
- The shader code for terrain texturing has been enhanced for hardware supporting array textures (currently G80 and later). When texture array functionality is available, terrain now renders faster and at higher quality while also using less memory for the palette of terrain textures. Existing terrain palette textures must be reimported before it's possible to take advantage of the new enhancements.
- A new manager has been added to the engine: the Job Manager. The Job Manager is designed to distribute work over the available processor cores so that the engine can utilize the full potential of multi-core CPUs. Work is submitted in the form of "jobs" representing a single task of some kind. Jobs will be used for both short tasks that take place every frame and longer tasks that run in the background. Various parts of the engine will start using the Job Manager over the next few releases.
- The Collada Importer will now recognize two sets of texture coordinates and import them. If there are two sets, then they are accessible as Texcoord 1 and Texcoord 2 in the Material Manager and the Shader Editor.
- The Round process has been added to the Shader Editor. It simply rounds numbers to the nearest integer. On hardware that does not explicitly support a round instruction, the round operation is replaced by an addition of 0.5 followed by the floor operation.
- New functions have been added to the
Playerclass that let you get and set the volume for the voice chat associated with each player. - The log file format has been upgraded. It now shows more information about the current system on which the engine is running, and more information is given when errors occur.
Version 1.5 — 27-Dec-2008
- A new voxel terrain system has been added to the engine, along with several terrain editing tools in the World Editor. More information about these can be found in the wiki article. Support for the old terrain geometry has been removed from the engine, so any old terrain in existing worlds will disappear when opened in the new version of the engine. To preserve the old terrain, select it in the editor under a previous version and convert it to a generic mesh before opening it in the current version of the engine.
- All of the shading systems in the engine have been completely replaced by a new architecture based on shader graphs. Every existing attribute-based material will continue to work just fine, but they are translated into shader graphs internally. The Material Manager still allows materials to be created by configuring a fixed set of material attributes, and this is still the preferred method of creating materials that only use the standard options. Arbitrary custom materials can now be created in the new Shader Editor that's accessible from the Material Manager window. More information about the Shader Editor can be found in its wiki article.
- Both the new Shader Editor and the existing Script Editor have a new tool for creating sections in a graph. A section is simply a rectangular area drawn beneath the graph that can be used to group a set of nodes for organizational purposes—it has absolutely no effect on the function of the graph itself. Each section has a user-configurable title and background color that can be changed by double-clicking on the title bar or by selecting the section and choosing Get Info from the menu (or hitting Ctrl-I).
- Three new script methods have been added that can be used to set scalar, vector, and color parameter values in shader-based materials. These methods allow you to specify a parameter slot number and a new parameter value. When executed, the methods search all of the materials on the target geometry node for Constant Scalar, Constant Vector, and Constant Color processes that use the parameter slot and change the input value for those processes to the new value specified in the script.
- A new tool has been added to the Material page in the World Editor that works like the eyedropper in a painting program. When this tool is clicked on a geometry surface in a scene, the current material is set to the material used on that surface.
- For transition zones having exactly two outgoing direct portals, the ambient light color is now dynamically calculated. The light color is simply a smooth gradient in between the two portals, blending from one zone's ambient light color to the other's. If either zone's ambient light color changes, then the gradient is automatically updated.
- The collision system has been improved in this release. To gain the full benefits of these improvements, it is necessary to rebuild the collision data for geometry nodes in the World Editor. This can be done by selecting all of the geometry nodes, hitting Ctrl-I to open the Node Info window, moving to the Collision tab, and then just clicking OK.
- The engine now recognizes the operating system clipboard under Windows and Mac OS X, so it's possible to copy and paste text between other applications and text boxes inside C4.
- The project files now have a new build target called Server. When this target is selected, the engine builds without any graphics, sound, or input systems so that it can be run on minimal hardware and used as a dedicated server.
- The
kWindowMaximizeflag can now be passed to theWindowconstructor to make it as large as possible upon creation. - If an attempt is made to read strings from a non-existent string table resource, the engine now returns the "<missing>" string in the same way that it already does for missing strings in an existing resource.
- The Time Manager has been modified so that it correctly handles frame rates greater than 1000 fps.
- The quad effect now has a setting for the blend mode that it's rendered with.
- The Panel Controller script functions for getting and setting panel item text now work on editable text items as well as static text items.
- New standard Panel Controller script functions have been added to get and set the texture map shown in an image item.
- The script expression parser now recognizes the words "true" and "false" as boolean literals. These are now treated as keywords and cannot be used as variable names.
- Hexadecimal integer literals using the
0xsyntax are now recognized by the script expression parser. - The box select tool in the World Editor has been reimplemented and is now very precise.
- In the World Editor, double-clicking on a node in the scene graph now opens the Node Info window.
- When importing a geometry node with the Collada Importer, if the transform contains any kind of scale, then the 3×3 portion of the transform (containing the scale and rotation) is now baked into the vertices.
- A voice chat channel can now be enabled and disabled so that it's possible to switch among chat configurations without having to create and/or delete channels.
- A new type of event handler, the
WindowEventHandler, can now be installed in the Interface Manager to receive events pertaining to GUI windows. The types of events posted are (a) a window was added/removed from the GUI, (b) a window's enable or hidden state has changed, and (c) the mouse has moved into or out of a window's content area. - The Input Manager has been modified so that it is possible to receive raw input from only specific classes of devices
while still receiving ordinary OS events for mouse and/or keyboard devices. The
kInputNormalmode that could previously be passed to theInputMgr::SetInputMode()function has been replaced by the three valueskInputMouseActive,kInputKeyboardActive, andkInputGameActive. The "Game" classification includes all devices that are not mice or keyboards. These values can be passed in any combination (through logical OR) to theInputMgr::SetInputMode()function to set the input mode for those classes of device. If eitherkInputMouseActiveorkInputKeyboardActiveis not specified, then you continue to receive OS events for those classes of device. ThekInputAllActivevalue is provided to enable raw input for all devices, equivalent to the old value ofkInputNormal. - The
SetAudioCaptureProc()function has been added to the Audio Capture Manager. This function lets you install a callback procedure that is periodically invoked when new audio data has been captured on the local machine, and it provides a way for the application to intercept the raw sample data. - The configuration file
Engine/engine.cfghas been renamed toEngine/input.cfgsince it only includes commands for binding input controls. - In debug mode, the values used to fill newly allocated memory and just-deallocated memory have been changed
to
0x7FCCCCCCand0x7FDDDDDD, respectively. This was done so that any float-point values read from uninitialized memory would be interpreted as NANs. In the case that a memory block is not a multiple of four bytes in size,0xCCand0xDDare used to fill in the remainder bytes. - In debug mode under Windows, the engine will now display an error message at startup if the working directory does
not point to the location containing the
Datadirectory. - The per-vertex fog option has been removed from the engine. Fog calculations are now always performed at the fragment level.
- The separate specular color option has been removed from light objects.
- The microfacet rendering variable
$renderMicrofacetShadinghas been removed from the engine. Microfacet rendering can no longer be turned off through a flag.
Version 1.4.10 — 25-Jul-2008
- A new cross-platform voice chat system has been added to the engine as the Audio Capture Manager. In a multiplayer game, audio can be captured on each player's machine, compressed using a variable bit-rate algorithm, and distributed through the server to the other players in the game. In the demo game, there are options for enabling or disabling sending and receiving of voice chat, and there's a volume control for received voice chat.
- Each
Playerobject that corresponds to a player in a game is now part of a graph that represents the voice communication channels among all of the players. Voice chat is only sent from player A to player B if there exists a channel starting at player A and ending at player B. A channel is an edge in the player graph encapsulated by theChannelclass. The demo game automatically establishes channels among all players who have enabled voice chat receipt, but more complex arrangements such as team chat can be set up. - It is now possible for a remote portal to span multiple zones so that a single large portal can be used in several zones in cases when a reflective or refractive surface is bigger than a single room. To use this functionality, just add a connector to each zone (other than the portal's owning zone) and link it to the remote portal.
- The S3TC texture compression algorithm built into the engine has been significantly improved in this release, both in terms of image quality and speed.
- Due to some serious limitations in Mac OS 10.4 (Tiger), we will only be supporting Mac OS 10.5 (Leopard) beginning with this release. The Mac project files now require Xcode 3. It's still possible to build the engine under earlier versions of Mac OS X, but it will require making your own project files for Xcode 2 and working around the dynamic loader limitations (for which one solution is to hard-code an absolute installation path for the C4.app bundle).
Build 149 — 8-Jul-2008
- The graphical scripting system in the engine has been replaced with a far more powerful design that supports variables, loops, and conditional execution. All previously existing scripts will continue to run without modification. Details about the new scripting system are too extensive to include here, but they can be found in its wiki article.
- The
Function::Execute()function now takes a pointer to the method that is calling it. This allows the function to set the method's boolean result value in the new scripting system. -
The engine's texture format has been changed in this release. The file extension is still
.tex, and the engine can still read the old format. However, in the next release, the old format will no longer be supported. We have included a conversion utility in this release that will scan yourDatafolder and convert all.texfiles to the new format automatically. All textures that ship with the engine have already been converted.To use the conversion utility, run the engine and type
convtexin the command console. This will convert all.texfiles in yourDatafolder to the new format in place. Be sure that you have a backup copy of your custom textures before running this utility. - The Texture Viewer tool has been renamed to Texture Tool, and all the code that creates textures of any kind
has been moved to this plugin. Generated textures (light projections, shadow maps, environment maps, and
ambient spaces) are now made using the
gentexconsole command. - The ambient space feature has been replaced with a new rendering method for static volumetric ambient occlusion. Ambient spaces are still placed in zones as they were previously, but now they only encode directional occlusion that modulates the ambient light intensity as opposed to encoding the ambient light intensity itself. More ambient lighting capabilities will be added to near-term future releases.
- The
SceneImportPluginclass has been changed slightly so that it's possible for an import plugin to display a dialog before importing a scene. (See the Collada import plugin for an example.) TheSceneImportPlugin::ImportGeometry()function now takes a pointer to the editor window as a parameter, and the importer must call theEditor::ImportScene()function in order to complete the import. - The Collada importer now offers the option to attempt to import texture maps while it is importing a scene.
When this option is turned on, any qualified diffuse map, normal map, gloss map, or emission map specified in a
Collada file will be imported with the Texture Tool using the default settings. A texture map qualifies for
import if its path name contains
/Import/so that the importer recognizes it as being in the C4Importfolder. If the Collada file specifies the wrap modes for a texture map, then they are respected when a texture map is automatically imported. - A Cleanup button has been added to the Material Manager. Clicking this button causes all duplicate materials to be merged into one material. Materials are considered equivalent if they produce the same shaders.
- The
Entityclass has been renamed to theModelclass. To update your code, make the case-sensitive global replacements ofEntitytoModelandentitytomodel. This will have the effect of inadvertently changing the word "identity" as well, so you'll need to also make the replacement ofdmodeltodentityto clean it up. - A new toggle button has been added to the World Editor that turns display of models on and off. Models are no longer displayed as a bounding box.
- A model registration now takes one more parameter that specifies the human-readable model name to be displayed in the World Editor.
- A new multi-zone referencing system has been implemented that generalizes some older techniques used in the engine for transition zones and effects that span multiple zones. Most of this system is internal to the engine and not exposed to higher-level code, but there's one new addition that game programmers need to be aware of. Model nodes have always automatically reparented themselves to the zones that contain them as they move around, but now when a model exits a zone, it also attaches a special reference to the zone that survives until the model's bounding volume has completely left the zone. This allows large models to span multiple zones and to be correctly identified by the visibility determination system. The whole thing is automated, so no code needs to be written to take advantage of this feature.
- The
kEntityAttachedflag, previously used to signify that a model is attached to another model in some way, has been removed from the engine. TheModelclass now determines whether models are attached to other models automatically. - Under Windows, the Sound Manager now uses XAudio2 instead of DirectSound. This should be completely transparent to all higher-level code, but you will need to upgrade to the latest version of DirectX. The engine will only compile with the June 2008 DirectX SDK or later.
- The streaming capabilities in the Sound Manager have been generalized so that it's possible to stream sound data from any kind of source. The method for setting up a streaming wave file has changed—see the wiki article for more information.
- A color scale and bias operation has been added to the post-processing pass. The
World::SetFinalColorTransform()function can be used to specify a scale color S and a bias color B that are applied to the final rendered color C to yield SC + B. The red, green, and blue channels of these colors can be any floating-point values that produce the desired effect. The scale and bias colors only affect rendering of the current world and not the graphical user interface. - The
WorldRenderTask()andInterfaceRenderTask()functions have been added to theApplicationclass. These functions are called once per frame after the world has been rendered and after the graphical user interface has been rendered, respectively. - The Display Manager will now allow any window size to be specified by the
$displayWidthand$displayHeightvariables when running in windowed mode. - The
Nodeclass is now subclassed fromConstructableso that custom node types can be defined and properly deserialized. TheConstructable::InstallConstructor()function is used to install a callback function that constructs custom node subclasses. - Full native support for Xbox 360 controllers under Windows has been added to the Input Manager (using XInput). The demo game code has been updated so that it's possible to play using only the Xbox controller. Better support for DirectInput joysticks has also been added to the Input Manager.
- The movies plugin now allows movies to be played as streams from remote locations. The movie controller and movie panel item now both have check boxes indicating whether the movie name is a URL.
- Movie play position is now synchronized in multiplayer games when new players join.
Build 148 — 13-Mar-2008
- Glow and bloom effects have been added to the post-processing phase of the rendering system. No distinction is made between glow and bloom during post-processing, but the two effects are created by different parts of the shading equations. Glow comes from the emission component's alpha channel, and bloom is determined by the intensity of the specular component. Glow and bloom are enabled on a per-material basis, and each has a checkbox in the Material Manager. (Glow is found under the Ambient tab, and bloom is found under the Specular tab.) Glow and bloom can be enabled or disabled globally in the Graphics Settings dialog.
- A new generic animation controller has been added to the engine. This controller can be attached to an entity node, and it simply plays an animation resource for that entity. The animation controller also exposes play and stop functions that can be called from a script to change animations or stop the current animation.
-
The Material Manager in the World Editor has been largely redesigned. It now always displays every material that is used by a world, and all previews are rendered in real-time. The various material attribute settings have been reorganized into four panes: Diffuse, Specular, Ambient, and Texcoords. The first three panes group attributes by where they appear in the lighting equations, and the Texcoords pane contains everything related to texture coordinate transforms and animation.
The New button now creates an empty material, and a Duplicate button has been added that creates a copy of the currently selected material. A Delete button has been added that removes a material from a world, but only if it is not used by anything. The Import and Export buttons still exist and function as before.
- The World Editor now directly supports plugin modules. The external API is in a rather early state, but it
is possible to create a plugin that displays new tool pages in the editor. World Editor plugins should be
placed inside the
Plugins/Tools/Editor/directory so that they are loaded after the World Editor itself is loaded. Support for import and export plugins has been moved to the World Editor, and the Collada Importer plugin has been modified to work directly with the editor. - Up to four columns of tool pages can now be displayed in the World Editor. How many columns there are, and where they appear, is configured by selecting Editor Settings from the Layout menu. Each of the four available columns can be placed on the left or right side of the viewports when made visible. Pages can be dragged from one column to another.
- By holding in the Control key (Command key on Mac) while clicking on the collapse or close button of a tool page, all pages in the same column can now be collapsed or closed at once. There is a new command in the Page menu that shows all available tool pages.
- In the World Editor, the selection mask will now be automatically updated whenever a new node is drawn so that the node is always selectable right after it is created.
- The Clone Group command in the World Editor has been replaced with the Clone command. Any node can be cloned now, and the result is a new copy of the node that refers to the same object(s).
- The right-click popup menu in the World Editor now contains a Get Info item. Also, the Frame All and Frame Selection items in this menu now work on perspective viewports.
- Editable text elements can now be made read-only by setting the
kEditableTextReadOnlyflag with theSetEditableTextFlags()function. Text can still be selected and copied from a read-only text element, but it cannot be modified by the user. - The Movies plugin now exposes script functions for playing, stopping, pausing, and resuming movie items inside panel effects.
- The Collada Importer now correctly sets the default up direction to the y axis if an imported file does not indicate an up axis.
Build 147 — 25-Feb-2008
- This release is primarily an update that contains the demo shown at GDC.
- A new enemy character, the spider, has been added to the demo game. Its controller is now the simplest example of a controller for a non-player character.
- A world can now be paused by setting the
kWorldPausedflag with theWorld::SetWorldFlags()function. (Care should be taken to avoid clearing other flags by callingWorld::GetWorldFlags()and logically ORing in thekWorldPausedflag.) While this flag is set, controllers and effects are not moved. The demo game now sets this flag when the menu window is displayed in single player mode.
Build 146 — 7-Feb-2008
- With this release, we begin officially supporting the Intel GMA X3000 series of graphics chips under Windows. Some driver issues are currently preventing us from supporting these chips on the Mac.
-
A new post-processing effect has been implemented that enables distortion effects such as heat haze. Any effect can be configured so that it renders into the distortion buffer instead of into the main scene by using the
Effect::SetEffectListIndex()function to set the effect list tokEffectListDistortionand by setting thekShaderDistortionshader flag. TheEffect::SetDistortionState()function has been provided to set all of the necessary state for rendering into the distortion buffer.When an effect is rendered into the distortion buffer, only the red and green channels of the texture color matter, and they encode horizontal and vertical offsets, respectively. A value of 128 in either channel means no offset, while 0 means the largest possible negative offset, and 255 means the largest possible positive offset. Offsets are accumulated in the distortion buffer so that multiple effect nodes can have an additive effect on the amount of distortion visible at a particular point. The alpha channel of the vertex color can be used to modulate the intensity of the offset values after RG decoding. See the
ShimmerSystemclass in the demo game for an example of a particle system that renders heat waves into the distortion buffer. - It is now possible to render effect nodes in the lighting passes so that all of the shading capabilities of
the engine can be applied to the effect. This is accomplished by using the
Effect::SetEffectListIndex()function to set the effect list tokEffectListLight. An effect must have normal and tangent arrays in order to render correctly in the lighting passes. The marking effect has been extended to create these arrays automatically and set the effect list index. To use this functionality, thekMarkingLightflag should be specified when creating a newMarkingDatastructure. The demo game now uses this flag for blood splatters. - The engine now supports a hierarchical relationship among plugins, and it is now possible for a plugin to
depend on the existence of other plugins. The way this works is through the use of subdirectories inside the
Pluginsdirectory. All plugins in a particular directory are loaded before any plugins in the subdirectories of that directory, so if plugin B depends on plugin A, then plugin B should be in a subdirectory inside the directory containing plugin A. - It is no longer necessary to define
C4MODULEwhen compiling the application module or any plugin modules. Instead, the engine project definesC4ENGINEMODULEso that it can be determined that the engine is being compiled as opposed to any other module. - All of the movie code has been moved into a new Movies plugin. All dependencies on QuickTime are now isolated to this plugin, and the plugin can simply be omitted if movie playing capabilities are not needed. The MoviePlayer plugin depends on the Movies plugin.
- A new plugin called Extras has been created that contains functionality that may not be needed by every game, but is general enough to be made available outside the application module. Currently, the Extras plugin includes the rotation controller and the star field particle system. More functionality will be moved to the Extras plugin in the future.
-
New path editing tools have been added to the World Editor. A path is made up of a series of components that can be any of the types linear, elliptical, or Bezier. A linear component is simply a straight line that connects two endpoints, an elliptical component is a 90-degree elliptical arc between two endpoints, and a Bezier component is a single cubic Bezier curve with four control points (two endpoints and two off-curve control points). Paths are created by using the three tools in the Paths page corresponding to linear, elliptical, and Bezier components. Switching among the tools allows the user to add different types of components to the same path. Whenever a single path node is selected, using the path tools will add to that path.
The path tools will snap to the beginning endpoint of the current path so that perfectly closed paths can be created. The snap can be disabled by holding in the Control key (Command key on Mac).
Control points along a curve can be selected with the ordinary selection tools. Shift-clicking adds or subtracts from a selection. A Control-click (Command-click on the Mac) will cause control points along the tangent to be selected in addition to an on-curve control point in a single click. If an off-curve control point is moved for a Bezier component, then it's opposing control point in any adjacent Bezier component is moved in the opposite direction unless it is also selected or the Control key is held in (Command key on Mac).
- Three new geometric primitives based on paths have been added to the engine and are available in the Geometries page inside the World Editor. They are called path tube, path extrusion, and path revolution. Each of these primitives can be created when a path is selected in the editor to define the shape of a tube, the base shape of an extrusion, or the lateral surface shape of a revolution. When creating a tube geometry, you drag out a disk representing the shape of the tube's cross section. When creating an extrusion or revolution, the drawing tools behave like a box and a cylinder, respectively so that you can create geometries with the shape of the path, but at any size.
- A new effect type called a tube effect has been added to the engine. It is similar to the beam effect, except that it follows a path instead of a straight line. The tube effect is drawn as a circular disk representing the cross-sectional shape. The actual effect can only be seen in the perspective view with lighting turned on.
- When a tube (geometry or effect), extrusion, or revolution is created, the path from which it was made is copied into the
geometry or effect node so that the original path is not needed in order to rebuild the node (for example, with different
subdivision settings). A link to the original path is also stored in a built-in connector of type
PATH. When the original path is edited, the node linking to it will not be updated automatically, but any such node can be explicitly rebuilt using the linked path by choosing the Rebuild with New Path command under the Geometry menu. Several improvements have been made to the in-game interface panels and the Panel Editor:
- It is now possible to create and register custom panel items.
- There is a new stock panel item that encapsulates editable text.
- The selection tool in the Panel Editor now functions as a box select tool once the cursor has been dragged a few pixels. The shift key can be used to add to the current selection when dragging out a box.
- It is now possible to modify settings for multiple items simultaneously in the Panel Editor.
- A new mutator called Animate has been implemented which plays frames of animation out of a texture by changing the texture coordinates of an image item. The mutator is configured by specifying the horizontal and vertical grid dimensions for subdividing the texture, the total number of frames, and the frame rate.
- Script method registrations now take only a single name string instead of the two name strings previously taken.
When a script method name is displayed in the Script Editor, lines will automatically be broken at a space, hyphen,
or forward slash, if necessary, or at any newline character (represented by
\n). - In the World Editor, the types of entities, locator markers, and reference markers are now displayed in the Info page for the node to which the gizmo is attached.
- A new command called Bake Transform into Vertices has been added to the Geometry menu in the World Editor. This applies the node transform of a geometry node to each of its vertices, and then sets the node transform to the identity.
- Another new command called Reposition Mesh Origin has been added to the Geometry menu. When this is selected, a dialog appears that lets you select min, center, or max for each of the three axes, where these refer to the bounding box. The node position for each selected mesh will be moved to the specified location, and the vertices of the mesh will be translated the same distance in the opposite direction. This has the effect of moving the object origin without actually moving the world-space vertex positions.
- A new command called Move Viewport Camera to Node has been added to the Node menu. This command moves the camera in all perspective viewports to the position of the selected node and faces it along the node's z-axis. The camera still obeys the ordinary restrictions on the viewport camera, so it will not roll side to side or tilt up or down more than about 83 degrees from the horizontal.
- Another new command called Open Referenced World has been added to the Node menu. This command opens the world resource referenced by each selected reference marker in a separate editor window.
- A new camera speed slider has been added to the Viewports page in the World Editor. This controls the maximum speed of the free camera in the perspective viewports.
- When the Invert Geometry command (Ctrl-Shift-I) is used in the World Editor to invert a primitive geometry node, it will now also flip the "Build inverted" flag from the Get Info dialog automatically. This will cause the geometry to continue rebuilding in the inverted state if it's altered at a later point in time.
- When placing a locator marker in the World Editor, the marker will now keep the identity transform until the mouse has been dragged several pixels away from the click point. This prevents random rotations if the mouse is clicked and released at the same point.
- The Markers page now displays a list of registered locator types. Selecting one of these lets you place a locator in the scene with the registered type already set.
- The Memory Manager has been largely rewritten and there is an enormous performance improvement in general allocation speed.
- Screenshots saved using the
shotcommand are now saved as compressed TGA files (whereas before they were not compressed). - All interface elements now have common functions for getting and setting their sizes. These functions are
GetElementWidth(),GetElementHeight(), andSetElementSize(). Also, the origin for the push button element is now at the left edge of the button at the vertical position for the button text. - When a radio button is selected by the user, it will now automatically unselect all other radio buttons having the same parent element.
- It is no longer necessary to type the full path name when opening a world, texture, or sound using the command line. The top-level virtual directory name should be left off.
- All resource names may now contain the names of system variables, and these will be replaced by the value of
each variable before the Resource Manager tries to locate a resource. The syntax is
($name). For example, if you try to load a resource with the nametextures/($season)/leaves, and the value of the variable$seasonis "summer", then the Resource Manager will load the resource namedtextures/summer/leaves. A resource name may contain any number of variable names. In any case when the right syntax isn't used or the variable doesn't exist, the resource name is not altered. - The Xcode projects for the Mac have been changed significantly. Everything now builds as a dynamic library
instead of a bundle. The engine module also builds as a dynamic library because it's not possible to link
against both an executable and another plugin on the Mac, and this is necessary for plugins that depend
on other plugins. A small executable that contains only the
main()function is now built as a wrapper for the engine module.
Build 145 — 27-Nov-2007
- Implemented a new GUI rendering system. For details, see the wiki article about Creating a GUI Skin.
- Added a radio button interface element as the
RadioButtonElementclass. - Cameras now have a new flag to indicate that they may temporarily move outside their owning zone. This is useful in such cases as a camera mounted on a gun that's attached to a character. A similar flag has existed for lights, and now both flags are exposed in the Get Info dialog.
-
A new concept of “perspective” has been worked into the engine, and this refers to the kind of viewing position the scene is currently being rendered from. There are currently four perspectives defined: direct, reflection, refraction, and camera. The direct perspective pertains to the scene as it is rendered directly from the main camera, the reflection and refraction perspectives pertain to the scene as it is rendered through remote portals, and the camera perspective pertains to the scene as it is rendered through a camera item in an interface panel. Multiple perspectives can be in effect at the same time; for example, the reflection in a water surface seen through a panel camera.
Geometries and fog spaces can now be excluded from each of the four perspectives by setting flags in the Get Info box. (The flags for a geometry appear under the Node tab.) For geometries, the visibility of shadows can also be controlled independently.
- A new flag has been added for remote portals that enables recursive rendering. By default, this flag is off, so a remote portal will not be rendered again if you are already looking through that portal.
- When shadow maps, cube light projections, spot light projections, or ambient space maps are generated, they are now written into the same virtual directory that contains the world resource from which they were generated. Any subdirectory names in the resource path are relative to the top-level virtual directory.
- Added the
GetImportResourceCatalog()function to theSceneImportPluginclass and theGetExportResourceCatalog()function to theSceneExportPluginclass to let the plugins specify what catalog to use for import or export. - Added some resource caching optimizations.
- A lot of work has been done to move the PS3 rendering code to a much lower-level system. The Graphics Manager now minimizes use of the GCM library and instead uses custom code to build command buffers. This allows the C4 rendering code to be as fast as possible, and it gives C4 access to more hardware features than are available to other PS3 games.
Build 144 — 9-Nov-2007
-
The Resource Manager has been redesigned and now supports pack files and a virtual directory hierarchy. All resources are still stored inside the
Datafolder, but the subfolders that previously separated resources by type no longer exist. Resources can now be organized in an arbitrary manner inside theDatafolder. However, the top-level contents of theDatafolder have special meanings.All of the top-level subfolders of the
Datafolder behave as if their contents belonged to a single virtual folder at the root of the resource namespace. These top-level subfolders exist only for external organization and do not participate in the unique identification of any resources. As an example, suppose that there existed two subfoldersData/Interiors/andData/Exteriors/. A resource namedWood.texcould be stored in either subfolder, but it would still be identified only as "Wood" by the Resource Manager. The name of the top-level subfolder is not part of the resource's path. However, if theWood.texresource was placed in an additional subfolder such asData/Exteriors/Forest/, then the name of the resource would be "Forest/Wood". All folder names beneath the top-level subfolders of theDatadirectory are part of the resource name.The resources that ship with C4 have been divided into the following subfolders:
- A
C4folder containing the resources used by the core engine and required by all applications built with C4. - A
Demofolder containing the resources used exclusively by the demo game. - A
Toolsfolder containing the resources used exclusively by the tool plugins. - A
Tutorialfolder containing the resources associated with the tutorials and sample worlds.
Pack files, having the extension
.pak, can also be stored at the top level of theDatadirectory. A pack file is created by using a new tool plugin, the Resource Packer, to pack the contents of a top-level subfolder into a single file. The console commandpack<name> is used to create a pack file, where <name> is the name of a top-level subfolder. For example, the commandpack Demowill create the fileDemo.pakcontaining all of the resources used exclusively by the demo game. Once a pack file has been created, the folder from which it was made can be deleted, and the Resource Manager will fetch resources from the pack file instead. (Pack files actually override ordinary folders.)Some additional miscellaneous notes about the Resource Manager:
- Folders and pack files are the only items allowed at the top level of the
Datadirectory. Other types of files in that location will be ignored. - Resource path names inside pack files are case sensitive.
- QuickTime movies cannot be accessed inside pack files.
- Because concealment is a benefit provided by pack files, there will not be an unpacking tool that would allow
users to easily extract resources from a
.pakfile.
- A
- It is no longer necessary to use the
ModuleResourceclass template when defining a resource type in a game module or plugin module. New resource types should now just inherit from theResourceclass template. However, the resource descriptor is now declared in the subclass. - The
Packable::GetPackSize()andPackable::GetPackTypeCount()functions have been removed from the engine. All overrides of these functions in custom class types should be deleted. These sizes are now calculated automatically by calling thePackable::Pack()andPackable::PackType()functions with a nonwritable data object. - Added a new flag to the script controller that lets you limit concurrent runs of a script to unique activators. That is, with this flag set, only one instance of the script will run for each node that is activating the trigger for the script.
- The C4 Sound Manager has been upgraded on the Mac to use the CoreAudio framework. This should provide greater compatibility with future hardware and OS releases as well as yield better performance.
- Added a new
HashTableclass to the engine utilities. - The
PrimitiveGeometryclass now inherits fromConstructableso that custom primitives can be defined by an application. - A new setting has been added to the Texture Import dialog that allows you to select the channel from which height
data is read when calculating normal maps, horizon maps, and ambient occlusion maps. The command line equivalent
is
-height<n>, where n is an integer between 0 and 3 representing the red, green, blue, or alpha channel, in that order. - Since world resources don't all have to be in the same location any more, the demo game now reads the strings in
the
Data/Demo/game/Worlds.strfile to obtain the list of playable worlds displayed in the New Game and Host Game dialogs. The corresponding.txtfile in theImportdirectory can be edited and re-imported (with theistringcommand) to add or remove worlds from the list. - A new command, Save and Play World, has been added to the World menu in the World Editor. This saves the world being edited, closes the World Editor, and loads the world in the game.
Build 143 — 19-Oct-2007
- Reference markers can now be expanded and collapsed dynamically from code using the
ReferenceMarker::Expand()andReferenceMarker::Collapse()functions. - The
TextElementinterface element class has been rewritten and now combines all of the functionality that was previously spread over four different classes. Several new features have also been added that can be used almost everywhere that text is rendered in the engine, including panel effects. For more information, see the documentation for theTextElementclass. - The
EditableTextElementclass has been expanded to allow multi-line text boxes. This is enabled by setting thekEditableTextMultilineflag with theEditableTextElement::SetEditableTextFlags()function. Multi-line text boxes support all the bells and whistles, including full selection capabilities, copy and paste, mouse wheeling, word wrap, double-click word selection, and smart cursoring. - Made some general improvements to the Panel Editor. One of these is that the text entry box for text items is now a multi-line box.
- The Set Panel Item Text script function has been expanded so that you can choose to append or prepend text in
addition to replacing it altogether. Also added a way to limit the length of the resulting text. An example that
uses this new functionality has been added to the
Samples/Lasersworld. - Added a truncated cone primitive geometry type. This produces a cleaner mesh than intersecting a cone with a box in many cases.
- Some improvements have been made to the CSG code in the World Editor. They can now handle some more topologically complex cases.
- Exposed the GetMillisecondCount() function in the Time Manager. This will return a real-time absolute millisecond count, but with no zero reference. This function should only be used if you know what you're doing. If you have to ask whether it's the right function, then you shouldn't use it.
Build 142 — 9-Oct-2007
- The Tool Manager has been renamed to the Plugin Manager. The
Toolclass is now thePluginclass, theToolMgrclass is now thePluginMgrclass, and the Tools folder is now the Plugins folder. - A new feature has been added to the in-game interface panels that allows an impostor image to be displayed beyond a given distance instead of the set of elements in the panel. This can improve performance considerably when many panels are visible at once. The impostor image will cross-fade with the real panel between two distances that can be set in the Get Info dialog under the Panel tab. An impostor image should be a 2D texture so that mipmapping is supported. It is possible to change the impostor image from a script using the Change Settings method.
- A geometry detail level bias and shader detail level bias have been added to the Get Info dialog for geometry nodes. These are specified in units of fractional detail levels. A value of 1.0 means to use a detail level that's exactly one level lower quality than would normally be selected. Negative values can be used to keep higher detail at farther distances.
- A detail level bias setting has been added to remote portals and panel cameras. This value is added to the detail level that would normally be selected by the engine (in addition to per-geometry detail level biases) and can be used to boost performance when rendering reflections, refractions, or panel cameras.
- A simple
QuadEffectclass has been added to the engine for cases when you just need to render a single billboarded quad. It has a position, radius, color, and texture. It gets rendered in the sorted transparent effect pass. - Calling the
Entity::SetRootAnimator()function now causes the new root animator to be invalidated, so it's no longer necessary to invalidate it through a separate call toAnimator::Invalidate(). - Added settings to the
DoorControllerin the demo game that control the opening speed and closing speed of a door, the time that a door stays open, and whether the door is initially open or closed. - Added a generic rain particle system to the demo game. Also added a new setting to the burning rain particle system that controls what percentage of the rain drops turn into flames. (Note that setting the rain intensity and burning rain percentage too high in combination can result in the flame particle system periodically running out of free particles.)
- Implemented a fallback mechanism for missing fonts. If an attempt to load a nonexistent is made, then the default GUI font is loaded in its place.
- The middle mouse button now pans viewports in the World Editor.
- The Collada Importer now recognizes any empty node whose name begins with
MARKER_as a locator marker. This will prevent an empty leaf node from being deleted during import. When the marker is imported, the first 7 characters are stripped from the beginning of the node's name. - The Graphics Manager now allows three texture quality settings, and this is exposed in the Graphics Settings dialog in the game code. The high quality setting causes the highest-resolution mipmap to be used, and the medium and low quality settings remove the top one or two mipmaps, respectively. Any mipmaps having a resolution higher than that supported by the hardware are also removed.
- Added an icon to the multiplayer game that appears over a player's head when he's typing a chat message.
- Made some adjustments to the weapon code in the demo game so that shots are no longer fired parallel to the line of sight, but instead in a slightly bent direction based on how far away the target in the crosshairs is. This precisely aligns the projectile's destination with the center of the crosshairs.
Build 141 — 3-Oct-2007
- The Info page in the World Editor now displays the number of instances in the scene corresponding to the node for which the gizmo is currently shown. The number of instances is equal to the total number of nodes referencing the same data object.
- When replacing materials on individual surfaces of a geometry that has multiple instances in the scene, the World Editor now enforces the preservation of the material segmentation structure in order to prevent mismatches among the different instances. What this means is that you can't change the number of material slots or the surface-to-material-slot mapping for geometries having multiple instances in the scene. The only consequence of this rule is that attempting to change the material for a set of surfaces on an multiply-instanced geometry may result in the material being applied to more surfaces than are selected.
- Added the Copy Transform and Paste Transform commands to the Edit menu in the World Editor. These commands copy and paste the local node transform corresponding to the node for which the gizmo is currently shown. They do not copy and paste the node size (since that's not part of the transform), but just the position and rotation. The transform clipboard is independent from the main clipboard.
-
Added the Combine Detail Levels and Separate Detail Levels commands to the Geometry menu in the World Editor. These commands allow you to combine multiple geometries into a single geometry with multiple levels of detail, or to separate multiple levels of detail in a single geometry into multiple geometries with a single level of detail.
The Combine Detail Levels command is available when 2–4 geometries are selected. It examines the highest level of detail from each geometry and puts them in order by vertex count. The geometry having the most vertices is designated the primary geometry node, and it continues to exist after the detail levels are combined. The highest level of detail from each geometry is added to the primary geometry as a lower detail level, replacing any lower detail levels that were already there. The geometry data from each input geometry is transformed into the coordinate space for the primary geometry. (Geometries should be manually aligned before combining detail levels.) Input geometries other than the primary geometry are finally deleted.
The Separate Detail Levels command has the opposite function. It takes an input geometry and creates new geometry nodes for each level of detail, removing them from the input geometry. The new geometry nodes are identical to the input geometry, including controller assignment, properties, and connections. However, the collision data will be rebuilt for level 0 if it had been changed.
- The collision detail level is now exposed in the Get Info dialog under the Collision tab. By default, collision detection information is generated for the highest level of detail (level 0) for a geometry. This can now be changed so that collisions occur against a lower level of detail. The advantages to setting a higher-numbered collision detail level (which corresponds to lower geometric level of detail) are that it saves space and it performs a little faster. If the collision detail level is set greater than or equal to the number of geometric detail levels, then the last available level of detail is used.
- A check box called "Reflection" has been added to the Texture Mapping page in the World Editor. Checking this box will cause texture coordinates to be mirrored in the s direction, effectively adding an inversion on top of the reflection in the texture coordinate generation matrix. Mirroring in the t direction can be achieved by rotating 180 degrees after checking the Reflection box.
- An alignment plane popup menu has also been added to the Texture Mapping page. This allows selection of the XY, XZ, or YZ plane as the texcoord generation plane. These are set automatically by many primitive geometries, but may need to be changed for imported geometry to get the desired mapping.
- The default texture used when a texture resource is missing has been changed so that it works better as a
normal map. (The file is
Data/tex/C4/missing.tex.) This texture now looks like a bunch of green Xs on top of a pastel purple background (representing the <0,0,1> normal vector). - The
Constructable::Construct()function has been changed to take a second parameter. Any custom construction functions (for custom objects, properties, controllers, etc.) will need to be altered so that they take a second parameter of typeunsigned longfor additional flags to be passed in. The value of the flags parameter can safely be ignored. - Fixed a crash that would occur only on PowerPC-based Macs when streaming sounds were played.
Build 140 — 27-Sep-2007
-
IMPORTANT: It is particularly important that you backup your resources before installing this build. The World Editor will throw away obsolete information when you open files, and worlds will be saved in an updated format.
After installing build 140, you should open each of your worlds in the World Editor and then immediately save them to automatically update them to the new format. Resource sizes will decrease a bit depending on how many generic meshes each world contains. Models should also be opened in the Model Viewer and then immediately saved to update those as well.
If you have any worlds or models that have not been opened and saved for a very long time, then you should open them and save them in build 139 before installing build 140. Specifically, any resources not saved in build 112 or later need to be opened and saved in build 112–139 before installing build 140. Some very old backwards compatibility mechanisms have been removed from build 140, and this could cause information to be lost if resources aren't first updated in a previous build.
- All geometry building code in the engine has been completed rewritten. The World Editor no longer relies on the existence of a separate source of polygon data for generic meshes, and a lot of support for obsolete mesh operations has been removed. Even though most of this rewrite pertains to internal functionality that is transparent to the user, the completion of this task opens the door for much faster implementation of new geometrical editor features.
- Most of the new geometry building code is concentrated in the
GeometryLevelclass, which represents a single level-of-detail for a geometry object. Non-primitive (generic) geometries are no longer implicitly rebuilt when certain operations are performed on them in the editor. Primitive geometries are rebuilt when they are changed, and they can be explicitly rebuilt by the user. Imported geometries are always generic, and normals for imported geometries are always preserved. Normals can be explicitly recalculated in the editor, however (see next item). -
The Node menu in the World Editor has been split into a Node menu and a Geometry menu. The Geometry menu contains two new commands, Rebuild Primitive and Recalculate Normals.
The Rebuild Primitive command has limited utility in this build, but it will become a lot more useful in future builds when edits have been made to a primitive geometry and you want to restore it to its original state. One present use for this command is to restore natural texture coordinates after they've been altered.
The Recalculate Normals command recalculates all of the normals for selected geometries. This is useful for replacing bad normals on imported geometries. When normals are recalculated, so are the tangents.
- A primitive geometry will no longer remember that it has been inverted by the Invert Geometry command. If a primitive is rebuilt, then the inversion will be lost. There is a new flag in the Get Info dialog for primitive geometries that causes them to be built inverted, and this should be used to permanently invert a primitive.
- The CSG operations (intersection, union, subtraction) in the World Editor have received a major upgrade. They are now capable of handling much more complex geometry, and they generate very clean meshes using some new geometry optimization operations. There are still some precision-related issues with high-density meshes and complex topologies, but the CSG operations can do a lot more than they could before.
- The resize tool has been completely rewritten for generic meshes.
- A new Mesh Tools page has been added to the World Editor. It currently contains only one tool, and that tool
selects individual surfaces on a geometry. (A surface is a group of faces which, as a whole, has a
tangent space domain and material that is independent from other surfaces belonging to the geometry.)
Clicking on a geometry with the surface selection tool will select the surface containing the triangle
that you clicked on. The Shift key can be used to select multiple surfaces, and it's possible to select
surfaces from multiple geometries simultaneously. The highlight color for selected surfaces is given by
the
$surfaceColorsystem variable. - If individual surfaces are selected on a geometry, then the Set Material command in the Geometry menu now replaces materials only on those surfaces, leaving the materials on other surfaces unchanged. If a geometry is selected, but none of its individual surfaces are selected, then the Set Material command replaces the material for all of the geometry's surfaces.
- The Select by Material command in the Edit menu now selects all of the individual surfaces using the current material instead of entire geometries.
-
A new Texture Mapping page has been added to the World Editor. It contains tools for offsetting, rotating, and scaling texture coordinates. It also contains type-in boxes for the texcoord generation transform and popup menus for the coordinates generation modes. This replaces the Texturing tab which used to exist in the Get Info dialog for a geometry node. (The Texturing tab has been removed.)
When an entire geometry is selected, the texture offset, rotate, and scale tools apply to all surfaces of the geometry. If individual surfaces of a geometry are selected, then texture operations only affect the selected surfaces.
The texcoord generation transform information appears when exactly one surface is selected. Two offsets (one for each of the s and t coordinates), two scales, and a single rotation value can be changed by entering new numbers in the text boxes, and the changes take affect immediately. For undo, the Texture Mapping page works like the Transform page: any contiguous sequence of inputs for offset, scale, rotation, or mode is treated as a single undoable action. Also like the Transform page, keyboard focus is ended whenever you click in a viewport, select a standard tool at the top of the editor window, or hit the Escape key.
- Operations that combine multiple geometries into one now generate as many detail levels as the maximum number existing in any of the input geometries. The applies to the Merge Geometry, Intersect Geometry, and Union Geometry commands in the World Editor.
- The
FunnelGeometryprimitive geometry type has been removed from the engine. The same type of shape will be achievable in the World Editor using a revolved path in an upcoming release. Any existing funnel geometries will disappear when a world containing them is opened in this build. To keep the funnels, convert each one to a generic mesh using a previous build. (Select all of them and hit Ctrl-Shift-C in the World Editor.) - Eight flags have been added to the cloth geometry to control which vertices are fixed in position. This is a temporary solution that allows control over whether each of the four corners or four edges of a cloth geometry is fixed. The flags appear in the Get Info dialog under the Geometry tab.
- The utility window that has been called "Graphics" is now called "Stats", and the
grafcommand has been changed tostat. This window now displays four new stats, two for textures and two for sound sources. For textures, the window shows the current number of textures loaded and the total amount of memory used by the textures. For sound sources, the window shows the current number of playing sources and the number of those sources that are currently engaged. (A source is considered playing if it would be audible when you're close enough to it, and it's engaged when you actually are close enough to it for the engine to need to send it through the Sound Manager. - Additional mouse wheel support has been added in various places. In particular, the mouse wheel will now scroll the pages in the World Editor and the materials in the Material Manager.
- Added the
Stop()function to theMethodclass. This function should be called from within the method'sExecute()function to indicate that the method's subnodes should not be executed, effectively stopping execution of the script along the branch containing the method for whichStop()is called. - Added the static
Sleep()andYield()functions to theThreadclass. These functions can be used to temporarily suspend execution of the current thread. - Added the
Complete()function to theThreadclass. This function can be used to poll for the completion of thread execution. - The Textue Importer dialog contains a new check box that causes the green channel of the output texture to be inverted.
This is useful for changing handedness on precomputed normal maps. The command line switch is
-invgreen. - In the World Editor, holding in the Ctrl key (or Cmd key on the Mac) while clicking in the Selection Mask page will now cause the mask buttons for all other node types to be unselected.
- The Memory Manager has been upgraded. It is now safe to allocate or deallocate memory from any thread.
- The
C4SIMDdefine has been removed from the engine. SSE code will now always be compiled, but the engine will only call SSE functions if the processor supports SSE2 instructions.
Build 139 — 21-Aug-2007
- Implemented a workaround for an ATI driver crash that some people have been experiencing.
- Fixed a couple minor bugs in the engine.
Build 138 — 18-Aug-2007
-
A new script method called "Change Settings" has been added to the core scripting system. This method lets a script change the same settings for an object that are displayed in the World Editor's Get Info dialog. Not all of every object's settings are exposed to scripts because there are some things that can't be changed dynamically, but in general, any object setting for which it makes sense to change can now be changed by a script. A single method can change any number of settings from a single settings category (each tab in the Get Info dialog represents a separate category), and each changed setting generates a journaled message that overrides any previous changes to the same setting.
In the Script Editor, once a target has been chosen for the Change Settings method, a list of available categories appears. Clicking on a category causes the settings in that category to be displayed. Initially, all of the settings are in an indeterminant state, meaning that they are not changed by the script method. Modifying a setting causes it to be added to the method. The settings can be put back into the indeterminant state by clicking the Reset button.
- The Change Light Color script method has been removed because it has been subsumed by the Change Settings method.
- The
Function::Execute()function now takes aScriptStateobject as a second parameter so that it's possible to retrieve information about the activator and trigger nodes. - The Script Editor and Panel Editor will now accept the Enter and Escape keys as shortcuts for the OK and Canel buttons. If the Cancel button is clicked, or the Escape key is pressed, and changes have been made, a confirmation dialog is displayed.
- The Script Editor and Panel Editor windows are now resizeable.
- Added the Ticker mutator to the panel effect code. This mutator can be applied to a text item to make the text scroll left or right and be clipped against the edges of the item's bounding box. A new check box in the Panel Editor lets you choose to put the text all on one line, and this must be checked for the Ticker mutator to do anything.
- The Texture Importer tool now supports 8-bit grayscale TGA files.
- Added a rotation menu to the animation import picker in the Model Viewer. This lets you rotate a character by any multiple of 90 degrees and hardwire it into the animation.
- Made several additions to the Collada Importer tool to handle various quirks in the exporters out there.
- Implemented several bug fixes and minor feature requests that aren't listed here.
Build 137 — 4-Aug-2007
-
The Sound Manager has been almost completely rewritten and now includes a much larger set of features. More important than the number of features, though, is the fact that every single feature is available on all platforms and with all sound hardware. The engine no longer contains any support for vendor-specific libraries like EAX and instead uses a custom multi-threaded software audio renderer. This gets rid of all the headaches associated with supporting different hardware, buggy drivers, and poorly designed APIs. Furthermore, it means that the audio experience is identical on all machines, so testing across a wide spectrum of sound hardware is not necessary.
The following list briefly describes the new features in the Sound Manager.
- All sounds can now have any loop count. Previously, spatialized sounds could only play once or loop forever.
- The previously-existing sound classifications (effects, music, voice) have been removed and replaced by registered sound groups. A game module can define any number of sound groups for which the volume can be independently controlled.
- WAV files no longer need to have a sampling rate of 22.05 kHz or 44.1 kHz. The Sound Manager will play WAV files using any frequency.
- The playback frequency of a sound can be changed while it is playing, and the Sound Manager ensures a smooth transition without popping artifacts.
- A Doppler shift can be applied to a sound based on the relative velocity between it and the listener.
- A very precise sound travel delay can be applied based on the distance between a sound and the listener. When a sound is played, this delay is calculated using the current distance to the listener, but the motion of the listener will also be taken into account so that the sound begins playing at the right time.
- Atmospheric absorption can be applied to a sound based on distance from the listener. This attenuates high frequencies so that distant sounds are muffled somewhat.
- The Sound Manager includes a full reverberation model and supports multiple simultaneously active environments.
A new type of space node, an
AcousticsSpacehas been added that defines the size and reflective properties of an acoustics environment. The listener does not need to be in the same environment as a sound in order for the correct reverberation effects to be audible. - The volumes of early reflections can be set on a per-environment and per-sound basis. There is a separate setting for high-frequency attenuation of reflected sound. Each environment also has a reverberation decay time associated with it.
- Directional sounds are now supported. As the listener moves through a sound cone for a directional sound, the volume falls off to the exterior volume at the cone's boundary. The exterior volume and extra high-frequency attenuation are applied outside the sound cone.
- Sounds can be attenuated by obstructions. There are separate obstructive volume settings for the direct path
and for reflected paths. The
AcousticsPropertyhas been updated for the new obstruction settings. - Sounds use a new fall-off model, and there is a new sound permeation system that determines how sounds travel throughout worlds. Sounds will now penetrate much more deeply through different zones, traveling down halls and around corners until they naturally become too faint to be heard.
Some aspects of the new Sound Manager are still a slight bit rough and will get some tweaking in the next few builds. Acoustics environments have been added to a few of the worlds that ship with the engine, but not all of them.
Some additional audio features that will be added to future releases include direct mixing to multi-channel surround sound and a generalized streaming mechanism that will allow plugin decompressors.
-
For various reasons, all C++ exception handling has been removed from the engine. This resulted in significantly smaller binaries, and execution speed should be slightly faster due to the removal of some code and space overhead. If you have a custom project, be sure to turn off support for exception handling in the code generation properties.
As a consequence of there being no exception handling, many error handling mechanisms in the engine had to be reworked. The design pattern for constructors that used to throw exceptions to indicate failure had to be changed to a pattern in which the constructor doesn't really do anything, and a separate initialization function is called. The most prominently affected classes are
File,Sound, andMovie. The constructors for these classes no longer take any parameters. TheFileclass now hasOpen()andClose()functions, and theSoundandMovieclasses now both have aLoad()function. - In the World Editor, the Get Info dialog nows displays settings for all selected nodes simultaneously. Making changes to the settings has an effect on every selected node when the Get Info dialog is closed. Every type of setting can now assume an indeterminant state that is used when values from multiple nodes conflict. If a setting is left in the indeterminant state, then its value is left unchanged for all nodes. The appearance of the indeterminant states are as follows: check boxes show a dash instead of an X, sliders do not show a handle, popup menus show a blank selection, and both color boxes and text boxes are filled with a striped pattern.
-
Several node settings have been moved or changed to work better with the new Get Info dialog:
- The "Do not render through remote portals" setting for geometries has been moved to a subsection under the Node pane because it is a setting for the geometry node and not the geometry object.
- The "Do not share light object data" setting for lights has also been moved to a subsection under the Node pane because it represents a general node flag.
- The "Light is statically confined" setting for lights has been removed. Controllers that make lights move in a small volume now set the confined flag automatically when the "Light is static" flag has been set in the editor.
- The clear color property of the root zone is now exposed as an actual property. This was a property all along, but it was previously shown under the Zone pane instead of the Properties pane.
-
Several upgrades have been made to the weapons code in the demo game:
- Three checkboxes have been added to the Player Settings dialog that control automatic weapon switching. The game can be configured to automatically change weapons when you pick up a new weapon or when you run out of ammo.
- There are new ammo packs for the grenade launcher, rocket launcher, plasma gun, and proton cannon.
- The proton cannon now does a reasonable amount of damage per unit time.
- The code for the Display Settings, Audio Settings, and Control Settings dialogs has been moved to the demo game module.
- Added a new setting type called
PowerTwoSettingthat displays a slider and allows the user to choose a power of two between a minimum and maximum value. - Added a new setting type called
MultiResourceSettingthat displays a text box containing a semicolon-separated list of resources. - The
ResourceSettingandMultiResourceSettingsettings now display the file picker with texture preview when the resource type is a texture map. - The Interface Manager now maintains a global clipboard for text. Copy, cut, and paste are now supported for all editable text boxes, and this is independent of the World Editor's clipboard for nodes.
- The
TypeToStringandStringToTypefunctions have been moved into theTextnamespace. Furthermore,TypeToStringnow returns a string instead of taking a pointer to an array of characters as a parameter. - Added a
SetThreadPriority()function to theThreadclass. - Changed the
Signal::Wait()function so that it takes a timeout parameter. - The engine now ships with a new project called SimpleChar. This project contains a simple example
of an implementation of a subclass of the
CharacterControllerclass and let's you run a character around the world. This game module can be run by changing the$applicNamevariable (in Data/cfg/Variables.cfg) to"SimpleChar". As with the SimpleBall game module, you need to open the console and use theloadcommand to load a world.
Build 136 — 22-May-2007
- There have been several problems with input not responding on the Mac lately. This issue has been traced to behavior changes in some MacOS X HID Manager functions introduced by the latest security updates from Apple. Some users would have started experiencing the problem after upgrading to MacOS 10.4.9, and other users would have seen the problem only after installing security update 2007-004. A workaround has been implemented in the engine, so all input problems on the Mac should now be resolved.
- Added some new optimizations to the shadow culling code that will stop unnecessary shadows from being drawn in some cases.
- Added a new feature to the motion blur effect that uses fast-clearing hardware to initialize the velocity buffer to the correct background velocity when appropriate. This allows motion blur to be applied when the clear color is being used in a world, and it provides a more optimal way to set the velocity of a skybox. There is no case in which this has any additional performance cost.
- Improved the quality of horizon mapping when used in conjunction with parallax mapping.
- Fixed several minor bugs in the world editor and demo game.
Build 135 — 12-May-2007
- Antialiasing has been re-implemented in the engine using the
GL_EXT_framebuffer_multisampleextension. The number of samples per pixel can be set in the Graphics Settings dialog, and the engine supports up to 8 samples when available. - The weapon code in the demo game has received a big upgrade. All weapons now shoot precisely from their barrels. More importantly, the proton cannon is now implemented. When it's fired, the barrel takes a moment to spin up before the beams actually shoot, but the gun has a devastating effect on its target.
- The configuration interface for customizable settings has been completely reworked. It now displays a two-column
scrollable list of settings. Slider-based settings now also accept text entry. The only affect this has on existing
code is that the
TextSettingconstructor no longer takes a width parameter. - There is a new
HeadingSettingclass that lets you insert a section heading into a list of settings. There is a new Transform page in the World Editor that displays the position, rotation, and size of the node for which the gizmo is currently shown. (Remember that the gizmo can be advanced through the selected nodes by pressing Tab.) Entering new data in the Transform page has an immediate effect on the node. All changes to the position and rotation are clumped together for a single undo step, and all changes to the size are clumped together for a separate single undo step. Keyboard focus in the Transform page is ended whenever you click in a viewport, select one of the standard tools at the top of the editor, or hit the Escape key.
The size fields in the Transform page require a little explanation. These aren't to be confused with scales, which are not included in transformation matrices in C4. All objects that have well-defined sizes can express their dimensions using 1–4 measurements. For most primitive geometries, the measurements correspond to the size of the geometry in the x, y, and z directions. The annulus and hole primitives are exceptions where two numbers correspond to the size of the inner boundary, and two numbers correspond to the size of the outer boundary. For things like lights and sound sources, the first size parameter corresponds to the light's range.
- There is a new Info page in the World Editor that displays various kinds of information about the node for which the gizmo is currently shown. Currently, the Info page displays the node name, the controller type, the number of connectors, and the number of properties for every type of node. For geometry nodes, the Info page also displays the vertex count, face count, surface count, material count, and detail level count. More information may be added in a future release.
- There is a new Grid page in the World Editor that contains controls for all grid-related settings. The toggle buttons for showing gridlines, snapping to the grid, and showing the coordinate axes have all been moved to the Grid page. The settings for gridline spacing and grid color have also been moved to the Grid page from their previous home in the Editor Settings dialog. There is a new setting called "major grid" that specifies how many grid squares separate each brighter major gridline. There are also two new buttons that immediately double or halve the gridline spacing.
- The grid snap mechanism in the World Editor has been changed. Instead of being applied to everything, grid snap is now only applied where it makes sense. In general, grid snap is applied when nodes are placed, moved, or resized. Furthermore, grid snap now applies when nodes are moved in the perspective viewport.
-
The motion blur algorithm has been upgraded in several ways. It's now more accurate, and it takes depth gradients into account so that distant objects don't blur together with close objects. Previously, you could see a halo around the weapon in the demo game because the background was moving, but the weapon was stationary with respect to the camera. This no longer happens, and additionally, the spinning barrel of the proton cannon won't blur with the stationary parts of the same gun.
It was not possible to implement the motion blur as nicely on ATI hardware because the ATI drivers do not support derivative instructions in
ARB_fragment_program. So the ability to separate motion blur into different depth layers is limited on ATI hardware, but it's still better in this release than in the previous ones. In particular, the engine can't stop the stationary part of the proton cannon from blurring into the spinning barrel on ATI hardware. Derivative instructions are available on ATI hardware in GLSL, but GLSL has serious limitations that don't exist inARB_fragment_program, such as a lack of shared global variables, that have prevented the engine from using it. - The cursor in an interface panel no longer blurs into the rest of the panel when the camera moves (since it's stationary with respect to the camera). Again, this isn't 100% perfect on ATI hardware for the reasons mentioned above.
- The Script Editor will now automatically assign generic controllers to nodes that are the targets of script methods, but don't already have controllers assigned to them. This removes the extra step that was necessary before in order for a script method to send messages to a node.
- Added a new function called
SetInputManagementModeto the Interface Manager class. PassingkInputManagementManualto this function will stop the Interface Manager from changing the input mode based on whether a window capable of receiving events is currently active. PassingkInputManagementAutomaticto the function will cause the Interface Manager to switch the input mode to gameplay mode whenever all interactive windows are closed.
Build 134 — 14-Apr-2007
- Added a new
PolygonZoneclass that allows a zone to have the shape of an extruded convex polygon. In the World Editor, polygon zones are drawn in a manner similar to portals, in which new vertices can be inserted, and existing vertices can be individually dragged around or removed. The polygonal shape defines the base of the zone, and the height of the zone is controlled by an additional handle at the top center of the zone. - When a node is cloned, links between any pair of its subnodes are now replicated in the cloned subtree. (Any connectors that lead out of the subtree being cloned continue to be cleared in the new copy.) This also affects connectors in referenced worlds, since these worlds are cloned when more than one instance is used in a level. Connectors inside a referenced world will now be replicated in all copies of that world.
- In the World Editor, panel effects are now rendered in the perspective viewport when lighting is enabled. Panels are only shown in their initial state because controllers do not run in the editor.
- Particle systems are now subclassed from the
Configurableclass and can expose settings in the World Editor. If a particle system exposes any settings, then a Particles pane will appear in its Get Info dialog. - Several improvements have been made to the burning rain effect in the demo game. The flames can now be rendered
as particles, so a single particle system is used to render all of the flames at once. The
BurningRainclass also exposes some settings in the editor now. - Added a color setting to the waterfall particle effects in the demo game.
- Added the Select Connected Node command to the Node menu in the World Editor. This command is available when one or more connectors are selected, and it selects the nodes that they are connected to.
- Added virtual functions
BeginRendering()andEndRendering()to theWorldclass. These contain the code previously in theWorld::Render()function that should only be executed once per frame. The render callback function that could be installed in the last build is no longer necessary since it's exact behavior can now be implemented by overriding theWorld::Render()function and executing extra code after calling the base class'sRender()function. Thus, theWorld::SetRenderProc()function has been removed. - The
CompressorandDecompressorclasses now support 64-bit integers for network messages.
Build 133 — 6-Apr-2007
- FBOs are now enabled by default on the Mac. They seem to be working correctly in MacOS 10.4.9.
- The
Systemclass has been removed from the engine, and its functions have been moved to theEngineclass. All occurrences ofSystem::andTheSystem->should be changed toEngine::andTheEngine->, respectively. -
With the intent of reducing the number of steps required to register custom class types, the registration mechanism has been changed a bit. First, for all registration types, it is no longer necessary to explicitly call one of the
Register*()functions. Instead, every registration type automatically registers itself upon construction. Calls to the following functions should simply be removed:RegisterControllerRegisterPropertyRegisterMethodRegisterMutatorRegisterEffectRegisterEntityRegisterFunction
Second, there is a new, slightly different way to declare registrations for controllers, properties, methods, mutators, effects, particle systems, and functions. Instead of declaring a controller registration object as a
ControllerRegistration, you should declare it as aControllerReg<type>template object, wheretypeis the derived type of the custom controller class. For example, the registraton for theRotationControllerclass is declared asControllerReg<RotationController>. The following templates exist for registering various types of custom classes:ControllerReg<type>PropertyReg<type>MethodReg<type>MutatorReg<type>EffectReg<type>ParticleSystemReg<type>FunctionReg<type>
Custom class types registered with these templates no longer need to be constructed explicitly by the application. If you've implemented a function such as
ConstructController, then you can remove any registered types because they will be constructed automatically.The function registration object is a little different in that its constructor takes a pointer to a controller registration as its first parameter. Function registrations for each type of controller are stored in the controller's registration object. There is no longer any need to implement a
ConstructFunction()function in controller classes that define custom functions.Previously, registration objects for controllers, properties, and mutators took a parameter that specified some kind of validation function. These have been removed because the new registration templates can call the validation function for the custom class type directly. When a controller or property subclass defines the
ValidNode()function (as a static member function), then it is automatically called to determine whether the controller or property can be applied to a particular node. Likewise, defining theValidPanelItem()function in a mutator subclass will cause that function to automatically be called to determine what kind of panel item the mutator can be assigned to.Entity and locator registrations still work as they did before since they don't register new subclass types. Continue using the
EntityRegistrationandLocatorRegistrationobjects to register these types. - The perspective viewport in the World Editor can now render with full lighting, reflection, refraction, fog, and some effects. There is a new toggle button at the top of the editor window that switches between full lighting and bright ambient rendering. Geometries, lights, etc., can be moved around with full lighting turned on to see the immediate results of your changes.
- In the scene graph viewport, hidden nodes are now shown in a darker gray color. Nodes belonging to referenced worlds are shown in a reddish color.
- In the World Editor, the Layout page has been renamed to the Viewports page to avoid confusion with a future Layers page.
- The mouse wheel will now work at all times in the World Editor to zoom viewports, even when you're doing something else with the mouse button down.
- Pages in the World Editor can now be displayed on either the left or right side of the window. This can be changed in the Editor Settings dialog accessible from the Layout menu.
-
The World Editor now displays a gizmo for selected nodes that shows the orientation of the node's local axes. The gizmo is shown as three arrows with colors red, green, and blue corresponding to the x-, y-, and z-axes, respectively. The gizmo is shown for one node in the selection at a time, and it can be iterated through the selected nodes by pressing the tab key. When the Select and Move tool is used, an arrowhead on the gizmo can be grabbed in any viewport and used to drag the node along its corresponding axis.
In the next build, the gizmo will also have rotation handles, and it will be possible to display world-space and zone-space axes instead of object-space axes.
- Added a new Particle Systems page to the World Editor. This page displays a list of registered particle systems (see next item) and also contains tools for drawing emitter volumes. Particle systems now have a built-in connector of type EMIT that can be connected to an emitter volume. How the emitter volume is used depends on the particular particle system's implementation. Multiple particle systems can be connected to the same emitter volume.
- Application-defined particle systems can now be registered using the
ParticleSystemReg<>class. Registered particle systems can be placed in a world using the World Editor. - Particle systems can now be fully serialized, meaning that the state of all active particles is saved.
If a custom particle type is defined, then it must implement
PackandUnpackfunctions that save any custom state in addition to the base state saved withParticle::Pack. - Added a new particle style called
kParticleQuadthat causes particles to be drawn as fully oriented quads instead of camera-facing billboards. Particle systems using this style must use theQuadParticlestructure to store particles. Thetransformfield of theQuadParticlestructure specifies the orientation of each particle as a quaternion. - Added the
AddFarthestParticle()function to theParticleSystemclass. This makes the newly added particle the first to render instead of the last, as is the case when theAddParticle()function is called. - Previously, it has been possible to render multiple fog spaces at once as long as they apply to different render targets, but each fog space had to be in a different zone. It is now possible to place multiple fog spaces in a single zone and have them all be considered for rendering (but still only into different render targets). This makes it a lot easier to add fog to areas that already contain a fog space for an underwater volume.
- The
DoorControllernow exposes settings for three different sounds: one that plays when the door has fully opened, one that plays when the door has fully closed, and one that loops while the door is moving in either direction. - The demo game module now defines the variable
$fovto be the field of view for all cameras, in degrees. The game will clamp the value to the range [45,90]. - The String Importer tool will now translate
\t,\n, and\rinto tab, newline, and carriage return, respectively. As usual, a backslash can be obtained by using\\. - The
TextBoxElementinterface class now starts a new line whenever a newline or carriage return character is encountered. The\nis recognized as a newline in the panel editor for text items. - If an attempt is made to load a nonexistent model resource, the engine will now load a stand-in “missing” model instead of throwing an exception. The “missing” model is currently a yellow cylinder.
- The
shotcommand will now pad out screenshot index numbers in filenames to four digits. - Added support for 64-bit integers to the
Stringclass andTextnamespace. - Added a rendering callback to the
Worldclass. TheWorld::SetRenderProc()function sets a callback function that is called right after the entire scene has been rendered insideWorld::Render(), but before the Graphics Manager render target is changed back to the primary surface. This lets you render extra objects directly into the world's render target. - Precached entity models will now be reloaded when a model resource is exported from the World Editor. This removes the need to quit and restart the engine when a model is changed. If the change occurs while clones of the model exist (perhaps because a world is running in the background), then they will not be replaced, but all new instances will use the new model resource.
- The Collada Importer tool has been updated to recognize additional material structures that are output by the 3DS Max exporter.
Build 132 — 14-Feb-2007
- NOTE: A lot of changes have been made to the distribution of source code files among the three code directories in this build. The directories have been renamed to “EngineCode”, “GameCode”, and “ToolCode”, without spaces, so unzipping into an existing installation will result in three new code directories being created with clean groups of files.
- The World Editor has received a massive upgrade, and the existing editor code has been largely reorganized. It is now structured in such a way that custom editor extensions (plugins) will be possible in a near-term release.
- Most of the editor tools have now been organized into palette-like subwindows called “pages”. Pages contain groups of related tools and can be arranged on the left side of the editor window by dragging them around. Pages can also be hidden or collapsed, and invisible pages can be shown by selecting them in the new Page menu. The page state is saved and restored for each world separately.
- Some previously existing editor features have been moved into new pages. The selection mask buttons are now part of the Selection Mask page, and the show/hide items previously in the View menu are now part of the Visibility page.
- The bulk of the manipulator code has been moved out of the engine core and into the World Editor module, and some internal structures have been changed. All saved manipulators will be dumped when worlds are first opened with this build and replaced with new ones. The only impact this has is that certain manipulator state such a node's editor-only visibility state will be reset.
- There is a new page called Layout that controls viewport configuration and manipulator appearance. Several new viewport layouts are now possible, and the type of each viewport can be chosen by right-clicking in the viewport itself. All editor viewports will be reset to default configurations when worlds are opened with this build.
-
A new viewport type has been added to the editor that displays the scene graph hierarchy. Each node is shown with an icon representing its type and either its name or a string describing its type if it doesn't have a name. The collapse boxes in the hierarchy can be used to hide subtrees. Nodes belonging to referenced worlds are shown in a darker color (when referenced world display is on) and cannot be selected.
The node select, rect select, scroll, zoom, and rect zoom tools work in the scene graph viewport in the same way that they do elsewhere. The move tool works as a reparenting tool in the scene graph viewport, allowing you to drag the selection to a new parent node. Nodes cannot be reparented to one of their descendants or to a reference marker, but anything else goes.
The root node can be selected in the scene graph viewport, but it cannot be deleted or reparented.
- The concept of a target group has been removed from the editor because its functionality has been superseded by the reparenting capabilities in the scene graph viewport.
- The World Settings command has been removed from the editor. It simply opened the Get Info dialog for the root node, and this can now be accomplished by selecting the root node directly and hitting Ctrl-I.
- The right-click menu contains two additional items called Frame All and Frame Selection. These center a viewport on either all nodes or just selected nodes and scale so that everything fits into view.
- Most node types are now visible and selectable in the perspective viewport. Lights, sources, markers, and effects are represented by cubic icons whose size can be changed in the Layout page. The volumes covered by triggers, spaces, and effects are also visible.
- The default grid color in the World Editor is now given by the variable
$editorGridColor. - Added a camera placement tool to the World Editor in a new Cameras page. Also, connectors can now be set up so that they can only link to camera nodes.
- Added a new interface panel item that displays an image rendered from another camera in the world. This can be used for things like security camera monitors. To use this panel item, a connector must be assigned to the panel effect node and linked to the target camera. Then the same connector key should be assigned to the camera panel item.
- A new function that changes the connector key for a camera panel item has been added to the panel controller. This lets a script change which camera is used to render an image for a camera panel item.
- Added a new Skybox page that contains a skybox placement tool. A skybox is now added to a world by explicitly placing a skybox node in the root zone. Skyboxes in existing worlds will show up at the world-space origin. Since a skybox is rendered at infinity, the physical location of a skybox node has no effect, but its orientation does affect the angle at which the skybox is rendered. Furthermore, it is now possible to assign a controller to a skybox node so that, for example, it can be rotated or controlled by a script.
- It is now possible to assign a material to a skybox node in the World Editor. Such a material affects how a skybox is rendered in addition to the texture maps assigned to the six skybox faces. Only material attributes that pertain to the ambient lighting equation affect the appearance of a skybox. A material can be removed from a skybox using the new Remove Material command under the Node menu.
- The Change Material Color script method will now affect any material assigned to a skybox.
-
Added a new sound source type that plays ambient sounds. These can be placed in a world to serve as containers for music or environmental sounds. Currently, the physical location of an ambient source has no effect. If an ambient source is playing, it can be heard at the same volume everywhere.
The Get Info dialog for an ambient source lets you assign a list of sound files to play. If the source is streaming, then multiple sounds can be attached to the source, and they will play consecutively without interruption. The same file can be listed more than once.
- Under the texcoord animation pane in the material manager, the texcoord speed is now displayed numerically, and the allowable range of speeds has been increased.
- When geometry is imported into the World Editor, it will now always appear at the same world-space coordinates no matter what zone is currently the target zone. Imported geometry is still added to the current target zone, but it's transform is multiplied by the inverse of the zone's transform to keep it at the location specified in the import file.
- The Remove Transform command has been renamed to Reset Transform to Identity, and a new command called Align Position to Grid has been added to the Node menu in the editor.
- The Texture Viewer and Texture Importer tools have been merged into a single tool module.
- A new checkbox has been added to the Texture Importer that lets you specify that the RGB channels of the
source texture already contain vector information (such as a normal map). Checking this box causes
mipmaps to be generated for vectors instead of colors. This option can be accessed on the command
line using the
-vectorswitch. - The Model Viewer has been integrated into the World Editor tool module. It's likely that the model viewer will eventually be integrated into the editor window itself so that a separate window isn't even necessary.
- The
Constructableclass template has been changed in a couple of ways that make it more flexible in general and slightly simpler in the default case. All installed custom constructor objects (such asConstructor<Controller>) should now encapsulate a function taking a single parameter of type reference toUnpacker. The type to be constructed can be retrieved by calling theGetType()function on theUnpackerobject. See the examples in the game modules. - The polyboard rendering code has been improved so that polyboards viewed near-tangentially look better.
- Panels now render correctly in fog. Fog must be explicitly enabled for panels by checking a new box in the Get Info dialog for a panel effect node.
- New functions have been added to the
Controllerclass calledWake()andSleep(). When a controller is asleep, it does not receive calls to itsMove()function, saving processing time. New script methods for putting controllers to sleep and waking them are now available. - Added a new flag to the script controller that causes a script to loop continuously. If this flag is set, a script will start over when its last method has finished executing.
- When a world is loaded, all nodes now have their world transforms updated before they are preprocessed.
This means that the world transform of a node is valid inside the
Preprocess()function when a world is being loaded. The world transform is not valid insidePreprocess()if this function is called explicitly or indirectly through a call to theAddNewSubnode()function. - The
Node::EnumerateGeometries()function has been updated so that the callback function gets the center and radius of the input sphere. - Added a loop callback to the
Interpolatorclass. This allows you to install a function that is called each time an interpolator loops (such as the frame interpolator for theFrameAnimatorclass). - Modified the
RotationControllerclass in the Game Module. The center of rotation and the rotation axis are now specified by adding connectors of type CENT and AXIS to the controller's target node and connecting them to markers. If the AXIS connector is present and connected to a node, then the difference in the positions of the two markers gives the axis of rotation. If there is no AXIS connector, then the rotation axis is the z-axis. These markers should not be subnodes of the node that is actually moved. - Modified the
DoorControllerclass in the Game Module. The controller should now be applied directly to the node that gets moved (which can be the root node of a bigger tree). Open, closed, and shifted positions are specified by adding connectors of type OPEN, CLOS, and SHFT to the controller's target node and connecting them to markers. The relative positions of the markers (which can actually be any kind of node) tell the controller how to move the door. These markers should not be subnodes of the node that is actually moved. - Added a new enemy character to the Game Module. The AI for the Pumpkinhead is extremely basic for now, but the code demonstrates how an NPC could be added to a game. The Pumpkinhead can be found in the Dungeon level, and he'll come after you with fireballs.
- By fiddling with internal formats, a 75% increase in shadow map rendering speed has been achieved on ATI hardware.
- The C4 Engine now runs on PS3.
Build 131 — 20-Nov-2006
- Implemented an example of a polyboard particle system. The
SpiralHelixEffectclass in the Game Module animates a particle system for which every group of 8 particles forms a ribbon. - Added a workaround to the Collada Importer that would handle apparently erroneous bone weights of zero generated by the ColladaMax 1.06 export plugin.
- Fixed a scale problem that affected Collada exports from 3D Studio MAX. Models that looked mangled before should now import correctly.
- Fixed a problem that could prevent animations from importing correctly.
- Fixed a hardware detection problem that could cause shadow mapping not to render correctly on ATI hardware.
(A hacky workaround has to be used on ATI hardware because
GL_ARB_fragment_program_shadowdoes not function correctly.)
Build 130 — 10-Nov-2006
-
Finished the animation blending system based on a new design. There are three built-in animator subclasses that provide general functionality, and applications can define custom animators for more specific purposes (see next note). Each animator in the tree assigned to an entity targets a range of nodes rooted at a given target node (which is often the entity itself).
The
FrameAnimatorclass is used to play an animation stored in an animation resource. This replaces the functionality that was previously part of theEntityclass. The frame animator is based on time instead of frame number, and its rate can be changed arbitrarily. Control over the playback is accessed through theInterpolatorobject returned by theFrameAnimator::GetFrameInterpolator()function.The
MergeAnimatorclass can be used to combine the outputs of multiple animators. It takes the outputs of all of its subnodes and combines them into a single output. Later subnodes can override the outputs of earlier nodes.The
BlendAnimatorclass blends the outputs of at most two sub-animators. The weight of each animator is controlled through anotherInterpolatorobject that can be retrieved with theAnimator::GetWeightInterpolator()function. Weights are always renormalized by the blend animator, so they don't need to sum to one. - Removed the bone modifier mechanism that was being used to twist the spine of the player as he looked
around. This is now handled by a custom animator called
SpineTwistAnimatorin the game code. - Fixed a bug that could cause a crash on exit when using microfacet shading together with fog.
- Fixed a crash that would occur if you combined dual textures, refraction, and environment mapping in a single material.
Build 129 — 3-Nov-2006
-
Designed and implemented an animation blending system. The
Entityclass can now own a tree ofAnimatorobjects that calculate transforms for the node hierarchy rooted at the entity node. Each animator has its own target root node so that it can be assigned to a subtree of the whole entity. Animators can calculate transforms in any way they wish, and the final transforms output by the root animator are ultimately applied by theEntityclass.NOTE: Some parts of the animation blending system have been intentionally removed from this release because they are being redesigned. The complete system will be included with the next release.
-
Implemented horizon maps. It is now possible, while importing a normal map, to generate two auxiliary textures that contain data about how bumps cast shadows onto themselves. When the “Generate horizon maps” check box is selected in the Texture Importer dialog, two additional textures with suffixes
-h1and-h2are created along with the normal map. Once these exist, horizon mapping can be enabled for a material by selecting the “Apply horizon maps” check box in the General pane of the Material Manager. Horizon maps can only be applied when a single normal map is present in a material, and they use the same texture coordinates as the normal map.There is a new setting in the Graphics Options dialog that enables or disables horizon mapping globally.
- Removed the two-sided and alpha test flags from the
GeometryObjectclass. These rendering flags can now only be set in a material. - Added a new type of particle that can be used for ribbon/trail effects. When the
kParticlePolyboardconstant is specified as a particle's style, then thePolyParticlestructure must be the base structure used in the particle pool. It contains a tangent direction, a texture coordinate, and a flag indicating whether the particle is the last in a single polyboard. If it is not the last, then the polyboard continues to the next particle in the system. If it is the last, then the next particle begins a new polyboard. The radius of a particle controls the width of the polyboard. -
Several big changes have been made to the Message Manager. The
PlayerMgrclass has been removed from the engine and replaced with a system based on events that are passed to handler functions in theApplicationclass.Two new general classes have been defined for distributing information to client machines in a multiplayer game. The
StateSenderclass is used to send initial state when a new client joins a game, and theSnapshotSenderclass is used to send state at fixed intervals during gameplay. - Added a new script function to the
PanelControllerthat activates panel items. This runs the scripts attached to the panel items as if the player had clicked on them. - Removed the
PositionMarkerclass and renamed theLocationMarkerclass toLocatorMarker. All position markers will be converted to locator markers automatically. There was really no need to have two different marker types that essentially mean the same thing. - In the Game Module, the player's weapon is now visible in the first-person view. Both the weapon and the flashlight are now hooked up to a special mount node that the attached to the character. The player's hands do not yet grasp the weapon correctly—we are planning to use IK in a future release to keep the hands in the right place. There are a couple of additional minor issues: projectiles do not yet fire directly out of the weapons, and motion blur around the border of the weapon is not acceptable when the background is in motion. These will both be addressed in a future release.
- The geometry building code now splits vertices along edges that are too sharp to share normals. The Collada Importer now preserves the normal vectors on all imported geometry.
- The Collada Importer now recognizes the custom bump map settings written by 3DS Max.
- The Graphics Manager will now attempt to auto-configure some rendering options. On lower-end graphics chips, some options will be turned off automatically the first time the engine is run.
- Fixed a problem in which some geometries in a zone may not be lit properly if the zone is visible through multiple portals simultaneously and a particular light region doesn't intersect all of the camera regions.
- Made some small changes to the material manager layout. The two-sided flag, alpha test flag, and texture blend mode menu have been moved to a new Options pane. New settings for enabling horizon mapping in a material are also in the Options pane.
- Made several updates to the Texture Importer tool. You can now specify a different output name in the
import dialog. The
itexturecommand can now take command line parameters to specify import settings. If any parameters are specified, then the import dialog is not displayed. This allows batch texture imports to be performed by storing a bunch ofitexturecommands in acfgfile and executing it (with theexeccommand). See the Texture Importer wiki page for a description of the command line parameters. - Added a checkbox to the Texture Viewer tool that lets you turn alpha blending on and off.
- Fixed a minor glitch that would cause the in-air propulsion to be too high for the first frame during which the player is falling. This caused a noticeable burst of acceleration on slower machines when you did something like walk off the edge of a platform.
Build 128 — 1-Oct-2006
- The engine now builds as a universal binary on the Mac, but the Intel version has not yet been tested.
- Made changes to the Network Manager and Message Manager that are too numerous to list here. The vast majority of the changes are finished, but there will be a few more in the next build, mostly to move some functionality currently in the demo game module into the engine module.
-
Added a lot of new gameplay code to the game module:
- Players can steer a little bit while falling through the air now (you exert a small propulsive force).
- Because you can propel yourself in the air, it is now possible to jump onto something even if you are standing right next to it and can't get any forward motion on the ground.
- Motion of client players is now predicted and smoothly corrected in multiplayer games.
- Rockets and grenades now do splash damage.
- When a player spawns, he has a protection shield for a few seconds.
- When you have another player in your sights, his name is displayed.
- The weapon balance has been improved—the blaster does a little more damage, and the plasma gun does a little less damage than before.
- Added a +100 health power-up (jack-o-lantern model).
- Added a Kill Character script method.
- The
Node::EnumerateNodesfunction has been updated so that the callback function gets the center and radius of the input sphere. - Added the
World::QueryWorldfunction. This determines whether a fat ray hits environmental geometry, a collider, or nothing. It works likeWorld::DetectCollision, except it returns a collision state constant indicating what was hit. - Added the
InvalidateStaticShadowVolumesfunction to theGeometryclass. This wipes out any cached shadow volumes and should be called if an object becomes dynamic after being static. - Added the Import Model menu command to the World Editor. This lets you import an
MDLfile. - Added amplitude and period settings to the
TeleportControllerclass in the Game Module. These control the floating effect for the teleporting remote portals. - Updated the Display Manager code for MacOS X to use newer operating system APIs. This should allow more display modes to be accessible, and there is no longer a dependency on DrawSprocket.
- (Bug #0000113) Fixed a crash that would occur if a panel effect was cloned.
Build 127 — 15-Sep-2006
-
Implemented a large amount of new multiplayer functionality. The overall system is a work in progress and will be completed in build 128. The primary enhancement in this release is a new message journal that stores certain controller messages. The journal is sent to client machines when they join a game in order to update the state of various controllers before the current world is displayed. When a client machine receives the messages in the journal, it plays them as if it had been connected to the server all along, ensuring that the correct state is set for controllers that have changed since the game was started.
A controller message is added to the Message Manager's journal when it is sent from the server using the
MessageMgr::SendMessageJournalfunction instead of theSendMessageAllfunction. Journaled messages are also tracked on a per-controller basis, and new messages may override previous messages in the journal for the same controller. TheControllerMessageclass now has a virtual function namedControllerMessage::OverridesMessagethat is called once for each message in the journal that was previously sent to the same controller. It can inspect the previous message object and returntrueto knock the previous message out of the journal. - It is now possible to assign a generic controller to a node. The only purpose of the generic controller is to receive built-in controller messages used by the built-in script methods (such as Enable Node and Disable Node). Any node that is the target of a built-in script method must have a controller assigned to it in order to receive the messages send to it by the script. Any type of controller will do, but if the node doesn't have a controller assigned to it for any other purpose, then it will need a generic controller.
- Scripts now always run only on the server machine. The “script runs on server only” flag has been removed.
- Split the color for light sources into a diffuse color and a specular color. Ordinarily, these are the same, but you can now set a separate specular color for a light source that will be used in the specular component of the shading formula.
- Added a brightness scale box to the Get Info dialog for lights. The overall brightness of a light is scaled by whatever number is entered, as long as it's greater than 1.0.
- Added a beam effect node that renders a cylindrical beam between two points. The beam is rendered as a quad that always faces the camera. The beam may have a custom texture assigned to it that repeats a given number of times along the beam, or it can use a default built-in texture.
- Implemented the Convert to Generic Mesh command in the World Editor. This independently converts each selected geometry into a generic mesh geometry. This will be useful for future vertex/face editing tools because they will only operate on mesh geometries and not primitive geometries.
- The Merge Geometry and Convert to Generic Mesh commands now perform internal T-junction elimination. This is very useful if you build up a multi-material mesh by creating several different components that don't necessarily all share the same vertex positions.
- The concept of group space has been removed from the engine. Vertex coordinates for a geometry are now always stored in either object space or world space.
-
Added command line parsing. The same commands that can be put in a CFG file can now be appended to the command line, and these are executed immediately after the
Variables.cfgfile is executed. Commands are separated by semicolons, and variables begin with a dollar sign. As an example,C4.exe $displayWidth=1024; $displayHeight=768; $applicName="Skeleton"resets the display resolution to 1024×768 and sets the application module to
Skeleton.dll. - Further improved the Collada Importer's ability to locate texture files. It will now recognize the substring "/../tga/" and treat anything that comes after it as the full path to a texture image.
- The Collada Importer will now recognize multiple objects being instanced for a single node. It's a bit odd for a Collada file to have this (and its legality is questionable), but Google SketchUp likes to do it.
- (Bug #0000078) The Collada Importer now imports lights specified in the manner defined by Collada 1.4.
- Added two new built-in script methods that enable and disable interactivity for a node.
- Added a script function to the panel controller that changes the text for a panel item.
- (Bug #0000001) Fixed a problem in the demo game module that would cause a weapon to get stuck in the firing mode if you engaged an interactive object while firing. Interaction events are now simply ignored if you're firing your weapon.
- (Bug #0000035) Fixed a problem in the material manager that was not correctly invalidating changed materials on a mesh with multiple materials.
- (Bug #0000057) Fixed a problem that prevented subfolders from being created on the Mac when new resources were imported.
Build 126 — 31-Aug-2006
- IMPORTANT: In the unlikely case that you have world or model resources that have not been saved in build 113 or later, you need to open them and save them in build 125 before opening them in build 126.
- IMPORTANT: Because of some format changes in this build, it's recommended that you open and save all worlds and models to update your resources. In most cases, resources will shrink in size slightly.
- IMPORTANT: Changes in this build have largely removed the need for the concept of “group space” in the engine. Plans are to remove group space functionality in the next build, so please update any geometries using group space by merging all such geometries in each group together into a single object (more below).
-
Implemented support for multiple materials on a single renderable object. The
Renderableclass now supports multiple render segments represented by theRenderSegmentclass. Each segment corresponds to a separate material and has its own material attributes and shading data. The first segment is built into theRenderableclass, and additional segments can be attached by a higher-level object.The higher-level object normally attaching additional render segments is the
Geometryclass, which now supports multiple materials. TheGetMaterialObject()andSetMaterialObject()functions now take a material index to identify a material slot. The number of material slots for a geometry is always at least 1 and can be set using theSetMaterialCount()function. The granularity at which multiple materials can be applied is based on the division of a geometry into surfaces. Surfaces are groups of polygons that are isolated with respect to normal smoothing, bump mapping, etc. These have been supported by the engine for some time, but now each surface can designate a separate material. When a geometry is built, all sets of surfaces sharing a common material are combined to form a single segment, so the number of render segments is always less than or equal to the number of surfaces. - The Collada Importer tool will now apply multiple materials to meshes that have multiple surfaces referencing
different materials. Each occurrence of a
<polygons>,<polylist>, or<triangles>element within a<mesh>element generates a separate surface to which a distinct material may be applied. - Changed the behavior of the Merge Geometry command in the World Editor. Previously, this would merge the selected geometries and apply the current material to the result. Now, it generates a single geometry that has all of the original materials applied to it. The number of surfaces in the resulting geometry is the sum of the numbers of surfaces in the input geometries. If surfaces of multiple input geometries use the same material, then they are combined into the same segment of the resulting geometry, but the surfaces remain separate.
- Changed the behavior of the CSG operations in the World Editor so that they now always produce a single geometry with multiple materials. All surviving surfaces of a CSG operation between two geometries are combined into a single geometry, and only the materials used by the surviving surfaces are applied to the new geometry.
- CSG operations now generate as many LODs as the maximum number possessed by the two input geometries, whereas previously, only the minimum number of LODs were generated. This is useful if you do something like subtract a two-LOD cylinder from a single-LOD box and still want two LODs in the result.
-
Completed the in-game interface panel system. Under the markers/triggers/effects panel in the World Editor, there is a new effect called “Panel Effect” that lets you draw a rectangular interface panel. This effect automatically has a panel controller assigned to it that can be configured under the Controller pane in the Get Info dialog. There are two sliders here that control the resolution of the interface panel—these are independent of the size of the panel effect in the editor viewport. Clicking on the Edit Panel button opens the Panel Editor window where the contents of the interface can be designed.
The Panel Editor window contains tools similar to those that would typically be found in a 2D drawing application. In this build, there are two types of items that can be placed in an interface panel: images and text. A future build will also include a viewport item that can display a rendered image from another camera in the world. An image or text item is placed in the interface by selecting one of the drawing tools in the upper-left part of the window and dragging out a rectangle. The texture applied to an image item is the one selected on the left side of the window. The texture palette displays all of the textures in the
Data/tex/panels/directory (but any texture can be applied to an image by changing it after it's drawn).When a single item is selected in the Panel Editor, its properties can be edited on the right side of the window. The item identifier is a four-character code that can be used to identify different items from a script—they do not need to be unique, so it's possible to identify a group of items using the same value. The Disabled and Hidden checkboxes determine whether an item is initially clickable or initially hidden, respectively.
A panel item can be made interactive by assigned a script to it. To do so, select the item and click the Edit Script button at the bottom of the window. The script will run each time the panel item is clicked. Note that the Interaction property must be assigned to a panel in order for it to receive interaction events (see below).
Panel items can be animated by assigning one or more mutators to them. The popup menu on the right side of the window contains the available mutators for a selected panel item, and the list box next to it displays the mutators that are currently assigned to the item. A new mutator is added to a panel item by selecting it from the menu and clicking the Add button. Like a panel item, each mutator also has a four-character identifier that can be used to identify it from a script.
The
PanelControllerclass exposes a number of functions that can be called from a script. Each function takes a panel item identifier as a parameter that determines which items are affected. A blank identifier is a wildcard and matches all panel items. For functions that operate on mutators, a separate mutator identifier is also specified, and a blank identifier is a wildcard that matches all mutators. -
Implemented an interaction event system that's used to communicate user interaction information to the controllers of interactive objects in a world. Currently, any geometry node or panel effect node can be made interactive by assigning the new Interaction property to it in the Get Info window. (In particular, this property must be assigned to a panel effect before anything in the panel can be clicked.)
Interactions are reported through the
Interactorclass. An application can define subclasses of theInteractorclass and add them to a world in order to detect interactions between a given line segment and any interactive nodes in the world. When the line segment probe first hits an interactive node, akInteractionEventEngageevent is sent to theInteractorclass. As long as the probe remains in contact with the interactive node, theInteractorclass continues receivingkInteractionEventTrackevents. When the probe later misses the interactive node, theInteractorclass receives thekInteractionEventDisengageevent. The application-defined subclass can handle these in any manner necessary.Controllers now have a
HandleInteractionEventfunction for handling interaction events. Normally, a subclass ofInteractorwill pass interaction events to the controller attached to the interactive node that has been engaged. There are two additional events,kInteractionEventActivateandkInteractionEventDeactivate, that can be sent to a controller when the user explicitly generates some kind of input indicating that they want to activate the node that they're currently passively engaged to. This needs to be handled by the Application Module. -
Implemented an associative key-value container called
Map. It works like theListclass in that there is also aMapElementclass from which objects stored in a map need to be derived and the map owns its members. As with the list container, there is no memory allocation done when an object is inserted into a map—all of the linking pointers are part of the object itself. This also has the advantage that destroying an object automatically removes it from any map it is a member of.The
Mapclass uses an AVL tree implementation to maintain a balanced binary tree. This provides 1.44×O(log n) time searches in the worst possible case, where n is the number of objects in the map. (A red-black tree, used by most STL implementations, will take 2×O(log n) time in the worst case.) - Added the
Terminatefunction to theScriptControllerclass. This terminates all scripts currently running on the controller. - Added a flag to fog spaces that causes their boundary planes to become collision barriers for cameras.
- Added a small feature to the
MarkingEffectclass that causes a marking to exist for exactly one frame. This is useful if you're using a marking for something like a blob shadow. To specify that a marking lives for only one frame, thelifeTimefield of the MarkingData structure should be set to -1. - Added a flag to light nodes that cause them to connect to a shadow space in the referencing world when they are included through a reference marker. If the “Connect to shadow space in referencing world” box is checked in a light's Get Info dialog, then the light will look for a SHAD connector on the reference marker that caused it to be included in another world. If that connector is found and is connected to a shadow space, then the light will automatically connect to that shadow space.
- Added a node flag that causes a node's object not to be shared when the node is replicated. In order for this flag to be effective, the object attached to the node must support replication. Currently, only light objects can be replicated, and a new check box has been added to the Get Info dialog that turns this flag on. This is used to force lights in referenced worlds to have independent objects so that controllers can animate them separately for things like flickering effects.
- Shadow spaces can now be used with infinite lights and depth lights. As with point lights, shadows rendered for a light connected to a shadow space can be restricted by the engine to the volume bounded by the shadow space as a performance optimization.
- Made significant improvements to the shadow culling code for spot lights. Some areas of the demo world got a 10-15% speed-up.
- The graphics stats window (accessed by the
grafconsole command) has been expanded to display a lot more information. It now shows the number of faces and the number of drawing commands used for normal rendering, shadows, and the special effect buffer. It also displays more information about the higher-level visibility statistics, such as number of objects visible, number of shadows visible, and various portal counts. - The
Cursorclass no longer holds a hotspot position. Instead, the center position of a cursor is now specified in the cursor's texture. The Texture Importer tool has been updated to allow a center point to be specified. - Connectors in the World Editor can now be set to link only to entities (in addition to all the other node types that were already there).
- The Collada Importer tool will now recognize texture names with spaces in them. It will also recognize
the substring "/Import/tga/" and treat anything that comes after it as the full path to a texture image
so that the imported material has the correct corresponding path in the
Data/tex/directory. - The Collada Importer tool can now apply textures for which a material attribute references a sampler instead of directly referencing the texture image.
- Added a checkbox to the Font Generator tool that enables mipmap generation for font textures. This should be enabled for fonts that are to be used for in-game interface panels.
- Added specializations to the << and >> operators in the
Packer,Unpacker,Compressor, andDecompressorclasses to explicitly handle thebooltype correctly. When packing into a file, aboolis always saved as four bytes (for alignment). When compressing into a network message, aboolis always written as one byte. - Made a shader optimization that reduces the number of interpolants needed when fog is used. This allows all possible combinations of shading attributes to be applied with fog. (Previously, combinations such as depth light + dual texcoords + specular + fog would overflow the available interpolants by one.)
- The
kGeometryStaticShadowInhibitflag has been renamed tokGeometryDynamic. This flag means a geometry might move, so the engine will not do things like cache shadow volumes for a geometry having this flag set. - Resolved a problem in which motion blur would “stick” and cause screen trashing when decals were visible. There is an unrelated motion blur problem occurring only on GeForce 7x00 hardware which is currently under investigation at Nvidia as bug #251255. UPDATE: A zero-cost workaround has been found, so motion blur should be rendering correctly on all graphics cards now.
- Fixed a problem in which dual texcoords were not working if a material used a parallax map.
- Fixed a problem that could cause a stopped sound source to start playing when a game is saved and restored.
- Fixed a crash that would occur if the cloth controller was removed from a cloth geometry.
Build 125 — 30-Jun-2006
- Implemented an entity placement tool pane in the World Editor. An entity is placed in the world by selecting an entity type from the list, clicking on the entity's position, and dragging to rotate it into the desired orientation. This places an actual entity node into the scene, but it has no model hierarchy until the world is loaded for gameplay. An entity may be initially disabled in the Get Info dialog, in which case it is not rendered until it is explicitly enabled.
- The
EntityRegistrationclass now accepts a controller type parameter that specifies the type of controller to automatically assign to an entity when it is placed in a world using the World Editor. The Skeleton game code has been modified to demonstrate how to register the entity for the green bouncing balls and automatically assign theBallControllerto them. Also, all of the collectable items in the demo game code have been upgraded to use the new entity placement system with automatic assignment of theCollectablecontroller. - Updated the Collada 1.4 import tool to handle some additional variations of skinning data.
- Added simple mouse smoothing code. Mouse smoothing can be turned on and off in the Control Settings dialog. The default setting is on.
- Implemented some experimental frame time filtering code. This should help smooth jitters out when frame deltas change by a large amount.
- Added some code that should make monitor frequency selection more reliable under Windows in full-screen mode.
- The menu bar will now always appear if the console window is opened without a world being loaded.
- Fixed a problem in the game code that would cause a crash if the camera view was changed in spectator mode.
Build 124 — 25-Jun-2006
- Implemented support for version 1.4 of the Collada format. The Collada Importer tool can now read both versions 1.3 and 1.4, and everything that was supported in version 1.3 is now supported in version 1.4.
- Introduced frame time normalization in the World Manager. This is currently applied to velocity-dependent
effects like full-scene motion blur and line particles, giving them a uniform appearance at all frame rates.
By default, the effects are adjusted so that they appear as if the game was running at 60 frames per second
(i.e., 16.666 milliseconds between frames). The default frame time can be changed by calling the
WorldMgr::SetDefaultVelocityNormalizationTime()function and passing in a new normalization time in milliseconds. When a world is loaded or created, it grabs this default time, but you can also set a per-world normalization time using theWorld::SetVelocityNormalizationTime()function. Longer times make the effects more prominent, and shorter times make the effects more subtle. - Added a new flag to remote portals that allows light to pass through them as if they were direct portals. This can be used to let light pass through windows that use remote portals to get bumpy transparency. If this flag is turned on for a remote portal that isn't a simple "pass-through" portal, then the results are undefined. That is, it won't work for mirrors and portals that look at a remote location.
- Implemented significantly better shadow-casting set determination in the World Manager. The engine will now render far fewer shadow volumes, saving a lot of time that was previously spent both calculating and rendering shadows that couldn't be seen.
- The
Clonableclass has been renamed toEntityRegistrationto be consistent with the other types of objects that are registered. - Updated the primitive geometries where necessary so that the natural texture coordinates always form right-handed tangent space.
- The World Editor now initially disables shadows for the planar primitive geometries since they don't form closed meshes by themselves.
- Added an input action binding to the game module that lets you switch between the first-person camera and the chase camera. This is disabled in multiplayer mode so that you can't cheat by looking around corners.
- Added a specialization to the String class template for arbitrary-length strings. Passing 0 as the template parameter causes this specialization to be used. This is the default value, so declaring a string as String<> will grab the class that supports arbitrary lengths. Note that it is less efficient to use this class (but more convenient), so the sized strings should be used when possible and/or practical.
- Fixed a problem in the World Editor that would cause hidden objects to be selected by the box select tool.
- Fixed a problem in the game code that would fail to catch a
ResourceExceptionif you tried to do a quick load, but there was no quick save file.
Build 123 — 06-Jun-2006
- A pbuffer fallback has been implemented on the Windows platform, and it is used if the
GL_EXT_packed_depth_stencilextension is not present. An equivalent fallback has not been implemented for the Mac platform because it does not support pbuffers that can share a rendering context when the pixel format is identical. - Motion blur can now be rendered on all supported hardware running on the Windows platform.
- Reflection and refraction images are now rendered directly to texture buffers (i.e., there is no copy) on the Windows platform. In some cases, this can produce a 5-10% speed increase.
- The material editor now has settings for texcoord scale and offset under the Texcoord pane. There are separate settings for the s and t directions. Scale and offset are applied before texcoord animation.
- Dual diffuse texture maps are now supported. The material editor has a new popup menu at the bottom of the General pane that lets you select how the two textures are combined. The current options are add, average, multiply (modulate), blend with vertex alpha (for future use), or blend with the alpha or inverse alpha of either texture map. The two textures can also use independent texcoord transforms and animations.
- Right mouse button events are now sent through to interface elements using the event types
kEventRightMouseDownandkEventRightMouseUp. - The Tool Manager now maintains a list of scene export tools. You can register a scene export tool by creating
a subclass of the SceneExportTool class and calling the
ToolMgr::RegisterSceneExportTool()function. When one or more export tools are registered, the Export Scene command becomes available in the World menu inside the World Editor.
Build 122 — 24-May-2006
- IMPORTANT: In order to use the save game functionality in this release, you must update any world that will be saved as a save game to a slightly newer format. To update a world, simply open the world in the World Editor and then immediately save it. Although no problems are anticipated, it's highly recommended that you backup your WLD resources before running this build.
-
Implemented delta save files for saved games. Saved games get stored in the
Save/sav/directory. (TheSavedirectory is the root of a new resource catalog.) Games are saved and restored using theWorldMgr::SaveDeltaWorld()andWorldMgr::RestoreDeltaWorld()functions. A save game file stores the entire node hierarchy and all controller information, but it only stores the objects that it actually needs to store. Any objects that exist in the original world and haven't been modified are not saved in the delta file. Since nearly all geometrical information is stored in the shared objects, this makes saved games extremely small compared to the original world. (In the case of the demo world, a saved game is only 1.5% the size of the original world.) Any new objects introduced since a world was loaded and any deleted objects are automatically handled.If a saved game is restored while the original world for which it was saved is still loaded, then a special fast path is taken through which any original, unmodified objects already in memory are reused. Then only missing or modified objects are reloaded from the original world resource. Since materials are stored in objects, this also minimizes texture reloading.
If the game code modifies an object directly, it must call the
Object::SetModifiedFlag()function to ensure that the object is correctly saved in a delta file. If this function is not called appropriately, a modified object may be restored to its original state when a saved game is reloaded. Note that this function only needs to be called for changes to anObjectclass, which are relatively rare. Modifications to aNodeclass do not require a similar call to be made because all node data is always saved. - Added QuickSave and QuickLoad input actions to the sample game. These are initially bound to the F6 and F9 keys, respectively. There is also a new Save Current Game item in the main menu that lets you save a named file. The Load Saved Game item in the main menu is now functional.
- Scripts are now fully re-entrant without limitation. By default, a script has re-entrancy disabled, but it
can be enabled by checking the “Allow multiple instances to run simultaneously” box in the
Controller pane of the Get Info dialog. In order to support re-entrancy, all script methods and controller
functions must be able to replicate themselves, meaning they must implement a copy constructor
and override the
Replicatefunction. -
Implemented full-scene motion blur as a postprocess effect. Motion blur affects everything uniformly and provides the same “cinematic” level of quality advertised by another engine that shall go unnamed. In particular, motion blur is determined by the combination of camera motion, object motion, and also vertex motion for things like skinned characters and cloth.
In this release, motion blur requires FBO support. A p-buffer fallback will be implemented in a minor update.
- Added a geometry flag to the Get Info dialog to disable motion blur. This can be useful for things like geometry covering a remote portal so that double blurring of the remote image doesn't occur.
- Added new checkboxes for enabling or disabling postprocessing effects in the Graphics Options dialog.
- Added the
StopMotionfunction to theNode. This function is used to signal that a node previously in motion has stopped and ensures that the stored transforms used for determining motion blur are reset. This function is necessary because stopped nodes usually aren't being invalidated, so they also aren't being updated any more, and that's where previous transforms are saved to calculate motion blur. See the documentation at http://www.terathon.com/c4engine/doco/WorldMgr/Node_StopMotion.html. - Added flags to the
MaterialObjectclass that let you specify two-sidedness and alpha testing on a per-material basis (whereas before, it could only be done per-geometry). The material editor has been updated to support these flags—they can be found in the General pane. - Added slots for a secondary texture map and a secondary normal map in the material editor. When two normal maps are specified, they always add in the mathematically correct way as if their original height maps had been added together. Parallax mapping is automatically disabled for a material when there are two normal maps.
- You can now choose an input texture coordinate set for each texture in a material.
- Added support for animated texture coordinates. Each texture coordinate set can be animated using the settings under the Texcoords panel in the material editor. All texcoord animation is based on a 120 second period, so individual coordinate velocities must be set so that an integer number of complete cycles have occurred every 120 seconds. (The editor enforces this.) Since the coordinate velocities are quantized, not all animation directions are available at slow speeds. At the slowest possible speed (making one cycle every 120 seconds), the available directions are multiples of 45 degrees.
- The reflection attribute now uses the Schlick approximation for a Fresnel factor. The normal incidence reflectivity is still controlled by the existing slider under the Buffers panel in the material editor. (Water has a very low normal incidence reflectivity, so a value of 1 or 2 would be appropriate.)
- Added a flag for remote portals that stops skyboxes from being rendered through them. This is useful if you know that no part of the skybox will be visible through the portal (e.g., when used for underwater refraction).
- Added a flag to the fluid controller that forces vertices to remain in a plane. When this flag is specified, only the normals and tangents are animated. This is necessary to prevent gaps in a refraction buffer rendered for the fluid. This flag can be set in the Get Info dialog under the Controller pane.
- Added a buffer exclusion mask to fog spaces. These will stop fog from being applied in the primary, reflection, or refraction render buffers. These are accessible in the Get Info dialog.
- The fire effect and flare effect tools in the World Editor now let you drag out their sizes. The fire effect is cylindrical, and the flare effect is spherical.
- Implemented the
FlickerControllerclass in the game module. This causes a point light source to change in intensity and move back and forth quickly like flickering fire. This controller can be assigned to a light and configured in the Get Info dialog. - Made a lot of improvements to the Model Viewer tool. The window now displays information about the model
such as node count, vertex count, and face count. The mouse wheel will now zoom in and out. The tools
can be selected with hotkeys. (The pan, zoom, and free camera tools use the same keys as the World Editor:
6, 7, and 9. The orbit and light tools use 1 and 2.) You can now select an environment in which the model
is placed by choosing Select Environment from the Model menu. Any world saved in the
Data/wld/ModelViewerdirectory can be used as the environment. If you make a new environment, it should not have any subzones in it (just the root zone). The model is always placed at the origin. - Reimplemented normalization cube maps for GeForceFX processors. (This was implemented a long time ago, but was removed somewhere along the way during shader system revisions.) In fill-limited test scenes, this now provides about a 25% speedup. This optimization is only used on GeForceFX-class hardware because all other supported hardware performs normalizations faster using ALU instructions.
- Added a lower-quality texturing mode that can provide a quality/performance trade-off. If the “Use high-resolution textures” box is unchecked in the Graphics Options dialog, then all textures with mipmaps are reduced to half resolution.
- Fixed a problem that would cause entities using a
SkinControllernot to get cloned correctly (the controller wasn't getting cloned for any skinned meshes). - Fixed a bug that would cause QuickTime movies to crash on MacOS X.
- Added a message box that appears if the engine is run on sub-minimal graphics hardware.
Build 121 — 24-April-2006
-
Added a new procedural fire effect. This replaces the old effect that's been in the engine and is vastly superior in multiple respects. The
FireEffectclass is now in the engine core and is accessible in the World Editor. The fire effect can be placed in a world by using the tool in the markers/triggers/effects panel. The Get Info dialog for the fire effect contains settings for the radius and height of the fire, the texture to use, and a couple animation parameters.A single fire effect is rendered as a camera-facing quad that is constrained to rotate about its local z-axis. Its animation is controlled by an intensity value and a turbulence speed value. The default texture,
Flame.tex, can be used to simulate everything between a flickering candle and a roaring torch. When designing a new texture for use with the fire effect, be sure to leave empty space at the top and on the left/right sides so that flames aren't cut off. The alpha channel is used to control transparency. - The texture pickers in the material manager and info dialogs now show preview images.
- Fixed a bug that would cause the file save dialog to crash if there was no selection in the file list.
Build 120 — 20-April-2006
- Implemented the rectangular select tool in the World Editor. It respects the selection mask, and the shift key can be used to add to an existing selection. Because of the different kinds of bounding volumes that some things use, you may select a little more than you expect for a particular dragged out rectangle.
- Fixed a bug introduced in build 119 that would cause geometries not to update properly in the World Editor.
- Fixed a bug in the Texture Viewer tool that was introduced with the new preview box that would cause a crash if a texture was double-clicked to be opened in the file picker dialog.
Build 119 — 18-April-2006
- For fog spaces, you can now select whether to use a constant density or a density that increases linearly with distance from the boundary plane. The linear density function is slightly more expensive (one additional fragment program instruction on NV40+, a surprise considering the extra complexity), but it can look much better when the camera is near the fog boundary.
- Fog spaces now use the occlusion system to cull objects that are completely fogged. In all cases, 1-2 planes are used to cull objects, but the exact configuration depends on the camera location with respect to the fog boundary plane and the density function. In cases where you know that no objects will ever be completely fogged, you can disable distance occlusion for a fog space in the Get Info dialog to save a little CPU processing time that would ordinarily be spent looking for objects to cull. The culling distance varies smoothly with the fog color. For bright fog, the culling distance is set to be the point at which the fog fraction is 1/32, and for dark fog, the distance corresponds to a fog fraction of 1/256. This was done because the human eye can't distinguish between close bright shades as well as close dark shades.
- If the camera is outside a fog space, then the rectangular boundary plane must be visible in order for the fog to be rendered. This is different from previous versions—before, fog would render if the zone containing it (or connected to it) was visible. Existing fog planes may have to be resized to cover the entire area that they affect. It's okay for a fog plane to extend outside its owning zone.
- Added a “confined light” optimization that avoids recalculating light regions for a light source
that moves but is known to stay confined within a certain radius. This is currently used for the torches in
the demo level—the
TorchControllerclass makes the torch light wiggle around a little bit as part of the flickering effect. Previously, the light regions would have to be recalculated every frame, and this involved a lot of portal clipping. Now, slightly larger light regions that are valid as long as the light stays inside its confinement sphere. This saves a significant amount of CPU processing time. - Support for vertex buffer objects (VBOs) has been completed in the Graphics Manager. After several iterations, a good design for using VBOs without requiring them was converged upon. All geometry objects will now store static vertex and index data in VBOs to increase performance. In future releases, more types of objects will take advantage of VBOs.
- Added an opacity map attribute to the material system. This is only used in conjunction with the refraction attribute and controls how opaque a surface is at each texel. Values in the opcaity map are used as a linear interpolation parameter between the diffuse reflection term and the refraction term. White means completely opaque (100% diffuse term), and black means completely transparent (100% refraction term). Opacity can either be stored in its own texture map, or it can be stored in the alpha channel of the diffuse map, normal map, gloss map, or emission map.
- The gloss map attribute is now applied to the reflection attribute. Gloss can also come from the alpha channel of the diffuse map, normal map, emission map, or opacity map.
- The Collada importer can now handle skinned meshes placed anywhere in the node hierarchy, whereas before, a skinned mesh was expected to be at the top level.
- The Collada importer will now strip out dead nodes. A “dead node” is a node that doesn't instance any object, doesn't have any subnodes, and isn't a bone. Collada exporters tend to write a bunch of these out because they're used to represent various items in the art package, but they don't carry any useful information. Importing them into the engine just wastes space and time.
- Made multiple improvements to the Time Manager so that it reports time values that are as accurate as possible.
- The Properties tab will now show up in the World Settings dialog so that properties can be assigned to the root zone. This allows games to store custom properties on the root zone for global level settings.
- Added a loop count box to the Play Ambient Sound script method.
- Added a preview box to the file picker for the Texture Viewer tool.
- Fixed a typo introduced in build 117 that causes rendering problems when multiple remote portals were visible at once that rendered to the same buffer.
- Made lots of improvements to the Mac project file. There are now two configurations named “Debug” and “Release”. Precompiled headers are used in a better way now, so build times are much faster.
Build 118 — 28-March-2006
- Added a validation function to the
PropertyRegistrationclass so that property subclasses could identify which types of nodes they are supposed to be used with. This works in the same way that the validation function works for controllers. The validation function is only used to determine which available properties to list for a particular node in the Get Info dialog. - Fixed a problem in the Collada Importer tool that would cause polygons having more than four vertices to import incorrectly.
- Fixed a problem in the Texture Importer tool that was causing manually created cube maps to import incorrectly.
Build 117 — 20-March-2006
- The standard appearance of the graphical user interface has been overhauled. The new design doesn't have so much color in it and uses the more familiar dark-on-light shading for text. The fonts have been updated to look nicer and be more readable.
- Added the
$backgroundColor,$windowColor, and$hiliteColorpermanent variables to the Interface Manager. These can be changed in theData/CFG/Variables.cfgfile to alter the default appearance of the user interface. Each variable is interpreted as a 6-digit RGB hexcode with 8-bits per component: RRGGBB. - Added window resizing to the Interface Manager. The World Editor and Model Viewer windows can now be
resized by dragging the little widget in the bottom-right corner. As a window is being resized, it
receives calls to the virtual
SetWindowSize()function so that a window can reposition its contents. - Added some new functionality to the
EditableTextElementinterface class. It can now accept more text than its size allows it to display (when thekEditableTextOverflowflag is set), and you can now use the shift key with the left and right arrows to select text. - The standard file picker dialog now allows you to navigate into subdirectories. The popup menu at the top of the dialog contains each directory in the path leading back up to the original directory for which the file picker was created. Clicking the button with the 'go up a directory' icon or hitting Ctrl-Up-Arrow navigates to the enclosing directory.
- Added a checkbox to the Save As dialog in the World Editor that lets you strip out the editor data when saving a world. Stripping out the editor data removes information about things like viewport configurations, material names and previews, show/hide state, etc. When the strip box is checked, it only applies to that one save—subsequent saves will continue to write the editor data. The intent is that users will save different copies of final worlds that are stripped down for gameplay.
- Added the Connect to Root Zone item to the Node menu in the World Editor. After selecting a connector, this item connects it to the infinite root zone of the scene.
- Added the ability to set the number of skybox subdivisions in the World Settings dialog.
- Added a "Developer Panel" window that provides an interface for generating texture resources for
lights, environment maps, etc., and also provides an interface for turning some rendering diagnostics
on and off. The developer panel can be opened by selecting Developer Panel from the Tools menu or by
typing
devin the console. This replaces thegentexcommand that was previously used to generate textures. - Added a
Preprocess()function to theMethodclass. This allows a method to perform precaching if it wants to. - Made some miscellaneous optimizations in the light and shadow culling code.
- Fixed a problem that could cause a recursive chain of multiple remote portals to render incorrectly.
- Fixed a problem that would cause a vertex program error if refraction and fog were used in the same material.
- Worked around a driver bug that was causing the glow shader to drop into a software path on some GeForce FX GPUs. Glow should now render at full speed on all Nvidia hardware.
Build 116 — 28-February-2006
- The Get Info dialog in the World Editor has been expanded to include controller and texture mapping settings that used to be shown in separate windows. The Get Info dialog now has multiple tabs, and the Controller tab is always present. Geometries now have tabs for geometry building flags, rendering flags, collision properties, and texturing settings.
- There are now a few additional tabs in the Get Info dialog: General, Properties, and Connectors. The General settings pane allows you to set the name of any node and, for certain types of node, to specify whether it is initially disabled. The Properties pane lets you assign any kind of properties defined by a game to a node. (More about properties below.) The Connectors pane lets you define a list of connectors that can be linked to other nodes. (Connectors are described in the next item.)
-
Implemented a general node connecting interface in the World Editor. There is now a “Select and Connect” tool that causes available connection sites for a node to be displayed along with connectors that point to their targets. Several types of nodes have built-in connectors that can be linked to other nodes for specific purposes, and any node can have an unlimited number of custom connectors defined for it in the Connectors pane of the Get Info dialog. Connectors are identified by a 32-bit (four character) identifier. The built-in connectors are as follows:
- A zone has two connectors: one called AMBT that connects to an ambient space, and one called FOG that connects to a fog space.
- A portal has one connector called ZONE that connects to the portal's destination zone.
- A light has one connector called SHAD that connects to a shadow space.
- A trigger has one connector called TARG that can connect to any type of node.
To specify the target of a connector, click on the Select and Connect tool (or press 5) and then select a node for which you want to set an outgoing connection (but don't select the target yet). The available connectors will appear in little boxes containing their identifiers with icons showing what types of node they can be connected to. Click in a box to select a connector, and it will change color and get a thicker outline to indicate that it's selected. Then select the target node and choose Connect Node from the Node menu (or just hit Ctrl-L). You will see a yellowish line with arrowheads pointing from the connector to the center of its target. Connectors from multiple nodes (one connector each) can be selected by using the shift key. This can be useful if, for instance, you want to connect a bunch of zones to the same fog space. (You don't have to use the shift when selecting the zones, but just when selecting the connectors in the zones.) A connector can be broken by selecting it and choosing Unconnect Node from the Node menu (or hitting Ctrl-U).
- There is now a connection marker that can be used simply as a container that holds connectors. This could be useful in cases such as when multiple triggers need to activate the same script. (This replaces the collection node mentioned in the notes for build 112.)
-
Added a reference marker node type that lets you reference an external world resource from within a scene graph. In the world editor, the reference marker is represented by a world icon with crosshairs running through it. The position where the crosshairs meet determines where the origin of the external world in placed. The referenced world resource is set in the Get Info box for the reference marker.
When a world is loaded, reference markers cause external worlds to be brought in as nonpersistent nodes so that they are not saved as part of the referencing world. If the same world is referenced by multiple reference markers, then they share the same object storage; that is, they are instanced. Reference inclusion is not recursive—referenced worlds within referenced worlds will not be expanded. This avoids problems with cyclic references, etc.
There is a toggle button in the World Editor that shows or hides referenced worlds. When it's off, you just see the reference markers. When it's on, you see the reference markers and the instances of the worlds that they reference. Moving or rotating the reference marker also affects the included world (because the included world is attached to the marker as a subtree). You cannot select any part of a referenced world because it doesn't really belong to the world that references it. Changes to referenced worlds must be made in the original file. If you change a referenced world while another world referencing it is also open, you can toggle the referenced world button off and back on again to see the updated version.
-
Implemented a general scripting architecture. The scripting system is not based on a scripting language, but is instead designed to execute a tree of operations called methods that can be assembled graphically in the World Editor. A script is assigned to a node by selecting the script controller in the Get Info dialog and then opening the script editor. Details about the script editor can be found on its wiki page.
A script is normally executed through the activation of the script controller. It is also possible to make a script run immediately upon loading a world by checking a box in the Controller pane of the Get Info dialog.
By default, a script runs on all machines in a multiplayer game. It can be made to run only on the server, but then each of the script methods must somehow communicate any actions that need to take place on the client machines. This is normally done by sending controller messages from within custom script methods.
This is only the first version of the scripting system, and additional features will be added in future releases. In particular, conditional execution is script methods is not present, but will be added later. The current scripting system is very extensible because it's possible for the Game Module to define custom script methods, and these appear in the script editor. There is also a new mechanism for accessing controller functionality from within scripts by calling “function” objects, described next.
- Added the ability for controllers to define subclasses of the
Functionclass that expose various kinds of functionality that can be accessed from a script. There is a script method named “Call Function” that lets you select a function belonging to the controller attached to the method's target node. When you select a function, its configurable settings appear, and these act as the function's parameters. - Trigger node functionality has been enhanced. A trigger will now call its target controller's
Activate()function whenever it transitions from the unactivated to activated state, and it will call its target controller'sDeactivate()function whenever it transitions from the activated to unactivated state. A trigger can be set to automatically disable itself that first time it is activated, and in this case theDeactivate()call is not made. It's also possible to specify that a trigger is to be continuously activated as long as an eligible node intersects it, in which case theActivate()function is called every frame until the trigger is unactivated. - The Game Module can now define
Propertysubclasses for whatever reason it needs to, and these can be exposed in the World Editor under the Properties tab of the Get Info dialog. - Finished implementing the
Configurablebase class. Different types of classes that are capable of displaying a configuration interface in the World Editor are subclassed fromConfigurable. Currently, the classes that have the configurable functionality areController,Property,Method, andFunction. A configurable class specifies that it has one or more settings that need to be presented to the user at the appropriate time. There are several types of built-in settings: a boolean (check box) setting, integer/float (slider) settings, a text box, a popup menu, a color box, and a resource picker. New types of settings can be defined by the Game Module. - Added a movie controller that plays a QuickTime movie into any of the texture map material attributes.
The
MovieControllerclass exposes twoFunctionobjects that can be used to play or stop movies from a script. A movie can also be played immediately upon loading a level or it can be played in response to a trigger activating the movie controller. - Added the
MovieElementclass that plays a QuickTime movie into an interface element. - The
Sourcenode has been updated with more complete functionality. Sound sources can now be placed in a world in a dormant state until they are explicitly played. There are two script methods, “Play Sound Source” and “Stop Sound Source” that play/stop a source node connected to the script's owning node. - Implemented a particle rendering technique that I call “sprite quads”. This allows the sprite rendering hardware to be used to render an arbitrarily-oriented quad inside a screen-aligned point sprite. The benefit is that only one quarter of the vertex information needs to be transferred to the GPU for each quad. The expense is a small increase in fill, but this can be alpha-tested to avoid the final write. This technique was used with excellent results in a PS3 technology demo, and it works very well on Nvidia hardware. Unfortunately, the OpenGL spec requires that point sprites be entirely clipped if their centers go outside the view frustum. Nvidia has ignored this requirement (which is good), but ATI adheres to it by clipping point sprites in software (which also means they perform the vertex transform in software). This could make the whole sprite quad technique somewhat useless unless an OpenGL extension can be agreed upon to allow point sprites to be clipped as if they were quads. Of course, with the forthcoming geometry shaders, none of this will really matter.
- Made several improvements to the joystick support in the Input Manager. More to come, including direct access to the Xbox 360 controller data.
- Added the
SetMousePosition()function to the Interface Manager. - Added a “world time multiplier” to the Time Manager that can be used to control the rate at
which time passes in a game world. The multiplier is initially 1.0 and can be changed by calling the
TimeMgr::SetWorldTimeMultiplier()function. The functionsTimeMgr::GetDeltaTime()andTimeMgr::GetFloatDeltaTime()now return world time, which is the actual time that has passed multiplied by the world time multiplier. You can still get the unaltered actual time that has passed using the newTimeMgr::GetSystemDeltaTime()andTimeMgr::GetSystemFloatDeltaTime()functions. - Removed the
GeometryControllerclass. A controller which can be assigned to a geometry node no longer needs to be subclassed fromGeometryController. - Settings for the fluid controller and cloth controller can now be accessed in the Controller pane of the Get Info dialog.
- Added the
MoveSubtree()andDescendant()functions to theTreeclass. - Added the Strong AA check box to the Font Generator tool. This causes partially filled pixels to be weighted more heavily so that small font sizes can be made more clear.
- If the
GL_EXT_timer_queryextension is available (currently, only on Nvidia hardware), then the frame rate window will now display a second graph that shows the amount of time spent rendering on the GPU. This shows the actual GPU load regardless of whether vertical sync is on or off, and it can highlight time spikes that happen only on the CPU.
Build 115 — 12-January-2006
- This is a tune-up build that corrects some existing problems, most of which are rather minor, and makes various improvements in the sample game module.
- Changed the way that grenades behave in the game module. Previously, the grenade controller determined that a grenade should stop when it collides with something if the velocity component along the collision normal was small enough. This caused the grenades to stick to surfaces if they were shot at a low enough angle even though they still had a lot of speed tangent to the surface. The grenade controller now takes the tangent velocity into consideration and won't stop a grenade that's still travelling too fast.
- Modified the
CharacterControllerin the engine module andFighterControllerclass in the game module so that they allow the player to jump if he is within a certain distance of the ground instead of requiring that he actually be on the ground. Previously, a character running around on an uneven surface (like terrain) would have a hard time jumping because he frequently falls for very short distances and wouldn't technically be standing on the ground during those times. - Made some changes to the
CharacterControllerthat prevents the character from missing collisions with the terrain. However, the character can now get stuck in some corners if you try hard enough. I've come to the conclusion that using a curved surface for collisions against an arbitrary triangle mesh with smooth sliding is inherently non-robust, so the current system is temporary and will be replaced. - Moved the
SpectatorCameraandBenchmarkCameraclasses into the engine module and tweaked them a little bit. - The
MarkingDatastructure used to be nested inside theMarkingEffect, but this was a little unwieldy. It's now defined outsideMarkingEffect, so any previous declarations ofMarkingEffect::MarkingDataneed to be changed to justMarkingData. - Fixed some bad collision settings in the demo level.
Build 114 — 9-January-2006
-
Fog has been completely redesigned in this build. Fog is no longer a property of a zone, and any existing uses of the old fog property will disappear from worlds opened in this build. Fog is now controlled by placing a fog space node into the scene. The zone containing the fog space node is automatically fogged, and other zones may be linked to the fog space so that one fog space can be used to fog areas covered by more than one zone. The fog space itself defines a boundary plane between fogged and unfogged half-spaces. The half-space on the negative side of the plane contains fog, and the half-space on the positive side of the plane is clear. A single formula is used to handle the four possible configurations between a camera and an arbitrary point in the scene. (The camera can either by in the fog half-space or in the clear half-space, and a surface point can be on either side of the plane.) In all cases, the amount of fog applied to a fragment is determined by the distance along the direction from the surface point to the camera that actually lies on the fogged side of the plane. Fog is applied to everything, and it is integrated into the existing rendering passes—there is no post-processing calculation.
A world may contain multiple fog spaces, but only one can be active at any time for a particular camera view with defined results. It's okay for one fog space to be used in a zone directly visible to the primary camera and then for another fog space to be seen through a remote portal. This works because the image seen through the remote portal is rendered from a different camera.
Fog can be rendered in two modes. By default, fog is computed at each fragment to yield an accurate result regardless of the position of the fog plane or an object's degree of tessellation. This can have performance implications, however, so it is also possible to force the fog distance to be computed on a per-vertex basis. Doing this on Nvidia hardware is especially fast because it can take advantage of dedicated fog silicon that reduces the per-fragment cost to virtually zero (but this has limited precision). Since the interpolated fog distance for large polygons can get quite inaccurate far from the vertices, calculating fog distance per-vertex generally requires higher levels of tessellation. In this mode, it's also necessary to split polygons at the fog plane so that positive fog distances don't get extrapolated outside the fogged half-space. The geometry flags now contain a setting for splitting polygons automatically at the fog plane referenced by the geometry's owning zone.
A fog space is created in the editor using the fog space tool in the light/sound/space panel. Only the plane of the fog space matters—the rectangular size can be anything you want. Additional zones can be linked to the fog space by first making the fog space the current target (Ctrl-T), then selecting one or more zones, and finally choosing Link to Target (Ctrl-L). The zone actually containing the fog space does not need to be explicitly linked.
As a performance optimization, direct portals may have a flag set that prevents fog from being rendered through them. This is useful if the portal looks into a zone containing fog, but it is known that none of the fogged area can be seen from the other side of the portal.
- Occlusion portals are now fully implemented. (These have been available in the editor, but were ignored by the visibility code in previous builds.) Also known as an antiportal, an occlusion portal prevents objects that are behind it from being rendered. An occlusion portal is not linked to a destination zone and is usually placed in the middle of a zone inside some large object that blocks a lot of things from view. Any geometry, light, portal, or effect that is completely blocked by an occlusion portal from the camera's perspective is not considered any further for rendering. In general, occlusion portals should be as large as possible so that culling is maximized, and the number of occlusion portals visible at any one time should be kept as low as possible to minimize CPU calculations. Note that occlusion portals may not always produce big speed improvements where you think they should because of good hardware z-culling.
-
Added the
SetOcclusionProc()function to theNodeclass and modified the existingSetVisibilityProc()function. The procedure installed by theSetVisibilityProc()function now takes a pointer to a singleZoneRegionand must determine whether a node is visible within that region. The procedure installed by theSetOcclusionProc()function takes a pointer to a list ofZoneRegionobjects and must determine of a node is occluded within any of them. See the documentation at http://www.terathon.com/c4engine/doco/WorldMgr/Node.html for details. By default, a node's visibility and occlusion procedures check the node's bounding sphere against a region's bounding planes using the functions provided in theRegionclass. Several geometry primitives override this behavior to use tighter bounding volumes like boxes or cylinders.Ordinarily, a game module only needs to worry about visibility and occlusion procedures for special effect classes derived from the
Effectnode. An effect needs to either provide a bounding sphere (by overriding theNode::CalculateBoundingSphere()function) or needs to install a visibility procedure and an occlusion procedure. TheRender()function of an effect no longer needs to test for visibility and will only be called if the effect is enabled, visible, and unoccluded. See the documentation at http://www.terathon.com/c4engine/doco/EffectMgr/Effect_Render.html. -
Improved the way in which multi-zone effects are handled. Because some special effects can span mutiple zones (notably particle systems like smoke trails), their eligibility for rendering can't be determined solely based on whether their owning zones are visible. Being a scene graph node, an effect node can only be in one zone at a time, but there is a mechanism that lets any number of other zones reference the effect so that it will be considered for rendering whenever those zones are visible. By default, an effect is referenced by the zone that owns the effect node. If the effect defines a bounding sphere (by overriding the
Node::CalculateBoundingSphere()function), then any zone into which that sphere extends through portals also references the effect. This ensures, for instance, that particles from an explosion that fly into another zone are visible to someone who can't see the zone containing the effect node itself.An effect may override the default zone-referencing behavior by disabling the post-bounding-sphere calculation. This is done by adding the following line to an effect's constructor or
Preprocess()function:SetActiveUpdateFlags(GetActiveUpdateFlags() & ~kUpdatePostBounding);If this is done, then the effect is responsible for explicitly adding references to zones from which the effect could be visible. The
Effect::AddEffectReference()andEffect::RemoveEffectReference()functions are supplied to do this. It is often convenient to call these from within overriddenEnterZone()andExitZone()functions. For more details, see the documentation at http://www.terathon.com/c4engine/doco/EffectMgr/Effect.html. - The Display Manager will now choose the highest refresh frequency available for any particular resolution when in fullscreen mode. Previously, it let the driver choose the frequency, but this seems to have always resulted in the somewhat low 60 Hz refresh rate.
- Made various vertex program and fragment program improvements after observing how the driver was compiling them on both Nvidia and ATI hardware. The engine now contains some conditionally-compiled hooks that lets an external tool capture the actual hardware command buffer, from which it's possible to gain a lot of information about exactly what is being done on the hardware. (Sorry, this tool cannot be released.)
- The command console now stores a small command history that can be accessed with the up and down arrows.
- Changed what used to be called "focal length" for a spot light to "apex tangent". The term "focal length" was borrowed from the same property that a camera has in relation to its field of view, but it's a little confusing when it's applied to spot lights. The apex tangent t is the trigonometric tangent of half of the horizontal field of illumination. That is, at a distance t from the spot light's center in the direction that it's pointing, the pyramid of illumination has widened to one unit left and right.
- A new tool is shown in the World Editor that will let you select objects by dragging out a box, but this is not yet implemented and will have no effect if used.
- Fixed a small bug in the World Settings dialog that always caused the skybox glow enable box to be unchecked when the window is opened. (The skybox would still get the glow property if you checked the box and closed the window.) Also fixed a bug that would make it impossible to disable glow for a geometry once it was enabled.
- Fixed a minor bug in which the brightness setting in the Graphics Options dialog was not being saved unless you changed the display resolution or fullscreen setting. Also made it so that changing only the brightness and then cancelling the dialog would restore the original brightness.
- Fixed a bug that would generate a bad fragment program if specular color, microfacet color, and gloss map were all being used in a material.
- Fixed a bug that prevented depth maps from being created in the previous build due to all of the shader system changes.
Build 113 — 26-December-2005
- WARNING: It is strongly recommended that you backup
WLDandMDLresources before upgrading to this version of the code. The geometry serialization format has changed a little, and existing resources will automatically be updated to the new format when they are loaded and then saved (see next item). Although no problems are anticipated, a backup of your old files should be kept until you're sure the updated files are able to be loaded. - The geometry data format has been changed a little bit, and some extra information has been
removed from the array structures stored in the
GeometryLevelclass. The engine will still read the old format, but it is recommended that all worlds and models be updated to the new format. To update a world, all you have to do is open the world in the editor and then just save it. You can update a model by opening it in the model viewer and saving it using the Save item under the Model menu.WLDandMDLfiles will generally shrink by an average of 3% to 7%. All new files are saved in the new format. - Support for NV2x hardware has been removed, along with several thousand lines of shader code. The result is that the rendering core of the engine is much cleaner, the data structures used for shading are smaller, and several ugly pieces of special-case code have been removed. A lot of work had been put into the NV2x shading code a few years ago, so it's sad to see it go, but after careful consideration, it was decided that it was bad for the engine's future to keep it around. Some of the reasons for the cut were 1) we never supported ATI hardware from the same generation, 2) the NV2x shading code was the only rendering path that required multiple passes per light, and 3) Nvidia has not implemented FBO functionality for NV2x chips.
-
This build includes the first release of the Collada format import tool. This tool supports version 1.3.x of the Collada format, and version 1.4 will be supported once the specification has been finalized. Collada export plugins for various content creation packages can be found at the following locations:
Maya
https://collada.org/public_forum/viewtopic.php?t=2413D Studio MAX
https://collada.org/public_forum/viewtopic.php?t=255XSI
https://collada.org/public_forum/viewtopic.php?t=242Blender
http://sourceforge.net/projects/colladablender/The Collada export plugins write files with the
DAEextension. Place these in theImport/DAE/directory, and they will be found by the Collada import tool. To import geometry from a Collada file, select Import Geometry from the World menu in the world editor. The import tool will recognize and import the node hierarchy, instanced geometries, instanced light sources, skinning information, material information, and animations.Once something has been imported into the world editor, it can be turned into an entity by using the Export Model command under the World menu. You can make changes to the imported geometry first if necessary. An exported model can be opened in the model viewer, and animations can be applied using the Import button. Animations for a particular model need to be stored in a subdirectory having the same name as the imported model. For example, if you import a Collada file named
Monster.dae(in theImport/DAE/directory), then all the animations for that model should be stored in theImport/DAE/Monster/directory.The import dialogs for both importing geometries and animations have a popup menu at the bottom that lets you select an import tool. The Collada importer is active by default, but the old 3DS Max importer is there as well. When you select the Max importer, the source directory will change to
Import/C4G/(for geometries) orImport/C4A/<name>/(for animations).Note: There appears to be a bug in the Collada export plugin for 3D Studio Max that generates bad skinning data. This is an issue with the export plugin provided by Autodesk and is beyond our control. Until the issue is resolved, you still need to use the old Max plugins for skinned models. (Skinned models exported from Maya work fine.)
- Animation interpolation has been improved, and it is now possible to change the animation rate.
The
Entity::SetAnimationRate()function sets the animation rate in frames per millisecond. - Added a new particle system feature that places particles at infinity. This is useful for placing
objects infinitely far away in the sky. Specifying the
kParticleSystemInfiniteflag for a particle system will cause the particles to be rendered at infinity, and the radius of each particle is then interpreted as a percentage of the horizontal field of view. - The
StarFieldparticle system has been added to the sample game module. It reads star positions and intensities out of aFLDresource and generates a particle system that places the stars at infinity in the sky. Currently, the positions of the 12,000 brightest stars visible from Earth will be read from the file. A star field is placed in a world by adding a location marker with the "Star field" type. An example world named "Earth" has been included which contains two spheres representing the Earth and the moon, and the star field. - Support for framebuffer objects (FBOs) has been added to the Graphics Manager. Currently, this
will only be used on Nvidia hardware under Windows because they are the only ones who have
implemented it to a usable degree (meaning they support
EXT_packed_depth_stencil). This build includes a glow post-processing effect that uses the FBO functionality, and more effects will be added soon. - Implemented a glow post-processing effect. Glow is automatically applied whenever a glow-enabled object is rendered in the scene. Currently, a skybox can be made to glow by checking the "Enable skybox glow" box in the World Settings dialog. The textures used in a glowing skybox should contain alpha channels representing the glow intensity. Glow for ordinary geometries is determined by the emission attribute in their materials. The emission alpha determines the glow intensity, and this is taken from the emission color or emission texture (or the product of the two if they are both present). For a geometry to glow, the "Enable emission glow" box must be checked in its Get Info dialog.
- There is now a new alpha channel format that can be selected in the Texture Importer tool called "Glow Intensity". This should be selected for textures used as emission maps or skybox faces that should have the glow effect applied to them.
- Several global rendering options have been exposed in the Graphics Options dialog. Among them
are control over bilinear/trilinear/anisotropic texture filtering and enable switches for
parallax mapping, microfacet shading, and higher-quality bump mapping. Some of these options
were previously controlled using the
$featureDisableMaskvariable, but each option now has its own variable (and$featureDisableMaskhas been removed). - Microfacet shading (Cook-Torrance) is now fully implemented for all light types.
- The
CharacterControllercode has been updated to handle some nasty corner cases, and a lot of the functionality that used to be in theFighterControllerclass of the sample game module has been moved to theCharacterControllerbase class. More tweaks are planned for this class in near-term releases. - Two new functions,
LookAtPoint()andLookInDirection(), have been added to theCameraclass, and they do exactly what they sound like they do. For details, see the documentation at http://www.terathon.com/c4engine/doco/WorldMgr/Camera.html. - Added the
C4Spatial.hfile that contains generic structures for octrees, quadtrees, bintrees. - Added the
AlignedBoxclass to theC4Bounding.*files to represent an axis-aligned bounding box. - Added the
ProjectOnto()function that projects one 2D/3D/4D vector onto another. - It's now possible to set a clear color in the world editor. Normally, the color buffer is not cleared before rendering because the whole screen will be filled by geometry. However, in some scenes such as a space environment, it's convenient to be able to specify a clear color instead of using a solid-color skybox. If a clear color is selected in the World Settings dialog, the color buffer is cleared to that color before rendering occurs for each camera. Note that using the clear color will prevent remote portals that render to the primary buffer from working.
- Added the Select All by Mask command to the Edit menu in the World Editor. Unlike the ordinary Select All command, this respects the current selection mask.
- Added a toggle button to the World Editor for showing backfaces in wireframe. This also allows planar geometries to be seen when viewed edge-on in an orthographic viewport.
- The world editor now generates picking rays that account for the bounding sphere of the whole world. Some huge worlds were experiencing problems because the 2km range of the previous rays was too small, causing some items to be unselectable.
- Leak detection functionality in the Memory Manager has been improved. There is now a preprocessor
define at the top of
C4Base.hcalledLEAK_DETECTIONthat controls whether this functionality is enabled. To turn leak detection on, setLEAK_DETECTIONto 1 and recompile. When you run the engine with leak detection, exercise all of the code you want to test, and then quit the engine. Right before exiting, the engine will write out the fileleaks.txtin the same directory asC4.exe. This file contains a list of unfreed memory blocks along with the allocation count, filename, and line number at which each was allocated.
Build 112 — 15-October-2005
- This build includes a heavily commented sample game module called "Skeleton" that represents
nearly the minimum amount of code that needs to be written to have a working game module. You
can tell the engine to load this game module by editing the file
Data/CFG/Variables.cfgand changing the value of the variable$applicNameto "Skeleton". To get the primary game module back, change$applicNameto "Game" again. -
Implemented a large amount of new collision detection functionality. The existing function
World::DetectCollision()is still present and should continue to be used for line-of-sight tests and sphere-environment collision tests. There is now a new function for capsule collisions,World::DetectCapsuleCollision(), and it detects collisions between an arbitrary swept capsule and the environment. Both of these functions are precise to the polygon level and are implemented using continuous techniques (as opposed to iterative techniques). This means the collision detection is tunnel-proof.For most types of moving objects, it is now best to use the new Collider class for collision detection instead of calling the above functions directly. The Collider class has two subclasses,
SphereColliderandCapsuleCollider. Each controller class corresponding to a moving object should inherit from one of these two Collider subclasses. Then the controller'sMove()function simply specifies the starting position and delta for the current frame. After all controllers have moved, the collision detection among all colliders is performed, and then theTravel()function of each collider class is called. At this point, the Collider class contains a collision state that indicates whether a collision occurred and, if so, whether it was with the environment or another collider. The implementation of theTravel()function can do whatever it wants in response.See the
BallControllerclass in theSkeleton.*files for an example showing how to use the new collision system. To see a cool stress test, load the world called "Test" while running the Skeleton application module by enteringload testin the command console. (Nothing will happen in this room if running the big game module.)Also see the documentation for the
Colliderclass at http://www.terathon.com/c4engine/doco/Controller/Collider.html. - The engine module now contains stock controller base classes for basic projectiles and
characters. The
ProjectileControllerclass is subclassed fromSphereColliderand handles the motion of simple projectiles under the influence of gravity and/or through a resistive medium. TheCharacterControllerclass is subclassed fromCapsuleColliderand handles things like gravity, falling off of things, sliding against walls, and climbing ramps. -
Updated the sample game module to use the new collision system and controller base classes. Projectiles will now hit each other, so it's possible to shoot down rockets, etc. The game module class
FighterControlleris now in a clean state and handles player movement, character collisions, weapon firing, and projectile hits.The game module contains a class called
FighterControllerthat is a subclass of theCharacterControllerand handles more details of the player movement. It's pretty functional right now, but is still a work in progress in some ways. In particular, it doesn't currently spend any time trying to detect whether the character is climbing stairs, but some research is being done to determine whether this is practical and worth the extra computational expense. Right now, it's best to cover stairs with an invisible ramp for smooth character movement.The
FighterControllerdoesn't currently implement client prediction for multiplayer games, but it will soon. The previous code, which was very hacky, has been removed. - Added shader level of detail for parallax mapping. When enabled, the scale of the parallax effect will gradually decrease to zero at the transition point from level 0 to level 1, and parallax mapping is reduced to ordinary bump mapping in level 1 and above.
- Implemented full support for Cook-Torrance specular reflection via the MicrofacetAttribute material attribute. Both isotropic and anisotropic microfacet distributions are supported, but the geometrical attenuation factor has been omitted because it almost always makes an unnoticeable difference. Note: Microfacet shading has been disabled for all types of lights except infinite lights due to some pending changes in the shader building code. It will be fully functional in the next release.
- Added the
$featureDisableMaskpermanent system variable. This has 1-bits for any graphics features that are explicitly disabled by the user. Updated the graphics settings dialog to allow parallax mapping and microfacet shading to be turned on/off. - Added the
kShaderCubeLightInhibitshader flag that prevents a cube light projection from being rendered on a geometry. This is useful when applied to the geometry surrounding a cube light source (that is actually casting the projected shadow) so that it doesn't receive its own shadow. - Updated the Sound Player tool. It now displays the wave being played as it used to under the old windowing system, and there is a volume control.
- The sound mixer now supports 22.05 kHz stereo sounds, both streaming and non-streaming. All mono and stereo sounds that are either 22.05 kHz or 44.1 kHz are now supported.
- Modified the free camera tool in both the World Editor and Model Viewer so that the camera accelerates like the spectator camera does.
- Added the
PropertyObjectclass. This serves as a shared container for an arbitrary list of properties, and it can be attached to nodes just like material objects. Thus, changing any of the properties affects all nodes using the property object. There's currently no interface for this in the World Editor, but it will be present in a later release. - Added the
Collectionnode. This is a container that holds a set of key/node pairs. There's currently no interface for this in the World Editor, but it will be present in a later release. - There is now a new
EnvironmentMapAttributethat can specify a texture map that will override the environment map assigned to the zone containing an object. This attribute should be applied in addition to theEnvironmentAttributeto take effect. It can be specified in the Textures pane in the World Editor's material manager. - Added a constructor and
Set()overload for theVector4Dclass that take aVector3Dand aPoint3D. These are interpreted as the normal direction of a plane and a point lying in that plane. The normal is copied into thex,y, andzcomponents, and thewcomponent is given the value-Dot(n, p). - All of the random number functions have been moved into the
Mathnamespace. This includesRandom(),RandomFloat(),RandomUnitVector(),RandomUnitQuaternion(),GetRandomSeed(), andSetRandomSeed(). These functions either need to be qualified withMath::or the statementusing namespace C4::Math;needs to appear in any source file that uses them. - Defined an integer type called
naturalthat corresponds to the natural register width on the target machine. This type should be used for variables which are expected to be kept in CPU registers so that arithmetic is performed on them at the machine's natural size, avoiding extra sign extensions or high-word clears. Defining the natural type is primarily a performance optimization for the 64-bit PowerPC architecture. - Made lots of various minor additions and improvements to the primary game module.
- The Visual Studio project files have been updated to be easier to move to different machines and easier to convert to later versions.
- This release contains temporary plugins for Maya, but these are going to be replaced by the Collada format in the next release.
- The source texture map for the terrain in the demo is included in this release. It's path is
Data/TEX/terrain/Lake.tex.
Build 111 — 26-July-2005
- Fixed a minor glitch in the light region determination code that could cause light regions generated by large portals to be too small. This only affected point lights, and could cause the illumination to drop out too early as the camera turned away from the portal.
- Implemented a new diagnostic mechanism that displays light regions. This is toggled on/off
by using the command
rgnsin the command console. The green lines that are shown represent the edges of the light regions generated by portals for every light source that can shine through a portal. Only geometry intersecting any particular light region is considered to be potentially lit by the light source generating the region. - Changed the
Controller::Activate()function so that it takes an additional parameter that indicates which trigger node caused the controller to be activated, if any. See the function documentation at http://www.terathon.com/c4engine/doco/Controller/Controller_Activate.html. - Fixed a small problem in which the BoxGeometryObject primitive would not generate the right polygons if the number of subdivisions in the x and y directions were not the same.
- Added the
kNodeGenerateInhibitflag to the flags that can be set for the Node class. This flag prevents the node from participating in resource generation (shadow maps, environment maps, and ambient maps). - Added a flexibility array to the fluid geometry. This controls how much each vertex in a fluid is able to move so that non-square borders can be used with a fluid surface.
- Added the option to include an uncompressed fallback format when importing a texture map and using S3TC compression. (If a texture resource contains both compressed and uncompressed images, only the one that's actually used gets loaded.)
Build 110 — 5-July-2005
- Made some adjustments so that the projects will build correctly on the Mac using Xcode 2.0.
- The main project now compiles and links successfully under Dev-cpp. However, there are still issues preventing the game module and tools from being linked to the main executable.
- Removed the requirement that the
GL_ARB_fragment_program_shadowextension be available in order to get the ARB1 shader path. The Mac and some notebook graphics drivers don't expose this and it forced the engine into the NV20 path. - Added a safety mechanism to the string table resource so that attempting to retrieve a string whose identifier doesn't exist causes the string "<missing>" to be returned.
- Added support for 24-bit TGA files in the Texture Importer tool. It will now accept 16-bit, 24-bit, and 32-bit images, either compressed or uncompressed.
- Removed an experimental deferred lighting effect. Not enough bang for the buck.
Build 109 — 23-June-2005
- Added the
PaneBoxElementinterface element. This provides a tabbed box that can be used for switching among panes containing different groups of settings. - Rearranged the material attribute settings to use multiple panes.
- Added reflection and refraction settings to the material manager. These can be used with remote portals by specifying that the image rendered a remote portal is to be directed to either the reflection buffer or the refraction buffer. There is no NV20 fallback for this functionality yet.
- Added support in the Graphics Manager and for reflection and refraction buffers. A remote portal can now indicate that what it sees can be rendered to one of these buffers instead of the primary buffer. The buffers can then be used as texture maps in the primary rendering pass so that effects like bumpy reflection and refraction are possible.
- Added a feature mask the the Graphics Manager. This allows certain rendering features to be enabled or disabled for some extra performance tuning ability on lower-end GPUs. It's also used for disabling features that aren't shown in the World Editor.
- The
Unpackerclass now stores the version number from the file being loaded. This allows unpacking functions to perform certain actions only if the version number is high enough so that backwards compatibility is more easily maintained. - Changed the popup menu in the World Editor's controller assignment window to a list box.
- Added registration mechanisms for location and position markers. Types of locations and positions don't have to be registered, but if they are, the World Manager displays them in a list box now in the Get Info window.
- Renamed the
Controller::Create()function toController::EnterWorld()to make it more clear what it's actually used for. - This build includes an Xcode project file for MacOS X. The engine runs full-featured on the Mac, build there are some issues with Apple's OpenGL implementation that will never be resolved unless a miracle occurs and Apple starts to care about games and middleware.
- Preliminary fog functionality is now implemented as a post-processing effect. This works fine on Nvidia hardware, but currently gets stuck in a software mode under ATI drivers. We have just been informed that ATI hardware does not support copies from the depth buffer to a texture, so we need to develop an alternative. Also, there is no NV20 fallback yet.
- Finished implementing good menu bar behavior. Mouse interaction with pulldown menus now works like you would expect.
Build 108 — 27-May-2005
- Added the
kLightExternalZoneflag to the LightObject class. This tells the lighting system that the light may not be physically located in the zone that contains the light node in the scene graph. This flag is useful for lights that are attached to other objects (like a character). It's possible for a character to be in one zone, but the light that he's holding to be in a different zone because his arm extends through a portal. Setting the flag allows the lighting system to build the light's illumination tree correctly at the slight expense of having to find the zone that contains the light. - Added a tool tip mechanism to the Interface Manager. Any renderable interface element can now have tip text assigned to it, and this text will appear in a little pop-up box whenever the cursor hovers over the element for half a second. Tool tips were added to all of the World Editor palettes.
- Added mouse wheel zooming to the World Editor. Mouse wheel support was also added to the ListBoxElement class.
- Changed the way that portals are rendered in the World Editor. It's much easier to see a portal now when you're looking directly at its face (perpendicular to its plane) and its edges coincide with scene geometry.
- Fixed a model export bug in the World Editor.
- Added a simple progress bar interface element.
- Added more picking capabilities to the
GeometryManipulatorclass. Previously, only geometries that had collision data could be directly selected because the collision detection system is used to pick geometries in the World Editor. Now, a fallback routine takes over for geometries without collision data that just tests a ray against the triangle soup. - Finished updating the Movie Player tool.










