Format for ascii ani scripts I. Scope of this document. Ani deals with many different types of files on many different machines... and from more than one paint system as well! This document will only deal with the ascii format files which are specific to ani. These currently are the .script and the .poly files. The .poly files are a single "*act INSERT_POLY ..." out of the .script files. The rest of this discussion will hence be confined to the .script files. II. Overview. A script has 3 levels: 1. The script declaration and associated "globals". 2. Beneath this you have the tween - a segment of time. 3. Beneath this are the acts - or motions. The overall design of the "ani assembler" developed at a time when the Amiga drives were very unreliable. Hence ani will try real hard to extract a script from a file (though ani bitches about things that don't seem to fit in.) Partly as a consequence of this you can usually have garbage at the beginning and end, a few binary characters here and there, and \n's \r's pretty much anywhere. Unfortunately another consequence is that it is harder to avoid scrambled lists when reading nonsense than if ani simply gave up.... The tokenizer chops up things by "white space" as per C. Though to look at a file ani puts out you might think new lines were significant. They are not. '#' at the beginning of a line (except very first line - my bug) will make it a comment. The token "*end" is treated as a end of file - useful for debugging. All lines ani puts out start either with a '*' or a tab. If they are a tab they are continuations of the line before. I would like to propose kind of a standard that other programs that want to mix with ani use a similar format but with their own character in place of '*'. Ideally then extensions to ani could parse the parts that go to the tweener portion most simply, and you could use a slightly modified grep to separate a file into it's components. Currently ani treats parenthesis as white space. They are included only for human readability. Clearly an ascii format is not suitable for raster data. I really pray that people will start using ascii formats wherever possible. It makes it so much easier for programs to work together. III. Script level. i. Script declaration: *script name_of_script number_of_tweens width height The *script is the only absolutely necessary part. Ani ignores name, uses name of file instead. Included only so can tell where came from. Number of tweens is ignored. Ani counts. Nice to have for reference... Width and height are the screen dimensions. Not used by ani, but used by programs that take scripts from one machine to another... ii. Version number: *version number This line is optional. If missing ani uses most recent version. There is a routine that converts version 0 to version 1. Another that converts version 1 to 2. And so forth in a chain. This is how I maintain the ability to upgrade and not lose artwork.... I think we're on 14 or 15 now. iii. Ground zero: *ground_z number This is the magic number in the z coordinate so that if you are here the multiplies and divides in the psuedo-perspective calculations cancel each other out. It is incedentally where all objects are created, and you better believe there is a test for this in the perspective code to avoid them if this is the magic plane of birth... Changing this has a dramatic effect on the replay of the script. In later versions this will probably go away because I want users to be able to change it dynamically. Currently varies from machine to machine, and is generally about 1 and 1/2 times the x screen dimension. Optional. Default value (512 on amiga) assumed if missing. iv. Raster declarations: *define RASTER_TYPE file_name. Ani currently loads ALL rasters used in a script while reading this part. If ani can't find a file, ani makes up a little raster just big enough to hold the file name, and writes the file name in it. You've seen the effects of this, or will soon if you try to re-organize your script disks. Current RASTER_TYPES are: BITPLANE_RASTER (SUN and Amiga) single color raster. BYTEPLANE_RASTER (SUN only) full color raster. BYTEPLANE_STENCIL (SUN only) full color with transparency AMIGA_BITMAP (Amiga only) full color with transparency Of course there need not be any of these if the script has no rasters. Most of my favorite scripts are purely metamorphic actually .... BUG: sometimes (maybe all the time...) when you delete all references to a raster in a script, it isn't cleaned off of here. v. Tween level. *tween start duration stop number_of_acts I'm pretty sure all of these are necessary though ani ignores the number of acts, computers can count better than we can... BUG: Not only are the start and the stop never used (though something like them will be necessary when I finally figure out how to implement overlaying of scripts), but they are not even always accurately maintained. Duration is the only significant slot. vi. Act level. *act [length_of_act_in_words] OP_CODE addressing_words op_data_words Again ani counts. There is some error checking here. If ani see's you don't have enough words ani pads with zero. If you have to many the excess is truncated. In either case ani bitches. Generally the zero pad is ok, but occassionally - especially if in address fields - will cause crash. Think a place in SIZE ops where could cauze zero divide. There are 6 basic address types: 1. Point addresses *act length POINT_OP poly point_in_poly op_data 2. Segment addresses *act length SEGMENT_OP poly start_point number_of_points ... 3. Poly (object) addresses *act length POLY_OP poly ... 4. Multiple (frame) addresses *act length POLYS_OP start_poly #of_polys 5. Color addresses *act length color_op -1 ... 6. Background addresses *act length background_op -2 ... The addressing is probably the weakest part of the script design. In my next one the objects are going to have names not numbers. Actually the scripts for the next one - aeolus - are already partly designed and a prototype with no user interface is working. I hope I will be able to convert ani formats to aeolus ones but I can't gaurantee it. Aeolus does allow overlays and the scripts amazingly are even shorter than ani's. However given my current schedule I'd be amazed to have Aeolus finished by the middle of 1987. Unfortunately the poly_ix of (what the user identifies as ) an object varies from tween to tween depending on the birth and death of other objects. This is mostly because the poly_ix was done with parallel code to the point_ix which must be done this way unless you can afford to name each point ... something I haven't yet addressed in Aeolus. I have a feeling I will use ani style point ops in Aeolus though since it took me 3 months to get the hook to work upstream... But god knows. The hook is the last thing going in Aeolus, not the first like it was in Ani ... cause it's going to be a son of a bitch no matter what, so I might as well make the rest of the code as nice as possible. Also (sigh) the addresses vary even within tween. Any really pretends the ops are sequential though they appear to user as in parallel. (Deep sigh) The addresses of kill points are a special case. They are the address at end of tween. The hook is a bitch! Also ani does no checking for valid address. This is quickest way to crash and burn - try a nice negative number or a real big one in an address field. VII. The OPS. First a list of them all: INSERT_POLY INSERT_RASTER INSERT_STENCIL INSERT_POINT INSERT_CBLOCK INSERT_POINT KILL_POLY KILL_POINT MOVE_POINT MOVE_SEGMENT MOVE_POLY MOVE_POLYS PATH_POINT PATH_SEGMENT PATH_POLY PATH_POLYS ROTATE_POINT ROTATE_SEGMENT ROTATE_POLY ROTATE_POLYS SIZE_POINT SIZE_SEGMENT SIZE_POLY SIZE_POLYS CHANGE_COLOR CHANGE_TYPE (of polygon ... "instant ops") INIT_COLORS CYCLE_COLORS TWEEN_COLORS TWEEN_TO_COLORS LOAD_BACKGROUND REMOVE_BACKGROUND VIII. The OPS individually (more or less) Say hey, this is going to be very long. I'm just going to give you the INSERT_POLY format and the MOVE, PATH, ROTATE, and SIZE for now. You got to figure a little out for yosehf! i INSERT_POLY: *act [short count] INSERT_POLY insert_where(poly_ix) type_number color pt_count 0 0 0 (x y z 0) (x y z 0) ... (x y z 0) Keep the damn zeros zeros of course, expecially the one after xyz ... The type numbers are filled - 0 outline - 1 just_line - 2 stroke_font - 3 (use at own risk, untested for ages and Aegis ... a (x y z 1) instead of (x y z 0) means break line & move...) Sorry, just looked at sources, ifdefed out... Try using outline or just_line though with the 1's for same effect I'm pretty sure. ii MOVES: *act MOVE_OP address dx dy dz iii PATH: *act PATH_OP address #of_points (ani no count these...) (0 0 0) (dx1 dy1 dz1) ... (dxn dyn dzn) The dx's are relative to the initial (0 0 0), not sequentially to each other... it's faster that way. Basically just like polygon with always first point zero offset. iv ROTATES: This one is why I needed a graduate degree in mathematics to write this program... *act ROTATE_OP address centerx centery centerz higher_math_you_ignore_ani_recalculates_from_axis_a higher_math_you_ignore_ani_recalculates_from_axis_b amount to rotate - 1024 = 360 degrees axis_x axis_y axis_z Axis is a 3 vector of length 16384. Yes, code handles rotations about arbitrary axis, just no user interface. Try rotations about different axises (axees ... how to spell...) upstream of each other... Naturally any checks and trys to do 2-d rotation only if at all possible. The higher_math ones involve conjugates of matrices. You can safely stuff any number here, just give me SOME number... v SIZE_OPS: *act SIZE_OP address centerx centery centerz multiply_by divide_by That's all you get for now. Hope this helps. -Jim Kent Proprietor Dancing Flame