]>
Dogcows Code - chaz/yoink/blob - src/Scene.cc
2 /*******************************************************************************
4 Copyright (c) 2009, Charles McGarvey
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
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.
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.
27 *******************************************************************************/
31 #include <Moof/Aabb.hh>
32 #include <Moof/Camera.hh>
33 #include <Moof/Entity.hh>
34 #include <Moof/Library.hh>
35 #include <Moof/Line.hh>
36 #include <Moof/Log.hh>
37 #include <Moof/Math.hh>
38 //#include <Moof/Octree.hh>
39 #include <Moof/Script.hh>
40 #include <Moof/Settings.hh>
42 #include "Character.hh"
47 struct Scene::Impl
: public Mf::Library
<Impl
>
49 struct Quad
: public Mf::Entity
59 Quad(const Mf::Vector3
* vertices
[4], const std::string
& texture
,
60 Tilemap::Index tileIndex
) :
66 for (int i
= 0; i
< 4; ++i
)
68 mVertices
[i
] = *vertices
[i
];
69 //for (int j = 0; j < 3; ++j, ++num)
71 //mVertices[num] = (*vertices[i])[j];
75 if (!mTilemap
.getTileCoords(tileIndex
, mTexCoords
))
77 Mf::logWarning
<< "no index " << tileIndex
<<
78 " in texture " << texture
<< std::endl
;
80 mTexCoords
[0] = mTexCoords
[1] =
81 mTexCoords
[3] = mTexCoords
[6] = 0.0;
82 mTexCoords
[2] = mTexCoords
[4] =
83 mTexCoords
[5] = mTexCoords
[7] = 1.0;
86 mAabb
.encloseVertices(mVertices
, 4);
87 mSphere
.point
= mAabb
.getCenter();
88 mSphere
.radius
= (mAabb
.min
- mSphere
.point
).length();
91 void setBlending(bool blending
)
101 void setSurface(Surface type
)
106 Surface
getSurface() const
111 void draw(Mf::Scalar alpha
= 0.0) const
116 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
122 glFogi(GL_FOG_MODE
, GL_LINEAR
);
125 //glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
128 glVertexPointer(3, GL_SCALAR
, 0, mVertices
[0].data());
129 glTexCoordPointer(2, GL_SCALAR
, 0, mTexCoords
);
131 glDrawArrays(GL_TRIANGLE_FAN
, 0, 4);
137 bool isVisible(const Mf::Frustum
& frustum
) const
139 return mSphere
.isVisible(frustum
);
143 Mf::Vector3 mVertices
[4];
144 Mf::Scalar mTexCoords
[8];
155 Mf::Matrix4 mTransform
;
156 std::string mTexture
;
158 //Mf::Octree<Quad>::Ptr mOctree;
159 std::list
< boost::shared_ptr
<Impl::Quad
> > mObjects
;
160 std::list
< Mf::Line
<2> > mLines
;
173 explicit Impl(const std::string
& name
) :
174 Mf::Library
<Impl
>(name
) {}
176 void importSceneBindings(Mf::Script
& script
)
178 script
.importFunction("SetBounds",
179 boost::bind(&Impl::setBounds
, this, _1
));
180 script
.importFunction("ResetTransform",
181 boost::bind(&Impl::resetTransform
, this, _1
));
182 script
.importFunction("Translate",
183 boost::bind(&Impl::translate
, this, _1
));
184 script
.importFunction("Scale",
185 boost::bind(&Impl::scale
, this, _1
));
186 script
.importFunction("Rotate",
187 boost::bind(&Impl::rotate
, this, _1
));
188 script
.importFunction("SetTexture",
189 boost::bind(&Impl::setTexture
, this, _1
));
190 script
.importFunction("DrawTilemap",
191 boost::bind(&Impl::drawTilemap
, this, _1
));
192 script
.importFunction("DrawTile",
193 boost::bind(&Impl::drawTile
, this, _1
));
196 Mf::settings
.get("detail", detail
);
197 script
.push(detail
); script
.set("detail");
199 script
.push(1); script
.set("LOW");
200 script
.push(2); script
.set("MEDIUM");
201 script
.push(3); script
.set("HIGH");
203 script
.push(X
); script
.set("X");
204 script
.push(Y
); script
.set("Y");
205 script
.push(Z
); script
.set("Z");
207 script
.push(Quad::LEFT
); script
.set("LEFT");
208 script
.push(Quad::RIGHT
); script
.set("RIGHT");
209 script
.push(Quad::TOP
); script
.set("TOP");
213 Mf::Script::Result
load(Mf::Script
& script
)
215 std::string filePath
= Scene::getPath(getName());
218 script
.push("the scene file could not be found");
219 return Mf::Script::FILE_ERROR
;
222 importSceneBindings(script
);
223 return script
.doFile(filePath
);
227 static int loadBox(Mf::Script
& script
, Mf::Aabb
<3>& aabb
)
229 script
[1].requireTable();
230 script
[2].requireTable();
233 for (int i
= 1; i
<= 2; ++i
)
235 for (int j
= 1; j
<= 3; ++j
)
237 script
[i
].pushField(j
);
241 script
[3].get(aabb
.min
[0]);
242 script
[4].get(aabb
.min
[1]);
243 script
[5].get(aabb
.min
[2]);
244 script
[6].get(aabb
.max
[0]);
245 script
[7].get(aabb
.max
[1]);
246 script
[8].get(aabb
.max
[2]);
251 int setBounds(Mf::Script
& script
)
253 int ret
= loadBox(script
, mBounds
);
254 //mOctree = Mf::Octree<Quad>::alloc(mBounds);
258 int resetTransform(Mf::Script
& script
)
260 mTransform
.identity();
264 int translate(Mf::Script
& script
)
268 script
[1].requireNumber().get(vec
[0]);
269 script
[2].requireNumber().get(vec
[1]);
270 script
[3].requireNumber().get(vec
[2]);
272 Mf::Matrix4 translation
;
273 cml::matrix_translation(translation
, vec
);
274 mTransform
= translation
* mTransform
;
279 int scale(Mf::Script
& script
)
281 if (script
.getSize() == 3)
284 script
[1].requireNumber().get(vec
[0]);
285 script
[2].requireNumber().get(vec
[1]);
286 script
[3].requireNumber().get(vec
[2]);
289 cml::matrix_scale(scaling
, vec
);
290 mTransform
= scaling
* mTransform
;
292 else if (script
.getSize() == 1)
294 Mf::Scalar value
= 1.0;
295 script
[1].requireNumber().get(value
);
298 cml::matrix_uniform_scale(scaling
, value
);
299 mTransform
= scaling
* mTransform
;
303 script
.getTop().throwError("wrong number of arguments");
309 int rotate(Mf::Script
& script
)
312 script
[1].requireNumber().get(index
);
315 script
[2].requireNumber().get(value
);
317 cml::matrix_rotate_about_world_axis(mTransform
, index
, cml::rad(value
));
322 int setTexture(Mf::Script
& script
)
324 script
[1].requireString().get(mTexture
);
328 int drawTilemap(Mf::Script
& script
)
330 Mf::Script::Slot table
= script
[1].requireTable();
331 Mf::Script::Slot top
= script
[-1];
337 table
.pushField("width");
341 nTiles
= table
.getLength();
342 if (nTiles
% width
!= 0) table
.throwError("invalid number of tiles");
344 if (width
== 0) table
.throwError("width field must not be zero");
345 height
= nTiles
/ width
;
347 Mf::Vector3 vertices
[height
+1][width
+1];
349 // the indices are stored upside-down in the scene file so that they are
350 // easier to edit as text, so we'll need to load them last row first
352 // do first row and first column of vertices
354 for (int w
= 0; w
<= width
; ++w
)
356 vertices
[height
][w
] = Mf::demote(mTransform
*
357 Mf::Vector4(w
, height
, 0.0, 1.0));
359 for (int h
= 0; h
< height
; ++h
)
361 vertices
[h
][0] = Mf::demote(mTransform
*
362 Mf::Vector4(0.0, h
, 0.0, 1.0));
366 for (int h
= height
- 1; h
>= 0; --h
)
368 for (int w
= 0; w
< width
; ++w
, ++i
)
375 Tilemap::Index index
;
380 vertices
[h
][wPlus1
] = Mf::demote(mTransform
*
381 Mf::Vector4(wPlus1
, h
, 0.0, 1.0));
383 if (index
== Tilemap::NO_TILE
) continue;
385 const Mf::Vector3
* corners
[4] = {
387 &vertices
[h
][wPlus1
],
388 &vertices
[hPlus1
][wPlus1
],
392 Quad
* quad
= new Quad(corners
, mTexture
, index
);
393 //quad->setSurface(surface);
395 boost::shared_ptr
<Quad
> quadPtr(quad
);
396 mObjects
.push_back(quadPtr
);
400 Quad::Surface surface
= Quad::NONE
;
402 table
.pushField("surface");
406 if (surface
!= Quad::NONE
)
408 // need a 2d line for collisions
409 // assuming the camera always looks directly to -z when the
410 // scene is built, simply demoting the vector again should
411 // project the points to the xy-plane
413 Mf::Vector2 bl
= Mf::demote(vertices
[0][0]);
414 Mf::Vector2 tr
= Mf::demote(vertices
[height
][width
]);
416 mLines
.push_back(Mf::Line
<2>(bl
, tr
));
417 Mf::logInfo("new line");
423 int drawTile(Mf::Script
& script
)
425 Mf::Script::Slot param
= script
[1];
426 Mf::Script::Slot top
= script
[-1];
428 Tilemap::Index index
= 0;
430 bool blending
= false;
439 param
.pushField("u_scale");
442 param
.pushField("blend");
445 param
.pushField("fog");
448 else if (param
.isNumber())
453 Mf::Vector3 vertices
[2][width
+1];
456 Mf::Scalar increment
= 1.0 / Mf::Scalar(width
);
458 for (int h
= 0; h
<= 1; ++h
)
461 for (int w
= 0; w
<= width
; ++w
, xf
+= increment
)
463 vertices
[h
][w
] = Mf::demote(mTransform
*
464 Mf::Vector4(xf
, Mf::Scalar(h
), 0.0, 1.0));
468 for (int w
= 0; w
< width
; ++w
)
472 const Mf::Vector3
* corners
[4] = {
474 &vertices
[0][wPlus1
],
475 &vertices
[1][wPlus1
],
479 Quad
* quad
= new Quad(corners
, mTexture
, index
);
480 quad
->setBlending(blending
);
483 boost::shared_ptr
<Quad
> quadPtr(quad
);
484 mObjects
.push_back(quadPtr
);
492 Scene::Scene(const std::string
& name
) :
494 mImpl(Scene::Impl::getInstance(name
)) {}
497 Mf::Script::Result
Scene::load(Mf::Script
& script
)
500 return mImpl
->load(script
);
504 void Scene::draw(Mf::Scalar alpha
) const
506 std::list
< boost::shared_ptr
<Impl::Quad
> >& objects
= mImpl
->mObjects
;
507 std::list
< boost::shared_ptr
<Impl::Quad
> >::const_iterator it
;
509 for (it
= objects
.begin(); it
!= objects
.end(); ++it
)
514 mImpl
->mBounds
.draw();
517 void Scene::drawIfVisible(Mf::Scalar alpha
, const Mf::Frustum
& frustum
) const
519 std::list
< boost::shared_ptr
<Impl::Quad
> >& objects
= mImpl
->mObjects
;
520 std::list
< boost::shared_ptr
<Impl::Quad
> >::const_iterator it
;
522 for (it
= objects
.begin(); it
!= objects
.end(); ++it
)
524 (*it
)->drawIfVisible(alpha
, frustum
);
527 std::list
< Mf::Line
<2> >& lines
= mImpl
->mLines
;
528 std::list
< Mf::Line
<2> >::const_iterator lit
;
530 for (lit
= lines
.begin(); lit
!= lines
.end(); ++lit
)
535 mImpl
->mBounds
.draw();
539 bool Scene::castRay(const Mf::Ray
<2>& ray
,
540 std::list
<Mf::Ray
<2>::Intersection
>& hits
) const
542 std::list
< Mf::Line
<2> >& lines
= mImpl
->mLines
;
543 std::list
< Mf::Line
<2> >::const_iterator it
;
545 for (it
= lines
.begin(); it
!= lines
.end(); ++it
)
547 Mf::Ray
<2>::Intersection hit
;
548 Mf::Scalar d
= (*it
).intersectRay(ray
, hit
);
557 return !hits
.empty();
561 bool Scene::checkForCollision(Character
& character
)
564 //std::list< boost::shared_ptr<Impl::Quad> > objects;
565 //std::list<Mf::Octree<Impl::Quad>::InsertableP> objects;
566 //mImpl->mOctree->getNearbyObjects(objects, character);
568 std::list
< boost::shared_ptr
<Impl::Quad
> >& objects
= mImpl
->mObjects
;
569 std::list
< boost::shared_ptr
<Impl::Quad
> >::const_iterator it
;
572 Mf::Sphere
<3> sphere
= character
.getSphere();
574 for (it
= objects
.begin(); it
!= objects
.end(); ++it
)
576 Impl::Quad::Surface type
= (*it
)->getSurface();
577 if (type
== Impl::Quad::NONE
) continue;
579 if (Mf::checkCollision(sphere
, (*it
)->getSphere()))
583 Mf::Vector2
impulse(0.0, 0.0);
584 Mf::Vector2 p
= character
.getState().momentum
;
586 Mf::State2 state
= character
.getState(1.0);
587 sphere
= character
.getSphere();
588 Mf::Scalar alpha
= 1.0;
589 while (Mf::checkCollision(sphere
, (*it
)->getSphere()))
592 state
= character
.getState(alpha
);
595 character
.setPosition(state
.position
);
599 //case Impl::Quad::TOP:
600 //if (p[1] < 0.0) impulse[1] = -p[1];
602 //case Impl::Quad::LEFT:
603 //if (p[0] > 0.0) impulse[0] = 1.5*-p[0];
605 //case Impl::Quad::RIGHT:
606 //if (p[0] < 0.0) impulse[0] = 1.5*-p[0];
610 //character.addImpulse(impulse);
616 Mf::logInfo
<< "collisions: " << collisions
<< std::endl
;
623 std::string
Scene::getPath(const std::string
& name
)
625 return Mf::Resource::getPath("scenes/" + name
+ ".lua");
629 /** vim: set ts=4 sw=4 tw=80: *************************************************/
This page took 0.060624 seconds and 4 git commands to generate.