Attaching Accessory Geometry to an existing Avatar

by Tim Batchelor Hnd,

loanwolffe.farzone@virgin.net

 

This method works for Avatar Studio v2 avatars where you have made an object that you wish to attach to your avatar. It can be used to include custom made hair, hats, guns or whatever to a limited number of points on the avatar that will allow the accessory to move along with the gestures of the avatar[1].

In order to use this tutorial you must have some method of making a vrml object and you need to be able to decompress or 'unzip' the Avatar Studio .wrl file and re-compress it after the necessary changes have been made, for this you should refer to existing tutorials on making objects and in using 'winChisel'[2] .

1.Creating your Accessories

The first and probably the most important point here is that your avatar accessory should be specifically designed for the purpose, while it is possible to attach any object to an avatar you will have real problems if your object is on a very different scale than the avatar itself, and if the object is not well centered.

Err, what does that mean ?

Most people use software to make vrml models or objects[3], this software hides a lot of the technical detail of how an object is constructed from the user, with the result that you can spend a lot of time making something that looks good on screen only to find that your object either disappears or seems huge when you put it into a 'world' or vrml scene. Each software package is different but basically you need to check the 'help' and tutorials to learn how to make the object to a specific scale. The convention in vrml is that 1 vrml unit is equivalent to 1 real world meter. Thus an avatar will normally be about 1.75m or vrml units in height. Your accessory geometry therefore needs to be built on roughly the same scale.

VRML uses something that is described as a 'right handed Cartesian co-ordinate system' [4] this means that the geometry is described mathematically relative to a grid similar to that which you would use in high school geometry, except that it has three dimension axes instead of two. When you make an object you should construct it so that it is centered on the 'origin' of the co-ordinate system. This is not usually done for you automatically by the software but it is necessary because scaling is applied in all three geometrical dimensions, thus if your object is not centered on the origin when scaled it will move closer to, or further away from the origin as well as getting larger or smaller.

2.Constructing your Avatar

Ideally the avatar you intend to attach accessory geometry to should be constructed with the accessory object in mind. If the accessory is hair for example then your avatar should be produced without Avatar Studio hair. If the object is to be attached to the avatar's hand then you should take note of the objects expected size and shape when you animate the avatar gestures, otherwise you may find that once attached the object appears to pass through parts of the avatar.

The next section assumes that you have constructed your accessory object on a similar scale to your avatar and that you have constructed the avatar keeping the size and shape of the accessory object in mind.

3.Preparing the Avatar file

Firstly you need to prepare that avatar file to receive the additional geometry, unzip or decompress the .wrl file for the avatar ( and of the accessory if necessary) then open the avatar file in a text editor. The following lines of code need to be added exactly to the file in precisely the right places.

1st code group

These lines need to be added after the main shape node and before the first gesture, for convenience the end of the main shape will usually be indicated by a vrml 'comment' like so ;

# shape

copy and paste the following lines into a new line immediately after the above comment.

##########################################
# Add these lines after the main shape   #
##########################################
DEF center_Obj Transform {
    children [
      #Place your accessory geometry here 
    ]
}
#
DEF vl5_Obj Transform { 
    children [
     #Place your accessory geometry here
    ]
}
#
DEF vc7_Obj Transform {
    children [
     #Place your accessory geometry here
    ]
}
#
DEF neck_Obj Transform {
    children [
     #Place your accessory geometry here
    ]
}
#
DEF skull_Obj Transform {
    children [
     #Place your accessory geometry here
    ]
}
#
DEF r_wrist_Obj Transform {
    children [
     #Place your accessory geometry here
    ]
}
#
DEF l_wrist_Obj Transform {
    children [
     #Place your accessory geometry here 
    ]
}
#
##########################################

The lines of code above provide the avatar with a place in its structure where you can insert the new geometry, however the attachment will not work properly unless the remaining groups of code are also added, these link the new geometry into the animation of the existing avatar mesh.

2nd code group

The following lines of code need to be inserted into the interface of the 'welder script'. This script is the code that enables the different parts of the avatar, which is constructed from one single mesh, to be manipulated.

Insert them after the line;

               eventIn SFRotation rot_pubis

and before the line;

               field SFNode Vtx USE PointList


