need help with these structs im using

Posted By: The_Clyde

need help with these structs im using - 06/07/10 01:50

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:
Code:
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...
Posted By: EvilSOB

Re: need help with these structs im using - 06/07/10 03:09

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...


Posted By: The_Clyde

Re: need help with these structs im using - 06/07/10 03:36

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 grin

As for secrecy- its not so important since I've already detailed my algorithm anyway....
Code:
#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);
}


Posted By: tD_Datura_v

Re: need help with these structs im using - 06/07/10 13:59

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:
Code:
typdef struct t{
	ANGLE a1;
	VECTOR v1;
} t;



Of course that might be "ill-advised".
Posted By: The_Clyde

Re: need help with these structs im using - 06/07/10 18:40

That makes a good deal of sense. It there a correct way to handle vectors and angles in structs or is it better to create and address them as separate vars?
Posted By: EvilSOB

Re: need help with these structs im using - 06/07/10 22:44

The way tD_Datura_v says is the best way, IMHO, but others may disagree.

So i would use define the structs this way
Code:
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;


Posted By: EvilSOB

Re: need help with these structs im using - 06/07/10 22:54

Next, when passing custom objects as parameters or return values,
be specific wherever possible.

Code:
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;
}


Posted By: EvilSOB

Re: need help with these structs im using - 06/07/10 23:28

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.

Code:
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.
Posted By: The_Clyde

Re: need help with these structs im using - 06/07/10 23:33

Should I malloc the Cue array as well when I create the new Keyframe?

also- thank you very much, you've been VERY informative laugh
Posted By: EvilSOB

Re: need help with these structs im using - 06/07/10 23:47

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.
Posted By: The_Clyde

Re: need help with these structs im using - 06/14/10 17:42

-Still can't figure this out frown

It seems that I'm doing something wrong in playScene that causes a problem when more than one cue is loaded...
Posted By: The_Clyde

Re: need help with these structs im using - 06/14/10 18:33

I think my problem is in
Code:
Cue* thiscue = newCue();
memcpy(thiscue,scene[cutscene_keyframe].actions[i],sizeof(Cue));



because thats where it gets to as it crashes.

I have an array "scene" of pointers to Keyframe structs. Among the members of the Keyframe struct is an array "actions" of pointers to Cue structs. I want to copy the content of a Cue from "actions" from a Keyframe from "scene".

Is the above code correct for doing this?
Posted By: The_Clyde

Re: need help with these structs im using - 06/14/10 19:01

Okay then it turns out my problem was a typo that created wrong function behavior leading to a crash, but the typo was still proper syntax so it didn't cause compile errors. Only a runtime error later in the program tongue

Even though the real problem wasn't related- thanks again EvilSOB for helping me out with the struct problems that might have become a problem later!
Posted By: EvilSOB

Re: need help with these structs im using - 06/14/10 21:49

No problems dude.

If you have any more problems or questions with it, just yell out here...
© 2024 lite-C Forums