]>
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/Exception.hh>
35 #include <Moof/Library.hh>
36 #include <Moof/Line.hh>
37 #include <Moof/Log.hh>
38 #include <Moof/Math.hh>
39 //#include <Moof/Octree.hh>
40 #include <Moof/Script.hh>
41 #include <Moof/Settings.hh>
43 #include "Character.hh"
48 struct Scene::Impl
: public Mf::Library
<Impl
>
50 struct Quad
: public Mf::Entity
60 Quad(const Mf::Vector3
* vertices
[4], const std::string
& texture
,
61 Tilemap::Index tileIndex
) :
67 for (int i
= 0; i
< 4; ++i
)
69 mVertices
[i
] = *vertices
[i
];
70 //for (int j = 0; j < 3; ++j, ++num)
72 //mVertices[num] = (*vertices[i])[j];
76 if (!mTilemap
.getTileCoords(tileIndex
, mTexCoords
))
78 Mf::logWarning("no index %d in texture %s", tileIndex
,
81 mTexCoords
[0] = mTexCoords
[1] =
82 mTexCoords
[3] = mTexCoords
[6] = 0.0;
83 mTexCoords
[2] = mTexCoords
[4] =
84 mTexCoords
[5] = mTexCoords
[7] = 1.0;
87 mAabb
.encloseVertices(mVertices
, 4);
88 mSphere
.point
= mAabb
.getCenter();
89 mSphere
.radius
= (mAabb
.min
- mSphere
.point
).length();
92 void setBlending(bool blending
)
102 void setSurface(Surface type
)
107 Surface
getSurface() const
112 void draw(Mf::Scalar alpha
= 0.0) const
117 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
123 glFogi(GL_FOG_MODE
, GL_LINEAR
);
126 //glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
129 glVertexPointer(3, GL_SCALAR
, 0, mVertices
[0].data());
130 glTexCoordPointer(2, GL_SCALAR
, 0, mTexCoords
);
132 glDrawArrays(GL_TRIANGLE_FAN
, 0, 4);
138 bool isVisible(const Mf::Frustum
& frustum
) const
140 return mSphere
.isVisible(frustum
);
144 Mf::Vector3 mVertices
[4];
145 Mf::Scalar mTexCoords
[8];
156 Mf::Matrix4 mTransform
;
157 std::string mTexture
;
159 //Mf::Octree<Quad>::Ptr mOctree;
160 std::list
< boost::shared_ptr
<Impl::Quad
> > mObjects
;
161 std::list
< Mf::Line
<2> > mLines
;
174 explicit Impl(const std::string
& name
) :
175 Mf::Library
<Impl
>(name
) {}
177 void importSceneBindings(Mf::Script
& script
)
179 script
.importFunction("SetBounds",
180 boost::bind(&Impl::setBounds
, this, _1
));
181 script
.importFunction("ResetTransform",
182 boost::bind(&Impl::resetTransform
, this, _1
));
183 script
.importFunction("Translate",
184 boost::bind(&Impl::translate
, this, _1
));
185 script
.importFunction("Scale",
186 boost::bind(&Impl::scale
, this, _1
));
187 script
.importFunction("Rotate",
188 boost::bind(&Impl::rotate
, this, _1
));
189 script
.importFunction("SetTexture",
190 boost::bind(&Impl::setTexture
, this, _1
));
191 script
.importFunction("DrawTilemap",
192 boost::bind(&Impl::drawTilemap
, this, _1
));
193 script
.importFunction("DrawTile",
194 boost::bind(&Impl::drawTile
, this, _1
));
197 Mf::Settings::getInstance().get("detail", detail
);
198 script
.push(detail
); script
.set("detail");
200 script
.push(1); script
.set("LOW");
201 script
.push(2); script
.set("MEDIUM");
202 script
.push(3); script
.set("HIGH");
204 script
.push(X
); script
.set("X");
205 script
.push(Y
); script
.set("Y");
206 script
.push(Z
); script
.set("Z");
208 script
.push(Quad::LEFT
); script
.set("LEFT");
209 script
.push(Quad::RIGHT
); script
.set("RIGHT");
210 script
.push(Quad::TOP
); script
.set("TOP");
214 Mf::Script::Status
load(Mf::Script
& script
)
216 std::string filePath
= Scene::getPath(getName());
219 script
.push("the scene file could not be found");
220 return Mf::Script::FILE_ERROR
;
223 importSceneBindings(script
);
224 return script
.doFile(filePath
);
228 static int loadBox(Mf::Script
& script
, Mf::Aabb
<3>& aabb
)
230 Mf::Script::Value table
[] =
232 script
[1].requireTable(),
233 script
[2].requireTable()
236 for (int i
= 0; i
<= 1; ++i
)
238 for (int j
= 1; j
<= 3; ++j
)
241 table
[i
].pushField();
245 script
[3].get(aabb
.min
[0]);
246 script
[4].get(aabb
.min
[1]);
247 script
[5].get(aabb
.min
[2]);
248 script
[6].get(aabb
.max
[0]);
249 script
[7].get(aabb
.max
[1]);
250 script
[8].get(aabb
.max
[2]);
255 int setBounds(Mf::Script
& script
)
257 int ret
= loadBox(script
, mBounds
);
258 //mOctree = Mf::Octree<Quad>::alloc(mBounds);
262 int resetTransform(Mf::Script
& script
)
264 mTransform
.identity();
268 int translate(Mf::Script
& script
)
270 Mf::Script::Value x
= script
[1].requireNumber();
271 Mf::Script::Value y
= script
[2].requireNumber();
272 Mf::Script::Value z
= script
[3].requireNumber();
279 Mf::Matrix4 translation
;
280 cml::matrix_translation(translation
, vec
);
281 mTransform
= translation
* mTransform
;
286 int scale(Mf::Script
& script
)
288 if (script
.getSize() == 3)
291 script
[1].requireNumber().get(vec
[0]);
292 script
[2].requireNumber().get(vec
[1]);
293 script
[3].requireNumber().get(vec
[2]);
296 cml::matrix_scale(scaling
, vec
);
297 mTransform
= scaling
* mTransform
;
299 else if (script
.getSize() == 1)
301 Mf::Scalar value
= 1.0;
302 script
[1].requireNumber().get(value
);
305 cml::matrix_uniform_scale(scaling
, value
);
306 mTransform
= scaling
* mTransform
;
310 script
.getTop().throwError("wrong number of arguments");
316 int rotate(Mf::Script
& script
)
318 Mf::Script::Value axis
= script
[1].requireNumber();
319 Mf::Script::Value angle
= script
[2].requireNumber();
327 cml::matrix_rotate_about_world_axis(mTransform
, index
, cml::rad(value
));
332 int setTexture(Mf::Script
& script
)
334 script
[1].requireString().get(mTexture
);
338 int drawTilemap(Mf::Script
& script
)
340 Mf::Script::Value table
= script
[1].requireTable();
341 Mf::Script::Value top
= script
[-1];
347 table
.pushField("width");
351 nTiles
= table
.getLength();
352 if (nTiles
% width
!= 0) table
.throwError("invalid number of tiles");
354 if (width
== 0) table
.throwError("width field must not be zero");
355 height
= nTiles
/ width
;
357 Mf::Vector3 vertices
[height
+1][width
+1];
359 // the indices are stored upside-down in the scene file so that they are
360 // easier to edit as text, so we'll need to load them last row first
362 // do first row and first column of vertices
364 for (int w
= 0; w
<= width
; ++w
)
366 vertices
[height
][w
] = Mf::demote(mTransform
*
367 Mf::Vector4(w
, height
, 0.0, 1.0));
369 for (int h
= 0; h
< height
; ++h
)
371 vertices
[h
][0] = Mf::demote(mTransform
*
372 Mf::Vector4(0.0, h
, 0.0, 1.0));
376 for (int h
= height
- 1; h
>= 0; --h
)
378 for (int w
= 0; w
< width
; ++w
, ++i
)
385 Tilemap::Index index
;
390 vertices
[h
][wPlus1
] = Mf::demote(mTransform
*
391 Mf::Vector4(wPlus1
, h
, 0.0, 1.0));
393 if (index
== Tilemap::NO_TILE
) continue;
395 const Mf::Vector3
* corners
[4] = {
397 &vertices
[h
][wPlus1
],
398 &vertices
[hPlus1
][wPlus1
],
402 Quad
* quad
= new Quad(corners
, mTexture
, index
);
403 //quad->setSurface(surface);
405 boost::shared_ptr
<Quad
> quadPtr(quad
);
406 mObjects
.push_back(quadPtr
);
410 Quad::Surface surface
= Quad::NONE
;
412 table
.pushField("surface");
416 if (surface
!= Quad::NONE
)
418 // need a 2d line for collisions
419 // assuming the camera always looks directly to -z when the
420 // scene is built, simply demoting the vector again should
421 // project the points to the xy-plane
423 //Mf::Vector2 tr = Mf::demote(vertices[height+1][width+1]);
424 //Mf::Vector2 bl = Mf::demote(vertices[0][0]);
426 Mf::Vector2 bl
= Mf::demote(vertices
[0][0]);
427 Mf::Vector2 tr
= Mf::demote(vertices
[height
][width
]);
428 //Mf::logInfo("pt1: %f, %f", bl[0], bl[1]);
429 //Mf::logInfo("pt2: %f, %f", tr[0], tr[1]);
431 mLines
.push_back(Mf::Line
<2>(bl
, tr
));
432 Mf::logInfo("new line");
436 //mLines.push_back(Mf::Line<2>(bl, tl));
440 //mLines.push_back(Mf::Line<2>(bl, tl));
447 int drawTile(Mf::Script
& script
)
449 Mf::Script::Value param
= script
[1];
450 Mf::Script::Value top
= script
[-1];
452 Tilemap::Index index
= 0;
454 bool blending
= false;
463 param
.pushField("u_scale");
466 param
.pushField("blend");
469 param
.pushField("fog");
472 else if (param
.isNumber())
477 Mf::Vector3 vertices
[2][width
+1];
480 Mf::Scalar increment
= 1.0 / Mf::Scalar(width
);
482 for (int h
= 0; h
<= 1; ++h
)
485 for (int w
= 0; w
<= width
; ++w
, xf
+= increment
)
487 vertices
[h
][w
] = Mf::demote(mTransform
*
488 Mf::Vector4(xf
, Mf::Scalar(h
), 0.0, 1.0));
492 for (int w
= 0; w
< width
; ++w
)
496 const Mf::Vector3
* corners
[4] = {
498 &vertices
[0][wPlus1
],
499 &vertices
[1][wPlus1
],
503 Quad
* quad
= new Quad(corners
, mTexture
, index
);
504 quad
->setBlending(blending
);
507 boost::shared_ptr
<Quad
> quadPtr(quad
);
508 mObjects
.push_back(quadPtr
);
516 Scene::Scene(const std::string
& name
) :
518 mImpl(Scene::Impl::getInstance(name
)) {}
521 Mf::Script::Status
Scene::load(Mf::Script
& script
)
524 return mImpl
->load(script
);
528 void Scene::draw(Mf::Scalar alpha
) const
530 std::list
< boost::shared_ptr
<Impl::Quad
> >& objects
= mImpl
->mObjects
;
531 std::list
< boost::shared_ptr
<Impl::Quad
> >::const_iterator it
;
533 for (it
= objects
.begin(); it
!= objects
.end(); ++it
)
538 mImpl
->mBounds
.draw();
541 void Scene::drawIfVisible(Mf::Scalar alpha
, const Mf::Frustum
& frustum
) const
543 std::list
< boost::shared_ptr
<Impl::Quad
> >& objects
= mImpl
->mObjects
;
544 std::list
< boost::shared_ptr
<Impl::Quad
> >::const_iterator it
;
546 for (it
= objects
.begin(); it
!= objects
.end(); ++it
)
548 (*it
)->drawIfVisible(alpha
, frustum
);
551 std::list
< Mf::Line
<2> >& lines
= mImpl
->mLines
;
552 std::list
< Mf::Line
<2> >::const_iterator lit
;
554 for (lit
= lines
.begin(); lit
!= lines
.end(); ++lit
)
559 mImpl
->mBounds
.draw();
563 bool Scene::castRay(const Mf::Ray
<2>& ray
,
564 std::list
<Mf::Ray
<2>::Intersection
>& hits
) const
566 std::list
< Mf::Line
<2> >& lines
= mImpl
->mLines
;
567 std::list
< Mf::Line
<2> >::const_iterator it
;
569 for (it
= lines
.begin(); it
!= lines
.end(); ++it
)
571 Mf::Ray
<2>::Intersection hit
;
572 Mf::Scalar d
= (*it
).intersectRay(ray
, hit
);
583 bool Scene::checkForCollision(Character
& character
)
586 //std::list< boost::shared_ptr<Impl::Quad> > objects;
587 //std::list<Mf::Octree<Impl::Quad>::InsertableP> objects;
588 //mImpl->mOctree->getNearbyObjects(objects, character);
590 std::list
< boost::shared_ptr
<Impl::Quad
> >& objects
= mImpl
->mObjects
;
591 std::list
< boost::shared_ptr
<Impl::Quad
> >::const_iterator it
;
594 Mf::Sphere
<3> sphere
= character
.getSphere();
596 for (it
= objects
.begin(); it
!= objects
.end(); ++it
)
598 Impl::Quad::Surface type
= (*it
)->getSurface();
599 if (type
== Impl::Quad::NONE
) continue;
601 if (Mf::checkCollision(sphere
, (*it
)->getSphere()))
605 Mf::Vector2
impulse(0.0, 0.0);
606 Mf::Vector2 p
= character
.getState().momentum
;
608 Mf::State2 state
= character
.getState(1.0);
609 sphere
= character
.getSphere();
610 Mf::Scalar alpha
= 1.0;
611 while (Mf::checkCollision(sphere
, (*it
)->getSphere()))
614 state
= character
.getState(alpha
);
617 character
.setPosition(state
.position
);
621 //case Impl::Quad::TOP:
622 //if (p[1] < 0.0) impulse[1] = -p[1];
624 //case Impl::Quad::LEFT:
625 //if (p[0] > 0.0) impulse[0] = 1.5*-p[0];
627 //case Impl::Quad::RIGHT:
628 //if (p[0] < 0.0) impulse[0] = 1.5*-p[0];
632 //character.addImpulse(impulse);
638 Mf::logInfo("collisions: %d", collisions
);
645 std::string
Scene::getPath(const std::string
& name
)
647 return Mf::Resource::getPath("scenes/" + name
+ ".lua");
651 /** vim: set ts=4 sw=4 tw=80: *************************************************/
This page took 0.061785 seconds and 5 git commands to generate.