Entraides et échanges autour de la technologie Scol - Informations and exchanges on the Scol technology
Vous pouvez changer la langue de l'interface une fois inscrit - You can change the language once registered
You are not logged in.
no this is not implemented that way for now.
what the purpose here ? you mean you want a skeleton file per animation ?
I see. Not one skeleton per animation but one fk animated skeleton and one ik skeleton....so I don't have to do as much work in blender. No worries I'll look into an fk ik switch in blender.
I'm not sure about Ogre, but the answer is no with the SO3Engine.
But a skeleton can have several root bones.
thx Arkeon
I see...I don't think my question was clear enough. What I meant was can a .mesh use skeleton 1, then os3d unlocks skeleton 1 and links another skeleton to the same mesh.
Colleagues. ...I couldn't find an answer on ogre3d.org...can one .mesh use multiple skeletons (I'm making a rig in blender and would like to use an ik version and an fk version.....but this is pretty complicated in blender, it would be easier just to use two skeletons)
i'm rebuilding it so it has only manifold geometry (normal shaders don't like using planes so i gave up on the old model)


Well, few remarks in vrac.
//fun [] I
//get an id from lDeleted_cylinder_ids....if there are no ids available, return 0, once an index is encountered, return the index
fun get_deleted_cylinder_ID ()=Are you sure that an index will never be equal at 0 ? If no, you should return nil instead if the deleted list is empty.
Thx I changed that, I don't know how the index could ever be zero, but nil does seem safer.
You should rename explicitely your variables. By example, in lDeleted_cylinder_ids, the first l for a list is ok. But lindex is an integer, not a list. Why this first l ? An i (iIndex by example) is more comprehensive for the reader. And if the second character is upper, keep this convention.
I'll do that when I work on my throttle plugit that I never finished.
To optimize easily the memory, you should avoid to define uselessly some locale variables. By example :
fun add_cylinder()=
(...)
let @birthphase -> birth_function in
let @deathphase -> death_function in
let @returnvolume-> volume_function in
let @returnarea -> area_function in
(
//assign birth and death functions
set lcylinder.fbirthfunction = birth_function;
set lcylinder.fdeathfunction = death_function;
set lcylinder.funreturnarea = area_function;
set lcylinder.funreturnvolume = volume_function;
(...)Write instead :
fun add_cylinder()=
(...)
(
//assign birth and death functions
set lcylinder.fbirthfunction = @birthphase ;
set lcylinder.fdeathfunction = @deathphase;
set lcylinder.funreturnarea = @returnvolume;
set lcylinder.funreturnvolume = @returnarea;
done
If i understand correctly, you want keep the index value when a cylinder is deleted ? Right ?
yes
If several life span exist, set several lists may be another method, instead of a big list. One list by life span. It is an idea ...
Or, if you know, you could use an hash table (otherwise, forget that !).
I set things up so the lifespan is anywhere from ms to around 1638 ms.
A timer object (not only in Scol) is always a greedy object. Some timers are ok. A large number can be problematic, especially as they are destroyed to the first "top". Perhaps, one timer by life span and all cylinders (for a given life span) are created and destroyed in the same "top" ? Depending on your project, of course.
If the vm had something like a built in frame by frame callback, I could build some sort of 'kill' function depending on the lifespan left in each cylinder. But os3d does, and that's where I want to apply this knowledge.
This is a good start !
Thanks! I think I'll end it here, these cylinders have had enough attention from me. Perhaps this example will help others who want to see how you can build simple objects and have them do things, albeit trival things. On to something some other people can actually use.
I still haven't figured how to configure bluefish so I can paste the code into posts correctly, here is the .pkg:
to re familiarize myself with scol for this winter's efforts (I hope to actually finish some project, however small, a plugit at least that others can use, maybe the throttle from last year, or using arkeon's avatar plugit to support user determined meshes for virtual meetings and, at my son's request, fps shooters), I made a script that creates objects, executes their functions, and destroys them by building and destroying lists. it puts the objects in one list and their unique indexes in another list, and minimizes the time consuming recursive list functions (searching through a list to find, do, add, or remove something) to one. maybe this could be used in a simple fps game, where the players are hiding behind structures that appear and disappear randomly.
i'm sure there are more elegant ways to do this. i wanted to write a script that could store unused indecies for objects in one list, so that when there were available indices, the vm would not have to iterate through an entire list. i was thinking of setting the maximum index each time a new object (cylinder) was created, but if the objects have different lifespans, I'm not sure if that would work.
struct Cylinder =[
Icylindernumber : I,
Icylinderindex : I,
Fradius : F,
Fheight : F,
funlifespan : Timer,
Ilifespanlength : I,
Sbirthfphrase : S,
Sdeathphrase : S,
fundyingclyinder : fun [Cylinder] S,
funreturnarea : fun [Cylinder] F,
funreturnvolume : fun[Cylinder] F,
fbirthfunction : fun[Cylinder] S,
fdeathfunction : fun[Cylinder] S
]mkCylinder;;
//global list of Cylinders to grow and shrink
typeof lCylinderlist=[Cylinder r1];;
//global list of intergers to grab for new cylinders if they are free and to hold indeces of dead cylinders
typeof lDeleted_cylinder_ids = [I r1];;
typeof ICylinder_counter= I;;
var Ihighest_Cylinder_Index= 0;;
//fun [Cylinder] F
fun returnarea(cylinder)=
PIf*. cylinder.Fradius;;
//fun [Cylinder] F
fun returnvolume(cylinder)=
(returnarea cylinder)*. cylinder.Fheight;;
//fun [Cylinder] S
fun birthphase(cylinder)=
_fooS strcatn "My name is: ":: (itoa(cylinder.Icylinderindex))::" and now I am being born, hello!"::nil;
_fooS strcatn "My lifespan is :":: (itoa (cylinder.Ilifespanlength)):: " milliseconds."::nil;;
//fun [Cylinder] S
fun deathphase(cylinder)=
_fooS strcatn "My name is: ":: (itoa(cylinder.Icylinderindex))::" and now I am dying, goodbye!"::nil;;
/* --------- */
// Miscelleanous
// Note : A function already exists for that in the standard library
fun removeItemInList (list, item)=
if list == nil then
nil
else
if item == hd list then
tl list
else
(hd list) :: removeItemInList tl list item;;
/* --------- */
//fun [] I
//get an id from lDeleted_cylinder_ids....if there are no ids available, return 0, once an index is encountered, return the index
fun get_deleted_cylinder_ID ()=
_fooS "get_deleted_cylinder_ID called";
let hd lDeleted_cylinder_ids -> head in
(
if (head == nil) then
(
// there are no available deleted cylinder indexes, they have been used up between the function calling this function and the execution
//of the line below
nil;
) else
(
_fooS strcatn "head of lDeleted_cylinder_ids is ":: (itoa head)::nil;
//remove head from lDeleted_cylinder_ids
set lDeleted_cylinder_ids= (tl lDeleted_cylinder_ids);
_fooS strcatn "the new head of the lDeleted_cylinder_ids list is: " ::(itoa(hd lDeleted_cylinder_ids))::nil;
_fooS strcatn "the head of the list in this function after resetting list is: ":: (itoa head)::nil;
head;
);
);;
//fun [[Cylinder r1] I] I
fun get_highest_id_from_cylinderlist (cylinderlist, id)=
//we want to get the highest Cylinder.Icylinderindex that exists in this list
if ((hd cylinderlist)==nil)&& ((sizelist lCylinderlist)==0) then
(
_fooS "there are no items in the list at all";
1;
)
else if ((hd cylinderlist)==nil)&& ((sizelist lCylinderlist)>0) then
(
_fooS "we are at the end of a list that has items in it";
_fooS strcat "the following value is the highest value found in the complete list is: " (itoa id);
//since we are making a new cylinder with an index that does not exist, increment global
//Ihighest_Cylinder_Index by 1 from the highest found id
set Ihighest_Cylinder_Index = id+1;
Ihighest_Cylinder_Index;
)
else
//we are not at the end of the list yet
(
//_fooS "there are items in the list and we are not at the end yet";
let hd cylinderlist -> cylinder in
let cylinder.Icylinderindex -> this_index in
if (this_index > id) then
(
set id = this_index;
//_fooS strcat "the highest id found so far is: " (itoa id);
//we havve the higghest id so far, recursively search through rest of list
//to see if we can find a higher id
get_highest_id_from_cylinderlist (tl cylinderlist) id;
)
else
(
//don't change the id, we have the highest found so far
//so we recursively search through rest of list
// _fooS strcat "the highest id found so far is: " (itoa id);
get_highest_id_from_cylinderlist (tl cylinderlist) id;
);
);;
//fun[] I
fun get_highest_id_from_all_lists()=
let get_deleted_cylinder_ID -> result in
(
//if there are no items in lDeleted_cylinder_ids, go search for highest id in lCylinderlist
if (result == nil) then
(
get_highest_id_from_cylinderlist lCylinderlist nil;
)
else
(
result;
);
);;
//fun [cylinder] lCylinderlist
fun delete_cylinder(timer, dcylinder)=
//destroy the timer
_deltimer timer;
//execute death function
exec dcylinder.fdeathfunction with [dcylinder];
//add the deleted cylinder index to the lDeleted_cylinder_ids list, so we can grab it if it is free and we add a new cylinder
let dcylinder.Icylinderindex -> lindex in
(
_fooS strcatn "cylinder with index number ":: (itoa lindex):: " has died"::nil;
//add index to lDeleted_cylinder_ids
set lDeleted_cylinder_ids =lindex:: lDeleted_cylinder_ids;
//decrement amount of cylinders in existence
set ICylinder_counter= ICylinder_counter-1;
//remove cylinder from lCylinderlist
set lCylinderlist= removeItemInList lCylinderlist dcylinder;
_fooS strcatn "there are now :" ::(itoa(sizelist lDeleted_cylinder_ids))::" cylinders in the lDeleted_cylinder_ids list."::nil;
_fooS "the list of deleted cylinder id's is below:";
_fooIdList lDeleted_cylinder_ids;
_fooS strcatn "there are now ":: (itoa (sizelist lCylinderlist))::" cylinders in the lCylinderlist. \n \n \n":: nil;
lCylinderlist;
);;
//fun [Cylinder Timer] Cylinder
fun makeCylinderTimer (sCylinder, lifespan)=
//assign the lifespan in milliseconds for our ephemeral cylinder
set sCylinder.Ilifespanlength = lifespan;
set sCylinder.funlifespan = _rfltimer _starttimer _channel lifespan @delete_cylinder sCylinder;
sCylinder;;
//fun [] Cylinder
fun add_cylinder()=
//whenever we add a cylinder, no matter where its id comes from, we are incemeneting the ICylinder_counter by one
set ICylinder_counter=ICylinder_counter+1;
//get cylinder id
let get_highest_id_from_all_lists -> id in
let mkCylinder [ICylinder_counter id 2.0 22.0 nil nil nil nil nil nil nil nil nil ]->lcylinder in
let rand/20 -> llifespan in
let makeCylinderTimer lcylinder llifespan-> lcylinder in
(
//assign birth and death functions
set lcylinder.fbirthfunction = @birthphase;
set lcylinder.fdeathfunction = @deathphase;
set lcylinder.funreturnarea = @returnvolume;
set lcylinder.funreturnvolume = @returnarea;
//execute birth function
_fooS "\n \n \n \n";
_fooS "new cylinder created!";
exec lcylinder.fbirthfunction with [lcylinder];
let exec lcylinder.funreturnarea with [lcylinder] ->result in
_fooS strcat "my area is " (ftoa result);
let exec lcylinder.funreturnvolume with [lcylinder] ->result in
_fooS strcat "my volume is " (ftoa result);
//add cylinder to global lCylinderlist
set lCylinderlist= lcylinder::lCylinderlist;
_fooS strcatn "there are now ":: (itoa (sizelist lCylinderlist))::" cylinders in the lCylinderlist.":: nil;
_fooS strcatn "the new cylinder id is: ":: (itoa id)::nil;
lcylinder;
);;
fun add_another_cylinder_after_timer(timer, param)=
_deltimer timer;
let 100 -> counter in
while (counter >0) do
(
add_cylinder;
set counter= counter-1;
);;
fun main()=
_showconsole;
let 20 -> counter in
while (counter >0) do
(
add_cylinder;
set counter= counter-1;
);
_rfltimer _starttimer _channel 4000 @add_another_cylinder_after_timer nil;;[edited] as per most of Iri's suggestions.
This is normal. The returned list is your result.
set list1 = remove_from_list list1 561;and you are happy
yes I am thx!
by inference, the cause is probably me, but here it is, neither remove_from_list and removeItemInList seem to be removing the requested item from the list
![]()
typeof list1 =[I r1];;
typeof list2 =[I r1];;
fun remove_from_list(l,p)=
if l==nil then nil
else let l -> [a nxt] in
if a==p then nxt
else a::remove_from_list nxt p;;
fun removeItemInList (list, item)=
if list == nil then
nil
else
if item == hd list then
tl list
else
(hd list) :: removeItemInList tl list item;;
fun main()=
_showconsole;
set list1= 2::8::561::591::nil;
set list2= 2::8::561::591::nil;
_fooS "we are starting with list1 below:";
_fooIdList list1;
remove_from_list list1 561;
_fooS "the list after remove_from_list is below";
_fooIdList list1;
_fooS "we are starting with list2 below:";
_fooIdList list2;
removeItemInList list2 561;
_fooS "the list after removeItemInList is below";
_fooIdList list2;;Thanks for the correction Iri .....bluefish indents fone for me but I lose the tabs when I paste into posts. I will try changing that setting Arkeon.
[edit] I checked out my code....I hadn't pasted all of it in and it looks more or like your correct function Iri.
But I get the point...if you can avoid stepping through a list, especially a big one, it's better to do that.
Edited to reflect Iri's observation below, although I'm still having problems with formatting indents from bluefish.
There is probably a list function that would make this easier, but, in any case, if you have a struct of whatever kind, and one of the fields of the struct, named Iwhateverindex is an interger, and you are trying to find the object that has the highest Iwhateverindex , this is how you can do it. in this example, the Iwhateverindex property is named Icylinderindex:
struct Cylinder =[
Icylindernumber: I,
Icylinderindex: I,
Fradius : F,
Fheight : F,
Tlifespan : Timer,
Sbirthfphrase : S,
Sdeathphrase : S,
fundyingclyinder: fun [Cylinder] S,
funreturnarea : fun [Cylinder] F,
funreturnvolume: fun[Cylinder] F
]mkCylinder;;
typeof lCylinderlist=[Cylinder r1];;
typeof lDeleted_cylinder_ids= [I r1];;
typeof ICylinder_counter= I;;
var Ihighest_Cylinder_Index= 0;;
fun get_highest_id_from_cylinderlist (cylinderlist, id)=
//we want to get the highest Cylinder.Icylinderindex that exists in this list!!!!!
if ((hd cylinderlist)==nil)&& ((sizelist lCylinderlist)==0) then
(
_fooS "there are no items in the list at all";
1;
)
else if ((hd cylinderlist)==nil)&& ((sizelist lCylinderlist)>0) then
(
_fooS "we are at the end of a list that has items in it";
_fooS strcat "the following value is the highest value found in the complete list is: " (itoa id);
id;
)
else
//we are not at the end of the list yet
(
_fooS "there are items in the list and we are not at the end yet";
let hd cylinderlist -> cylinder in
let cylinder.Icylinderindex -> this_index in
if (this_index > id) then
(
set id = this_index;
_fooS strcat "the highest id found so far is: " (itoa id);
//we havve the higghest id so far, recursively search through rest of list
//to see if we can find a higher id
get_highest_id_from_cylinderlist (tl cylinderlist) id;
)
else
(
//don't change the id, we have the highest found so far
//so we recursively search through rest of list
_fooS strcat "the highest id found so far is: " (itoa id);
get_highest_id_from_cylinderlist (tl cylinderlist) id;
);
);;
fun main()=
_showconsole;
let mkCylinder [1 879 nil nil nil nil nil nil nil nil]-> cylinder1 in
let mkCylinder [2 1056 nil nil nil nil nil nil nil nil]-> cylinder2 in
let mkCylinder [3 3456 nil nil nil nil nil nil nil nil]-> cylinder3 in
set lCylinderlist = cylinder1:: cylinder2::cylinder3::lCylinderlist;
let nth_list lCylinderlist 0-> dcylinder in
let dcylinder.Icylinderindex -> index in
_fooS strcatn "the result of the index search through the list is: ":: (itoa (get_highest_id_from_cylinderlist lCylinderlist nil))::nil;;Thx Arkeon and iri....my brother just confirmed this (and explained it more to me...he teaches computer science at the university level).
I don't remerber precisely.
(hd list) :: removeItemInList tl list item;This line removes nothing. Instead of that, it adds (so, it keeps) the current item.
In fact, once the function finishes, the returned list is the truncated list.
Thus, it is after the line below that a GC could free the deleted item.set lCylinder = removeItemInList lCylinder sCylinder;I'm clear ?
Oops I quoted the wrong line....yes its clear now.
gc take time so you should use it really only when you need it.
sometimes it's worst than better so do not abuse
I see, so at what point does the vm free the memory taken up by the cylinder after the removal of a cylinder from the global list lCylinder in the line below? Answer at your leisure.
(hd list) :: removeItemInList tl list item;Aha...are there drawbacks to using it?
thx iri, my goal is dynamically creating and destroying objects in a global list while minimizing the amount of memory taken up by them. so if the list is full, no more objects can be created, the objects are periodically 'dying' which means emptying the of value, and when time comes to create a new object, if there is an object with empty values in the list (or array, perhaps an table as you made it is a better solution), then that object is filled with new values
I coded with a list, because, for a time, memory allocation is less than if creating a table it automatically has the maximum numbers of elements. I'm just figuring out (for the sake of it) how to create and destroy lots of objects while being the most efficient with memory, so that local objects are not left on the heap and taking up memory where they can just be emptied of values and refilled with new ones
The problem I'm trying to think through is: if you create a local object and remove it from a list, then it's occupying memory until the garbage collector steps in. So if I cannot manually deallocate the memory set aside for an object, it's better to empty the values from an object and insert new values into it
I hope that makes things clear (and that will be determined by how clear the ideas are to me, which I'm not quite sure of here)
Thanks as always Iri
I will study your code iri it's much simpler than my spaghetti
arkeon's suggestion fixed things...but from your other post there is a more elegant way of going about this
Aahhh! Or Ack! Thx Arkeon! I thought it would be more likely to be a stupid error, though it looked so strange...
hello
for the following code:
//variable to keep track of total created cylinders
var Cylinder_counter = 0;;
//variable to keep track of empties cylinders
var Emptied_Cylinders =0;;
struct Cylinder =[
Fradius : F,
Fheight : F,
funreturnheightasintergerasstring: fun[Cylinder] S,
funreturnarea : fun [Cylinder] F,
funreturnvolume: fun[Cylinder] F
]mkCylinder;;
typeof Cylinderlist = [[I Cylinder]r1];;
typeof Deleted_Cylinder_list =[I r1];;
fun returnheight(dcylinder)=
let ftoi dcylinder.Fheight -> height in
itoa height;;
fun killcylinder (trm, param)=
let param -> [dcylinderindex dcylinder] in
(
//empty cylinder of all its values, it is now empty and its index is added to the Deleted_Cylinder_list
set dcylinder.Fradius=nil;
set dcylinder.Fheight=nil;
set dcylinder.funreturnheightasintergerasstring=nil;
set dcylinder.funreturnarea=nil;
set dcylinder.funreturnvolume=nil;
set dcylinder=nil;
set Deleted_Cylinder_list = dcylinderindex::Deleted_Cylinder_list;
_fooS strcatn "Just killed a cylinder with index: "::(itoa dcylinderindex):: nil;
);
0;;
fun return_area_function(dyclinder)=
let dyclinder.Fradius *. PIf-> result in
result;;
fun return_volune_function(dyclinder)=
let return_area_function dyclinder-> area in
area *. dyclinder.Fheight;;
fun initcylinder(radius, height, returnheightfunction, returnareafunction, returnvolumefunction)=
_fooS "initializing cylinder";
mkCylinder [radius height returnheightfunction returnareafunction returnvolumefunction];;
fun see_if_we_can_make_a_new_cylinder (deletedcylinderslist, radius, height) =
if ((sizelist deletedcylinderslist)==0) then
(
_fooS "sorry, there are a maximum number of cylinders and none are free to assign new values to";
0;
)
else
(
//get an index from the Deleted_Cylinder_list and fill it with new values, search Deleted_Cylinder_list recursively
if ((hd deletedcylinderslist) != nil) then
(
//fill a deleted cylinder with new values and put the values in the Cylinderlist
let initcylinder radius height @returnheight @return_area_function @return_volune_function -> lcylinder in
let hd deletedcylinderslist -> cylinderindex in
let switch cylinderindex Cylinderlist -> cylinder_to_change in
set cylinder_to_change =lcylinder;
_fooS "cylinder filled with new values.";
0;
)
else
(
see_if_we_can_make_a_new_cylinder (tl deletedcylinderslist) radius height;
0;
);
0;
);
0;;
fun makenewcylinder2(dfradius,dfheight )=
//first check if Cylinderlist is full. If it's full, then we will have to see if there are any empty cylinders in the Deleted_Cylinder_list
//that we can fill with new values
//I set an arbitrary nubmer of 1000 cylinders
if ((sizelist Cylinderlist)>1001) then
(
//the list is full, find out if there are any cylinders in the deleted cylinder list that can be assigned new values
see_if_we_can_make_a_new_cylinder Deleted_Cylinder_list dfradius dfheight;
0;
)
else
(
//the Cylinderlist is not full, so we can add a new cylinder and index to the head of the Cylinderlist
let initcylinder dfradius dfheight @returnheight @return_area_function @return_volune_function -> lcylinder in
let ((sizelist Cylinderlist)-1)-> lcylinderlistsize in
let [lcylinderlistsize lcylinder] -> cylinderparamter in
(
set Cylinderlist = [lcylinderlistsize lcylinder]:: Cylinderlist;
_rfltimer _starttimer _channel 2500 @killcylinder cylinderparamter;
);
0;
);
0;;
fun main()=
_showconsole;
set Deleted_Cylinder_list = nil;
_fooS "the code up to now has compiled OK!";
let 2000 -> counter in
(
while (counter > 0)do
(
makenewcylinder2 1.0 12.0;
set counter = counter-1;
);
);
0;;
I get a typing error at this line:
see_if_we_can_make_a_new_cylinder Deleted_Cylinder_list dfradius dfheight;even though the global variable Deleted_Cylinder_list is of the type [I r1], the vm shows the following typing error for the line directly above:
line 455 in ..\..\..\..\..\vm\kernel5\src\compiler\typmisc.cpp
File : C:\Users\Damiel Green\Documents\OpenSpace3D\customobjectfunctions\cylinderobjectlist.pkg
(!) Line #92:
see_if_we_can_make_a_new_cylinder Deleted_Cylinder_list dfradius dfheight??;
>>> ERROR - Type mismatch (detail):
Found: [[I r1] u0 u1]
Expected: [[[[[[I Cylinder] r1] Cylinder] r1] r1] F F]I don't know why the vm thinks that see_if_we_can_make_a_new_cylinder is not taking the correct argument of [I r1] and instead is expecting it to take [[[[[[I Cylinder] r1] Cylinder] r1] r1] F F]...maybe it's a bug in the kernel, although it's probably me...
wip, i still have to manage the removal of specific cylinders from the cylinderlist with a timer, and i think i have to pass the index between a (some) function(s). todo..the objects have lifespans, and once the amount of cylinders reaches a specific number, the vm will have to wait for them to 'die' (be emptied of content) before they can be refilled with new values (two floats, radius and height)
typeof Cylinderlist = [[I Cylinder]r1];;
typeof Deleted_Cylinder_list =[I r1];;
//variable to keep track of total created cylinders
var Cylinder_counter = 0;;
//variable to keep track of empties cylinders
var Emptied_Cylinders =0;;
struct Cylinder =[
Fradius : F,
Fheight : F,
funreturnheightasintergerasstring: fun[Cylinder] S,
funreturnarea : fun [Cylinder] F,
funreturnvolume: fun[Cylinder] F
]mkCylinder;;
fun returnheight(dcylinder)=
let ftoi dcylinder.Fheight -> height in
itoa height;;
fun killcylinder (dcylinder)=
_fooS "stub for now, this function will kill cylinder,using the deletecylinder function with an index in the [[I Cylinder]r1] Cylinder list with a timer";;
fun return_area_function(dyclinder)=
let dyclinder.Fradius *. PIf-> result in
result;;
fun return_volune_function(dyclinder)=
let return_area_function dyclinder-> area in
area *. dyclinder.Fheight;;
fun initcylinder(radius, height, returnheightfunction, returnareafunction, returnvolumefunction)=
_fooS "initializing cylinder";
mkCylinder [radius height returnheightfunction returnareafunction returnvolumefunction];;
//deletes the first cylinder in the cylinder list
fun deletecylinder(cylinderlistindex)=
if ((sizelist Cylinderlist) == 0) then
(
_fooS "there are no cylinders to delete! none have been placed in the Cylinderlist yet!";
0;
)
else
(
let hd Cylinderlist -> [index dcylinder] in
(
//this does not remove the cylinder from the cylinder list, since it will still be in memory although unreachable, and we want to be as efficient as possible
//this function sets all the cylinder values to nil, and then places the index of the cylinder in the Deleted_Cylinder_list, so the vm can use the index
//this cylinder searches through the cylinder list to find a cylinder that still exists, and empties it of all values, I will use cylinderlistindex later
set dcylinder.Fradius=nil;
set dcylinder.Fheight=nil;
set dcylinder.funreturnheightasintergerasstring=nil;
set dcylinder.funreturnarea=nil;
set dcylinder.funreturnvolume=nil;
set dcylinder=nil;
set Deleted_Cylinder_list = index::Deleted_Cylinder_list;
_fooS strcatn (itoa (sizelist Deleted_Cylinder_list)):: " cylinders have been deleted, or, rather, set to nil in Cylinderlist." ::nil;
);
0;
);
0;;
//this function makes a new cylinder, given it's float radius and float height
fun makenewcylinder(fradius, fheight)=
if ((sizelist Deleted_Cylinder_list) == 0) then
(
//no cylinders have been deleted yet! place the new cylinder at the beginning of the list
_fooS "No cylinders have been deleted yet";
_fooS strcat (itoa sizelist Deleted_Cylinder_list) " are the amount of objects in the Deleted Cylinder list!";
let initcylinder fradius fheight @returnheight @return_area_function @return_volune_function -> lcylinder in
let Cylinderlist -> lcylinderlist in
let Cylinder_counter -> lcylindercounter in
(
set Cylinderlist = [lcylindercounter lcylinder]::Cylinderlist;
set Cylinder_counter = Cylinder_counter+1;
_fooS strcatn "there are: " :: (itoa (sizelist Cylinderlist)):: " cylinders in the Cylinderlist"::nil;
_fooS "this cylinder will live for 500 milliseconds, then the vm will kill it";
killcylinder lcylinder;
0;
);
)
else
//get an index from the deleted cylinder list
(
let sizelist Deleted_Cylinder_list ->lcounter in
(
while lcounter >0 do
(
if ((hd Deleted_Cylinder_list) != nil) then
(
let hd Deleted_Cylinder_list -> lDeleted_Cylinder_listindex in
(
//do switch statement here! use index from head of Deleted_Cylinder_list and get Cylinder from the [I Cylinder] tuple in Cylinderlist
//and put new values into that cylinder. that way you are using already allocated memory for a cylinder set to 'nil' for all its values
//fetch a nil Cylinder from the lDeleted_Cylinder_listindex and put the radius and height values in it
let switch Cylinderlist lDeleted_Cylinder_listindex -> dcylinder in
(
set dcylinder = initcylinder fradius fheight @returnheight @return_area_function @return_volune_function;
_fooS "filled an empty cylinder with new values!";
killcylinder dcylinder;
);
set lcounter = lcounter-1;
0;
)
)
else
(
set lcounter = lcounter-1;
0;
);
)
);
0;
);
0;;
fun main()=
_showconsole;
_fooS "the code up to now has compiled OK!";
deletecylinder nil;
makenewcylinder 1.0 12.0;
makenewcylinder 411.0 102.0;
deletecylinder nil;
makenewcylinder 411.0 102.0;;
I don't think in this case sorting is an issue because if I have a list of tuples such as [[I objecttype]r1] there are plenty of ways to find an object that has been emptied of values.
Thanks for answering these relatively abstract questions. They are applicable to any app/game/simulation where the vm is continually creating and destroying objects prior to vm shutdown. Another section for the O'Reilly book.
I see, perhaps then if I create a global list like
typeof Cylinderlist= [[I Cylinder] r1];;and
typeof Deleted_Cylinderlist= [I r1];;I can add a new cylinder to the global list, and when a particular indexed cylinder and all its fields are set to NIL,its index is created in the Deleted_Cylinderlist.
When time comes to create a new cylinder, the vm could assign a new Cylinder to an index in the Deleted_Cylinderlist, and fill an 'empty' cylinder in the Cylinderlist with new values.
That way if hundreds of cylinders are being created and destroyed a second, and you have something like a hard limit to the number of cylinders (like, say 10,000), an empty Cylinder can be retrieved from the list and assigned new values, so the vm could search through the list of empty indexes in the Deleted_Cylinderlist, pick one index, and put new values in an empty Cylinder in the [[I Cylinder] r1] list.
Or something along those lines.
I see, so what happens to the memory allocated by
let createLocalStructure 15 "Shinning" -> local inwhen
(
set local = nil;
);in other words, are the memory addresses allocated by "local" now free to be assigned to other variables, such as other MyStructures?
thanks Iri!
so what exactly does the code:
set dcylinder = nil;do in terms of freeing memory.
what I'm thinking of is how scol would handle a game or simulation where you have, say, thousands of animals swimming around the viewer (most would not be rendered by the so3 engine, but scol would keep track of them since once they come close to the viewer, they will become visible), where each animal holds variables like strings (names), hit-points (integers) and transforms ([scale][location][rotation][speed][transform coefficient])[FFF][FFF][FFFF][F][F] tuples, where they are eating each other and mating, therefore destroying and creating new animals, increasing and decreasing hitpoints.
or the simulation of a planet containing thousands of scene nodes (buildings or perhaps life forms) which must be dynamically created and destroyed.
I see. In the example above, two cylinders are created, one with initcylinder and the other with copy_this_cylinder. Is there a way I could use scol code at the end of the main function to deallocaye memory before main terminates and the cylinders become unreachable?
I've seen many functions in the 3d API to destroy objects but was wondering what to do with other objects, like basic scol types or structs.