]> Dogcows Code - chaz/yoink/blob - src/Moof/Scene.cc
b3313124d22100bb4e59871ca8d4e3070d290987
[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 <map>
30 #include <vector>
31
32 #include "Aabb.hh"
33 #include "Camera.hh"
34 #include "Entity.hh"
35 #include "Log.hh"
36 #include "Math.hh"
37 #include "Scene.hh"
38 #include "Script.hh"
39 #include "Settings.hh"
40 #include "Tilemap.hh"
41
42
43 namespace Mf {
44
45
46 static std::string getPath(const std::string& name)
47 {
48 return Resource::getPath("scenes/" + name + ".lua");
49 }
50
51
52 struct Meh
53 {
54 Matrix4 transform;
55 std::string texture;
56
57 OctreeP octree;
58
59 enum AXIS
60 {
61 X = 0,
62 Y = 1,
63 Z = 2
64 };
65
66 Meh()
67 {
68 octree = Octree::alloc(Aabb());
69 }
70
71 static int loadBox(Script& script, Aabb& aabb)
72 {
73 Script::Value table[] = {script[1], script[2]};
74
75 if (!table[0].isTable() || !table[1].isTable())
76 {
77 logWarning("wrong arguments to setPlayfieldBounds; ignoring...");
78 return 0;
79 }
80
81 for (int i = 0; i <= 1; ++i)
82 {
83 for (int j = 1; j <= 3; ++j)
84 {
85 script.push((long)j);
86 table[i].pushField();
87 }
88 }
89
90 script[3].get(aabb.min[0]);
91 script[4].get(aabb.min[1]);
92 script[5].get(aabb.min[2]);
93 script[6].get(aabb.max[0]);
94 script[7].get(aabb.max[1]);
95 script[8].get(aabb.max[2]);
96
97 return 0;
98 }
99
100 int setPlayfieldBounds(Script& script)
101 {
102 Aabb bounds;
103 return loadBox(script, bounds);
104 }
105
106 int setMaximumBounds(Script& script)
107 {
108 Aabb bounds;
109 int ret = loadBox(script, bounds);
110 octree = Octree::alloc(bounds);
111 return ret;
112 }
113
114 int resetTransform(Script& script)
115 {
116 transform.identity();
117 return 0;
118 }
119
120 int translate(Script& script)
121 {
122 Script::Value x = script[1].requireNumber();
123 Script::Value y = script[2].requireNumber();
124 Script::Value z = script[3].requireNumber();
125
126 Vector3 vec;
127 x.get(vec[0]);
128 y.get(vec[1]);
129 z.get(vec[2]);
130
131 Matrix4 translation;
132 cml::matrix_translation(translation, vec);
133 transform = translation * transform;
134
135 return 0;
136 }
137
138 int scale(Script& script)
139 {
140 if (script.getSize() == 3)
141 {
142 Vector3 vec;
143 script[1].requireNumber().get(vec[0]);
144 script[2].requireNumber().get(vec[1]);
145 script[3].requireNumber().get(vec[2]);
146
147 Matrix4 scaling;
148 cml::matrix_scale(scaling, vec);
149 transform = scaling * transform;
150 }
151 else if (script.getSize() == 1)
152 {
153 Scalar value = 1.0;
154 script[1].requireNumber().get(value);
155
156 Matrix4 scaling;
157 cml::matrix_uniform_scale(scaling, value);
158 transform = scaling * transform;
159 }
160 else
161 {
162 script.getTop().throwError("wrong number of arguments");
163 }
164
165 return 0;
166 }
167
168 int rotate(Script& script)
169 {
170 Script::Value axis = script[1].requireString();
171 Script::Value angle = script[2].requireNumber();
172
173 size_t index = 0;
174 axis.get(index);
175
176 Scalar value;
177 angle.get(value);
178
179 cml::matrix_rotate_about_world_axis(transform, index, cml::rad(value));
180
181 return 0;
182 }
183
184 int setTexture(Script& script)
185 {
186 Script::Value name = script[1].requireString();
187
188 name.get(texture);
189
190 return 0;
191 }
192
193 int makeTilemap(Script& script)
194 {
195 Script::Value table = script[1].requireTable();
196 Script::Value top = script[-1];
197
198 long width = 1;
199 long height = 1;
200
201 table.pushField("width");
202 top.get(width);
203
204 long nTiles = 0;
205
206 table.pushField("tiles");
207 Script::Value tiles = script.getTop();
208 nTiles = tiles.getLength();
209
210 if (nTiles % width != 0) table.throwError("invalid number of tiles");
211
212 std::vector< std::vector<Tilemap::Index> > indices;
213
214 int i, w, h;
215
216 height = nTiles / width;
217 indices.resize(height);
218
219 // the indices are stored upside-down in the scene file so that they
220 // are easier to edit as text, so we'll need to load them last row
221 // first
222
223 i = 1;
224 for (h = height - 1; h >= 0; --h)
225 {
226 std::vector<Tilemap::Index> row;
227
228 for (w = 0; w < width; ++w, ++i)
229 {
230 script.checkStack(2);
231 script.push(long(i));
232 tiles.pushField();
233
234 long index;
235 top.get(index);
236
237 row.push_back(Tilemap::Index(index));
238 }
239
240 indices[h] = row;
241 }
242
243 Vector4 vertices[height+1][width+1];
244
245 Matrix4 transposedTransform = transform;
246 transposedTransform.transpose();
247
248 for (int h = 0; h <= height; ++h)
249 {
250 for (int w = 0; w <= width; ++w)
251 {
252 vertices[h][w] = Vector4(Scalar(w), Scalar(h), 0.0, 1.0) *
253 transposedTransform;
254 }
255 }
256
257 for (int h = 0; h < height; ++h)
258 {
259 for (int w = 0; w < width; ++w)
260 {
261 if (indices[h][w] == Tilemap::NO_TILE) continue;
262
263 Vector3 quadVertices[4];
264
265 demoteVector(quadVertices[0], vertices[h][w]);
266 demoteVector(quadVertices[1], vertices[h][w+1]);
267 demoteVector(quadVertices[2], vertices[h+1][w+1]);
268 demoteVector(quadVertices[3], vertices[h+1][w]);
269
270 Quad* quad = new Quad(quadVertices, texture, indices[h][w]);
271 boost::shared_ptr<Quad> quadPtr(quad);
272
273 octree->insert(quadPtr);
274 }
275 }
276
277 return 0;
278 }
279
280 int makeBillboard(Script& script)
281 {
282 Script::Value table = script[1];
283 Script::Value top = script[-1];
284
285 long index = 0;
286 long width = 1;
287 bool blending = false;
288 bool fog = false;
289
290 if (table.isTable())
291 {
292 table.pushField("tile");
293 top.get(index);
294
295 table.pushField("u_scale");
296 top.get(width);
297
298 table.pushField("blend");
299 top.get(blending);
300
301 table.pushField("fog");
302 top.get(fog);
303 }
304
305 Vector4 vertices[2][width+1];
306
307 Matrix4 transposedTransform = transform;
308 transposedTransform.transpose();
309
310 Scalar xf;
311 Scalar increment = 1.0 / Scalar(width);
312
313 for (int h = 0; h <= 1; ++h)
314 {
315 xf = 0.0;
316 for (int w = 0; w <= width; ++w, xf += increment)
317 {
318 vertices[h][w] = Vector4(xf, Scalar(h), 0.0, 1.0) *
319 transposedTransform;
320 }
321 }
322
323 for (int w = 0; w < width; ++w)
324 {
325 Vector3 quadVertices[4];
326
327 demoteVector(quadVertices[0], vertices[0][w]);
328 demoteVector(quadVertices[1], vertices[0][w+1]);
329 demoteVector(quadVertices[2], vertices[1][w+1]);
330 demoteVector(quadVertices[3], vertices[1][w]);
331
332 Quad* quad = new Quad(quadVertices, texture, Tilemap::Index(index));
333 quad->setBlending(blending);
334 quad->setFog(fog);
335
336 boost::shared_ptr<Quad> quadPtr(quad);
337
338 octree->insert(quadPtr);
339 }
340
341 return 0;
342 }
343 };
344
345
346 static void importSceneBindings(Script& script, Meh& scene)
347 {
348 script.importFunction("SetPlayfieldBounds",
349 boost::bind(&Meh::setPlayfieldBounds, &scene, _1));
350 script.importFunction("SetMaximumBounds",
351 boost::bind(&Meh::setMaximumBounds, &scene, _1));
352 script.importFunction("ResetTransform",
353 boost::bind(&Meh::resetTransform, &scene, _1));
354 script.importFunction("Translate",
355 boost::bind(&Meh::translate, &scene, _1));
356 script.importFunction("Scale",
357 boost::bind(&Meh::scale, &scene, _1));
358 script.importFunction("Rotate",
359 boost::bind(&Meh::rotate, &scene, _1));
360 script.importFunction("SetTexture",
361 boost::bind(&Meh::setTexture, &scene, _1));
362 script.importFunction("MakeTilemap",
363 boost::bind(&Meh::makeTilemap, &scene, _1));
364 script.importFunction("MakeBillboard",
365 boost::bind(&Meh::makeBillboard, &scene, _1));
366
367 long detail = 3;
368 Settings::getInstance().get("detail", detail);
369 script.push(detail);
370 script.set("detail");
371
372 script.push(Quad::LEFT);
373 script.set("LEFT");
374 script.push(Quad::RIGHT);
375 script.set("RIGHT");
376 script.push(Quad::TOP);
377 script.set("TOP");
378
379 script.push(Meh::X);
380 script.set("X");
381 script.push(Meh::Y);
382 script.set("Y");
383 script.push(Meh::Z);
384 script.set("Z");
385 }
386
387
388 OctreeP loadScene(const std::string& name)
389 {
390 std::string filePath = getPath(name);
391
392 Meh cool;
393
394 Script script;
395 script.importStandardLibraries();
396 importLogScript(script);
397 importSceneBindings(script, cool);
398
399 if (script.doFile(filePath) != Script::SUCCESS)
400 {
401 std::string str;
402 script[-1].get(str);
403 logScript("%s", str.c_str());
404 }
405
406 cool.octree->sort();
407 return cool.octree;
408 }
409
410
411 } // namespace Mf
412
413 /** vim: set ts=4 sw=4 tw=80: *************************************************/
414
This page took 0.049924 seconds and 3 git commands to generate.