27template<>
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))
96 out = G3D::AABox(lo, hi);
99 const std::vector<Vector3>::const_iterator
vertices;
105 iTilesX(width), iTilesY(height), iCorner(corner), iType(type)
109 iHeight =
new float[(width + 1) * (height + 1)];
110 iFlags =
new uint8[width * height];
114 iHeight =
new float[1];
168 if (tx_f < 0.0f || tx >=
iTilesX)
172 if (ty_f < 0.0f || ty >=
iTilesY)
181 float dx = tx_f - (float)tx;
182 float dy = ty_f - (float)ty;
200 float sx =
iHeight[tx+1 + ty * rowOffset] -
iHeight[tx + ty * rowOffset];
201 float sy =
iHeight[tx+1 + (ty+1) * rowOffset] -
iHeight[tx+1 + ty * rowOffset];
202 liqHeight =
iHeight[tx + ty * rowOffset] + dx * sx + dy * sy;
206 float sx =
iHeight[tx+1 + (ty+1) * rowOffset] -
iHeight[tx + (ty+1) * rowOffset];
207 float sy =
iHeight[tx + (ty+1) * rowOffset] -
iHeight[tx + ty * rowOffset];
208 liqHeight =
iHeight[tx + ty * rowOffset] + dx * sx + dy * sy;
215 return 2 *
sizeof(
uint32) +
226 fwrite(&
iCorner,
sizeof(Vector3), 1, wf) == 1 &&
232 if (fwrite(
iHeight,
sizeof(
float), size, wf) == size)
235 result = fwrite(
iFlags,
sizeof(
uint8), size, wf) == size;
239 result = fwrite(
iHeight,
sizeof(
float), 1, wf) == 1;
252 fread(&liquid->
iCorner,
sizeof(Vector3), 1, rf) == 1 &&
258 liquid->
iHeight =
new float[size];
259 if (fread(liquid->
iHeight,
sizeof(
float), size, rf) == size)
263 result = fread(liquid->
iFlags,
sizeof(
uint8), size, rf) == size;
268 liquid->
iHeight =
new float[1];
269 result = fread(liquid->
iHeight,
sizeof(
float), 1, rf) == 1;
291 iBound(other.iBound), iMogpFlags(other.iMogpFlags), iGroupWMOID(other.iGroupWMOID),
292 vertices(other.vertices), triangles(other.triangles), meshTree(other.meshTree), iLiquid(nullptr)
311 if (result && fwrite(&
iBound,
sizeof(G3D::AABox), 1, wf) != 1) result =
false;
312 if (result && fwrite(&
iMogpFlags,
sizeof(
uint32), 1, wf) != 1) result =
false;
316 if (result && fwrite(
"VERT", 1, 4, wf) != 4) result =
false;
318 chunkSize =
sizeof(
uint32)+
sizeof(Vector3)*count;
319 if (result && fwrite(&chunkSize,
sizeof(
uint32), 1, wf) != 1) result =
false;
320 if (result && fwrite(&count,
sizeof(
uint32), 1, wf) != 1) result =
false;
323 if (result && fwrite(&
vertices[0],
sizeof(Vector3), count, wf) != count) result =
false;
326 if (result && fwrite(
"TRIM", 1, 4, wf) != 4) result =
false;
329 if (result && fwrite(&chunkSize,
sizeof(
uint32), 1, wf) != 1) result =
false;
330 if (result && fwrite(&count,
sizeof(
uint32), 1, wf) != 1) result =
false;
334 if (result && fwrite(
"MBIH", 1, 4, wf) != 4) result =
false;
338 if (result && fwrite(
"LIQU", 1, 4, wf) != 4) result =
false;
342 if (result && fwrite(&chunkSize,
sizeof(
uint32), 1, wf) != 1) result =
false;
346 if (result && fwrite(&chunkSize,
sizeof(
uint32), 1, wf) != 1) result =
false;
363 if (result && fread(&
iBound,
sizeof(G3D::AABox), 1, rf) != 1) result =
false;
364 if (result && fread(&
iMogpFlags,
sizeof(
uint32), 1, rf) != 1) result =
false;
368 if (result && !
readChunk(rf, chunk,
"VERT", 4)) result =
false;
369 if (result && fread(&chunkSize,
sizeof(
uint32), 1, rf) != 1) result =
false;
370 if (result && fread(&count,
sizeof(
uint32), 1, rf) != 1) result =
false;
374 if (result && fread(&
vertices[0],
sizeof(Vector3), count, rf) != count) result =
false;
377 if (result && !
readChunk(rf, chunk,
"TRIM", 4)) result =
false;
378 if (result && fread(&chunkSize,
sizeof(
uint32), 1, rf) != 1) result =
false;
379 if (result && fread(&count,
sizeof(
uint32), 1, rf) != 1) result =
false;
384 if (result && !
readChunk(rf, chunk,
"MBIH", 4)) result =
false;
388 if (result && !
readChunk(rf, chunk,
"LIQU", 4)) result =
false;
389 if (result && fread(&chunkSize,
sizeof(
uint32), 1, rf) != 1) result =
false;
390 if (result && chunkSize > 0)
421 return point.x >= bounds.low().x
422 && point.y >= bounds.low().y
423 && point.z >= bounds.low().z
424 && point.x <= bounds.high().x
425 && point.y <= bounds.high().y;
435 float dist = G3D::finf();
438 z_dist = dist - 0.1f;
449 float dist = G3D::finf();
453 z_dist = dist - 0.1f + delta;
495 bool result =
models[entry].IntersectRay(ray, distance, pStopAtFirstHit);
500 std::vector<GroupModel>::const_iterator
models;
517 return groupModels[0].IntersectRay(ray, distance, stopAtFirstHit);
529 std::vector<GroupModel>
const&
prims;
530 std::array<GroupModel const*, 3>
hit;
539 if (group_Z < distance)
559 G3D::Ray r(p - down * 0.1f, down);
585 FILE* wf = fopen(filename.c_str(),
"wb");
590 bool result = fwrite(
VMAP_MAGIC, 1, 8, wf) == 8;
591 if (result && fwrite(
"WMOD", 1, 4, wf) != 4) result =
false;
593 if (result && fwrite(&chunkSize,
sizeof(
uint32), 1, wf) != 1) result =
false;
594 if (result && fwrite(&
RootWMOID,
sizeof(
uint32), 1, wf) != 1) result =
false;
600 if (result && fwrite(
"GMOD", 1, 4, wf) != 4) result =
false;
603 if (result && fwrite(&count,
sizeof(
uint32), 1, wf) != 1) result =
false;
608 if (result && fwrite(
"GBIH", 1, 4, wf) != 4) result =
false;
618 FILE* rf = fopen(filename.c_str(),
"rb");
628 if (result && !
readChunk(rf, chunk,
"WMOD", 4)) result =
false;
629 if (result && fread(&chunkSize,
sizeof(
uint32), 1, rf) != 1) result =
false;
630 if (result && fread(&
RootWMOID,
sizeof(
uint32), 1, rf) != 1) result =
false;
633 if (result &&
readChunk(rf, chunk,
"GMOD", 4))
637 if (result && fread(&count,
sizeof(
uint32), 1, rf) != 1) result =
false;
640 for (
uint32 i=0; i<count && result; ++i)
644 if (result && !
readChunk(rf, chunk,
"GBIH", 4)) result =
false;
void build(PrimArray const &primitives, BoundsFunc &getBounds, uint32 leafSize=3, bool printStats=false)
bool writeToFile(FILE *wf) const
G3D::AABox const & bound() const
bool readFromFile(FILE *rf)
void intersectRay(const G3D::Ray &r, RayCallback &intersectCallback, float &maxDist, bool stopAtFirst=false) const
std::vector< G3D::Vector3 > vertices
uint32 GetLiquidType() const
bool readFromFile(FILE *rf)
void getMeshData(std::vector< G3D::Vector3 > &outVertices, std::vector< MeshTriangle > &outTriangles, WmoLiquid *&liquid)
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. Passed vectors get get swapped with old geometry!
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)
bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit, ModelIgnoreFlags ignoreFlags) const
void getGroupModels(std::vector< GroupModel > &outGroupModels)
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)
static void getBounds(const VMAP::GroupModel &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)