]>
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::Line
<2> > 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
.push(detail
); script
.set("detail");
182 script
.push(1); script
.set("LOW");
183 script
.push(2); script
.set("MEDIUM");
184 script
.push(3); script
.set("HIGH");
186 script
.push(X
); script
.set("X");
187 script
.push(Y
); script
.set("Y");
188 script
.push(Z
); script
.set("Z");
190 script
.push(Quad::LEFT
); script
.set("LEFT");
191 script
.push(Quad::RIGHT
); script
.set("RIGHT");
192 script
.push(Quad::TOP
); script
.set("TOP");
196 Mf::Script::Result
load(Mf::Settings
& settings
, Mf::Script
& script
)
198 std::string filePath
= Scene::getPath(getName());
201 script
.push("the scene file could not be found");
202 return Mf::Script::FILE_ERROR
;
205 importSceneBindings(settings
, script
);
206 return script
.doFile(filePath
);
210 static int loadBox(Mf::Script
& script
, Mf::Aabb
<3>& aabb
)
212 script
[1].requireTable();
213 script
[2].requireTable();
216 for (int i
= 1; i
<= 2; ++i
)
218 for (int j
= 1; j
<= 3; ++j
)
220 script
[i
].pushField(j
);
224 script
[3].get(aabb
.min
[0]);
225 script
[4].get(aabb
.min
[1]);
226 script
[5].get(aabb
.min
[2]);
227 script
[6].get(aabb
.max
[0]);
228 script
[7].get(aabb
.max
[1]);
229 script
[8].get(aabb
.max
[2]);
234 int setBounds(Mf::Script
& script
)
236 int ret
= loadBox(script
, mBounds
);
237 //mOctree = Mf::Octree<Quad>::alloc(mBounds);
241 int resetTransform(Mf::Script
& script
)
243 mTransform
.identity();
247 int translate(Mf::Script
& script
)
251 script
[1].requireNumber().get(vec
[0]);
252 script
[2].requireNumber().get(vec
[1]);
253 script
[3].requireNumber().get(vec
[2]);
255 Mf::Matrix4 translation
;
256 cml::matrix_translation(translation
, vec
);
257 mTransform
= translation
* mTransform
;
262 int scale(Mf::Script
& script
)
264 if (script
.getSize() == 3)
267 script
[1].requireNumber().get(vec
[0]);
268 script
[2].requireNumber().get(vec
[1]);
269 script
[3].requireNumber().get(vec
[2]);
272 cml::matrix_scale(scaling
, vec
);
273 mTransform
= scaling
* mTransform
;
275 else if (script
.getSize() == 1)
277 Mf::Scalar value
= 1.0;
278 script
[1].requireNumber().get(value
);
281 cml::matrix_uniform_scale(scaling
, value
);
282 mTransform
= scaling
* mTransform
;
286 script
.getTop().throwError("wrong number of arguments");
292 int rotate(Mf::Script
& script
)
295 script
[1].requireNumber().get(index
);
298 script
[2].requireNumber().get(value
);
300 cml::matrix_rotate_about_world_axis(mTransform
,
301 index
, cml::rad(value
));
306 int setTexture(Mf::Script
& script
)
308 script
[1].requireString().get(mTexture
);
312 int drawTilemap(Mf::Script
& script
)
314 Mf::Script::Slot table
= script
[1].requireTable();
315 Mf::Script::Slot top
= script
[-1];
321 table
.pushField("width");
325 nTiles
= table
.getLength();
326 if (nTiles
% width
!= 0)
328 table
.throwError("invalid number of tiles");
331 if (width
== 0) table
.throwError("width field must not be zero");
332 height
= nTiles
/ width
;
334 Mf::Vector3 vertices
[height
+1][width
+1];
336 // the indices are stored upside-down in the scene file so that
337 // they are easier to edit as text, so we'll need to load them last
340 // do first row and first column of vertices
342 for (int w
= 0; w
<= width
; ++w
)
344 vertices
[height
][w
] = Mf::demote(mTransform
*
345 Mf::Vector4(w
, height
, 0.0, 1.0));
347 for (int h
= 0; h
< height
; ++h
)
349 vertices
[h
][0] = Mf::demote(mTransform
*
350 Mf::Vector4(0.0, h
, 0.0, 1.0));
354 for (int h
= height
- 1; h
>= 0; --h
)
356 for (int w
= 0; w
< width
; ++w
, ++i
)
363 Mf::Texture::TileIndex index
;
368 vertices
[h
][wPlus1
] = Mf::demote(mTransform
*
369 Mf::Vector4(wPlus1
, h
, 0.0, 1.0));
371 if (index
== Mf::Texture::NO_TILE
) continue;
373 const Mf::Vector3
* corners
[4] = {
375 &vertices
[h
][wPlus1
],
376 &vertices
[hPlus1
][wPlus1
],
380 Quad
* quad
= new Quad(corners
, mTexture
, index
);
381 //quad->setSurface(surface);
383 boost::shared_ptr
<Quad
> quadPtr(quad
);
384 mObjects
.push_back(quadPtr
);
388 Quad::Surface surface
= Quad::NONE
;
390 table
.pushField("surface");
394 if (surface
!= Quad::NONE
)
396 // need a 2d line for collisions
397 // assuming the camera always looks directly to -z when the
398 // scene is built, simply demoting the vector again should
399 // project the points to the xy-plane
401 Mf::Vector2 bl
= Mf::demote(vertices
[0][0]);
402 Mf::Vector2 tr
= Mf::demote(vertices
[height
][width
]);
404 mLines
.push_back(Mf::Line
<2>(bl
, tr
));
405 Mf::logInfo("new line");
411 int drawTile(Mf::Script
& script
)
413 Mf::Script::Slot param
= script
[1];
414 Mf::Script::Slot top
= script
[-1];
416 Mf::Texture::TileIndex index
= 0;
418 bool blending
= false;
427 param
.pushField("u_scale");
430 param
.pushField("blend");
433 param
.pushField("fog");
436 else if (param
.isNumber())
441 Mf::Vector3 vertices
[2][width
+1];
444 Mf::Scalar increment
= 1.0 / Mf::Scalar(width
);
446 for (int h
= 0; h
<= 1; ++h
)
449 for (int w
= 0; w
<= width
; ++w
, xf
+= increment
)
451 vertices
[h
][w
] = Mf::demote(mTransform
*
452 Mf::Vector4(xf
, Mf::Scalar(h
), 0.0, 1.0));
456 for (int w
= 0; w
< width
; ++w
)
460 const Mf::Vector3
* corners
[4] = {
462 &vertices
[0][wPlus1
],
463 &vertices
[1][wPlus1
],
467 Quad
* quad
= new Quad(corners
, mTexture
, index
);
468 quad
->setBlending(blending
);
471 boost::shared_ptr
<Quad
> quadPtr(quad
);
472 mObjects
.push_back(quadPtr
);
480 Scene::Scene(const std::string
& name
) :
482 mImpl(Scene::Impl::getInstance(name
)) {}
485 Mf::Script::Result
Scene::load(Mf::Settings
& settings
, Mf::Script
& script
)
488 return mImpl
->load(settings
, script
);
492 void Scene::draw(Mf::Scalar alpha
) const
494 std::list
< boost::shared_ptr
<Impl::Quad
> >& objects
= mImpl
->mObjects
;
495 std::list
< boost::shared_ptr
<Impl::Quad
> >::const_iterator it
;
497 for (it
= objects
.begin(); it
!= objects
.end(); ++it
)
502 mImpl
->mBounds
.draw();
505 void Scene::drawIfVisible(Mf::Scalar alpha
,
506 const Mf::Frustum
& frustum
) const
508 std::list
< boost::shared_ptr
<Impl::Quad
> >& objects
= mImpl
->mObjects
;
509 std::list
< boost::shared_ptr
<Impl::Quad
> >::const_iterator it
;
511 for (it
= objects
.begin(); it
!= objects
.end(); ++it
)
513 (*it
)->drawIfVisible(alpha
, frustum
);
516 std::list
< Mf::Line
<2> >& lines
= mImpl
->mLines
;
517 std::list
< Mf::Line
<2> >::const_iterator lit
;
519 for (lit
= lines
.begin(); lit
!= lines
.end(); ++lit
)
524 mImpl
->mBounds
.draw();
528 bool Scene::castRay(const Mf::Ray
<2>& ray
,
529 std::list
<Mf::Ray
<2>::Contact
>& hits
) const
531 std::list
< Mf::Line
<2> >& lines
= mImpl
->mLines
;
532 std::list
< Mf::Line
<2> >::const_iterator it
;
534 for (it
= lines
.begin(); it
!= lines
.end(); ++it
)
536 Mf::Ray
<2>::Contact hit
;
537 Mf::Scalar d
= (*it
).intersectRay(ray
, hit
);
546 return !hits
.empty();
550 bool Scene::checkForCollision(Character
& character
)
553 //std::list< boost::shared_ptr<Impl::Quad> > objects;
554 //std::list<Mf::Octree<Impl::Quad>::InsertableP> objects;
555 //mImpl->mOctree->getNearbyObjects(objects, character);
557 std::list
< boost::shared_ptr
<Impl::Quad
> >& objects
= mImpl
->mObjects
;
558 std::list
< boost::shared_ptr
<Impl::Quad
> >::const_iterator it
;
561 Mf::Sphere
<3> sphere
= character
.getSphere();
563 for (it
= objects
.begin(); it
!= objects
.end(); ++it
)
565 Impl::Quad::Surface type
= (*it
)->getSurface();
566 if (type
== Impl::Quad::NONE
) continue;
568 if (Mf::checkCollision(sphere
, (*it
)->getSphere()))
572 Mf::Vector2
impulse(0.0, 0.0);
573 Mf::Vector2 p
= character
.getState().momentum
;
575 Mf::State2 state
= character
.getState(1.0);
576 sphere
= character
.getSphere();
577 Mf::Scalar alpha
= 1.0;
578 while (Mf::checkCollision(sphere
, (*it
)->getSphere()))
581 state
= character
.getState(alpha
);
584 character
.setPosition(state
.position
);
588 //case Impl::Quad::TOP:
589 //if (p[1] < 0.0) impulse[1] = -p[1];
591 //case Impl::Quad::LEFT:
592 //if (p[0] > 0.0) impulse[0] = 1.5*-p[0];
594 //case Impl::Quad::RIGHT:
595 //if (p[0] < 0.0) impulse[0] = 1.5*-p[0];
599 //character.addImpulse(impulse);
605 Mf::logInfo
<< "collisions: " << collisions
<< std::endl
;
612 std::string
Scene::getPath(const std::string
& name
)
614 return Mf::Resource::getPath("scenes/" + name
+ ".lua");
This page took 0.059947 seconds and 4 git commands to generate.