]> Dogcows Code - chaz/yoink/blob - src/scene.cc
beginnings of scene rendering
[chaz/yoink] / src / 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 "serializable.hh"
42 #include "tilemap.hh"
43
44 #include "scene.hh"
45
46
47 namespace dc {
48
49
50 class scene::scene_impl : public mippleton<scene_impl>
51 {
52 class scenery : public drawable, public cullable
53 {
54 public:
55 scenery(const matrix4& transform, const std::string& textureName) :
56 transformation(transform),
57 image(textureName) {}
58
59 protected:
60 matrix4 transformation;
61 tilemap image;
62 bool blending;
63 long detail;
64 bool fog;
65 };
66
67 class tiles : public scenery
68 {
69 public:
70 tiles(const matrix4& transform, const std::string& textureName,
71 serializable_ptr root) :
72 scenery(transform, textureName),
73 width(1),
74 height(1)
75 {
76 std::map<std::string,serializable_ptr> rootObj;
77
78 if (root->get(rootObj))
79 {
80 std::map<std::string,serializable_ptr>::iterator it;
81
82 if ((it = rootObj.find("width")) != rootObj.end())
83 {
84 (*it).second->get(width);
85 }
86 if ((it = rootObj.find("tiles")) != rootObj.end())
87 {
88 std::vector<serializable_ptr> theTiles;
89
90 if ((*it).second->get(theTiles))
91 {
92 std::vector<serializable_ptr>::iterator jt;
93
94 height = theTiles.size() / width;
95 int w, h;
96
97 indices.resize(height);
98
99 for (h = height - 1, jt = theTiles.begin();
100 jt != theTiles.end(); h--)
101 {
102 std::vector<unsigned> row;
103
104 for (w = 0; w < width && jt != theTiles.end();
105 w++, jt++)
106 {
107 long index;
108
109 if ((*jt)->get(index))
110 {
111 row.push_back(unsigned(index));
112 }
113 }
114
115 indices[h] = row;
116 }
117 }
118 }
119 }
120 }
121
122 void draw(scalar alpha)
123 {
124 glPushMatrix();
125 //std::cout << "transforming..." << std::endl;
126 //std::cout << transformation << std::endl;
127 glMultMatrixf(transformation.data());
128
129 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
130 image.bind();
131
132 long x, y;
133 scalar xf, yf;
134
135 for (y = 0, yf = 0.0; y < height; y++, yf += 1.0)
136 {
137 for (x = 0, xf = 0.0; x < width; x++, xf += 1.0)
138 {
139 scalar texCoords[8];
140
141 unsigned index = indices[y][x];
142
143 if (image.getTileCoords(index, texCoords))
144 {
145 glBegin(GL_TRIANGLE_FAN);
146 glTexCoord2f(texCoords[0], texCoords[1]);
147 glVertex3f(xf, yf, 0.0f);
148 glTexCoord2f(texCoords[2], texCoords[3]);
149 glVertex3f(xf+1.0, yf, 0.0f);
150 glTexCoord2f(texCoords[4], texCoords[5]);
151 glVertex3f(xf+1.0, yf+1.0, 0.0f);
152 glTexCoord2f(texCoords[6], texCoords[7]);
153 glVertex3f(xf, yf+1.0, 0.0f);
154 glEnd();
155 }
156 }
157 }
158
159 glPopMatrix();
160 }
161
162 bool isVisible(const camera& cam)
163 {
164 return true;
165 }
166
167 private:
168 long width, height;
169 std::vector<std::vector<unsigned> > indices;
170 };
171
172 class billboard : public scenery
173 {
174 public:
175 billboard(const matrix4& transform, const std::string& textureName,
176 serializable_ptr root) :
177 scenery(transform, textureName),
178 index(0)
179 {
180 std::map<std::string,serializable_ptr> rootObj;
181
182 if (root->get(rootObj))
183 {
184 std::map<std::string,serializable_ptr>::iterator it;
185
186 if ((it = rootObj.find("tile")) != rootObj.end())
187 {
188 long value;
189 if ((*it).second->get(value))
190 {
191 index = unsigned(value);
192 }
193 }
194 }
195
196 image.getTileCoords(index, texCoords);
197 }
198
199 void draw(scalar alpha)
200 {
201 glPushMatrix();
202 glMultMatrixf(transformation.data());
203
204 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
205 image.bind();
206
207 glBegin(GL_TRIANGLE_FAN);
208 glTexCoord2f(texCoords[0], texCoords[1]);
209 glVertex2f(0.0f, 0.0f);
210 glTexCoord2f(texCoords[2], texCoords[3]);
211 glVertex2f(1.0f, 0.0f);
212 glTexCoord2f(texCoords[4], texCoords[5]);
213 glVertex2f(1.0f, 1.0f);
214 glTexCoord2f(texCoords[6], texCoords[7]);
215 glVertex2f(0.0f, 1.0f);
216 glEnd();
217
218 glPopMatrix();
219 }
220
221 bool isVisible(const camera& cam)
222 {
223 return false;
224 }
225
226 private:
227 unsigned index;
228 scalar texCoords[8];
229 };
230
231
232 static bool loadBox(aabb& theBox, serializable_ptr obj)
233 {
234 std::vector<serializable_ptr> numbers;
235
236 if (obj->get(numbers))
237 {
238 if (numbers.size() == 6)
239 {
240 double num;
241
242 if (numbers[0]->getNumber(num))
243 {
244
245 }
246 }
247 }
248
249 return false;
250 }
251
252 public:
253 scene_impl(const std::string& name) :
254 mippleton<scene_impl>(name)
255 {
256 loadFromFile();
257 }
258
259
260 void loadInstructions(serializable_ptr root)
261 {
262 std::vector<serializable_ptr> rootObj;
263
264 if (root->get(rootObj))
265 {
266 std::vector<serializable_ptr>::iterator it;
267
268 matrix4 transform;
269 std::string texture;
270
271 for (it = rootObj.begin(); it != rootObj.end(); it++)
272 {
273 std::string instruction;
274
275 if ((*it)->get(instruction))
276 {
277 if (instruction == "reset_transform")
278 {
279 transform.identity();
280 //std::cout << "===================RESET=====================" << std::endl;
281 }
282 else if (instruction == "translate")
283 {
284 std::vector<serializable_ptr> values;
285
286 it++;
287 if ((*it)->get(values))
288 {
289 vector3 vec;
290
291 for (unsigned i = 0; i < values.size(); i++)
292 {
293 double value;
294
295 if (values[i]->getNumber(value))
296 {
297 vec[i] = value;
298 }
299 }
300
301 matrix4 translation;
302 cml::matrix_translation(translation, vec);
303 transform = translation * transform;
304 //std::cout << "TRANSLATE\t" << vec << std::endl
305 //<< transform << std::endl;
306 }
307 }
308 else if (instruction == "scale")
309 {
310 std::vector<serializable_ptr> values;
311
312 it++;
313 if ((*it)->get(values))
314 {
315 if (values.size() == 1)
316 {
317 double value = 1.0;
318
319 values[0]->getNumber(value);
320
321 matrix4 scaling;
322 cml::matrix_uniform_scale(scaling, scalar(value));
323 transform = scaling * transform;
324 //std::cout << "SCALE\t\t" << value << std::endl
325 //<< transform << std::endl;
326 }
327 else if (values.size() == 3)
328 {
329 vector3 vec;
330
331 for (unsigned i = 0; i < values.size(); i++)
332 {
333 double value;
334
335 if (values[i]->getNumber(value))
336 {
337 vec[i] = value;
338 }
339 }
340
341 matrix4 scaling;
342 cml::matrix_scale(scaling, vec);
343 transform = scaling * transform;
344 //std::cout << "SCALE\t\t" << vec << std::endl
345 //<< transform << std::endl;
346 }
347 }
348 }
349 else if (instruction == "rotate")
350 {
351 std::vector<serializable_ptr> values;
352
353 it++;
354 if ((*it)->get(values))
355 {
356 if (values.size() == 2)
357 {
358 std::string axis;
359 size_t axisIndex = 0;
360 double value = 0.0;
361
362 if (values[0]->get(axis))
363 {
364 if (axis == "x")
365 {
366 axisIndex = 0;
367 }
368 else if (axis == "y")
369 {
370 axisIndex = 1;
371 }
372 else if (axis == "z")
373 {
374 axisIndex = 2;
375 }
376 values[1]->getNumber(value);
377 }
378
379 cml::matrix_rotate_about_local_axis(transform,
380 axisIndex, scalar(value * cml::constantsd::rad_per_deg()));
381 //std::cout << "ROTATE\t" << axis << " " << value << std::endl
382 //<< transform << std::endl;
383 }
384 }
385 }
386 else if (instruction == "texture")
387 {
388 it++;
389 (*it)->get(texture);
390 }
391 else if (instruction == "tilemap")
392 {
393 //std::cout << "TILEMAP\t" << texture<< std::endl;
394 //std::cout << transform << std::endl;
395
396 it++;
397 tiles* newTiles = new tiles(transform, texture, *it);
398 boost::shared_ptr<scenery> sceneItem(newTiles);
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* newBB = new billboard(transform, texture,
408 *it);
409 boost::shared_ptr<scenery> sceneItem(newBB);
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 in(filePath, true);
423
424 serializable_ptr root = in.deserialize();
425
426 if (root)
427 {
428 std::map<std::string,serializable_ptr> rootObj;
429
430 if (root->get(rootObj))
431 {
432 std::map<std::string,serializable_ptr>::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 scenery_list::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> > scenery_list;
467 scenery_list objects;
468 };
469
470
471 scene::scene(const std::string& name) :
472 // pass through
473 impl(scene::scene_impl::retain(name), &scene::scene_impl::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 dc
495
496 /** vim: set ts=4 sw=4 tw=80: *************************************************/
497
This page took 0.057364 seconds and 4 git commands to generate.