# # model.icn - classes for static stuff # openings, doors, wall, box, room # which creates the 3D architecture # # plane = 1 x plane has all x coords equal and thus is parallel to yz plane # and perpendicular to x axis # plane = 2 y plane has all y coords equal and thus is parallel to xz plane # and perpendicular to y axis - typically floor and ceiling # plane = 3 z plane has all z coords equal and thus is parallel to xy plane # and perpendicular to z axis link printf # -------------------------------- # # class Opening is any cut-out in an instance of class Wall # special case: class Door below which renders a moveable door # in the opening. # class Opening ( x, y, z, width, height, plane, rooms, collide, is_rendered, delt, id ) #(x,y,z, width, height, thickness, rooms, textures, # rotator, openness, hinge_left, direction, delt, is_rendered, # plane, open_angle) method add_room(r) ## Opening put(rooms, r) id := "" every r2 := !rooms do id ||:= r.name || "," id := id[1:-1] end method other(room) ## Opening local r every r := !rooms do if r ~=== room then return r write("other room failed") end method allows(px,pz) ## Opening #write("allows? ",px,",",pz) if plane = 3 then { # z plane #write("plane 3, x ", x, " -> ", x+width) if x+0.05 < px < x + width-0.05 then { #write("x is good enough, abs ", abs(z-pz)) if abs( z - pz ) < collide+ 0.10 then { return } } } if ( ( plane = 1 ) & # x plane ( z+0.05 < pz < z + width-0.05 ) & ( abs( x - px ) < collide + 0.10) ) then return fail end method render() ## Opening return end method print_opening() ## Opening local rm printf(" opening x,y,z,w,h,t %6.2r %6.2r %6.2r %6.2r %6.2r \n", x, y, z, width, height ) # printf(" openness, direction delt %6.2r %6.2r %6.2r \n", # openness, direction, delt ) write(" plane ", plane ) write(" # rooms ",*rooms) every rm := !rooms do write(" room ", image(rm) ) write(" " ) end # method print_opening() initially( x_in , y_in , z_in , collide_in, wd_in) # ,width,height,thickness) ## Opening # be sure x,y,z,w,h,t are floats x := x_in y := y_in z := z_in width := wd_in / width := 1.0 # default = 1 meter / height := 2.0 # default = 2 meters collide := (\collide_in | 0.8) # maybe should reduce to 0.8 or less rooms := [] plane := &null # set to 1 for xplane 3 for zplane delt := 0 id := "unconnected opening" end # class Opening # # class Door represents a closable connection between rooms # this will be sub-class of class Opening which itself has no door, but # provides the opening # class Door:Opening( x, y, z, thickness, rotator, openness, hinge_left, direction, delt, open_angle , texture, is_rendered) # (x,y,z, width, height, thickness, rooms, textures, # rotator, openness, hinge_left, direction, delt, is_rendered, # plane, open_angle) method add_room(r) ## Door put(rooms, r) end method other(room) ## Door local r every r := !rooms do if r ~=== room then return r write("other room failed") end # **************** needs work here method allows(px,pz) ## Door if openness < 0.67 then fail return self$Opening.allows(px,pz) end method dist1( px, py, pz ) ## Door return ( ( ( abs( px - x ) ^ 2.0 ) + ( abs ( pz - z ) ^ 2.0 ) ) ^ 0.50 ) end method distance(px,py,pz) ## Door # xplane zplane issues ??? # write ( " door distance px x ",px," ", x ) # write ( " pz z ",pz," ", z ) # write ( " dist 1 ", dist1( px, py, pz ) ) # write ( " dist 2 ", dist1( px, py, pz ) ) if plane = 3 then { # zplane return min ( dist1( px , py, pz ), dist1( px + width, py, pz ) ) } else { # plane = 1 x plane return min ( dist1( px , py, pz ), dist1( px , py, pz + width ) ) } end # method distance method done_opening() delt := 0 end method start_opening() direction *:= -1 delt := 0.03 end method delta() if (direction=1 & openness < 1) | (direction=-1 & openness > 0) then { set_openness(openness + direction * delt) return } end method set_openness(o) openness := o openness <:= 0 openness >:= 1 if \rotator then { rotator.angle := 90.0 * openness if /hinge_left then rotator.angle *:= -1.0 } end method render() ## Door if \is_rendered then return is_rendered := 1 if (type(self))[1+:4] ~== "Door" then return set_open_angle() if world.current_texture ~=== texture then { world.current_texture := texture } if WAttrib("texture="||\texture) then { WAttrib("texcoord= 0,0, 0,1, 1,1, 1,0") } else { WAttrib("texmode=off", "fg=very light yellow") } if plane = 3 then { # zplane - code renders ok render_z() } else { if plane = 1 then render_x() else write(" door rendering fails " ) } end # method render() method render_z() ## Door # write(" entering render_z ") PushMatrix() Translate(x,y,z) if /hinge_left then Translate(width,0,0) if \openness then { if \hinge_left then rotator := Rotate(-90.0 * openness, 0,1, 0) else rotator := Rotate(-90.0 * openness, 0, 1, 0) } if \hinge_left then { PushMatrix() Translate( -width/2.0, -height/2.0, -thickness/2.0) Scale(width,height,thickness) Translate( width , height/2.0 , thickness/2.0 ) DrawCube(0,0,0,1) PopMatrix() WAttrib("texmode=off") # this is not very general ######## Fg("brown") DrawSphere((width*0.92), height/2.0, 0.08, 0.04) DrawSphere((width*0.92), height/2.0, -0.08-thickness, 0.04) WAttrib("texmode=on") } else { # normal door = hinge right PushMatrix() Translate( -width/2.0, height/2.0, -thickness/2.0) Scale(width,height,thickness) DrawCube(0,0,0,1) PopMatrix() WAttrib("texmode=off") # this is not very general ######## Fg("brown") DrawSphere((-width*0.92), height/2.0, 0.08, 0.04) DrawSphere((-width*0.92), height/2.0, -0.08-thickness, 0.04) WAttrib("texmode=on") } PopMatrix() end # method render_z() method render_x() ## Door # write(" enter render_x " ) PushMatrix() Translate(x,y,z) # if /hinge_left then Translate(0.0, 0.0, width ) if \openness then { if \hinge_left then rotator := Rotate(-90.0 * openness, 0,1, 0) else rotator := Rotate( 90.0 * openness, 0, 1, 0) } if \hinge_left then { PushMatrix() Translate( -thickness/2.0, -height/2.0, -width/2.0) Scale(thickness,height,width) Translate( thickness/2.0 , height/2.0 , width ) DrawCube(0,0,0,1) PopMatrix() WAttrib("texmode=off") # this is not very general ######## Fg("brown") DrawSphere( 0.08 , height/2.0, (width*0.92), 0.04) DrawSphere(-0.08-thickness, height/2.0, (width*0.92), 0.04) WAttrib("texmode=on") } else { PushMatrix() Translate( -thickness/2.0, height/2.0, -width/2.0) Scale(thickness,height,width) #Translate( thickness/2.0 , height/2.0 , width ) Translate( 0 , 0 , width ) DrawCube(0,0,0,1) PopMatrix() WAttrib("texmode=off") # this is not very general ######## Fg("brown") DrawSphere( 0.08 , height/2.0, (width*0.92), 0.04) DrawSphere(-0.08-thickness, height/2.0, (width*0.92), 0.04) WAttrib("texmode=on") } PopMatrix() end # method render_x() method print_door() ## Door local rm printf(" door x,y,z,w,h,t %6.2r %6.2r %6.2r %6.2r %6.2r %6.2r \n", x, y, z, width, height, thickness ) printf(" openness, direction delt %6.2r %6.2r %6.2r \n", openness, direction, delt ) write(" plane ", plane ) write(" # rooms ",*rooms) every rm := !rooms do write(" room ", image(rm) ) write(" " ) end # method print_door() method set_open_angle() # Door if plane = 1 then { if /hinge_left then open_angle := 90.00 else open_angle := -90.00 } if plane = 3 then { if /hinge_left then open_angle := -90.00 else open_angle := 90.00 } end # method set_open_angle() # class Door:Opening( x, y, z, thickness, rotator, openness, hinge_left, direction, # delt, open_angle , texture, is_rendered) initially(x1, y1, z1, collide_in, tex, ht, wd) # ,width,height,thickness) ## Door self$Opening.initially( ) # (x, y, z) # be sure x,y,z,w,h,t are floats self.x := x1 self.y := y1 self.z := z1 # / x := 0.0 # / y := 0.0 # / z := 0.0 width := wd / width := 1.0 # default = 1 meter height := ht / height := 2.6 # default = 2.6 meters / thickness := 0.03 # something over an inch thick collide := (\collide_in | 0.8) # maybe should reduce to 0.8 or less texture := tex # default texture for this room openness := 0.00 direction := 1.00 delt := 0.03 hinge_left := &null open_angle := 0.00 is_rendered := &null plane := 3 end # class Door # # class Wall is a textured polygon # class Wall(texture, coords, minx, maxx, miny, maxy, minz, maxz, xdelta, ydelta, zdelta, plane, tex_fact) method calc_boundbox() ## Box local w, L, i maxx := minx := coords[1] maxy := miny := coords[2] maxz := minz := coords[3] L := coords every i := 4 to *L by 3 do { minx >:= L[i] maxx <:= L[i] miny >:= L[i+1] maxy <:= L[i+1] minz >:= L[i+2] maxz <:= L[i+2] } end method dist( p1, p2, p3, p4, p5, p6 ) ## Wall return ( ( ( abs( p4 - p1 ) ^ 2.0 ) + ( abs( p5 - p2 ) ^ 2.0 ) + ( abs( p6 - p3 ) ^ 2.0 ) ) ^ 0.50 ) end # method dist() method render() ## Wall local txcoords, i, c, mult_1, mult_2, tmp if world.current_texture ~=== texture then world.current_texture := texture # /tex_fact := [ 0.2, 0.2 ] # this should be a field in a texture object tex_fact := "off" # big debug printout # printf( "\n\n BEGIN WALL:::: \n" ) # self.printwall() # c := coords # printf( "\nWall: max x %8.2r, max y %8.2r, max z %8.2r \n", xdelta, ydelta, zdelta ) # self.printwall() if plane = 3 then { # z plane if tex_fact === "off" then { mult_1 := 1 mult_2 := 1 }else { mult_1 := xdelta / tex_fact[1] mult_2 := ydelta / tex_fact[2] } txcoords := [0.0, 0.0, 0.0, mult_2, mult_1, mult_2, mult_1, 0.0] # best # printf( " z_plane mult_1 mult_2 : %6.2r %6.2r \n",mult_1,mult_2 ) } else { if plane = 2 then { # y plane if tex_fact === "off" then { mult_1 := 1 mult_2 := 1 }else { mult_1 := xdelta / tex_fact[1] mult_2 := zdelta / tex_fact[2] } txcoords := [0.0, 0.0, 0.0, mult_2, mult_1, mult_2, mult_1, 0.0] # best # printf( " y_plane mult_1 mult_2 : %6.2r %6.2r \n",mult_1,mult_2 ) } else { if plane = 1 then { # x plane if tex_fact === "off" then { mult_1 := 1 mult_2 := 1 }else { mult_1 := zdelta / tex_fact[2] mult_2 := ydelta / tex_fact[1] } txcoords := [0.0, 0.0, 0.0, mult_2, mult_1, mult_2, mult_1, 0.0] # best # printf( " x_plane mult_1 mult_2 : %6.2r %6.2r \n",mult_1,mult_2 ) } else { write( " Render fails on Wall ") self.printwall() } } } # printf(" tx : %6.2r %6.2r %6.2r %6.2r \n", # txcoords[3],txcoords[4], txcoords[5],txcoords[6] ) # printf(" tx : %6.2r %6.2r %6.2r %6.2r \n", # txcoords[1],txcoords[2], txcoords[7],txcoords[8] ) # write (" texture : ", texture ) # # write( " end Wall:::" ) tmp := txcoords[1] || "," || txcoords[2] || "," || txcoords[3] || "," || txcoords[4] || "," || txcoords[5] || "," || txcoords[6] || "," || txcoords[7] || "," || txcoords[8] if WAttrib("texture="||\texture) then WAttrib("texcoord=" || tmp ) else write("no texture in wall, wanted ", image(\texture)) (FillPolygon ! coords) | write("FillPolygon fails") end # method render() method settexture(newtext) ## Wall # write( " resetting texture to ",newtext) texture := newtext # render() end method printwall() ## Wall local c c := coords printf(" Wall: %6.2r %6.2r %6.2r %6.2r %6.2r %6.2r \n", c[4],c[5],c[6],c[7],c[8],c[9] ) printf(" Wall: %6.2r %6.2r %6.2r %6.2r %6.2r %6.2r \n", c[1],c[2],c[3],c[10],c[11],c[12] ) write(" ------------------- ") end method set_plane() ## Wall local c plane := &null if /coords | (*coords=0) then fail c := coords if *c < 12 then stop("fatal: short wall needs 12 coordinates, had "|| *c) xdelta := max( abs( c[4]-c[1] ), abs(c[7]-c[4]), abs(c[10]-c[7]), abs(c[10] - c[1] ) ) ydelta := max( abs( c[5]-c[2] ), abs(c[8]-c[5]), abs(c[11]-c[8]), abs(c[11] - c[2] ) ) zdelta := max( abs( c[6]-c[3] ), abs(c[9]-c[6]), abs(c[12]-c[9]), abs(c[12] - c[3] ) ) if -0.0001 < zdelta < 0.05 then plane := 3 else if -0.0001 < ydelta < 0.05 then plane := 2 else if -0.0001 < xdelta < 0.05 then plane := 1 else { write( "Wall does not have a plane! " ) printwall() } end # method set_plane() method sort_coords() local L, T, d, c, i, j, k # sort is disabled return T := table() c := copy(coords) every i := 1 to *c by 3 do { d := dist( c[i], c[i+1], c[i+2], 0.0, 0.0, 0.0 ) T[i] := d } L := sort(T, 4) # sort by value, return list of alternating key,value k := 1 every i := (1 | 3 | 7 | 5) do { j := L[i] coords[k ] := c[j ] coords[k+1] := c[j+1] coords[k+2] := c[j+2] k +:= 3 } end # method sort_coords() initially(t, c[]) ## Wall texture := t coords := c sort_coords() set_plane() end # class Wall # # this class should not merge with class Room; # it has a separate existence because of obstacles and such # class Box( walls, minx, miny, maxy, maxx, minz, maxz, collide) # dtexture, collide ) method mkwall( x[] ) ## Box local w, t if type(x[1]) == "string" then t := pop(x) else t := world.d_wall_tex w := Wall ! push(x, t) put(walls, w) end method render() ## Box every (!walls).render() end # why did Box.disallows get removed? Someone not understand obstacles? method disallows(x,z) ## Box if /minx then calc_boundbox() if minx-collide <= x <= maxx+collide & minz-collide <= z <= maxz+collide then { return } end method calc_boundbox() ## Box local w, L, i maxx := minx := walls[1].coords[1] maxy := miny := walls[1].coords[2] maxz := minz := walls[1].coords[3] every w := !walls do { L := w.coords every i := 1 to *L by 3 do { # write(" L[i,i+1,i+2] ",L[i]," ",L[i+1]," ",L[i+2] ) minx >:= L[i] maxx <:= L[i] miny >:= L[i+1] maxy <:= L[i+1] minz >:= L[i+2] maxz <:= L[i+2] } } end initially() ## Box walls := [] # dtexture := world.find_texture("walltest.gif") # default texture for this room collide := world.collide # distance to maintain camera from walls to keep # textures unpixelated end # class Box # # class Room would denote a block with bounding walls. # Inside it are obstacles (affect movement) and decorations. # Exits may include doors and openings, both connecting to # other "Rooms". Cooridoors are rooms with openings. # # Room forms a natural unit of visibility, especially # when doors are closed. This may reduce the amount # of the world that needs to be rendered and the number # of textures that have to be loaded. # class Room : Box(floor, ceiling, obstacles, # things that should stop movement decorations, # things to just look at exits, # x-y ways to leave room name, # world, nearest_door, # avatar picks this one to open debug # switch for detailed debug info ) method inRoom(x,y,z) if /minx then calc_boundbox() if minx <= x <= maxx & miny <= y <= maxy & minz <= z <= maxz then return end # a room disallows a move if: (a) outside or (b) something in the way method disallows(x,y,z) ## Room # return disallows, fail allows local msg, o, e # write("checking if ", name, " disallows ",x,",",z) if /minx then calc_boundbox() # write( " minx-maxx minz-maxz x z ",minx,"-",maxx," ",minz,"-", maxz," ",x," ",z ) if minx+collide <= x <= maxx-collide & minz+collide <= z <= maxz-collide then { every o := !obstacles do { if o.disallows(x,z) then { return } } fail } else { every e := !exits do { if e.allows(x,z) then { if minx <= x <= maxx & minz <= z <= maxz then { #write("allow but don't change, still in ", # world.curr_room.name) } else { # change rooms and notify other users if \ (world.connection.connID) then { msg := "\\say leaves " || world.curr_room.name || " and enters " || e.other(self).name || " " # write( " debug move msg:" || msg ) write( world.connection.connID, msg ) } world.curr_room := e.other(self) } fail } } return } return end # method disallows ## Room method render() ## Room WAttrib("texmode=on") # write(" PRINTING OPENINGS ") # every (!exits).print_opening() every (!exits).render() # write(" floor.printwall() : " ) # floor.printwall() floor.render() ceiling.render() every (!walls).render() every (!obstacles).render() every (!decorations).render() end # figure out what wall this opening is in, and tear a hole in it, # for example, find the wall the opening is in, # remove that wall, and replace it with three sub-pieces of wall $ifdef UNDEF method add_opening(d) ## Room local c, i ,w, w2, w3, jj # list walls can be modified inside the loop, but doing so # gives "interesting" generator behavior, so if you do so, # it is wise to break or return out of the loop every jj := 1 to *walls do { w := walls[jj] # write("checking wall ",jj,"/",*walls," on plane ", w.plane, # " in room ", name, " for ", image(d)[8:0]) # w.sort_coords() c := w.coords if \debug then w.printwall() if (w.plane = 1) & (d.plane=1) then { # x plane if /(w.minx) then w.calc_boundbox() if ( abs(d.x - c[1]) < 0.08 & w.minz <= d.z <= w.maxz & w.miny <= d.y <= w.maxy ) then { # opening is in an xplane wall if d.z+d.width > w.maxz then { write("door/opening might be too wide for ", name, "\n\t z ", d.z, " width ", d.width, " z+w ", d.z+d.width, " maxz ", w.maxz) next } if d.y+d.height > w.maxy then { write("door/opening might be too high for ", name) next } # write("opening is on an xplane wall?") # remove this wall while walls[1] ~=== w do put(walls,pop(walls)) pop(walls) # replace it with three segments: # w = above, w2 = left, and w3 = right of door w2 := Wall ! ([w.texture] ||| w.coords) w3 := Wall ! ([w.texture] ||| w.coords) # write( "room add_door x,y,w,h ",d.x," ",d.y," ",d.width, # " ",d.height) every i := 1 to *w.coords by 3 do { w.coords[ i+1] <:= d.y + d.height w2.coords[i+1] >:= d.y + d.height w3.coords[i+1] >:= d.y + d.height w2.coords[i+2] >:= d.z w3.coords[i+2] <:= d.z + d.width } w.sort_coords() w.set_plane() w2.sort_coords() w2.set_plane() w3.sort_coords() w3.set_plane() w.calc_boundbox() w2.calc_boundbox() w3.calc_boundbox() put(walls, w, w2, w3) d.plane := 1 put(exits, d) d.add_room(self) # write( "room add_opening plane ", d.plane) # write( " adding wall w ") # w.printwall() # write( " adding wall w2 ") # w2.printwall() # write( " adding wall w3 ") # w3.printwall() return } } else { if (w.plane = 3) & (d.plane=3) then { if /(w.minx) then w.calc_boundbox() #write("checking a zplane wall ", image(d.z), " vs. ", c[3]) if (abs(d.z - c[3]) < 0.08 & w.minx <= d.x & d.x+d.width <= w.maxx & w.miny <= d.y & d.y+d.height <= w.maxy ) then { # door is in a zplane wall #write("found door on zplane wall in room ", name) # remove this wall while walls[1] ~=== w do put(walls,pop(walls)) pop(walls) # replace it with three segments: # w = above, w2 = left, and w3 = right of door w2 := Wall ! ([w.texture] ||| w.coords) w3 := Wall ! ([w.texture] ||| w.coords) # write( "room add_door x,y,w,h ",d.x," ",d.y," ",d.width," ",d.height) every i := 1 to *w.coords by 3 do { w.coords[ i+1] <:= d.y + d.height w2.coords[i+1] >:= d.y + d.height w3.coords[i+1] >:= d.y + d.height w2.coords[i] >:= d.x w3.coords[i] <:= d.x + d.width } w.sort_coords() w.set_plane() w2.sort_coords() w2.set_plane() w3.sort_coords() w3.set_plane() put(walls, w, w2, w3) put(exits, d) d.plane := 3 d.add_room(self) # write( "room add_door plane open_angle ", d.plane," ",d.open_angle) # write( " adding wall w ") # w.printwall() # write( " adding wall w2 ") # w2.printwall() # write( " adding wall w3 ") # w3.printwall() return } } } } write(&errout, "no wall found for ", image(d), " from room ", name, " to ", (d.other(self).name) | "?") if \debug then d.print_door() end # method add_opening ## Room $else method add_opening(d) ## Room local c, i ,w, w2, w3, jj # list walls can be modified inside the loop, but doing so # gives "interesting" generator behavior, so if you do so, # it is wise to break or return out of the loop every jj := 1 to *walls do { w := walls[jj] #if find("Opening", type(d)) & # (d.plane=3) & # name==("atrium"|"atrium south") then # write("checking wall ",jj,"/",*walls," on plane ", w.plane, # " in room ", name, " for ", image(d)[8:0]) c := w.coords # if \debug then #if find("Opening", type(d)) & # (d.plane=3) & # name==("atrium"|"atrium south") then # w.printwall() if (w.plane = 1) & (d.plane=1) then { # x plane if /(w.minx) then w.calc_boundbox() if ( abs(d.x - c[1]) < 0.08 & w.minz <= d.z <= w.maxz & w.miny <= d.y <= w.maxy ) then { # opening is in an xplane wall if d.z+d.width > w.maxz then { write("door/opening might be too wide for ", name, "\n\t z ", d.z, " width ", d.width, " z+w ", d.z+d.width, " maxz ", w.maxz) next } if d.y+d.height > w.maxy then { write("door/opening might be too high for ", name) next } # write("opening is on an xplane wall?") # remove this wall while walls[1] ~=== w do put(walls,pop(walls)) pop(walls) # replace it with three segments: # w = above, w2 = left, and w3 = right of door w2 := Wall ! ([w.texture] ||| w.coords) w3 := Wall ! ([w.texture] ||| w.coords) # write( "room add_door x,y,w,h ",d.x," ",d.y," ",d.width, # " ",d.height) every i := 1 to *w.coords by 3 do { w.coords[ i+1] <:= d.y + d.height w2.coords[i+1] >:= d.y + d.height w3.coords[i+1] >:= d.y + d.height w2.coords[i+2] >:= d.z w3.coords[i+2] <:= d.z + d.width } w.sort_coords() w.set_plane() w2.sort_coords() w2.set_plane() w3.sort_coords() w3.set_plane() w.calc_boundbox() w2.calc_boundbox() w3.calc_boundbox() put(walls, w, w2, w3) d.plane := 1 put(exits, d) d.add_room(self) # write( "room add_opening plane ", d.plane) # write( " adding wall w ") # w.printwall() # write( " adding wall w2 ") # w2.printwall() # write( " adding wall w3 ") # w3.printwall() return } } else { if (w.plane = 3) & (d.plane=3) then { if /(w.minx) then w.calc_boundbox() # write("checking a zplane wall ", image(d.z), " vs. ", c[3]) # write("w.miny ", image(w.miny), " w.maxy ", image(w.maxy)) # write("d.y ", image(d.y), " d.y+ht ", d.y+d.height) if ((abs(d.z - c[3]) < 0.08) & (w.minx <= d.x) & (d.x+d.width <= w.maxx) & (w.miny <= d.y) & (d.y+d.height <= w.maxy) ) then { # door is in a zplane wall # write("found door on zplane wall in room ", name) # remove this wall while walls[1] ~=== w do put(walls,pop(walls)) pop(walls) # replace it with three segments: # w = above, w2 = left, and w3 = right of door w2 := Wall ! ([w.texture] ||| w.coords) w3 := Wall ! ([w.texture] ||| w.coords) # write( "room add_door x,y,w,h ",d.x," ",d.y," ", # d.width," ",d.height) every i := 1 to *w.coords by 3 do { w.coords[ i+1] <:= d.y + d.height w2.coords[i+1] >:= d.y + d.height w3.coords[i+1] >:= d.y + d.height w2.coords[i] >:= d.x w3.coords[i] <:= d.x + d.width } w.sort_coords() w.set_plane() w2.sort_coords() w2.set_plane() w3.sort_coords() w3.set_plane() w.calc_boundbox() w2.calc_boundbox() w3.calc_boundbox() put(walls, w, w2, w3) put(exits, d) d.plane := 3 d.add_room(self) # write( "room add_door plane open_angle ", d.plane," ",d.open_angle) # write( " adding wall w ") # w.printwall() # write( " adding wall w2 ") # w2.printwall() # write( " adding wall w3 ") # w3.printwall() return } } } } write(&errout, "no wall found for Door/Opening ", d.id, " from room ", name, " to ", (d.other(self).name) | "?") # if \debug then d.print_door() end # method add_opening ## Room $endif # obj is cam or avatar method select_nearest_door( obj ) ## Room local i, idx, minval, tmp every i := 1 to *exits do { if type(exits[i])[1+:4] ~== "Door" then next tmp := exits[i].distance(obj.x, obj.y, obj.z) if /minval | (tmp < minval) then { idx := i minval := tmp } } nearest_door := exits[\idx] end # method select_nearest_door ## Room method add_obstacle(o) ## Room put(obstacles, o) end method add_decoration(d) ## Room put(decorations, d) end # really need multi textures - floor, wall, ceiling if we're going to have # defaults at this level... initially(nam,x,y,z,w,h,l,tex) ## Room self$Box.initially() # world := worl # dtexture := world.d_wall_tex /tex := world.d_wall_tex nearest_door := &null name := nam floor := Wall(world.d_floor_tex, x, y , z, x, y , z+l, x+w, y , z+l, x+w, y , z ) ceiling:= Wall(world.d_ceil_tex, x, y+h, z, x, y+h, z+l, x+w, y+h, z+l, x+w, y+h, z ) mkwall(tex, x, y, z+l, x , y+h, z+l, x+w, y+h, z+l, x+w, y, z+l) # back wall (3'?) mkwall(tex, x+w, y, z , x+w, y+h, z , x+w, y+h, z+l, x+w, y, z+l) # right wall mkwall(tex, x, y, z , x , y+h, z , x , y+h, z+l, x , y, z+l) # left wall mkwall(tex, x, y, z , x , y+h, z , x+w, y+h, z , x+w, y, z ) # front wall exits := [] obstacles := [] decorations := [] collide := world.collide debug := &null end # class Room class ToolsUtilities(opMode,x,y,z,Id, origXangle,origYangle,origZangle, romx,romy,romz, rox,roy,roz, mov,rot,mv,mvDraw, sca, movable, isMoving, owner, placedAt, cover, render_set, avatarSizeX, avatarSizeY, avatarSizeZ, avatarPartX, avatarPartY, avatarPartZ, avatarObjX, avatarObjY, avatarObjZ, possessed, name ) method setSize(xscale,yscale,zscale) avatarSizeX:=xscale avatarSizeY:=yscale avatarSizeZ:=zscale #sca.x:=xscale #sca.y:=yscale #sca.z:=zscale end method setPosAvatar(posx,posy,posz,angle) #write("entered setposavatar") mov.x:=posx mov.y:=posy mov.z:=posz rot.angle:=angle end method setPosPart(posx,posy,posz) #write("entered setpospart") avatarPartX:=posx avatarPartY:=posy avatarPartZ:=posz mv.x:=posx mv.y:=posy mv.z:=posz end method setPosObj(posx,posy,posz) #write("entered setposobj") avatarObjX:=posx avatarObjY:=posy avatarObjZ:=posz mvDraw.x:=posx mvDraw.y:=posy mvDraw.z:=posz rox.angle:=110 roy.angle:=0 roz.angle:=0 end method moveAlongAvatar(posx,posy,posz,angle) #write("entered movealongavatar") rot.angle:=angle mov.x:=posx mov.y:=posy mov.z:=posz end method moveAlongPart(xangle,yangle,zangle) #write("entered movealongpart") romx.angle:=xangle romy.angle:=yangle romz.angle:=zangle end method deRender() local len, i, item, dispList dispList := WindowContents(&window) len := *WindowContents(&window) every i := 1 to len do { item := pop(dispList) if not member(render_set,item) then put(dispList, item) } return end # method deRender() method getX() return x end method getY() return y end method getZ() return z end method getOwner() return owner end method setOwner(newowner) owner:=newowner end method getPlacedAt() return placedAt end method getMovable() return isMoving end method getPossessed() return possessed end initially() render_set := set() #possessed := 0 end # # Class Book # class Book : ToolsUtilities( color,angle, scalex,scaley,scalez,scaleside, height, width, length, defaultOwner ) method reRender() render() setSize(avatarSizeX,avatarSizeY,avatarSizeZ) setPosPart(avatarPartX,avatarPartY,avatarPartZ) setPosObj(avatarObjX,avatarObjY,avatarObjZ) end method render() local i,j,height1 i := 0 PushMatrix() sca:=Scale(1,1,1) mov:=Translate(x,y,z) rot:=Rotate(0,0,1,0) PushMatrix() mv:=Translate(0,0,0) romx:=Rotate(0,1,0,0) romy:=Rotate(0,0,1,0) romz:=Rotate(0,0,0,1) PushMatrix() mvDraw:=Translate(0,0,0) rox:=Rotate(origXangle,1,0,0) roy:=Rotate(origYangle,0,1,0) roz:=Rotate(origZangle,0,0,1) WAttrib("texmode=off") WAttrib("fg="||color) PushMatrix() scaleside := (height*scaley)/0.06 Translate(-((scalex*0.06)/2),-((scaleside*0.06)/2),0) Scale(scaley,scaleside,scalez) DrawCube(0,0,0,0.06) PopMatrix() PushMatrix() Scale(scalex,scaley,scalez) #write("Book color",color) WAttrib("fg="||color) DrawCube(0,0,0,0.06) PushMatrix() Translate(0,-height,0) DrawCube(0,0,0,0.06) PopMatrix() height1 := height/10 WAttrib("fg=diffuse white") every j:=1 to 8 do { i := i - height1 PushMatrix() Translate(0,i,0) Scale(1,scaley,1) DrawCube(0,0,0,0.06) PopMatrix() } PopMatrix() PopMatrix() PopMatrix() PopMatrix() WAttrib("texmode=on") end method allows(posx,posy,posz) #write("X: ", posx, " | ", x) #write("Y: ", posy, " | ", y) #write("Z: ", posz, " | ", z) #write("possessed in allows = ",possessed) if x-1 <= posx <= x+1 & z-1 <= posz <= z+1 then { isMoving:=1 return 1 } else return 0 end method unpossessed(posx,posy,posz) #write("entered unpossessed method") mov.x:=posx x := posx write("x:=", mov.x) mov.y:=length/2 mov.z:=posz z := posz write("z:=", mov.z) mv.x:=0 mv.y:=0 mv.z:=0 mvDraw.x:=0 mvDraw.y:=0 mvDraw.z:=0 romx.angle:=0 romy.angle:=0 romz.angle:=0 rox.angle:=origXangle roy.angle:=origYangle roz.angle:=origZangle owner:=defaultOwner possessed := 0 end initially(opMode,coords,col,A) self.opMode := opMode /x := coords[1] /y := coords[2] /z := coords[3] color := col /color := "blue" /origXangle:=0 origYangle := A /origYangle:=0 /origZangle:=0 /movable:=1 /isMoving:=0 /defaultOwner:="nobody" /owner:=defaultOwner /placedAt:="hand" /cover:="book.gif" /scalex := 4 /scaley := 0.1 /scalez := 7 /height := 0.7 /width := 0.06 /length := 0.06 /possessed := 0 /name := "Book" end # # abstract class that describes what obstacles do # class Obstacle(opMode,action) method render() #write("render!") end method disallows() #write("disallows") end end # # Chair.icn # # In class declaration I am taking the variables from T1 to T4 # (including the variables in between them) as reference to # the operations performed on different parts of the chair. # I am going to use these variables in rotation,moving functions. class Chair:Obstacle( x, # x coordinate of chair position y, # y coordinate of chair position z, # z coordinate of chair position color, # color of the chair position_cube, # position of the cube type, dle1, dle2, dle3, movable, # Tells whether the chair is movable or not minx,maxx,miny,maxz,minz,maxy,collide, #variables which restricts the # movement through the chair name, # these variables are used for accessing the various graphical operations # of the render method in remaining methods. T1,T2,R1,R2,Tleg1,Tleg2,Tleg3,Tleg4,Tdisk,Tstand,Trod,Tbottom,Tscube, Ts1,Ts2,Ts3,Ts4,T3,T4 ) method render(render_level) # local i,flag,k,l,xtrans,ztrans, win3d if \dle3 then { case render_level of { 0: { dle1.skip := 1 fail } 1: { dle1.skip := 0 dle2.skip := 1 fail } 2: { dle1.skip := dle2.skip := 0 dle3.skip := 1 fail } 3: { dle1.skip := dle2.skip := dle3.skip := 0 fail } } } else full_detail_draw() end method full_detail_draw() local i,flag,k,l,xtrans,ztrans, win3d WAttrib("dim=3") WAttrib("texmode=off") win3d := !gui::dispatcher.subwins dle1 := WSection(win3d, "Chain") PushMatrix() Translate(0,0.65,0) # Upper Cube PushMatrix() Draw_Parts("cube",position_cube) Rotate(-10,1,0,0) Scale(3.5,2.25,1) Fg("diffuse"||" " || color ) DrawCube(0,0,0,0.16) PopMatrix() # Disk PushMatrix() Tdisk := Translate(x,y,z) Rotate(90,1.0,0,0) DrawDisk(0,0,0,0,0.32) PopMatrix() #Cylinder rod below stand PushMatrix() Trod := Translate(0,-0.56,0) DrawCylinder(x,y,z,0.48,0.055,0.055) PopMatrix() dle2 := WSection(win3d, "Chair2") # Cube at the bottom of stand (It connects all the legs) PushMatrix() Tscube := Translate(x,y+(y/2)+0.12,z) Scale(2.8,1.75,1) Fg("diffuse black") DrawCube(0,0,0,0.05) PopMatrix() #Connector to Disk and back Cube PushMatrix() Draw_Parts("connector",position_cube) Rotate(-10,1,0,0) Scale(2.5,6.5,1.75) DrawCube(0,0,0,0.05) PopMatrix() # Cylinder at the bottom of stand PushMatrix() Translate(0,-0.56,0) Tbottom := DrawCylinder(x,y,z,0.1,0.065,0.065) PopMatrix() # dle2 # WSection(win3d) dle3 := WSection(win3d, "Chair3") # the legs below to the chair. flag := 0 i := 1 while i <= 2 do { PushMatrix() if flag == 0 then { Tleg1:= Translate(x,y+0.09,z-0.155) Rotate(80, 0.5,0,0) } else { Tleg2 := Translate(x,y+0.09,z+0.155) Rotate(-80,0.5,0,0) } Rotate(90,0,0.65,0) Scale(1,4.25,0.7) Fg("diffuse black") DrawCube(0,0,0,0.05) flag := 1 i +:= 1 PopMatrix() } flag := 0 i := 1 while i <= 2 do { PushMatrix() if flag == 0 then { Tleg3 := Translate(x+0.155,y+0.09,z) Rotate(-10,0,0,0.06) } else { Tleg4 := Translate(x-0.155,y+0.09,z) Rotate(10,0,0,0.06) } Scale(4.25,1,0.7) DrawCube(0,0,0,0.05) PopMatrix() i +:= 1 flag := 1 } # Cylinder above Stand and below disk PushMatrix() Tstand := Translate(0,-0.1,0) DrawCylinder(x,y,z,0.1,0.32,0.32) PopMatrix() Fg("diffuse black") # Spheres Drawsphere(-0.275,0,0,1) Drawsphere(0.275,0,0,2) Drawsphere(0,0,-0.275,3) Drawsphere(0,0,0.275,4) WAttrib("texmode=on") #dle3 WSection(win3d) #dle2 WSection(win3d) PopMatrix() # dle1 WSection(win3d) end method Draw_Parts(component,angle) local ang_rad,x_trans,z_trans if component == "cube" then { ang_rad := dtor(angle) x_trans := (-0.32) * sin(ang_rad) z_trans := (-0.32) * cos(ang_rad) T2 := Translate(x_trans,0,z_trans) T4 := Translate(x+0,y+0.48,z) R2 := Rotate(angle,0.0,1.2,0.0) } else if component == "connector" then { ang_rad := dtor(angle) x_trans := (-0.32) * sin(ang_rad) z_trans := (-0.32) * cos(ang_rad) T1 := Translate(x_trans,0,z_trans) T3 := Translate(x,y+0.15,z) R1 := Rotate(angle,0.0,1.2,0.0) } end method Drawsphere(x1,y1,z1,s) PushMatrix() case s of { 1: { Ts1 := Translate(x1,y1,z1) } 2: { Ts2 := Translate(x1,y1,z1) } 3: { Ts3:= Translate(x1,y1,z1) } 4: { Ts4:= Translate(x1,y1,z1) } } DrawSphere(x,y+0.04,z,0.035) PopMatrix() end method draw_support(anglez,angles) local xtrans,ztrans,ang_rad ang_rad := dtor(position_cube + angles) xtrans := 0.28 * sin(ang_rad) ztrans := 0.28 * cos(ang_rad) PushMatrix() Translate(xtrans,0,ztrans) Rotate(position_cube,0,1,0) Rotate(anglez,0,0,1) DrawCylinder(0,0,0,0.32,0.02,0.015) PopMatrix() end method draw_leg(anglex,anglel) local xtrans,ztrans,rads rads := dtor(position_cube + anglel) xtrans := 0.25 * sin(rads) ztrans := 0.25 * cos(rads) PushMatrix() Translate(xtrans,-0.52,ztrans) Rotate(position_cube,0,1,0) Rotate(anglex,1,0,0) DrawCylinder(0,0,0,0.55,0.02,0.02) PopMatrix() end # Here I am taking the parametric equation of a line in 3D. # By using which I am tracking the all points lies between the # given point and the point of location of the chair. method move_chair(x_dest,y_dest,z_dest) local distance,i,j, flag, incr i := 0 j := 1 flag := 0 if movable == "true" then { distance := sqrt( ((x-x_dest)*(x-x_dest))+ ((y-y_dest)*(y-y_dest)) + ((z-z_dest)*(z-z_dest)) ) incr := 0 # repeating until 'incr'(parameter in line equation) # becomes equal to 1. while incr <= 1 do { while j <= 2 do { if flag == 0 then { # parametric equation x := x1 + t (x2-x1) Tleg1.x := Tleg1.x + incr * (x_dest-x) # parametric equation z:= z1 + t (z2-z1) Tleg1.z := Tleg1.z + incr * (z_dest-z) } else { Tleg2.x := Tleg2.x + incr * (x_dest-x) Tleg2.z := Tleg2.z + incr * (z_dest-z) } flag := 1 j := j + 1 } flag := 0 j := 1 while j <= 2 do { if flag == 0 then { Tleg3.x := Tleg3.x + incr * (x_dest-x) Tleg3.z := Tleg3.z + incr * (z_dest-z) } else { Tleg4.x := Tleg4.x + incr * (x_dest-x) Tleg4.z := Tleg4.z + incr * (z_dest-z) } j := j + 1 flag := 1 } j := 1 flag := 0 T3.x := T3.x + incr * (x_dest-x) T3.z := T3.z + incr * (z_dest-z) T4.x := T4.x + incr * (x_dest-x) T4.z := T4.z + incr * (z_dest-z) Tdisk.x := Tdisk.x + incr * (x_dest-x) Tdisk.z := Tdisk.z + incr * (z_dest-z) Tstand.x := Tstand.x + incr * (x_dest-x) Tstand.z := Tstand.z + incr * (z_dest-z) Trod.x := Trod.x + incr * (x_dest-x) Trod.z := Trod.z + incr * (z_dest-z) Tbottom.x := Tbottom.x + incr * (x_dest-x) Tbottom.z := Tbottom.z + incr * (z_dest-z) Tscube.x := Tscube.x + incr * (x_dest-x) Tscube.z := Tscube.z + incr * (z_dest-z) Ts1.x := Ts1.x + incr * (x_dest-x) Ts1.z := Ts1.z + incr * (z_dest-z) Ts2.x := Ts2.x + incr * (x_dest-x) Ts2.z := Ts2.z + incr * (z_dest-z) Ts3.x := Ts3.x + incr * (x_dest-x) Ts3.z := Ts3.z + incr * (z_dest-z) Ts4.x := Ts4.x + incr * (x_dest-x) Ts4.z := Ts4.z + incr * (z_dest-z) if distance < 1 then incr := incr + (1/(6*distance)) else incr := incr + (1/(5*distance)) delay(250) Refresh() } } else { write("the chair cannot move") } end method Rotate_Chair(dir) local theta,x_trans,z_trans , ang_rad,i i:=0 theta := position_cube if \dir then { every i:= 1 to 35 do { Refresh() if dir == "positive" then theta := theta + 20 else if dir == "negative" then theta := theta - 20 ang_rad := dtor(theta) x_trans := (-0.16) * sin(ang_rad) z_trans := (-0.16) * cos(ang_rad) T1.x := 0+x_trans T1.z := 0+z_trans R1.angle := 0+theta T2.x := 0+x_trans T2.z := 0+z_trans R2.angle := 0+theta delay(50) Refresh() } } end method disallows(x,z) ## Box #calc_boundbox_chair() if minx-collide <= x <= maxx+collide & minz-collide <= z <= maxz+collide then { return } fail end initially(coords,pos,col,kind,mov) # write("OPMODE",opMode) #self.opMode := opMode x := coords[1] y := coords[2] z := coords[3] movable := mov position_cube := pos color := col type := kind # default values /x := 0 /y := 0 /z := 0 /movable := "true" /position_cube := "-z" /color := "blue" /type := "office" /minx := x - 0.7 /miny := y /minz := z - 0.7 /maxx := x + 0.7 /maxy := y /maxz := z + 0.7 /collide := 0.1 /name := "Chair" # write(color, " chair created") end class Computer:Obstacle( x_mntr,y_mntr,z_mntr, #coordinates of monitor x_cpu,y_cpu,z_cpu, #coordinates of cpu x_kb,y_kb,z_kb, #coordinates of key board angle, #angle color, #color of the computer users, #its a table which contains the info of users of this computer owner, #tells owner of the computer name, #tells name of the computer status, #tells the status of the computer minx,miny,minz,maxx, maxy,maxz,collide, # variables which restricts the avatar # movement through the computer dle_mon1, dle_mon2, dle_kb1, dle_kb3, dle_cpu1, dle_cpu2, dle_drv1, dle_drv3 ) method render(render_level) WAttrib("texmode=off") if \dle_mon1 then { case render_level of { 0: { dle_mon1.skip := dle_kb1.skip := dle_cpu1.skip := dle_drv1.skip := 1 } 1: { dle_mon1.skip := 0 dle_mon2.skip := 1 dle_kb1.skip := 0 dle_kb3.skip := 1 dle_cpu1.skip := 0 dle_cpu2.skip := 1 dle_drv1.skip := 0 dle_drv3.skip := 1 } 2: { dle_mon1.skip := 0 dle_mon2.skip := 0 dle_kb1.skip := 0 dle_kb3.skip := 1 dle_cpu1.skip := 0 dle_cpu2.skip := 0 dle_drv1.skip := 0 dle_drv3.skip := 1 } default: { dle_mon1.skip := dle_mon2.skip := dle_kb1.skip := dle_kb3.skip := dle_cpu1.skip := dle_cpu2.skip := dle_drv1.skip := dle_drv3.skip := 0 } } fail } else { draw_MONITOR(x_mntr,y_mntr,z_mntr,angle,color) draw_CPU(x_cpu,y_cpu,z_cpu,angle,color) draw_KB(x_kb,y_kb,z_kb,angle,color) #draw_MOUSE(x,y,z,angle,color) WAttrib("texmode=on") } end method draw_MONITOR(x,y,z,angle,col) local x_trans,z_trans, win3d win3d := !gui::dispatcher.subwins dle_mon1 := WSection(win3d, "Monitor1") x_trans := 0.15 * sin(dtor(angle)) z_trans := 0.15 * cos(dtor(angle)) WAttrib("fg=black") PushMatrix() PushMatrix() Translate(x+x_trans,y,z+z_trans) Rotate(angle,0,1,0) Scale(2.2,5,1.4) DrawCube(0,0,0,0.06) PopMatrix() x_trans := 0.17 * sin(dtor(angle)) z_trans := 0.17 * cos(dtor(angle)) PushMatrix() Translate(x+x_trans,y-0.05,z+z_trans) Rotate(angle,0,1,0) Rotate(90,1,0,0) Scale(6,6,0.15) DrawSphere(0,0,0,0.025) PopMatrix() x_trans := 0.215 * sin(dtor(angle)) z_trans := 0.215 * cos(dtor(angle)) PushMatrix() PushMatrix() Translate(x+x_trans,y+0.17,z+z_trans) Rotate(angle,0,1,0) Scale(4,4,0.8) DrawCube(0,0,0,0.06) PopMatrix() x_trans := 0.255 * sin(dtor(angle)) z_trans := 0.255 * cos(dtor(angle)) PushMatrix() Translate(x+x_trans,y+0.27,z+z_trans) Rotate(angle,0,1,0) Scale(7,7,0.7) DrawCube(0,0,0,0.06) PopMatrix() PopMatrix() x_trans := 0.28 * sin(dtor(angle)) z_trans := 0.28 * cos(dtor(angle)) dle_mon2 := WSection(win3d, "Monitor2") PushMatrix() Translate(x+x_trans,y,z+z_trans) Rotate(angle,0,1,0) WAttrib("texmode=on") WAttrib("texcoord=0,0,0,1,1,1,1,0") | write("texcoord failed") WAttrib("texture=dat/textures/screen2.gif") | write("texture=monitor.gif failed") FillPolygon(-0.16,0.12,0, -0.16,0.44,0, 0.16,0.44,0, 0.16,0.12,0) WAttrib("texmode=off") Fg("light gray") draw_monitorbtn(0.02,0.09,0,1.7) draw_monitorbtn(0.06,0.09,0,2) draw_monitorbtn(-0.02,0.09,0,1.7) draw_monitorbtn(-0.06,0.09,0,2) PopMatrix() WSection(win3d) PopMatrix() WSection(win3d) end method draw_monitorbtn(x1,y1,z1,scalex) PushMatrix() Translate(x1,y1,z1) Scale(scalex,0.8,0.4) DrawSphere(0,0,0,0.005) PopMatrix() end method draw_KB(x,y,z,angle,col) local x_trans,z_trans, win3d win3d := !gui::dispatcher.subwins dle_kb1 := WSection(win3d, "kb1_0") x_trans := 0 z_trans := 0 Fg(color) PushMatrix() Translate(x+x_trans,y,z+z_trans) Rotate(angle,0,1,0) Rotate(15,1,0,0) PushMatrix() Scale(8.5,0.3,3.5) Fg("black") DrawCube(0,0,0,0.06) PopMatrix() WAttrib("texmode=on") dle_kb3 := WSection(win3d, "kb3") PushMatrix() Translate(0,0.01,0) Scale(8.5,0.3,3.5) WAttrib("texcoord=0,0,1,0,1,1,0,1") | write("texcoord failed") WAttrib("texture=dat/textures/keyboard.gif") | write("texture=keyboard.gif failed") FillPolygon(-0.03,0,0.03, 0.03,0,0.03, 0.03,0,-0.03, -0.03,0,-0.03) PopMatrix() WSection(win3d) PopMatrix() WAttrib("texmode=off") WSection(win3d) end method draw_drive(angle,theight,drive) local x_trans,z_trans, win3d win3d := !gui::dispatcher.subwins dle_drv1 := WSection(win3d, "drive1") x_trans := 0.18 * sin(dtor(angle)) z_trans := 0.18 * cos(dtor(angle)) PushMatrix() Translate(x_trans,theight,z_trans) Rotate(angle,0,1,0) Scale(1.3,0.3,1.2) dle_drv3 := WSection(win3d, "drive3") WAttrib("texmode=on","texcoord=0,0, 0,1, 1,1, 1,0") WAttrib("texture=dat/textures/" || drive || ".gif") | write("texture=drive.gif failed") FillPolygon(-0.075,-0.07,0.076, -0.075,0.09,0.076, 0.075,0.09,0.076, 0.075,-0.07,0.076) WAttrib("texmode=off") WSection(win3d) WAttrib("fg=black") DrawCube(0,0,0,0.15) PopMatrix() # dle_drv1 WSection(win3d) end method draw_button(angle,height,r) local x_trans,z_trans x_trans := r * sin(dtor(angle)) z_trans := r * cos(dtor(angle)) PushMatrix() Translate(x_trans,height,z_trans) Rotate(angle,0,1,0) DrawSphere(0,0,0,0.013) PopMatrix() end method draw_CPU(x,y,z,angle,col) local x_trans,z_trans, win3d win3d := !gui::dispatcher.subwins dle_cpu1 := WSection(win3d, "cpu1") PushMatrix() Translate(x,y+0.12,z) WAttrib("fg=black") PushMatrix() Rotate(angle,0,1,0) Scale(1.5,3.4,3.6) DrawCube(0,0,0,0.15) PopMatrix() PushMatrix() Translate(0,-0.03,0) Rotate(angle,0,1,0) WAttrib("texmode=on","texcoord=0,0, 0,1, 1,1, 1,0") WAttrib("texture=dat/textures/nmsulogo.gif") | write("texture=nmsulogo.gif failed") FillPolygon(-0.03,-0.06,0.275,-0.03,0.0,0.275, 0.03,0.0,0.275,0.03,-0.06,0.275) WAttrib("texture=dat/textures/name2.gif") | write("texture=name2.gif failed") FillPolygon(-0.1,-0.2,0.275, -0.1,-0.125,0.275, 0.1,-0.125,0.275, 0.1,-0.2,0.275) PopMatrix() dle_cpu2 := WSection(win3d, "cpu2") WAttrib("texmode=off") draw_drive(angle,0.2,"cddrive") draw_drive(angle,0.13,"dvddrive") WAttrib("fg=red") draw_button(angle+15,0.05,0.272) WAttrib("fg=green") draw_button(angle+15,0.02,0.268) WSection(win3d) PopMatrix() WSection(win3d) end method disallows(x,z) ## Box #calc_boundbox_chair() if minx-collide <= x <= maxx+collide & minz-collide <= z <= maxz+collide then { return } fail end initially(coords_mntr,coords_cpu,coords_kb,col,A) x_mntr := coords_mntr[1] y_mntr := coords_mntr[2] z_mntr := coords_mntr[3] x_cpu := coords_cpu[1] y_cpu := coords_cpu[2] z_cpu := coords_cpu[3] x_kb := coords_kb[1] y_kb := coords_kb[2] z_kb := coords_kb[3] angle := A color := col #default values /x_mntr := 0 /y_mntr := 0 /z_mntr := 0 /x_cpu := 0 /y_cpu := 0 /z_cpu := 0 /x_kb := 0 /y_kb := 0 /z_kb := 0 /color := "gray" /owner := "no owner" /status := "free" /name := "Computer" /users := table() /minx := x_mntr - 0.9 /miny := y_mntr /minz := z_mntr - 0.9 /maxx := x_mntr + 0.9 /maxy := y_mntr /maxz := z_mntr + 0.9 /collide := 0.1 end # # Virtual Pen/marker # class Pen : ToolsUtilities( color, defaultOwner, dle1, dle2 ) method reRender(render_level) render(render_level) #write("avatarSizeX :=", avatarSizeX) #write("avatarPartX :=", avatarPartX) #write("avatarObjX :=", avatarObjX) setSize(avatarSizeX,avatarSizeY,avatarSizeZ) setPosPart(avatarPartX,avatarPartY,avatarPartZ) setPosObj(avatarObjX,avatarObjY,avatarObjZ) end method render(render_level) if \dle1 then { if render_level=0 then { # 'derender' dle1.skip := 1 } else if render_level=1 then { # 'minimal' dle1.skip := 0 dle2.skip := 1 } else { dle1.skip := 0 dle2.skip := 0 } } else { full_pen_detail() render(render_level) } end method full_pen_detail() local win3d win3d := !gui::dispatcher.subwins dle1 := WSection(win3d, "Pen1_0") PushMatrix() sca:=Scale(1,1,1) mov:=Translate(x,y,z) rot:=Rotate(0,0,1,0) # SET POSITION PART# PushMatrix() mv:=Translate(0,0,0) romx:=Rotate(0,1,0,0) romy:=Rotate(0,0,1,0) romz:=Rotate(0,0,0,1) # SET POSITION OBJECT# PushMatrix() mvDraw:=Translate(0,0,0) rox:=Rotate(origXangle,1,0,0) roy:=Rotate(origYangle,0,1,0) roz:=Rotate(origZangle,0,0,1) WAttrib("texmode=off") Fg("white") # Upper part DrawCylinder(0,0,0,0.35,0.035,0.035) dle2 := WSection(win3d, "Pen2") #Lower part DrawCylinder(0,0.35,0,0.09,0.035,0.015) # Point WAttrib("fg="||color) DrawCylinder(0,0.44,0,0.05,0.015,0.003) # Top DrawCylinder(0,-0.09,0,0.09,0.035,0.035) # Closing for Top DrawSphere(0,-0.09,0,0.035) # dle2 WSection(win3d) WAttrib("texmode=on") PopMatrix() PopMatrix() PopMatrix() # dle1 WSection(win3d) end method allows(posx,posy,posz) #write("X: ", posx, " | ", x) #write("Y: ", posy, " | ", y) #write("Z: ", posz, " | ", z) #write("possessed for pen=",possessed) if x-1 <= posx <= x+1 & z-1 <= posz <= z+1 then { isMoving := 1 return 1 } else return 0 end method unpossessed(posx,posy,posz) #write("entered unpossessed method") mov.x := posx x := posx #write("x:=", mov.x) mov.y := 0 mov.z := posz z := posz #write("z:=", mov.z) mv.x := 0 mv.y := 0 mv.z := 0 mvDraw.x := 0 mvDraw.y := 0 mvDraw.z := 0 romx.angle:=0 romy.angle:=0 romz.angle:=0 rox.angle:=origXangle roy.angle:=origYangle roz.angle:=origZangle owner:=defaultOwner possessed := 0 end initially(opMode,ID,coords,col,A) self.opMode := opMode /Id := ID #write("ID ", self.Id) /x:=coords[1] /y:=coords[2] /z:=coords[3] color := col /color := "blue" /origXangle:=90 origYangle := A /origYangle:=0 /origZangle:=0 /movable:=1 /isMoving:=0 /defaultOwner:="nobody" /owner:=defaultOwner /name:= "Pen" /placedAt:="hand" /cover:="pencil.gif" /render_set := set() /possessed := 0 #/name := "Pen" end class Printer:Obstacle(x,y,z, #coordinates of the position of the computer color, # color of the printer angle, # angle at which printershould be places in side the room name, # contains name of the printer status, # status of the printer (on, off, busy) tray, # table which gives the status of the trays job, #job queue contains info of jobs executing currently on printer minx,miny,minz,maxx, # collide variables maxy,maxz,collide # variables which restricts the avatar movement # through the computer ) method render() WAttrib("texmode=off") WAttrib("fg=black") draw_component(0,0,0, 3,0.15,4, 0,angle, 0,0, "notexture") draw_component(0,0.095,0, 3,0.15,4, 0,angle, 0,0, "notexture") draw_component(0,0.189,0, 3,0.15,4, 0,angle, 0,0, "notexture") draw_component(0,0.012,0, 3,0.05,4, 0,angle, 0,0, "notexture") WAttrib("fg=white") draw_component(0,0.019,0, 3,0.12,4, 0, angle, 0,0, "notexture") draw_component(0,0.056,0, 3,0.5,0.1, 0.24, angle, 0,0, "notexture") draw_component(0,0.056,0, 4,0.5,0.1, 0.173, 90+angle, 0,0, "notexture") draw_component(0,0.056,0, 3,0.5,0.1, 0.24, 180+angle, 0,0, "notexture") draw_component(0,0.056,0, 4,0.5,0.1, 0.173, 270+angle, 0,0, "notexture") if tray["tray1_status"] == "nonempty" then draw_label(0,0.056,0, 0.247, angle, 0,1, "two") else draw_label(0,0.056,0, 0.247, angle, 0,1, "twor") draw_component(0,0.118,0, 3,0.12,4, 0, angle, 0,0, "notexture") draw_component(0,0.15,0, 3,0.5,0.1, 0.24, angle, 0,0, "notexture") draw_component(0,0.15,0, 4,0.5,0.1, 0.173, 90+angle, 0,0, "notexture") draw_component(0,0.15,0, 3,0.5,0.1, 0.24, 180+angle, 0,0, "notexture") draw_component(0,0.15,0, 4,0.5,0.1, 0.173, 270+angle, 0,0, "notexture") if tray["tray2_status"] == "nonempty" then draw_label(0,0.15,0, 0.247, angle, 0,1, "one") else draw_label(0,0.15,0, 0.247, angle, 0,1, "oner") WAttrib("fg=black") draw_component(0,0.108,0, 3,0.05,4, 0,angle, 0,0, "notexture") WAttrib("fg=white") draw_component(0,0.265,0, 3,1,4, 0,angle, 0,0, "notexture") draw_component(0,0.235,0, 4,1.5,0.4, 0.206, 270+angle, 0,0, "notexture") WAttrib("fg=white") draw_component(0,0.05,0, 2.5,0.1,2, 0.28, 270+angle, 1,0, "notexture") WAttrib("texmode=on") end method draw_label(tx,ty,tz, r,a1, s,lac, texname) local x_trans,z_trans x_trans := r * sin(dtor(a1)) z_trans := r * cos(dtor(a1)) PushMatrix() Translate(x,y,z) Translate(tx+x_trans, ty, tz+z_trans) Rotate(a1,0,1,0) write("entered") WAttrib("texmode=on") WAttrib("texcoord=0,0,0,1,1,1,1,0") | write("texcoord failed") WAttrib("texture=dat/textures/" || \texname || ".gif") | write("texture=name2.gif failed") FillPolygon(-0.1,-0.025,0, -0.1,0.025,0, 0,0.025,0, 0,-0.025,0) WAttrib("texmode=off") PopMatrix() end method draw_component(tx,ty,tz, sx,sy,sz, r,a1, s,lac, texname) local x_trans,z_trans x_trans := r * sin(dtor(a1)) z_trans := r * cos(dtor(a1)) PushMatrix() Translate(x,y,z) Translate(tx+x_trans, ty, tz+z_trans) if s = 1 then { Rotate(a1-270,0,1,0) Rotate(170,0,0,1) } else { Rotate(a1,0,1,0) } Scale(sx,sy,sz) if lac = 0 then { DrawCube(0,0,0,0.12) } PopMatrix() end method disallows(x,z) ## Box #calc_boundbox_chair() if minx-collide <= x <= maxx+collide & minz-collide <= z <= maxz+collide then { return } fail end initially(coords,col,A) x := coords[1] y := coords[2] z := coords[3] color := col angle := A # default values /x := 0 /y := 0 /z := 0 /col := "white" /A := 0 /name := "NMSU" /status := "on" /tray := table() tray["tray1_status"] := "nonempty" tray["tray2_status"] := "nonempty" /job := table() /minx := x - 0.9 /miny := y /minz := z - 0.9 /maxx := x + 0.9 /maxy := y /maxz := z + 0.9 /collide := 0.1 end class Ramp: Obstacle ( ramptype, coords, color_ramp, render_set, minx, maxx, minz, maxz, miny, maxy, x, y, z, width, height, length, type ) method render(render_level) if type=1 then { WAttrib("dim=3") WAttrib("texmode=on") WAttrib("texture=dat/textures/blue_tile.gif") | write("texture=blue_tile.gif failed") Fg(color_ramp) DrawPolygon(x-length,y,z, x-length,y+height,z+width, x,y+height,z+width, x,y,z) FillPolygon(x-length,y,z,x-length,y+height,z+width, x,y+height,z+width,x,y,z) DrawPolygon(x-length,y+height,z+width,x,y+height,z+width, x,y,z+width,x-length,y,z+width) FillPolygon(x-length,y+height,z+width,x,y+height,z+width, x,y,z+width,x-length,y,z+width) DrawPolygon(x-length,y+height,z+width,x-length,y,z+width, x-length,y,z,x-length,y,z) FillPolygon(x-length,y+height,z+width,x-length,y,z+width, x-length,y,z,x-length,y,z) DrawPolygon(x,y+height,z+width,x,y,z+width,x,y,z,x,y,z) FillPolygon(x,y+height,z+width,x,y,z+width,x,y,z,x,y,z) } else if type=2 then { WAttrib("dim=3") WAttrib("texmode=on") WAttrib("texture=dat/textures/blue_tile.gif") | write("texture=blue_tile.gif failed") Fg(color_ramp) # main ramp walking area FillPolygon(x,y,z-length, x+width,y+height,z-length, x+width,y+height,z ,x,y,z) # flat square, back of ramp if height > 0 then xback := x + width else xback := x FillPolygon(xback,y+height,z-length, xback,y+height,z, xback,y,z, xback,y,z-length) if height > 0 then { FillPolygon(x,y,z, x+width,y+height,z, x+width,y,z) FillPolygon(x,y,z-length, x+width,y+height,z-length, x+width,y,z-length, x,y,z-length) } else { FillPolygon(x,y,z, x+width,y+height,z, x,y+height,z) FillPolygon(x,y,z-length, x+width,y+height,z-length, x,y+height,z-length) } } else if type=3 then { WAttrib("dim=3") WAttrib("texmode=on") WAttrib("texture=dat/textures/floor.gif") | write("texture=floor.gif failed") Fg(color_ramp) #top DrawPolygon(x,y+height,z-width, x+length,y+height,z-width, x+length,y+height,z, x,y+height,z) FillPolygon(x,y+height,z-width, x+length,y+height,z-width, x+length,y+height,z ,x,y+height,z) WAttrib("texture=dat/textures/wood9.gif") | write("texture=wood9.gif failed") #back DrawPolygon(x+length,y+height,z-width, x+length,y+height,z, x+length,y,z, x+length,y,z-width) FillPolygon(x+length,y+height,z-width, x+length,y+height,z, x+length,y,z, x+length,y,z-width) #front DrawPolygon(x,y+height,z-width, x,y+height,z, x,y,z, x,y,z-width) FillPolygon(x,y+height,z-width, x,y+height,z, x,y,z, x,y,z-width) #left DrawPolygon(x,y,z-width, x,y+height,z-width, x+length,y+height,z-width, x+length,y,z-width) FillPolygon(x,y,z-width, x,y+height,z-width, x+length,y+height,z-width, x+length,y,z-width) #right DrawPolygon(x,y,z, x,y+height,z, x+length,y+height,z, x+length,y,z) FillPolygon(x,y,z, x,y+height,z, x+length,y+height,z, x+length,y,z) } else if type=4 then { WAttrib("dim=3") WAttrib("texmode=on") WAttrib("texture=dat/textures/blue_tile.gif") | write("texture=blue_tile.gif failed") wstair:=width/5.0 hstair:=height/5.0 i:=0 j:=0 while (i<4 & j<3) do { FillPolygon(x,y+hstair,z, x,y+hstair,z-length, x+wstair,y+hstair,z-length, x+wstair,y+hstair,z) FillPolygon(x,y,z, x,y,z-length, x,y+hstair,z-length, x,y+hstair,z) x:=x+wstair y:=y+hstair i:=i+1 j:=j+1 } FillPolygon(x,y+hstair,z, x,y+hstair,z-length, x+wstair+0.8,y+hstair,z-length, x+wstair+0.8,y+hstair,z) FillPolygon(x,y,z, x,y,z-length, x,y+hstair,z-length, x,y+hstair,z) } return render_set end method disallows(x,y,z) if ((minx<=x<=maxx) & (minz<=z<=maxz) & (miny<=y<=maxy)) then { return [type, width, height] } fail end initially(coords,col,typ,w,h,l) /width:=w /height:=h /x:=coords[1] /y:=coords[2] /z:=coords[3] color_ramp:=col /type:=typ /length:=l if type=1 then { /minx:=x-length /maxx:=x+0.1 /minz:=z-0.7 /maxz:=z+width } if type = (2|4) then { /minx:=x-0.7 /maxx:=x+width /minz:=z-length /maxz:=z+0.1 } #TYPE 3 IS PLATFORM if type=3 then { /minx:=x-0.1 /maxx:=x+length /minz:=z-width-1 /maxz:=z+0.1 } /miny:=y /maxy:=y+height /render_set := set() end # # Virtual table class. # class Table:Obstacle( x, # 'x' position of the table centre y, # 'y' position of the table centre z, # 'z' posiion of the table centre color, # color of the table angle, # angle in which table should be drawn w.r.t. centre type, # it describes whether the table is of 'office' type or # 'lab' type w, # width h, # height l, # length minx,miny,minz,maxx,maxy,maxz, # used in restricting the avatar to collide, # move through the table. name, dle0, dle1_0, dle1_1, dle1_2, dle2, dle3, T1,T2,T3,R1,R2,R3) # useful in translating the draws of the table method render(render_level) local ang_rad,x_trans,z_trans,flag,incr if (\dle0) then { if render_level=0 then dle0.skip := 1 if render_level=1 then { dle0.skip := 0 (\ dle1_2).skip := 1 (\ dle3).skip := 1 if type=="lab" then { dle1_0.skip := 0 dle1_1.skip := 0 dle2.skip := 1 } if type=="office" then { dle1_0.skip := 1 dle1_1.skip := 1 dle2.skip := 0 } } if render_level=2 then { dle0.skip := 0 dle2.skip := 0 dle1_0.skip := 0 dle1_1.skip := 0 (\dle3).skip := 1 if type=="office" then { dle1_2.skip := 0 } } if render_level=3 then { dle0.skip := 0 dle2.skip := 0 dle1_0.skip := 0 dle1_1.skip := 0 if type=="office" then { dle1_2.skip := 0 dle3.skip := 0 } } } else full_detail_table() end method full_detail_table() local ang_rad,x_trans,z_trans,flag,incr,win3d win3d := !gui::dispatcher.subwins dle0 := WSection(win3d, "table0") WAttrib("texmode=off") PushMatrix() Translate(0,h,0) #Upper one PushMatrix() Translate(x,y,z) Rotate(angle,0,1,0) Scale(w*2,h,l) Rotate(-90,1,0,0) Scale(1,1,0.07) Fg("diffuse"||" " || color ) DrawCube(0,0,0,0.9) PopMatrix() ang_rad := dtor(90+angle) x_trans := 0.85 * l * sin(ang_rad) z_trans := 0.85 * w * cos(ang_rad) draw_big_leg(angle,x_trans,z_trans) dle1_0 := WSection(win3d, "table1_0") draw_lower_leg(angle,x_trans,z_trans) # dle1_0 WSection(win3d) ang_rad := dtor(-90+angle) x_trans := 0.85 * l * sin(ang_rad) z_trans := 0.85 * w * cos(ang_rad) draw_big_leg(angle,x_trans,z_trans) dle1_1 := WSection(win3d, "table1_1") draw_lower_leg(angle,x_trans,z_trans) # dle1_1 WSection(win3d) dle2 := WSection(win3d, "table2") # Back Table PushMatrix() Translate(x,y,z) Rotate(angle,0,1,0) Scale(w,1,l) FillPolygon(-0.86,0,-0.24, -0.86,-0.6,-0.24, 0.86, -0.6,-0.24,0.86,0,-0.24,-0.86,0,-0.24) PopMatrix() # dle2 WSection(win3d) if type == "office" then { dle1_2 := WSection(win3d, "table1_2") PushMatrix() T1 := Translate(x,y,z) R1 := Rotate(angle,0,1,0) Scale(w,h,l) #Bottom FillPolygon(-0.25,-0.6,-0.49, -0.25,-0.6,0.47, -0.8,-0.6,0.47, -0.8,-0.6,-0.49, -0.25,-0.6,-0.49) # Right Side FillPolygon(-0.25,0,-0.49, -0.25,0,+0.47, -0.25,-0.6,0.47, -0.25,-0.6,-0.49, -0.25,0,-0.49) #Left side FillPolygon(-0.8,0,-0.49, -0.8,0,0.47, -0.8,-0.6,0.47, -0.8,-0.6,-0.49, -0.8,0,-0.49) #Front Side FillPolygon(-0.8,-0.6,0.47, -0.8,0,0.47, -0.25, 0,0.47, -0.25,-0.6,0.47, -0.8,-0.6,0.47) #Bottom FillPolygon(0.25,-0.6,-0.49, 0.25,-0.6,0.47, 0.8,-0.6,0.47, 0.8,-0.6,-0.49, 0.25,-0.6,-0.49) #Left side FillPolygon(0.8,0,-0.49, 0.8,0,0.47, 0.8,-0.6,0.47, 0.8,-0.6,-0.49, 0.8,0,-0.49) # Right side FillPolygon(0.25,0,-0.49, 0.25,0,+0.47, 0.25,-0.6,0.47, 0.25,-0.6,-0.49, 0.25,0,-0.49) #Front Side FillPolygon(0.8,-0.6,0.47, 0.8,0,0.47, 0.25, 0,0.47, 0.25,-0.6,0.47, 0.8,-0.6,0.47) PopMatrix() # dle1_2 WSection(win3d) } if type == "office" then { dle3 := WSection(win3d, "table3") # LEFT PART OF TABLE PushMatrix() T1 := Translate(x,y,z) R1 := Rotate(angle,0,1,0) Scale(w,h,l) #Bottom FillPolygon(-0.25,-0.6,-0.49, -0.25,-0.6,0.47, -0.8,-0.6,0.47, -0.8,-0.6,-0.49, -0.25,-0.6,-0.49) # draw1 FillPolygon(-0.25,-0.2,-0.49, -0.25,-0.2,0.47, -0.8,-0.2,0.47, -0.8,-0.2,-0.49, -0.25,-0.2,-0.49) # draw2 FillPolygon(-0.25,-0.4,-0.49, -0.25,-0.4,0.47, -0.8,-0.4,0.47, -0.8,-0.4,-0.49, -0.25,-0.4,-0.49) # RIGHT PART OF TABLE #Bottom FillPolygon(0.25,-0.6,-0.49, 0.25,-0.6,0.47, 0.8,-0.6,0.47, 0.8,-0.6,-0.49, 0.25,-0.6,-0.49) # draw1 FillPolygon(0.25,-0.2,0.47, 0.25,0,0.47, 0.8,0,0.47, 0.8,-0.2,0.47, 0.25,-0.2,0.47) # draw2 FillPolygon(0.25,-0.4,-0.49, 0.25,-0.4,0.47, 0.8,-0.4,0.47, 0.8,-0.4,-0.49, 0.25,-0.4,-0.49) # LEFT PART OF TABLE # Right Side FillPolygon(-0.25,0,-0.49, -0.25,0,+0.47, -0.25,-0.6,0.47, -0.25,-0.6,-0.49, -0.25,0,-0.49) #Left side FillPolygon(-0.8,0,-0.49, -0.8,0,0.47, -0.8,-0.6,0.47, -0.8,-0.6,-0.49, -0.8,0,-0.49) #RIGHT PART OF TABLE #Left side FillPolygon(0.8,0,-0.49, 0.8,0,0.47, 0.8,-0.6,0.47, 0.8,-0.6,-0.49, 0.8,0,-0.49) # Right side FillPolygon(0.25,0,-0.49, 0.25,0,+0.47, 0.25,-0.6,0.47, 0.25,-0.6,-0.49, 0.25,0,-0.49) # LEFT PART OF TABLE # Bottom closing FillPolygon(-0.25,-0.6,0.47, -0.25,-0.4,0.47, -0.8,-0.4,0.47, -0.8,-0.6,0.47, -0.25,-0.6,0.47) # Draw1 closing FillPolygon(-0.25,-0.2,0.47, -0.25,0,0.47, -0.8,0,0.47, -0.8,-0.2,0.47, -0.25,-0.2,0.47) # Draw2 closing FillPolygon(-0.25,-0.4,0.47, -0.25,-0.2,0.47, -0.8,-0.2,0.47, -0.8,-0.4,0.47, -0.25,-0.4,0.47) # RIGHT PART OF TABLE # Bottom closing FillPolygon(0.25,-0.6,0.47, 0.25,-0.4,0.47, 0.8,-0.4,0.47, 0.8,-0.6,0.47, 0.25,-0.6,0.47) # Draw1 closing FillPolygon(0.25,-0.2,0.47, 0.25,0,0.47, 0.8,0,0.47, 0.8,-0.2,0.47, 0.25,-0.2,0.47) # Draw2 closing FillPolygon(0.25,-0.4,0.47, 0.25,-0.2,0.47, 0.8,-0.2,0.47, 0.8,-0.4,0.47, 0.25,-0.4,0.47) PopMatrix() Fg("diffuse gray blue") PushMatrix() T2:= Translate(x,y,z) R2 := Rotate(angle,0,1,0) Scale(w,h,l) DrawOpener(-0.525,-0.1) DrawOpener(-0.525,-0.3) DrawOpener(-0.525,-0.5) DrawOpener(0.525,-0.1) DrawOpener(0.525,-0.3) DrawOpener(0.525,-0.5) PopMatrix() WSection(win3d) } WAttrib("texmode=on") # } PopMatrix() # dle0 WSection(win3d) end # The draw opener draws knobs(Openers) of the desks method DrawOpener(p,q) DrawSphere(p,q,0.5,0.025) end method draw_big_leg(angle_rad,xtrans,ztrans) PushMatrix() if y ~= 0 then Translate(x+xtrans,y-0.24*y,z+ztrans) else Translate(x+xtrans,y-0.6,z+ztrans) Rotate(angle_rad,0,1,0) Scale(w,1,l) Scale(0.1,2.5,1) DrawCube(0,0,0,0.45) PopMatrix() end method draw_lower_leg(angle_rad,xtrans,ztrans) PushMatrix() Translate(x+xtrans,y-1,z+ztrans) Rotate(angle_rad,0,1,0) Scale(w,1,l) Scale(0.2,0.6,2) DrawCube(0,0,0,0.45) PopMatrix() end method disallows(x,z) ## Box #calc_boundbox_chair() if minx-collide <= x <= maxx+collide & minz-collide <= z <= maxz+collide then { return } fail end initially(opMode,coords,A,col,type_table) self.opMode := opMode x := coords[1] y := coords[2] z := coords[3] w := 2.0 h := 1.0 l := 1.0 color := col #direction := dir type := type_table angle := A /x := 0 /y := 0 /z := 0 /color := "gray" /minx := x - 0.5 /miny := y /minz := z - 0.5 /maxx := x + 0.5 /maxy := y /maxz := z + 0.5 /collide := 0.3 /type := "office" /angle := 0 /name := "Table" #write(color, "table created") end class TiledWall(maxx,minx,maxy,miny,maxz,minz,walls,coords,plane, xdelta,ydelta,zdelta) method render() local i every i := 1 to *walls do walls[i].render(, 1) end method printwall() local i every i := 1 to *walls do walls[i].printwall() end method calc_boundbox() local L,i maxx := minx := coords[1] maxy := miny := coords[2] maxz := minz := coords[3] L := coords every i := 4 to *L by 3 do { minx >:= L[i] maxx <:= L[i] miny >:= L[i+1] maxy <:= L[i+1] minz >:= L[i+2] maxz <:= L[i+2] } end method addwall(w) put(walls,w) end method setcoords(c[]) coords := c end method set_plane() ## Wall local c plane := &null if /coords | (*coords=0) then fail c := coords if *c < 12 then { write(&errout, "short wall needs 12 coordinates, had "|| *c) runerr(500, c) } xdelta := max( abs( c[4]-c[1] ), abs(c[7]-c[4]), abs(c[10]-c[7]), abs(c[10] - c[1] ) ) ydelta := max( abs( c[5]-c[2] ), abs(c[8]-c[5]), abs(c[11]-c[8]), abs(c[11] - c[2] ) ) zdelta := max( abs( c[6]-c[3] ), abs(c[9]-c[6]), abs(c[12]-c[9]), abs(c[12] - c[3] ) ) if -0.0001 < zdelta < 0.05 then plane := 3 else if -0.0001 < ydelta < 0.05 then plane := 2 else if -0.0001 < xdelta < 0.05 then plane := 1 else { write( "Wall does not have a plane! " ) printwall() } end # method set_plane() initially(c[]) coords := c walls := [] set_plane() end # # A class drawing decorative windowblinds # class Windowblinds( x, y, z, color_rod, color_blinds, angle, height, width) method render(render_level) local i,j,k, x_trans, z_trans,h j := 0 WAttrib("texmode=off") Fg(color_rod) PushMatrix() Translate(x,y,z) PushMatrix() Translate(0,height/2,0) Rotate(angle,0,1,0) Rotate(90,1,0,0) DrawCylinder(0,0,0,width,0.02,0.02) PopMatrix() Fg(color_blinds) if render_level = 3 then k := width / 0.2 else if render_level = 2 then k := width / 0.4 else if render_level = 1 then k := width / 0.6 else if render_level = 0 then k := width / 0.8 h := 2.0/0.06 every i := 1 to k do { x_trans := j * sin(dtor(angle)) z_trans := j * cos(dtor(angle)) PushMatrix() Translate(x_trans,0.5,z_trans) Rotate(angle,0,1,0) Rotate(75,0,1,0) Scale(1.65,h,0.05) DrawCube(0,0,0,0.06) PopMatrix() if render_level = 3 then j := j + 0.2 else if render_level = 2 then j := j + 0.4 else if render_level = 1 then j := j + 0.6 else if render_level = 0 then j := j + 0.8 } PushMatrix() Translate(0,0.25,0) DrawCylinder(0,0,0,0.5,0.015,0.015) PopMatrix() PopMatrix() WAttrib("texmode=on") end initially(coords,pos,crod,cblinds,ht,wth) #self.opMode := opMode x := coords[1] y := coords[2] z := coords[3] angle := pos color_rod := crod color_blinds := cblinds height := ht width := wth #default values /x := 0 /y := 0 /z := 0 /color_rod := "blue" /color_blinds := "green" /width := 2 /height := 2 end # parsing code global linenum procedure parsebox(s, f) local b, w #write("parsebox") b := Box() s ? { tab(many(' \t')) ="{" tab(many(' \t')) s := tab(0) } while not (s ? (tab(many(' \t')) & ="}" & *tab(0)=0)) do { s ? { tab(many(' \t')) if ="Wall" then { w := parsewall(tab(0), f) put(b.walls, w) } } s := readlin(f) } return b end procedure parselelems(L, s, f) local elem #write("parselelem ", image(s)) s ? { tab(many(' \t')) if ="Box" then { elem := parsebox(tab(0), f) put(L, elem) } else if ="Wall" then { elem := parsewall(tab(0), f) put(L, elem) } else if ="WhiteBoard" then { elem := parsewall(tab(0), f) elem := WhiteBoard ! (push(elem.coords, elem.texture,self.dispatcher,self, &null)) put(L, elem) } else if ="Windowblinds" then { elem := parsewindowblinds(tab(0), f) put(L, elem) } else if ="Chair" then { elem := parsechair(tab(0), f) put(L, elem) } else if ="Table" then { elem := parsetable(tab(0), f) put(L, elem) } else if ="Pen" then { #write("parsepen is calling") elem := parsepen(tab(0), f) put(L, elem) } else if ="Book" then { #write("parsebook is calling") elem := parsebook(tab(0), f) put(L, elem) } else if ="Computer" then { elem := parsecomputer(tab(0), f) #write("parsecomputer is calling") put(L, elem) } else if ="Printer" then { elem := parseprinter(tab(0), f) #write("parseprinter is calling") put(L, elem) } else if ="Ramp" then { elem := parseramp(tab(0), f) #write("parseramp is calling") put(L, elem) } else { while elem := trim(tab(find(","))) do { put(L, elem) ="," tab(many(' \t')) } elem := trim(tab(0)) if *elem>0 then put(L, elem) } } end procedure parselist(s,f) local L #write("parselist ", image(s)) L := [] while (*s=0) | (s[-1] ~== "]") do s ? { parselelems(L, s, f) s := readlin(f) } if s ~== "]" then parselelems(L, s[1:-1], f) return L end procedure parsewall(s,f) local w, field_s, t := table() s ? { repeat { tab(many(' \t')) if ="{" then break tab(many(' \t')) if &pos = *&subject + 1 then &subject := readlin(f) } tab(many(' \t')) s := tab(0) } s := trim(s,' \t') while (*s=0) | (s[-1] ~== "}") do s ? { field_s := trim(tab(find("}")|0), ' \t') if *field_s>0 then { parsefield(t, field_s, f) } if (*s=0) | (s[-1] ~== "}") then s := trim(readlin(f), ' \t') } s ?:= (tab(many(' \t')) & tab(0)) if s ~== "}" then parsefield(t, s[1:-1], f) w := Wall ! ([t["texture"]] ||| (\ (t["coords"]) | [])) return w end procedure parsewindowblinds(s,f) local w, field_s, t := table() s ? { tab(many(' \t')) ="{" tab(many(' \t')) s := tab(0) } while (*s=0) | (s[-1] ~== "}") do s ? { field_s := tab(find("}")|0) if *field_s>0 then { parsefield(t, field_s, f) } if (*s=0) | (s[-1] ~== "}") then s := readlin(f) } s ?:= (tab(many(' \t')) & tab(0)) if s ~== "}" then parsefield(t, s[1:-1], f) w := Windowblinds ( (\ (t["coords"]) | []), t["angle"], t["crod"], t["cblinds"],t["height"], t["width"]) return w end procedure parsechair(s,f) local w, field_s, t := table() s ? { tab(many(' \t')) ="{" tab(many(' \t')) s := tab(0) } while (*s=0) | (s[-1] ~== "}") do s ? { field_s := tab(find("}")|0) if *field_s>0 then { parsefield(t, field_s, f) } if (*s=0) | (s[-1] ~== "}") then s := readlin(f) } s ?:= (tab(many(' \t')) & tab(0)) if s ~== "}" then parsefield(t, s[1:-1], f) w := Chair ((\ (t["coords"]) | []), t["position"], t["color"], t["type"], t["movable"]) if (\ t["action"]) then w.action := t["action"] return w end procedure parsetable(s,f) local w, field_s, t := table() #write("parsetable entered") s ? { tab(many(' \t')) ="{" tab(many(' \t')) s := tab(0) } while (*s=0) | (s[-1] ~== "}") do s ? { field_s := tab(find("}")|0) if *field_s>0 then { parsefield(t, field_s, f) } if (*s=0) | (s[-1] ~== "}") then s := readlin(f) } s ?:= (tab(many(' \t')) & tab(0)) if s ~== "}" then parsefield(t, s[1:-1], f) w := Table ( &null, (\ (t["coords"]) | []), t["position"], t["color"],t["type"]) if (\ t["action"]) then w.action := t["action"] return w end procedure parsepen(s,f) local w, field_s, t := table() s ? { tab(many(' \t')) ="{" tab(many(' \t')) s := tab(0) } while (*s=0) | (s[-1] ~== "}") do s ? { field_s := tab(find("}")|0) if *field_s>0 then { parsefield(t, field_s, f) } if (*s=0) | (s[-1] ~== "}") then s := readlin(f) } s ?:= (tab(many(' \t')) & tab(0)) if s ~== "}" then parsefield(t, s[1:-1], f) w := Pen (&null, t["Id"], (\ (t["coords"]) | []) ,t["color"], t["Angle"]) return w end procedure parsebook(s,f) local w, field_s, t := table() s ? { tab(many(' \t')) ="{" tab(many(' \t')) s := tab(0) } while (*s=0) | (s[-1] ~== "}") do s ? { field_s := tab(find("}")|0) if *field_s>0 then { parsefield(t, field_s, f) } if (*s=0) | (s[-1] ~== "}") then s := readlin(f) } s ?:= (tab(many(' \t')) & tab(0)) if s ~== "}" then parsefield(t, s[1:-1], f) w := Book ( &null, (\ (t["coords"]) | []), t["color"], t["Angle"]) return w end procedure parseramp(s,f) local w, field_s, t := table() s ? { tab(many(' \t')) ="{" tab(many(' \t')) s := tab(0) } while (*s=0) | (s[-1] ~== "}") do s ? { field_s := tab(find("}")|0) if *field_s>0 then { parsefield(t, field_s, f) } if (*s=0) | (s[-1] ~== "}") then s := readlin(f) } s ?:= (tab(many(' \t')) & tab(0)) if s ~== "}" then parsefield(t, s[1:-1], f) w:= Ramp ( (\ (t["coords"]) | []), t["color"], t["type"], t["width"], t["height"], t["length"] ) return w end procedure parsecomputer(s,f) local w, field_s, t := table() s ? { tab(many(' \t')) ="{" tab(many(' \t')) s := tab(0) } while (*s=0) | (s[-1] ~== "}") do s ? { field_s := tab(find("}")|0) if *field_s>0 then { parsefield(t, field_s, f) } if (*s=0) | (s[-1] ~== "}") then s := readlin(f) } s ?:= (tab(many(' \t')) & tab(0)) if s ~== "}" then parsefield(t, s[1:-1], f) w := Computer ( (\ (t["coords_mntr"]) | []),(\ (t["coords_cpu"]) | []),(\ (t["coords_kb"]) | []), t["color"], t["angle"]) return w end procedure parseprinter(s,f) local w, field_s, t := table() s ? { tab(many(' \t')) ="{" tab(many(' \t')) s := tab(0) } while (*s=0) | (s[-1] ~== "}") do s ? { field_s := tab(find("}")|0) if *field_s>0 then { parsefield(t, field_s, f) } if (*s=0) | (s[-1] ~== "}") then s := readlin(f) } s ?:= (tab(many(' \t')) & tab(0)) if s ~== "}" then parsefield(t, s[1:-1], f) w := Printer ( (\ (t["coords"]) | []), t["color"], t["angle"]) return w end procedure parsefield(x,s,f) local field, val s ? { tab(many(' \t')) (field := tab(many(&letters++&digits))) | { write("fieldname expected at ", image(tab(0)), " in ", image(s)) stop("model error in line ", linenum) } tab(many(' \t')) val := parseval(tab(0),f) if field=="texture" then val := world.find_texture(val) if (field == "action") then { /(x["actors"]) := [] put(x["actors"], 1) } x [field] := val } end procedure parseval(s,f) local val s ? { tab(many(' \t')) if &pos = *&subject + 1 then &subject := readlin(f) tab(many(' \t')) if val := numeric(tab(many(&digits++"."))) then return val else if ="Wall" then { pw := parsewall(tab(0), f) return \pw } else if ="[" then { pl := parselist(tab(0), f) return \pl } else return trim(tab(0)) } end procedure parseplace(s,f) local t, line t := table() while line := readlin(f) do line ? { tab(many(' \t')) if ="}" then break if &pos = *&subject+1 then next parsefield(t, tab(0), f) } return t end procedure parseroom(s,f) local t, r repeat { tab(many(' \t')) if ="{" then break if &pos = *&subject+1 then &subject := readlin(f) else stop("parseroom chokes on ", tab(0)) } t := parseplace(s,f) r := Room(t["name"], t["x"], t["y"], t["z"], t["w"], t["h"], t["l"], t["texture"]) if \ (t["floor"]) then { t["floor"].coords := [t["x"],t["y"],t["z"], t["x"],t["y"],t["z"]+t["l"], t["x"]+t["w"],t["y"],t["z"]+t["l"], t["x"]+t["w"],t["y"],t["z"]] t["floor"].set_plane() r.floor := t["floor"] } if \ (t["ceiling"]) then { t["ceiling"].coords := [t["x"],t["y"]+t["h"],t["z"], t["x"],t["y"]+t["h"],t["z"]+t["l"], t["x"]+t["w"],t["y"]+t["h"],t["z"]+t["l"], t["x"]+t["w"],t["y"]+t["h"],t["z"]] t["ceiling"].set_plane() r.ceiling := t["ceiling"] } every r.add_obstacle(!\ (t["obstacles"])) every r.add_decoration(!\ (t["decorations"])) return r end procedure readlin(f) local line if line := read(f) then { linenum +:= 1 if linenum % 100 = 0 then write("[",linenum,"]") line[find("#", line):0] := "" return line } end procedure parsedoor(s,f) local t, d, r repeat { tab(many(' \t')) if ="{" then break if &pos = *&subject+1 then &subject := readlin(f) else stop("parseroom chokes on ", tab(0)) } t := parseplace(s,f) d := Door(t["x"], t["y"], t["z"], t["collide_in"], t["texure"], t["h"], t["w"]) d.plane := \ (t["plane"]) every r := !t["rooms"] do { (\ (world.RoomsTable[r])).add_opening(d) | write("warning: could not add door to room ", image(r)) } return d end procedure parseopening(s,f) local t, d, r t := parseplace(s,f) d := Opening(t["x"], t["y"], t["z"], t["collide_in"], t["w"]) d.height := \ (t["height"]) d.plane := \ (t["plane"]) every r := !t["rooms"] do { (\ (world.RoomsTable[r])).add_opening(d) | write("warning: could not add opening to room ", image(r)) } return d end