OpenGothic
Open source reimplementation of Gothic I and II
Loading...
Searching...
No Matches
dynamicworld.h
Go to the documentation of this file.
1#pragma once
2
3#include <zenkit/Mesh.hh>
4
5#include <Tempest/Matrix4x4>
6#include <memory>
7#include <limits>
8
9class btTriangleIndexVertexArray;
10class btCollisionShape;
11class btCollisionObject;
12class btRigidBody;
13class btVector3;
14
15class PhysicMeshShape;
16class PhysicVbo;
17class PackedMesh;
18class Bounds;
19
20class World;
21class Bullet;
22class Npc;
23class Item;
24class Interactive;
25
26class CollisionWorld;
27
28class DynamicWorld final {
29 private:
30 struct HumShape;
31 struct NpcBody;
32 struct NpcBodyList;
33 struct BulletsList;
34 struct BBoxList;
35
36 public:
37 static constexpr float gravityMS = 9.8f; // meters per second^2
38 static constexpr float gravity = gravityMS*100.f/(1000.f*1000.f); // centimeters per milliseconds^2
39 static constexpr float bulletSpeed = 3; // centimeters per milliseconds
40 static constexpr float spellSpeed = 1; // centimeters per milliseconds
41 static const float ghostPadding;
42
43 DynamicWorld(World &world, const zenkit::Mesh& mesh);
44 DynamicWorld(const DynamicWorld&)=delete;
46
47 enum Category {
48 C_Null = 1,
53 C_Item = 6,
54 };
55
62
64 Tempest::Vec3 partial = {};
65 Tempest::Vec3 normal = {};
66 bool npcCol = false;
67 bool preFall = false;
68 Interactive* vob = nullptr;
69 Npc* npc = nullptr;
70 };
71
72 struct NpcItem {
73 public:
74 NpcItem()=default;
75 NpcItem(DynamicWorld* owner,NpcBody* obj,float r):owner(owner),obj(obj){}
76 NpcItem(NpcItem&& it):owner(it.owner),obj(it.obj){it.obj=nullptr;}
77 ~NpcItem();
78
80 std::swap(owner,it.owner);
81 std::swap(obj,it.obj);
82 return *this;
83 }
84
85 void setPosition(const Tempest::Vec3& pos);
86 const Tempest::Vec3& position() const;
87
88 void setEnable(bool e);
89 void setUserPointer(void* p);
90
91 float centerY() const;
92
93 bool testMove(const Tempest::Vec3& to, CollisionTest& out);
94 bool testMove(const Tempest::Vec3& to, const Tempest::Vec3& from, CollisionTest& out);
95 auto tryMove (const Tempest::Vec3& to, CollisionTest& out) -> DynamicWorld::MoveCode;
96
97 bool hasCollision() const;
98
99 private:
100 DynamicWorld* owner = nullptr;
101 NpcBody* obj = nullptr;
102
103 auto implTryMove (const Tempest::Vec3& dp, const Tempest::Vec3& pos0, CollisionTest& out) -> DynamicWorld::MoveCode;
104 void implSetPosition(const Tempest::Vec3& pos);
105
106 friend class DynamicWorld;
107 };
108
109 struct Item {
110 public:
111 Item()=default;
112 Item(DynamicWorld* owner, btCollisionObject* obj, btCollisionShape* shp):owner(owner),obj(obj),shp(shp){}
113 Item(Item&& it):owner(it.owner),obj(it.obj),shp(it.shp){ it.obj=nullptr; it.shp=nullptr; }
114 ~Item();
115
117 std::swap(owner,it.owner);
118 std::swap(obj, it.obj);
119 std::swap(shp, it.shp);
120 return *this;
121 }
122
123 void setObjMatrix(const Tempest::Matrix4x4& m);
124 void setItem(::Item* it);
125 void setInteractive(Interactive* it);
126 bool isEmpty() const { return obj==nullptr; }
127
128 private:
129 DynamicWorld* owner = nullptr;
130 btCollisionObject* obj = nullptr;
131 btCollisionShape* shp = nullptr;
132 };
133
135 Tempest::Vec3 v={};
136 Tempest::Vec3 n={};
137 zenkit::MaterialGroup mat = zenkit::MaterialGroup::UNDEFINED;
138 bool hasCol = false;
139 float hitFraction = 0;
140
141 const char* sector = nullptr;
142 };
143
145 float wdepth = 0.f;
146 bool hasCol = false;
147 };
148
150 int waterCol = 0;
151 };
152
154 Npc* npcHit = nullptr;
155 };
156
158 virtual ~BulletCallback()=default;
159 virtual void onStop(){}
160 virtual void onMove(){}
161 virtual void onCollide(zenkit::MaterialGroup matId){(void)matId;}
162 virtual bool onCollide(Npc& other){(void)other; return true; }
163 };
164
165 struct BulletBody final {
166 public:
169
170 void setSpellId(int spl);
171 void setTargetRange(float tgRange);
172
173 void move(const Tempest::Vec3& to);
174 void setPosition (const Tempest::Vec3& pos);
175 void setDirection (const Tempest::Vec3& dir);
176 float pathLength() const;
177 void addPathLen(float v);
178
179 float speed() const { return dirL; }
180 float targetRange() const { return tgRange; }
181 Tempest::Vec3 position() const { return pos; }
182 Tempest::Vec3 direction() const { return dir; }
183 Tempest::Matrix4x4 matrix() const;
184 bool isSpell() const { return spl!=std::numeric_limits<int>::max(); }
185 int spellId() const { return spl; }
186
187 void addHit() { hitCnt++; }
188 int hitCount() const { return hitCnt; }
189
190 private:
191 DynamicWorld* owner = nullptr;
192 BulletCallback* cb = nullptr;
193
194 Tempest::Vec3 pos={};
195 Tempest::Vec3 lastPos={};
196
197 Tempest::Vec3 dir={};
198 float dirL=0.f;
199 float totalL=0.f;
200 int spl=std::numeric_limits<int>::max();
201 int hitCnt = 0;
202 float tgRange = 0;
203
204 friend class DynamicWorld;
205 };
206
208 BBoxCallback() = default;
209 virtual ~BBoxCallback()=default;
210 virtual void onCollide(BulletBody& other){(void)other;}
211 };
212
213 struct BBoxBody final {
214 public:
215 BBoxBody() = default;
216 BBoxBody(DynamicWorld* wrld, BBoxCallback* cb, const zenkit::AxisAlignedBoundingBox& bbox);
217 BBoxBody(DynamicWorld* wrld, BBoxCallback* cb, const Tempest::Vec3& pos, float R);
218 BBoxBody(BBoxBody&& other);
219 ~BBoxBody();
220
221 BBoxBody& operator=(BBoxBody&& other);
222
223 private:
224 DynamicWorld* owner = nullptr;
225 BBoxCallback* cb = nullptr;
226
227 btCollisionShape* shape = nullptr;
228 btRigidBody* obj = nullptr;
229
230 friend class DynamicWorld;
231 };
232
233 RayLandResult landRay (const Tempest::Vec3& from, float maxDy=0) const;
234 RayWaterResult waterRay (const Tempest::Vec3& from) const;
235 RayWaterResult waterRay (const Tempest::Vec3& from, const Tempest::Vec3& to) const;
236 RayCamResult cameraRay (const Tempest::Vec3& from, const Tempest::Vec3& to) const;
237
238 RayLandResult ray (const Tempest::Vec3& from, const Tempest::Vec3& to) const;
239 RayQueryResult rayNpc (const Tempest::Vec3& from, const Tempest::Vec3& to, const Npc* except) const;
240 float soundOclusion(const Tempest::Vec3& from, const Tempest::Vec3& to) const;
241
242 NpcItem ghostObj (std::string_view visual);
243 Item staticObj (const PhysicMeshShape *src, const Tempest::Matrix4x4& m);
244 Item movableObj(const PhysicMeshShape *src, const Tempest::Matrix4x4& m);
245 Item dynamicObj(const Tempest::Matrix4x4& pos, const Bounds& bbox, zenkit::MaterialGroup mat);
246
248 BBoxBody bboxObj(BBoxCallback* cb, const zenkit::AxisAlignedBoundingBox& bbox);
249 BBoxBody bboxObj(BBoxCallback* cb, const Tempest::Vec3& pos, float R);
250
251 void tick(uint64_t dt);
252
253 void deleteObj(BulletBody* obj);
254
255 static float materialFriction(zenkit::MaterialGroup mat);
256 static float materialDensity (zenkit::MaterialGroup mat);
257
258 std::string_view validateSectorName(std::string_view name) const;
259
260 private:
261 enum ItemType : uint8_t {
262 IT_Static,
263 IT_Movable,
264 IT_Dynamic,
265 };
266 Item createObj(btCollisionShape* shape, bool ownShape, const Tempest::Matrix4x4& m,
267 float mass, float friction, ItemType type);
268
269
270 void moveBullet(BulletBody& b, const Tempest::Vec3& dir, uint64_t dt);
271 RayWaterResult implWaterRay(const Tempest::Vec3& from, const Tempest::Vec3& to) const;
272 bool hasCollision(const NpcItem &it, CollisionTest& out);
273
274 std::unique_ptr<CollisionWorld> world;
275
276 std::vector<std::string> sectors;
277
278 std::vector<btVector3> landVbo;
279 std::unique_ptr<PhysicVbo> landMesh;
280 std::unique_ptr<btCollisionShape> landShape;
281 std::unique_ptr<btRigidBody> landBody;
282
283 std::unique_ptr<btCollisionShape> waterShape;
284 std::unique_ptr<btRigidBody> waterBody;
285 std::unique_ptr<PhysicVbo> waterMesh;
286
287 std::unique_ptr<NpcBodyList> npcList;
288 std::unique_ptr<BulletsList> bulletList;
289 std::unique_ptr<BBoxList> bboxList;
290
291 static const float ghostHeight;
292 static const float worldHeight;
293 };
static constexpr float bulletSpeed
Item movableObj(const PhysicMeshShape *src, const Tempest::Matrix4x4 &m)
RayWaterResult waterRay(const Tempest::Vec3 &from) const
RayCamResult cameraRay(const Tempest::Vec3 &from, const Tempest::Vec3 &to) const
static const float ghostPadding
static constexpr float gravity
static float materialFriction(zenkit::MaterialGroup mat)
static constexpr float spellSpeed
BBoxBody bboxObj(BBoxCallback *cb, const zenkit::AxisAlignedBoundingBox &bbox)
void deleteObj(BulletBody *obj)
float soundOclusion(const Tempest::Vec3 &from, const Tempest::Vec3 &to) const
DynamicWorld(const DynamicWorld &)=delete
RayLandResult landRay(const Tempest::Vec3 &from, float maxDy=0) const
Item dynamicObj(const Tempest::Matrix4x4 &pos, const Bounds &bbox, zenkit::MaterialGroup mat)
RayLandResult ray(const Tempest::Vec3 &from, const Tempest::Vec3 &to) const
std::string_view validateSectorName(std::string_view name) const
static float materialDensity(zenkit::MaterialGroup mat)
void tick(uint64_t dt)
Item staticObj(const PhysicMeshShape *src, const Tempest::Matrix4x4 &m)
BulletBody * bulletObj(BulletCallback *cb)
NpcItem ghostObj(std::string_view visual)
RayQueryResult rayNpc(const Tempest::Vec3 &from, const Tempest::Vec3 &to, const Npc *except) const
static constexpr float gravityMS
Definition item.h:14
Definition npc.h:25
Definition world.h:31
BBoxBody & operator=(BBoxBody &&other)
virtual void onCollide(BulletBody &other)
virtual ~BBoxCallback()=default
void setPosition(const Tempest::Vec3 &pos)
void setTargetRange(float tgRange)
void move(const Tempest::Vec3 &to)
Tempest::Matrix4x4 matrix() const
Tempest::Vec3 direction() const
Tempest::Vec3 position() const
void setDirection(const Tempest::Vec3 &dir)
virtual ~BulletCallback()=default
virtual bool onCollide(Npc &other)
virtual void onCollide(zenkit::MaterialGroup matId)
bool isEmpty() const
void setInteractive(Interactive *it)
void setItem(::Item *it)
void setObjMatrix(const Tempest::Matrix4x4 &m)
Item & operator=(Item &&it)
Item(DynamicWorld *owner, btCollisionObject *obj, btCollisionShape *shp)
bool testMove(const Tempest::Vec3 &to, CollisionTest &out)
void setPosition(const Tempest::Vec3 &pos)
void setUserPointer(void *p)
const Tempest::Vec3 & position() const
auto tryMove(const Tempest::Vec3 &to, CollisionTest &out) -> DynamicWorld::MoveCode
NpcItem(NpcItem &&it)
NpcItem & operator=(NpcItem &&it)
NpcItem(DynamicWorld *owner, NpcBody *obj, float r)
zenkit::MaterialGroup mat