]>
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 " << tileIndex
<<
79 " in texture " << texture
<< std::endl
;
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::Result
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 script
[1].requireTable();
231 script
[2].requireTable();
234 for (int i
= 1; i
<= 2; ++i
)
236 for (int j
= 1; j
<= 3; ++j
)
238 script
[i
].pushField(j
);
242 script
[3].get(aabb
.min
[0]);
243 script
[4].get(aabb
.min
[1]);
244 script
[5].get(aabb
.min
[2]);
245 script
[6].get(aabb
.max
[0]);
246 script
[7].get(aabb
.max
[1]);
247 script
[8].get(aabb
.max
[2]);
252 int setBounds(Mf::Script
& script
)
254 int ret
= loadBox(script
, mBounds
);
255 //mOctree = Mf::Octree<Quad>::alloc(mBounds);
259 int resetTransform(Mf::Script
& script
)
261 mTransform
.identity();
265 int translate(Mf::Script
& script
)
269 script
[1].requireNumber().get(vec
[0]);
270 script
[2].requireNumber().get(vec
[1]);
271 script
[3].requireNumber().get(vec
[2]);
273 Mf::Matrix4 translation
;
274 cml::matrix_translation(translation
, vec
);
275 mTransform
= translation
* mTransform
;
280 int scale(Mf::Script
& script
)
282 if (script
.getSize() == 3)
285 script
[1].requireNumber().get(vec
[0]);
286 script
[2].requireNumber().get(vec
[1]);
287 script
[3].requireNumber().get(vec
[2]);
290 cml::matrix_scale(scaling
, vec
);
291 mTransform
= scaling
* mTransform
;
293 else if (script
.getSize() == 1)
295 Mf::Scalar value
= 1.0;
296 script
[1].requireNumber().get(value
);
299 cml::matrix_uniform_scale(scaling
, value
);
300 mTransform
= scaling
* mTransform
;
304 script
.getTop().throwError("wrong number of arguments");
310 int rotate(Mf::Script
& script
)
313 script
[1].requireNumber().get(index
);
316 script
[2].requireNumber().get(value
);
318 cml::matrix_rotate_about_world_axis(mTransform
, index
, cml::rad(value
));
323 int setTexture(Mf::Script
& script
)
325 script
[1].requireString().get(mTexture
);
329 int drawTilemap(Mf::Script
& script
)
331 Mf::Script::Slot table
= script
[1].requireTable();
332 Mf::Script::Slot top
= script
[-1];
338 table
.pushField("width");
342 nTiles
= table
.getLength();
343 if (nTiles
% width
!= 0) table
.throwError("invalid number of tiles");
345 if (width
== 0) table
.throwError("width field must not be zero");
346 height
= nTiles
/ width
;
348 Mf::Vector3 vertices
[height
+1][width
+1];
350 // the indices are stored upside-down in the scene file so that they are
351 // easier to edit as text, so we'll need to load them last row first
353 // do first row and first column of vertices
355 for (int w
= 0; w
<= width
; ++w
)
357 vertices
[height
][w
] = Mf::demote(mTransform
*
358 Mf::Vector4(w
, height
, 0.0, 1.0));
360 for (int h
= 0; h
< height
; ++h
)
362 vertices
[h
][0] = Mf::demote(mTransform
*
363 Mf::Vector4(0.0, h
, 0.0, 1.0));
367 for (int h
= height
- 1; h
>= 0; --h
)
369 for (int w
= 0; w
< width
; ++w
, ++i
)
376 Tilemap::Index index
;
381 vertices
[h
][wPlus1
] = Mf::demote(mTransform
*
382 Mf::Vector4(wPlus1
, h
, 0.0, 1.0));
384 if (index
== Tilemap::NO_TILE
) continue;
386 const Mf::Vector3
* corners
[4] = {
388 &vertices
[h
][wPlus1
],
389 &vertices
[hPlus1
][wPlus1
],
393 Quad
* quad
= new Quad(corners
, mTexture
, index
);
394 //quad->setSurface(surface);
396 boost::shared_ptr
<Quad
> quadPtr(quad
);
397 mObjects
.push_back(quadPtr
);
401 Quad::Surface surface
= Quad::NONE
;
403 table
.pushField("surface");
407 if (surface
!= Quad::NONE
)
409 // need a 2d line for collisions
410 // assuming the camera always looks directly to -z when the
411 // scene is built, simply demoting the vector again should
412 // project the points to the xy-plane
414 Mf::Vector2 bl
= Mf::demote(vertices
[0][0]);
415 Mf::Vector2 tr
= Mf::demote(vertices
[height
][width
]);
417 mLines
.push_back(Mf::Line
<2>(bl
, tr
));
418 Mf::logDebug("new line");
424 int drawTile(Mf::Script
& script
)
426 Mf::Script::Slot param
= script
[1];
427 Mf::Script::Slot top
= script
[-1];
429 Tilemap::Index index
= 0;
431 bool blending
= false;
440 param
.pushField("u_scale");
443 param
.pushField("blend");
446 param
.pushField("fog");
449 else if (param
.isNumber())
454 Mf::Vector3 vertices
[2][width
+1];
457 Mf::Scalar increment
= 1.0 / Mf::Scalar(width
);
459 for (int h
= 0; h
<= 1; ++h
)
462 for (int w
= 0; w
<= width
; ++w
, xf
+= increment
)
464 vertices
[h
][w
] = Mf::demote(mTransform
*
465 Mf::Vector4(xf
, Mf::Scalar(h
), 0.0, 1.0));
469 for (int w
= 0; w
< width
; ++w
)
473 const Mf::Vector3
* corners
[4] = {
475 &vertices
[0][wPlus1
],
476 &vertices
[1][wPlus1
],
480 Quad
* quad
= new Quad(corners
, mTexture
, index
);
481 quad
->setBlending(blending
);
484 boost::shared_ptr
<Quad
> quadPtr(quad
);
485 mObjects
.push_back(quadPtr
);
493 Scene::Scene(const std::string
& name
) :
495 mImpl(Scene::Impl::getInstance(name
)) {}
498 Mf::Script::Result
Scene::load(Mf::Script
& script
)
501 return mImpl
->load(script
);
505 void Scene::draw(Mf::Scalar alpha
) const
507 std::list
< boost::shared_ptr
<Impl::Quad
> >& objects
= mImpl
->mObjects
;
508 std::list
< boost::shared_ptr
<Impl::Quad
> >::const_iterator it
;
510 for (it
= objects
.begin(); it
!= objects
.end(); ++it
)
515 mImpl
->mBounds
.draw();
518 void Scene::drawIfVisible(Mf::Scalar alpha
, const Mf::Frustum
& frustum
) const
520 std::list
< boost::shared_ptr
<Impl::Quad
> >& objects
= mImpl
->mObjects
;
521 std::list
< boost::shared_ptr
<Impl::Quad
> >::const_iterator it
;
523 for (it
= objects
.begin(); it
!= objects
.end(); ++it
)
525 (*it
)->drawIfVisible(alpha
, frustum
);
528 std::list
< Mf::Line
<2> >& lines
= mImpl
->mLines
;
529 std::list
< Mf::Line
<2> >::const_iterator lit
;
531 for (lit
= lines
.begin(); lit
!= lines
.end(); ++lit
)
536 mImpl
->mBounds
.draw();
540 bool Scene::castRay(const Mf::Ray
<2>& ray
,
541 std::list
<Mf::Ray
<2>::Intersection
>& hits
) const
543 std::list
< Mf::Line
<2> >& lines
= mImpl
->mLines
;
544 std::list
< Mf::Line
<2> >::const_iterator it
;
546 for (it
= lines
.begin(); it
!= lines
.end(); ++it
)
548 Mf::Ray
<2>::Intersection hit
;
549 Mf::Scalar d
= (*it
).intersectRay(ray
, hit
);
558 return !hits
.empty();
562 bool Scene::checkForCollision(Character
& character
)
565 //std::list< boost::shared_ptr<Impl::Quad> > objects;
566 //std::list<Mf::Octree<Impl::Quad>::InsertableP> objects;
567 //mImpl->mOctree->getNearbyObjects(objects, character);
569 std::list
< boost::shared_ptr
<Impl::Quad
> >& objects
= mImpl
->mObjects
;
570 std::list
< boost::shared_ptr
<Impl::Quad
> >::const_iterator it
;
573 Mf::Sphere
<3> sphere
= character
.getSphere();
575 for (it
= objects
.begin(); it
!= objects
.end(); ++it
)
577 Impl::Quad::Surface type
= (*it
)->getSurface();
578 if (type
== Impl::Quad::NONE
) continue;
580 if (Mf::checkCollision(sphere
, (*it
)->getSphere()))
584 Mf::Vector2
impulse(0.0, 0.0);
585 Mf::Vector2 p
= character
.getState().momentum
;
587 Mf::State2 state
= character
.getState(1.0);
588 sphere
= character
.getSphere();
589 Mf::Scalar alpha
= 1.0;
590 while (Mf::checkCollision(sphere
, (*it
)->getSphere()))
593 state
= character
.getState(alpha
);
596 character
.setPosition(state
.position
);
600 //case Impl::Quad::TOP:
601 //if (p[1] < 0.0) impulse[1] = -p[1];
603 //case Impl::Quad::LEFT:
604 //if (p[0] > 0.0) impulse[0] = 1.5*-p[0];
606 //case Impl::Quad::RIGHT:
607 //if (p[0] < 0.0) impulse[0] = 1.5*-p[0];
611 //character.addImpulse(impulse);
617 Mf::logInfo
<< "collisions: " << collisions
<< std::endl
;
624 std::string
Scene::getPath(const std::string
& name
)
626 return Mf::Resource::getPath("scenes/" + name
+ ".lua");
630 /** vim: set ts=4 sw=4 tw=80: *************************************************/
This page took 0.058268 seconds and 5 git commands to generate.