1 // This file belongs to the "MiniCore" game engine. 2 // Copyright (C) 2010 Jussi Lind <jussi.lind@iki.fi> 3 // 4 // This program is free software; you can redistribute it and/or 5 // modify it under the terms of the GNU General Public License 6 // as published by the Free Software Foundation; either version 2 7 // of the License, or (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with this program; if not, write to the Free Software 16 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 // MA 02110-1301, USA. 18 // 19 20 #ifndef MCWORLD_HH 21 #define MCWORLD_HH 22 23 #include "mcmacros.hh" 24 #include "mcrendergroup.hh" 25 #include "mcvector2d.hh" 26 #include "mcvector3d.hh" 27 28 #include <memory> 29 #include <vector> 30 31 class MCCamera; 32 class MCCollisionDetector; 33 class MCContact; 34 class MCForceRegistry; 35 class MCImpulseGenerator; 36 class MCObject; 37 class MCObjectGrid; 38 class MCWorldRenderer; 39 40 /*! \class World base class. 41 * \brief World class holds every MCObject in the scene. 42 * 43 * MCWorld class holds every MCObject-derived object in the scene. 44 * It applies the physics integration and collision detections for 45 * the objects. 46 * 47 * MCWorld has always positive Z-axis pointing "up" and objects 48 * move on the XY-plane. Direction of the gravity can be freely set. 49 * 50 * MCWorld uses MCWorldRenderer to render the scene. 51 */ 52 class MCWorld 53 { 54 public: 55 typedef std::vector<MCObject *> ObjectVector; 56 57 //! Constructor. 58 MCWorld(); 59 60 //! Destructor. 61 virtual ~MCWorld(); 62 63 //! Return the one-and-only MCWorld instance. 64 static MCWorld & instance(); 65 66 static bool hasInstance(); 67 68 //! Remove all objects. 69 void clear(); 70 71 /*! Set dimensions of the world box in units. 72 * 73 * \param metersPerUnit You could have, for example, a game object that is a 74 * MCSurface of 10x20 units, but want it to behave like an real-world object 75 * of 1x2 meters, so the metersPerUnits would be 0.1 in that case. 76 * 77 * \param gridSize ver and hor size of the object grid. This affects the collision 78 * detection performance. 79 */ 80 void setDimensions( 81 float minX, 82 float maxX, 83 float minY, 84 float maxY, 85 float minZ, 86 float maxZ, 87 float metersPerUnit = 1.0f, 88 bool addAreaWalls = true, 89 size_t gridSize = 128); 90 91 /*! Set gravity vector used by default friction generators (on XY-plane). 92 * The default is [0, 0, -9.81]. Set the gravity (acceleration) for objects 93 * independently when needed. */ 94 void setGravity(const MCVector3dF & gravity); 95 96 const MCVector3dF & gravity() const; 97 98 //! Set how many meters equal one unit in the scene. 99 static void setMetersPerUnit(float value); 100 101 //! Get how many meters equal one unit in the scene. 102 static float metersPerUnit(); 103 104 //! Convert scene units to meters. 105 static void toMeters(float & units); 106 107 //! Convert scene units to meters. 108 static void toMeters(MCVector2dF & units); 109 110 //! Convert scene units to meters. 111 static void toMeters(MCVector3dF & units); 112 113 /*! Add object to the world. Object's current location is used. 114 * \param object Object to be added. */ 115 void addObject(MCObject & object); 116 117 /*! Schedules the object to be removed from the world. This method 118 * should be used when removing objects in the middle of a run. 119 * Object is not removed immediately so possibly on-going physics 120 * and collision calculations are not messed up. Do not delete the object. 121 * \param object Object to be removed. */ 122 void removeObject(MCObject & object); 123 124 /*! Removes object from the world immediately. This can be used if the object 125 * gets deleted. Slow. 126 * \param object Object to be removed. */ 127 void removeObjectNow(MCObject & object); 128 129 //! Stop integrating the given object. 130 void removeObjectFromIntegration(MCObject & object); 131 132 //! Restart integrating the given object. 133 void restoreObjectToIntegration(MCObject & object); 134 135 //! \return Force registry. Use this to add force generators to objects. 136 MCForceRegistry & forceRegistry() const; 137 138 /*! \brief Step world time 139 * This causes the integration of physics and executes collision detections. 140 * \param step Time step to be updated in msecs. */ 141 void stepTime(int step); 142 143 /*! \brief Call this (once) before calling render() or renderShadows(). 144 * \param camera The camera window to be used. If nullptr, then 145 * no any translations or clipping done. */ 146 virtual void prepareRendering(MCCamera * camera); 147 148 /*! \brief Render given component. 149 * \param camera Camera box, can be nullptr. */ 150 virtual void render(MCCamera * camera, MCRenderGroup renderGroup); 151 152 //! \return Reference to the objectGrid. 153 MCObjectGrid & objectGrid() const; 154 155 //! \return The world renderer. 156 MCWorldRenderer & renderer() const; 157 158 //! Get minimum X 159 float minX() const; 160 161 //! Get maximum X 162 float maxX() const; 163 164 //! Get minimum Y 165 float minY() const; 166 167 //! Get maximum Y 168 float maxY() const; 169 170 //! Get minimum Z 171 float minZ() const; 172 173 //! Get maximum Z 174 float maxZ() const; 175 176 /*! \brief Set collision resolver loop count. 177 * Lower loop count results in faster collision calculations, but lower accuracy. */ 178 void setResolverLoopCount(size_t resolverLoopCount = 5); 179 180 //! \return size of the current integration vector 181 size_t objectCount() const; 182 183 //! Get registered objects 184 const ObjectVector & objects() const; 185 186 private: 187 DISABLE_COPY(MCWorld); 188 DISABLE_ASSI(MCWorld); 189 DISABLE_MOVE(MCWorld); 190 191 void integrate(int step); 192 193 void processRemovedObjects(); 194 195 void processCollisions(); 196 197 void doRemoveObject(MCObject & object); 198 199 void generateImpulses(); 200 201 void resolvePositions(float accuracy); 202 203 MCContact * getDeepestInterpenetration(const std::vector<MCContact *> & contacts); 204 205 static MCWorld * m_instance; 206 207 MCWorldRenderer * m_renderer; 208 209 MCForceRegistry * m_forceRegistry; 210 211 MCCollisionDetector * m_collisionDetector; 212 213 MCImpulseGenerator * m_impulseGenerator; 214 215 std::unique_ptr<MCObjectGrid> m_objectGrid; 216 217 static float m_metersPerUnit; 218 219 static float m_metersPerUnitSquared; 220 221 float m_minX, m_maxX, m_minY, m_maxY, m_minZ, m_maxZ; 222 223 MCWorld::ObjectVector m_objects; 224 225 MCWorld::ObjectVector m_removeObjs; 226 227 std::unique_ptr<MCObject> m_leftWallObject; 228 229 std::unique_ptr<MCObject> m_rightWallObject; 230 231 std::unique_ptr<MCObject> m_topWallObject; 232 233 std::unique_ptr<MCObject> m_bottomWallObject; 234 235 size_t m_numCollisions; 236 237 size_t m_resolverLoopCount; 238 239 float m_resolverStep; 240 241 MCVector3dF m_gravity; 242 }; 243 244 #endif // MCWORLD_HH 245