Ubisim is a Quake III Arena (monster-shooting computer game) modification designed to aid the development of systems that integrate the physical and virtual worlds by simulating the physical world of people, the things they interact with, and the places they work, play, and live in. These systems are emerging from the new field of "ubiquitious" or "pervasive" computing. Ubisim works in tandem with WISE, a Java UI and protocol development tool. The entire package is called "ubiwise".
If you want to work on the ubisim code, please just ask questions on the ubiwise-discuss mailing list.
To understand how Q3A works as a tool for ubiquitous computing we need to translate from the world of 3D computer games into the world of ubicomp:
|
Quake III Arena Game
|
Ubisim Simulator
|
|---|---|
| weapons | handheld devices (handy) |
| entities | people and things |
| baseq3/scripts/entities.def ... all possible entities for levels | ubisim/scripts/ubients.def
... all possible entities for scenarios |
| levels | scenarios |
| 8 (eight) Game units (grid) | one foot (12 inches,30.5 cm) |
| level editor, eg GtkRadiant | scenario editor, when used with ubisim/scripts/ubients.def
and fsgame="ubisim" |
| models | 3D presentation of people or things for simulator |
| model editor, eg Milkshape | model editor |
| brush | 3D polygon-faced shape |
Ubisim, like Quake III Arena, has three parts:
G:\ubisim\quake3\quake3.exe
when Q3A is installed G:\ubisim\quake3\ubisim.G:\ubisim\quake3\ubisim.The rendering engine is run with the command line option "+set fsgame
ubisim". This causes the rendering engine to look into the subdirectory
under quake3 for the dlls and media.
The subdirectories of quake3/ubisim include files loaded into ubisim to create the 3D environment. They are organized along the lines of Q3A:
models
.md3d for Milkshape3d editor), a binary file output by the editor for
input to the simulator (.md3), and one or more image files. Milkshape
also requires a .qc file that associates the model with image
files. Generally each object is in a subdirectory.texturestextures
subtree is for shared textures and ones independent of models. For examples,
textures/sfx/logo512.jpg is the background screen for the main setup
menu. These files are .jpg or .tga for Targa (use
32 bit Targa with alpha channel). Textures should be sized to a power of 2
in number of pixels in each dimension, eg 256x128.maps.map for text versions and .bsp
for compiled binary files. These are created by a level editor like GtkRadiant.
If you are careful with matching braces and quotes, then the .map files can
be edited with a text editor then compiled in to .bsps. This approach is prefered
when models or textures are moved to new file names for example.scripts.shader files). Whereever a texture is used to cover
a model, a shader script can replace it. These scripts are commands to a texture
pipeline that allows rapid subframe animation with various timebases. This
is how visual effects like flames are created. Also in the scripts
directory is the important file ubients.def
file that specifies the entites that can be placed into maps.
sound.wav files.levelshotsiconsdemos/+set g_synchronousClients 1; record "file_name",
running the simulator in a way you want recorded, then /+set g_synchronousClients
1; stoprecord. You can play back the demo with the command /demo
"file_name". The files are type DM_66.bindocUbisim has three dlls built from three Microsoft Visual C++ projects contained
in matching subdirectories of the source tree:
qagamex86.dll. This code deals
with simulation of the physical world.cgamex86.dll. This code presents
the physical world to the user.Some source files are shared between the dlls. When they are changed, all dlls
have to be rebuilt. Usually if you are changing pure physics in game
you can just compile it, or if you are changing pure presentation logic in cgame
you can just compile that dll. Generally if the simulator crashes or acts wierd,
try rebuilding all three dlls (eg MSVC++->Build->BatchBuild) before you
panic.
The three DLLs communicate with the rendering engine (in quake3.exe) through
functions prefixed with trap_. These trap
functions each wrap another function called syscall. For example
void trap_Cmd_ExecuteText( int exec_when, const char *text ) {
syscall( UI_CMD_EXECUTETEXT, exec_when, text );
}
Here is more from AnthonyJ as posted on PlanetQuake Forum for Q3 Mod Making:
As for how they're actually implemented...
DLL:
When Q3 loads a dll, it calls "dllEntry()" and passes a pointer to the function "syscall" which is then stored with the dll. This function is a variable parameter function (like printf) which calls the appropriate things within the engine to do whatever is needed. The first parameter tells it which trap function it should do (the numerical constant you found), and then any further parameters are additional params for the syscalls.QVM:
id have bundled an asm file that hooks into the qvm interface to specify the system calls by passing in the correct ids.Basically, dont worry about these files (and dont fiddle), since you cant make meaningful changes.
The Microsoft Visual C++ workspace file for ubisim is in source/ubisim.dsw.
It has the three projects outlined above: game, cgame and q3_ui.
The server-side or physics part of the simulator is in the game project. Here are some of the important files:
.bsp file.
If you look at one of these files you can see that the entities are stored
as text mixed in with binary coordinates for the level.
.bsp. Usually the function is named SP_entityname().As far as developers can tell, two loops control activity: one for game
(server side) and one for cgame (client side). The quake.exe
engine has the loop start and end, it calls vmMain() for the loop body. For
game, the loop body is in G_RunFrame(); for cgame it is in ClientThink_real()
(I think ;-)
Both the client and server are in loops, but these loops are not synchronous.
Q3A has physical prediction code to smooth over the frame-rate mismatches caused
by network connections and different resources available to client and server.
The time-base for the physics is therefore not the frame cycle, but rather it
is a seperate clock maintained by the server. This clock value is held in level.time
and it is measured in milliseconds since the level (aka map aka scenario) started.
There are four kinds of objects in ubisim as inherited from the Q3A code:
game.
The other meaning of "entity" is as a class of entities.
These are listed in ubients.def, the ubisim version
of entities.def. These entities can be placed in the scenario with the GtkRadiant
editor and they can have code attached to them
when they are spawned. For Ubisim purposes the object system is not ideal. Generally I would like to take all of the media names out of the code and treat everything via ubients.def. I don't want entities to magically appear so respawning is disabled. Eventually then I would like to remove the "items" subsystem and make weapons be entities that are marked as "handy" meaning they can be held.
A "weapon" or "handy" entity that looks like HP's 618 digital camera:

