]> Dogcows Code - chaz/yoink/blob - src/Moof/Scene.cc
fixed up video and texture handling
[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 glMultMatrix(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 glVertex2f(xf, yf);
147 glTexCoord2f(texCoords[2], texCoords[3]);
148 glVertex2f(xf+1.0, yf);
149 glTexCoord2f(texCoords[4], texCoords[5]);
150 glVertex2f(xf+1.0, yf+1.0);
151 glTexCoord2f(texCoords[6], texCoords[7]);
152 glVertex2f(xf, yf+1.0);
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 uScale(1)
179 {
180 std::map<std::string,SerializablePtr> rootObj;
181
182 if (root->get(rootObj))
183 {
184 std::map<std::string,SerializablePtr>::iterator it;
185
186 if ((it = rootObj.find("tile")) != rootObj.end())
187 {
188 long value;
189 if ((*it).second->get(value))
190 {
191 index = Tilemap::Index(value);
192 }
193 }
194 if ((it = rootObj.find("u_scale")) != rootObj.end())
195 {
196 (*it).second->get(uScale);
197 }
198 }
199
200 image.getTileCoords(index, texCoords);
201 }
202
203 void draw(Scalar alpha)
204 {
205 glPushMatrix();
206 glMultMatrix(transformation.data());
207
208 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
209 image.bind();
210
211 float increment = 1.0f / float(uScale);
212 int x;
213 float xf;
214
215 for (x = 0, xf = 0.0f; x < uScale; x++, xf += increment)
216 {
217 glBegin(GL_TRIANGLE_FAN);
218 glTexCoord2f(texCoords[0], texCoords[1]);
219 glVertex2f(xf, 0.0f);
220 glTexCoord2f(texCoords[2], texCoords[3]);
221 glVertex2f(xf+increment, 0.0f);
222 glTexCoord2f(texCoords[4], texCoords[5]);
223 glVertex2f(xf+increment, 1.0f);
224 glTexCoord2f(texCoords[6], texCoords[7]);
225 glVertex2f(xf, 1.0f);
226 glEnd();
227 }
228
229 glPopMatrix();
230 }
231
232 bool isVisible(const Camera& cam)
233 {
234 return false;
235 }
236
237 private:
238 Tilemap::Index index;
239 Scalar texCoords[8];
240 long uScale;
241 };
242
243
244 static bool loadBox(Aabb& theBox, SerializablePtr obj)
245 {
246 std::vector<SerializablePtr> numbers;
247
248 if (obj->get(numbers))
249 {
250 if (numbers.size() == 6)
251 {
252 double num;
253
254 if (numbers[0]->getNumber(num))
255 {
256
257 }
258 }
259 }
260
261 return false;
262 }
263
264 public:
265 SceneImpl(const std::string& name) :
266 Mippleton<SceneImpl>(name)
267 {
268 loadFromFile();
269 }
270
271
272 void loadInstructions(SerializablePtr root)
273 {
274 std::vector<SerializablePtr> rootObj;
275
276 if (root->get(rootObj))
277 {
278 std::vector<SerializablePtr>::iterator it;
279
280 Matrix4 transform;
281 std::string texture;
282
283 for (it = rootObj.begin(); it != rootObj.end(); it++)
284 {
285 std::string instruction;
286
287 if ((*it)->get(instruction))
288 {
289 if (instruction == "reset_transform")
290 {
291 transform.identity();
292 //std::cout << "===================RESET=====================" << std::endl;
293 }
294 else if (instruction == "translate")
295 {
296 std::vector<SerializablePtr> values;
297
298 it++;
299 if ((*it)->get(values))
300 {
301 Vector3 vec;
302
303 for (size_t i = 0; i < values.size(); i++)
304 {
305 double value;
306
307 if (values[i]->getNumber(value))
308 {
309 vec[i] = value;
310 }
311 }
312
313 Matrix4 translation;
314 cml::matrix_translation(translation, vec);
315 transform = translation * transform;
316 //std::cout << "TRANSLATE\t" << vec << std::endl
317 //<< transform << std::endl;
318 }
319 }
320 else if (instruction == "scale")
321 {
322 std::vector<SerializablePtr> values;
323
324 it++;
325 if ((*it)->get(values))
326 {
327 if (values.size() == 1)
328 {
329 double value = 1.0;
330
331 values[0]->getNumber(value);
332
333 Matrix4 scaling;
334 cml::matrix_uniform_scale(scaling, Scalar(value));
335 transform = scaling * transform;
336 //std::cout << "SCALE\t\t" << value << std::endl
337 //<< transform << std::endl;
338 }
339 else if (values.size() == 3)
340 {
341 Vector3 vec;
342
343 for (size_t i = 0; i < values.size(); i++)
344 {
345 double value;
346
347 if (values[i]->getNumber(value))
348 {
349 vec[i] = value;
350 }
351 }
352
353 Matrix4 scaling;
354 cml::matrix_scale(scaling, vec);
355 transform = scaling * transform;
356 //std::cout << "SCALE\t\t" << vec << std::endl
357 //<< transform << std::endl;
358 }
359 }
360 }
361 else if (instruction == "rotate")
362 {
363 std::vector<SerializablePtr> values;
364
365 it++;
366 if ((*it)->get(values))
367 {
368 if (values.size() == 2)
369 {
370 std::string axis;
371 size_t axisIndex = 0;
372 double value = 0.0;
373
374 if (values[0]->get(axis))
375 {
376 if (axis == "x")
377 {
378 axisIndex = 0;
379 }
380 else if (axis == "y")
381 {
382 axisIndex = 1;
383 }
384 else if (axis == "z")
385 {
386 axisIndex = 2;
387 }
388 values[1]->getNumber(value);
389 }
390
391 cml::matrix_rotate_about_local_axis(transform,
392 axisIndex, Scalar(value * cml::constantsd::rad_per_deg()));
393 //std::cout << "ROTATE\t" << axis << " " << value << std::endl
394 //<< transform << std::endl;
395 }
396 }
397 }
398 else if (instruction == "texture")
399 {
400 it++;
401 (*it)->get(texture);
402 }
403 else if (instruction == "tilemap")
404 {
405 //std::cout << "TILEMAP\t" << texture<< std::endl;
406 //std::cout << transform << std::endl;
407
408 it++;
409 TilePanel* tilePanel = new TilePanel(transform, texture,
410 *it);
411 boost::shared_ptr<Scenery> sceneItem(tilePanel);
412 objects.push_back(sceneItem);
413 }
414 else if (instruction == "billboard")
415 {
416 //std::cout << "BILLBOARD\t" << texture << std::endl;
417 //std::cout << transform << std::endl;
418
419 it++;
420 Billboard* billboard = new Billboard(transform, texture,
421 *it);
422 boost::shared_ptr<Scenery> sceneItem(billboard);
423 objects.push_back(sceneItem);
424 }
425 }
426 }
427 }
428 }
429
430
431 void loadFromFile()
432 {
433 std::string filePath = Scene::getPathToResource(getName());
434
435 Deserializer deserializer(filePath, true);
436
437 SerializablePtr root = deserializer.deserialize();
438
439 if (root)
440 {
441 std::map<std::string,SerializablePtr> rootObj;
442
443 if (root->get(rootObj))
444 {
445 std::map<std::string,SerializablePtr>::iterator it;
446
447 if ((it = rootObj.find("playfield_bounds")) != rootObj.end())
448 {
449 loadBox(playfieldBounds, (*it).second);
450 }
451 if ((it = rootObj.find("maximum_bounds")) != rootObj.end())
452 {
453 loadBox(maximumBounds, (*it).second);
454 }
455 if ((it = rootObj.find("instructions")) != rootObj.end())
456 {
457 loadInstructions((*it).second);
458 }
459 }
460 }
461 }
462
463
464 void draw(Scalar alpha)
465 {
466 SceneryVector::iterator it;
467
468 for (it = objects.begin(); it != objects.end(); it++)
469 {
470 //std::cout << "draw object";
471 (*it)->draw(alpha);
472 }
473 }
474
475
476 Aabb playfieldBounds;
477 Aabb maximumBounds;
478
479 typedef std::vector<boost::shared_ptr<Scenery> > SceneryVector;
480 SceneryVector objects;
481 };
482
483
484 Scene::Scene(const std::string& name) :
485 // pass through
486 impl_(Scene::SceneImpl::retain(name), &Scene::SceneImpl::release) {}
487
488
489 void Scene::draw(Scalar alpha)
490 {
491 // pass through
492 impl_->draw(alpha);
493 }
494
495
496 /**
497 * Specialized search location for scene files. They can be found in the
498 * "scenes" subdirectory of any of the searched directories.
499 */
500
501 std::string Scene::getPathToResource(const std::string& name)
502 {
503 return Resource::getPathToResource("scenes/" + name + ".json");
504 }
505
506
507 } // namespace Mf
508
509 /** vim: set ts=4 sw=4 tw=80: *************************************************/
510
This page took 0.053411 seconds and 5 git commands to generate.