#################################################
# ADD These lines to the interface of Welder    #
#################################################
eventOut SFVec3f pos_Center_changed #
eventOut SFRotation rot_Center_changed #
#
eventOut SFVec3f pos_sacroiliac_changed #
eventOut SFRotation rot_sacroiliac_changed #
#
eventOut SFVec3f pos_vl5_changed #
eventOut SFRotation rot_vl5_changed #
eventOut SFVec3f pos_vc7_changed #
eventOut SFRotation rot_vc7_changed #
eventOut SFVec3f pos_neck_changed #
eventOut SFRotation rot_neck_changed #
eventOut SFVec3f pos_skull_changed #
eventOut SFRotation rot_skull_changed #
#
eventOut SFVec3f pos_r_shoulder_changed #
eventOut SFRotation rot_r_shoulder_changed #
eventOut SFVec3f pos_r_elbow_changed #
eventOut SFRotation rot_r_elbow_changed #
eventOut SFVec3f pos_r_wrist_changed #
eventOut SFRotation rot_r_wrist_changed #
#
eventOut SFVec3f pos_l_shoulder_changed #
eventOut SFRotation rot_l_shoulder_changed #
eventOut SFVec3f pos_l_elbow_changed #
eventOut SFRotation rot_l_elbow_changed #
eventOut SFVec3f pos_l_wrist_changed #
eventOut SFRotation rot_l_wrist_changed #
#
eventOut SFVec3f pos_r_hip_changed #
eventOut SFRotation rot_r_hip_changed #
eventOut SFVec3f pos_r_knee_changed #
eventOut SFRotation rot_r_knee_changed #
eventOut SFVec3f pos_r_ankle_changed #
eventOut SFRotation rot_r_ankle_changed #
#
eventOut SFVec3f pos_l_hip_changed #
eventOut SFRotation rot_l_hip_changed #
eventOut SFVec3f pos_l_knee_changed #
eventOut SFRotation rot_l_knee_changed #
eventOut SFVec3f pos_l_ankle_changed #
eventOut SFRotation rot_l_ankle_changed #
#
eventOut SFVec3f pos_pubis_changed #
eventOut SFRotation rot_pubis_changed #
################################################
3rd code group

The following lines of code need to be added inside the script itself, in this case to a script function called 'eventsProcessed'. This is the original function ;

 function eventsProcessed(){
     if(mode==2) Vtx.point.setByVertexTransform(V,vgroups,P,R);
 }

The code below should be inserted before the final curly brace of this function and after the semi colon at the end of the if statement.

 //#####################################################
 // ADD to end of the Welder function eventsProcessed  #
 //##################################################### 
   m0=new VrmlMatrix();                                               
   m0.setTransform(P[0],R[0]);

   m1=new VrmlMatrix();
   m1.setTransform(P[1],R[1]);m1=m1.multRight(m0);
   m1.getTransform(pos_Center_changed,rot_Center_changed);

   m2=new VrmlMatrix();
   m2.setTransform(P[2],R[2]);m2=m2.multRight(m1);
   m2.getTransform(pos_sacroiliac_changed,rot_sacroiliac_changed);
 
   m3=new VrmlMatrix();
   m3.setTransform(P[3],R[3]);m3=m3.multRight(m2);
   m3.getTransform(pos_vl5_changed,rot_vl5_changed); 

   m4=new VrmlMatrix();
   m4.setTransform(P[4],R[4]);m4=m4.multRight(m3);
   m4.getTransform(pos_vc7_changed,rot_vc7_changed);

   m5=new VrmlMatrix();
   m5.setTransform(P[7],R[7]);m5=m5.multRight(m4);
   m5.getTransform(pos_neck_changed,rot_neck_changed,scale);

   m6=new VrmlMatrix();
   m6.setTransform(P[8],R[8]);m6=m6.multRight(m5);
   m6.getTransform(pos_skull_changed,rot_skull_changed,scale);

   m7=new VrmlMatrix();
   m5.setTransform(P[22],R[22]);m5=m5.multRight(m4);
   m6.setTransform(P[24],R[24]);m6=m6.multRight(m5);
   m7.setTransform(P[25],R[25]);m7=m7.multRight(m6);
   m5.getTransform(pos_r_shoulder_changed,rot_r_shoulder_changed);
   m6.getTransform(pos_r_elbow_changed,rot_r_elbow_changed);
   m7.getTransform(pos_r_wrist_changed,rot_r_wrist_changed);

   m5.setTransform(P[29],R[29]);m5=m5.multRight(m4);
   m6.setTransform(P[31],R[31]);m6=m6.multRight(m5);
   m7.setTransform(P[32],R[32]);m7=m7.multRight(m6);
   m5.getTransform(pos_l_shoulder_changed,rot_l_shoulder_changed);
   m6.getTransform(pos_l_elbow_changed,rot_l_elbow_changed);
   m7.getTransform(pos_l_wrist_changed,rot_l_wrist_changed);

   m3.setTransform(P[36],R[36]);m3=m3.multRight(m2);
   m4.setTransform(P[37],R[37]);m4=m4.multRight(m3);
   m5.setTransform(P[39],R[39]);m5=m5.multRight(m4);
   m6.setTransform(P[40],R[40]);m6=m6.multRight(m5);
   m4.getTransform(pos_r_hip_changed,rot_r_hip_changed);
   m5.getTransform(pos_r_knee_changed,rot_r_knee_changed);
   m6.getTransform(pos_r_ankle_changed,rot_r_ankle_changed);

   m3.setTransform(P[43],R[43]);m3=m3.multRight(m2);
   m4.setTransform(P[44],R[44]);m4=m4.multRight(m3);
   m5.setTransform(P[46],R[46]);m5=m5.multRight(m4);
   m6.setTransform(P[47],R[47]);m6=m6.multRight(m5);
   m4.getTransform(pos_l_hip_changed,rot_l_hip_changed);
   m5.getTransform(pos_l_knee_changed,rot_l_knee_changed);
   m6.getTransform(pos_l_ankle_changed,rot_l_ankle_changed);

 //#####################################################

