import java.util.Vector; import java.awt.Dialog; import java.awt.Button; import java.awt.Event; import java.awt.List; import java.awt.Frame; import java.awt.BorderLayout; import vrml.*; import vrml.node.*; import vrml.field.*; // MainScript // // public class MainScript extends Script { // eventOut private SFVec3f arrow_position_changed; private SFRotation arrow_orientation_changed; private SFRotation last_orientation; private SFVec3f last_position; private String currentRoom; private String destRoom; private Node building; private Browser browser; private float targetCoords[]; private Vector rooms; private Vector doors; public void initialize() { try { arrow_position_changed = (SFVec3f)getEventOut( "arrow_position_changed" ); arrow_orientation_changed = (SFRotation)getEventOut( "arrow_orientation_changed" ); last_position = new SFVec3f(); last_orientation = new SFRotation(); building = (Node)((SFNode)getField( "buildingnode" )).getValue(); browser = this.getBrowser(); targetCoords = new float[3]; // need to initialize it with the starting door position rooms = new Vector(); doors = new Vector(); currentRoom = ""; // The destination room is 'Canny's Office' and is hardcoded. Refer to README for details destRoom = "Canny's Office"; buildRoomGraph( building ); // Debug code System.out.println( "\nFound #" + rooms.size() + " rooms:" ); for( int i=0; i < rooms.size(); i++ ) System.out.println( rooms.elementAt(i)); System.out.println( "\nFound #" + doors.size() + " doors:" ); for( int i=0; i < doors.size(); i++ ) System.out.println( doors.elementAt(i)); } catch( Exception e ) { e.printStackTrace(); } } // Build a graph of all the rooms and doors in the building protected void buildRoomGraph( Node bnode ) { rooms.removeAllElements(); doors.removeAllElements(); findRooms( bnode ); for( int i=0; i<doors.size(); i++ ) for( int j=0; j<((Door)doors.elementAt(i)).roomnames.length; j++ ) { Room t = getRoom( (String)((Door)doors.elementAt(i)).roomnames[j] ); if( t == null ) { System.err.println( "Can't find room matching: " + ((Door)doors.elementAt(i)).roomnames[j] + "; the door is " + doors.elementAt(i) ); } else { t.doors.addElement( doors.elementAt(i) ); ((Door)doors.elementAt(i)).rooms[j] = t; } } } private boolean internalFindPath( Room from, Room to, Vector path ) { if( from == null ) { System.out.println( "ifp called with null from" ); } if( to == null ) { System.out.println( "ifp called with null to" ); } if( from.touched ) return false; from.touched = true; if( from == to ) return true; for(int i=0; i<from.doors.size(); i++ ) { Room next; if( from == ((Door)from.doors.elementAt(i)).rooms[0] ) next = ((Door)from.doors.elementAt(i)).rooms[1]; else next = ((Door)from.doors.elementAt(i)).rooms[0]; if( internalFindPath( next, to, path )) { path.addElement( from.doors.elementAt(i)); return true; } } return false; } // When the user enters a new room, the door and the corresponding target // coordinates change. This function finds the new target coordinates // given the new and old room as arguments public float[] getNextCoord( String fromroom, String toroom ) { Vector vec = findPath( fromroom, toroom ); if( vec.size() >= 1 ) return ((Door)vec.elementAt( vec.size()-1 )).center; else return getRoom( toroom ).center; } // Determine the path between two rooms public Vector findPath( String fromroom, String toroom ) { for( int i=0; i<rooms.size(); i++ ) ((Room)rooms.elementAt(i)).touched = false; Room froom = getRoom( fromroom ); if( froom == null ) System.out.println( "could not find " + fromroom ); Room troom = getRoom( toroom ); if( troom == null ) System.out.println( "could not find " + toroom ); Vector ret = new Vector(); internalFindPath( froom, troom, ret ); return ret; } protected Room getRoom( String name ) { for( int i=0; i<rooms.size(); i++ ) if( ((Room)rooms.elementAt(i)).name.equals( name )) return (Room)rooms.elementAt(i); return null; } protected void findRooms( Node bnode ) { if( bnode.getType().equals( "Room" )) { Room aroom = new Room(); aroom.name = ((SFString)bnode.getExposedField( "name" )).getValue(); ((SFVec3f)bnode.getExposedField( "center" )).getValue(aroom.center); ((SFVec3f)bnode.getExposedField( "size" )).getValue(aroom.size); rooms.addElement( aroom ); } else if( bnode.getType().equals( "Door" )) { Door adoor = new Door(); ((SFVec3f)bnode.getExposedField( "center" )).getValue(adoor.center); ((MFString)bnode.getExposedField( "rooms")).getValue(adoor.roomnames); doors.addElement( adoor ); } else if(( bnode.getType().equals( "Transform" )) || ( bnode.getType().equals( "Group" ))) { MFNode children = (MFNode)bnode.getExposedField( "children" ); int size = children.getSize(); if( size > 0 ) { BaseNode[] nodes = new BaseNode[ size ]; children.getValue( nodes ); for( int i=0; i < nodes.length; i++ ) { if( nodes[i] instanceof Node ) { findRooms( (Node)nodes[i]); } } } } } public void processEvent( vrml.Event e ) { if( e.getName().equals( "set_viewer_position" )) { set_viewer_position((ConstSFVec3f)e.getValue()); } else if( e.getName().equals( "set_viewer_orientation" )) { set_viewer_orientation((ConstSFRotation)e.getValue()); } else if( e.getName().equals( "activeRoom" )) { IsNewRoom((ConstSFString)e.getValue()); } } // set the viewer(arrow) position using the value from the Proximity sensor public void set_viewer_position( ConstSFVec3f pos ) { last_position.setValue( pos ); set_arrow(); } // set the viewer orientation using the proximity sensor public void set_viewer_orientation( ConstSFRotation rot ) { last_orientation.setValue( rot ); set_arrow(); } // updates the position_changed and orientation changed eventOuts. // The arrow is rotated so that it always points to the target coordinates public void set_arrow() { float[] pos = new float[3]; float[] rot = new float[4]; last_position.getValue( pos ); last_orientation.getValue( rot ); rot[0] = 0; rot[1] = 1; rot[2] = 0; rot[3] = (float)Math.atan((targetCoords[0] - pos[0])/(targetCoords[2] - pos[2])); if( targetCoords[2] - pos[2] < 0) rot[3] = (float)(Math.PI) + rot[3]; arrow_position_changed.setValue( pos ); arrow_orientation_changed.setValue( rot ); } // Tells whether or not the viewer has entered a new room public void IsNewRoom(ConstSFString room) { try { System.out.println( "Entered: " + room.getValue() ); currentRoom = room.getValue(); targetCoords = getNextCoord(currentRoom, destRoom ); System.out.println( "go to: (" + targetCoords[0] + "," + targetCoords[1] + "," + targetCoords[2] + ")" ); } catch( Exception e ) { e.printStackTrace(); } } } // Simple Room class class Room { public float center[]; public float size[]; public String name; public boolean touched; public Vector doors; public Room() { center = new float[3]; size = new float[3]; doors = new Vector(); } public String toString() { return "Room{ name=" + name + ";center=" + center + "; size=" + size + "}"; } } // And the Door class class Door { public float center[]; public String roomnames[]; public Room rooms[]; public Door() { center = new float[3]; roomnames = new String[2]; rooms = new Room[2]; } public String toString() { return "Door{ center=" + center + "; roomnames[0]=" + roomnames[0] + "; roomnames[1]=" + roomnames[1] + "}"; } }