OregonCore  revision 3611e8a-git
Your Favourite TBC server
GameObjectModel.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "VMapFactory.h"
19 #include "VMapManager2.h"
20 #include "VMapDefinitions.h"
21 #include "WorldModel.h"
22 
23 #include "GameObjectModel.h"
24 #include "GameObject.h"
25 #include "Creature.h"
26 #include "TemporarySummon.h"
27 #include "Object.h"
28 #include "DBCStores.h"
29 
30 using G3D::Vector3;
31 using G3D::Ray;
32 using G3D::AABox;
33 
35 {
36  GameobjectModelData(const std::string& name_, const AABox& box) :
37  bound(box), name(name_) {}
38 
39  AABox bound;
40  std::string name;
41 };
42 
43 typedef std::unordered_map<uint32, GameobjectModelData> ModelList;
45 
47 {
48  uint32 oldMSTime = getMSTime();
49  FILE* model_list_file = fopen((sWorld.GetDataPath() + "vmaps/" + VMAP::GAMEOBJECT_MODELS).c_str(), "rb");
50  if (!model_list_file)
51  {
52  ERROR_LOG("Unable to open '%s' file.", VMAP::GAMEOBJECT_MODELS);
53  return;
54  }
55 
56  uint32 name_length, displayId;
57  char buff[500];
58  while (true)
59  {
60  Vector3 v1, v2;
61  if (fread(&displayId, sizeof(uint32), 1, model_list_file) != 1)
62  if (feof(model_list_file)) // EOF flag is only set after failed reading attempt
63  break;
64 
65  if (fread(&name_length, sizeof(uint32), 1, model_list_file) != 1
66  || name_length >= sizeof(buff)
67  || fread(&buff, sizeof(char), name_length, model_list_file) != name_length
68  || fread(&v1, sizeof(Vector3), 1, model_list_file) != 1
69  || fread(&v2, sizeof(Vector3), 1, model_list_file) != 1)
70  {
71  ERROR_LOG("File '%s' seems to be corrupted!", VMAP::GAMEOBJECT_MODELS);
72  break;
73  }
74 
75  model_list.insert
76  (
77  ModelList::value_type( displayId, GameobjectModelData(std::string(buff,name_length),AABox(v1,v2)) )
78  );
79  }
80 
81  fclose(model_list_file);
82  sLog.outString(">> Loaded %u GameObject models in %u ms", uint32(model_list.size()), getMSTimeDiff(oldMSTime, getMSTime()));
83  sLog.outString();
84 }
85 
87 {
88  if (iModel)
90 }
91 
93 {
94  ModelList::const_iterator it = model_list.find(info.Displayid);
95  if (it == model_list.end())
96  return false;
97 
98  G3D::AABox mdl_box(it->second.bound);
99  // ignore models with no bounds
100  if (mdl_box == G3D::AABox::zero())
101  {
102  sLog.outError("GameObject model %s has zero bounds, loading skipped", it->second.name.c_str());
103  return false;
104  }
105 
106  iModel = ((VMAP::VMapManager2*)VMAP::VMapFactory::createOrGetVMapManager())->acquireModelInstance(sWorld.GetDataPath() + "vmaps/", it->second.name);
107 
108  if (!iModel)
109  return false;
110 
111  name = it->second.name;
112  //flags = VMAP::MOD_M2;
113  //adtId = 0;
114  //ID = 0;
115  iPos = Vector3(go.GetPositionX(), go.GetPositionY(), go.GetPositionZ());
116  iScale = go.GetFloatValue(OBJECT_FIELD_SCALE_X);
117  iInvScale = 1.f / iScale;
118 
119  G3D::Matrix3 iRotation = G3D::Matrix3::fromEulerAnglesZYX(go.GetOrientation(), 0, 0);
120  iInvRot = iRotation.inverse();
121  // transform bounding box:
122  mdl_box = AABox(mdl_box.low() * iScale, mdl_box.high() * iScale);
123  AABox rotated_bounds;
124  for (int i = 0; i < 8; ++i)
125  rotated_bounds.merge(iRotation * mdl_box.corner(i));
126 
127  this->iBound = rotated_bounds + iPos;
128 #ifdef SPAWN_CORNERS
129  // test:
130  for (int i = 0; i < 8; ++i)
131  {
132  Vector3 pos(iBound.corner(i));
133  if (Creature* c = const_cast<GameObject&>(go).SummonCreature(23472, pos.x, pos.y, pos.z, 0, TEMPSUMMON_MANUAL_DESPAWN))
134  {
135  c->setFaction(35);
136  c->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.1f);
137  }
138  }
139 #endif
140 
141  return true;
142 }
143 
145 {
147  if (!info)
148  return NULL;
149 
150  GameObjectModel* mdl = new GameObjectModel();
151  if (!mdl->initialize(go, *info))
152  {
153  delete mdl;
154  return NULL;
155  }
156 
157  return mdl;
158 }
159 
161 {
162  if (!iModel)
163  return false;
164 
165  ModelList::const_iterator it = model_list.find(go.GetUInt32Value(GAMEOBJECT_DISPLAYID));
166  if (it == model_list.end())
167  return false;
168 
169  G3D::AABox mdl_box(it->second.bound);
170  // ignore models with no bounds
171  if (mdl_box == G3D::AABox::zero())
172  {
173  sLog.outVMap("GameObject model %s has zero bounds, loading skipped", it->second.name.c_str());
174  return false;
175  }
176 
177  iPos = Vector3(go.GetPositionX(), go.GetPositionY(), go.GetPositionZ());
178 
179  G3D::Matrix3 iRotation = G3D::Matrix3::fromEulerAnglesZYX(go.GetOrientation(), 0, 0);
180  iInvRot = iRotation.inverse();
181  // transform bounding box:
182  mdl_box = AABox(mdl_box.low() * iScale, mdl_box.high() * iScale);
183  AABox rotated_bounds;
184  for (int i = 0; i < 8; ++i)
185  rotated_bounds.merge(iRotation * mdl_box.corner(i));
186 
187  iBound = rotated_bounds + iPos;
188 #ifdef SPAWN_CORNERS
189  // test:
190  for (int i = 0; i < 8; ++i)
191  {
192  Vector3 pos(iBound.corner(i));
193  const_cast<GameObject&>(go).SummonCreature(1, pos.x, pos.y, pos.z, 0, TEMPSUMMON_MANUAL_DESPAWN);
194  }
195 #endif
196 
197  return true;
198 }
199 
200 bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool StopAtFirstHit) const
201 {
202  float time = ray.intersectionTime(iBound);
203  if (time == G3D::inf())
204  return false;
205 
206  // child bounds are defined in object space:
207  Vector3 p = iInvRot * (ray.origin() - iPos) * iInvScale;
208  Ray modRay(p, iInvRot * ray.direction());
209  float distance = MaxDist * iInvScale;
210  bool hit = iModel->IntersectRay(modRay, distance, StopAtFirstHit);
211  if(hit)
212  {
213  distance *= iScale;
214  MaxDist = distance;
215  }
216  return hit;
217 }
despawns when UnSummon() is called
GameobjectModelData(const std::string &name_, const AABox &box)
const uint32 & GetUInt32Value(uint16 index) const
Definition: Object.h:228
uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime)
Definition: Timer.h:78
TempSummon * SummonCreature(uint32 id, const Position &pos, TempSummonType spwtype=TEMPSUMMON_MANUAL_DESPAWN, uint32 despwtime=0)
Definition: Object.cpp:2088
uint32 getMSTime()
Definition: Timer.h:32
#define sLog
Log class singleton.
Definition: Log.h:187
uint32 displayId
Definition: GameObject.h:40
bool initialize(const GameObject &go, const GameObjectDisplayInfoEntry &info)
bool Relocate(GameObject const &go)
ModelList model_list
float GetOrientation() const
Definition: Position.h:100
#define ERROR_LOG(...)
float GetPositionY() const
Definition: Position.h:98
std::unordered_map< uint32, GameobjectModelData > ModelList
float GetPositionZ() const
Definition: Position.h:99
DBCStorage< GameObjectDisplayInfoEntry > sGameObjectDisplayInfoStore(GameObjectDisplayInfofmt)
const char GAMEOBJECT_MODELS[]
GameObjectInfo const * GetGOInfo() const
Definition: GameObject.h:591
static IVMapManager * createOrGetVMapManager()
#define sWorld
Definition: World.h:860
void LoadGameObjectModelList()
bool intersectRay(const G3D::Ray &Ray, float &MaxDist, bool StopAtFirstHit) const
ACE_UINT32 uint32
Definition: Define.h:71
float GetPositionX() const
Definition: Position.h:97
static GameObjectModel * Create(const GameObject &go)
const float & GetFloatValue(uint16 index) const
Definition: Object.h:240