[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 488: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 112: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 112: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 112: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 112: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 112: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 112: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 112: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 112: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 112: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 112: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/bbcode.php on line 112: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
[phpBB Debug] PHP Warning: in file [ROOT]/includes/functions.php on line 4787: Cannot modify header information - headers already sent by (output started at [ROOT]/includes/functions.php:3922)
[phpBB Debug] PHP Warning: in file [ROOT]/includes/functions.php on line 4789: Cannot modify header information - headers already sent by (output started at [ROOT]/includes/functions.php:3922)
[phpBB Debug] PHP Warning: in file [ROOT]/includes/functions.php on line 4790: Cannot modify header information - headers already sent by (output started at [ROOT]/includes/functions.php:3922)
[phpBB Debug] PHP Warning: in file [ROOT]/includes/functions.php on line 4791: Cannot modify header information - headers already sent by (output started at [ROOT]/includes/functions.php:3922)
InsideQC Forums • View topic - CSQC skeletal animations played by anim name

CSQC skeletal animations played by anim name

Discuss CSQC related programming.

Moderator: InsideQC Admins

CSQC skeletal animations played by anim name

Postby toneddu2000 » Mon May 12, 2014 10:47 pm

- my first commercial game, made with FTEQW game engine
toneddu2000
 
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: CSQC skeletal animations played by anim name

Postby Spike » Mon May 12, 2014 11:29 pm

void(float modidx, string framename) frameforname = #276;
self.frame = frameforname(self.modelindex, "walk1") + index;

dedicated servers don't load models, frameforname is thus only valid in csqc. you should probably use some sort of enumeration for the actions in ssqc, and translate those to actual per-model frame numbers inside the csqc.

string(float modidx, float framenum) frametoname = #284; also exists for completeness. really its only useful for debugging.

once you have your entity in csqc, you can do something like:
enum
{
ACTION_WALK=0,
ACTION_STAND=1,
ACTION_TAUNT=2,
};
struct {
string firstframe;
float numframes;
float nextaction;
} actioninfo[] =
{
{"walk1", 6, ACTION_WALK},
{"stand1", 6, ACTION_STAND},
{"taunt1", 6, ACTION_STAND}
};
void() mypredraw =
{
self.lerpfrac -= frametime*framerate;
while (self.lerpfrac < 0)
{
self.frame2 = self.frame;
self.frame += 1;
float firstframe = frameforname(actioninfo[self.action].firstframe);
if (self.frame == frameforname(actioninfo[self.action].firstframe) + actioninfo[self.action].numframes)
{
self.action = actioninfo[self.action].nextaction;
self.frame = frameforname(actioninfo[self.action].firstframe);
}
}
};
then you can set self.action to ACTION_STAND to get it to loop a stand animation, or ACTION_WALK to get it to loop the walk animation... or ACTION_TAUNT to get it to taunt and then loop the stand animation instead.
obviously getting this stuff to work properly will require ensuring that the new action is only applied if the action has actually changed. which makes taunting fun.
you probably want to use an attack animation like this example uses taunt or something. I dunno, you'll probably want nailguns to loop instead.

Alternatively you can use framegroups (with frame1time+frame2time in combination with the frameduration builtin), and blend between animations separately from actual frames.

The skeletal objects extension allows you to animate separate parts of the model independantly (by copying the animation data into some separate skeletal state object). By blending multiple leg animations together with it, and playing them at different rates based upon their speed (self.frame1time += (distancemovedvector*v_forward)/animatedspeed) you should be able to achieve some sort of foot/ground syncronisation.
.
Spike
 
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Re: CSQC skeletal animations played by anim name

Postby toneddu2000 » Tue May 13, 2014 8:07 pm

- my first commercial game, made with FTEQW game engine
toneddu2000
 
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: CSQC skeletal animations played by anim name

Postby Spike » Tue May 13, 2014 8:53 pm

split the struct/array into 3 regular non-struct arrays I guess, if you're not going fte-specific.

.action is just some random custom field to hold which action the csqc entity should be doing at the time (to avoid randomly overwriting .frame, which would break .frame2 and generally result in issues).

the frameforname I mentioned returns either framegroups or ungrouped frames (as opposed to poses within a framegroup/sequence). the code example assumes that there are no framegroups in the model, which is a valid assumption for most of vanilla quake, torches/flames basically being the only exception.
framegroups are conceptually simpler, as the framerate etc can be fully determined by the model itself (assuming the animations are looping anyway, use frameduration to query a framegroup's duration for non-looping animations). However, framegroups generally have a problem with the end of their animation. typically your framegroup's last frame will need to blend into some other animation somehow. This typically results in either wasted frames at the end (which the qc will have to be aware of somehow) or weird freezes as it blends from one framegroup to another. there's no problem when they're looped animations, its really just a problem when they don't blend into the idle or whatever animation properly.

regarding skeletal objects, you can think of the engine as doing this as a wrapper around addentity(which is used internally by addentities):
if (self.skeletonobject) //|| isnotskeletal(self)
addentity(self);//use a custom skeleton
else
{//build a temporary skeleton
self.skeletonobject = skel_create(self.modelindex);
skel_build(self.skeletonobject, self, self.modelindex, 0, 0, 0, 1);
addentity(self);
skel_delete(self.skeletonobject);
}
the key thing to note is that skel_build copies the animation data from the specified modelindex according to the frame+frame2+lerpfrac etc fields in the given entity into the named skeletal object. the renderer will use the entity's .skeletonobject field to determine the animation data to use instead of doing an implicit skel_build.
skel_delete calls are defered until the end of the frame, allowing you to create+add+delete within a single frame without having to take so much care.
by explicitly calling skel_build yourself, you can have _direct_ control over the state of the bones. note the extra arguments (which allow you to constrict the set of bones to a range (0 means all), and with custom blend weights as an alternative to lerpfrac). you can also call the other various skel_ functions to tweak or query the skeleton. note that gettaginfo builtin will query the entity's attached skeletal object, if you want world positions.
you can rotate an individual bone (and its children) by calling skel_build(...);makevectors('0 1 0'*time);skel_mul_bone(self.skeletonobject, skel_find_bone(self.skeletonobject, "head"), '0 0 0', v_forward, v_right, v_up); This will give you a really disturbing 'The Exorcist' effect with the head spinning around. The skel_build first ensures that you get new data for this frame, technically you can skip it however if you do so you should use frametime instead of time as the effects are then cumulative. Matricies can be fun.
.
Spike
 
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Re: CSQC skeletal animations played by anim name

Postby toneddu2000 » Wed May 14, 2014 1:02 pm

- my first commercial game, made with FTEQW game engine
toneddu2000
 
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: CSQC skeletal animations played by anim name

Postby Spike » Wed May 14, 2014 2:58 pm

.
Spike
 
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Re: CSQC skeletal animations played by anim name

Postby toneddu2000 » Thu May 15, 2014 2:56 pm

- my first commercial game, made with FTEQW game engine
toneddu2000
 
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: CSQC skeletal animations played by anim name

Postby Spike » Thu May 15, 2014 5:01 pm

regarding conflicting extensions, its like targetting the lowest common denominator, but first you have to figure out what exactly that is.
renamed builtins are not a problem with fte or dp. the engine really doesn't care what the builtin is called. rename it if you want. only the # and the number of arguments is important.
renamed arguments is not something the engine is aware of. its safe. prototypes can have different argument names from your actual function body too!
additional arguments in entry points (qc functions) may have undefined values in the engine which does not define them. the qcc may care, but the engine sure as heck does not.
additional arguments in builtins may generate some annoying error in DP. FTE will ignore additional arguments, while missing arguments will be undefined - as in vanilla... so pay attention to warnings about missing arguments!

pr_dumpplatform will give you a dump that is meant to exactly match the binary you use the command from.
http://triptohell.info/moodles/fteqcc/fteextensions.qc is a link to one that is generated from the latest nightly build.

regarding your console inputs issue, I tried to add support for XIM for proper unicode text entry, and it worked in debian, however, I later noticed that it didn't work in cygwin which should now also be fixed.
If you still have issues, you can use -noxim to use the old code.

actually, the skeletal object is not an entity, but rather both are 'objects' in the programming sense, so you're mostly correct. model indexes refer to a model object too, which contain their own framegroup objects, which in turn contain pose objects, if that helps... a skeletal object is just some generic pose object that can be used independantly of the model that it came from, and can be dynamically changed.
by 'independantly', you can actually build a skeletal object from one model and use it with a different one instead. this is useful when you have all-animation models and mesh-only models like with doom3's md5mesh/md5anim formats, or whatever.
but yeah, the skeletal objects are referenced by index, much like entities are (except with floats instead of an entity/hidden-int type).
.
Spike
 
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Re: CSQC skeletal animations played by anim name

Postby toneddu2000 » Thu May 15, 2014 9:40 pm

I always ignored missing arguments warnings, from now on I'll be more careful!
the -noxim argument did the trick, thanks
And thanks for the clarification about skeletons, let's see what I can do!
- my first commercial game, made with FTEQW game engine
toneddu2000
 
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: CSQC skeletal animations played by anim name

Postby toneddu2000 » Fri May 16, 2014 1:51 am

- my first commercial game, made with FTEQW game engine
toneddu2000
 
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: CSQC skeletal animations played by anim name

Postby Spike » Fri May 16, 2014 2:58 am

lerpfrac is how much of .frame2 to use. the more of frame2 that is used, the less of .frame that is used.

essentually:
decrement lerpfrac by frametime*animframerate (where animframerate is 10 or so, and frametime is the global that says how much time has passed).
if lerpfrac is now less than one, set .frame2 to .frame, increase lerpfrac to 1, and set .frame to the next frame that should be displayed (ie: increment it by 1, and reset to the first frame when it reaches the last frame or so).

your skeletonindex stuff isn't doing anything. it doesn't help that you set the 'addition' field as 0 instead of 1, but also your skel_delete leaves the entity trying to use an invalid skeleton next frame (due to the check that avoids creating a new one).

if you're using a framegroup, you need to set frame1time/frame2time to the time into their respective animation. self.frame1time+=frametime; for instance. for a running animation, you should increment it based upon the distance traveled instead of the time interval. which gets ugly when you slow down to low speeds. woo.
.
Spike
 
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Re: CSQC skeletal animations played by anim name

Postby toneddu2000 » Fri May 16, 2014 11:24 pm

- my first commercial game, made with FTEQW game engine
toneddu2000
 
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: CSQC skeletal animations played by anim name

Postby Spike » Sat May 17, 2014 1:03 am

modelindexes are positive if they were precached on the server, and negative if they were precached only on the client. it is actually possible for both a positive and negative value to map to the same actual model, any lookups in that case will result the positive/ssqc index, but this typically requires late precaches in ssqc to achieve.
a modelindex of -1 is thus perfectly valid.
its modelindex 0 which is the only invalid one. generally the engine will disconnect with an error message instead of it turning up (when its the engine's fault, anyway).
this mechanism means that csqc can use models without requiring the server to have already precached them, while modelindexes sent from the ssqc can still be used as-is in csqc.

I somewhat recently added a 'modelviewer' command, which should show the various frames in a model as the engine sees them. framegroups will autoanimate, but single frames will not. pgup/pgdn to change the framegroup/frame shown.
it also displays the bones and their positions at that point in the animation. which is probably not useful, but hey.

in your myenemyPredraw function, this line:
skel_delete(self.skeletonindex);
releases the skeleton (at the end of the frame). it does NOT set self.skeletonindex=0;
the next frame happens, the engine calls your predraw function, skeletonindex is not 0, but the skeleton it refers to has been released so the engine ignores it because its no longer valid. you have also not updated the .frame/frame1time etc fields. thus nothing animates. aka: you have a dangling pointer.
addentity makes a copy of the entity including its skeletonindex field, this combined with released skeletons remaining valid until the end of the frame mean you can just addentity(self);skel_delete(self.skeletonindex);self.skeletonindex=0; safely.
.
Spike
 
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Re: CSQC skeletal animations played by anim name

Postby toneddu2000 » Sat May 17, 2014 5:01 pm

- my first commercial game, made with FTEQW game engine
toneddu2000
 
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: CSQC skeletal animations played by anim name

Postby Spike » Sat May 17, 2014 7:41 pm

.frame1time is one of those engine difference things (sigh...). each engine's behaviour is good for something at least. if you're using the dp-specific csqc defs, fte will enable its dp-compat mode (along with warning about it).
fte behaviour: .frame1time is the time into the animation (need to update it each frame, giving easy control over the speed that it animates).
dp behaviour: .frame1time is the timestamp (=time) of the start of the animation (set it when the ent is first spawned. if you want to change the speed that it animates at you'll need to do extra maths).
fte feature: .renderflags |= 64; will switch the behaviour from one to the other.

in all cases, the frame1time is specified in seconds and not frames (some model formats potentially animate framegroups at a non-linear rate). the framerate of the animation is thus generally not important to the gamecode.

setting the current time to the duration of the animation is completely pointless.
you can use this maths to animate within a framegroup to ignore the loop flag completely.
if (dp) self.frame1time = time-self.frame1time; else self.frame1time += frametime;
float duration = frameduration(self.modelindex, self.frame);
float t = self.frame1time / duration; self.frame1time = (t-floor(t))*duration;
if (dp) self.frame1time = time-self.frame1time;

and this to animate it while honouring the loop flame properly:
if (!dp) self.frame1time += frametime;

both of the above require this when you spawn the entity/change animation:
if (dp) self.frame1time = time; else self.frame1time = 0;
.
Spike
 
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Next

Return to CSQC Programming

Who is online

Users browsing this forum: No registered users and 1 guest