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.
Hello everyone, long time, no code, but it's cold again in n.a, and I'm back in coding mode.
Where can I find a function to get a list of all the nodes in a given scene? I want to improve my multiplayer script by checking and setting the position and orientation of scene nodes with the prerender callback, and then (hopefully) code in interpolation to make remote avatars smoothly move from one place to another.
thanks!
-h
Offline
Hello and welcome back
searching in all scene node could be slow on scene with a lot of objects.
the better way should be to keep a list in your plugIT of the avatars objects to update them.
when you add a player avatar, you should keep a complete structure for example :
struct AvatarStr = [
AV_user : NetUser,
AV_shell : SO3_OBJECT,
AV_Mesh : SO3_OBJECT,
AV_body : SO3_PHYSICBODY,
AV_pos : [[F F F] [F F F]],
AV_nextPos : [[F F F] [F F F]],
AV_fInterpolate : F,
AV_fMass : F,
AV_fState : I
//animations ...
]mkAvatarStr;;
then you could iterate the user list to interpolate the moves.
[int] look at SO3MathsQuatInterpolate for quaternion lerp http://redmine.scolring.org/projects/so … 3e96eb2362
Offline
Thanks, creating a new class with the struct command is a bit too abstract for a coder like me. I guess what I could do is build a list every time a new user logs in to an environment and updates his position and have the pre render call back search through the list for new positions and orientations.
Last edited by hebdemnobad (26-Nov-2013 18:45:12)
Offline
maybe that you should start a little test to understand the scol structures.
this is really useful for that kind of process.
Iri do you have a tutorial for "struct" somewhere ?
Offline
I taught myself a bit of java over the summer...I assume the struct command is similar to that involved in making or extending a class in Java?
Offline
I guess I will teach myself struct syntax, perhaps with creating something like a 'circle' class. But a tutorial would be great.
Last edited by hebdemnobad (26-Nov-2013 19:14:34)
Offline
Hello -h
struct allows to create a new Scol type.
I've already written a tutorial on the Scol wiki : http://redmine.scolring.org/projects/tu … es_in_Scol
Few basic examples below :
To create this :
struct MyNewScolStructure = [
aNumber : I,
aString : S,
aStringList : [S r1]
] mkMyNewScolStructure;;
Here, MyNewScolStructure is your new Scol type. mkMyNewScolStructure is its constructor.
To use this :
typeof myVariable = MyNewScolStructure;;
fun main ()=
// Initialisation
set myVariable = mkMyNewScolStructure [
5,
"Life is beautiful",
"Scol" :: "is" :: "a" :: "great" :: "language" :: nil];
_showconsole;
// getters
_fooId myVariable.aNumber; // 5
_fooS myVariable.aString; // Life is beautiful
_fooSList myVariable.aStringList; // Scol:is:a:great:language:nil
// setters
set myVariable.aNumber = myVariable.aNumber*2;
// getters
_fooId myVariable.aNumber; // 10
0;;
Other example, more complex :
struct MyNewScolStructureB = [
aNumber : I,
aString : S
] mkMyNewScolStructureB;;
struct MyNewScolStructureA = [
aId : I,
aName : S,
aObjectTypeB : MyNewScolStructureB
] mkMyNewScolStructureA;;
typeof listObjA = [MyNewScolStructureA r1];;
fun addNewBinA (id)=
let rand () -> anyRandomValue in
// The structure variable (global or local) must be always initialized before use
// directly with any explicit values (like below)
// or with 'nil' (for example : let mkMyNewScolStructureB [nil nil nil] -> objB in)
let mkMyNewScolStructureB [
anyRandomValue,
itoa anyRandomValue
] -> objB in
// This structure variable must be initialized too !
let mkMyNewScolStructureA [
id,
itoa id,
objB
] -> objA in
set listObjA = objA :: listObjA;
0;;
fun main ()=
srand (time);
// setters
addNewBinA 0;
addNewBinA 5;
addNewBinA 7;
// getters
_showconsole;
let nth_list listObjA 2 -> objA in
_fooId objA.aObjectTypeB.aNumber;
0;;
Offline
Thx Iri! so when one class extends another you have to initialize the higher level class before the extended class, so MyNewScolStructureB a must be initialized before MyNewScolStructureA.
Offline
- MyNewScolStructureA and MyNewScolStructureB must be defined before any variable wich use them. You can define MyNewScolStructureA before MyNewScolStructureB if you want if they are in the same package.
- In this example, yes, the MyNewScolStructureB local variable must be initialized before the MyNewScolStructureA local variable. Because a such variable must be initialized before be used. Otherwise, it will be ALWAYS nil, even if you initialize after.
Offline
Hello and welcome back ;)
searching in all scene node could be slow on scene with a lot of objects.
the better way should be to keep a list in your plugIT of the avatars objects to update them.
when you add a player avatar, you should keep a complete structure for example :
struct AvatarStr = [ AV_user : NetUser, AV_shell : SO3_OBJECT, AV_Mesh : SO3_OBJECT, AV_body : SO3_PHYSICBODY, AV_pos : [[F F F] [F F F]], AV_nextPos : [[F F F] [F F F]], AV_fInterpolate : F, AV_fMass : F, AV_fState : I //animations ... ]mkAvatarStr;;
then you could iterate the user list to interpolate the moves.
[int] look at SO3MathsQuatInterpolate for quaternion lerp http://redmine.scolring.org/projects/so … 3e96eb2362
I'm wondering how I could plug in this avatar object into the multiplayer hacked chat plugit from this thread without totally rebuilding it (I'm thinking of using the code I wrote which sends various clients' locations and orientations to the server, and somehow updating a growing or shrinking pool of AvatarStr objects) : http://www.scolring.org/forum/viewtopic.php?id=471&p=3
Last edited by hebdemnobad (26-Nov-2013 22:50:32)
Offline
Set a list to manage all avatars in a specific sphere (so, remove an avatar leaving the sphere, add the avatar entering, ..).
Wite a message (Comm) for each avatar when the position or orientation has changed (from a callback, like renderCallback). Remember the framerate of each client : it can be different. Perhaps, send the message one time per second or something like this.
Your client code is still current ? http://www.scolring.org/forum/viewtopic … 2841#p2841
Offline
Set a list to manage all avatars in a specific sphere (so, remove an avatar leaving the sphere, add the avatar entering, ..).
Wite a message (Comm) for each avatar when the position or orientation has changed (from a callback, like renderCallback). Remember the framerate of each client : it can be different. Perhaps, send the message one time per second or something like this.Your client code is still current ? http://www.scolring.org/forum/viewtopic … 2841#p2841
We agreed in that thread that it made sense to use a timer to send a camera shell's location/orientation (I will refer to both as "transform") to the server, since different clients will have different framerates. As I understand it, a prerender callback with interpolation would save resources for me (client 1) updating the transforms of other user's avatar transforms in an environment. Then I could update remote avatar's transforms, say, once every 500ms, instead of once every 80ms (which is where I had left off working on my script). And interpolation would allow for smoother movement of remote avatars, instead of jerky movements every 80ms and using up bandwidth the way my crude method does. Using the avatar struct is definitely the way to go, especially in a game environment where each client could have fields for health, blood, limbs, eyes, etc. if I am making a game of various animals trying to eat each other, for example.
So I will improve my script to use the prerender callback and interpolation with remote avatars. But I have a couple of questions.
If I use the avatar struct as Arkeon describes it, I'm wondering about this:
Question 1:
1. When the cbAddUser callback is fired (i.e. a remote user logs in to the same environment that my client is already inhabiting), my code will have the resources to create a mesh and a shell, but a short lapse of time will pass before the server sends my client information on the avatar's transform ([F F F] [F F F]). Can an avatar object have an empty (that is, undefined) AV_pos field at the moment of creation, and then have that field given the AV_pos information a moment of later, updating the new object?
and
2. Whether I use the avatar struct or not, I have to deal with a dynamic list. If I use my old method, the list will be of tuples of the the structure [S F F F F F F], where S is the shell's name (derived from a remote user's login), and F F F F F F contains the transform information. That list will grow when a cbAddUser callback fires, and will shrink when cbDelUser fires. So when cbAddUser fires, a list containing one avatar changing to two would change from
["login_name_of_shell1" F F F F F F ] to
["login_name_of_shell1" F F F F F F ] ["login_name_of_shell2" F F F F F F ]
and when cbDeluser fires, the list would change from
["login_name_of_shell1" F F F F F F ] ["login_name_of_shell2" F F F F F F ] back to
["login_name_of_shell1" F F F F F F ]
If I use the new struct method indicated by arkeon, the list would be less complicated since the list would be of the type [AV_shell Av_pos AV_nextPOS]. In either case I have to dynamically change a list of tuples, each of which contains at least 3 variables and at most 7.
I think the methods are pretty straightforward with array functions in javascript, so what I would be trying to do in Scol would be analogous to removing and adding specific indices of a multiple dimensional javascript array. Something akin to this using the firefox console, although this example involves changing a specific index of a multi-dimensional array, not deleting the index in toto:
var board = [
['R','N','B','Q','K','B','N','R'],
['P','P','P','P','P','P','P','P'],
[' ',' ',' ',' ',' ',' ',' ',' '],
[' ',' ',' ',' ',' ',' ',' ',' '],
[' ',' ',' ',' ',' ',' ',' ',' '],
[' ',' ',' ',' ',' ',' ',' ',' '],
['p','p','p','p','p','p','p','p'],
['r','n','b','q','k','b','n','r'] ];
console.log(board.join('\n') + '\n\n');
// Move King's Pawn forward 2
board[4][4] = board[6][4];
board[6][4] = ' ';
console.log(board.join('\n'));
Output:
R,N,B,Q,K,B,N,R
P,P,P,P,P,P,P,P
, , , , , , ,
, , , , , , ,
, , , , , , ,
, , , , , , ,
p,p,p,p,p,p,p,p
r,n,b,q,k,b,n,r
R,N,B,Q,K,B,N,R
P,P,P,P,P,P,P,P
, , , , , , ,
, , , , , , ,
, , , ,p, , ,
, , , , , , ,
p,p,p,p, ,p,p,p
r,n,b,q,k,b,n,r
here is an example of deleting an item in a one dimensional array:
var arr = ["Go", "to", "home"]
// remove 1 element starting at index 1
arr.splice(1, 1);
// ["Go", "home"] (1 element removed)
alert( arr.join(',') );
I think i know the goal! It's just the way that I'm confused about.
Happy U.S. Thanksgiving. (It's a holiday involving religious fundamentalists from England and their friendship with local Indians that then goes way downhill, leaving blood on everyone's hands. Such is my interpretation.)
Last edited by hebdemnobad (27-Nov-2013 18:58:50)
Offline
We agreed in that thread that it made sense to use a timer to send a camera shell's location/orientation (I will refer to both as "transform") to the server, since different clients will have different framerates. As I understand it, a prerender callback with interpolation would save resources for me (client 1) updating the transforms of other user's avatar transforms in an environment. Then I could update remote avatar's transforms, say, once every 500ms, instead of once every 80ms (which is where I had left off working on my script). And interpolation would allow for smoother movement of remote avatars, instead of jerky movements every 80ms and using up bandwidth the way my crude method does.
Ok.
A first optmization could be :
save the last transformers;
calculate the new transformers when the time is elapsed (this period can be replaced by a framerate / N);
send a message with transformers IF the new transformers has changed from the last one.
Question 1: (...)
If a new user (Client2) enters in your sphere (Client1), Client2 has already a position and an orientation.
If Client2 enters in this scene, he hasn't a position and an orientation. In this case, you can set fields with the default values (for example, a ramdom position, etc).
In Scol, you can initialize a structure to nil but, here, i will not do this.
Question 2: (...)
You should define a list in each client. Basically, each list item contains an user/client (an userstr structure, another structure, or anything who identify strictly this client) and its AvatarStr structure.
To add an element in your list, you could write something like :
/* u0 is incorrect here, you must replace by the "real" type */
typeof listClients = [[u0 AvatarStr] r1];;
(...)
/* the type of addNewClient is fun [u0 AvatarStr] I */
fun addNewClient (paramClient, avatarClient)=
let [paramClient avatarClient] -> newItem in
set listClients = newItem :: listClients;
0;;
To delete an item, some way are available.
The locked/lib subdirectory contains a lot of useful package, such _mlist.pkg
/* check if the given client is the client to delete */
fun checkClient (itemList, clientToDelete)=
let itemList -> [client avatarClient] in
client == clientToDelete;;
/* the removef_from_list is declared in locked/lib/_mlist.pkg,
so you must load this package in your environment before use the function. */
fun deleteClient (anyClient)=
set listClients = removef_from_list listClients @checkClient anyClient;
0;;
Offline
Thx! I think that answers the question I just posted in that other thread just now.
Offline
the OpenSpace Plugin API document is here : http://redmine.scolring.org/projects/op … lslib.html
there is also a lot of list manipulation tools
Offline
I add one thing about the structures :
if you want initialize to nil, set nil directly is incorrect (the compiler will be ok but your structure will be uniniatilized).
INCORRECT :
struct AvatarStr = [
AV_user : NetUser,
AV_shell : SO3_OBJECT,
AV_Mesh : SO3_OBJECT,
AV_body : SO3_PHYSICBODY,
AV_pos : [[F F F] [F F F]],
AV_nextPos : [[F F F] [F F F]],
AV_fInterpolate : F,
AV_fMass : F,
AV_fState : I
//animations ...
]mkAvatarStr;;
typeof myAv = AvatarStr;;
fun main ()=
set myAv = nil; // no error in Scol but myAv keep uninitialized
...
CORRECT :
struct AvatarStr = [
AV_user : NetUser,
AV_shell : SO3_OBJECT,
AV_Mesh : SO3_OBJECT,
AV_body : SO3_PHYSICBODY,
AV_pos : [[F F F] [F F F]],
AV_nextPos : [[F F F] [F F F]],
AV_fInterpolate : F,
AV_fMass : F,
AV_fState : I
//animations ...
]mkAvatarStr;;
typeof myAv = AvatarStr;;
fun main ()=
set myAv = mkAvatarStr [nil nil nil nil nil nil nil nil nil ...]; // Ok, EACH item is initialized
...
Offline
that's what I was thinking....creating a new avatar while leaving location/orientation initialized to nil.
Offline
I just realized if I have a list of avatar is objects, I don't have to bother with a list of tuples, since each item in the list will have various properties that don't have to be specified in the list itself....I'll start working on a GUI for project that grows, shrinks, and finds rectangle objects in a list of rectangles as rectangle objects are used in the school tutorial PDF and are pretty simple....I will start a separate thread on that project.
Last edited by hebdemnobad (28-Nov-2013 14:26:31)
Offline
In the list of object avatars, the user is included in these data ?
Ok, to perform the position/orientation, the user is not required : the avatar object can be sufficient.
But if you want later add another features, your current code will be useless ...
Offline
I think as long as I have the unique login string of each remote avatar, I can make sure that each user hangs on to the same properties.
Offline