# avatar.icn (03/18/05) # Las modified by Yosep Kim # # This is a beta version of avatar.icn, which is intended # for integration to Unicron, but has not yet been tested. # # As of 03/19/05, this version has been forwarded to # Dr. Jeffery for validity and integrity check. # # # avatar() # # This class is a wrapper for a class Skeleton. I created # this because some reasons I cannot remember. # class avatarParser( name, # Name sex, # Gender hdchoice, # Head Shape (1 for square;2 for egghead) face, # Name of the face picture file xsize,ysize,zsize, # X,Y,Z scalor factors height, # Y-axis Scalar factor (i.e. = ysize) color, # Primary color (Skin color) scolor, # Shirt color pcolor, # Pants color shcolor # Shoes color ) # # parser(File) # Purpose: Takes a file and parse each line and set them to their # appropriate variables # method parser(file) local line, count count:=0 line:= open(file||".avt") | stop("Can't open ", file||".avt") while sentence:=read(line) do { sentence:=trim(sentence,'\t') sentence:=trim(sentence,' ') if sentence[1]~=="#" then { i:=1 while i < *sentence do { if sentence[i] == "=" then { break } i:=i+1 } if count == 0 then { name:=sentence[i+1:*sentence+1] } else if count == 1 then { sex:=sentence[i+1:*sentence+1] } else if count == 2 then { height:=sentence[i+1:*sentence+1] } else if count == 3 then { xsize:=sentence[i+1:*sentence+1] } else if count == 4 then { ysize:=sentence[i+1:*sentence+1] } else if count == 5 then { zsize:=sentence[i+1:*sentence+1] } else if count == 6 then { color:=sentence[i+1:*sentence+1] } else if count == 7 then { scolor:=sentence[i+1:*sentence+1] } else if count == 8 then { pcolor:=sentence[i+1:*sentence+1] } else if count == 9 then { shcolor:=sentence[i+1:*sentence+1] } else if count == 10 then { hdchoice:=sentence[i+1:*sentence+1] } else if count == 11 then { face:=sentence[i+1:*sentence+1] } count:=count+1 } } end initially() i:=0 name:="guest" xsize:=0 ysize:=0 zsize:=0 height:=170 origx := 0 origy := 0 origz := 0 sex := "m" face := "smily.gif" hdchoice := 1 end class avatarParts ( romx, romy, romz #rotation matrix for setAngleComplex() ) method initRMatrix() local L put(L, romx:=Rotate(0,0,0,0)) put(L, romy:=Rotate(0,0,0,0)) put(L, romz:=Rotate(0,0,0,0)) return copy(L) end method setAngleComplex(xangle, yangle, zangle) romx.angle:=xangle romy.angle:=yangle romz.angle:=zangle romx.x:=1 romx.y:=0 romx.z:=0 romy.x:=0 romy.y:=1 romy.z:=0 romz.x:=0 romz.y:=0 romz.z:=1 end # # setAngle (Angle, Dir) # Purpose: to move the arm and hand # method setAngle(angle, dir) # # fb stands for forward-back # s stands for side-side # if dir == "fb" then { romx.angle:=angle # set the angle romx.x:=1 # update the angle of the arm romx.y:=0 # to be rotated by; along X- romx.z:=0 # axis } else if dir == "s" then { romz.angle:=angle # set the angle romz.x:=0 # update the angle of the arm romz.y:=0 # along Z-axis romz.z:=1 } end method createNameTag(name,len,x,y,z) local i, txcoords, tmp, interval, ls, L L:=[] i:=0 ls:=len/*name interval:=-(x+len/2) put(L, WAttrib("texmode=off")) while i < *name do { txcoords := [0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0 ] tmp := txcoords[1] || "," || txcoords[2] || "," || txcoords[3] || "," tmp := tmp || txcoords[4] || "," || txcoords[5] || "," || txcoords[6] || "," tmp := tmp || txcoords[7] || "," || txcoords[8] coords := [ 0 , 0 , 0, 0 , ls, 0, ls, ls, 0, ls, 0 , 0 ] put(L, PushMatrix()) put(L, Translate(interval,y,z)) put(L, WAttrib("texmode=on","texture=.\\letters\\"||name[i+1]||".GIF", "texcoord="||tmp)) put(L, FillPolygon ! coords) put(L, WAttrib("texmode=off")) put(L, DrawCube(ls/2,ls/2,-ls/2-0.001,ls)) put(L, PopMatrix()) interval:=interval+ls i:=i+1 } put(L, WAttrib("texmode=off")) return copy(L) end end # # Class: humanoid # This is the actual class that creates and renders the avatar # Note that the (origx, origy, origz) is located at the intersection # of the neck and body. # class avatar:avatarParser ( world, uid, x,y,z, deltax, deltay, deltaz, # used by camera cam_move lx, lz, # in view mode 2 cam_lx, cam_lz, # deprecated angle, render_list, ro, # rotate matrix over whole avatar mv, # traslates matrix " " angle, # angle by which rotation should occur # Instances of following classes h, # head b, # body la, # left arm ra, # right arm lg, # left leg rg, # right leg fint,rarm,larm, # counters used for actions cam_angle, # angle of the avatar vertical_ptr,horizontal_ptr # angles for pointing ) # # move_part(Name, Dir, Angle) # Purpose: to move a particular body part either vertically or horizontally # Parameters: Name - name of the part to be moved # Dir - direction in which it is to move # Angle - angle for which it is to be rotated # method move_part(name, dir, angle) local msg case name of { "right_arm" : ra.setAngle(angle, dir) "left_arm" : la.setAngle(angle, dir) "right_leg" : rg.setAngle(angle, dir) "left_leg" : lg.setAngle(angle, dir) } Refresh(world.g_win) if \world.cve_session.connection.connID then { msg := "\\move " || uid || " " || "part" || " " || name || " " || dir || " " || angle write( world.cve_session.connection.connID, msg ) } end # # move_part_complex(name,x,z) # Purpose: to move a body part in x,z direction freely # USED for pointing # Parameters: name - name of the body part to be moved # x - angle along the x-axis # z - angle along the z-axis # method move_part_complex(partName,inx,iny,inz) local msg if partName == "right_arm" then { ra.setAngleComplex(inx,iny,inz) } else if partName == "head" then { h.setAngleComplex(inx,iny,inz) } else if partName == "left_arm" then { la.setAngleComplex(inx,iny,inz) } Refresh(world.g_win) if \world.cve_session.connection.connID then { msg := "\\move " || uid || " " || "part" || " " || partName || " " || dir || " " || angle write( world.cve_session.connection.connID, msg ) } end # # move1(X,Y,Z,Angle) # Purpose: to move the avatar # Parameters: [X,Y,Z] - current x, y, z coordinates # Angle - angle in which the avatar should be # turned # method move1(posx,posy,posz,angle) degree:=rtod(angle) # convert angle(radian) to degree ro.angle:=degree # update the angle of rotation matrix (e.g. ro) mv.x := posx mv.y := posy mv.z := posz if world.cam.view_mode ~= 2 then { Refresh(world.g_win) } end # # talkingface(newface) # Purpose: to update the face picture with a new one # Parameter: newface - name of the new face picture file # method talkingOn() h.talkingOn() end method talkingOff() h.talkingOff() end # # initializer # method initialize() parser(world.avatar_path || uid || ".avt") setup() end # # setup() # Purpose: to set up each part of avatar by instantiating # the body part # method setup() h := head() # head and neck b := body() # body la := arm() # left arm ra := arm() # right arm lg := leg() # left leg rg := leg() # right leg render_list:=render() end # # render() # Purpose: to render graphics of each part thus a whole # avatar # method render() local L L:=[] put(L, PushMatrix()) put(L, Scale(xsize,height,zsize)) # size the avatar mv:=Translate(origx,origy,origz) # move the avatar put(L, mv) ro:=Rotate(0,0,1,0) # and turn it put(L, ro) L:=L ||| h.render(world.avatar_path,color,hdchoice) # head and neck L:=L ||| b.render(scolor,name,sex) # body L:=L ||| la.render("l",color,scolor) # left arm and shoulder L:=L ||| ra.render("r",color,scolor) # right arm and shoulder L:=L ||| lg.render("l",pcolor,shcolor) # left leg L:=L ||| rg.render("r",pcolor,shcolor) # right leg put(L, PopMatrix()) return copy(L) end # # move() # method move(type, step) case type of { 1: { # # move FORWARD # lx := sin(angle) lz := cos(angle) deltax := step * lx deltaz := step * lz if world.cam.test_new_pos( self, step ) then { x +:= deltax z +:= deltaz move1(x, y, z, angle) if world.cam.view_mode > 1 then cam_follows() # avatar==cam if fint < 3 then { if rarm = 0 then { move_part("right_arm", "fb", 10) } move_part("left_leg", "fb", 10) if larm = 0 then { move_part("left_arm", "fb", -10) } move_part("right_leg", "fb", -10) fint +:= 1 } else { if rarm = 0 then { move_part("right_arm", "fb", -10) } move_part("left_leg", "fb", -10) if larm = 0 then { move_part("left_arm", "fb", 10) } move_part("right_leg", "fb", 10) fint +:= 1 if fint = 6 then { fint:=0 } } broadcast_move() } } 2 : { # # move BACKWARD - moon-walk style # lx := sin(angle) lz := cos(angle) deltax := step * lx deltaz := step * lz # write("avatar move x,y,z, angle ",x," ",y," ",z," ", angle) if world.cam.test_new_pos( self, step ) then { x +:= deltax z +:= deltaz move1(x, y, z, angle) if world.cam.view_mode > 1 then cam_follows() # avatar == cam if fint < 3 then { if rarm = 0 then { move_part("right_arm", "fb", 10) } move_part("left_leg", "fb", 10) if larm = 0 then { move_part("left_arm", "fb", -10) } move_part("right_leg", "fb", -10) fint +:= 1 } else { if rarm = 0 then { move_part("right_arm", "fb", -10) } move_part("left_leg", "fb", -10) if larm = 0 then { move_part("left_arm", "fb", 10) } move_part("right_leg", "fb", 10) fint +:= 1 if fint = 6 then { fint:=0 } } broadcast_move() } } # end case 2: 3 : { # # Raising Right Arm # if rarm = 0 then { rarm:=1 move_part("right_arm", "fb", 180) } else { rarm:=0 move_part("right_arm", "fb", 0) } } # end case 3 4 : { # # Raising Left Arm # if larm = 0 then { larm:=1 move_part("left_arm", "fb", 180) # -10 ? } else { larm:=0 move_part("left_arm", "fb", 0) } } # end case 4 5 : { # # move SIDEWAY-right # # x := x - sin(1.571-angle)*0.1 # z := z + cos(1.571-angle)*0.1 # should these be updated ??? # lx := sin(1.571-angle) # lz := cos(1.571-angle) deltax := step * ( -sin(1.571-angle) ) deltaz := step * ( cos(1.571-angle)) # write("avatar move x,y,z, angle ",x," ",y," ",z," ", angle) if world.cam.test_new_pos( self, step ) then { x +:= deltax z +:= deltaz lx +:= deltax lz +:= deltaz if fint < 3 then { move_part("right_leg", "s", -10) Refresh() move1(x, y, z, angle) if world.cam.view_mode > 1 then cam_follows() #avatar==cam broadcast_move() Refresh() fint +:= 1 } else { move_part("right_leg", "s", 0) fint +:= 1 if fint = 6 then { fint:=0 } } } } # end case 5 6 : { # # move SIDEWAY-left # # x := x + sin(1.571-angle)*0.1 # z := z - cos(1.571-angle)*0.1 deltax := step * ( sin(1.571-angle)) deltaz := step * ( -cos(1.571-angle)) # write("avatar move x,y,z, angle ",x," ",y," ",z," ", angle) if world.cam.test_new_pos( self, step) then { x +:= deltax z +:= deltaz lx +:= deltax lz +:= deltaz if fint < 3 then { move_part("left_leg", "s", 10) Refresh() move1( x, y, z, angle) if world.cam.view_mode > 1 then cam_follows() # avatar == cam broadcast_move() Refresh() fint +:= 1 } else { move_part("left_leg", "s", 0) fint +:= 1 if fint = 6 then { fint:=0 } } } } # end case 6 7 : { # # turn LEFT # angle +:= step if abs(angle) > 2 * &pi then angle := 0.0 move1( x, y, z, angle) if world.cam.view_mode > 1 then cam_follows() # avatar == cam broadcast_move() } # end case 7 8 : { # # turn RIGHT # angle -:= step if abs(angle) > 2 * &pi then angle := 0.0 move1( x, y, z, angle) if world.cam.view_mode > 1 then cam_follows() # avatar == cam broadcast_move() } # end case 8 9 : { # # back to NORMAL # move_part("right_arm", "fb", 0) move_part("left_leg", "fb", 0) move_part("left_arm", "fb", 0) move_part("right_leg", "fb", 0) } # end case 9 # # pointing # 10: { # Everything goes back to normal move_part("right_arm", "fb", 0) move_part("left_leg", "fb", 0) move_part("left_arm", "fb", 0) move_part("right_leg", "fb", 0) # BRINGS THE RIGHT ARM UP vertical_ptr:=270 horizontal_ptr:=0 move_part("right_arm", "fb", 270) Refresh() } # # talking-on # 11: { talkingOn() } # # talking-off # 12: { talkingOff() } 13: { if vertical_ptr > 210 then vertical_ptr:=vertical_ptr-1 move_part_complex("right_arm", vertical_ptr, 0, horizontal_ptr) move_part_complex("head", vertical_ptr-270, horizontal_ptr, 0) } 14: { if vertical_ptr < 330 then vertical_ptr:=vertical_ptr+1 move_part_complex("right_arm", vertical_ptr, 0, horizontal_ptr) move_part_complex("head", vertical_ptr-270, horizontal_ptr, 0) } 15: { if horizontal_ptr > -30 then horizontal_ptr:=horizontal_ptr-1 move_part_complex("right_arm", vertical_ptr, 0, horizontal_ptr) move_part_complex("head", vertical_ptr-270, horizontal_ptr, 0) } 16: { if horizontal_ptr < 30 then horizontal_ptr:=horizontal_ptr+1 move_part_complex("right_arm", vertical_ptr, 0, horizontal_ptr) move_part_complex("head", vertical_ptr-270, horizontal_ptr, 0) } 17: { move_part_complex("right_arm",0,0,0) move_part_complex("head",0,0,0) } } # end case type end method cam_follows() local adj_angle, r # camera === avatar eye if world.cam.view_mode = 3 then { r := h.headr world.cam.x := x + r * sin(angle) # world.cam.y := ??? world.cam.z := z + r * cos(angle) # lx := sin(angle) # lz := -cos(angle) world.cam.lookx := x + 4 * sin(angle) # world.cam.looky := world.cam.lookz := z + 4 * cos(angle) Eye( world.cam.x, world.cam.y , world.cam.z, world.cam.lookx, world.cam.looky, world.cam.lookz) return } if world.cam.view_mode = 2 then { # camera over shoulder adj_angle := angle + dtor(200.0) if adj_angle > 2 * &pi then { adj_angle -:= 2 * &pi } if adj_angle < -2 * &pi then { adj_angle +:= 2 * &pi } # write ( "rotator adj : ",avatar.rotator.angle," ",adj_angle) lx := sin( adj_angle ) lz := cos( adj_angle ) world.cam.x := (x + 2 * lx ) # world.cam.y := 1.90 world.cam.z := (z + 2 * lz ) world.cam.lookx := x - lx # world.cam.looky := y world.cam.lookz := z - lz Eye( world.cam.x, world.cam.y , world.cam.z, world.cam.lookx, world.cam.looky, world.cam.lookz) return } end # method cam_follows() # now called from avatar.move() # maybe this should be moved to move1???? # ###### cannot seem to access field uid from there - very strange method broadcast_move() local msg msg := "\\move " || uid || " " || "body" || " " || x || " " || y || " " || z || " " || angle if \world.cve_session.connection.connID then write( world.cve_session.connection.connID, msg ) WSync() end # _broadcast_move method delete_avatar() local len, i, item, ritem, flag, old_win old_win := world.get_window() world.set_window(world.g_win) len := *WindowContents() every i := 1 to len do { item := pop(WindowContents()) flag := 1 # maybe use member???? every ritem := !render_list do if item === ritem then flag := 0 if flag = 1 then put(WindowContents(), item ) } render_list := [] Refresh() world.set_window( old_win ) return end # method delete_avatar() initially(uid_in, x_in, y_in, z_in, ang, worl)#aky world := worl uid := uid_in x := x_in # avatar's cooridinates y := y_in # previously named origx, origy, origx z := z_in cam_lx := 0.0 # cam_lx, cam_lz, deltax, deltay, deltaz cam_lz := 0.0 # are used only in the camera cam_move() stuff lx := 0.0 lz := 0.0 deltax := 0.0 deltay := 0.0 deltaz := 0.0 angle := ang #aky # avatar orientation angle # previously named cam_angle fint := 0 rarm := 0 larm := 0 vertical_ptr:=0 horizontal_ptr:=0 # angles for pointing render_list := [] # capture display list elts for \delavatar end # # Class: head # This class just renders head and neck # class head : avatarParts ( headx,heady,headz,headr, # Head coodinate, radius of the head neckx,necky,neckz,neckh,neckt,neckb, # Neck coor. and other info. on neck m1,m2,m3,m4, # stuff for talking effect counter, # Internal counter to manage talking on-off romx,romy, romz, # rotation matrix for x and z axis ch ) method render(face, color, choice) local L L:=[] ch:=choice counter:=0 # Neck if (color[*color-3:*color+1] == ".gif")|(color[*color-3:*color+1] == ".GIF") then put(L, WAttrib("texmode=on","texture="||color)) else { put(L, WAttrib("texmode=off")) put(L, Fg("ambient "||color)) } put(L, DrawCylinder(neckx, necky, neckz, neckh, neckt, neckb)) # Head put(L, PushMatrix()) if (color[*color-3:*color+1] == ".gif")|(color[*color-3:*color+1] == ".GIF") then put(L, WAttrib("texmode=on","texture="||color)) else { put(L, WAttrib("texmode=off")) put(L, Fg("ambient "||color)) } # # Egg Shape or Putting picture on a box # if choice == 2 then { put(L, PushMatrix()) initRMatrix() put(L, WAttrib("texmode=on","texture="||face)) put(L, Rotate(270,1,0,0)) put(L, Scale(1,1,1.2)) put(L, PushMatrix()) put(L, Translate(headx,0,0.55)) put(L, DrawSphere(0, 0, 0, headr)) put(L, WAttrib("texmode=off")) put(L, Fg("ambient red")) put(L, Rotate(90,1,0,0)) m1:=DrawCylinder(-headx,-heady+heady*0.7,0,0.03,0.01,0.01) m2:=DrawCylinder(-headx,-heady+heady*0.7,0,0.05,0.015,0.015) m3:=DrawCylinder(-headx,-heady+heady*0.7,0,0.08,0.02,0.02) m4:=DrawCylinder(-headx,-heady+heady*0.7,0,0.12,0.03,0.03) put(L,m1) put(L,m2) put(L,m3) put(L,m4) put(L, PopMatrix()) put(L, PopMatrix()) } else { put(L, PushMatrix()) put(L, Translate(headx, heady, headz)) initRMatrix() put(L, DrawSphere(0,0,0, headr)) put(L, WAttrib("texmode=on","texture="||face,"texcoord=auto")) # Face cube txcoords := [0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0 ] tmp := txcoords[1] || "," || txcoords[2] || "," || txcoords[3] || "," tmp := tmp || txcoords[4] || "," || txcoords[5] || "," || txcoords[6] || "," tmp := tmp || txcoords[7] || "," || txcoords[8] sz := headr*1.3 / 2.0 coords := [ 0 , 0, 0, 0 , 2 * sz, 0, 2* sz , 2 * sz, 0, 2* sz , 0, 0 ] # Face polygon # formerly a cube put(L, PushMatrix()) put(L, Translate( -sz, -heady/2, headr )) put(L, WAttrib("texmode=on", "texture="|| face , "texcoord="||tmp)) put(L, FillPolygon ! coords) put(L, WAttrib("texmode=off")) put(L, PopMatrix()) put(L, Fg("ambient red")) m1:=DrawCylinder(-headx,-heady+heady*0.7,0,0.03,0.01,0.01) m2:=DrawCylinder(-headx,-heady+heady*0.7,0,0.05,0.015,0.015) m3:=DrawCylinder(-headx,-heady+heady*0.7,0,0.08,0.02,0.02) m4:=DrawCylinder(-headx,-heady+heady*0.7,0,0.12,0.03,0.03) put(L,m1) put(L,m2) put(L,m3) put(L,m4) put(L, PopMatrix()) } put(L, PopMatrix()) return copy(L) end method talkingOn() if counter=0 then { if ch == 1 then { m1.z:=0.5 m2.z:=0.55 m3.z:=0.6 m4.z:=0.68 } else { m1.z:=0.5 m2.z:=0.55 m3.z:=0.6 m4.z:=0.68 } counter:=1} else { if ch == 1 then { m1.z:=0 m2.z:=0 m3.z:=0 m4.z:=0 } else { m1.z:=0 m2.z:=0 m3.z:=0 m4.z:=0 } counter:=0} end method talkingOff() if ch == 1 then { m1.z:=0 m2.z:=0 m3.z:=0 m4.z:=0 } else { m1.z:=0 m2.z:=0 m3.z:=0 m4.z:=0 } counter:=0 end initially() headx := 0 heady := 0.6 headz := 0 headr := 0.5 neckx := 0 necky := 0 neckz := 0 neckh := 0.1 neckt := 0.1 neckb := 0.1 end # # Class: body # This class just renders the body # class body : avatarParts ( bodyx,bodyy,bodyz,bodyh,bodyt,bodyb, chestx,chesty,chestz,chestr ) method render(scolor, name, sex) local L L:=[] if (scolor[*scolor-3:*scolor+1] == ".gif")|(scolor[*scolor-3:*scolor+1] == ".GIF") then put(L, WAttrib("texmode=on","texture="||scolor)) else { put(L, WAttrib("texmode=off")) put(L, Fg("ambient "||scolor))} put(L, DrawCylinder(0, -bodyh, 0, bodyh, bodyt, bodyb)) put(L, WAttrib("texmode=off")) put(L, PushMatrix()) put(L, Rotate(90,1,0,0)) put(L, DrawDisk(0,0,0,0,bodyt)) put(L, PopMatrix()) if sex == "w" then { put(L, PushMatrix()) put(L, Translate(0,chesty,chestz)) if (scolor[*scolor-3:*scolor+1] == ".gif")|(scolor[*scolor-3:*scolor+1] == ".GIF") then put(L, WAttrib("texmode=on","texture="||scolor)) else { put(L, WAttrib("texmode=off")) put(L, Fg("ambient "||scolor))} put(L, DrawSphere(chestx,0,0, chestr)) put(L, DrawSphere(-chestx,0,0, chestr)) put(L, PopMatrix()) createNameTag(name,0.8,0,-bodyh+0.25,0.51) } else createNameTag(name,0.8,0,-bodyh+0.7,0.51) return (L) end initially() bodyx := 0 bodyy := 0 bodyz := 0 bodyh := 1.0 bodyt := 0.5 bodyb := 0.5 chestx := 0.175 chesty := -0.3 chestz := 0.3 chestr := 0.3 end # # Class: arm # This class renders the left arm and hand and shoulder # class arm : avatarParts ( # Information for: sholdx,sholdy,sholdz,sholdr, # Shoulder armx,army,armz,armh,armt,armb, # Arm handx,handy,handz,handr # Hand ) # # render # Purpose: to render the left arm of the avatar # method render(side,color,scolor) put(L, PushMatrix()) if side == "l" then put(L, Translate(sholdx,sholdy,sholdz)) else put(L, Translate(-sholdx,sholdy,sholdz)) initRMatrix() if (scolor[*scolor-3:*scolor+1] == ".gif")|(scolor[*scolor-3:*scolor+1] == ".GIF") then put(L, WAttrib("texmode=on","texture="||scolor)) else { put(L, WAttrib("texmode=off")) put(L, Fg("ambient "||scolor))} put(L, DrawSphere(0,0,0, sholdr)) if (color[*color-3:*color+1] == ".gif")|(color[*color-3:*color+1] == ".GIF") then put(L, WAttrib("texmode=on","texture="||color)) else { put(L, WAttrib("texmode=off")) put(L, Fg("ambient "||color))} put(L, DrawCylinder(0, -armh, 0, armh, armt, armb)) put(L, DrawSphere(0, -handy, 0, handr)) # Chicken finger if side == "r" then { put(L, DrawCylinder(0.1,-handy-0.25,0.1,0.25,0.07,0.07)) put(L, DrawSphere(0.1,-handy-0.25,0.1,0.07)) } put(L, PopMatrix()) return copy(L) end initially() sholdx := 0.7 sholdy := -0.1 sholdz := 0 sholdr := 0.3 armx := 0.7 army := -0.05 armz := 0 armh := 1.2 armt := 0.15 armb := 0.15 handx := armx handy := (army+armh)*0.95 handz := armz handr := 0.24 end # # Class: leg # This class renders left hip, leg, and foot # Please, refer to left_arm method for information # class leg : avatarParts ( # Information for: hipx,hipy,hipz,hipr, # Hip legx,legy,legz,legh,legt,legb, # Leg feetx,feety,feetz,feetir,feetor # Feet ) method render(side,pcolor,shcolor) local L L:=[] put(L, PushMatrix()) if side == "l" then put(L, Translate(hipx,-hipy,hipz)) else put(L, Translate(-hipx,-hipy,hipz)) initRMatrix() if (pcolor[*pcolor-3:*pcolor+1] == ".gif")|(pcolor[*pcolor-3:*pcolor+1] == ".GIF") then put(L, WAttrib("texmode=on","texture="||pcolor)) else { put(L, WAttrib("texmode=off")) put(L, Fg("ambient "||pcolor))} put(L, DrawSphere(0,0,0, hipr)) put(L, DrawCylinder(0, -legh, 0, legh, legt, legb)) if (shcolor[*shcolor-3:*shcolor+1] == ".gif")|(shcolor[*shcolor-3:*shcolor+1] == ".GIF") then put(L, WAttrib("texmode=on","texture="||shcolor)) else { put(L, WAttrib("texmode=off")) put(L, Fg("ambient "||shcolor))} put(L, DrawTorus(0, -legh, 0, feetir, feetor)) put(L, PopMatrix()) return copy(L) end initially() hipx := 0.25 hipy := 0.95 hipz := 0 hipr := 0.23 legx := hipx legy := hipy legz := hipz legh := 0.85 legt := hipr*0.7 legb := hipr*0.7 feetx := legx feety := legy+legh feetz := legz feetir := 0.13 feetor := 0.2 end