Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Scene.cpp
Go to the documentation of this file.
1 /* Project nGenEx
2  Destroyer Studios LLC
3  Copyright © 1997-2004. All Rights Reserved.
4 
5  SUBSYSTEM: nGenEx.lib
6  FILE: Scene.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  A 3D Scene
13 */
14 
15 #include "MemDebug.h"
16 #include "Scene.h"
17 #include "Graphic.h"
18 #include "Light.h"
19 
20 void Print(const char* fmt, ...);
21 
22 // +--------------------------------------------------------------------+
23 
25 { }
26 
28 {
31  graphics.destroy();
32  sprites.destroy();
33 
34  lights.destroy();
35 }
36 
37 // +--------------------------------------------------------------------+
38 
39 void
41 {
42  if (g) {
43  if (!background.contains(g))
44  background.append(g);
45 
46  g->SetScene(this);
47  }
48 }
49 
50 void
52 {
53  if (g) {
54  background.remove(g);
55  g->SetScene(0);
56  }
57 }
58 
59 // +--------------------------------------------------------------------+
60 
61 void
63 {
64  if (g) {
65  if (!foreground.contains(g))
66  foreground.append(g);
67 
68  g->SetScene(this);
69  }
70 }
71 
72 void
74 {
75  if (g) {
76  foreground.remove(g);
77  g->SetScene(0);
78  }
79 }
80 
81 // +--------------------------------------------------------------------+
82 
83 void
85 {
86  if (g) {
87  if (!graphics.contains(g))
88  graphics.append(g);
89 
90  g->SetScene(this);
91  }
92 }
93 
94 void
96 {
97  if (g) {
98  graphics.remove(g) || // it's gotta be in here somewhere!
99  foreground.remove(g) || // use the logical-or operator to early
100  sprites.remove(g) || // out when we find it...
101  background.remove(g);
102 
103  g->SetScene(0);
104  }
105 }
106 
107 // +--------------------------------------------------------------------+
108 
109 void
111 {
112  if (g) {
113  if (!sprites.contains(g))
114  sprites.append(g);
115 
116  g->SetScene(this);
117  }
118 }
119 
120 void
122 {
123  if (g) {
124  sprites.remove(g);
125  g->SetScene(0);
126  }
127 }
128 
129 // +--------------------------------------------------------------------+
130 
131 void
133 {
134  if (l) {
135  if (!lights.contains(l))
136  lights.append(l);
137  l->SetScene(this);
138  }
139 }
140 
141 void
143 {
144  if (l) {
145  lights.remove(l);
146  l->SetScene(0);
147  }
148 }
149 
150 // +--------------------------------------------------------------------+
151 
152 void
154 {
156 
157  while (++iter) {
158  Graphic* g = iter.value();
159  if (g->Life() == 0) {
160  delete iter.removeItem();
161  }
162  }
163 
164  iter.attach(sprites);
165 
166  while (++iter) {
167  Graphic* g = iter.value();
168  if (g->Life() == 0) {
169  delete iter.removeItem();
170  }
171  }
172 
173  ListIter<Light> iter1 = lights;
174 
175  while (++iter1) {
176  Light* l = iter1.value();
177  if (l->Life() == 0) {
178  delete iter1.removeItem();
179  }
180  }
181 }
182 
183 
184 // +--------------------------------------------------------------------+
185 
186 bool
187 Scene::IsLightObscured(const Point& obj_pos, const Point& light_pos, double obj_radius, Point* impact_point) const
188 {
189  Point dir = light_pos - obj_pos;
190  double len = dir.Normalize();
191 
192  Scene* pThis = (Scene*) this; // cast-away const
193  Graphic* g = 0;
194  bool obscured = false;
195 
196  ListIter<Graphic> g_iter = pThis->graphics;
197  while (++g_iter && !obscured) {
198  g = g_iter.value();
199 
200  if (g->CastsShadow() && !g->Hidden() && !g->IsInfinite()) {
201  double gdist = (g->Location() - obj_pos).length();
202  if (gdist > 0.1 && // different than object being obscured
203  g->Radius() > obj_radius && // larger than object being obscured
204  (g->Radius()*400)/gdist > 10) { // projects to a resonable size
205 
206  Point delta = (g->Location() - light_pos);
207 
208  if (delta.length() > g->Radius() / 100) { // not the object that is emitting the light
209  Point impact;
210  obscured = g->CheckRayIntersection(obj_pos, dir, len, impact, false) ? true : false;
211 
212  if (impact_point)
213  *impact_point = impact;
214  }
215  }
216 
217  else if (obj_radius < 0 && gdist < 0.1) { // special case for camera (needed for cockpits)
218  Point delta = (g->Location() - light_pos);
219 
220  if (delta.length() > g->Radius() / 100) { // not the object that is emitting the light
221  Point impact;
222  obscured = g->CheckRayIntersection(obj_pos, dir, len, impact, false) ? true : false;
223  }
224  }
225  }
226  }
227 
228  g_iter.attach(pThis->foreground);
229  while (++g_iter && !obscured) {
230  g = g_iter.value();
231 
232  if (g->CastsShadow() && !g->Hidden()) {
233  double gdist = (g->Location() - obj_pos).length();
234  if (gdist > 0.1 && // different than object being obscured
235  g->Radius() > obj_radius && // larger than object being obscured
236  (g->Radius()*400)/gdist > 10) { // projects to a resonable size
237 
238  Point delta = (g->Location() - light_pos);
239 
240  if (delta.length() > g->Radius() / 100) { // not the object that is emitting the light
241  Point impact;
242  obscured = g->CheckRayIntersection(obj_pos, dir, len, impact, false) ? true : false;
243 
244  if (impact_point)
245  *impact_point = impact;
246  }
247  }
248 
249  else if (obj_radius < 0 && gdist < 0.1) { // special case for camera (needed for cockpits)
250  Point delta = (g->Location() - light_pos);
251 
252  if (delta.length() > g->Radius() / 100) { // not the object that is emitting the light
253  Point impact;
254  obscured = g->CheckRayIntersection(obj_pos, dir, len, impact, false) ? true : false;
255  }
256  }
257  }
258  }
259 
260  return obscured;
261 }