This is work that was distracting me from exam revision in the end of my BSc in 2001. I was watching various people talk about bandwidth usage on new media and had just completed a game called 'Oni'. Most of the character and small object animation in the game was done via scripts, rather than pre-recorded video or fixed actions the character object “knows”. This allowed the games developers a better simulation of martial arts. It occurred to me the two concepts should be merged.
This project is obsolete, these days I would use HTML5. Please read 1 that article.
Goals of sgfx.
- Similar to games, render 3d models of objects;
- Provide script support to allow the models to animate;
- Setup process so the above this can be distributed as an alternative to MPEG4 video;
- Generate a selection of lighting and shading modules (again to be regulated by the scripting);
- Generate a smaller “network edition”, in the language of my University, Java;
- Generate a more games oriented complete C++ and OpenGL edition;
- The OpenGL edition to run on Linux and Windows NT kernel;
This engine was designed around a rendering pipeline, which moves models into polygons, then visible polygons, then shaded polygons, then perspective clipped polygons then finally written to the screen buffer. I like the idea of pipeline processing, it is friendly towards modular evolving code-bases. As I needed a solution in Java, I was using multiple frame buffers (even in faster languages, you still get better use of memory writes by having multiple screen buffers). I had started an algorithm similar to JPEG chunking, to only repaint the areas of the screen that had been changed.
The engine had “pseudo time” in the form of engine ticks to map the animation against. Loosely a tick is one screen refresh, but practically this doesn't work on slower languages. When I had completed features and was optimising sections of code (most importantly for performance, turn the logging off), I was aiming for twenty five ticks per second. The model transformations in the scripts where applied one step per tick.
I wrote a configuration parser to pull the very mathematical scripts into the engine. I have been using similar parsers for every configuration file since.
At the start of the project I was team working with various other students playing with graphic code. We helped cancel each other bad ideas. Afterwards, this was work I was doing for myself, without deadlines, so project management paperwork was unnecessary. I was trying to build and improve my coding ability, not sell anything. I should read the project to add more content to this page, but the project is not something I anticipate being useful for employment.
I had more urgent commitments, and have never gone back to it. The source has never been “completed” into a releasable state, although is available if you mail me. As the class structure was evolving, I had no time to generate documentation. Caveat emptor.
I started job hunting and had to abandon this project. It was a massive project I was distracting myself with. The other reason for halting was the increase in ADSL1 provision (this was 2001). Bandwidth constraints and need to control timing properly in video was now less important on this new network technology. Since then youtube has entirely proved it irrelevant. If I had completed sgfx, it would be useful for video on phones.
If sgfx was a completed product, I would need to sell the whole project - all rights - to a company to make it onto the market. As an art student, I have sketched all my life; at that point I was still sketching only using an entirely different media. I had no ambition of changing the way media worked, but was playing with graphics.
To write animations with this project you need:
- A text editor
- Some 3D modelling files in a format recognised by the project%, or the software to make them.
- A copy of sgfx, to test the animation with. The early versions are only in Java, as understanding the algorithms involved is a good idea. Later versions will be also provided in C++ using OpenGL and GLUT for rendering.
- A good basic understanding of matrices, and 3dimensional viewing theory (i.e. 3d computer graphics, different to rendering).
- Quite a lot of spare time ;-)
% Other file types can be added if you write the file import code, and the file type has the necessary features (some of the 3d modelling stuff has no colour information). TODO Create list of known file formats
In this manual :
- 'STRING' means a line of text, to be read as text (i.e. a file name), not numbers.
- 'INT' means a number, used in circumstances where there are discreet values. No decimal fractions allowed. Currently only positive integers are used, although this is not fixed.
- 'REAL' means a number, used in analogue circumstances. A decimal point is expected, can be either sign. Internally these are represented as double floats.
The configuration files can be given any name (including the suffix); it will be read a parameter to the final release of the code. Obviously, it must be legal on the target system(s), therefore it suggested to keep them named in the dos fat16 style and all lower case (UNIX habit), as this is the most restrictive.
The files are designed to be human readable (and hopefully human understandable). To this objective, comments have been included in the file spec. Anything typed after a ';' character will be ignored by the parser. In standard programming style, it is recommended to put author, date and purpose (and version on large projects) in a comment at the top of the file.
The file must be in ASCII text (i.e. no word documents).
The files can be in UNIX or Microsoft line terminating style (CR or CRLF). Mac standard (just LF) is not supported and probably won't be. I am not aware of much 3d modelling software for the Mac, so this does not seem a good platform.
The files structure are based on lines (like programming languages). Other than lines, there is no importance in white space (spaces, tabs, new lines). Empty lines, or comment only lines are ignored.
None of the data values are not case sensitive ('yes', 'YES' and 'Yes' are all the same). The letters in the names aren't case sensitive, but the other characters have to be typed precisely.
The data in put in blocks, separated by headers. All of the information before the next header is assumed to be in the block.
A header token must be on a line to its self, and starts with a '#' character. There are two types of header, repeating and non-repeating. For consistency reasons all the header tags terminate in a '_'.
Repeating blocks are distinguished by numbers at the end of their name, and are for things that happen more than once, like actions. The numbers start at 1 and count upwards (i.e. five objects mean 1, 2, 3, 4, 5). The numbers are used for internal references.
Currently available headers (stars indicate repeating headers and are replaced by numbers):
There is a special header named '__SYSTEM' used for meta information. Most of it is not compulsory, but the script language version number is.
Name value pairs are on a line to themselves separated by an equals sign. There are no quotes and any leading or trailing spaces on the data are trimmed.
If the data is multiple values (like a 3dim co-ords, '(x, y, z)'), they are surrounded by round brackets, and separated by commas. This is preferred over using spaces for separators, as it matches standard notation for vertex/vectors, and it is easier to read.
As previously stated the data values are treated as case insensitive, and so converted to upper case. Some times (for instance UNIX file names) this is not appropriate, and can be avoided by using double quotes '"' around the data value. Using quotes also prevents the String.trim() from removing any critical characters in awkward file names.
List of known keywords to the current edition of SGFX.
|FrameSizeX||y||int range 0-screen size||Main_||X axis size, measured in pixels|
|FrameSizeY||y||int range 0-screen size||Main_||Y axis size, measured in pixels|
|Length||y||int range >0||Main_||number of 'ticks' the animation should last for|
|BG||y||4x real (r, g, b, a)||Main_||The red, green, blue and alpha values for the background colour, only RGB colour space available at the moment|
|Loop||n||(yes | 1 | true) | (no | 0 | false)||Main_||Whether the animation should loop forever, restarting on finish|
|VRP||y||3x real (x, y, z)||Camera_||The 3dim coordinate of the vrp, in camera co-ords|
|VPN||y||3x real (x, y, z)||Camera_||The 3dim coordinate of the vpn, in camera co-ords|
|VUV||y||3x real (x, y, z)||Camera_||The 3dim coordinate of the vuv, in camera co-ords|
|Center||y||3x real (x, y, z)||Camera_||The 3dim coordinate of the camera centre in world/global co-ords|
|FrontClip||y||real range >0||Camera_||The minimum distance from the VPN that things are visible|
|BackClip||y||real range >0||Camera_||The maximum distance from the VPN that things are visible|
|WindowDim||y||4x real (xmin, ymin, xmax, ymax)||Camera_||the size of the viewing area in world dim, the values forming opposing points in a square defined in 2dim space (on the film)|
|Version||n||string||Camera_||The version identifier of a specific camera class, if not listed uses a default|
|FOV||y||int range 20-180||Camera_||The number of degrees that the camera can view (i.e. left edge to right)|
|Data||y||string||Object_*||The path to the data file specifying the object. Relative pathing should be from the basic frame or applet class|
|InitPos||y||3x real (x, y, z)||Object_*||The initial centre point of the object, in world co-ords|
|Align||y||16x real to form a 4x4 matrix||NULL | Object_*||The rotation, scaling and shearing of the object, used to translate object co-ords into world co-ords|
|Children||y||int||Object_*||The number of children specified in the data file (used to count the number of internal objects generated)|
|Type||y||'Ambient' | Others to be written||Light_*||The mathematical model used for lighting faces of objects|
|Brightness||y||real range 0.0-1.0||Light_*||The generic brightness of the light, scaled according to the light model|
|Direction||y||3x real (x, y, z)||Light_*||The direction that the 'lights normal' points. This is a mathematical abstraction|
|Objects||n||int* numbers must refer to objects||Action_*||The objects that the action manipulates/changes MUST be present if not a camera action|
|Lights||y||int* numbers must refer to lights||Action_*||The lights that the objects are lit by.|
|Start||y||int range <length in Main||Action_*||The starting 'tick' for the action|
|End||y||int range <length in Main||Action_*||The last 'tick' for the action|
|Camera||y||(yes | 1 | true) | (no | 0 | false)||Action_*||Whether or not the action manipulates the camera or just objects|
|Matrix||y||16x real to form a 4x4 matrix | NULL||Action_*||The matrix used to alter the 3dim points in the object or camera|
Matrices can be defined in two ways, first they can be written as a long string of numbers, just like the 3dim co-ords. Alternately they can be defined as a series of operations. The operations are separated by commas and grouped in brackets, as with the co-ords. If defined as this (text style), they must start with the STRING 'IDENTITY'. All of the other operations are followed by a number (no space gap), indicating the amount of change. After this the following operations can occur (remember that matrix operations are not commutative):
|Token||Operation||Dimension [x |y |z]|
|IDENTITY||Set to an identity matrix||All|
% By default, all of the rotation angles are in radians, as this is Java's default. If the number has a 'd' character on the end, it will be interpreted as measured in degrees, and converted. All the mathematical operations have 19 significant figure accuracy, which should be enough for any one.
Future versions of this project will include/ support (in order of likelihood):
- More lighting models than the useless ambient lighting.
- Better shading with the improved lighting models.
- Text objects to be painted onto the screen with scrolling effects (i.e. 'Animation by Owen.').
- Named objects (i.e. 'LeftLeg' not '4501').
- Functions (for complex manipulations, for example to make a person model walk).
- Mirror surfaces.
- Keyboard/mouse triggers.
- Some sort of public object database, so you can have a house in your animation, without actually making a house model yourself. You can get it out of the database. This will require a strict identifier system, so the objects can be uniformly referenced.
- Object 'genericness' system, so you can have simpler versions of models for lower spec machines. The script loader decides the computing resources and takes the appropriate complexity of model. This is similar to font lists in HTML, where rare/specific fonts are listed, then more common ones (normally ending in sanserif, or other system defaults). It is designed this way so the file will render on most systems, but there is a level of control.