spawns[],
Here is a guess. From g_items.c, you can see how to
get a vector (dest) for a point infinitely below an
entity:
VectorSet( dest, ent->s.origin[0], ent->s.origin[1], ent->s.origin[2]
- 4096 );
Then you can ask the engine to trace along the line from
your entity at ent->s.origin to "dest" and give back
any collisions with a bounding box given by ent->r.mins
and ent->r.maxs:
trap_Trace( &tr, ent->s.origin, ent->r.mins, ent->r.maxs, dest,
ent->s.number, MASK_SOLID );
Now you just need to decide of the trace hit the ground
or another entity (eg a train). Hopefully you don't
care, you only care if something is below by 20 units
if( (ent->s.origin[2] - tr.endpos[2]) < 20 ) ...
----------------------------------^ z axis, up and down
+set fs_game "ubisim" +set vm_game 0 +set vm_cgame 0 +set vm_ui 0 +set sv_pure 0
to get the dlls to load. The sv_pure setting allows non-idSoftware
dlls I guess. You can use the last panel of the q3a ui for multiplayer mode
to set it.
g_syscalls.c: void trap_SendConsoleCommand(int exec_when, const char *text );
cg_syscalls.c void trap_SendConsoleCommand( const char *text );
ui_syscalls.c: void trap_Cmd_ExecuteText( int exec_when, const char *text );
are all the same function with exec_when==EXEC_APPEND. They all send
a text string from their respective DLL to the Q3A engine.
Inside there must be some sort of table of commands that can be built-in to
the engine (like "screenshot") or directed to one of the DLLs (like
"centerview"). For the UI DLL at least the internal table seems
to configurable from a mod via the binding mechanism in ui_controls2.c. But
I am guessing. See also the console part of Cvars,
commands, and VM Communication
Links to Q3A related info that may be helpful
These are random older notes as I tried to learn about Q3A modification.
(c) 2002 Hewlett Packard
John J. Barton http://www.johnjbarton.com/index.htm