]>
Dogcows Code - chaz/yoink/blob - src/Scene.cc
918ff5250b843c8c8b0020b3935ab848e07cf4ae
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
.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
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::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 int size
= script
.getSize();
268 Mf::Scalar value
= 1.0;
269 script
[1].requireNumber().get(value
);
272 cml::matrix_uniform_scale(scaling
, value
);
273 mTransform
= scaling
* mTransform
;
278 script
[1].requireNumber().get(vec
[0]);
279 script
[2].requireNumber().get(vec
[1]);
280 script
[3].requireNumber().get(vec
[2]);
283 cml::matrix_scale(scaling
, vec
);
284 mTransform
= scaling
* mTransform
;
288 script
.getTop().throwError("wrong number of arguments");
294 int rotate(Mf::Script
& script
)
297 script
[1].requireNumber().get(index
);
300 script
[2].requireNumber().get(value
);
302 cml::matrix_rotate_about_world_axis(mTransform
,
303 index
, cml::rad(value
));
308 int setTexture(Mf::Script
& script
)
310 script
[1].requireString().get(mTexture
);
314 int drawTilemap(Mf::Script
& script
)
316 Mf::Script::Slot table
= script
[1].requireTable();
322 table
.get(width
, "width");
324 nTiles
= table
.getLength();
325 if (nTiles
% width
!= 0)
327 table
.throwError("invalid number of tiles");
330 if (width
== 0) table
.throwError("width field must not be zero");
331 height
= nTiles
/ width
;
333 Mf::Vector3 vertices
[height
+1][width
+1];
335 // the indices are stored upside-down in the scene file so that
336 // they are easier to edit as text, so we'll need to load them last
339 // do first row and first column of vertices
341 for (int w
= 0; w
<= width
; ++w
)
343 vertices
[height
][w
] = Mf::demote(mTransform
*
344 Mf::Vector4(w
, height
, 0.0, 1.0));
346 for (int h
= 0; h
< height
; ++h
)
348 vertices
[h
][0] = Mf::demote(mTransform
*
349 Mf::Vector4(0.0, h
, 0.0, 1.0));
353 for (int h
= height
- 1; h
>= 0; --h
)
355 for (int w
= 0; w
< width
; ++w
, ++i
)
360 Mf::Texture::TileIndex index
;
363 vertices
[h
][wPlus1
] = Mf::demote(mTransform
*
364 Mf::Vector4(wPlus1
, h
, 0.0, 1.0));
366 if (index
== Mf::Texture::NO_TILE
) continue;
368 const Mf::Vector3
* corners
[4] = {
370 &vertices
[h
][wPlus1
],
371 &vertices
[hPlus1
][wPlus1
],
375 Quad
* quad
= new Quad(corners
, mTexture
, index
);
376 //quad->setSurface(surface);
378 boost::shared_ptr
<Quad
> quadPtr(quad
);
379 mObjects
.push_back(quadPtr
);
383 Quad::Surface surface
= Quad::NONE
;
384 table
.get(surface
, "surface");
386 if (surface
!= Quad::NONE
)
388 // need a 2d line for collisions
389 // assuming the camera always looks directly to -z when the
390 // scene is built, simply demoting the vector again should
391 // project the points to the xy-plane
393 Mf::Vector2 bl
= Mf::demote(vertices
[0][0]);
394 Mf::Vector2 tr
= Mf::demote(vertices
[height
][width
]);
396 mLines
.push_back(Mf::Line
<2>(bl
, tr
));
402 int drawTile(Mf::Script
& script
)
404 Mf::Script::Slot param
= script
[1];
405 Mf::Script::Slot top
= script
[-1];
407 Mf::Texture::TileIndex index
= 0;
409 bool blending
= false;
415 param
.get(width
, "u_scale");
416 param
.get(blending
, "blend");
417 param
.get(fog
, "fog");
419 else if (param
.isNumber())
424 Mf::Vector3 vertices
[2][width
+1];
427 Mf::Scalar increment
= SCALAR(1.0) / Mf::Scalar(width
);
429 for (int h
= 0; h
<= 1; ++h
)
432 for (int w
= 0; w
<= width
; ++w
, xf
+= increment
)
434 vertices
[h
][w
] = Mf::demote(mTransform
*
435 Mf::Vector4(xf
, Mf::Scalar(h
), 0.0, 1.0));
439 for (int w
= 0; w
< width
; ++w
)
443 const Mf::Vector3
* corners
[4] = {
445 &vertices
[0][wPlus1
],
446 &vertices
[1][wPlus1
],
450 Quad
* quad
= new Quad(corners
, mTexture
, index
);
451 quad
->setBlending(blending
);
454 boost::shared_ptr
<Quad
> quadPtr(quad
);
455 mObjects
.push_back(quadPtr
);
463 Scene::Scene(const std::string
& name
) :
465 mImpl(Scene::Impl::getInstance(name
)) {}
468 Mf::Script::Result
Scene::load(Mf::Settings
& settings
, Mf::Script
& script
)
471 return mImpl
->load(settings
, script
);
475 void Scene::draw(Mf::Scalar alpha
) const
477 std::list
< boost::shared_ptr
<Impl::Quad
> >& objects
= mImpl
->mObjects
;
478 std::list
< boost::shared_ptr
<Impl::Quad
> >::const_iterator it
;
480 for (it
= objects
.begin(); it
!= objects
.end(); ++it
)
485 mImpl
->mBounds
.draw();
488 void Scene::drawIfVisible(Mf::Scalar alpha
,
489 const Mf::Frustum
& frustum
) const
491 std::list
< boost::shared_ptr
<Impl::Quad
> >& objects
= mImpl
->mObjects
;
492 std::list
< boost::shared_ptr
<Impl::Quad
> >::const_iterator it
;
494 for (it
= objects
.begin(); it
!= objects
.end(); ++it
)
496 (*it
)->drawIfVisible(alpha
, frustum
);
499 std::list
< Mf::Line
<2> >& lines
= mImpl
->mLines
;
500 std::list
< Mf::Line
<2> >::const_iterator lit
;
502 for (lit
= lines
.begin(); lit
!= lines
.end(); ++lit
)
507 mImpl
->mBounds
.draw();
511 bool Scene::castRay(const Mf::Ray
<2>& ray
,
512 std::list
<Mf::Ray
<2>::Contact
>& hits
) const
514 std::list
< Mf::Line
<2> >& lines
= mImpl
->mLines
;
515 std::list
< Mf::Line
<2> >::const_iterator it
;
517 for (it
= lines
.begin(); it
!= lines
.end(); ++it
)
519 Mf::Ray
<2>::Contact hit
;
520 Mf::Scalar d
= (*it
).intersectRay(ray
, hit
);
529 return !hits
.empty();
533 bool Scene::checkForCollision(Character
& character
)
536 //std::list< boost::shared_ptr<Impl::Quad> > objects;
537 //std::list<Mf::Octree<Impl::Quad>::InsertableP> objects;
538 //mImpl->mOctree->getNearbyObjects(objects, character);
540 std::list
< boost::shared_ptr
<Impl::Quad
> >& objects
= mImpl
->mObjects
;
541 std::list
< boost::shared_ptr
<Impl::Quad
> >::const_iterator it
;
544 Mf::Sphere
<3> sphere
= character
.getSphere();
546 for (it
= objects
.begin(); it
!= objects
.end(); ++it
)
548 Impl::Quad::Surface type
= (*it
)->getSurface();
549 if (type
== Impl::Quad::NONE
) continue;
551 if (Mf::checkCollision(sphere
, (*it
)->getSphere()))
555 Mf::Vector2
impulse(0.0, 0.0);
556 Mf::Vector2 p
= character
.getState().momentum
;
558 Mf::State2 state
= character
.getState(1.0);
559 sphere
= character
.getSphere();
560 Mf::Scalar alpha
= 1.0;
561 while (Mf::checkCollision(sphere
, (*it
)->getSphere()))
564 state
= character
.getState(alpha
);
567 character
.setPosition(state
.position
);
571 //case Impl::Quad::TOP:
572 //if (p[1] < 0.0) impulse[1] = -p[1];
574 //case Impl::Quad::LEFT:
575 //if (p[0] > 0.0) impulse[0] = 1.5*-p[0];
577 //case Impl::Quad::RIGHT:
578 //if (p[0] < 0.0) impulse[0] = 1.5*-p[0];
582 //character.addImpulse(impulse);
588 Mf::logInfo
<< "collisions: " << collisions
<< std::endl
;
595 bool Scene::getPath(std::string
& name
)
597 return Mf::Resource::getPath(name
, "scenes/", "lua");
This page took 0.062889 seconds and 4 git commands to generate.