]>
Dogcows Code - chaz/yoink/blob - src/Scene.cc
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
7 * Distributable under the terms and conditions of the 2-clause BSD license;
8 * see the file COPYING for a complete text of the license.
10 **************************************************************************/
14 #include <Moof/Aabb.hh>
15 #include <Moof/Camera.hh>
16 #include <Moof/Entity.hh>
17 #include <Moof/Manager.hh>
18 #include <Moof/Line.hh>
19 #include <Moof/Log.hh>
20 #include <Moof/Math.hh>
21 //#include <Moof/Octree.hh>
22 #include <Moof/Script.hh>
23 #include <Moof/Settings.hh>
24 #include <Moof/Texture.hh>
26 #include "Character.hh"
30 struct Scene::Impl
: public Mf::Manager
<Impl
>
32 struct Quad
: public Mf::Entity
42 Quad(const Mf::Vector3
* vertices
[4], const std::string
& texture
,
43 Mf::Texture::TileIndex tileIndex
) :
49 for (int i
= 0; i
< 4; ++i
)
51 mVertices
[i
] = *vertices
[i
];
52 //for (int j = 0; j < 3; ++j, ++num)
54 //mVertices[num] = (*vertices[i])[j];
58 if (!mTilemap
.getTileCoords(tileIndex
, mTexCoords
))
60 Mf::logWarning
<< "no index " << tileIndex
<<
61 " in texture " << texture
<< std::endl
;
63 mTexCoords
[0] = mTexCoords
[1] =
64 mTexCoords
[3] = mTexCoords
[6] = 0.0;
65 mTexCoords
[2] = mTexCoords
[4] =
66 mTexCoords
[5] = mTexCoords
[7] = 1.0;
69 mAabb
.encloseVertices(mVertices
, 4);
70 mSphere
.point
= mAabb
.getCenter();
71 mSphere
.radius
= (mAabb
.min
- mSphere
.point
).length();
74 void setBlending(bool blending
)
84 void setSurface(Surface type
)
89 Surface
getSurface() const
94 void draw(Mf::Scalar alpha
= 0.0) const
99 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
105 glFogi(GL_FOG_MODE
, GL_LINEAR
);
108 //glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
111 glVertexPointer(3, GL_SCALAR
, 0, mVertices
[0].data());
112 glTexCoordPointer(2, GL_SCALAR
, 0, mTexCoords
);
114 glDrawArrays(GL_TRIANGLE_FAN
, 0, 4);
120 bool isVisible(const Mf::Frustum
& frustum
) const
122 return mSphere
.isVisible(frustum
);
126 Mf::Vector3 mVertices
[4];
127 Mf::Scalar mTexCoords
[8];
129 Mf::Texture mTilemap
;
138 Mf::Matrix4 mTransform
;
139 std::string mTexture
;
141 //Mf::Octree<Quad>::Ptr mOctree;
142 std::list
< boost::shared_ptr
<Impl::Quad
> > mObjects
;
143 std::list
<Mf::Line2
> mLines
;
156 void init(const std::string
& name
) {}
159 void importSceneBindings(Mf::Settings
& settings
, Mf::Script
& script
)
161 script
.importFunction("SetBounds",
162 boost::bind(&Impl::setBounds
, this, _1
));
163 script
.importFunction("ResetTransform",
164 boost::bind(&Impl::resetTransform
, this, _1
));
165 script
.importFunction("Translate",
166 boost::bind(&Impl::translate
, this, _1
));
167 script
.importFunction("Scale",
168 boost::bind(&Impl::scale
, this, _1
));
169 script
.importFunction("Rotate",
170 boost::bind(&Impl::rotate
, this, _1
));
171 script
.importFunction("SetTexture",
172 boost::bind(&Impl::setTexture
, this, _1
));
173 script
.importFunction("DrawTilemap",
174 boost::bind(&Impl::drawTilemap
, this, _1
));
175 script
.importFunction("DrawTile",
176 boost::bind(&Impl::drawTile
, this, _1
));
179 settings
.get("detail", detail
);
180 script
.globals().setField("detail", detail
);
182 script
.globals().setField("LOW", 1);
183 script
.globals().setField("MEDIUM", 2);
184 script
.globals().setField("HIGH", 3);
186 script
.globals().setField("X", X
);
187 script
.globals().setField("Y", Y
);
188 script
.globals().setField("Z", Z
);
190 script
.globals().setField("LEFT", Quad::LEFT
);
191 script
.globals().setField("RIGHT", Quad::RIGHT
);
192 script
.globals().setField("TOP", Quad::TOP
);
196 Mf::Script::Result
load(Mf::Settings
& settings
, Mf::Script
& script
)
198 std::string
path(getName());
199 if (!Scene::getPath(path
))
201 script
.push("the scene file could not be found");
202 return Mf::Script::FILE_ERROR
;
205 importSceneBindings(settings
, script
);
206 return script
.doFile(path
);
210 static int loadBox(Mf::Script
& script
, Mf::Aabb3
& aabb
)
212 script
[1].requireTable();
213 script
[2].requireTable();
215 script
[1].pushField(1).get(aabb
.min
[0]);
216 script
[1].pushField(2).get(aabb
.min
[1]);
217 script
[1].pushField(3).get(aabb
.min
[2]);
218 script
[2].pushField(1).get(aabb
.max
[0]);
219 script
[2].pushField(2).get(aabb
.max
[1]);
220 script
[2].pushField(3).get(aabb
.max
[2]);
225 int setBounds(Mf::Script
& script
)
227 int ret
= loadBox(script
, mBounds
);
228 //mOctree = Mf::Octree<Quad>::alloc(mBounds);
232 int resetTransform(Mf::Script
& script
)
234 mTransform
.identity();
238 int translate(Mf::Script
& script
)
241 script
[1].requireNumber().get(vec
[0]);
242 script
[2].requireNumber().get(vec
[1]);
243 script
[3].requireNumber().get(vec
[2]);
245 Mf::Matrix4 translation
;
246 cml::matrix_translation(translation
, vec
);
247 mTransform
= translation
* mTransform
;
252 int scale(Mf::Script
& script
)
254 int size
= script
.stackSize();
258 Mf::Scalar value
= 1.0;
259 script
[1].requireNumber().get(value
);
262 cml::matrix_uniform_scale(scaling
, value
);
263 mTransform
= scaling
* mTransform
;
268 script
[1].requireNumber().get(vec
[0]);
269 script
[2].requireNumber().get(vec
[1]);
270 script
[3].requireNumber().get(vec
[2]);
273 cml::matrix_scale(scaling
, vec
);
274 mTransform
= scaling
* mTransform
;
278 script
.top().raise("wrong number of arguments");
284 int rotate(Mf::Script
& script
)
287 script
[1].requireNumber().get(index
);
290 script
[2].requireNumber().get(value
);
292 cml::matrix_rotate_about_world_axis(mTransform
,
293 index
, cml::rad(value
));
298 int setTexture(Mf::Script
& script
)
300 script
[1].requireString().get(mTexture
);
304 int drawTilemap(Mf::Script
& script
)
306 Mf::Script::Slot table
= script
[1].requireTable();
309 table
.get(width
, "width");
311 int nTiles
= table
.length();
312 if (nTiles
% width
!= 0)
314 table
.raise("invalid number of tiles");
317 if (width
== 0) table
.raise("width field must not be zero");
318 int height
= nTiles
/ width
;
320 Mf::Vector3 vertices
[height
+1][width
+1];
322 // the indices are stored upside-down in the scene file so that
323 // they are easier to edit as text, so we'll need to load them last
326 // do first row and first column of vertices
328 for (int w
= 0; w
<= width
; ++w
)
330 vertices
[height
][w
] = Mf::demote(mTransform
*
331 Mf::Vector4(w
, height
, 0.0, 1.0));
333 for (int h
= 0; h
< height
; ++h
)
335 vertices
[h
][0] = Mf::demote(mTransform
*
336 Mf::Vector4(0.0, h
, 0.0, 1.0));
340 for (int h
= height
- 1; h
>= 0; --h
)
342 for (int w
= 0; w
< width
; ++w
, ++i
)
347 Mf::Texture::TileIndex index
;
350 vertices
[h
][wPlus1
] = Mf::demote(mTransform
*
351 Mf::Vector4(wPlus1
, h
, 0.0, 1.0));
353 if (index
== Mf::Texture::NO_TILE
) continue;
355 const Mf::Vector3
* corners
[4] = {
357 &vertices
[h
][wPlus1
],
358 &vertices
[hPlus1
][wPlus1
],
362 Quad
* quad
= new Quad(corners
, mTexture
, index
);
363 //quad->setSurface(surface);
365 boost::shared_ptr
<Quad
> quadPtr(quad
);
366 mObjects
.push_back(quadPtr
);
370 Quad::Surface surface
= Quad::NONE
;
371 table
.get(surface
, "surface");
373 if (surface
!= Quad::NONE
)
375 // need a 2d line for collisions
376 // assuming the camera always looks directly to -z when the
377 // scene is built, simply demoting the vector again should
378 // project the points to the xy-plane
380 Mf::Vector2 bl
= Mf::demote(vertices
[0][0]);
381 Mf::Vector2 tr
= Mf::demote(vertices
[height
][width
]);
383 mLines
.push_back(Mf::Line
<2>(bl
, tr
));
389 int drawTile(Mf::Script
& script
)
391 Mf::Script::Slot param
= script
[1];
392 Mf::Script::Slot top
= script
[-1];
394 Mf::Texture::TileIndex index
= 0;
396 bool blending
= false;
402 param
.get(width
, "u_scale");
403 param
.get(blending
, "blend");
404 param
.get(fog
, "fog");
406 else if (param
.isNumber())
411 Mf::Vector3 vertices
[2][width
+1];
414 Mf::Scalar increment
= SCALAR(1.0) / Mf::Scalar(width
);
416 for (int h
= 0; h
<= 1; ++h
)
419 for (int w
= 0; w
<= width
; ++w
, xf
+= increment
)
421 vertices
[h
][w
] = Mf::demote(mTransform
*
422 Mf::Vector4(xf
, Mf::Scalar(h
), 0.0, 1.0));
426 for (int w
= 0; w
< width
; ++w
)
430 const Mf::Vector3
* corners
[4] = {
432 &vertices
[0][wPlus1
],
433 &vertices
[1][wPlus1
],
437 Quad
* quad
= new Quad(corners
, mTexture
, index
);
438 quad
->setBlending(blending
);
441 boost::shared_ptr
<Quad
> quadPtr(quad
);
442 mObjects
.push_back(quadPtr
);
450 Scene::Scene(const std::string
& name
) :
452 mImpl(Scene::Impl::getInstance(name
)) {}
455 Mf::Script::Result
Scene::load(Mf::Settings
& settings
, Mf::Script
& script
)
458 return mImpl
->load(settings
, script
);
462 void Scene::draw(Mf::Scalar alpha
) const
464 std::list
< boost::shared_ptr
<Impl::Quad
> >& objects
= mImpl
->mObjects
;
465 std::list
< boost::shared_ptr
<Impl::Quad
> >::const_iterator it
;
467 for (it
= objects
.begin(); it
!= objects
.end(); ++it
)
472 mImpl
->mBounds
.draw();
475 void Scene::drawIfVisible(Mf::Scalar alpha
,
476 const Mf::Frustum
& frustum
) const
478 std::list
< boost::shared_ptr
<Impl::Quad
> >& objects
= mImpl
->mObjects
;
479 std::list
< boost::shared_ptr
<Impl::Quad
> >::const_iterator it
;
481 for (it
= objects
.begin(); it
!= objects
.end(); ++it
)
483 (*it
)->drawIfVisible(alpha
, frustum
);
486 std::list
< Mf::Line
<2> >& lines
= mImpl
->mLines
;
487 std::list
< Mf::Line
<2> >::const_iterator lit
;
489 for (lit
= lines
.begin(); lit
!= lines
.end(); ++lit
)
494 mImpl
->mBounds
.draw();
498 bool Scene::castRay(const Mf::Ray
<2>& ray
,
499 std::list
<Mf::Ray
<2>::Contact
>& hits
) const
501 std::list
< Mf::Line
<2> >& lines
= mImpl
->mLines
;
502 std::list
< Mf::Line
<2> >::const_iterator it
;
504 for (it
= lines
.begin(); it
!= lines
.end(); ++it
)
506 Mf::Ray
<2>::Contact hit
;
507 Mf::Scalar d
= (*it
).intersectRay(ray
, hit
);
516 return !hits
.empty();
520 bool Scene::checkForCollision(Character
& character
)
523 //std::list< boost::shared_ptr<Impl::Quad> > objects;
524 //std::list<Mf::Octree<Impl::Quad>::InsertableP> objects;
525 //mImpl->mOctree->getNearbyObjects(objects, character);
527 std::list
< boost::shared_ptr
<Impl::Quad
> >& objects
= mImpl
->mObjects
;
528 std::list
< boost::shared_ptr
<Impl::Quad
> >::const_iterator it
;
531 Mf::Sphere
<3> sphere
= character
.getSphere();
533 for (it
= objects
.begin(); it
!= objects
.end(); ++it
)
535 Impl::Quad::Surface type
= (*it
)->getSurface();
536 if (type
== Impl::Quad::NONE
) continue;
538 if (Mf::checkCollision(sphere
, (*it
)->getSphere()))
542 Mf::Vector2
impulse(0.0, 0.0);
543 Mf::Vector2 p
= character
.getState().momentum
;
545 Mf::State2 state
= character
.getState(1.0);
546 sphere
= character
.getSphere();
547 Mf::Scalar alpha
= 1.0;
548 while (Mf::checkCollision(sphere
, (*it
)->getSphere()))
551 state
= character
.getState(alpha
);
554 character
.setPosition(state
.position
);
558 //case Impl::Quad::TOP:
559 //if (p[1] < 0.0) impulse[1] = -p[1];
561 //case Impl::Quad::LEFT:
562 //if (p[0] > 0.0) impulse[0] = 1.5*-p[0];
564 //case Impl::Quad::RIGHT:
565 //if (p[0] < 0.0) impulse[0] = 1.5*-p[0];
569 //character.addImpulse(impulse);
575 Mf::logInfo
<< "collisions: " << collisions
<< std::endl
;
582 bool Scene::getPath(std::string
& name
)
584 return Mf::Resource::getPath(name
, "scenes/", "lua");
This page took 0.060948 seconds and 4 git commands to generate.