2 registered members (AndrewAMD, SBGuy),
987
guests, and 3
spiders. |
Key:
Admin,
Global Mod,
Mod
|
|
|
need help with these structs im using
#327544
06/07/10 01:50
06/07/10 01:50
|
Joined: Jul 2008
Posts: 223 Pittsburgh
The_Clyde
OP
Member
|
OP
Member
Joined: Jul 2008
Posts: 223
Pittsburgh
|
I'm working on what I think would be a very useful tool for all Gamestudio users... an easy way to create and play back in-engine cutscenes (rendered by A7 instead of loading a video). On the whiteboard my algorithm and data structures appear to work nicely... but then I tried to implement these and used structs for my data structures and things got weird. I am not so familiar with the use of structs and the related commands such as malloc and memcopy and others. I'll detail my playback method and data structs below. It would be really great if somebody could describe to me how to use the structs to accomplish what I've planned. (I've already got code that sort of works but need better knowledge in order to find the bugs) ---------------------------- struct Keyframe contains - activation time of keyframe
- array of Cues
struct Cue contains - WED entity name
- start and end positions
- start and end rotations
- start and end scale
- animation name
- duration of this Cue
Playback Algorithm:
load keyframes information from text file
put keyframes into an array of keyframes
repeat every frame
{
if the total time passed has exceeded the start time of the next keyframe
{
add all the cues stored in the keyframe to a linked list containing all active cues
}
for each cue in the active cues linked list:
{
if the total time has passed the end time of the cue
remove it from the linked list
otherwise interpolate the position, rotation, scale, and animation of the entity named in the cue based on the current time, and the start and end times of the cue
}
}
once the end of the keyframe has been reached the scene is ended
At this moment it can load the scene from the text file, but it crashes if I try to make it play any more than one keyframe/cue...
|
|
|
Re: need help with these structs im using
[Re: The_Clyde]
#327546
06/07/10 03:09
06/07/10 03:09
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
Expert
|
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
Post your existing functions for initialising, saving, and loading your data please, It will gimme something to work from.
The capture and playback code would help too, but not so important if you wanna maintain secrecy...
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
Re: need help with these structs im using
[Re: EvilSOB]
#327547
06/07/10 03:36
06/07/10 03:36
|
Joined: Jul 2008
Posts: 223 Pittsburgh
The_Clyde
OP
Member
|
OP
Member
Joined: Jul 2008
Posts: 223
Pittsburgh
|
Well the capture code is non-existent so far since I haven't made the editor yet... so the only editor I've been using is notepad As for secrecy- its not so important since I've already detailed my algorithm anyway....
#include <acknex.h>
var cutscene_editmode = 0;
var cutscene_playing = 0;
var cutscene_paused = 0;
var cutscene_time;
var cutscene_keyframe;
typedef struct Cue {
STRING* entname;
VECTOR* startpos;
VECTOR* endpos;
ANGLE* startang;
ANGLE* endang;
VECTOR* startscale;
VECTOR* endscale;
STRING* anim; //animation name- or NULL
var animloops;
var starttime;
var duration;
struct Cue* next; //used when the cue is in the linked list of active cues
struct Cue* prev;
} Cue;
typedef struct Keyframe {
var cuetime;
var actions_count;
Cue* actions[64];
} Keyframe;
Keyframe* scene;
Cue* active_cues[300];
var keyframe_count;
Cue* active_cues_head = NULL;
function newCue()
{
Cue* newcue = malloc(sizeof(Cue));
memset(newcue,0,sizeof(Cue));
return newcue;
}
function newKeyframe()
{
Keyframe* newkeyframe = malloc(sizeof(Keyframe));
memset(newkeyframe,0,sizeof(Keyframe));
return newkeyframe;
}
function killCue(Cue* c)
{
free(c);
}
function killKeyframe(Keyframe* k)
{
free(k);
}
function loadScene(STRING* filename)
{
str_cpy(delimit_str," ");
var filehandle = file_open_read(filename);
var flop = file_open_write("testt.txt");
var length = file_var_read(filehandle); //first number is number of keyframes to malloc
file_var_write(flop,length);
scene = malloc(length * sizeof(Keyframe));
var i;
for(i = 0; i < length; i += 1)
{
memcpy(scene[i],newKeyframe(),sizeof(Keyframe));
scene[i].cuetime = file_var_read(filehandle);
scene[i].actions_count = file_var_read(filehandle);
if(scene[i].actions_count > 0)
{
scene[i].actions = malloc(scene[i].actions_count * sizeof(Cue));
var k;
for(k = 0; i < scene[i].actions_count; i++)
{
scene[i].actions[k] = newCue();
scene[i].actions[k].entname = str_create("#20");
file_str_read(filehandle,scene[i].actions[k].entname);
scene[i].actions[k].startpos = vector(0,0,0);
scene[i].actions[k].endpos = vector(0,0,0);
scene[i].actions[k].startang = vector(0,0,0);
scene[i].actions[k].endang = vector(0,0,0);
scene[i].actions[k].startscale = vector(0,0,0);
scene[i].actions[k].endscale = vector(0,0,0);
scene[i].actions[k].startpos.x = file_var_read(filehandle);
scene[i].actions[k].startpos.y = file_var_read(filehandle);
scene[i].actions[k].startpos.z = file_var_read(filehandle);
scene[i].actions[k].endpos.x = file_var_read(filehandle);
scene[i].actions[k].endpos.y = file_var_read(filehandle);
scene[i].actions[k].endpos.z = file_var_read(filehandle);
scene[i].actions[k].startang.pan = file_var_read(filehandle);
scene[i].actions[k].startang.tilt = file_var_read(filehandle);
scene[i].actions[k].startang.roll = file_var_read(filehandle);
scene[i].actions[k].endang.pan = file_var_read(filehandle);
scene[i].actions[k].endang.tilt = file_var_read(filehandle);
scene[i].actions[k].endang.roll = file_var_read(filehandle);
scene[i].actions[k].startscale.x = file_var_read(filehandle);
scene[i].actions[k].startscale.y = file_var_read(filehandle);
scene[i].actions[k].startscale.z = file_var_read(filehandle);
scene[i].actions[k].endscale.x = file_var_read(filehandle);
scene[i].actions[k].endscale.y = file_var_read(filehandle);
scene[i].actions[k].endscale.z = file_var_read(filehandle);
file_str_read(filehandle,scene[i].actions[k].anim);
scene[i].actions[k].animloops = file_var_read(filehandle);
scene[i].actions[k].starttime = scene[i].cuetime;
scene[i].actions[k].duration = file_var_read(filehandle);
scene[i].actions[k].next = NULL;
scene[i].actions[k].prev = NULL;
}
}
}
file_close(filehandle);
file_close(flop);
}
function playScene()
{
cutscene_time = 0;
cutscene_keyframe = 0;
cutscene_playing = 1;
var flog = file_open_write("scenelog.txt");
while(cutscene_playing == 1)
{
while(cutscene_paused) wait(1);
if(scene[cutscene_keyframe].cuetime == 0)
{
cutscene_playing = 0;
}
else{
if(cutscene_time >= scene[cutscene_keyframe].cuetime)
{
Cue* reader = active_cues_head;
if(reader != NULL)
{
while(reader != NULL && reader.next != NULL)
{
reader = reader.next;
}
}
var i;
for(i = 0; i < scene[cutscene_keyframe].actions_count; i += 1)
{
Cue* thiscue = newCue();
memcpy(thiscue,scene[cutscene_keyframe].actions[i],sizeof(Cue)); //ERROR HERE
if(reader == NULL)
{
active_cues_head = thiscue;
reader = thiscue;
}
else
{
reader.next = thiscue;
reader.next.prev = reader;
reader = reader.next;
}
}
cutscene_keyframe += 1;
}
Cue* reader = active_cues_head;
while(reader != NULL)
{
if((reader.starttime + reader.duration) < cutscene_time)
{
file_var_write(flog,reader.starttime);
file_var_write(flog,reader.duration);
Cue* killme = reader;
if(reader == active_cues_head && reader.next != NULL)
{
reader.next.prev = NULL;
active_cues_head = reader.next;
reader = reader.next;
}
else if(reader == active_cues_head && reader.next == NULL)
{
active_cues_head = NULL;
reader = NULL;
}
else if(reader.next == NULL)
{
reader.prev.next = NULL;
reader = NULL;
}
else
{
reader.prev.next = reader.next;
reader.next.prev = reader.prev;
reader = reader.next;
}
free(killme);
}
else
{
if(reader.entname == NULL)
{
var factor = (cutscene_time - reader.starttime) / reader.duration;
vec_lerp(camera.x,reader.startpos,reader.endpos,factor);
vec_lerp(camera.pan,reader.startang,reader.endang,factor);
}
else
{
ENTITY* actor = ent_for_name(reader.entname);
var factor = (cutscene_time - reader.starttime) / reader.duration;
if(vec_dist(reader.startpos,reader.endpos) != 0) vec_lerp(actor.x,reader.startpos,reader.endpos,factor);
if(vec_dist(reader.startang,reader.endang) != 0) vec_lerp(actor.pan,reader.startang,reader.endang,factor);
if(vec_dist(reader.startscale,reader.endscale) != 0) vec_lerp(actor.scale_x,reader.startscale,reader.endscale,factor);
if(reader.anim != NULL) ent_animate(actor,reader.anim,(factor * 100 * reader.animloops) % 100,ANM_CYCLE);
}
reader = reader.next;
}
}
cutscene_time += time_frame;
}
wait(1);
}
file_close(flog);
}
function pauseScene()
{
cutscene_paused = 1;
}
function unpauseScene()
{
cutscene_paused = 0;
}
function freeScene()
{
free(scene);
}
action actor()
{
wait(1);
}
|
|
|
Re: need help with these structs im using
[Re: The_Clyde]
#327590
06/07/10 13:59
06/07/10 13:59
|
Joined: Dec 2005
Posts: 116
tD_Datura_v
Member
|
Member
Joined: Dec 2005
Posts: 116
|
A quick note: It might be assumed ...that the vector() function is not roughly equivalent to the str_create function ...and that the vector() function might return a VECTOR from a shared internal pool, ...and that such memory probably should not be directly freed by the user. VECTORs and ANGLEs might be declared in structs as such:
typdef struct t{
ANGLE a1;
VECTOR v1;
} t;
Of course that might be "ill-advised".
|
|
|
Re: need help with these structs im using
[Re: The_Clyde]
#327695
06/07/10 22:44
06/07/10 22:44
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
Expert
|
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
The way tD_Datura_v says is the best way, IMHO, but others may disagree. So i would use define the structs this way
typedef struct Cue {
STRING* entname;
VECTOR startpos;
VECTOR endpos;
ANGLE startang;
ANGLE endang;
VECTOR startscale;
VECTOR endscale;
STRING* anim; //animation name- or NULL
var animloops;
var starttime;
var duration;
struct Cue* next; //used when the cue is in the linked list of active cues
struct Cue* prev;
} Cue;
typedef struct Keyframe {
var cuetime;
var actions_count;
Cue* actions[64];
} Keyframe;
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
Re: need help with these structs im using
[Re: EvilSOB]
#327696
06/07/10 22:54
06/07/10 22:54
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
Expert
|
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
Next, when passing custom objects as parameters or return values, be specific wherever possible.
Cue* newCue()
{
Cue* newcue = sys_malloc(sizeof(Cue));
memset(newcue,0,sizeof(Cue));
return newcue;
}
Keyframe* newKeyframe()
{
Keyframe* newkeyframe = sys_malloc(sizeof(Keyframe));
memset(newkeyframe,0,sizeof(Keyframe));
return newkeyframe;
}
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
Re: need help with these structs im using
[Re: EvilSOB]
#327700
06/07/10 23:28
06/07/10 23:28
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
Expert
|
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
Lastly, whenever you are removing an object, be sure to remove all its sub-objects too, before removing the object itself. That way youve still got access to them. This is assuming of course the the sub-objects in question are NOT "shared" between objects.
function killCue(Cue* c)
{
if(c.entname) str_remove(c.entname);
if(c.anim) str_remove(c.anim);
//note: dont free c.next and c.prev, cause they are shared
sys_free(c);
}
function killKeyframe(Keyframe* k)
{
var i; for(i=0; i<64; i++)
{
if((k.actions)[i])
{ killCue((k.actions)[i]); }
}
sys_free(k);
}
Note :: I havent looked at loadscene or playscene yet as that would require more time than I have to spare ATM. I'll try to take a look at work tonite... Hope thtis has ben informative.
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
Re: need help with these structs im using
[Re: EvilSOB]
#327701
06/07/10 23:33
06/07/10 23:33
|
Joined: Jul 2008
Posts: 223 Pittsburgh
The_Clyde
OP
Member
|
OP
Member
Joined: Jul 2008
Posts: 223
Pittsburgh
|
Should I malloc the Cue array as well when I create the new Keyframe? also- thank you very much, you've been VERY informative
Last edited by The_Clyde; 06/07/10 23:34.
|
|
|
Re: need help with these structs im using
[Re: The_Clyde]
#327703
06/07/10 23:47
06/07/10 23:47
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
Expert
|
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
You CAN if you want, but that will eat up memory with all the un-used Cue's.
I would suggest calling a "newCue" only when you need to (ie. you have data to put in it), from within "loadScene" or from within your (as yet un-built) editor.
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
|