Video Vector Scene Text file format is the heart and soul of everything you create. It's very powerful, but it can be a bit cryptic at first glance. However, armed with some basics, you'll quickly discover it was designed to be concise, yet easy to remember and read. The key to learning it quickly is realizing that it is also typographically symbolic and could be substituted for emojis in many places, lending to a primal form of pictorial processing our monkey brains can easily process.
Basic Structure
Video Vector Scene Text file format is the heart and soul of everything you create. It's very powerful, but it can be a bit cryptic at first glance. However, armed with some basics, you'll quickly discover it was designed to be concise, yet easy to remember and read. The key to learning it quickly is realizing that it is also typographically symbolic and could be substituted for emojis in many places, lending to a primal form of pictorial processing our monkey brains can easily process.
% 640 480 : 10 * 30 #video size, length and fps
& _ 0 0 10 ^ 0 0 0 v 90 < 0.01 40 #camera details
? lightX = 1
? lightY = 1
? lightZ = 1
? lightLen = ^"max(0.0001,sqrt((lightX^2)+(lightY^2)+(lightZ^2)))"
? lightDirX = ^"lightX/lightLen"
? lightDirY = ^"lightY/lightLen"
? lightDirZ = ^"lightZ/lightLen"
? worldFaceLight = ^"max(0,(Fnxw*lightDirX)+(Fnyw*lightDirY)+(Fnzw*lightDirZ))"
? worldLineLight = ^"max(0,(Lnxw*lightDirX)+(Lnyw*lightDirY)+(Lnzw*lightDirZ))"
[ origin_axis
@ 0: / 0 0 "tau*nt"
. 1 0 0
. -1 0 0
. 0 1 0
. 0 -1 0
. 0 0 1
. 0 0 -1
- 0 1 c rgb 1 0 0 w 3
- 2 3 c rgb 0 1 0
- 4 5 c rgb 0 0 1
]
[ geode
+ origin_axis
@ 0: _ 7 0 0
: sphere 10 10 2
- c rgb 0 worldLineLight worldLineLight w 2
> c rgb worldFaceLight 0 worldFaceLight
: - >
]
The Default Scene
Let's break down the default scene that you find when you open Video Vector. It is by no means a complete language guide, but it's a great place to start.
% 640 480 : 10 * 30 #video size, length and fps
% {width} {height} : {duration} * {fps}
The first thing you need to do is define your scene... or in many ways, how the video will be projected when exported. The % is symbolic of a dual reel film projector 📽️ and details the resolution width and height (640x480). Separated by a colon : is then the video length and frames per second. They are separated by an asterisk * and, in a sneaky visual reminder, is the way to calculate how many frames the video will have, 10 * 30 (= 300 frames). These details are required for all scenes.
& _ 0 0 10 ^ 0 0 0 v 90 < 0.01 40 #camera details
& _ {position} ^ {look at} v {fov} < {dof}
The next thing you need to define is the camera, &, symbolic of a film camera 🎥 and defines the properties of what you will actually see. Underscore _ is the notation for position x y z in world space (transforms, commonly used in keyframes, are a triplet of single lines with '_' for position, '/' for rotation, and '|' for scale.)
Then ^ is the symbol for what position the camera is looking at in x y z world space.
The field of view, 'v' is symbolic for the angle, in degrees, covered from the top-most edge to the botton-most edge, default is 90 degrees with the camera placed 10 units back. Which means the 640x480 scene is 20 units high, or the screen in 24 pixel unit squares. If you wanted pixel accurate units (1 unit = 1 pixel) at 90 degree fov, use scene height/2 for the Z position of the camera... or "& _ 0 0 240 ^ 0 0 0 v 90 < 0.01 480" for 640x480 scene. Note, I am setting the depth of field to 480... it needs to be greater than the 240 the camera is back. Everything at position Z 0 will be pixel accurate. This is more important for image presets displaying images at pixel accurate scale, but you are in full control of your world units.
Lastly, '<' represents the depth of field from the distance closest to the camera to the furthest. The field of view and depth of field are the effective clipping region in which everything will exist. Anything outside this region will not be rendered.
So, by default, the camera is effectively your eyes. Your eyes sit that 10 unit distance away from your monitor. The center of the monitor is world 0,0,0 and the viewable depth continues x3 as much, through your monitor and into the wall behind... of sorts. The 90 degree angle can cause distortion, as you can imagine is caused by being able to see 45 degrees to either side, but compacted into the region being rendered. If you have the means, measure all these dimensions of your eyes to the monitor and the angles of the bounds of the rendered box and you can achieve far more physically accurate settings.
? lightX = 1
...
? thing(x,y) = "(10*y)+x"
? myColor rgb 1 1 0
? myColor2 = "rgb(1,1,0)"
? {function} = {expression}
? {colorName} {colorType} {channels}
Now we start getting into the meat of Video Vector, custom defined expressions. The question mark declares a custom definition.
You can define a single value to be returned, via equals '=', or you can define a color via a color type, like 'rgb' or 'hsv', etc. You can pass in arguments and values into the expression, like 'thing(x,y)', or you can even use a color function to return a color value. There are some nuanced uses for each, but the other thing to understand is custom definitions can be declared globally (at the top of the scene text under the scene and camera settings), or they can be declared locally inside objects (local definitions override global definitions within that object).
You may see either '^' or '$' preceding an expression. They do not affect the operation of the expression, but are used for either caching the results '^' to be reused to speed things up, or to register the expression to the graphing system '$' so you can graph the results across the duration of the scene. Not too important to understand at this time, but they are associated with expressions, and I'll do formal posts about them later.
[ origin_axis
@ 0: / 0 0 "tau*nt"
. 1 0 0
. -1 0 0
. 0 1 0
. 0 -1 0
. 0 0 1
. 0 0 -1
- 0 1 c rgb 1 0 0 w 3
- 2 3 c rgb 0 1 0
- 4 5 c rgb 0 0 1
]
[...] The basic Object
Now we REALLY get into the meatier meat of Video Vector... objects! Objects have a couple different parts, but let's break down this first object, the origin axis.
Objects are defined within square brackets [...]. Immediately after the opening bracket is the object name itself to uniquely identify it, origin_axis. Keep the name as a continuous string.
The at symbol @ designates keyframing the object transform. You can control position, rotation and scale at specific points of time, in this case at time 0. For keyframes, the last set keyframe is used for all future times if there is no keyframe to transition towards, so you can define a constant state at time 0, for the entire video. In this case, it is using the normalized time, nt (a special variable that changes from 0 to 1 across the length of the video) to rotate tau radians. Rotation is in radians, 'tau' and 'pi' are special constants you can use for this purpose. There is also a degrees to radians function, 'd2r(deg)', that you can use to work in degrees... 'd2r(360)' is the same as 'tau' radians, 'd2r(180)' is 'pi' radians. In this case, the origin_axis object makes one complete rotation about the Z-axis.
Periods '.' denote a Vertex element. The full convention is ". {x} {y} {z} dx {+expr} dy {+expr} dz {+expr}" where you define the position of the vertex and then can have optional additive expressions bound to the vertex axis position. In this case, though, the positions are set to the +- 1 positions along each X/Y/Z axes.
Hypens '-' denote a Line element. The use the Vertex index number (0 based index) to define a line between two vertexes. Properties such as Color 'c' and line width 'w' follow. It's worth noting that a property is inherited from the previous element, if defined, so a line width of 3 only needs to be defined once for the first line for all following lines to be of width 3.
An object then uses a closing bracket ']' to denote the end of the object's structure.
[ geode
+ origin_axis
@ 0: _ 7 0 0
: sphere 10 10 2
- c rgb 0 worldLineLight worldLineLight w 2
> c rgb worldFaceLight 0 worldFaceLight
: - >
]
+ parentObject
The next object introduces object parenting with the plus '+'. This notation sets the object to be a child of, in this case, origin_axis. So, geode will inherit all transform information (position, rotation and scale) from the parent object, and it's own transform will be added to it. In this case, geode is offset from origin_axis's center by 7 units along the X-axis. You better see this relationship in the Tree editor mode.
: Presets
You'll notice in geode there are no vertexes, lines or faces defined, yet you see a very detailed sphere with hundreds of them. I have created numerous "Presets", shorthand notations that generate common geometry from a few arguments. Geode uses the sphere preset.
Presets have a common structure. Colon ':' starts the preset, then the name of the preset, in this case 'sphere', then any required arguments. For sphere you define the number of segments latitudinally, longitudinally and radius.
Within the preset you can define the properties for points, line and faces. In this case it's just defining line color and width, and face color. Color channels for Red, Green, and Blue are leveraging the custom defines from before, which are detailed in the previous post about the Video Vector Lighting System.
Presets close with another colon ':' but as a final argument, you specify which elements are to be rendered. In this case the lines '-' and faces '>' are to be rendered, via ': - >'. It's worth noting that all presets support points, lines and faces (where it applies), so you could have any combination of '* - >'... and in fact you can omit them completely! Yep, you'll see nothing. However! It is still generating the vertices in all cases... which you can leverage yourself by specifically defining your own points, lines and faces after the preset.
There's a LOT more to learn!
This default scene text is just scratching the surface of what you can do. There's a ton of fun things to explore, such as the '~' background color system, similar to a pixel shader, in which you can create dynamic background gradients or even fractals; '{...}' object prototyping where you can define an object once and create multiple object instances via '= prototypeName' inside the object, similar to parenting; '(...)' object emitters where you can auto-generate many object instances of prototypes; 'idx' notation and 'G(...)' global object element referencing, allowing you to target specific elements to override their properties or return their values; '$' graphing expression notation where you can graph an expression and see it's value across the scene; '^' expression caching which allows you to save processing time and reuse results from expressions... and so much more!
Be sure to go through the Scene Text Reference Guide, available in the Help menu, or with the book button at the top-right of the editor. I'll do more formal posts detailing everything Video Vector has to offer, so don't worry.
Have fun exploring!