Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
bubble_display.cpp
Go to the documentation of this file.
1 // -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*-
2 
3 #include <cmath>
4 #include <vector>
5 #include <boost/assign/std/vector.hpp>
6 #include "lin_time.h" // GetElapsedTime
7 #include "cmd/unit_generic.h"
8 #include "cmd/unit_util.h"
9 #include "gfxlib.h"
10 #include "viewarea.h"
11 #include "bubble_display.h"
12 
13 namespace
14 {
15 
17 {
18  using namespace Radar;
19 
20  switch (threat)
21  {
23  return 20.0; // Fast pulsation
24 
26  return 7.5; // Slow pulsation
27 
28  default:
29  return 0.0; // No pulsation
30  }
31 }
32 
33 } // anonymous namespace
34 
35 namespace Radar
36 {
37 
39  : innerSphere(0.45),
40  outerSphere(1.0),
41  sphereZoom(1.0),
42  radarTime(0.0),
43  currentTargetMarkerSize(0.0),
44  lastAnimationTime(0.0)
45 {
46  using namespace boost::assign; // vector::operator+=
47  explodeSequence += 0.0, 0.0001, 0.0009, 0.0036, 0.0100, 0.0225, 0.0441, 0.0784, 0.1296, 0.2025, 0.3025, 0.4356, 0.6084, 0.8281, 1.0, 0.8713, 0.7836, 0.7465, 0.7703, 0.8657, 1.0, 0.9340, 0.9595, 1.0, 0.9659, 1.0;
48  implodeSequence += 1.0, 0.9999, 0.9991, 0.9964, 0.9900, 0.9775, 0.9559, 0.9216, 0.8704, 0.7975, 0.6975, 0.5644, 0.3916, 0.1719, 0.0, 0.1287, 0.2164, 0.2535, 0.2297, 0.1343, 0.0, 0.0660, 0.0405, 0.0, 0.0341, 0.0;
49 }
50 
52 {
53  AnimationItem firstItem;
54  firstItem.duration = 0.0;
55  firstItem.sphereZoom = sequence[0];
56  animation.push(firstItem);
57 
58  float duration = 2.0;
59  for (ZoomSequence::size_type i = 1; i < sequence.size(); ++i)
60  {
61  AnimationItem item;
62  item.duration = duration;
63  item.sphereZoom = sequence[i];
64  animation.push(item);
65  duration = 0.05;
66  }
67 }
68 
70 {
72 }
73 
75 {
77 }
78 
80 {
82 }
83 
85 {
86  if (!animation.empty())
87  {
88  if (radarTime > lastAnimationTime + animation.front().duration)
89  {
90  sphereZoom = animation.front().sphereZoom;
91  animation.pop();
93  }
94  }
95 }
96 
97 void BubbleDisplay::Draw(const Sensor& sensor,
98  VSSprite *frontSprite,
99  VSSprite *rearSprite)
100 {
101  assert(frontSprite || rearSprite); // There should be at least one radar display
102 
104 
105  leftRadar.SetSprite(frontSprite);
106  rightRadar.SetSprite(rearSprite);
107 
108  if (frontSprite)
109  frontSprite->Draw();
110  if (rearSprite)
111  rearSprite->Draw();
112 
113  Sensor::TrackCollection tracks = sensor.FindTracksInRange();
114 
115  Animate();
116 
119  GFXEnable(SMOOTH);
120 
121  for (Sensor::TrackCollection::const_iterator it = tracks.begin(); it != tracks.end(); ++it)
122  {
123  if (it->GetPosition().z < 0)
124  {
125  // Draw tracks behind the ship
126  DrawTrack(sensor, rightRadar, *it);
127  }
128  else
129  {
130  // Draw tracks in front of the ship
131  DrawTrack(sensor, leftRadar, *it);
132  }
133  }
134 
137 
138  GFXPointSize(1);
142 }
143 
144 void BubbleDisplay::DrawTrack(const Sensor& sensor,
145  const ViewArea& radarView,
146  const Track& track)
147 {
148  if (!radarView.IsActive())
149  return;
150 
151  GFXColor color = sensor.GetColor(track);
152 
153  Vector position = track.GetPosition();
154  if (position.z < 0)
155  position.z = -position.z;
156 
157  float magnitude = position.Magnitude();
158  float scaleFactor = 0.0; // [0; 1] where 0 = border, 1 = center
159  float maxRange = sensor.GetMaxRange();
160  if (magnitude <= maxRange)
161  {
162  // [innerSphere; outerSphere]
163  scaleFactor = (outerSphere - innerSphere) * ((maxRange - magnitude) / maxRange);
164  magnitude /= (1.0 - scaleFactor);
165  }
166 
167  if (sensor.InsideNebula())
168  {
169  magnitude /= (1.0 - 0.04 * Jitter(0.0, 1.0));
170  }
171  Vector scaledPosition = sphereZoom * Vector(-position.x, position.y, position.z) / magnitude;
172 
173  Vector head = radarView.Scale(scaledPosition);
174 
175  GFXColor headColor = color;
176 
177  headColor.a *= 0.2 + scaleFactor * (1.0 - 0.2); // [0;1] => [0.1;1]
178  if (sensor.UseThreatAssessment())
179  {
180  float dangerRate = GetDangerRate(sensor.IdentifyThreat(track));
181  if (dangerRate > 0.0)
182  {
183  // Blinking blip
184  headColor.a *= cosf(dangerRate * radarTime);
185  }
186  }
187 
188  // Fade out dying ships
189  if (track.IsExploding())
190  {
191  headColor.a *= (1.0 - track.ExplodingProgress());
192  }
193 
194  float trackSize = std::max(1.0f, std::log10(track.GetSize()));
195  if (track.GetType() != Track::Type::Cargo)
196  trackSize += 1.0;
197 
198  GFXColorf(headColor);
199  if (sensor.IsTracking(track))
200  {
201  currentTargetMarkerSize = trackSize;
202  DrawTargetMarker(head, trackSize);
203  }
204 
205  const bool isNebula = (track.GetType() == Track::Type::Nebula);
206  const bool isEcmActive = track.HasActiveECM();
207  if (isNebula || isEcmActive)
208  {
209  // Vary size between 50% and 150%
210  trackSize *= Jitter(0.5, 1.0);
211  }
212 
213  GFXPointSize(trackSize);
215  GFXVertexf(head);
216  GFXEnd();
217 }
218 
219 void BubbleDisplay::DrawTargetMarker(const Vector& position, float trackSize)
220 {
221  // Split octagon
222  float size = 3.0 * std::max(trackSize, 3.0f);
223  float xsize = size / g_game.x_resolution;
224  float ysize = size / g_game.y_resolution;
225  GFXLineWidth(1);
227  GFXVertex3f(position.x - xsize / 2, position.y - ysize, position.z);
228  GFXVertex3f(position.x - xsize, position.y - ysize / 2, position.z);
229  GFXVertex3f(position.x - xsize, position.y + ysize / 2, position.z);
230  GFXVertex3f(position.x - xsize / 2, position.y + ysize, position.z);
231  GFXEnd();
233  GFXVertex3f(position.x + xsize / 2, position.y - ysize, position.z);
234  GFXVertex3f(position.x + xsize, position.y - ysize / 2, position.z);
235  GFXVertex3f(position.x + xsize, position.y + ysize / 2, position.z);
236  GFXVertex3f(position.x + xsize / 2, position.y + ysize, position.z);
237  GFXEnd();
238 }
239 
240 void BubbleDisplay::DrawBackground(const ViewArea& radarView, float trackSize)
241 {
242  if (!radarView.IsActive())
243  return;
244 
245  GFXColor groundColor = radarView.GetColor();
246 
247  // Split octagon
248  float size = 3.0 * std::max(trackSize, 3.0f);
249  float xground = size / g_game.x_resolution;
250  float yground = size / g_game.y_resolution;
251  Vector center = radarView.Scale(Vector(0.0, 0.0, 0.0));
252 
253  GFXColorf(groundColor);
254  GFXLineWidth(1);
256  GFXVertex3f(center.x - xground, center.y - yground / 2, center.z);
257  GFXVertex3f(center.x - xground / 2, center.y - yground, center.z);
258  GFXVertex3f(center.x + xground / 2, center.y - yground, center.z);
259  GFXVertex3f(center.x + xground, center.y - yground / 2, center.z);
260  GFXEnd();
262  GFXVertex3f(center.x - xground, center.y + yground / 2, center.z);
263  GFXVertex3f(center.x - xground / 2, center.y + yground, center.z);
264  GFXVertex3f(center.x + xground / 2, center.y + yground, center.z);
265  GFXVertex3f(center.x + xground, center.y + yground / 2, center.z);
266  GFXEnd();
267 }
268 
269 } // namespace Radar