ScummVM API documentation
line_of_sight.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * Additional copyright for this file:
8  * Copyright (C) 1999-2000 Revolution Software Ltd.
9  * This code is based on source code created by Revolution Software,
10  * used with permission.
11  *
12  * This program is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation, either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24  *
25  */
26 
27 #ifndef ICB_LINEOFSIGHT_H_INCLUDED
28 #define ICB_LINEOFSIGHT_H_INCLUDED
29 
30 #include "engines/icb/p4.h"
31 #include "engines/icb/debug.h"
32 #include "engines/icb/event_list.h"
33 #include "engines/icb/event_manager.h"
34 #include "engines/icb/common/px_linkeddatafile.h"
35 #include "engines/icb/common/px_route_barriers.h"
36 #include "engines/icb/common/px_string.h"
37 #include "engines/icb/common/px_3drealpoint.h"
38 
39 namespace ICB {
40 
41 #define LOS_LOG "LOS_log.txt"
42 
43 // This sets the default field-of-view for mega characters.
44 #define LOS_DEFAULT_MEGA_FIELD_OF_VIEW 180
45 
46 // This sets the default view height for mega characters (+/- this linear distance in cm).
47 // BIG NOTE: This value must be LESS than the difference between the crouched height and the normal eye-height,
48 // otherwise LOS will always return false when one mega is crouched and another is standing.
49 #define LOS_DEFAULT_OBJECT_HEIGHT_OF_VIEW (100 * REAL_ONE)
50 
51 // This sets how far an object can see by default.
52 #define LOS_DEFAULT_OBJECT_SEEING_DISTANCE 2000
53 
54 // This defines the default number of subscribers to process per cycle of the LOS logic.
55 #define LOS_DEFAULT_SUBSCRIBERS_PER_CYCLE 3
56 
57 // This is the size of the 2D and 1D tables.
58 #define LOS_1D_SIZE (MAX_session_objects)
59 #define LOS_2D_ROWSIZE_PACKED (MAX_session_objects / 8)
60 #define LOS_2D_SIZE_PACKED (MAX_session_objects * LOS_2D_ROWSIZE_PACKED)
61 
62 // Module to calculate which objects (voxel characters and other objects) can see which other objects. The information
63 // is used to generate events, which are given to the event manager, so it can decide what needs to hear about the change.
65 public:
66  // Definitions used by this class.
67  enum { ACTOR_EYE_HEIGHT = 160 };
68  enum { ACTOR_CROUCHED_HEIGHT = 61 };
69  enum ActorEyeMode { USE_OBJECT_VALUE = 0, FORCE_EYE_HEIGHT, FORCE_CROUCHED_HEIGHT };
70 
71  // Default constructor and destructor.
72  inline _line_of_sight();
73  inline ~_line_of_sight();
74 
75  // This attaches this object to its data files and sets other start-up values.
76  void Initialise();
77 
78  // These add and remove objects from the service.
79  void Subscribe(uint32 nObserverID, uint32 nTargetID);
80  void UnSubscribe(uint32 nObserverID, uint32 nTargetID);
81 
82  // These allow an object to be temporarily suspended in the LOS engine, but the objects they
83  // are registered to see are remembered for when the suspension is removed.
84  void Suspend(uint32 nObserverID);
85  inline void Unsuspend(uint32 nObserverID);
86 
87  // These two turn off the whole of line-of-sight processing for everybody. All the registrations are kept
88  // though, so it can resume where it left off.
89  void SwitchOff();
90  void SwitchOn() { m_bSwitchedOn = TRUE8; }
91 
92  // The engine actually calls this function instead of Cycle() directly, so that the amount of time
93  // spent in line-of-sight calculation can be controlled.
94  void DutyCycle();
95 
96  // This function allows the how many subscribers to do per cycle
97  inline void SetDutyCycle(uint32 nSubsPerCycle) { m_nSubsPerCycle = nSubsPerCycle; }
98 
99  // This allows the field-of-view to be changed from the default 180 for a mega character.
100  void SetFieldOfView(uint32 nID, uint32 nFieldOfView);
101 
102  // This allows the range an object sees to be changed from the default.
103  void SetSightRange(uint32 nID, uint32 nRange);
104 
105  // This allows the height range an object sees to be changed from the default.
106  void SetSightHeight(uint32 nID, uint32 nHeight);
107 
108  // This sets whether or not an object can see in the dark.
109  inline void SetCanSeeInDarkFlag(uint32 nID, bool8 bState);
110 
111  // This sets whether or not a mega is always seen regardless of shadows or not.
112  inline void SetNeverInShadowFlag(uint32 nID, bool8 bState);
113 
114  // This turns off shadow-handling for the whole LOS engine.
115  inline void ShadowsOnOff(bool8 bState) { m_bHandleShadows = bState; }
116 
117  // This checks line-of-sight between two objects, accounting for field-of-view if observer is an actor,
118  bool8 ObjectToObject(uint32 nObserverID, uint32 nTargetID, eBarrierRayType eRayType, bool8 bCanSeeUs, ActorEyeMode eEyeMode, bool8 bOverrideHeightLimit = FALSE8);
119 
120  // This checks line-of-sight using the current truth table values and so is fast.
121  inline bool8 LineOfSight(uint32 nObserverID, uint32 nTargetID);
122 
123  // And these two return extra information after a call to ObjectToObject().
124  const px3DRealPoint GetLastImpactPoint() const { return (m_oImpactPoint); }
125  eBarrierLogicValue GetLastImpactType() const { return (m_eImpactType); }
126 
127  // This allows other classes to get at the barrier slices (the Remora needs this).
128  LinkedDataFile *GetSlicesPointer() const { return (m_pyLOSData); }
129 
130  bool8 FailingOnHeight() const { return (m_bFailingOnHeight); }
131 
132 private:
133  LinkedDataFile *m_pyLOSData; // Pointer to the loaded line-of-sight data file.
134  uint32 m_nSubsPerCycle; // How many subscribers to process per cycle.
135  uint32 m_nFirstSubscriber; // Number of first subscriber to process
136  uint32 m_nNumObjects; // Number of subscribers to this service.
137  uint32 m_nTotalCurrentSubscribers; // Total number of current subscribers to this service.
138  uint32 m_pnFieldOfView[LOS_1D_SIZE]; // Current field-of-view for each mega.
139  uint32 m_pnSeeingDistance[LOS_1D_SIZE]; // Maximum distance an object can see.
140  PXreal m_pfHeightOfView[LOS_1D_SIZE]; // Height restriction on view.
141  int32 m_pnSubscribeNum[LOS_1D_SIZE]; // How many times a game object has subscribed.
142  uint8 m_pnTable[LOS_2D_SIZE_PACKED]; // The truth-table of who can see who.
143  uint8 m_pnSubscribers[LOS_2D_SIZE_PACKED]; // Housekeeping table of current subscribers to the service.
144  bool8 m_pbSuspended[LOS_1D_SIZE]; // If true, the object has been temporarily suspended.
145  bool8 m_pbCanSeeInDark[LOS_1D_SIZE]; // Housekeeping table of objects that should ignore shadows.
146  bool8 m_pbIgnoreShadows[LOS_1D_SIZE]; // Table of megas that are always seen regardless of shadows.
147  px3DRealPoint m_oImpactPoint; // Holds impact point from last call to ObjectToObject().
148  eBarrierLogicValue m_eImpactType; // Holds type of impact from last call to ObjectToObject().
149  bool8 m_bSwitchedOn; // Flag that allows LOS processing to be suspended.
150  bool8 m_bFailingOnHeight; // Debug flag that gets set when a barrier height check fails.
151  bool8 m_bHandleShadows; // Turns shadow handling on/off.
152  uint8 m_nPad;
153 
154  // Here I block the use of the default '='.
155  _line_of_sight(const _line_of_sight &) {}
156  void operator=(const _line_of_sight &) {}
157 
158  // Functions used internally by this class.
159  void WhatSeesWhat();
160 
161  bool8 InFieldOfView(PXreal fLookingX, PXreal fLookingZ, PXfloat fLookingDirection, PXreal fObservedX, PXreal fObservedZ, uint32 nFieldOfView) const;
162 
163  inline void SetPackedBit(uint8 *pnArray, uint32 i, uint32 j, bool8 bValue);
164  inline bool8 GetPackedBit(uint8 *pnArray, uint32 i, uint32 j) const;
165 };
166 
167 extern _line_of_sight *g_oLineOfSight;
168 
169 inline _line_of_sight::_line_of_sight() {
170  m_bSwitchedOn = TRUE8;
171  m_nSubsPerCycle = LOS_DEFAULT_SUBSCRIBERS_PER_CYCLE;
172  m_nFirstSubscriber = 0;
173  m_pyLOSData = NULL;
174  m_nNumObjects = 0;
175  m_nTotalCurrentSubscribers = 0;
176  m_bHandleShadows = TRUE8;
177  m_nPad = 0;
178 }
179 
180 inline _line_of_sight::~_line_of_sight() {
181  m_pyLOSData = NULL;
182  m_nNumObjects = 0;
183 
184  Zdebug("Destroyed line-of-sight object");
185 }
186 
187 inline void _line_of_sight::Unsuspend(uint32 nObserverID) {
188  // Set the flag for the object.
189  m_pbSuspended[nObserverID] = FALSE8;
190 }
191 
192 inline void _line_of_sight::SetCanSeeInDarkFlag(uint32 nID, bool8 bState) {
193  // Set the flag for the object.
194  m_pbCanSeeInDark[nID] = bState;
195 }
196 
197 inline void _line_of_sight::SetNeverInShadowFlag(uint32 nID, bool8 bState) {
198  // Set the flag for the object.
199  m_pbIgnoreShadows[nID] = bState;
200 }
201 
202 inline bool8 _line_of_sight::LineOfSight(uint32 nObserverID, uint32 nTargetID) { return (GetPackedBit(m_pnTable, nObserverID, nTargetID)); }
203 
204 inline void _line_of_sight::SwitchOff() {
205  m_bSwitchedOn = FALSE8;
206 
207  memset((uint8 *)m_pnTable, 0, (size_t)(LOS_2D_SIZE_PACKED * sizeof(uint8)));
208 }
209 
210 inline void _line_of_sight::SetPackedBit(uint8 *pnArray, uint32 i, uint32 j, bool8 bValue) {
211  uint32 nJIndex = j >> 3;
212  uint32 nJRemainder = (j & 0x00000007);
213 
214  if (bValue)
215  pnArray[i * LOS_2D_ROWSIZE_PACKED + nJIndex] |= (uint8)(1 << nJRemainder);
216  else
217  pnArray[i * LOS_2D_ROWSIZE_PACKED + nJIndex] &= (uint8)(~(1 << nJRemainder));
218 }
219 
220 inline bool8 _line_of_sight::GetPackedBit(uint8 *pnArray, uint32 i, uint32 j) const {
221  uint32 nJIndex = j >> 3;
222  uint32 nJRemainder = (j & 0x00000007);
223 
224  if ((pnArray[i * LOS_2D_ROWSIZE_PACKED + nJIndex] & (uint8)(1 << nJRemainder)) != 0)
225  return (TRUE8);
226  else
227  return (FALSE8);
228 }
229 
230 } // End of namespace ICB
231 
232 #endif // #if !defined( LINEOFSIGHT_H_INCLUDED )
Definition: px_3drealpoint.h:45
Definition: actor.h:32
Definition: px_linkeddatafile.h:53
Definition: line_of_sight.h:64