The above is the code which allows the attached object to move along with the joint it is attached to when the avatar gestures are animated.

4th code group

The following lines need to be added to the list of 'ROUTE' statements at the end of the avatar, add them after the line ;

   ROUTE Walker.walkFrac TO Welder.fooEvents

and before the curly brace at the end of the avatar proto.

#################################################################
# ADD These lines at the very end of the Avatar PROTO           #
################################################################# 
ROUTE Welder.pos_vl5_changed TO vl5_Obj.set_translation
ROUTE Welder.rot_vl5_changed TO vl5_Obj.set_rotation
ROUTE Welder.pos_Center_changed TO center_Obj.set_translation
ROUTE Welder.rot_Center_changed TO center_Obj.set_rotation
ROUTE Welder.pos_vc7_changed TO vc7_Obj.set_translation
ROUTE Welder.rot_vc7_changed TO vc7_Obj.set_rotation
ROUTE Welder.pos_neck_changed TO neck_Obj.set_translation
ROUTE Welder.rot_neck_changed TO neck_Obj.set_rotation
ROUTE Welder.pos_skull_changed TO skull_Obj.set_translation
ROUTE Welder.rot_skull_changed TO skull_Obj.set_rotation
ROUTE Welder.pos_r_wrist_changed TO r_wrist_Obj.set_translation
ROUTE Welder.rot_r_wrist_changed TO r_wrist_Obj.set_rotation
ROUTE Welder.pos_l_wrist_changed TO l_wrist_Obj.set_translation
ROUTE Welder.rot_l_wrist_changed TO l_wrist_Obj.set_rotation
#################################################################

Once all of the 4 code groups mentioned above have been added to the avatar file you should save the file, you are now ready to insert the accessory geometry.

4.Inserting the Accessory Geometry

We will assume for the sake of simplicity that the object to be inserted is a hat or hair, in this case the object code for the hat or hair must be pasted into the avatar file between the [ square brackets] that denote the 'skull Oject' children;

DEF skull_Obj Transform {
    children [
      #Place your accessory geometry here 
    ]
}

In the first instance you should cut and paste the entire contents of the object .wrl file into the avatar file at this point and then save the result.

If the saved file is now viewed in your browser it is most likely that the hat or hair will NOT be in the right place relative to the avatar, nor is it likely to be in exactly the right scale relative to the actual avatar. These two aspects need to be adjusted manually and it is best to get the scale approximately right before attempting to adjust the position.

5.Scaling and Positioning the object

The object can now be scaled up or down so that it is the required size to match the rest of the avatar. In the following example the object was actually 5 or 6 times bigger than was appropriate for the avatar;

      DEF skull_Obj Transform {
         #Place you accessory geometry here
         scale .15 .15 .15
         children [
            #@title [Stetsun W1] by Tim Batchelor (c) 2000AD
            DEF Stetsun_white Transform {
               rotation 0 1 0 3.14
               translation 0 .2 0
               children [
               # NB actual geometry code removed 
               ]
            }
         ]
      }

