Synchronising SSQC and CSQC animations

Discuss CSQC related programming.
Post Reply
OneManClan
Posts: 247
Joined: Sat Feb 28, 2009 2:38 pm
Contact:

Synchronising SSQC and CSQC animations

Post by OneManClan »

OBJECTIVE: To replace the player.mdl with a (new) player.iqm. Why? Skeletal animation blending, separate head/torso control, new animations, ragdoll etc

PROBLEM 1: Half of the current AGR playerbase insist on using clients such as EZQuake, Fuhquake etc. These clients cannot use iqms, so completely replacing the existing (SSQC) player.mdl is not an option.

SOLUTION TO PROBLEM 1: Use CSQC's deltalisten to intercept SSQC's player.mdl, and substitute a CSQC player.iqm. CSQC clients see the new iqm, and EZQuakers are unaffected. This is the current situation. I still have the regular quake.mdl, animating normally in SSQC. I've exported captn bubs's player.blender file as an IQM, and using a *.framegroups file, managed to get the iqm to replicate all of the SSQC mdl's movements. IIUC, the SSQC sends self.frame information to the CSQC (deltalisten'ed) entity every .. er.. frame ('tick'?), and the CSQC translates this information into poses in the iqm, as specified in the frameworks file. All works great except:


PROBLEM 2: I want to implement skeletal animation, and animate the IQM using it's 'embedded' animations (ie rather than use a framegroups file) (Apparently framegroups files are only necessary if there's a problem with the exporting). Anyway, I made a new version of the iqm which has all the quake animations as seperate 'actions'. My idea was to send the .frame information from SSQC to CSQC as a STAT (before I realised that the .frame information gets sent anyway) :

Code: Select all

//CSQC
float latest_frame = getstatf(STAT_FRAME); // get the frame from SSQC
self.frame = WhatAnimIsThat(latest_frame);// translate it to what the new animation
and then, run the correct animation in CSQC via something like:

Code: Select all

// receives the current .frame, and returns which (iqm) animation to run
float (float the_frame) WhatAnimIsThat = 
{
	
	
	switch(the_frame)
	{
		
		case 0: 
		case 1: 
		case 2: 
		case 3: 
		case 4: 
		case 5: return frameforname(self.modelindex,"axrun"); // this is a NEW animation embedded in the new iqm
		
		case 6: 
		case 7:
		case 8:
		case 9:
		case 10:
		case 11: return frameforname(self.modelindex,"rockrun"); // this is a NEW animation embedded in the NEW iqm

// etc
.
.

SO WHATS THE PROBLEM?
If this were a pure CSQC entity, IIUC, the way to run an iqm animation is:

self.frame1time += frametime;

However, deltalistened entities (such as the player.iqm in this case) receive self.frame information every tick(packet?), which is overrides/interferes my attempt to control the .frame info entirely within CSQC

SO WHAT'S THE QUESTION?
The question is: Does anyone have any tips, hints, or suggestions as to how to synchronise the animations of a (SSQC) player.mdl with a (CSQC + deltalisten) *.iqm substitute?
OneManClan
Posts: 247
Joined: Sat Feb 28, 2009 2:38 pm
Contact:

Re: Synchronising SSQC and CSQC animations

Post by OneManClan »

[Note: There seem to be three separate meanings for the term 'frame' at the moment:

A: a SSQC *.mdl's individual pose, from an animation (eg a regular ssqc monsters '.frame')

B: a CSQC iqm's complete animation sequence (eg an iqms 'axattack' '.frame' consists of ALL the poses are part of the 'axattack', animation. IIUC you can refer to the entire animation as 'the axattack frame')

C: "The common terms for one crank of the game loop are “tick” and “frame”"

So for now.. to minimise confusion, in this post, I'll refer to A as the 'MdlFrame', B as the 'IqmFrame', and C as the 'GameFrame']


Ok, Spike has informed me that

Code: Select all

self.frame = frameforname(self.modelindex, "foo");
does NOT restart the IqmFrame, so it can be run every GameFrame. Therefore we can do this:

Code: Select all

	    // CSQC runs every GameFrame
string incoming_mdl_frame = WhatAnimIsThat(self.frame);
	    
	    // is the SSQC entity's current .frame (ie the MdlFrame) NOT part of the current IqmFrame?
	    if(self.current_animation_name != incoming_mdl_frame)
	    {
	 
		// if we're here, we need to change the IqmFrame
		 
		 
		// debugging
print("Anim changed to = ", incoming_mdl_frame, "\n"); // prints everytime SSQC's incoming MdlFrame contains a MdlFrame which belongs to a different IqmFrame
		
		
		self.frame = frameforname(self.modelindex, incoming_mdl_frame); // change the IqmFrame

		self.current_animation_name = incoming_mdl_frame; // storage, so we can test next GameFrame
		
	 
	    }
	    else
	    // the MdlFrame info just received is still part of the current IqmFrame
	    {
		//overwrite the MdlFrame info, preventing it from changing the current IqmFrame
		self.frame = frameforname(self.modelindex, self.current_animation_name); // This will not restart the IqmFrame
	    }
Post Reply