View Javadoc

1   package cz.cuni.amis.pogamut.ut2004.agent.module.sensomotoric;
2   
3   import java.util.UUID;
4   import java.util.concurrent.Future;
5   import java.util.logging.Logger;
6   
7   import javax.vecmath.Vector3d;
8   
9   import cz.cuni.amis.pogamut.base.agent.module.SensomotoricModule;
10  import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldObjectUpdateResult;
11  import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldObjectUpdateResult.Result;
12  import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldObjectUpdateResult.WorldObjectUpdateResult;
13  import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldObjectUpdatedEvent;
14  import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObject;
15  import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEventListener;
16  import cz.cuni.amis.pogamut.base.communication.worldview.object.WorldObjectId;
17  import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectUpdatedEvent;
18  import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
19  import cz.cuni.amis.pogamut.unreal.communication.messages.UnrealId;
20  import cz.cuni.amis.pogamut.ut2004.agent.navigation.navmesh.LevelGeometry;
21  import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
22  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.AutoTraceRay;
23  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.AutoTraceRayMessage;
24  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Self;
25  import java.util.HashMap;
26  import java.util.Map;
27  import java.util.Map.Entry;
28  
29  public class RaycastingBSP extends SensomotoricModule<UT2004Bot> {
30  	
31      Map<String, BSPRayInfoContainer> rayInfoContainers = new HashMap<String, BSPRayInfoContainer>();
32      int counter = 0;
33      private String idSuffix;
34      LevelGeometry levelGeometry = null;
35  
36      private IWorldObjectEventListener<Self, WorldObjectUpdatedEvent<Self>> selfListener = new IWorldObjectEventListener<Self, WorldObjectUpdatedEvent<Self>>() {
37  
38              @Override
39              public void notify(WorldObjectUpdatedEvent<Self> event) {
40                      selfUpdate(event.getObject());
41              }
42  
43      };
44  
45      /**
46       * Alternative contructor
47       * @param bot 
48       */
49      public RaycastingBSP(UT2004Bot bot) {
50          this(bot, null);
51      }
52      
53      /**
54       * Object's contructor
55       * @param bot
56       * @param log 
57       */
58      public RaycastingBSP(UT2004Bot bot, Logger log) {
59          super(bot, log);
60          
61          idSuffix = "_" + bot.getName() + UUID.randomUUID().toString();
62          
63          // listener for updating rays
64          bot.getWorldView().addObjectListener(Self.class, WorldObjectUpdatedEvent.class, selfListener);
65          
66          //try to get level geometry from bot's navmesh. if the geometry is null, this raycasting will be unusable
67          if(bot.getNavMesh() != null) {
68              levelGeometry = bot.getNavMesh().getLevelGeometry();
69          }   
70      }
71      
72      /**
73       * Whether we have BSP data for raycasting.
74       * @return
75       */
76      public boolean isUsable() {
77      	return levelGeometry != null;
78      }
79  
80      /**
81       * Deletes all previous rays and makes this instance ready for setting up
82       * new rays.
83       */
84      public void clear() {
85          for(BSPRayInfoContainer rayInfo : rayInfoContainers.values()) {
86              if(rayInfo==null) continue;
87              UnrealId unrealId = rayInfo.unrealId;
88              if(unrealId==null) continue;
89              final AutoTraceRay ray = agent.getWorldView().get(unrealId, AutoTraceRay.class);
90              // LET'S DESTROY THE RAY INSIDE WORLDVIEW - IT WON'T BE ACCESSIBLE AGAIN!
91              agent.getWorldView().notifyImmediately( 				
92                      new IWorldObjectUpdatedEvent() {
93                                      @Override
94                                      public WorldObjectId getId() {
95                                              return ray.getId();
96                                      }
97                                      @Override
98                                      public IWorldObjectUpdateResult<IWorldObject> update(IWorldObject obj) {
99                                              return new WorldObjectUpdateResult<IWorldObject>(Result.DESTROYED, obj);
100                                     }
101                                     @Override
102                                     public long getSimTime() {
103                                             return ray.getSimTime();
104                                     }
105                     }
106             );                    
107         }        
108         rayInfoContainers.clear();
109     }
110 
111     public Future<AutoTraceRay> createRay(Vector3d direction, int length, boolean floorCorrection) {
112             String id = counter++ + idSuffix;
113             return createRay(id, direction, length, floorCorrection);
114     }
115 
116     /**
117      * This method creates a ray and puts it into worldview
118      * @param id
119      * @param direction
120      * @param length
121      * @param floorCorrection
122      * @return 
123      */
124     public Future<AutoTraceRay> createRay(String id, Vector3d direction, int length, boolean floorCorrection) {
125             
126             UnrealId unrealId = UnrealId.get(id);
127             BSPRayInfoContainer rayInfo = new BSPRayInfoContainer(unrealId, direction, length, floorCorrection);
128             rayInfoContainers.put(id, rayInfo);
129             // that's all for now. the ray will be put in worldview in selfUpdate()
130             selfUpdate(agent.getSelf());           
131             return null;
132     }
133 
134     /**
135      * gets all the rays from the hashmap, recomputes them and sends them to world view
136      * @param self 
137      */
138     protected void selfUpdate(Self self) {
139         // RECOMPUTE AutoTraceRay(s)      
140         for(BSPRayInfoContainer rayInfo : rayInfoContainers.values()) {
141             AutoTraceRay ray = levelGeometry.getAutoTraceRayMessage(self, rayInfo);
142             agent.getWorldView().notifyImmediately(ray);
143         }
144     }
145 
146     /**
147      * Returns a ray of specified id. If the ray of the specified id does not exist
148      * or was not initialized yet then it returns null.
149      * <p><p>
150      * Note that the {@link AutoTraceRay} instance is self updating - once obtained you may use it every
151      * logic cycle to obtain current readings from the ray.
152      * 
153      * @param rayID
154      * @return
155      */    
156     AutoTraceRay getRay(String rayID) {
157         BSPRayInfoContainer rayInfo = rayInfoContainers.get(rayID);
158         if(rayInfo==null) return null;
159         UnrealId unrealId = rayInfo.unrealId;
160         if(unrealId==null) return null;
161         AutoTraceRay ray = agent.getWorldView().get(unrealId, AutoTraceRay.class);
162         return ray;
163     }
164 
165 }