# # cve.icn - classes to support collaborative virtual environments # # $include "keysyms.icn" # $include "C:\Program Files\Unicon\ipl\gincl\keysyms.icn" link printf # link graphics # -------------------------------- # # 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, 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) ## Opening put(rooms, r) end method other(room) ## Opening every r := !rooms do if r ~=== room then return r write("other room failed") end method allows(px,pz) ## Opening return end method render(World) ## Opening return end method print_opening() ## Opening 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,y,z) # ,width,height,thickness) ## Opening # be sure x,y,z,w,h,t are floats # / x := 0.0 # / y := 0.0 # / z := 0.0 / width := 1.0 # default = 1 meter / height := 2.0 # default = 2 meters # / thickness := 0.03 # something over an inch thick rooms := [] # openness := 0.00 # direction := -1.00 # delt := 0.03 plane := &null # set to 1 for xplane 3 for zplane # open_angle := &null end # class Opening # # class Door represents a closable connection between rooms # this will be sub-class of class Opening which has no door # class Door:Opening( x, y, z, thickness, rotator, openness, hinge_left, direction, delt, open_angle ) # (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 every r := !rooms do if r ~=== room then return r write("other room failed") end # **************** needs work here method allows(px,pz) ## Door # write ( " enter door allows " ) if openness < 0.67 then fail # write("door allows checking ", # left(px,4), ",", left(pz,4), " openness ", image(openness)) # write("x ", x,"-",x+width, " z ", z,"-",z+thickness) if x+0.3 <= px <= x+width-0.3 & z-1.2 <= pz <= z+thickness+1.2 then { # write("door allows says OK") return } # write ( "exit door allows " ) 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 = 1 then # xplane { return min ( dist1( px , py, pz ), dist1( px + width, py, pz ) ) } else # plane = 3 zplane { return min ( dist1( px , py, pz ), dist1( px , py, pz + width ) ) } end # method distance method swing_door(camera) ## Door # cam := camera # if 0.00 < openness < 1.00 then # { openness +:= direction * delt rotator.angle := open_angle * openness Refresh() # } end # method swing_door() method render(world) ## Door if \is_rendered then return is_rendered := 1 if ( (type(self))[1+:4] ~== "Door" ) then return set_open_angle() 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 " ) } } WAttrib("texmode=on") end 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() 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) } else # normal door = hinge right { PushMatrix() Translate( -width/2.0, -height/2.0, -thickness/2.0) Scale(width,height,thickness) Translate( 0.0 , height/2.0 , thickness/2.0 ) DrawCube(0,0,0,1) PopMatrix() 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) } PopMatrix() end # 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() 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) } else { 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() 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) } PopMatrix() end # render_x() method print_door() ## Door 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() 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() # ( thickness, rotator, openness, hinge_left, direction, # delt, open_angle ) initially(x1, y1, z1) # ,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 := 1.0 # default = 1 meter # / height := 2.0 # default = 2 meters / thickness := 0.03 # something over an inch thick openness := 0.00 direction := -1.00 delt := 0.03 hinge_left := &null # plane := &null # set to 1 for xplane 3 for zplane open_angle := 0.00 end # class Door # # class Wall is a textured polygon # class Wall(texture, coords) method render( world ) ## Wall if world.current_texture ~=== texture then { WAttrib("texture="||texture, "texcoord=0,0,0,1,1,1,1,0") world.current_texture := texture } (FillPolygon ! coords) | write("FillPolygon fails") end method settexture(newtext) ## Wall # write( " resetting texture to ",newtext) texture := newtext # render( world ) end method printwall() ## Wall 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 initially(t, c[]) ## Wall texture := t coords := c end # class Wall # Coordinate system: # y=0 is ground level # -5 < x < 5; -6 < z < 0; 2' per unit class Box( walls, minx, maxx, minz, maxz, dtexture, lod01 ) method mkwall(x[]) ## Box if type(x[1]) == "string" then t := pop(x) else t := dtexture W := Wall ! push(x, t) put(walls, W) end method render(world) ## Box every (!walls).render(world) end method disallows(x,z) ## Box if /minx then calc_boundbox() if minx-lod01 <= x <= maxx+lod01 & minz-lod01 <= z <= maxz+lod01 then { return } end method calc_boundbox() ## Box maxx := minx := walls[1].coords[1] 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] minz >:= L[i+2] maxz <:= L[i+2] } } end initially(worl) ## Box walls := [] dtexture := worl.find_texture("walltest.gif") # default texture for this room lod01 := worl.lod01 # 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 ) # a room disallows a move if: (a) outside or (b) something in the way method disallows(x,z) ## Room local msg # 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+lod01 <= x <= maxx-lod01 & minz+lod01 <= z <= maxz-lod01 then { every o := !obstacles do if o.disallows(x,z) then return fail } every e := !exits do { if e.allows(x,z) then { if minx <= x <= maxx & minz <= z <= maxz then { # allow but don't change room yet } else { # change rooms and notify other users if \(world.net) then { msg := "\\say leaves " || world.curr_room.name || " and enters " || e.other(self).name || " " # write( " debug move msg:" || msg ) write( world.net, msg ) } world.curr_room := e.other(self) } fail } } return end # method disallows ## Room method render(world) ## Room WAttrib("texmode=on") # write(" PRINTING OPENINGS ") # every (!exits).print_opening() every (!exits).render(world) # write(" floor.printwall() : " ) floor.printwall() floor.render(world) ceiling.render(world) every (!walls).render(world) every (!obstacles).render(world) every (!decorations).render(world) end method add_opening(d) ## Room # 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 # write(" room add_opening type(d) ", type(d) ) every w := !walls do # can walls be modified inside the loop????? { c := w.coords if \debug then w.printwall() if c[1]=c[4]=c[7]=c[10] then { if ( abs(d.x - c[1]) < 0.08 & c[12] <= d.z <= c[3] & c[12] <= d.z + d.width <= c[3] & abs ( c[2] - d.y ) < 0.08 & d.height <= abs( c[5] - c[2] ) # & #( c[3]=c[6]=c[9]=c[12] ) ) then { # opening is in 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 } put(walls, w, w2, w3) d.plane := 1 put(exits, d) d.add_room(self) # write( "room add_opening 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 } } else { if c[3]=c[6]=c[9]=c[12] then { if ( abs(d.z - c[3]) < 0.08 & c[1] <= d.x <= c[10] & c[1] <= d.x + d.width <= c[10] & abs ( c[2] - d.y ) < 0.08 & d.height <= ( c[5] - c[2] ) # & #( c[3]=c[6]=c[9]=c[12] ) ) then { # door is in a zplane 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] >:= d.x w3.coords[i] <:= d.x + d.width } 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 } } else { write("wall not in x or z plane; giving up"); w.printwall() fail } } } write(" no wall found for this opening ", image(d) ) if \debug then d.print_door() end # method add_opening ## Room method select_nearest_door(px,py,pz) ## Room idx := 1 minval := exits[1].distance(px, py, pz) every i := 2 to *exits do { if ( (type(exits[i]))[1+:4] ~== "Door" ) then next tmp := exits[i].distance(px,py,pz) if tmp < minval then { idx := i minval := tmp } } nearest_door := exits[idx] # return 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 initially(nam,x,y,z,w,h,l,tex,worl) ## Room self$Box.initially(worl) world := worl dtexture := world.find_texture(tex) nearest_door := &null name := nam floor := Wall(world.find_texture("floor.gif"),x,y,z, x,y,z-l, x+w,y,z-l, x+w,y,z) ceiling:= Wall(world.find_texture("walltest.gif"),x,y+h,z, x,y+h,z-l, x+w,y+h,z-l, x+w,y+h,z) # SH 118b 50.60* 0.00 15.00* 61.50 0.00 23.90 # x,y,z,w,h,l # SH118b := Room("SH 118b", 50.60, 0.00, 15.00, 11.90, 2.75, 8.90) mkwall(x, y, z-l, x , y+h, z-l, x+w, y+h, z-l, x+w, y, z-l) # back wall (3'?) mkwall(x+w, y, z , x+w, y+h, z , x+w, y+h, z-l, x+w, y, z-l) # right wall mkwall(x, y, z , x , y+h, z , x , y+h, z-l, x , y, z-l) # left wall mkwall(x, y, z , x , y+h, z , x+w, y+h, z , x+w, y, z ) # front wall exits := [] obstacles := [] decorations := [] lod01 := world.lod01 debug := &null end # class Room # =============================================================================== # ====== end of active code - anything below is for reference ================= # ====== end of file ==========================================================