Right on both counts, Mage, but I think there might be more to this. So I've been testing this through a little trial and error:
First, I was wrong about the "sync camera" command; it will indeed update bones when called, just like "sync" and "fastsync" will. But all these commands will only update bones in models which are included in the chosen camera's individual view matrix. So basically, the camera must literally be looking at an object if its "sync" is going to update its bones - otherwise it simply skips the bone update altogether.
For all cameras, the view matrix is basically a spacial log of any model within its forward hemisphere. So any model in front of directly left, right, up and down from the camera is included, regardless of whether it is hidden, out of range, out of FOV or any other user setting. Furthermore, this matrix is rebuilt for every camera during every frame, regardless of whether the camera actually syncs or not. So even if you do not sync your camera, it will still suffer the draw-lag of any objects in its forward hemisphere - even if those objects are masked or hidden. What the hell, right?
(more knowledgeable people will confirm whether the matrix is based on objects or polygons - either way, the affect on bones is clear)
So building on GG's suggestion, my solution is to use a dummy camera with the "sync camera" command to update the bones. For any non-collision-check frames, this camera is exiled to a far corner of the game world and pointed out into empty space (so as to record absolutely nothing in its view matrix). Whenever a collision check is required, the camera is positioned in the appropriate place just long enough to "sync camera" then exiled again; so the 30-40% frame drop I experience from viewing a non-fastbone animated object twice in one update is contained in a single frame and pretty much invisible.
The results are good, if a little awkward. I've got this itching sense of dejavu over this solution - feel certain I've read this somewhere before.
I hope this little ditty explains what I mean. Maybe you guys could just check this for blatant code problems? I don't expect you to actually run it (you'd need your own models, anyway). Thanks guys.
`LOAD SOURCE MODEL:
global body as integer = 1
load object "body.x", body
`LOAD COLLISION BOX MODEL:
global head as integer = 2
load object "head.x", head
`SETUP MAIN CAMERA:
rawCam = 0
position camera rawCam,0,object size(body),-(object size(body)*4)
point camera rawCam,0,object size(body),0
`MAKE DUMMY CAMERA:
dumCam = 1 `(the dummy camera to force animation updates)
dumImg = 1 `(dummy image for dummy camera - never read)
make camera dumCam
set camera fov dumCam, 1 `(arbitrary)
set camera range dumCam, 1, 1 `(arbitrary)
set camera to image dumCam, dumImg, 2, 2 `(can be small because it is never read)
position camera dumCam, 0, 1000000, 0 `(arbitrary position far away from scene)
point camera dumCam, 0, 1000001, 0 `(look directly away from scene)
set current camera 0 `(otherwise newly made camera will be default camera)
`ORGANISE OBJECT RENDERS:
set object mask body, 2^rawCam
hide object head
`TEST VARIABLES:
global testbone as integer = 53 `(arbitrary bone for the test)
`KEY SECURITY:
global keysecurity as integer
`PROGRAM LOOP:
do
`RESET KEY SECURITY:
if scancode() = 0
if keysecurity = 1 then keysecurity = 0
endif
if keysecurity = 0
`PLAY SOURCE OBJECT:
if returnkey() `(playing object makes test results more obvious)
if object playing(body) = 0
loop object body,0,1 `(any arbitrary frame for the test)
endif
keysecurity = 1
endif
`TRIGGER COLLISION BOX UPDATE:
if spacekey()
if object playing(body) then stop object body
set object frame body, 8
position camera dumCam,camera position x(0),camera position y(0),camera position z(0)
point camera dumCam,0,object size(body),0
sync camera dumCam
position camera dumCam,0,1000000,0 `(arbitrary position far away from scene)
point camera dumCam,0,1000001,0 `(look directly away from scene)
`UPDATE COLLISION BOX:
position object head,limb position x(body,testbone),limb position y(body,testbone),limb position z(body,testbone)
rotate object head,limb direction x(body,testbone),limb direction y(body,testbone),limb direction z(body,testbone)
keysecurity = 1
endif
endif `(keysecurity)
`CONSOLE:
temptext = 12
text 10, temptext, "FPS: "+str$(screen fps())
temptext = temptext+(12*1)
text 10, temptext, "ANIM FRAME: "+str$(object frame(body))
temptext = temptext+(12*1)
text 10, temptext, "COLLISION BOX Xpos: "+str$(object position x(head))
temptext = temptext+(12*1)
text 10, temptext, "SOURCE BONE Xpos: "+str$(limb position x(body,testbone))
`SYNC MAIN CAMERA
sync camera rawCam
`CHECK DUMMY CAMERA FUNCTION:
if keystate(30)
repeat
paste image dumImg,0,0
until keystate(30) = 0
endif
loop