The object is scaled down to 15% of its real size using the line ;

         scale .15 .15 .15

This scales the x,y and z axes respectively, and since the object is reasonably well centered results is reduction of the objects size relative to the avatar with very little change in its position. In general all axes should be scaled by the same amount and if the object is smaller than expected a value greater than 1 should be used to increase the size of the object, otherwise a value less than 1 will reduce the size of the object.

On examination it was noticed that the hat was facing backwards, i.e. the pointy part at the front of the hat was actually at the back relative to the avatar, in this case the hat itself was rotated through 180 degrees by inserting the following line into the root or main 'Transform' of the accessory object ;

         rotation 0 1 0 3.14

This statement denotes a rotation of the object around the Y axis of 3.14 radians, approximately equal to 180 degrees. The actual orientation of your object when it is output to vrml from your software varies from package to package however it should be possible to bring the object into the correct orientation using a single rotation as above. The first three fields in the rotation statement are the axes, x , y and z respectively. 0 indicates no rotation on the axis and 1 denotes all of the specified rotation is applied to the axis. If 3.14 is roughly 180 then 1.57 is near enough 90 degrees and so on, negative values are allowed.

The hat appeared to be too low on the head of the avatar, this is corrected using the following line, placed after the rotation statement;

         translation 0 .2 0

This statement denotes a translation , or repositioning of the object of .2 m , or 20 cm upwards on the Y axis. Again the axes are x , y , and z respectively. Adjusting the x value will move the object left or right relative to the avatar and adjusting the z value will move it backwards or forwards. Initially it is best to use small values, otherwise you could easily translate your object a long way from the avatar. It is also important to note that these values are scaled by the scale statement which we have placed above them in the object.

Once you have scaled and positioned the object your avatar is practically finished, all that remains is to re-compress the .wrl file with the new accessory geometry you have added. If the accessory geometry contains and textures such as .gif or .jpg files you must remember to include these with the avatar's .wrl and .jpg files when you upload it to a server.

6.Inserting objects at other points in the avatar

You are not restricted to only one accessory object, in fact you can insert as many as you like. The places where you can insert accessory geometry are indicated in the 1st code group above. In addition you can insert objects at other points in the avatar by adding the appropriate lines to the necessary code groups shown above if they are not already present, however it requires a basic knowledge of coding and of how the avatar code works to do this successfully.

7.Conclusion

A set of working files to go along with this tutorial, right click to download, left click to view;

ghost_original.wrl ( the original Avatar Studio 2 .wrl file )

ghost.jpg ( the texture file for the avatar )

stetsun_w1.wrl ( an original cowboy hat model )

ghost_finished.wrl ( the finished version of the avatar )

This method is by no means perfect, but it does allow you to begin making your own accessories for avatars and include them in the avatar itself, and if you have done everything correctly the geometry you have added will move along with the gestures your avatar makes.

There is one final thing that may need to be done in order to make your new avatar work perfectly in most versions of Blaxxun contact, the code above works perfectly well for Blaxxun contact 5 and above but many people , especially members of Cybertown are still using Blaxxun Contact 4.4 . There is a problem with accessory geometry attachments in v4.4 which for example leads to accessory hair 'lagging' or appearing to slip of the head when the avatar performs some gestures. This problem can be solved relatively easily , you must " force mode 2 " for both 4.4 and 5+. This is done as follows ;

Find the function initialize() in the welder script, find the following line line in this function ;

else if(ver>5.0)mode=1; //setByVertexTransform()

and simply comment it out as follows ;

//else if(ver>5.0)mode=1; //setByVertexTransform() force mode=2

This forces the browser to use the eventsProcessed() function code for both browser versions 4.4 and 5+ and resolves the problem of laggin accessory geometry in contact 4.4.

I would like to thank CANAL+ and Mr Phillip of the World Builders Guild[5] for original code used in the development of this method, which is somewhat modified from the original examples, and also Barphe for his help in tracking down the solution to the 'laggy hair problem'.

8.References

[1] download Avatar studio 2 from http://www.Avatar Studio.com/

[2] winChisel can be obtained from http://www.trapezium.com/

[3] you can create objects using spazz3d from http://www.spazz3d.com/

[4] VRML is fully described here http://www.vrml.org/technicalinfo/specifications/vrml97/index.htm

[5] The VRML World Builders Guild home page : http://philliphansel.com/

[6] Author's own 3dchat and avatar website http://www.farzone.net/