]> Dogcows Code - chaz/yoink/blob - src/Moof/Scene.cc
extreme refactoring
[chaz/yoink] / src / Moof / Scene.cc
1
2 /*******************************************************************************
3
4 Copyright (c) 2009, Charles McGarvey
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9
10 * Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 *******************************************************************************/
28
29 #include <iostream>
30 #include <map>
31 #include <vector>
32
33 #include "Aabb.hh"
34 #include "Camera.hh"
35 #include "Cullable.hh"
36 #include "Deserializer.hh"
37 #include "Drawable.hh"
38 #include "Math.hh"
39 #include "Mippleton.hh"
40 #include "OpenGL.hh"
41 #include "Scene.hh"
42 #include "Serializable.hh"
43 #include "Tilemap.hh"
44
45
46 namespace Mf {
47
48
49 class Scene::SceneImpl : public Mippleton<SceneImpl>
50 {
51 class Scenery : public Drawable, public Cullable
52 {
53 public:
54 Scenery(const Matrix4& transform, const std::string& textureName) :
55 transformation(transform),
56 image(textureName) {}
57
58 protected:
59 Matrix4 transformation;
60 Tilemap image;
61 bool blending;
62 long detail;
63 bool fog;
64 };
65
66 class TilePanel : public Scenery
67 {
68 public:
69 TilePanel(const Matrix4& transform, const std::string& textureName,
70 SerializablePtr root) :
71 Scenery(transform, textureName),
72 width(1),
73 height(1)
74 {
75 std::map<std::string,SerializablePtr> rootObj;
76
77 if (root->get(rootObj))
78 {
79 std::map<std::string,SerializablePtr>::iterator it;
80
81 if ((it = rootObj.find("width")) != rootObj.end())
82 {
83 (*it).second->get(width);
84 }
85 if ((it = rootObj.find("tiles")) != rootObj.end())
86 {
87 std::vector<SerializablePtr> theTiles;
88
89 if ((*it).second->get(theTiles))
90 {
91 std::vector<SerializablePtr>::iterator jt;
92
93 height = theTiles.size() / width;
94 int w, h;
95
96 indices.resize(height);
97
98 for (h = height - 1, jt = theTiles.begin();
99 jt != theTiles.end(); h--)
100 {
101 std::vector<Tilemap::Index> row;
102
103 for (w = 0; w < width && jt != theTiles.end();
104 w++, jt++)
105 {
106 long index;
107
108 if ((*jt)->get(index))
109 {
110 row.push_back(Tilemap::Index(index));
111 }
112 }
113
114 indices[h] = row;
115 }
116 }
117 }
118 }
119 }
120
121 void draw(Scalar alpha)
122 {
123 glPushMatrix();
124 //std::cout << "transforming..." << std::endl;
125 //std::cout << transformation << std::endl;
126 glMultMatrixf(transformation.data());
127
128 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
129 image.bind();
130
131 long x, y;
132 Scalar xf, yf;
133
134 for (y = 0, yf = 0.0; y < height; y++, yf += 1.0)
135 {
136 for (x = 0, xf = 0.0; x < width; x++, xf += 1.0)
137 {
138 Scalar texCoords[8];
139
140 Tilemap::Index index = indices[y][x];
141
142 if (image.getTileCoords(index, texCoords))
143 {
144 glBegin(GL_TRIANGLE_FAN);
145 glTexCoord2f(texCoords[0], texCoords[1]);
146 glVertex3f(xf, yf, 0.0f);
147 glTexCoord2f(texCoords[2], texCoords[3]);
148 glVertex3f(xf+1.0, yf, 0.0f);
149 glTexCoord2f(texCoords[4], texCoords[5]);
150 glVertex3f(xf+1.0, yf+1.0, 0.0f);
151 glTexCoord2f(texCoords[6], texCoords[7]);
152 glVertex3f(xf, yf+1.0, 0.0f);
153 glEnd();
154 }
155 }
156 }
157
158 glPopMatrix();
159 }
160
161 bool isVisible(const Camera& cam)
162 {
163 return true;
164 }
165
166 private:
167 long width, height;
168 std::vector<std::vector<Tilemap::Index> > indices;
169 };
170
171 class Billboard : public Scenery
172 {
173 public:
174 Billboard(const Matrix4& transform, const std::string& textureName,
175 SerializablePtr root) :
176 Scenery(transform, textureName),
177 index(0)
178 {
179 std::map<std::string,SerializablePtr> rootObj;
180
181 if (root->get(rootObj))
182 {
183 std::map<std::string,SerializablePtr>::iterator it;
184
185 if ((it = rootObj.find("tile")) != rootObj.end())
186 {
187 long value;
188 if ((*it).second->get(value))
189 {
190 index = Tilemap::Index(value);
191 }
192 }
193 }
194
195 image.getTileCoords(index, texCoords);
196 }
197
198 void draw(Scalar alpha)
199 {
200 glPushMatrix();
201 glMultMatrixf(transformation.data());
202
203 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
204 image.bind();
205
206 glBegin(GL_TRIANGLE_FAN);
207 glTexCoord2f(texCoords[0], texCoords[1]);
208 glVertex2f(0.0f, 0.0f);
209 glTexCoord2f(texCoords[2], texCoords[3]);
210 glVertex2f(1.0f, 0.0f);
211 glTexCoord2f(texCoords[4], texCoords[5]);
212 glVertex2f(1.0f, 1.0f);
213 glTexCoord2f(texCoords[6], texCoords[7]);
214 glVertex2f(0.0f, 1.0f);
215 glEnd();
216
217 glPopMatrix();
218 }
219
220 bool isVisible(const Camera& cam)
221 {
222 return false;
223 }
224
225 private:
226 Tilemap::Index index;
227 Scalar texCoords[8];
228 };
229
230
231 static bool loadBox(Aabb& theBox, SerializablePtr obj)
232 {
233 std::vector<SerializablePtr> numbers;
234
235 if (obj->get(numbers))
236 {
237 if (numbers.size() == 6)
238 {
239 double num;
240
241 if (numbers[0]->getNumber(num))
242 {
243
244 }
245 }
246 }
247
248 return false;
249 }
250
251 public:
252 SceneImpl(const std::string& name) :
253 Mippleton<SceneImpl>(name)
254 {
255 loadFromFile();
256 }
257
258
259 void loadInstructions(SerializablePtr root)
260 {
261 std::vector<SerializablePtr> rootObj;
262
263 if (root->get(rootObj))
264 {
265 std::vector<SerializablePtr>::iterator it;
266
267 Matrix4 transform;
268 std::string texture;
269
270 for (it = rootObj.begin(); it != rootObj.end(); it++)
271 {
272 std::string instruction;
273
274 if ((*it)->get(instruction))
275 {
276 if (instruction == "reset_transform")
277 {
278 transform.identity();
279 //std::cout << "===================RESET=====================" << std::endl;
280 }
281 else if (instruction == "translate")
282 {
283 std::vector<SerializablePtr> values;
284
285 it++;
286 if ((*it)->get(values))
287 {
288 Vector3 vec;
289
290 for (size_t i = 0; i < values.size(); i++)
291 {
292 double value;
293
294 if (values[i]->getNumber(value))
295 {
296 vec[i] = value;
297 }
298 }
299
300 Matrix4 translation;
301 cml::matrix_translation(translation, vec);
302 transform = translation * transform;
303 //std::cout << "TRANSLATE\t" << vec << std::endl
304 //<< transform << std::endl;
305 }
306 }
307 else if (instruction == "scale")
308 {
309 std::vector<SerializablePtr> values;
310
311 it++;
312 if ((*it)->get(values))
313 {
314 if (values.size() == 1)
315 {
316 double value = 1.0;
317
318 values[0]->getNumber(value);
319
320 Matrix4 scaling;
321 cml::matrix_uniform_scale(scaling, Scalar(value));
322 transform = scaling * transform;
323 //std::cout << "SCALE\t\t" << value << std::endl
324 //<< transform << std::endl;
325 }
326 else if (values.size() == 3)
327 {
328 Vector3 vec;
329
330 for (size_t i = 0; i < values.size(); i++)
331 {
332 double value;
333
334 if (values[i]->getNumber(value))
335 {
336 vec[i] = value;
337 }
338 }
339
340 Matrix4 scaling;
341 cml::matrix_scale(scaling, vec);
342 transform = scaling * transform;
343 //std::cout << "SCALE\t\t" << vec << std::endl
344 //<< transform << std::endl;
345 }
346 }
347 }
348 else if (instruction == "rotate")
349 {
350 std::vector<SerializablePtr> values;
351
352 it++;
353 if ((*it)->get(values))
354 {
355 if (values.size() == 2)
356 {
357 std::string axis;
358 size_t axisIndex = 0;
359 double value = 0.0;
360
361 if (values[0]->get(axis))
362 {
363 if (axis == "x")
364 {
365 axisIndex = 0;
366 }
367 else if (axis == "y")
368 {
369 axisIndex = 1;
370 }
371 else if (axis == "z")
372 {
373 axisIndex = 2;
374 }
375 values[1]->getNumber(value);
376 }
377
378 cml::matrix_rotate_about_local_axis(transform,
379 axisIndex, Scalar(value * cml::constantsd::rad_per_deg()));
380 //std::cout << "ROTATE\t" << axis << " " << value << std::endl
381 //<< transform << std::endl;
382 }
383 }
384 }
385 else if (instruction == "texture")
386 {
387 it++;
388 (*it)->get(texture);
389 }
390 else if (instruction == "tilemap")
391 {
392 //std::cout << "TILEMAP\t" << texture<< std::endl;
393 //std::cout << transform << std::endl;
394
395 it++;
396 TilePanel* tilePanel = new TilePanel(transform, texture,
397 *it);
398 boost::shared_ptr<Scenery> sceneItem(tilePanel);
399 objects.push_back(sceneItem);
400 }
401 else if (instruction == "billboard")
402 {
403 //std::cout << "BILLBOARD\t" << texture << std::endl;
404 //std::cout << transform << std::endl;
405
406 it++;
407 Billboard* billboard = new Billboard(transform, texture,
408 *it);
409 boost::shared_ptr<Scenery> sceneItem(billboard);
410 objects.push_back(sceneItem);
411 }
412 }
413 }
414 }
415 }
416
417
418 void loadFromFile()
419 {
420 std::string filePath = Scene::getPathToResource(getName());
421
422 Deserializer deserializer(filePath, true);
423
424 SerializablePtr root = deserializer.deserialize();
425
426 if (root)
427 {
428 std::map<std::string,SerializablePtr> rootObj;
429
430 if (root->get(rootObj))
431 {
432 std::map<std::string,SerializablePtr>::iterator it;
433
434 if ((it = rootObj.find("playfield_bounds")) != rootObj.end())
435 {
436 loadBox(playfieldBounds, (*it).second);
437 }
438 if ((it = rootObj.find("maximum_bounds")) != rootObj.end())
439 {
440 loadBox(maximumBounds, (*it).second);
441 }
442 if ((it = rootObj.find("instructions")) != rootObj.end())
443 {
444 loadInstructions((*it).second);
445 }
446 }
447 }
448 }
449
450
451 void draw(Scalar alpha)
452 {
453 SceneryVector::iterator it;
454
455 for (it = objects.begin(); it != objects.end(); it++)
456 {
457 //std::cout << "draw object";
458 (*it)->draw(alpha);
459 }
460 }
461
462
463 Aabb playfieldBounds;
464 Aabb maximumBounds;
465
466 typedef std::vector<boost::shared_ptr<Scenery> > SceneryVector;
467 SceneryVector objects;
468 };
469
470
471 Scene::Scene(const std::string& name) :
472 // pass through
473 impl_(Scene::SceneImpl::retain(name), &Scene::SceneImpl::release) {}
474
475
476 void Scene::draw(Scalar alpha)
477 {
478 // pass through
479 impl_->draw(alpha);
480 }
481
482
483 /**
484 * Specialized search location for scene files. They can be found in the
485 * "scenes" subdirectory of any of the searched directories.
486 */
487
488 std::string Scene::getPathToResource(const std::string& name)
489 {
490 return Resource::getPathToResource("scenes/" + name + ".json");
491 }
492
493
494 } // namespace Mf
495
496 /** vim: set ts=4 sw=4 tw=80: *************************************************/
497
This page took 0.050864 seconds and 4 git commands to generate.