Monday, July 27, 2020

More Argus, Millisecs Per Frame, Silicone Guitar Picks

More programming here. The hard part is the distinction between 3D objects. Normally my objects have geometry that can change each animation frame, but textures remain the same, and objects are sorted by texture too, which can be used as a tool to print them in the right order. Now the animation will usually keep the same geometry but change texture each frame. They are essentially two types of animation, they could even animate independently (geometry changes, texture changes) so I'm storing both frame numbers separately. I'll keep the possibility of geometrical changes but won't immediately use it... this software is designed to change the texture-per-frame.

I'll need to load the geometry of the objects without storing that in the vertex buffers because the creation process will involve loading and toying with the 3D 'actors' before (and after) we see them moving in the scene, and this data (and the textures) can only be loaded when the 3D scene is set up and is destroyed when the 3D scene is destroyed. My current fairies (my word for design of a 3D object, a pun on sprite) are in an array, I'll need to put them in a linked list too. In a game, an array is more efficient because we know exactly how many we will use per game, but here this quantity varies on a project-by-project basis.

One problem was solved today. I needed to work out the timing. A game is normally updated 50 times a second (every 20ms), but we're animating here, so I need to update at the correct frame rate, which can vary, eg. 30 frames per second. There is a high-resolution timer in Windows but it's slow and, I think, overkill, one millisec here and there per frame is immaterial - the inaccuracies only mount up over long periods. I'd rather use my fast and neat timeGetTime() function, but this only operates in millisecs not fractions and 1000/30 (for 30 frames per sec) is 33.3333... millisecs per frame. We also have the possibility of other complex frame rates, like 29.97 frames per sec, to cope with.

So I needed a way to flip/flop the right frame, keeping track of the remainder so the frames would (here) be 33, 33, 34ms all nicely. The code is actually quite simple, it's just a matter of keeping track of the remainders.

fliptimefloat+=msperframe;
fliptimeint=(int)fliptimefloat;
fliptimefloat-=(float)fliptimeint;

fliptimefloat would keep the remainder, while fliptimeint will be the number of millisecs to wait, so when msperframe=30 then fliptimeint would equal 33, 33, 34, 33, 33, 34... as desired. Yay!

I've also had to revisit my vertex shader code (which is years out of date, I use DirectX9). Here is a snippet of the lighting calculations (with a fading radius, which I won't use):

; Light 1: Get direction to light
sub r4.xyz, c[13].xyz, r2.xyz
; LIGHT: normalise light direction and calc lighting
dp3 r3.x, r4, r4
mad r3.x, r3.x, c[13].w, c[13].w
rsq r3.x, r3.x
dp3 r4.w, r4, r4
rsq r4.w, r4.w
mul r4, r4, r4.w
; Put diffuse factor into r4.x
dp3 r4.x, r1, r4
; Limit r4.x to positive (c[0].x=0)
max r4.x, r4.x, c[0].x
mul r4.x, r4.x, r3.x
; APPLY (objectcolour is ignored): Result = (objectcolour*r4.x)*lightcolour
mul r5, r4.x, c[14]

As you can see it's rather assembler-ish. I don't mind this, I grew up coding is pure machine code, but I can't decipher most of it now. I'll be using 3 lights at most. My engine can cope with more but few animations will use more than three lights, and every extra one will slow it down for everyone.

In guitar news, I've now played every day this month to an album in my collection and have gone through all of the Electric Light Orchestra catalogue, all of the 12 Bowie Albums I have, a few Beatles albums, and the eponymous Roxy Music. I wondered if a chunky silicone pick, like a domed pastel shader, would work. It would stick to the strings a little, like fingers (that is the idea) but, being held, might be faster and easier to play than using fingers. The soft sound and feeling of fingers is so different from using a pick. I wonder how a metal dome would work.