27template<>
struct BoundsTrait<
VMAP::GroupModel>
37 static const float EPS = 1e-5f;
41 const Vector3 e1 = points[tri.
idx1] - points[tri.
idx0];
42 const Vector3 e2 = points[tri.
idx2] - points[tri.
idx0];
43 const Vector3 p(ray.direction().cross(e2));
44 const float a = e1.dot(p);
46 if (std::fabs(a) < EPS) {
51 const float f = 1.0f / a;
52 const Vector3 s(ray.origin() - points[tri.
idx0]);
53 const float u = f * s.dot(p);
55 if ((u < 0.0f) || (u > 1.0f)) {
60 const Vector3 q(s.cross(e1));
61 const float v = f * ray.direction().dot(q);
63 if ((v < 0.0f) || ((u + v) > 1.0f)) {
68 const float t = f * e2.dot(q);
70 if ((t > 0.0f) && (t < distance))
97 out = G3D::AABox(lo, hi);
100 const std::vector<Vector3>::const_iterator
vertices;
106 iTilesX(width), iTilesY(height), iCorner(corner), iType(type)
110 iHeight =
new float[(width + 1) * (height + 1)];
111 iFlags =
new uint8[width * height];
115 iHeight =
new float[1];
169 if (tx_f < 0.0f || tx >=
iTilesX)
173 if (ty_f < 0.0f || ty >=
iTilesY)
182 float dx = tx_f - (float)tx;
183 float dy = ty_f - (float)ty;
201 float sx =
iHeight[tx+1 + ty * rowOffset] -
iHeight[tx + ty * rowOffset];
202 float sy =
iHeight[tx+1 + (ty+1) * rowOffset] -
iHeight[tx+1 + ty * rowOffset];
203 liqHeight =
iHeight[tx + ty * rowOffset] + dx * sx + dy * sy;
207 float sx =
iHeight[tx+1 + (ty+1) * rowOffset] -
iHeight[tx + (ty+1) * rowOffset];
208 float sy =
iHeight[tx + (ty+1) * rowOffset] -
iHeight[tx + ty * rowOffset];
209 liqHeight =
iHeight[tx + ty * rowOffset] + dx * sx + dy * sy;
216 return 2 *
sizeof(
uint32) +
227 fwrite(&
iCorner,
sizeof(Vector3), 1, wf) == 1 &&
233 if (fwrite(
iHeight,
sizeof(
float), size, wf) == size)
236 result = fwrite(
iFlags,
sizeof(
uint8), size, wf) == size;
240 result = fwrite(
iHeight,
sizeof(
float), 1, wf) == 1;
253 fread(&liquid->
iCorner,
sizeof(Vector3), 1, rf) == 1 &&
259 liquid->
iHeight =
new float[size];
260 if (fread(liquid->
iHeight,
sizeof(
float), size, rf) == size)
264 result = fread(liquid->
iFlags,
sizeof(
uint8), size, rf) == size;
269 liquid->
iHeight =
new float[1];
270 result = fread(liquid->
iHeight,
sizeof(
float), 1, rf) == 1;
292 iBound(other.iBound), iMogpFlags(other.iMogpFlags), iGroupWMOID(other.iGroupWMOID),
293 vertices(other.vertices), triangles(other.triangles), meshTree(other.meshTree), iLiquid(nullptr)
312 if (result && fwrite(&
iBound,
sizeof(G3D::AABox), 1, wf) != 1) result =
false;
313 if (result && fwrite(&
iMogpFlags,
sizeof(
uint32), 1, wf) != 1) result =
false;
317 if (result && fwrite(
"VERT", 1, 4, wf) != 4) result =
false;
319 chunkSize =
sizeof(
uint32) +
sizeof(Vector3) * count;
320 if (result && fwrite(&chunkSize,
sizeof(
uint32), 1, wf) != 1) result =
false;
321 if (result && fwrite(&count,
sizeof(
uint32), 1, wf) != 1) result =
false;
324 if (result && fwrite(&
vertices[0],
sizeof(Vector3), count, wf) != count) result =
false;
327 if (result && fwrite(
"TRIM", 1, 4, wf) != 4) result =
false;
330 if (result && fwrite(&chunkSize,
sizeof(
uint32), 1, wf) != 1) result =
false;
331 if (result && fwrite(&count,
sizeof(
uint32), 1, wf) != 1) result =
false;
335 if (result && fwrite(
"MBIH", 1, 4, wf) != 4) result =
false;
339 if (result && fwrite(
"LIQU", 1, 4, wf) != 4) result =
false;
343 if (result && fwrite(&chunkSize,
sizeof(
uint32), 1, wf) != 1) result =
false;
347 if (result && fwrite(&chunkSize,
sizeof(
uint32), 1, wf) != 1) result =
false;
364 if (result && fread(&
iBound,
sizeof(G3D::AABox), 1, rf) != 1) result =
false;
365 if (result && fread(&
iMogpFlags,
sizeof(
uint32), 1, rf) != 1) result =
false;
369 if (result && !
readChunk(rf, chunk,
"VERT", 4)) result =
false;
370 if (result && fread(&chunkSize,
sizeof(
uint32), 1, rf) != 1) result =
false;
371 if (result && fread(&count,
sizeof(
uint32), 1, rf) != 1) result =
false;
375 if (result && fread(&
vertices[0],
sizeof(Vector3), count, rf) != count) result =
false;
378 if (result && !
readChunk(rf, chunk,
"TRIM", 4)) result =
false;
379 if (result && fread(&chunkSize,
sizeof(
uint32), 1, rf) != 1) result =
false;
380 if (result && fread(&count,
sizeof(
uint32), 1, rf) != 1) result =
false;
385 if (result && !
readChunk(rf, chunk,
"MBIH", 4)) result =
false;
389 if (result && !
readChunk(rf, chunk,
"LIQU", 4)) result =
false;
390 if (result && fread(&chunkSize,
sizeof(
uint32), 1, rf) != 1) result =
false;
391 if (result && chunkSize > 0)
422 return point.x >= bounds.low().x
423 && point.y >= bounds.low().y
424 && point.z >= bounds.low().z
425 && point.x <= bounds.high().x
426 && point.y <= bounds.high().y;
436 float dist = G3D::finf();
439 z_dist = dist - 0.1f;
450 float dist = G3D::finf();
454 z_dist = dist - 0.1f + delta;
489 bool result =
models[entry].IntersectRay(ray, distance, pStopAtFirstHit);
494 std::vector<GroupModel>::const_iterator
models;
511 return groupModels[0].IntersectRay(ray, distance, stopAtFirstHit);
523 std::vector<GroupModel>
const&
prims;
524 std::array<GroupModel const*, 3>
hit;
533 if (group_Z < distance)
553 G3D::Ray r(p - down * 0.1f, down);
579 FILE* wf = fopen(filename.c_str(),
"wb");
584 bool result = fwrite(
VMAP_MAGIC, 1, 8, wf) == 8;
585 if (result && fwrite(
"WMOD", 1, 4, wf) != 4) result =
false;
587 if (result && fwrite(&chunkSize,
sizeof(
uint32), 1, wf) != 1) result =
false;
591 if (fwrite(&
flags,
sizeof(
uint32), 1, wf) != 1) result =
false;
593 if (result && fwrite(&
RootWMOID,
sizeof(
uint32), 1, wf) != 1) result =
false;
599 if (result && fwrite(
"GMOD", 1, 4, wf) != 4) result =
false;
602 if (result && fwrite(&count,
sizeof(
uint32), 1, wf) != 1) result =
false;
607 if (result && fwrite(
"GBIH", 1, 4, wf) != 4) result =
false;
617 FILE* rf = fopen(filename.c_str(),
"rb");
627 if (result && !
readChunk(rf, chunk,
"WMOD", 4)) result =
false;
628 if (result && fread(&chunkSize,
sizeof(
uint32), 1, rf) != 1) result =
false;
637 if (result && fread(&
RootWMOID,
sizeof(
uint32), 1, rf) != 1) result =
false;
640 if (result &&
readChunk(rf, chunk,
"GMOD", 4))
644 if (result && fread(&count,
sizeof(
uint32), 1, rf) != 1) result =
false;
647 for (
uint32 i = 0; i < count && result; ++i)
651 if (result && !
readChunk(rf, chunk,
"GBIH", 4)) result =
false;
bool writeToFile(FILE *wf) const
void build(PrimArray const &primitives, BoundsFunc const &getBounds, uint32 leafSize=3, bool printStats=false)
G3D::AABox const & bound() const
void intersectRay(G3D::Ray const &r, RayCallback &intersectCallback, float &maxDist, bool stopAtFirst=false) const
bool readFromFile(FILE *rf)
constexpr std::underlying_type_t< T > AsUnderlyingType() const
std::vector< G3D::Vector3 > vertices
uint32 GetLiquidType() const
bool readFromFile(FILE *rf)
std::vector< MeshTriangle > triangles
bool GetLiquidLevel(const G3D::Vector3 &pos, float &liqHeight) const
InsideResult IsInsideObject(G3D::Ray const &ray, float &z_dist) const
bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const
bool writeToFile(FILE *wf)
void setMeshData(std::vector< G3D::Vector3 > &&vert, std::vector< MeshTriangle > &&tri)
pass mesh data to object and create BIH.
G3D::AABox const & GetBound() const
void operator()(MeshTriangle const &tri, G3D::AABox &out) const
const std::vector< Vector3 >::const_iterator vertices
TriBoundFunc(std::vector< Vector3 > &vert)
bool operator()(G3D::Ray const &ray, uint32 entry, float &distance, bool)
std::array< GroupModel const *, 3 > hit
std::vector< GroupModel > const & prims
WModelAreaCallback(std::vector< GroupModel > const &vals)
G3D::Vector3 iCorner
the lower corner
void getPosInfo(uint32 &tilesX, uint32 &tilesY, G3D::Vector3 &corner) const
float * iHeight
(tilesX + 1)*(tilesY + 1) height values
uint32 iTilesX
number of tiles in x direction, each
bool GetLiquidHeight(G3D::Vector3 const &pos, float &liqHeight) const
uint8 * iFlags
info if liquid tile is used
static bool readFromFile(FILE *rf, WmoLiquid *&liquid)
WmoLiquid & operator=(WmoLiquid const &other)
bool writeToFile(FILE *wf)
EnumFlag< ModelFlags > Flags
bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit, ModelIgnoreFlags ignoreFlags) const
bool readFile(const std::string &filename)
bool GetLocationInfo(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, GroupLocationInfo &info) const
void setGroupModels(std::vector< GroupModel > &models)
pass group models to WorldModel and create BIH. Passed vector is swapped with old geometry!
bool writeFile(const std::string &filename)
std::vector< GroupModel > groupModels
bool readChunk(FILE *rf, char *dest, const char *compare, uint32 len)
bool IntersectTriangle(MeshTriangle const &tri, std::vector< Vector3 >::const_iterator points, G3D::Ray const &ray, float &distance)
bool IsInsideOrAboveBound(G3D::AABox const &bounds, const G3D::Point3 &point)
void operator()(VMAP::GroupModel const &obj, G3D::AABox &out) const
static void getBounds(VMAP::GroupModel const &obj, G3D::AABox &out)
std::vector< MeshTriangle >::const_iterator triangles
bool operator()(G3D::Ray const &ray, uint32 entry, float &distance, bool)
GModelRayCallback(std::vector< MeshTriangle > const &tris, const std::vector< Vector3 > &vert)
std::vector< Vector3 >::const_iterator vertices
const GroupModel * hitModel
bool operator()(G3D::Ray const &ray, uint32 entry, float &distance, bool pStopAtFirstHit)
std::vector< GroupModel >::const_iterator models
WModelRayCallBack(std::vector< GroupModel > const &mod)