Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
GameObjectModel.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "VMapFactory.h"
7#include "VMapManager2.h"
8#include "VMapDefinitions.h"
9#include "WorldModel.h"
10#include "GameObjectModel.h"
11#include "Log.h"
12#include "Timer.h"
13
14using G3D::Vector3;
15using G3D::Ray;
16using G3D::AABox;
17
19{
20 GameobjectModelData(const std::string& name_, const AABox& box) :
21 bound(box), name(name_) { }
22
23 AABox bound;
24 std::string name;
25};
26
29
30void LoadGameObjectModelList(std::string const& dataPath)
31{
32#ifndef NO_CORE_FUNCS
33 uint32 oldMSTime = getMSTime();
34#endif
35
36 FILE* model_list_file = fopen((dataPath + "vmaps/" + VMAP::GAMEOBJECT_MODELS).c_str(), "rb");
37 if (!model_list_file)
38 {
39 VMAP_ERROR_LOG("misc", "Unable to open '%s' file.", VMAP::GAMEOBJECT_MODELS);
40 return;
41 }
42
43 uint32 name_length, displayId;
44 char buff[500];
45 while (true)
46 {
47 Vector3 v1, v2;
48 if (fread(&displayId, sizeof(uint32), 1, model_list_file) != 1)
49 if (feof(model_list_file)) // EOF flag is only set after failed reading attempt
50 break;
51
52 if (fread(&name_length, sizeof(uint32), 1, model_list_file) != 1
53 || name_length >= sizeof(buff)
54 || fread(&buff, sizeof(char), name_length, model_list_file) != name_length
55 || fread(&v1, sizeof(Vector3), 1, model_list_file) != 1
56 || fread(&v2, sizeof(Vector3), 1, model_list_file) != 1)
57 {
58 VMAP_ERROR_LOG("misc", "File '%s' seems to be corrupted!", VMAP::GAMEOBJECT_MODELS);
59 break;
60 }
61
62 if (v1.isNaN() || v2.isNaN())
63 {
64 VMAP_ERROR_LOG("misc", "File '%s' Model '%s' has invalid v1%s v2%s values!", VMAP::GAMEOBJECT_MODELS, std::string(buff, name_length).c_str(), v1.toString().c_str(), v2.toString().c_str());
65 continue;
66 }
67
68 model_list.insert
69 (
70 ModelList::value_type(displayId, GameobjectModelData(std::string(buff, name_length), AABox(v1, v2)))
71 );
72 }
73
74 fclose(model_list_file);
75 VMAP_INFO_LOG("server.loading", ">> Loaded %u GameObject models in %u ms", uint32(model_list.size()), GetMSTimeDiffToNow(oldMSTime));
76}
77
83
84bool GameObjectModel::initialize(std::unique_ptr<GameObjectModelOwnerBase> modelOwner, std::string const& dataPath)
85{
86 ModelList::const_iterator it = model_list.find(modelOwner->GetDisplayId());
87 if (it == model_list.end())
88 return false;
89
90 G3D::AABox mdl_box(it->second.bound);
91 // ignore models with no bounds
92 if (mdl_box == G3D::AABox::zero())
93 {
94 VMAP_ERROR_LOG("misc", "GameObject model %s has zero bounds, loading skipped", it->second.name.c_str());
95 return false;
96 }
97
98 iModel = ((VMAP::VMapManager2*)VMAP::VMapFactory::createOrGetVMapManager())->acquireModelInstance(dataPath + "vmaps/", it->second.name);
99
100 if (!iModel)
101 return false;
102
103 name = it->second.name;
104 //flags = VMAP::MOD_M2;
105 //adtId = 0;
106 //ID = 0;
107 iPos = modelOwner->GetPosition();
108 phasemask = modelOwner->GetPhaseMask();
109 iScale = modelOwner->GetScale();
110 iInvScale = 1.f / iScale;
111
112 G3D::Matrix3 iRotation = G3D::Matrix3::fromEulerAnglesZYX(modelOwner->GetOrientation(), 0, 0);
113 iInvRot = iRotation.inverse();
114 // transform bounding box:
115 mdl_box = AABox(mdl_box.low() * iScale, mdl_box.high() * iScale);
116 AABox rotated_bounds;
117 for (int i = 0; i < 8; ++i)
118 rotated_bounds.merge(iRotation * mdl_box.corner(i));
119
120 iBound = rotated_bounds + iPos;
121#ifdef SPAWN_CORNERS
122 // test:
123 for (int i = 0; i < 8; ++i)
124 {
125 Vector3 pos(iBound.corner(i));
126 modelOwner->DebugVisualizeCorner(pos);
127 }
128#endif
129 owner = std::move(modelOwner);
130 return true;
131}
132
133GameObjectModel* GameObjectModel::Create(std::unique_ptr<GameObjectModelOwnerBase> modelOwner, std::string const& dataPath)
134{
135 GameObjectModel* mdl = new GameObjectModel();
136 if (!mdl->initialize(std::move(modelOwner), dataPath))
137 {
138 delete mdl;
139 return NULL;
140 }
141
142 return mdl;
143}
144
145bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask) const
146{
147 if (!(phasemask & ph_mask) || !owner->isSpawned())
148 return false;
149
150 float time = ray.intersectionTime(iBound);
151 if (time == G3D::inf())
152 return false;
153
154 // child bounds are defined in object space:
155 Vector3 p = iInvRot * (ray.origin() - iPos) * iInvScale;
156 Ray modRay(p, iInvRot * ray.direction());
157 float distance = MaxDist * iInvScale;
158 bool hit = iModel->IntersectRay(modRay, distance, StopAtFirstHit);
159 if (hit)
160 {
161 distance *= iScale;
162 MaxDist = distance;
163 }
164 return hit;
165}
166
168{
169 if (!iModel)
170 return false;
171
172 ModelList::const_iterator it = model_list.find(owner->GetDisplayId());
173 if (it == model_list.end())
174 return false;
175
176 G3D::AABox mdl_box(it->second.bound);
177 // ignore models with no bounds
178 if (mdl_box == G3D::AABox::zero())
179 {
180 VMAP_ERROR_LOG("misc", "GameObject model %s has zero bounds, loading skipped", it->second.name.c_str());
181 return false;
182 }
183
184 iPos = owner->GetPosition();
185
186 G3D::Matrix3 iRotation = G3D::Matrix3::fromEulerAnglesZYX(owner->GetOrientation(), 0, 0);
187 iInvRot = iRotation.inverse();
188 // transform bounding box:
189 mdl_box = AABox(mdl_box.low() * iScale, mdl_box.high() * iScale);
190 AABox rotated_bounds;
191 for (int i = 0; i < 8; ++i)
192 rotated_bounds.merge(iRotation * mdl_box.corner(i));
193
194 iBound = rotated_bounds + iPos;
195#ifdef SPAWN_CORNERS
196 // test:
197 for (int i = 0; i < 8; ++i)
198 {
199 Vector3 pos(iBound.corner(i));
200 owner->DebugVisualizeCorner(pos);
201 }
202#endif
203
204 return true;
205}
std::uint32_t uint32
Definition Define.h:77
UNORDERED_MAP< uint32, GameobjectModelData > ModelList
void LoadGameObjectModelList(std::string const &dataPath)
ModelList model_list
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition Timer.h:22
uint32 getMSTime()
Definition Timer.h:12
#define UNORDERED_MAP
#define VMAP_ERROR_LOG(FILTER,...)
#define VMAP_INFO_LOG(FILTER,...)
G3D::Vector3 iPos
G3D::Matrix3 iInvRot
VMAP::WorldModel * iModel
static GameObjectModel * Create(std::unique_ptr< GameObjectModelOwnerBase > modelOwner, std::string const &dataPath)
std::unique_ptr< GameObjectModelOwnerBase > owner
bool intersectRay(const G3D::Ray &Ray, float &MaxDist, bool StopAtFirstHit, uint32 ph_mask) const
bool initialize(std::unique_ptr< GameObjectModelOwnerBase > modelOwner, std::string const &dataPath)
static IVMapManager * createOrGetVMapManager()
const char GAMEOBJECT_MODELS[]
GameobjectModelData(const std::string &name_, const AABox &box)