26template<>
struct BoundsTrait<
VMAP::GroupModel>
36 static const float EPS = 1e-5f;
40 const Vector3 e1 = points[tri.
idx1] - points[tri.
idx0];
41 const Vector3 e2 = points[tri.
idx2] - points[tri.
idx0];
42 const Vector3 p(ray.direction().cross(e2));
43 const float a = e1.dot(p);
45 if (std::fabs(a) < EPS) {
50 const float f = 1.0f / a;
51 const Vector3 s(ray.origin() - points[tri.
idx0]);
52 const float u = f * s.dot(p);
54 if ((u < 0.0f) || (u > 1.0f)) {
59 const Vector3 q(s.cross(e1));
60 const float v = f * ray.direction().dot(q);
62 if ((v < 0.0f) || ((u + v) > 1.0f)) {
67 const float t = f * e2.dot(q);
69 if ((t > 0.0f) && (t < distance))
91 out = { p1.min(p2).min(p3), p1.max(p2).max(p3) };
100 iTilesX(width), iTilesY(height), iCorner(corner), iType(type)
104 iHeight =
new float[(width + 1) * (height + 1)];
105 iFlags =
new uint8[width * height];
109 iHeight =
new float[1];
163 if (tx_f < 0.0f || tx >=
iTilesX)
167 if (ty_f < 0.0f || ty >=
iTilesY)
176 float dx = tx_f - (float)tx;
177 float dy = ty_f - (float)ty;
195 float sx =
iHeight[tx+1 + ty * rowOffset] -
iHeight[tx + ty * rowOffset];
196 float sy =
iHeight[tx+1 + (ty+1) * rowOffset] -
iHeight[tx+1 + ty * rowOffset];
197 liqHeight =
iHeight[tx + ty * rowOffset] + dx * sx + dy * sy;
201 float sx =
iHeight[tx+1 + (ty+1) * rowOffset] -
iHeight[tx + (ty+1) * rowOffset];
202 float sy =
iHeight[tx + (ty+1) * rowOffset] -
iHeight[tx + ty * rowOffset];
203 liqHeight =
iHeight[tx + ty * rowOffset] + dx * sx + dy * sy;
210 return 2 *
sizeof(
uint32) +
221 fwrite(&
iCorner,
sizeof(Vector3), 1, wf) == 1 &&
227 if (fwrite(
iHeight,
sizeof(
float), size, wf) == size)
230 result = fwrite(
iFlags,
sizeof(
uint8), size, wf) == size;
234 result = fwrite(
iHeight,
sizeof(
float), 1, wf) == 1;
247 fread(&liquid->
iCorner,
sizeof(Vector3), 1, rf) == 1 &&
253 liquid->
iHeight =
new float[size];
254 if (fread(liquid->
iHeight,
sizeof(
float), size, rf) == size)
258 result = fread(liquid->
iFlags,
sizeof(
uint8), size, rf) == size;
263 liquid->
iHeight =
new float[1];
264 result = fread(liquid->
iHeight,
sizeof(
float), 1, rf) == 1;
286 iBound(other.iBound), iMogpFlags(other.iMogpFlags), iGroupWMOID(other.iGroupWMOID),
287 vertices(other.vertices), triangles(other.triangles), meshTree(other.meshTree), iLiquid(nullptr)
306 if (result && fwrite(&
iBound,
sizeof(G3D::AABox), 1, wf) != 1) result =
false;
307 if (result && fwrite(&
iMogpFlags,
sizeof(
uint32), 1, wf) != 1) result =
false;
311 if (result && fwrite(
"VERT", 1, 4, wf) != 4) result =
false;
313 chunkSize =
sizeof(
uint32) +
sizeof(Vector3) * count;
314 if (result && fwrite(&chunkSize,
sizeof(
uint32), 1, wf) != 1) result =
false;
315 if (result && fwrite(&count,
sizeof(
uint32), 1, wf) != 1) result =
false;
318 if (result && fwrite(&
vertices[0],
sizeof(Vector3), count, wf) != count) result =
false;
321 if (result && fwrite(
"TRIM", 1, 4, wf) != 4) result =
false;
324 if (result && fwrite(&chunkSize,
sizeof(
uint32), 1, wf) != 1) result =
false;
325 if (result && fwrite(&count,
sizeof(
uint32), 1, wf) != 1) result =
false;
329 if (result && fwrite(
"MBIH", 1, 4, wf) != 4) result =
false;
333 if (result && fwrite(
"LIQU", 1, 4, wf) != 4) result =
false;
337 if (result && fwrite(&chunkSize,
sizeof(
uint32), 1, wf) != 1) result =
false;
341 if (result && fwrite(&chunkSize,
sizeof(
uint32), 1, wf) != 1) result =
false;
358 if (result && fread(&
iBound,
sizeof(G3D::AABox), 1, rf) != 1) result =
false;
359 if (result && fread(&
iMogpFlags,
sizeof(
uint32), 1, rf) != 1) result =
false;
363 if (result && !
readChunk(rf, chunk,
"VERT", 4)) result =
false;
364 if (result && fread(&chunkSize,
sizeof(
uint32), 1, rf) != 1) result =
false;
365 if (result && fread(&count,
sizeof(
uint32), 1, rf) != 1) result =
false;
369 if (result && fread(&
vertices[0],
sizeof(Vector3), count, rf) != count) result =
false;
372 if (result && !
readChunk(rf, chunk,
"TRIM", 4)) result =
false;
373 if (result && fread(&chunkSize,
sizeof(
uint32), 1, rf) != 1) result =
false;
374 if (result && fread(&count,
sizeof(
uint32), 1, rf) != 1) result =
false;
379 if (result && !
readChunk(rf, chunk,
"MBIH", 4)) result =
false;
383 if (result && !
readChunk(rf, chunk,
"LIQU", 4)) result =
false;
384 if (result && fread(&chunkSize,
sizeof(
uint32), 1, rf) != 1) result =
false;
385 if (result && chunkSize > 0)
392 GModelRayCallback(std::vector<MeshTriangle>
const& tris, std::vector<G3D::Vector3>
const& vert) :
415 return point.x >= bounds.low().x
416 && point.y >= bounds.low().y
417 && point.z >= bounds.low().z
418 && point.x <= bounds.high().x
419 && point.y <= bounds.high().y;
429 float dist = G3D::finf();
432 z_dist = dist - 0.1f;
443 float dist = G3D::finf();
447 z_dist = dist - 0.1f + delta;
501 return groupModels[0].IntersectRay(ray, distance, stopAtFirstHit);
513 std::vector<GroupModel>
const&
prims;
514 std::array<GroupModel const*, 3>
hit;
523 if (group_Z < distance)
543 G3D::Ray r(p - down * 0.1f, down);
569 FILE* wf = fopen(filename.c_str(),
"wb");
574 bool result = fwrite(
VMAP_MAGIC, 1, 8, wf) == 8;
575 if (result && fwrite(
"WMOD", 1, 4, wf) != 4) result =
false;
577 if (result && fwrite(&chunkSize,
sizeof(
uint32), 1, wf) != 1) result =
false;
581 if (fwrite(&
flags,
sizeof(
uint32), 1, wf) != 1) result =
false;
583 if (result && fwrite(&
RootWMOID,
sizeof(
uint32), 1, wf) != 1) result =
false;
589 if (result && fwrite(
"GMOD", 1, 4, wf) != 4) result =
false;
592 if (result && fwrite(&count,
sizeof(
uint32), 1, wf) != 1) result =
false;
597 if (result && fwrite(
"GBIH", 1, 4, wf) != 4) result =
false;
607 FILE* rf = fopen(filename.c_str(),
"rb");
617 if (result && !
readChunk(rf, chunk,
"WMOD", 4)) result =
false;
618 if (result && fread(&chunkSize,
sizeof(
uint32), 1, rf) != 1) result =
false;
627 if (result && fread(&
RootWMOID,
sizeof(
uint32), 1, rf) != 1) result =
false;
630 if (result &&
readChunk(rf, chunk,
"GMOD", 4))
634 if (result && fread(&count,
sizeof(
uint32), 1, rf) != 1) result =
false;
637 for (
uint32 i = 0; i < count && result; ++i)
641 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
TriBoundFunc(std::vector< G3D::Vector3 > const &vert)
G3D::Vector3 const * vertices
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 GetLocationInfo(G3D::Vector3 const &p, G3D::Vector3 const &down, WorldModelLocationInfoQueryResult &info) const
bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit, ModelIgnoreFlags ignoreFlags) const
bool readFile(const std::string &filename)
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, G3D::Vector3 const *points, G3D::Ray const &ray, float &distance)
bool IsInsideOrAboveBound(G3D::AABox const &bounds, G3D::Point3 const &point)
void operator()(VMAP::GroupModel const &obj, G3D::AABox &out) const
static void getBounds(VMAP::GroupModel const &obj, G3D::AABox &out)
MeshTriangle const * triangles
bool operator()(G3D::Ray const &ray, uint32 entry, float &distance, bool)
GModelRayCallback(std::vector< MeshTriangle > const &tris, std::vector< G3D::Vector3 > const &vert)
G3D::Vector3 const * vertices
bool operator()(G3D::Ray const &ray, uint32 entry, float &distance, bool pStopAtFirstHit)
WModelRayCallBack(std::vector< GroupModel > const &mod)
GroupModel const * models
GroupModel const * hitModel