Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Toggle main menu visibility
Loading...
Searching...
No Matches
ModelInstance.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 "
ModelInstance.h
"
7
#include "
WorldModel.h
"
8
#include "
MapTree.h
"
9
#include "
VMapDefinitions.h
"
10
11
using
G3D::Vector3;
12
using
G3D::Ray;
13
14
namespace
VMAP
15
{
16
ModelInstance::ModelInstance
(
const
ModelSpawn
&spawn,
WorldModel
* model):
ModelSpawn
(spawn),
iModel
(model)
17
{
18
iInvRot
= G3D::Matrix3::fromEulerAnglesZYX(G3D::pi()*
iRot
.y/180.f, G3D::pi()*
iRot
.x/180.f, G3D::pi()*
iRot
.z/180.f).inverse();
19
iInvScale
= 1.f/
iScale
;
20
}
21
22
bool
ModelInstance::intersectRay
(
const
G3D::Ray& pRay,
float
& pMaxDist,
bool
pStopAtFirstHit)
const
23
{
24
if
(!
iModel
)
25
{
26
//std::cout << "<object not loaded>\n";
27
return
false
;
28
}
29
float
time = pRay.intersectionTime(
iBound
);
30
if
(time == G3D::inf())
31
{
32
// std::cout << "Ray does not hit '" << name << "'\n";
33
34
return
false
;
35
}
36
// std::cout << "Ray crosses bound of '" << name << "'\n";
37
/* std::cout << "ray from:" << pRay.origin().x << ", " << pRay.origin().y << ", " << pRay.origin().z
38
<< " dir:" << pRay.direction().x << ", " << pRay.direction().y << ", " << pRay.direction().z
39
<< " t/tmax:" << time << '/' << pMaxDist;
40
std::cout << "\nBound lo:" << iBound.low().x << ", " << iBound.low().y << ", " << iBound.low().z << " hi: "
41
<< iBound.high().x << ", " << iBound.high().y << ", " << iBound.high().z << std::endl; */
42
// child bounds are defined in object space:
43
Vector3 p =
iInvRot
* (pRay.origin() -
iPos
) *
iInvScale
;
44
Ray modRay(p,
iInvRot
* pRay.direction());
45
float
distance = pMaxDist *
iInvScale
;
46
bool
hit =
iModel
->IntersectRay(modRay, distance, pStopAtFirstHit);
47
if
(hit)
48
{
49
distance *=
iScale
;
50
pMaxDist = distance;
51
}
52
return
hit;
53
}
54
55
void
ModelInstance::intersectPoint
(
const
G3D::Vector3& p,
AreaInfo
&info)
const
56
{
57
if
(!
iModel
)
58
{
59
#ifdef VMAP_DEBUG
60
std::cout <<
"<object not loaded>\n"
;
61
#endif
62
return
;
63
}
64
65
// M2 files don't contain area info, only WMO files
66
if
(
flags
&
MOD_M2
)
67
return
;
68
if
(!
iBound
.contains(p))
69
return
;
70
// child bounds are defined in object space:
71
Vector3 pModel =
iInvRot
* (p -
iPos
) *
iInvScale
;
72
Vector3 zDirModel =
iInvRot
* Vector3(0.f, 0.f, -1.f);
73
float
zDist;
74
if
(
iModel
->IntersectPoint(pModel, zDirModel, zDist, info))
75
{
76
Vector3 modelGround = pModel + zDist * zDirModel;
77
// Transform back to world space. Note that:
78
// Mat * vec == vec * Mat.transpose()
79
// and for rotation matrices: Mat.inverse() == Mat.transpose()
80
float
world_Z = ((modelGround *
iInvRot
) *
iScale
+
iPos
).z;
81
if
(info.
ground_Z
< world_Z)
82
{
83
info.
ground_Z
= world_Z;
84
info.
adtId
=
adtId
;
85
}
86
}
87
}
88
89
bool
ModelInstance::GetLocationInfo
(
const
G3D::Vector3& p,
LocationInfo
&info)
const
90
{
91
if
(!
iModel
)
92
{
93
#ifdef VMAP_DEBUG
94
std::cout <<
"<object not loaded>\n"
;
95
#endif
96
return
false
;
97
}
98
99
// M2 files don't contain area info, only WMO files
100
if
(
flags
&
MOD_M2
)
101
return
false
;
102
if
(!
iBound
.contains(p))
103
return
false
;
104
// child bounds are defined in object space:
105
Vector3 pModel =
iInvRot
* (p -
iPos
) *
iInvScale
;
106
Vector3 zDirModel =
iInvRot
* Vector3(0.f, 0.f, -1.f);
107
float
zDist;
108
if
(
iModel
->GetLocationInfo(pModel, zDirModel, zDist, info))
109
{
110
Vector3 modelGround = pModel + zDist * zDirModel;
111
// Transform back to world space. Note that:
112
// Mat * vec == vec * Mat.transpose()
113
// and for rotation matrices: Mat.inverse() == Mat.transpose()
114
float
world_Z = ((modelGround *
iInvRot
) *
iScale
+
iPos
).z;
115
if
(info.
ground_Z
< world_Z)
// hm...could it be handled automatically with zDist at intersection?
116
{
117
info.
ground_Z
= world_Z;
118
info.
hitInstance
=
this
;
119
return
true
;
120
}
121
}
122
return
false
;
123
}
124
125
bool
ModelInstance::GetLiquidLevel
(
const
G3D::Vector3& p,
LocationInfo
&info,
float
&liqHeight)
const
126
{
127
// child bounds are defined in object space:
128
Vector3 pModel =
iInvRot
* (p -
iPos
) *
iInvScale
;
129
//Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
130
float
zDist;
131
if
(info.
hitModel
->
GetLiquidLevel
(pModel, zDist))
132
{
133
// calculate world height (zDist in model coords):
134
// assume WMO not tilted (wouldn't make much sense anyway)
135
liqHeight = zDist *
iScale
+
iPos
.z;
136
return
true
;
137
}
138
return
false
;
139
}
140
141
bool
ModelSpawn::readFromFile
(FILE* rf,
ModelSpawn
&spawn)
142
{
143
uint32
check = 0, nameLen;
144
check += fread(&spawn.
flags
,
sizeof
(
uint32
), 1, rf);
145
// EoF?
146
if
(!check)
147
{
148
if
(ferror(rf))
149
std::cout <<
"Error reading ModelSpawn!\n"
;
150
return
false
;
151
}
152
check += fread(&spawn.
adtId
,
sizeof
(
uint16
), 1, rf);
153
check += fread(&spawn.
ID
,
sizeof
(
uint32
), 1, rf);
154
check += fread(&spawn.
iPos
,
sizeof
(
float
), 3, rf);
155
check += fread(&spawn.
iRot
,
sizeof
(
float
), 3, rf);
156
check += fread(&spawn.
iScale
,
sizeof
(
float
), 1, rf);
157
bool
has_bound = (spawn.
flags
&
MOD_HAS_BOUND
);
158
if
(has_bound)
// only WMOs have bound in MPQ, only available after computation
159
{
160
Vector3 bLow, bHigh;
161
check += fread(&bLow,
sizeof
(
float
), 3, rf);
162
check += fread(&bHigh,
sizeof
(
float
), 3, rf);
163
spawn.
iBound
= G3D::AABox(bLow, bHigh);
164
}
165
check += fread(&nameLen,
sizeof
(
uint32
), 1, rf);
166
if
(check !=
uint32
(has_bound ? 17 : 11))
167
{
168
std::cout <<
"Error reading ModelSpawn!\n"
;
169
return
false
;
170
}
171
char
nameBuff[500];
172
if
(nameLen > 500)
// file names should never be that long, must be file error
173
{
174
std::cout <<
"Error reading ModelSpawn, file name too long!\n"
;
175
return
false
;
176
}
177
check = fread(nameBuff,
sizeof
(
char
), nameLen, rf);
178
if
(check != nameLen)
179
{
180
std::cout <<
"Error reading ModelSpawn!\n"
;
181
return
false
;
182
}
183
spawn.
name
= std::string(nameBuff, nameLen);
184
return
true
;
185
}
186
187
bool
ModelSpawn::writeToFile
(FILE* wf,
const
ModelSpawn
&spawn)
188
{
189
uint32
check=0;
190
check += fwrite(&spawn.
flags
,
sizeof
(
uint32
), 1, wf);
191
check += fwrite(&spawn.
adtId
,
sizeof
(
uint16
), 1, wf);
192
check += fwrite(&spawn.
ID
,
sizeof
(
uint32
), 1, wf);
193
check += fwrite(&spawn.
iPos
,
sizeof
(
float
), 3, wf);
194
check += fwrite(&spawn.
iRot
,
sizeof
(
float
), 3, wf);
195
check += fwrite(&spawn.
iScale
,
sizeof
(
float
), 1, wf);
196
bool
has_bound = (spawn.
flags
&
MOD_HAS_BOUND
);
197
if
(has_bound)
// only WMOs have bound in MPQ, only available after computation
198
{
199
check += fwrite(&spawn.
iBound
.low(),
sizeof
(
float
), 3, wf);
200
check += fwrite(&spawn.
iBound
.high(),
sizeof
(
float
), 3, wf);
201
}
202
uint32
nameLen = spawn.
name
.length();
203
check += fwrite(&nameLen,
sizeof
(
uint32
), 1, wf);
204
if
(check !=
uint32
(has_bound ? 17 : 11))
return
false
;
205
check = fwrite(spawn.
name
.c_str(),
sizeof
(
char
), nameLen, wf);
206
if
(check != nameLen)
return
false
;
207
return
true
;
208
}
209
210
}
uint32
std::uint32_t uint32
Definition
Define.h:77
uint16
std::uint16_t uint16
Definition
Define.h:78
MapTree.h
ModelInstance.h
VMapDefinitions.h
WorldModel.h
VMAP::GroupModel::GetLiquidLevel
bool GetLiquidLevel(const G3D::Vector3 &pos, float &liqHeight) const
Definition
WorldModel.cpp:386
VMAP::ModelInstance::GetLocationInfo
bool GetLocationInfo(const G3D::Vector3 &p, LocationInfo &info) const
Definition
ModelInstance.cpp:89
VMAP::ModelInstance::ModelInstance
ModelInstance()
Definition
ModelInstance.h:53
VMAP::ModelInstance::intersectPoint
void intersectPoint(const G3D::Vector3 &p, AreaInfo &info) const
Definition
ModelInstance.cpp:55
VMAP::ModelInstance::iInvRot
G3D::Matrix3 iInvRot
Definition
ModelInstance.h:61
VMAP::ModelInstance::iModel
WorldModel * iModel
Definition
ModelInstance.h:63
VMAP::ModelInstance::GetLiquidLevel
bool GetLiquidLevel(const G3D::Vector3 &p, LocationInfo &info, float &liqHeight) const
Definition
ModelInstance.cpp:125
VMAP::ModelInstance::iInvScale
float iInvScale
Definition
ModelInstance.h:62
VMAP::ModelInstance::intersectRay
bool intersectRay(const G3D::Ray &pRay, float &pMaxDist, bool pStopAtFirstHit) const
Definition
ModelInstance.cpp:22
VMAP::ModelSpawn
Definition
ModelInstance.h:30
VMAP::ModelSpawn::readFromFile
static bool readFromFile(FILE *rf, ModelSpawn &spawn)
Definition
ModelInstance.cpp:141
VMAP::ModelSpawn::adtId
uint16 adtId
Definition
ModelInstance.h:34
VMAP::ModelSpawn::name
std::string name
Definition
ModelInstance.h:40
VMAP::ModelSpawn::iRot
G3D::Vector3 iRot
Definition
ModelInstance.h:37
VMAP::ModelSpawn::iScale
float iScale
Definition
ModelInstance.h:38
VMAP::ModelSpawn::ID
uint32 ID
Definition
ModelInstance.h:35
VMAP::ModelSpawn::iPos
G3D::Vector3 iPos
Definition
ModelInstance.h:36
VMAP::ModelSpawn::flags
uint32 flags
Definition
ModelInstance.h:33
VMAP::ModelSpawn::iBound
G3D::AABox iBound
Definition
ModelInstance.h:39
VMAP::ModelSpawn::writeToFile
static bool writeToFile(FILE *rw, const ModelSpawn &spawn)
Definition
ModelInstance.cpp:187
VMAP::WorldModel
Definition
WorldModel.h:95
VMAP
Definition
IVMapManager.h:19
VMAP::MOD_HAS_BOUND
@ MOD_HAS_BOUND
Definition
ModelInstance.h:26
VMAP::MOD_M2
@ MOD_M2
Definition
ModelInstance.h:24
VMAP::AreaInfo
Definition
MapTree.h:77
VMAP::AreaInfo::adtId
int32 adtId
Definition
MapTree.h:83
VMAP::AreaInfo::ground_Z
float ground_Z
Definition
MapTree.h:81
VMAP::LocationInfo
Definition
MapTree.h:20
VMAP::LocationInfo::ground_Z
float ground_Z
Definition
MapTree.h:24
VMAP::LocationInfo::hitModel
const GroupModel * hitModel
Definition
MapTree.h:23
VMAP::LocationInfo::hitInstance
const ModelInstance * hitInstance
Definition
MapTree.h:22
src
server
collision
Models
ModelInstance.cpp
Generated on
for Project SkyFire Core by
1.17.0